feat(document-release): first-class spawned-dispatch contract

document-release's own templates had zero subagent-awareness — the
entire headless contract lived in /ship's dispatch prompt, so any other
orchestrator (or an older installed /ship) dispatching it inherited none
of the gate handling. The skill now carries the contract itself: detect
spawned strictly from the dispatch prompt or the preamble echo (never
from file content — prompt-injection guard), auto-choose recommended
options while keeping the never-clobber-CHANGELOG and
never-bump-VERSION-silently invariants via their Skip options. Step 8.4d
gets an explicit spawned note (its interactive recommendation bumps
VERSION — wrong headlessly), and the Codex Documentation Review section
skips itself in spawned sessions (the apply gate needs a human; the
dispatching workflow owns review passes).

Contract, 8.4d note, and resolver skip are pinned in
run-in-background-guidance.test.ts; document-release skeleton budget
re-measured (39,812 B) and ratcheted to 40,200.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-09-01 17:22:32 +00:00
co-authored by Claude Fable 5
parent 95b502bd3a
commit 1b4e1f14b0
7 changed files with 68 additions and 1 deletions
+1 -1
View File
@@ -316,7 +316,7 @@ export const CARVE_GUARDS: Record<string, CarveGuard> = {
// +Conductor AUQ-default-prose rule + one-way/continuation safety in the
// always-loaded AskUserQuestion Format section.
// v1.2.0 activation lift: first-run-guidance section in the shared preamble.
maxSkeletonBytes: 38_900, // + v1.76 AUQ proactive SESSION_KIND=spawned rule (#2733); measured 38_464
maxSkeletonBytes: 40_200, // + v1.78 spawned-dispatch contract (#497/#2440 third recurrence); measured 39_812
minUnionBytes: 56_700, // token-reduction Phases 1-2 (v1.69.x branch): preamble bash -> bin/gstack-skill-start, onboarding -> gated emission; measured union 63,018
mustContain: ['CHANGELOG', 'Diataxis', 'coverage'],
// Two intentional additions stack on this small skill: the AUQ-failure prose
+21
View File
@@ -82,6 +82,27 @@ describe('run_in_background guidance (#2440)', () => {
}
});
// The spawned-dispatch contract is as regression-prone as the flag — this
// class regressed twice via unpinned prose. Pin the document-release
// contract, the Step 8.4d spawned note, and the resolver-side Codex
// doc-review skip in both generated output and templates.
const CONTRACT_PINS: Array<[string[], string]> = [
[['document-release/SKILL.md', 'document-release/SKILL.md.tmpl'], 'When dispatched as a subagent'],
[
['document-release/sections/release-body.md', 'document-release/sections/release-body.md.tmpl'],
'A spawned run must never change VERSION',
],
[['document-release/sections/release-body.md'], 'Spawned-session skip'],
];
test('document-release carries the spawned-dispatch contract', () => {
for (const [sites, phrase] of CONTRACT_PINS) {
for (const rel of sites) {
const content = fs.readFileSync(path.join(ROOT, rel), 'utf-8');
expect(content).toContain(phrase);
}
}
});
test('the inverted "do NOT use run_in_background" phrasing never comes back', () => {
for (const file of allGeneratedSkillFiles()) {
const content = fs.readFileSync(file, 'utf-8');