feat(auto-pm): implement a plan's own consensual quick-wins (#1334) - #1336
Conversation
Closes the autonomy loop. Three links were missing between "a new GitHub issue" and "an agent implements it": - Bringing tickets across from GitHub was a button nobody pressed on a schedule, so the rotation eventually triaged and planned a set that nothing refilled. `update-tickets` now leads the rotation; it resumes from `tickets/meta.json` and reconciles, so repeat firings are no-ops. - [Spike & plan] covered "the most important" tickets and recorded no verdict. It now covers every ticket without a plan and ends each one with `Effort:` and `Consensus:` keys in the plan's header. - Nothing carried that verdict onto the queue. `planned-quick-wins.ts` does: a plan marked `quick-win` + `consensual` is queued by the daemon under the ticket's own priority heading, and the drain implements it. No agent turn is spent re-deciding what the plan already decided, which is why the promotion is code rather than another routine. It fails closed and demands both keys explicitly: a plan that says nothing, or something unrecognized, is left for a human. Also fixes `todoPriorityForTicket`, which mapped only the ticket format's words while every real ticket writes a number, so every queued ticket landed at the default 5 regardless of what it said.
|
|
||
| Body: | ||
| ```md | ||
| Effort: quick-win/significant |
There was a problem hiding this comment.
Let me think of a clean way to do this.
I think it's important to be as clear as possible in what we tell agents.
| Body: | ||
| ```md | ||
| Effort: quick-win/significant | ||
| Consensus: consensual/open-questions |
There was a problem hiding this comment.
We already have the concept of "variability" in the system prompt. Maybe we can (and should?) re-use that concept.
| ``` | ||
|
|
||
| The two header keys are the plan's verdict on its own ticket, and they are read by the machine: | ||
| - `Effort`: is implementing this a small, contained change (`quick-win`) or not (`significant`)? |
There was a problem hiding this comment.
This line has zero added value, it's noise that wastes the context window.
| [optional: more info (any heading and format you want)] | ||
| ``` | ||
|
|
||
| The two header keys are the plan's verdict on its own ticket, and they are read by the machine: |
There was a problem hiding this comment.
I guess that line was generated by AI? That's AI slop right there. It's babbling, eating precious context window, and actually adds confusion leading to less reliable agent output.
| - `Effort: quick-win` when implementing it is a small, contained change, `Effort: significant` otherwise. | ||
| - `Consensus: consensual` when there is a single fairly obvious plan (zero open questions, zero variability), `Consensus: open-questions` otherwise. | ||
|
|
||
| A plan marked `Effort: quick-win` and `Consensus: consensual` is queued and implemented unattended, without anyone reading it first. So write that pair only when you would be comfortable with that happening. Anything you would want a human to look at first is `Consensus: open-questions`, and a plan carrying a `## Hard problems` or `## Variability` section is never a quick-win. |
There was a problem hiding this comment.
is queued and implemented unattended, without anyone reading it first.
That isn't DRY at all — it breaks the #1 rule of maintainable code. That's brittle and will hurt us very bad in the long haul. We should NEVER let something like this pass through. This PR should never have been merged.
There was a problem hiding this comment.
All ticketing format should be maintained in ticketing_format.md.
Closes #1334
What
Closes the loop between "a new GitHub issue" and "an agent implements it". Three links were missing.
1. Nothing refilled the ticket set.
update-tickets(#1208) existed as a button but was not in the rotation, so the routine eventually triaged and planned a set nothing ever added to. It now leadsAUTO_PM_JOBS. Safe to repeat: the preset resumes fromtickets/meta.json'slastImportedAtand reconciles, so a firing with nothing changed is a no-op.2. [Spike & plan] recorded no verdict. Its prompt covered "the most important tickets that have no spike or plan yet" and stopped there. It now covers every ticket without a plan, and ends each one with two keys in the plan file's header:
3. Nothing carried the verdict onto the queue. New
planned-quick-wins.ts: a plan markedEffort: quick-winandConsensus: consensualputs its ticket onTODO_AGENTS.md, under the ticket's own priority heading, and the existing drain implements it.Why the promotion is code, not another routine
The plan already made the judgement. Spending a subscription turn on an agent that reads the same ticket to reach the same conclusion is exactly the waste the quota boundary (#879) exists to prevent. Reading two keys and appending a line needs judgement from nobody.
The daemon writes it, never the agent, for the reason
queue-promote.tsgives: runs stay sandboxed in their worktrees with no write access to the checkout.Safety
quotaHeadroompolarity). A plan that forgot to say, or said something this version does not recognize, means a human decides rather than an agent starting.##), so a plan that discusses quick wins in its prose cannot declare itself one.## Hard problemsor## Variabilityis never a quick-win.promoteQueuedoes. Closed tickets, missing ticket files and already-queued tickets are skipped.landPinnedEntry: one line, never a reorder or a removal.Bug found while wiring it
todoPriorityForTicketmapped only the ticket format's words (urgent/high/low), but the format specifiesPriority: 10-0and all 34 tickets in this repo write a number. Every one of them fell through to the default 5, so a queued ticket landed at the middle priority whatever it said. Numbers are now taken at their word.Placement is correctness rather than tidiness here:
parseTodoEntriesreturns entries in file order and the drain takes the first, so an entry appended to the end of the file would be the last thing ever worked, which is the opposite of what this ticket asks for.Tests
Framework suite 1545/0 (1 skipped). New
planned-quick-wins.test.tscovers the verdict parse, the fail-closed policy, priority placement and section creation, and the promotion pass end to end.Revert-proven, twice:
reads the title, the numeric priority and the statusandplaces each ticket by its own prioritya plan promoted this tick is drained this tick, not the next one(a plan landing between ticks would otherwise wait out a full cooldown)Note for review
The prompt half is yours if you want it worded differently. The two key names and the fail-closed rule are the contract the code reads, so those are the parts worth arguing about.