A pull request is titled with a name for its work, never with the prompt - #1621
Conversation
`quotaBoundaryStatus` takes a model, filters the account's `week-model` windows down to that model's own week, and measures it against the same boundary as the account's week — documented, unit-tested, and never once called with a model in production. `dashboard/quota.ts` was the only caller and passes none, which is right for the panel it feeds: the bar is about the account. But nothing else computed a boundary at all, so both self-starting paths — auto PM and the CI-watch fix — gated on that same model-blind reading. Live on this account today: the week is 54% used, the Fable week is 100% used, and the gate said start. Every run it started died at its first API call. The fix is a second question rather than an argument on the first. `QuotaSource` grows `boundaryFor(model)` beside `read()`, both measured off the same reading and the same slider position, so #960's "one source" promise holds — the panel and the gate cannot disagree about the account, only about a question the panel never asks. Making `read()` take a model would instead have left the panel's call site looking like it had simply forgotten to pass one, which is exactly how this went unnoticed. The daemon resolves the model the way it resolves everything else about a background start: `resolveProjectAgentOptions`, the same two tiers the start itself uses, so the gate cannot measure a different model than the one that runs. That makes it per project rather than per sweep — the model is a project setting — so auto PM's `quota` seam now takes the project. It costs no extra reading: the poller's last good windows are simply measured again. A model with no window of its own, and a project with no model set, are gated on the account's week exactly as before: with nothing chosen the driver picks, and a window nobody can tie to the work must never stop it (#879). Blocked work now stands down instead of dying at the API. Auto PM already names the window that stopped it ("Current week (Fable) is 100% used"), which reaches the dashboard's own line under the toggle. The CI-fix half said nothing at all, so it now logs its stand-down once per failing head commit — the same re-arm rule its attempt cap uses, rather than a line per tick for as long as the PR stays red. The end-to-end test is the half that was missing here, so it uses the real poller and the real `pollerQuotaSource` over a stubbed driver read: a fake would have answered whatever the test wanted, which is how an argument only tests ever passed stayed unwired. Verified against the live reading too — the account's own label is `Current week (Fable)`, byte for byte the fixture's. Closes #1619
A session that emitted no session name got its PR titled `intent.slice(0, 72)` — the instruction it was given, cut wherever 72 characters landed. The squash merge inherits the PR title, so that becomes a permanent commit subject. One from the #1334 dogfood is now real history on the scratch repo: Open TODO_AGENTS.md and work on the FIRST open entry only. When the work (fix #1) It reads like a title while being neither a description of the change nor a whole sentence, and a drain preset's first line is identical across every run it fires — so repeated firings produce near-identical subjects that say nothing about what each one changed. It lands hardest where nobody is watching: unattended work, whose PRs merge without a human ever reading the title. The middle rung is gone. What replaces it is the better half of #1618: an agent that can be asked to describe its PR can be asked to name it. #1612 moved PR opening onto the path where the framework composes the title, and #1567 already has the agent writing the body in an `open-pr` block — so the block now reads like a commit message. First line the title, the rest the body: ```open-pr Keep the queued state across a reload The reader re-read the file on mount, so … ``` A first line longer than 100 characters is not a name for the work, it is the opening of a paragraph, and it is taken as body text rather than cut to fit — truncating a sentence into a title is the bug, not the fix. The title then falls back to the session's name, and past that to `Session <id>`, which says little but misleads nobody. Both halves of the block are defused for a plan agent now, not just the body: since the title is the agent's own prose, a closing phrase there would ride the squash-merge subject straight into the issue — which is what #1560 was. The event that carried the block is `open-pr` rather than `pull-request-description`: it carries a title as well as a description, and the old name is also one character from the `pull-request` event that records the PR the framework actually opened. Closes #1618
|
🤖 agent comment Dogfooded on the real daemon, and the run happened to be the exact case this is about: the session emitted no Built the branch, restarted the daemon on it, and started one unattended run against a scratch repo — "Add a CONTRIBUTING.md at the repository root: one short paragraph on how to run index.js, and a two-line note on how to open a pull request." What the framework opened (suleimansh/tf-1334-dogfood#3):
The agent's record for that run: Three things this actually shows:
For contrast, the same repo's history from the run that found this — a real commit subject on its
|
|
@brillout flagging this one because it changes the signal protocol every session is given, not just code.
The reason for touching the prompt rather than only the code: a session that emitted no session name had its PR titled with 72 characters of its own prompt, cut mid-sentence, and the squash merge made that a permanent commit subject on Tested end to end on the real daemon: the run I drove emitted no session name at all — exactly the case — and titled its PR "Add CONTRIBUTING.md with run and pull request instructions". Evidence in the comment above. Two decisions in here worth your veto:
|
|
The prompt changes are okay 👍 (a little bit too babbling at one place, but it's okay). |
… constraint Rom's read of #1621: the prompt change is fine, one place babbles. It did — the same rule was stated three times over. The placeholder repeated the failure mode the sentence above it already implies, and a sentence about squash merges making the title a permanent commit subject was rationale for us, not an instruction for the session reading it. Every session is given this file, so a sentence that only explains ourselves to ourselves is paid for on every run.
…mpt (#1621) * The quota gate is asked which model the work will run on `quotaBoundaryStatus` takes a model, filters the account's `week-model` windows down to that model's own week, and measures it against the same boundary as the account's week — documented, unit-tested, and never once called with a model in production. `dashboard/quota.ts` was the only caller and passes none, which is right for the panel it feeds: the bar is about the account. But nothing else computed a boundary at all, so both self-starting paths — auto PM and the CI-watch fix — gated on that same model-blind reading. Live on this account today: the week is 54% used, the Fable week is 100% used, and the gate said start. Every run it started died at its first API call. The fix is a second question rather than an argument on the first. `QuotaSource` grows `boundaryFor(model)` beside `read()`, both measured off the same reading and the same slider position, so #960's "one source" promise holds — the panel and the gate cannot disagree about the account, only about a question the panel never asks. Making `read()` take a model would instead have left the panel's call site looking like it had simply forgotten to pass one, which is exactly how this went unnoticed. The daemon resolves the model the way it resolves everything else about a background start: `resolveProjectAgentOptions`, the same two tiers the start itself uses, so the gate cannot measure a different model than the one that runs. That makes it per project rather than per sweep — the model is a project setting — so auto PM's `quota` seam now takes the project. It costs no extra reading: the poller's last good windows are simply measured again. A model with no window of its own, and a project with no model set, are gated on the account's week exactly as before: with nothing chosen the driver picks, and a window nobody can tie to the work must never stop it (#879). Blocked work now stands down instead of dying at the API. Auto PM already names the window that stopped it ("Current week (Fable) is 100% used"), which reaches the dashboard's own line under the toggle. The CI-fix half said nothing at all, so it now logs its stand-down once per failing head commit — the same re-arm rule its attempt cap uses, rather than a line per tick for as long as the PR stays red. The end-to-end test is the half that was missing here, so it uses the real poller and the real `pollerQuotaSource` over a stubbed driver read: a fake would have answered whatever the test wanted, which is how an argument only tests ever passed stayed unwired. Verified against the live reading too — the account's own label is `Current week (Fable)`, byte for byte the fixture's. Closes #1619 * A pull request is titled with a name for its work, never with the prompt A session that emitted no session name got its PR titled `intent.slice(0, 72)` — the instruction it was given, cut wherever 72 characters landed. The squash merge inherits the PR title, so that becomes a permanent commit subject. One from the #1334 dogfood is now real history on the scratch repo: Open TODO_AGENTS.md and work on the FIRST open entry only. When the work (fix #1) It reads like a title while being neither a description of the change nor a whole sentence, and a drain preset's first line is identical across every run it fires — so repeated firings produce near-identical subjects that say nothing about what each one changed. It lands hardest where nobody is watching: unattended work, whose PRs merge without a human ever reading the title. The middle rung is gone. What replaces it is the better half of #1618: an agent that can be asked to describe its PR can be asked to name it. #1612 moved PR opening onto the path where the framework composes the title, and #1567 already has the agent writing the body in an `open-pr` block — so the block now reads like a commit message. First line the title, the rest the body: ```open-pr Keep the queued state across a reload The reader re-read the file on mount, so … ``` A first line longer than 100 characters is not a name for the work, it is the opening of a paragraph, and it is taken as body text rather than cut to fit — truncating a sentence into a title is the bug, not the fix. The title then falls back to the session's name, and past that to `Session <id>`, which says little but misleads nobody. Both halves of the block are defused for a plan agent now, not just the body: since the title is the agent's own prose, a closing phrase there would ride the squash-merge subject straight into the issue — which is what #1560 was. The event that carried the block is `open-pr` rather than `pull-request-description`: it carries a title as well as a description, and the old name is also one character from the `pull-request` event that records the PR the framework actually opened. Closes #1618 * Say it once: the open-pr instruction loses its aside and its restated constraint Rom's read of #1621: the prompt change is fine, one place babbles. It did — the same rule was stated three times over. The placeholder repeated the failure mode the sentence above it already implies, and a sentence about squash merges making the title a permanent commit subject was rationale for us, not an instruction for the session reading it. Every session is given this file, so a sentence that only explains ourselves to ourselves is paid for on every run.
A session that emits no session name had its PR titled
intent.slice(0, 72)— the instruction it was given, cut wherever 72 characters landed. Squash-merge inherits the PR title, so it becomes a permanent commit subject. This one is real history on the #1334 dogfood repo:It reads like a title while being neither a description of the change nor a whole sentence. A drain preset's first line is identical across every run it fires, so repeated firings produce near-identical subjects saying nothing about what each one changed — and it lands hardest exactly where nobody is watching, on unattended work whose PRs merge without a human reading the title.
The block reads like a commit message
The issue offered a narrow fix (drop the middle rung) and a better one: an agent that can be asked to describe its PR can be asked to name it. This is the better one. #1612 moved PR opening onto the path where the framework composes the title, and #1567 already has the agent writing the body in an
open-prblock, so the block gains a title line:The three rungs are now all names for the work: the agent's own title, else the session's name, else
Session <id>— which says little, but says it honestly. The prompt is not among them.A first line longer than 100 characters is not a name for the work, it is the opening of a paragraph: it is taken as body text and the title falls back, rather than being cut to fit. Truncating a sentence into a title is the bug, not the fix.
Two things that fall out of it
Plan agents defuse both halves now. The title is the agent's own prose since this change, so a closing phrase in it would ride the squash-merge subject straight into the issue — which is what #1560 was. The body has been defused since then; the title had never carried prose before.
The event is
open-pr, notpull-request-description. It carries a title as well as a description, and the old name was one character from thepull-requestevent that records the PR the framework actually opened.Prompt change
prompts/protocols/signal.mdnow asks for the title line and says why it is worth a sentence (the squash merge makes it permanent). Flagged because it changes what every session is told, whatever else it was started for.Closes #1618