From ticket to task file: the agent drafts, a person decides
The ticket is written for people, the task file for the repo. Let the agent draft it, a second agent check it, then decide what no agent can.

The previous part ended on the third file, the task file. It carries the rule from the first part: the agent executes a decided scope, it never decides one. That raises an obvious objection: who writes the scope, and is that not the slow part?
It is not, if you let the agent draft it.
Two documents, one decision
Companies already have the ask written down. It is called a ticket, and it is written for people: the business language, the acceptance criteria, the screenshots, the comments. It stays where the company keeps it.
The task file is the same decision in repo terms: which libraries may be touched, which domain functions to reuse, the commands that define "done", the diff cap. A ticket rarely says "do not edit existing assertions" or "call canTransfer() from the domain library". A task file says little else.
Writing both by hand is duplication. Writing the ticket and letting the agent translate it is not: once it has read the code, it lists the files the ticket touches faster than the person who wrote it.
Step one: the agent drafts
Read AGENTS.md and docs/tasks/TEMPLATE.md. Below is the ticket as the business wrote it. Turn it into a task file for this repo.
Do not write code. List the files you would touch and why, the scope you propose, what you consider out of scope, the "done when" checklist with the exact commands, and every question you would need answered before starting. Keep the diff under 300 lines; if it cannot fit, split it into numbered tasks.
--- ticket --- ATLAS-218 · Export transactions to CSV As a customer I want to export the transactions of my account, with the filters I applied, so I can reconcile in Excel. Columns: date, label, category, amount in MAD. Max 10,000 rows. Must work on the mobile layout.
The draft comes back within minutes. It is usually more complete than a ticket written from memory, and it has a habit worth knowing: it answers its own questions. "Should the export respect the current filters? I will assume yes." That assumption is a decision, and it is not the agent's to make. Save the draft as docs/tasks/008-export-filtered-transactions-csv.md: the next two steps work on that file.
Step two: a second agent checks
Before a person reads the draft, let an agent with no stake in it read it. A fresh session, or a different model, with only the rules file and the draft, so it has no work of its own to defend:
Read AGENTS.md, then docs/tasks/008-export-filtered-transactions-csv.md. You did not write it. Check it against the rules and answer only this:
- Does the scope touch any path the rules forbid, or any library the task does not need?
- Is every "done when" item a command or a visible outcome, not an opinion?
- Can the proposed diff fit under 300 lines? If not, propose the split.
- Which open questions did the draft answer by itself instead of asking?
- Is anything in the ticket missing from the task?
Reply as a numbered list of findings. No rewrite.
The check is good at catching the mechanical faults: a scope that wanders into a shared library, a "done when" that says "works correctly", a diff that cannot fit, and every question the draft quietly answered itself.
Step three: a person decides
What is left is short. Cut the scope the draft was generous with. Answer the questions, in the file. Decide whether this is the change you want, which is the one thing no agent can do. Save the file, or paste it back into the ticket if that is where your team reads.
A few minutes of agent time, a few of yours, and nothing written twice by hand. The agent now has a task it did not decide.
The shape of a good task file
The task file is the truth. The code is the detail.
# Task 008: Export an account's filtered transactions to CSV
## Goal
A customer can download the filtered transactions of an account as a CSV file, on desktop and on mobile.
## Scope
- Allowed to change: `libs/feature/accounts`
- New files allowed in: `libs/feature/accounts/src/lib/` (a pure `transactions-csv.ts` + its spec)
## Out of scope
- `libs/ui` (no new shared component). `libs/data-access/*` (the transactions are already in the store). `libs/legacy/**`.
## Done when
- [ ] `npm run lint:arch`, `npm run test` (no changed assertions) and `npm run typecheck` pass
- [ ] On `/accounts/a-current`, filtering by category then clicking "Export CSV" downloads only the filtered rows (decided: yes, ATLAS-218 comment 3)
- [ ] Columns in this order: date, label, category, amount in MAD; at most 10,000 rows
- [ ] On the mobile layout the "Export CSV" button is visible and the download works
- [ ] Diff ≤ 300 lines
## Notes for the agent
- Closest analogue to mirror: `libs/feature/accounts/src/lib/account-detail.ts`
- Domain helpers to reuse: `formatMad`, `categoryLabel` from `@atlas/domain`The "closest analogue" line is the quiet hero. Agents copy shape. Point at the right shape and the code comes back looking like the rest of the codebase.
On Monday
- Stop writing task files by hand. Paste the ticket, ask for the task file, not the code.
- Run the check prompt in a fresh session before you read any draft.
- Decide in the file, never in chat. The file is what the agent reads next week.
Exercise: docs/tasks/TEMPLATE.md and task 001 in the demo repo, a finished, shorter version of this export. Start: git switch -c m1/you main. Reference: origin/track1/m1-solution.
A new feature is the easy case. The next part is code that is already in production: a legacy module to migrate, where the first thing to review is the agent's own plan.
Track 1, part 3 of the free series behind the Fast and safe: AI in your Angular codebase workshop.
Fast and safe: AI in your Angular codebase
Let agents write Angular under rules, modernise legacy code without breaking production, and keep it secure, in three days, on an enterprise-shaped codebase.
See the agenda