Fix everything the SPEC.md migration's grounding pass flagged - #1611
Merged
Conversation
The Queues section's rendered copy flipped the meaning of its own spec — "the cockpit that keeps humans in control" — into "keeps humans under control". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011XvEviGLEJZsp1h6iWzgma
The shared watch link's serving side went in #1536; the browser side stayed: RelayView, App's dead ?run= branch, and six spec sentences still promising the feature. The component and branch go, the hooks fall back to their defaults (the dashboard is always local now), and the specs stop naming the watch view, the shareable-link menu item, and the relay's own agents. The device relay — a different, live feature — is untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011XvEviGLEJZsp1h6iWzgma
The migration's grounding pass flagged claims the code contradicts; this closes them: the Overview rollup carries no recent-activity data (spec and test spec now say what the tests cover, including the shape guard), the handoff tests read the recorded branch and PR rather than re-deriving them, the handoff setting has no legacy spelled-out form, dashboard-rpc separates control-file writes from direct handoff/daemon writes and drops the preview claim, onboarding no longer names the removed public-host mode, last activity comes from agents alone, the theme default lives dashboard-side, the editor dropdown is runtime-detected, and project.ts loses its dead dependency-detection remnants (unused import, stale docblock, stale spec claims). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011XvEviGLEJZsp1h6iWzgma
This was referenced Aug 21, 2026
suleimansh
added a commit
that referenced
this pull request
Aug 21, 2026
Rom on #1612: wrapping the reference in backticks stopped the closing, but it also stopped the reference being a link, and stopped the issue's own timeline recording that a pull request had mentioned it. The ticket lost the backlink that says someone is discussing it. GitHub only obeys a closing keyword when the reference follows it directly, so two words in between are enough: `close #1164` becomes `close the ticket #1164`. The sentence still reads as the agent wrote it, the reference is untouched — clickable, and still cross-referenced onto the issue. Idempotence now falls out of the rewrite instead of needing a guard: after the first pass the keyword is followed by the filler, not by a reference. A reference already inside backticks is still skipped — it is a code sample, GitHub does not act on it, and the filler would corrupt it. Also lands the agent-handoff.test.SPEC.md clause deferred while #1611 was rewriting that sentence.
suleimansh
added a commit
that referenced
this pull request
Aug 21, 2026
…hemselves (#1567) (#1612) * Agents open a pull request through the framework by describing it, rather than running gh themselves #1567 found that a plan agent's PR body ended "…then comment on and close #1164", which GitHub read as a closing keyword: the plan merged, the issue closed, and the next tickets sync deleted the ticket and its fresh plan. The first fix directions were both wrong. Linting closing keywords out of every PR body breaks the correct case — 8 of the last 40 PRs legitimately close their issue that way. And the body that caused it was the agent's own: it ran `gh pr create` itself, outside the handoff path, where the framework never sees the text. brillout's answer on the issue: "As always, I'd frame it as a capability… We avoid limiting agents — we *enable* agents instead." So there is no prohibition here. An `open-pr` block is a new non-blocking signal, alongside set-session-name and ready-for-merge: the agent writes the description, the framework opens the PR. The agent gets to say what the change turned out to be instead of the PR body reciting the opening prompt; the framework keeps the parts that have to stay consistent — the title from the session name, the ticket's `(fix #N)`, and recording the number on the agent. An agent that prefers to open its own still can. The closing-keyword bug is then fixed where it belongs: a plan agent's description is defused before it is published, because a plan agent's PR lands the plan, not the work. That is the same rule that already keeps `(fix #N)` off a plan agent's title (#1327) — this is its other half. Defusing wraps the issue reference in backticks: the sentence a human reads is unchanged, and GitHub stops acting on it. Suite green: 1502 framework tests, 776 dashboard, typecheck clean. * Tie the open-pr block to the ready-for-merge moment, after a dogfood run skipped it Live evidence: a Sonnet run on a scratch project got the protocol verbatim in its system prompt (12,686 chars, `open-pr` present), emitted set-session-name and ready-for-merge from that same file, and did not emit open-pr. The other two signals name a concrete moment — the setSessionName() and setReadyForMerge() calls. This one said "when your work is ready to be published", which is not a moment the agent can recognize, and the agent had already emitted ready-for-merge by then. It now hangs off exactly that signal, and says what is lost without it. * Defuse closing keywords with a filler, so the issue reference stays live Rom on #1612: wrapping the reference in backticks stopped the closing, but it also stopped the reference being a link, and stopped the issue's own timeline recording that a pull request had mentioned it. The ticket lost the backlink that says someone is discussing it. GitHub only obeys a closing keyword when the reference follows it directly, so two words in between are enough: `close #1164` becomes `close the ticket #1164`. The sentence still reads as the agent wrote it, the reference is untouched — clickable, and still cross-referenced onto the issue. Idempotence now falls out of the rewrite instead of needing a guard: after the first pass the keyword is followed by the filler, not by a reference. A reference already inside backticks is still skipped — it is a code sample, GitHub does not act on it, and the filler would corrupt it. Also lands the agent-handoff.test.SPEC.md clause deferred while #1611 was rewriting that sentence.
suleimansh
added a commit
that referenced
this pull request
Aug 21, 2026
* Remove the code the watch relay's deletion left behind #1536 deleted the hosted watch relay and #1611 cleaned up after it, but three things it was the only reason for stayed: - AgentFeed's showSessionLink/showName/showStatus were passed `false` by AgentView, its only caller, so the AgentOverview they configured hit its `if (!sessionLink && !status) return null` on every render. The props and that render are gone; AgentOverview itself stays, since ProjectHome uses it with the defaults. - The `enabled` parameter on useWorking/useDaemonHealth/useFavicon was never passed `false` by anything — the relay view had been its only caller. Gone, along with the two tests that existed only to cover it. - Comments and specs across nine files still explained live behaviour by naming the deleted relay: FileTree "has no checkout", GitStatusBar "on the relay", EventList's "read-only relay watch", RoutineWork's sweep note, favicon, use-daemon-health's tests. The behaviour is real in each case, only the reason was a ghost — reworded to state the condition itself. The device relay (#1067) is untouched: relay-endpoints, relay-dispatch and relay-agent are a different feature that shares the word. No FEATURES-SPEC.md change: none of this was user-visible. Suite 1489 + 774, typecheck clean. * AgentFeed's projectId is required: an open gate must never render as log text The last of the same shape #1615 removes. AgentView is AgentFeed's only caller and always passes projectId, so the optional prop had exactly one production value — and the conditional forward below it could only ever take one branch. Required is the point, not tidiness: with it optional, a future caller that omits it gets an open choice gate silently rendered as plain log text, which is a run parked with nothing to answer it (#846). A required prop makes that a compile error instead of a dead-quiet downgrade. EventList's own projectId stays optional. It is a leaf presentational component with 35 direct test renders, and its browser pane already degrades on a genuinely nullable agentId, so the absent case is a real render mode there rather than a fiction.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #1609: that PR preserved every spec claim the code contradicts and listed them as findings; this PR closes them all — the 13-finding list, plus the watch-relay amplification suleimansh's review added. Three commits:
1. Website copy bug — the Queues section of the-framework.ai rendered "it keeps humans under control"; the spec (and the point of the product) says "in control". One word,
Queues.tsx.2. Watch-relay orphans — the shared watch link's serving side was removed in #1536, but the browser side survived:
RelayView.tsx, App's dead?run=early return, and six spec sentences still promising the feature (watch mode, the "copy a shareable watch link" menu item thatAgentActionsMenu.tsxdoesn't have, the shared-watch page in the components list, the shared-link sentence in the package spec, and the relay's-own-agents case inevents.SPEC.md). All gone; theuseWorking/useFavicon/useDaemonHealthcalls fall back to their defaults since the dashboard is always local now. The device relay (daemon-to-daemon,/_relay/events?run=) is a live feature and is untouched.3. Spec-drift corrections — each flagged claim brought back to what the code does, verified against the named code before editing:
src/dashboard/dashboard.SPEC.md+ test spec: the rollup carries no recent-activity data; the test spec now describes the actual tests (totals, working-now, ordering, ticket presence, and the shape guard pinning retired fields absent).src/dashboard/agent-handoff.test.SPEC.md: tests read the recorded branch and PR rather than re-deriving across candidate names.src/handoff-level.SPEC.md: no stored spelled-out three-stage form exists — the sanitizer reads onlyhandoff.src/dashboard-rpc/SPEC.md: control-file appends (stop, choice, message, arm handoff) separated from direct writes (push/PR/merge run the handoff; start and queue-ticket go through the daemon's wiring).src/dashboard-rpc/control.SPEC.md: "previews" dropped from the direct-wiring list.src/dashboard-rpc/projects.SPEC.md: the removed public-host mode no longer qualifies the onboarding hint.src/dashboard/projects.SPEC.md: last activity comes from the project's agents alone.dashboard/lib/preferences.SPEC.md: notification defaults are framework-side; the theme default (absent follows the OS) lives dashboard-side.dashboard/components/SettingsPage.SPEC.md: the editor dropdown is assembled at run time from detected editors.src/project.SPEC.md+project.ts: the dependency-detection remnants go — stale spec claims, the unusedreadFileSyncimport, and the docblock's "detection signals".No feature is added or removed: the watch relay was already removed in #1536 (it has no FEATURES-SPEC.md row), so
FEATURES-SPEC.mdis untouched.Verification:
pnpm typecheckclean,pnpm build+ all 1489 node tests pass, all 776 dashboard vitest tests pass (the 8 daemon-test failures in a buildless checkout reproduce without these changes — they needdist/and pass after a build), and the spec linter is green over all 557 SPEC.md files.🤖 Generated with Claude Code
https://claude.ai/code/session_011XvEviGLEJZsp1h6iWzgma
Generated by Claude Code