I thought the deliverable was the file format and the board. It was not. The deliverable is the process, written down in a form the agent executes.
That is the part I did not see coming when we replaced Jira with markdown files in our repositories. That post covers why we left and what the system is. This one is about what the system turned out to be for.
The skill is the product
Our workflow lives in a Claude Code skill: 452 lines covering how a ticket is created, refined, planned, picked up, worked, reviewed and closed, plus a few reference files it pulls in on demand so the always-loaded part stays readable. Not a style guide. Instructions with gates in them, which the agent is required to load before touching any ticket.
The create flow does not start by scaffolding a file. It starts by making the agent ask two to four targeted questions when a request is thin, then present the drafted Objective, Context and Acceptance Criteria for sign-off before anything is written. Planning runs in read-only mode, so no ticket write can happen before the plan is approved. Work happens one task at a time, each claimed on the board before a line of code is written.
The routing rule
The most useful rule in it fits in a sentence. There are two ways to write a ticket, and the diff decides which one.
Ticket-only changes go through the MCP server, which commits straight to the default branch: creating a ticket, refining it, flipping status before the code work or after the pull request lands. No checkout, no branch, no pull request, no review bot. The analysis still happens locally where the code is; only the write is remote.
Code work happens on a ticket branch with the CLI and git, where the plan, status changes, task completions and work log entries ride along with the code commits and merge through the same pull request.
Before the rule, every status change during a coding session was a small decision with no good answer: open a throwaway pull request for a one-line frontmatter edit, or commit ticket noise onto the feature branch. Now the diff answers it.
One implementation, four consumers
Underneath both paths sits one npm package holding the schema, the parser, the serializer, and every edit operation as a pure function.
Four things import it: the CLI that agents and humans run in a checkout, the Angular viewer behind every board edit, the Cloud Functions commit gateway, and the MCP server for the remote path. Nobody reimplements ticket semantics. The MCP server has no authoring logic of its own; it resolves the project, allocates an ID, runs the shared transform, and lets the gateway validate before committing.
That is what makes a guardrail real. When we added a rule that a ticket cannot be closed while its acceptance criteria are unticked, it went into the package once and now fires identically whether you type a CLI command, call the MCP tool from your phone, or drag a card across the board. There is no back door, because there is only one door.
The override is the part I like most. You can force past that gate, but it costs a written reason, and the same operation that flips the status appends that reason to the work log. A bypass is always visible and attributable. A gate people quietly route around reads as enforcement while providing none.
The loop
The thing that changed daily work most is one line:
/goal complete tasks according to the wbtickets skill until the PR is mergeable
That is the whole prompt. What follows runs on its own, and it can run on its own because the ticket carries enough state to make it possible:
- Pull, re-read the ticket, take the first task that is not done.
- Claim it: mark it in-progress, commit, push. Before any code, so the board and any parallel session see the claim.
- Implement exactly that task. Build it, test it.
- Present the pending diff and wait for approval.
- Complete the task, write the work log entry, commit code and bookkeeping together, push.
- Next task, back to step 2.
Step 4 is the default, and the goal is what waives it. A goal is a hook that blocks the session from ending until its condition holds, so typing that line is the approval: instead of stopping at each task, the agent finishes one, pushes, and walks straight into the next. The gate is not removed from the skill and it is not disabled for the repository. It is authorised once, for this run, by the person who started it. Point it at a ticket with seven tasks and it works the ticket, not the task.
Which makes it a judgement call rather than a setting I leave on. Waiving the per-task check is right when the tasks are small, the plan is well understood and a wrong turn costs one revert. It is wrong on anything where I would want to see the shape of task three before task four is built on top of it. The goal trades review granularity for throughput, and low-complexity, low-risk tickets are where that trade is clearly worth making.
Two things make the unattended version acceptable rather than reckless.
The claim happens before the code. It is bookkeeping with nothing attached and it must reach the board first, or a second session picks up the same task. The recurring failure was sliding from one task's finished commit into the next task's edits without claiming, which looks harmless until two agents are working in parallel.
One task is one commit. The loop never batches. Every step lands as a separate, conventionally named commit carrying its code, its task completion and its work log entry together. An unattended run is reviewable afterwards, commit by commit, and the pull request reads as a sequence of decisions instead of one wall of diff.
And the gates the goal cannot touch sit at the edges: an approved plan going in, and three layers of review coming out. Autonomy inside the ticket, scrutiny at the boundaries. Skipping the per-task check is defensible precisely because those two are not skippable.
Planning ends by throwing the context away
Planning is the one phase that deliberately stops, and it stops twice: once for approval, then again at the very end. The session writes the plan into the ticket, splits the work into tasks, adds a Mermaid diagram when a flow or state machine is clearer drawn than described, commits, and then clears its own context.
The rule that makes it work: if the reasoning exists only in the chat, the plan was not self-contained, and that is a bug to fix before clearing. The decisions, the rejected alternatives, the sequencing rationale and the per-task verification all go into the ticket.
The ticket is the context window. A fresh session picks up task three of seven without any of the conversation that produced the plan. It still syncs the branch and re-reads the ticket, but it never has to reconstruct why the work is shaped the way it is, because that is in a file it can read. The exploration transcript is not context, it is exhaust.
Getting that plan right is the highest-leverage step in the whole workflow, which is why it gets a review of its own before any code exists.
This is also why old tickets stay readable. They are time-locked decision records. Before planning work on a subsystem, the flow has the agent mine the history of the files it will touch and search older tickets on the same component, so a decision made in March is available in August without anyone remembering it exists.
Distribution is the quiet multiplier
A process written down helps one repository. A process that installs itself helps all of them.
The skill ships inside the same package as the CLI, with a sync command wired to a session-start hook, so every repository picks up the current version at the start of every session. Change the instructions and the change reaches every agent session in the company by the next session start. No migration, no announcement, no repository left on last month's process. The same package serves the guidance the MCP server hands to colleagues authoring tickets from claude.ai, so the two cannot drift apart.
It is not one skill riding along either. Ten travel that channel now, from the review process to the per-stack rubrics, reaching a Java repository and an Angular one alike. That was not the plan. It is what happens when you build a way to ship one process and discover the pipe does not care how much you put in it.
Watching four agents work
One ticket, one checkout, one session. That is forced rather than chosen: the bookkeeping auto-commits, so two sessions cannot share a working copy without fighting over it. A parallel command does the rest, provisioning a git worktree per ticket with its own port and dependencies, flagging any files two tickets would both touch, and handing back one kickoff prompt per session.
That constraint produced the best moment I have had with this system.
Three ingredients, none designed for it. Ticket bookkeeping auto-commits and pushes the instant it happens, the one deliberate exception to our never-auto-commit rule, because the board has to see it. The board is branch-aware, reading each ticket from its own feature branch rather than the stale copy on the default branch, so it shows work in flight. And the in-progress lane is double width with the task checklist inline.
Run four sessions at once and the board becomes a live view: four tickets in progress, four checklists ticking themselves off within seconds of each push. I had it open on a second screen and watched the work move.
The caveat is honest: the board is exactly as current as the last push, so unpushed work does not exist to it. In practice that is fine, because the bookkeeping pushes itself, and the bookkeeping is the part worth watching.
I did not build this to be watchable. But it is the first time a project management tool has shown me something I did not already know from being the person doing the work.
What this actually changed
Our tickets are now the thing an agent reads before it writes code, instead of the thing someone updates after the code is written.
The board did not get smarter. The tickets did.
Which leaves the uncomfortable question. If an agent writes most of the code, and on a good day you tell it not to pause between tasks, what stops it from confidently shipping the wrong thing? Three layers of review, and the one that does the most work runs before a single line of code exists.

Top comments (0)