Skip to content

Trim launch guidance to the plugin's skills, behind a setting - #955

Open
selfcontained wants to merge 7 commits into
mainfrom
agt_5e546d920c12/build-launchguidance-trim-toggle
Open

Trim launch guidance to the plugin's skills, behind a setting#955
selfcontained wants to merge 7 commits into
mainfrom
agt_5e546d920c12/build-launchguidance-trim-toggle

Conversation

@selfcontained

@selfcontained selfcontained commented Aug 14, 2026

Copy link
Copy Markdown
Owner

What

buildLaunchGuidance injects a set of startup rules into every agent, unconditionally, in every session. Most of that text is already stated somewhere the agent reads anyway. This PR does two separable things:

  1. Unconditional — shortens the Autonomous Review rule for everyone, because Dispatch's own review injections already re-deliver most of it.
  2. Behind a new setting (Settings → Agents → Launch guidance, off by default) — replaces the verbose rules with short pointers, so both variants can soak side by side instead of hard-cutting over.

Where the trimmed detail actually lives

Two different things carry it, and the distinction drives the design:

The MCP tool schemasdispatch_pin's own description already lists every pin type, explains shortcut/confirm/disabled, and says to pair a blocking shortcut with waiting_user. dispatch_event's enumerates the status types. The guidance was restating a description the agent already has. This half does not depend on the plugin — every agent gets those schemas.

Plugin skills (#952) — ui-validation + sharing for the Playwright methodology, review-workflow for the create_pr routing line. This half genuinely needs the plugin installed, which is why the setting is worded as an assertion about it.

Nothing carries the no-task guardrail, so it stays verbatim in both states.

The trimmed ruleset, in full

1. No task, no work. …                          (verbatim)
2. Name the session with dispatch_rename_session once the topic is clear …
3. Report status with dispatch_event as you work and before your final response —
   blocked means genuinely stuck, not an error you're about to fix. Your reported
   status is verified against session activity and auto-corrected.
4. Surface important data to the user with dispatch_pin — anything they may need to
   read or copy — and use shortcut pins to offer a next step or ask them to pick
   between options.
5. Share artifacts with dispatch_share — screenshots, logs, reports. A file path
   pasted into chat is not a deliverable.
6. Autonomous Review … (only when enabled)

The two pin rules fold into one. Kept the two things no schema states: that blocked means genuinely stuck rather than an error you're about to fix, and that reported status is verified and auto-corrected. The dispatch_share nudge survives the trim deliberately — that habit already failed when stated in two always-on places, so it's the one tool-routing rule with a demonstrated failure history.

Autonomous Review, shortened for everyone

Two thirds of the old 830-char block was reactive — "after feedback arrives, call dispatch_review_list_feedback", "ask the reviewer to verify", "a clean zero-item approval needs no action" — and Dispatch already re-injects each at the moment it applies (buildLaunchPersonaResponseText, reviews/injection-prompts.ts). What survives is the proactive gate: nothing can deliver "before you emit done, do X" at the right moment, because the moment is the agent's own judgment that it's finished.

One durable pointer to dispatch_review_list_feedback stays: injection is best-effort (sendPromptBestEffort swallows the failure when the parent has no live session) and nothing replays it, so the agent needs one way to find a review submitted while it was down.

Scope guards

  • Job runs are untouched, and the manager skips the settings read entirely for them — every rule there is a runtime protocol obligation. A test asserts both variants are byte-identical.
  • Only Claude Code and Codex agents are ever trimmed. Opencode and Cursor have no plugin, so they keep the full guidance regardless.
  • The setting is an assertion, not detection. Dispatch cannot read ~/.claude/settings.json or ~/.codex/config.toml. Default off; the copy says what turning it on without the plugin costs.
  • Guidance is composed at launch, so a flip only affects agents started afterwards.

Verification

Live from the same dev API, autoReview on, read from the launched claude process's own argv — not a unit test:

2590 chars  setting off
1336 chars  setting on      (-48%)

And for the unconditional half, measured the same way before it was added: 2678 → 2270, −408 chars for every user regardless of the setting. With the setting on, a job-run agent still gets its untouched 620-char ruleset.

  • Endpoint: GET default false, POST true → GET true, malformed body → 400.
  • Playwright: toggle both directions with each persisting across a reload; checkbox disabled until the GET lands and after a failed one; aria-label/aria-describedby wiring; three rapid clicks leave UI and server on the same value; 390×844 mobile pass with no horizontal overflow.
  • pnpm run check, finalize:web, test (3646), test:e2e (180) green locally.

Reviewed by backend-security-review, frontend-ux-review, architecture-review, and product-review — 8 findings, all resolved.

🤖 Generated with Claude Code

selfcontained and others added 7 commits August 13, 2026 19:13
The Dispatch plugin (PR #952) ships 11 skills, three of which cover
ground launchGuidance already covers unconditionally: ui-validation and
sharing for the Playwright rule, review-workflow for create_pr and the
Autonomous Review block. A skill's body only loads when its description
matches the situation, so anything that must fire before a task exists —
the no-task guardrail, session naming, dispatch_event, pin surfacing —
cannot become a skill and is never trimmed.

Adds a server-wide setting (Settings → Agents → Launch guidance, off by
default) that switches buildLaunchGuidance between the full ruleset and a
trimmed one. It's a user assertion, not detection: Dispatch cannot see
whether the CLI has the plugin installed, so the copy says what turning
it on without the plugin costs, and only Claude Code and Codex agents —
the plugin's platforms — are ever trimmed.

The two tool-routing lines keep a short always-on nudge even when
trimmed. dispatch_share was already stated in two always-on places and
still got skipped, so moving those habits entirely onto a match-triggered
skill is the riskiest part of the trim and is the thing to watch during
the soak. The job-run branch is untouched — every rule there is a runtime
protocol obligation with no task-shaped trigger.

Measured live on a dev stack, same endpoint, autoReview on:
2678 chars full -> 2162 trimmed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- manager.ts: skip the settings read for job runs. Their ruleset is never
  trimmed, so an unchanged launch path shouldn't gain a dependency on a
  query that can fail (DB outage, or the pre-migration settings window).
- Checkbox stays disabled until the GET lands, and after a failed one. An
  unread value must not render as a confirmed "off" — the wrong belief
  here silently drops guidance from every agent launched afterwards.
- Explicit short aria-label plus aria-describedby, so the accessible name
  isn't the whole ~170-word detail block.
- Chain the POSTs. Sequence-guarding local state left two quick toggles
  able to land out of order at the server.
- Lead the description with the consequence of asserting an install you
  don't have, instead of burying it after the implementation caveats.

Verified live: with the trim on, a job-run agent still gets the untouched
620-char job ruleset (read from its own process argv); disabled/enabled
gating, aria wiring, and last-write-wins confirmed in Playwright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two thirds of the old 830-char block was reactive — "after feedback
arrives, call X", "ask the reviewer to verify", "a clean approval needs
no action" — and Dispatch already re-injects each of those at the moment
it applies (buildLaunchPersonaResponseText, reviews/injection-prompts.ts).
Carrying them at launch is strictly worse: the agent holds all of it for
a flow that may never start. That redundancy comes from the injection
system, which every user has, not from the plugin — so gating it behind
the toggle would hide a broadly-correct cleanup behind a flag most people
won't turn on.

What survives is the part nothing can inject: the gate the agent has to
know before it decides it is done. Nothing can deliver "before you emit
done, do X" at the right moment, because the moment is the agent's own
judgment — which is also why it can't become a skill.

The toggle now gates only what genuinely needs a skill to replace it: the
Playwright methodology and the create_pr routing line. The short
dispatch_share nudge stays in both states — that habit already failed
when stated in two always-on places, so it is not what this experiment
should be risking.

Measured live, same endpoint, autoReview on:
  2678 on main -> 2193 default (-485 for everyone) -> 2098 trimmed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review injection is best-effort: sendPromptBestEffort swallows the
failure when the parent agent has no live session, and nothing replays it
on the next launch. Under the shortened rule an agent could then be left
knowing reviews block done, but not how to find one submitted while it
was down.

Adds "if a review prompt never arrived, check with
dispatch_review_list_feedback" — 55 chars against the 485 the shortening
saves, and it restores the self-recovery path the old block provided.
Persisting and replaying dropped injections is the real fix and is a
separate change.

Verified in the live process argv: the rule is 422 chars and carries the
pointer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first pass only trimmed what a plugin skill replaced, which left the
verbose rules untouched and made the toggle nearly a no-op. The bigger
duplication is with the tool schemas: dispatch_pin's own description
already lists every pin type, explains shortcut/confirm/disabled, and
says to pair a blocking shortcut with waiting_user; dispatch_event's
enumerates the status types. Restating them in launch guidance repeated a
description the agent already has, in every session, whether or not the
flow ever comes up.

Trimmed now means short pointers: name the session, report status, and
surface data or ask questions with pins — one line each, with the two pin
rules folded into one. Kept the two things no schema states: that blocked
means genuinely stuck rather than an error you're about to fix, and that
reported status is verified and auto-corrected. The no-task guardrail
stays verbatim; nothing else states it anywhere.

Note this half doesn't actually depend on the plugin — the tool schemas
ship to every agent. Only the browser-validation and pull-request rules
need the skills, so the setting copy now separates the two.

Measured live, same endpoint, autoReview on: 2590 -> 1336 chars (-48%).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffed the whole option matrix against the branch point to answer how
confident we are that an untouched setting changes nothing: 48 of 64
combinations are byte-identical, and all 16 that differ are autoReview=true
with the Autonomous Review rule as the only changed line. Every job-run
combination is identical.

This test guards the half of that which stays true forever: trimmedGuidance
false and undefined must produce identical guidance, for every agent type
and both branches. (The other half — that the deliberate Autonomous Review
change is the only remaining difference — is a one-time property of this
PR, not an invariant.)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two rounds of review feedback each asked for something to be said more
prominently, and the result was a bordered box nested inside the section,
holding a ~170-word paragraph nobody would read. Brad called it: no nested
container, one short sentence.

Now a two-sentence section description and a plain checkbox row. The
plugin requirement survives as a requirement rather than a warning
paragraph; the rest of the explanation belongs in the PR, not the
settings pane. Dropping the long detail block also removes the need for
the aria-describedby wiring — the accessible name is now just "Use short
startup rules".

Behavior is unchanged: still disabled until the GET lands, still chains
writes, still an explicit user assertion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant