mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-14 20:37:14 +01:00
fix(ship): make the five judge-flagged workflow spots match the code (GST-1346) (#4004)
* fix(ship): make the five judge-flagged workflow spots match the code (GST-1346)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): carry runs the pregate before its push (review fix)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): carry pushes early, waits for CI, then pregates; restore stage 1 wording (fix-check)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: diff-plus-blocking stops at the third fix cycle; carry order matches ship Step 1 (Step 14.5)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: changelog and TODOS
Documentation: updated
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* Revert "docs: diff-plus-blocking stops at the third fix cycle; carry order matches ship Step 1 (Step 14.5)"
This reverts commit 5151144c04.
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
2bf6bd7942
commit
15dac66e33
21 files changed
+370
-388
No files matched your search
@@ -0,0 +1 @@
|
||||
- **/ship's workflow now matches what its tools do, so main's backstop judge can pass.** The `ship/SKILL.md workflow` judge still failed on main at 622e8b1f (run 41884510834) because the prose and the code disagreed in five places. Step 11's Codex passes and every `CODEX_MODE` branch now follow the review plan's `DISPATCH:` lines, as /ship's driver does; they no longer say the native pass always runs. The review policy now gives one fix-loop cap. It is two rounds under `review_scope: frozen` (the review plan's stop) and Step 9.4's third fix cycle under the other scopes. Step 16 says `finish` runs stages 1–4, diffs the reviewed tree and checks each lane's receipt itself, what to pass when no reviewed tree was saved, and that a stage 5 commit of regenerated outputs is content-preserving. A Step 1 carry now says to push with the secrets scan and wait for CI before the pregate, and that it ends the run with its own result line. The ship, review and unattended docs now say `diff-plus-blocking` stops at Step 9.4's third fix cycle, as the workflow runs it, and give the same carry order. The Step 5 CI-carry push asks no consent, and Step 6.5's Greptile question says it cannot undo that push. No behavior changes. Reviewer briefs are byte-identical; the adversarial section's pin is updated under GST-1346's brief-identity check. (GST-1346)
|
||||
+2
-2
@@ -39,8 +39,8 @@ export const PARTS: PartSpec[] = [
|
||||
{ id: 'review-9.4', file: RA, from: '## Step 9.4: Fix-First and persistence', phase: 4 },
|
||||
{ id: 'adversarial-11', file: ADV, from: null, phase: 4 },
|
||||
{ id: 'adversarial-native', file: ADV, from: '### Claude adversarial subagent (on `DISPATCH: adversarial-native`)', phase: 4 },
|
||||
{ id: 'adversarial-codex', file: ADV, from: '### Codex adversarial challenge (runs whenever `CODEX_MODE` is `ready` or `unverified`)', phase: 4 },
|
||||
{ id: 'adversarial-structured', file: ADV, from: '### Codex structured review (large diffs only, 200+ lines)', phase: 4 },
|
||||
{ id: 'adversarial-codex', file: ADV, from: '### Codex adversarial challenge (on `DISPATCH: outside-voice`, when `CODEX_MODE` is `ready` or `unverified`)', phase: 4 },
|
||||
{ id: 'adversarial-structured', file: ADV, from: '### Codex structured review (on `DISPATCH: outside-voice`, 200+ lines)', phase: 4 },
|
||||
{ id: 'adversarial-finish', file: ADV, from: '### Persist the review result', phase: 4 },
|
||||
{ id: 'adversarial-learnings', file: ADV, from: '## Capture Learnings', phase: 4 },
|
||||
{ id: 'documentation', file: DOCS, from: null, phase: 6 },
|
||||
|
||||
@@ -155,13 +155,13 @@ On any error: continue — ${feature} is informational, not a gate.`;
|
||||
* - `codex-only` (diff adversarial): disabled gates only the Codex passes; the
|
||||
* free Claude adversarial subagent still runs.
|
||||
*/
|
||||
export function codexPreflight(opts: { modeVar?: string; disabledBehavior: 'skip-all' | 'codex-only'; nativeReview?: boolean; role?: boolean }): string {
|
||||
export function codexPreflight(opts: { modeVar?: string; disabledBehavior: 'skip-all' | 'codex-only'; nativeReview?: boolean; role?: boolean; nativeDispatched?: boolean }): string {
|
||||
const m = opts.modeVar ?? '_CODEX_MODE';
|
||||
const disabledLine = opts.disabledBehavior === 'codex-only'
|
||||
? 'Skip the Codex passes only; the Claude adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running Claude adversarial only."'
|
||||
? (opts.nativeDispatched ? 'Skip the Codex passes only; the Claude adversarial subagent below still follows its DISPATCH line. Print: "Codex passes skipped (codex_reviews disabled)."' : 'Skip the Codex passes only; the Claude adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running Claude adversarial only."')
|
||||
: 'Skip this section entirely; do NOT fall back to a Claude subagent — disabled means no extra review step. Print: "Codex review skipped (codex_reviews disabled). Re-enable: `gstack-config set codex_reviews enabled`."';
|
||||
const nativeRoute = opts.disabledBehavior === 'codex-only'
|
||||
? 'Keep the required Claude adversarial pass; do not dispatch a duplicate.'
|
||||
? (opts.nativeDispatched ? 'The Claude adversarial pass follows its own DISPATCH line.' : 'Keep the required Claude adversarial pass; do not dispatch a duplicate.')
|
||||
: 'Fall back to the Claude subagent path.';
|
||||
return `\`\`\`bash
|
||||
# Codex preflight: the probe runs as a command, so any shell works.
|
||||
|
||||
@@ -144,15 +144,15 @@ If the subagent fails or times out, record native coverage as incomplete. Contin
|
||||
}
|
||||
|
||||
function adversarialOutsideChallenge(ctx: TemplateContext, isShip: boolean): string {
|
||||
return `### ${outsideVoiceFor(ctx).label} adversarial challenge (runs whenever \`CODEX_MODE\` is \`ready\` or \`unverified\`)
|
||||
return `### ${outsideVoiceFor(ctx).label} adversarial challenge (${isShip ? 'on \`DISPATCH: outside-voice\`, when' : 'runs whenever'} \`CODEX_MODE\` is \`ready\` or \`unverified\`)
|
||||
|
||||
If \`CODEX_MODE\` is \`ready\` or \`unverified\`:
|
||||
${isShip ? 'On \`DISPATCH: outside-voice\`, if' : 'If'} \`CODEX_MODE\` is \`ready\` or \`unverified\`:
|
||||
|
||||
Outside prompt (supply repository context from the parent):
|
||||
|
||||
"${CODEX_BOUNDARY}Review the changes on this branch against the base branch. Use the supplied branch diff. If it was not supplied and you have repository tools, run DIFF_BASE=$(git merge-base origin/<base> HEAD) && git diff "$DIFF_BASE". Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. A finding blocks only if it ${BLOCKING_FLOOR}; end each finding with \`Severity: Critical|High|Medium|Low\` and \`Blocks: yes|no\`. End your output with ONE line in the canonical format \`Recommendation: <action> because <one-line reason naming the most exploitable finding>\`. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale."
|
||||
|
||||
${outsideVoiceInvocation(ctx, { timeoutMs: 540000, nativeAlreadyRequired: true, diffCommand: 'DIFF_BASE=$(git merge-base origin/<base> HEAD) && git diff "$DIFF_BASE"' })}
|
||||
${outsideVoiceInvocation(ctx, { timeoutMs: 540000, nativeAlreadyRequired: isShip ? 'dispatched' : true, diffCommand: 'DIFF_BASE=$(git merge-base origin/<base> HEAD) && git diff "$DIFF_BASE"' })}
|
||||
|
||||
Present the full output verbatim. A Critical, High or \`Blocks: yes\` finding is CRITICAL; \`Blocks: no\` never lowers one, and only a named policy ground drops it. ${isShip ? 'An unavailable outside challenge does not block shipping by itself; supported findings still enter Step 11, and the structured P0/P1 and non-convergence gates still apply.' : 'This outside challenge is informational; supported findings still enter Step 5 Fix-First, whose approval and convergence gates apply.'}
|
||||
|
||||
@@ -161,19 +161,19 @@ ${outsideVoiceFailurePolicy(ctx, { timeoutMinutes: 9, onTimeout: 'missing-covera
|
||||
|
||||
|
||||
|
||||
For other modes, retain the native pass above; do not dispatch it again.
|
||||
${isShip ? 'Other modes skip it; the native pass follows its own DISPATCH line.' : 'For other modes, retain the native pass above; do not dispatch it again.'}
|
||||
|
||||
---`;
|
||||
}
|
||||
|
||||
function adversarialStructuredReview(ctx: TemplateContext, isShip: boolean): string {
|
||||
return `### ${outsideVoiceFor(ctx).label} structured review (large diffs only, 200+ lines)
|
||||
return `### ${outsideVoiceFor(ctx).label} structured review (${isShip ? 'on \`DISPATCH: outside-voice\`, 200+ lines' : 'large diffs only, 200+ lines'})
|
||||
|
||||
If \`CODEX_MODE\` is \`ready\` or \`unverified\` and either \`DIFF_TOTAL >= 200\` or the user requested the override above:
|
||||
${isShip ? 'On \`DISPATCH: outside-voice\`, if' : 'If'} \`CODEX_MODE\` is \`ready\` or \`unverified\` and either \`DIFF_TOTAL >= 200\` or the user requested the override above:
|
||||
|
||||
Prepare a structured review prompt requesting severity-tagged findings ([P0]-[P3]) or an explicit NO_FINDINGS conclusion. Preserve the base-branch scope including committed changes and working-tree changes.
|
||||
|
||||
${outsideVoiceInvocation(ctx, { timeoutMs: 540000, nativeAlreadyRequired: true, structuredBase: '<base>', gate: 'structured', diffCommand: 'DIFF_BASE=$(git merge-base <base> HEAD) && git diff "$DIFF_BASE"' })}
|
||||
${outsideVoiceInvocation(ctx, { timeoutMs: 540000, nativeAlreadyRequired: isShip ? 'dispatched' : true, structuredBase: '<base>', gate: 'structured', diffCommand: 'DIFF_BASE=$(git merge-base <base> HEAD) && git diff "$DIFF_BASE"' })}
|
||||
|
||||
${outsideVoiceFor(ctx).id === 'codex' ? 'The Codex backend uses `codex review --base` without a positional prompt: those arguments are mutually exclusive. Never drop --base to resolve an argv error; prompt-only review changes the diff scope.' : 'The Claude Code backend receives the parent-captured base diff, including committed and working-tree changes, because review mode cannot execute git.'}
|
||||
|
||||
@@ -195,7 +195,7 @@ Read stderr for errors (same error handling as ${outsideVoiceFor(ctx).label} adv
|
||||
|
||||
|
||||
|
||||
If \`DIFF_TOTAL < 200\` without that override, skip structured review; the adversarial passes still run.
|
||||
If \`DIFF_TOTAL < 200\` without that override, skip structured review; the ${isShip ? 'dispatched ' : ''}adversarial passes still run.
|
||||
|
||||
---`;
|
||||
}
|
||||
@@ -250,13 +250,13 @@ echo "DIFF_SIZE: $DIFF_TOTAL"
|
||||
|
||||
**Detect the ${outsideVoiceFor(ctx).label} master switch + tool availability:**
|
||||
|
||||
${outsideVoicePreflight(ctx, { disabledBehavior: 'codex-only', nativeReview: true })}
|
||||
${outsideVoicePreflight(ctx, { disabledBehavior: 'codex-only', nativeReview: true, nativeDispatched: isShip })}
|
||||
|
||||
\`CODEX_MODE: disabled\` means skip the ${outsideVoiceFor(ctx).label} passes ONLY.
|
||||
\`ready\` and \`unverified\` run them; every other mode skips them with the printed reason.${isShip ? '' : `
|
||||
\`ready\` and \`unverified\` run them${isShip ? ' on \`DISPATCH: outside-voice\`' : ''}; every other mode skips them with the printed reason.${isShip ? '' : `
|
||||
The ${outsideVoiceFor(ctx).nativeLabel} adversarial subagent always runs.`}
|
||||
|
||||
**User override:** If the user explicitly requested "full review", "structured review", or "P1 gate", also run the ${outsideVoiceFor(ctx).label} structured review regardless of diff size (still requires \`CODEX_MODE: ready\` (or \`unverified\`)).
|
||||
**User override:** If the user explicitly requested "full review", "structured review", or "P1 gate", also run the ${outsideVoiceFor(ctx).label} structured review regardless of diff size (still requires ${isShip ? '\`DISPATCH: outside-voice\` and ' : ''}\`CODEX_MODE: ready\` (or \`unverified\`)).
|
||||
|
||||
---
|
||||
|
||||
@@ -309,7 +309,7 @@ in order before leaving Step 11:
|
||||
Otherwise insert Steps 9, 10 and 11 before the pending Step 11.5 in the work list.
|
||||
Step 9 completes full review before fixes; any further repair inserts its checks
|
||||
ahead of the remaining items. These fresh reviews after code edits are not recovery retries.
|
||||
Returning here never resets Step 9's three-cycle fix limit.
|
||||
Returning here never resets Step 9's three-cycle fix limit (under \`frozen\`, the plan's cap).
|
||||
3. **Native complete with no queued fixes, or not dispatched:** Finish the memory updates below,
|
||||
then continue to Step 11.5. Never jump directly to release preparation.` : 'The native pass is required for Step 5.8 completion. Optional outside failures remain separately recorded, not completed by native coverage. Return all findings and structured-review decisions to Step 5; the parent owns fixes and the full rerun.'}
|
||||
|
||||
|
||||
@@ -47,10 +47,10 @@ fi`;
|
||||
/** Caller-owned workflow role. Only enumerated plan-review generators pass it; everything else stays no-role. */
|
||||
export type OutsideRole = 'plan-review';
|
||||
|
||||
export function outsideVoicePreflight(ctx: TemplateContext, opts: { disabledBehavior: 'skip-all' | 'codex-only' | 'opt-in'; nativeReview?: boolean; role?: OutsideRole }): string {
|
||||
export function outsideVoicePreflight(ctx: TemplateContext, opts: { disabledBehavior: 'skip-all' | 'codex-only' | 'opt-in'; nativeReview?: boolean; role?: OutsideRole; nativeDispatched?: boolean }): string {
|
||||
const v = outsideVoiceFor(ctx);
|
||||
if (v.id === 'codex' && (opts.disabledBehavior === 'codex-only' || (opts.disabledBehavior === 'skip-all' && !opts.role))) {
|
||||
let preflight = outsideVoiceLabels(ctx, codexPreflight({ disabledBehavior: opts.disabledBehavior, nativeReview: opts.nativeReview, role: !!opts.role }))
|
||||
let preflight = outsideVoiceLabels(ctx, codexPreflight({ disabledBehavior: opts.disabledBehavior, nativeReview: opts.nativeReview, role: !!opts.role, nativeDispatched: opts.nativeDispatched }))
|
||||
.replace('```bash\n', `\`\`\`bash\n${runtimeRootPrelude(ctx)}\n`);
|
||||
if (['plan-eng-review', 'plan-ceo-review'].includes(ctx.skillName)) {
|
||||
preflight = preflight.replace("follow the workflow's native-review instructions below",
|
||||
@@ -82,7 +82,7 @@ ${readiness}
|
||||
|
||||
${ctx.skillName === 'ship' && opts.disabledBehavior === 'opt-in' ? `Ship attempts this optional design check when frontend review applies and \`codex_reviews\` allows it.
|
||||
Unset means the default, enabled; the first send prints a one-time notice.
|
||||
\`CODEX_MODE\` names the provider here, **${v.label}**.` : `The historical \`CODEX_MODE\` variable describes **${v.label}** availability here.`}${opts.disabledBehavior === 'opt-in' ? " `CODEX_MODE: disabled` or a send's `consent_missing` line: `codex_reviews` is off or unreadable; do not ask; record `outside_status: disabled`." : ''} ${opts.role ? 'The invocation checks auth and the [policy](https://github.com/garrytan/gstack/blob/main/docs/model-policy.md) plan-review model.' : 'Authentication and configured model validity are checked by the actual invocation, without overriding either.'} Missing/broken CLI: install or repair ${v.label}; authentication failure: run \`${v.id === 'codex' ? 'codex login' : 'claude auth login'}\`. ${opts.disabledBehavior === 'skip-all' ? "Disabled ends this entire extra review step (so does a send's `consent_missing` line), including the native fallback; record outside_status: disabled and continue after the section. Disabled is not an unavailable provider and never triggers a replacement reviewer." : opts.disabledBehavior === 'codex-only' ? "Disabled skips only the outside CLI (so does a send's `consent_missing` line); retain the native pass." : ctx.skillName === 'ship' ? '' : 'Otherwise honor this caller’s opt-in/skip choice.'} ${opts.disabledBehavior === 'skip-all' ? 'Provider failure is missing outside coverage; follow the caller’s existing fallback only when reviews are enabled.' : opts.disabledBehavior === 'codex-only' ? 'Non-ready means missing outside coverage. Keep the required native pass without duplicating it.' : 'Any non-ready outcome is missing outside coverage; follow the caller’s existing fallback.'} Never substitute another external provider.`;
|
||||
\`CODEX_MODE\` names the provider here, **${v.label}**.` : `The historical \`CODEX_MODE\` variable describes **${v.label}** availability here.`}${opts.disabledBehavior === 'opt-in' ? " `CODEX_MODE: disabled` or a send's `consent_missing` line: `codex_reviews` is off or unreadable; do not ask; record `outside_status: disabled`." : ''} ${opts.role ? 'The invocation checks auth and the [policy](https://github.com/garrytan/gstack/blob/main/docs/model-policy.md) plan-review model.' : 'Authentication and configured model validity are checked by the actual invocation, without overriding either.'} Missing/broken CLI: install or repair ${v.label}; authentication failure: run \`${v.id === 'codex' ? 'codex login' : 'claude auth login'}\`. ${opts.disabledBehavior === 'skip-all' ? "Disabled ends this entire extra review step (so does a send's `consent_missing` line), including the native fallback; record outside_status: disabled and continue after the section. Disabled is not an unavailable provider and never triggers a replacement reviewer." : opts.disabledBehavior === 'codex-only' ? `Disabled skips only the outside CLI (so does a send's \`consent_missing\` line)${opts.nativeDispatched ? '.' : '; retain the native pass.'}` : ctx.skillName === 'ship' ? '' : 'Otherwise honor this caller’s opt-in/skip choice.'} ${opts.disabledBehavior === 'skip-all' ? 'Provider failure is missing outside coverage; follow the caller’s existing fallback only when reviews are enabled.' : opts.disabledBehavior === 'codex-only' ? `Non-ready means missing outside coverage. ${opts.nativeDispatched ? 'The native pass follows its own DISPATCH line.' : 'Keep the required native pass without duplicating it.'}` : 'Any non-ready outcome is missing outside coverage; follow the caller’s existing fallback.'} Never substitute another external provider.`;
|
||||
}
|
||||
|
||||
export interface OutsideCommandOptions {
|
||||
@@ -97,7 +97,7 @@ export interface OutsideCommandOptions {
|
||||
reasoningEffort?: 'high' | 'medium';
|
||||
/** Creative proposals retain the recommendation gate with task-specific wording. */
|
||||
purpose?: 'design-direction';
|
||||
nativeAlreadyRequired?: boolean;
|
||||
nativeAlreadyRequired?: boolean | 'dispatched';
|
||||
/** Resolve the plan-review policy once in the invocation shell and bind it through probe and dispatch. */
|
||||
role?: OutsideRole;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ export function outsideVoiceInvocation(ctx: TemplateContext, requested: OutsideC
|
||||
${outsideVoiceCommand(ctx, opts)}
|
||||
\`\`\`
|
||||
|
||||
Use Bash \`timeout: ${gateMs}\`; show the full response in a \`tool-output\` fence. Require successful execution and valid markers. Refusal, empty/malformed output, missing ${planRecommendation ? 'Recommendation: <action> because <reason>' : opts.purpose === 'design-direction' ? 'Recommendation' : 'score/severity/completion'} markers, timeout or CLI failure means \`outside_status: unavailable\`. P0/P1 findings block like native ones; \`OUTSIDE_STATUS: unverified\` is missing coverage. ${opts.purpose === 'design-direction' ? 'Continue completed proposals; native completion does not count as outside coverage.' : opts.nativeAlreadyRequired ? 'Retain the required native pass without duplicating it; it cannot complete outside coverage.' : "Use the caller's fallback; missing coverage is never clean/PASS."} ${nativeStructured ? 'Scratch cleanup is automatic.' : 'After either outcome, delete only your private prompt; scratch cleanup is automatic.'}`;
|
||||
Use Bash \`timeout: ${gateMs}\`; show the full response in a \`tool-output\` fence. Require successful execution and valid markers. Refusal, empty/malformed output, missing ${planRecommendation ? 'Recommendation: <action> because <reason>' : opts.purpose === 'design-direction' ? 'Recommendation' : 'score/severity/completion'} markers, timeout or CLI failure means \`outside_status: unavailable\`. P0/P1 findings block like native ones; \`OUTSIDE_STATUS: unverified\` is missing coverage. ${opts.purpose === 'design-direction' ? 'Continue completed proposals; native completion does not count as outside coverage.' : opts.nativeAlreadyRequired === 'dispatched' ? 'A dispatched native pass runs once either way; outside output cannot complete it.' : opts.nativeAlreadyRequired ? 'Retain the required native pass without duplicating it; it cannot complete outside coverage.' : "Use the caller's fallback; missing coverage is never clean/PASS."} ${nativeStructured ? 'Scratch cleanup is automatic.' : 'After either outcome, delete only your private prompt; scratch cleanup is automatic.'}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+48
-52
@@ -204,14 +204,14 @@ A review's **start token** is the opaque value returned by `gstack-review-log --
|
||||
before it reads the diff. Keep `REVIEW_START` for Step 9, a separate `PASS_START` for
|
||||
each Step 11 attempt, and `DESIGN_START` for design. Finish each pass with its original
|
||||
token; `--finish` stamps the binding fields automatically. Never borrow or replace a token.
|
||||
`gstack-wtree` prints a Git tree hash covering tracked and non-ignored untracked files,
|
||||
not a commit ID. Use `git diff <old-tree> <new-tree>` to compare these snapshots.
|
||||
`gstack-wtree` prints a Git tree hash of tracked and non-ignored untracked files (not a commit);
|
||||
compare two with `git diff <old-tree> <new-tree>`.
|
||||
|
||||
**Review policy** (docs/review-policy.md): only a finding that would fail a test,
|
||||
break production, or lose data or secrets blocks a pass; the rest is a PR-body
|
||||
note. Step 9's plan sets both reviews' depth (`--depth-floor standard|full` only
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds,
|
||||
fix-checks included. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds under `frozen`
|
||||
(fix-checks included), else Step 9.4's third fix cycle. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
is the knob; the receipt's `review_loop` records the outcome.
|
||||
|
||||
### Ship control flow
|
||||
@@ -306,7 +306,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
|
||||
---
|
||||
|
||||
`<base>` means the detected branch name for fetch/helper arguments;
|
||||
`origin/<base>` is its remote-tracking ref for comparisons. Step 1 fetches it.
|
||||
`origin/<base>` is its remote-tracking ref for comparisons.
|
||||
|
||||
|
||||
|
||||
@@ -333,11 +333,12 @@ act on each `STOP:` and `NEXT:` line.
|
||||
restore access. `DIFF:` is the stat and commit count.
|
||||
|
||||
4. **Carry check.** An open PR prints `PR: #<n>` and its `gstack-ship-receipt carry --pr <n> --base <base> --dry-run` line.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review, fix
|
||||
what it broke (CHANGELOG, size caps), run `gstack-pregate --allow-repo-commands`, then carry
|
||||
without `--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and
|
||||
ends the run. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review and Step 14.5,
|
||||
fix what it broke (CHANGELOG, size caps), commit, `gstack-ship-release push --branch <branch-name>
|
||||
--early`, `gstack-ci-carry wait --base <base>`, run `gstack-pregate --allow-repo-commands`, then carry without
|
||||
`--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and ends
|
||||
the run with its `GSTACK_RESULT:` line. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16. Steps 17–21 then publish.
|
||||
|
||||
5. Display historical readiness using the dashboard below, then finish Step 1.
|
||||
Prior CLEAR reviews or dashboard skips never replace Step 9's gates.
|
||||
@@ -521,7 +522,8 @@ runs items 1 and 3–5; item commands serve only a `STOP:`, which names its reru
|
||||
(`--bump`, `--accept-incomplete`, `--version <v>`, `--keep-current`, `--answer`).
|
||||
|
||||
`VERSION: skipped` or `VERSION: <v> kept (…; no write)` ends Step 12 with
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch.
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch
|
||||
(`kept`: VERSION stays `<v>`).
|
||||
|
||||
1. **Classify state** — pure reader, never writes:
|
||||
```bash
|
||||
@@ -628,7 +630,7 @@ write failures are non-blocking.
|
||||
## Step 14.5: Documentation audit (every ship)
|
||||
|
||||
**Doc-sync invariant:** Every ship dispatches the /document-release subagent before final
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes.
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes, but not a Step 1 carry.
|
||||
No edits means an executed audit, not a skip; report the section's verified outcome.
|
||||
|
||||
> **STOP.** Before auditing docs before final commit/verification (Step 14.5), on every ship, Read `~/.claude/skills/gstack/ship/sections/documentation.md` and execute it
|
||||
@@ -653,17 +655,17 @@ Make bisectable commits; if already committed, continue to Step 16. Never create
|
||||
|
||||
**IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
|
||||
|
||||
Stages run in order; 1–4's other commands are `STOP:` recoveries. Content
|
||||
changes during or after verification restart at stage 1 and complete all five
|
||||
stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
`finish` runs stages 1–4 in order; act on each `STOP:` by its recovery below, then rerun
|
||||
it. Content changes during or after verification restart at
|
||||
stage 1 and complete all five stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
|
||||
**One call for stages 1–4:** `~/.claude/skills/gstack/bin/gstack-ship-release finish --base <base> --reviewed-tree <tree> --reviewed-base <mb> --docs-post <audit-id>-post.json --lane <label>=<Step 5 command>... [--build <cmd>]... --trailer '<trailer>'`
|
||||
makes Step 15's item-3 commit, runs stages 1–4 and the pregate; each `STOP:` is a recovery
|
||||
below (`--docs-rechecked`, `--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
also makes Step 15's item-3 commit and runs the pregate (`--docs-rechecked`,
|
||||
`--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
|
||||
### 1. Finish writers and prepare outputs
|
||||
|
||||
Inspect writer handles, including the docs child. Confirm terminal completion or
|
||||
Before `finish`, inspect writer handles, including the docs child. Confirm completion or
|
||||
termination before another writer runs; timeout or cancellation acknowledgment
|
||||
alone means STOP until confirmed.
|
||||
|
||||
@@ -672,30 +674,28 @@ files and CI. Pass each to `finish` as `--build`. If none exists, record not app
|
||||
the inspected sources. A missing prerequisite or failed build stops shipping:
|
||||
report **Build failed or prerequisite missing**, with the command, error and needed
|
||||
repair. Never invent a substitute command.
|
||||
**If blocked:** Repair it, then repeat stage 1. After it passes, continue
|
||||
to stage 2; treat any content repair as a behavioral change there.
|
||||
**If blocked:** repair it, repeat stage 1, then continue to stage 2: a content repair is behavior there.
|
||||
|
||||
### 2. Choose the change route
|
||||
|
||||
Capture the current tree with `~/.claude/skills/gstack/bin/gstack-wtree`. Inspect
|
||||
`git diff <reviewed-tree> <current-tree>` against the snapshot saved before Step 12.
|
||||
Missing snapshots block this comparison, regardless of HEAD equality.
|
||||
`finish` runs `git diff <reviewed-tree> <current-tree>` (`--reviewed-tree`, saved before Step 12,
|
||||
against `~/.claude/skills/gstack/bin/gstack-wtree`) and prints `ROUTE:`. No saved tree: pass `review_binding.end_wtree` from Step 11.5's bound Step 9 record;
|
||||
with none, insert `9 → 10 → 11 → 11.5`.
|
||||
|
||||
Classify the comparison in this order:
|
||||
Its `STOP:` names the route:
|
||||
|
||||
1. **Behavior, tests or build inputs changed:** Prompts/templates count as behavior.
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17, then stop this step.
|
||||
This repair excludes Step 14.5 because the rebuild can change generated docs.
|
||||
Step 16 restarts at stage 1: rebuild and compare again before stage 3 decides
|
||||
documentation freshness. Further repairs use the same work list. A STOP naming a scoped-review packet
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17. It excludes Step 14.5 (a rebuild
|
||||
can change generated docs; compare before stage 3) and Step 15 (`finish` STOPs on an uncommitted
|
||||
non-release file: commit it by Step 15's rules, then rerun). A STOP naming a scoped-review packet
|
||||
instead takes its fix-check and `--context-reviewed` rerun; a blocking finding is this item.
|
||||
2. **Only authored docs or release metadata changed:** Keep Step 8's original child
|
||||
report and counts. Recheck affected plan items using their recorded verification
|
||||
and append current evidence to the invocation record. If a classification is no
|
||||
longer supported, run Step 8's audit and decision gates only, then return to
|
||||
Step 16 stage 1. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** Continue to stage 3
|
||||
without a new code review.
|
||||
Step 16 stage 1; else rerun with `--docs-rechecked`. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** `finish` continues to
|
||||
stage 3 without a new code review.
|
||||
|
||||
### 3. Resolve documentation freshness
|
||||
|
||||
@@ -727,33 +727,29 @@ Never run a third audit. Child return is not acceptance.
|
||||
Freeze inputs through verification and push. Run declared docs/link/generated-file
|
||||
checks; report any that are unavailable.
|
||||
|
||||
**Reuse a check when its inputs match.** Compare hashes or complete bytes of its
|
||||
saved and current consumed files, fixtures, dependencies and execution parameters.
|
||||
Changed or unknown dependencies require a rerun. For model judges, compare the complete
|
||||
expanded request, rubric, parameters and builder/runtime dependencies. Cite the original
|
||||
command, result/counts, timestamp and log, never resample. Mandatory reviews still run.
|
||||
**Reuse a check when its inputs match.** Same consumed files, fixtures, dependencies
|
||||
and parameters (for a model judge, the complete expanded request and rubric); unknown means
|
||||
rerun. Cite the original command, result, timestamp and log; never resample. Mandatory reviews still run.
|
||||
|
||||
**Check each test lane's receipt as well.** Use its actual Step 5 label/command:
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`. Inspect changes since the run;
|
||||
`--allow-paths` exempts only release metadata. A `package.json` version-only edit
|
||||
can qualify; scripts, dependencies and runtime configuration require live tests.
|
||||
Uncertain edits cannot be exempted. Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review; a Step 14 TODOS.md edit reruns them. Use this example only once
|
||||
every allowed edit is release metadata:
|
||||
**Check each test lane's receipt as well.** `finish` checks every `--lane` as
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`, like this example:
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-evidence check --label tests --expect-cmd '<tests>' --label vitest --expect-cmd '<vitest>' --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json,agents-digest/gstack-AGENTS.md
|
||||
```
|
||||
|
||||
`--allow-paths` exempts only release metadata (in `package.json`, only a version edit). Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review.
|
||||
|
||||
| Receipt result | Next action |
|
||||
|---|---|
|
||||
| FRESH (exit 0) | Cite the label, exit, timestamp, log and `tests_ran`. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.claude/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once. Handle failures as described below. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.claude/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once (`finish` does; a CI-mapped lane is carried, else `EVIDENCE: DEFERRED`). Still not FRESH: a failed lane. |
|
||||
| ZERO-RUN: the receipt's `tests_ran` is 0 | STALE-equivalent: use Step 5's ZERO-RUN triage (a failed lane), never FRESH, even with exit 0. |
|
||||
| `tests_ran: unknown` | Non-blocking: keep the exit-0 verdict, cite the lane as `count unavailable`. Never record it as ZERO-RUN or as a counted pass. |
|
||||
| Only receipt storage/readback failed | Prove unchanged final content, the same command and valid age from the successful run's evidence. Cite its exact command, exit, timestamp and log as **ledger unavailable**, never FRESH. Without that proof, use STALE/MISSING. |
|
||||
|
||||
No test lanes: require Step 5's explicit untested-scope approval for final content,
|
||||
No test lanes: rerun with `--no-lanes-approved` on Step 5's explicit untested-scope approval,
|
||||
or run Steps 5–15, including the no-tests decision, then return to Step 16 stage 1.
|
||||
Report the gap, never FRESH; builds must pass.
|
||||
|
||||
@@ -765,7 +761,8 @@ does not authorize a third attempt.
|
||||
### 5. Report, then push
|
||||
|
||||
`finish` made the release commit. Commit only verified outputs stage 1's
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit.
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit. It is
|
||||
content-preserving: no restart.
|
||||
Preserve unrelated user files.
|
||||
|
||||
Paste build/docs/test results. Reuse waivers only for the same verified
|
||||
@@ -780,7 +777,7 @@ its records:
|
||||
- Each test lane's `tests_ran` (N, ZERO-RUN or `count unavailable`).
|
||||
Write this report in the auditor's posture: this session's own gate edits are
|
||||
evidence for the reader to examine, not positions to defend; a kept gate
|
||||
states its reason and nothing more. Otherwise continue to Step 17.
|
||||
states its reason and nothing more. Then continue to Step 17.
|
||||
|
||||
---
|
||||
|
||||
@@ -881,7 +878,8 @@ It checks the branch, the offer, the gate above (`--gate-open <n>`; `--gate-open
|
||||
even with unchanged content before returning to Step 17. Never bypass failed guards.
|
||||
Never force-push. Only a successful push or verified `ALREADY_PUSHED` proceeds.
|
||||
|
||||
Continue to Step 18. No documentation writer runs after push.
|
||||
After `EVIDENCE: DEFERRED`, run Step 5's `gstack-ship-release accept`; a `STOP:` there
|
||||
is a failed lane (stage 4). Continue to Step 18. No documentation writer runs after push.
|
||||
|
||||
---
|
||||
|
||||
@@ -909,8 +907,7 @@ echoed): an open PR at HEAD takes pr-body's existing-PR path (body and title onl
|
||||
|
||||
## Step 20: Persist ship metrics
|
||||
|
||||
Log metrics for `/retro` through `gstack-review-log`; it handles project/branch paths,
|
||||
JSON validation, storage and sync and takes **no path argument**.
|
||||
Log metrics for `/retro` through `gstack-review-log`; it takes **no path argument**.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"ship","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","coverage_pct":COVERAGE_PCT,"coverage_schema":2,"coverage_pct_value":COVERAGE_PCT_VALUE,"weak_gaps":WEAK_GAPS,"tests_extended":TESTS_EXTENDED,"tests_rejected":TESTS_REJECTED,"regression_proof":REGRESSION_PROOF,"plan_items_total":PLAN_TOTAL,"plan_items_done":PLAN_DONE,"verification_result":"VERIFY_RESULT","version":"VERSION","branch":"'"$(git rev-parse --abbrev-ref HEAD)"'"}'
|
||||
@@ -957,7 +954,7 @@ The last line printed is the result line a parent greps (docs/unattended.md):
|
||||
|
||||
It binds the receipt to HEAD, writes the run record, prints `GSTACK_RESULT: skill=ship
|
||||
status=complete head=<sha> run=<dir>`; `QUEUE_RECEIPT_STALE`: HEAD moved past the receipt (rewrite,
|
||||
repost, rerun). A run that STOPs early ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
repost, rerun). A STOP before Step 19 publishes ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
|
||||
---
|
||||
|
||||
@@ -973,7 +970,6 @@ hand-roll VERSION/package.json writes.
|
||||
|
||||
Follow the numbered gates and their explicit exceptions.
|
||||
|
||||
- **Never force push.** Use regular `git push` only.
|
||||
- **An early Greptile PR stays up.** A stop after Step 6.5 opened it leaves the draft
|
||||
open with one comment saying why (greptile-early section); never close it.
|
||||
- **Use the configured version file's format** (4-digit for VERSION); under NO_VERSION,
|
||||
|
||||
+48
-52
@@ -70,14 +70,14 @@ A review's **start token** is the opaque value returned by `gstack-review-log --
|
||||
before it reads the diff. Keep `REVIEW_START` for Step 9, a separate `PASS_START` for
|
||||
each Step 11 attempt, and `DESIGN_START` for design. Finish each pass with its original
|
||||
token; `--finish` stamps the binding fields automatically. Never borrow or replace a token.
|
||||
`gstack-wtree` prints a Git tree hash covering tracked and non-ignored untracked files,
|
||||
not a commit ID. Use `git diff <old-tree> <new-tree>` to compare these snapshots.
|
||||
`gstack-wtree` prints a Git tree hash of tracked and non-ignored untracked files (not a commit);
|
||||
compare two with `git diff <old-tree> <new-tree>`.
|
||||
|
||||
**Review policy** (docs/review-policy.md): only a finding that would fail a test,
|
||||
break production, or lose data or secrets blocks a pass; the rest is a PR-body
|
||||
note. Step 9's plan sets both reviews' depth (`--depth-floor standard|full` only
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds,
|
||||
fix-checks included. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds under `frozen`
|
||||
(fix-checks included), else Step 9.4's third fix cycle. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
is the knob; the receipt's `review_loop` records the outcome.
|
||||
|
||||
### Ship control flow
|
||||
@@ -112,7 +112,7 @@ Permitted repairs continue in this invocation without restarting /ship.
|
||||
{{BASE_BRANCH_DETECT}}
|
||||
|
||||
`<base>` means the detected branch name for fetch/helper arguments;
|
||||
`origin/<base>` is its remote-tracking ref for comparisons. Step 1 fetches it.
|
||||
`origin/<base>` is its remote-tracking ref for comparisons.
|
||||
|
||||
{{GBRAIN_CONTEXT_LOAD}}
|
||||
|
||||
@@ -139,11 +139,12 @@ act on each `STOP:` and `NEXT:` line.
|
||||
restore access. `DIFF:` is the stat and commit count.
|
||||
|
||||
4. **Carry check.** An open PR prints `PR: #<n>` and its `gstack-ship-receipt carry --pr <n> --base <base> --dry-run` line.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review, fix
|
||||
what it broke (CHANGELOG, size caps), run `gstack-pregate --allow-repo-commands`, then carry
|
||||
without `--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and
|
||||
ends the run. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review and Step 14.5,
|
||||
fix what it broke (CHANGELOG, size caps), commit, `gstack-ship-release push --branch <branch-name>
|
||||
--early`, `gstack-ci-carry wait --base <base>`, run `gstack-pregate --allow-repo-commands`, then carry without
|
||||
`--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and ends
|
||||
the run with its `GSTACK_RESULT:` line. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16. Steps 17–21 then publish.
|
||||
|
||||
5. Display historical readiness using the dashboard below, then finish Step 1.
|
||||
Prior CLEAR reviews or dashboard skips never replace Step 9's gates.
|
||||
@@ -244,7 +245,8 @@ runs items 1 and 3–5; item commands serve only a `STOP:`, which names its reru
|
||||
(`--bump`, `--accept-incomplete`, `--version <v>`, `--keep-current`, `--answer`).
|
||||
|
||||
`VERSION: skipped` or `VERSION: <v> kept (…; no write)` ends Step 12 with
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch.
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch
|
||||
(`kept`: VERSION stays `<v>`).
|
||||
|
||||
1. **Classify state** — pure reader, never writes:
|
||||
```bash
|
||||
@@ -350,7 +352,7 @@ write failures are non-blocking.
|
||||
## Step 14.5: Documentation audit (every ship)
|
||||
|
||||
**Doc-sync invariant:** Every ship dispatches the /document-release subagent before final
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes.
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes, but not a Step 1 carry.
|
||||
No edits means an executed audit, not a skip; report the section's verified outcome.
|
||||
|
||||
{{SECTION:documentation}}
|
||||
@@ -374,17 +376,17 @@ Make bisectable commits; if already committed, continue to Step 16. Never create
|
||||
|
||||
**IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
|
||||
|
||||
Stages run in order; 1–4's other commands are `STOP:` recoveries. Content
|
||||
changes during or after verification restart at stage 1 and complete all five
|
||||
stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
`finish` runs stages 1–4 in order; act on each `STOP:` by its recovery below, then rerun
|
||||
it. Content changes during or after verification restart at
|
||||
stage 1 and complete all five stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
|
||||
**One call for stages 1–4:** `~/.claude/skills/gstack/bin/gstack-ship-release finish --base <base> --reviewed-tree <tree> --reviewed-base <mb> --docs-post <audit-id>-post.json --lane <label>=<Step 5 command>... [--build <cmd>]... --trailer '<trailer>'`
|
||||
makes Step 15's item-3 commit, runs stages 1–4 and the pregate; each `STOP:` is a recovery
|
||||
below (`--docs-rechecked`, `--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
also makes Step 15's item-3 commit and runs the pregate (`--docs-rechecked`,
|
||||
`--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
|
||||
### 1. Finish writers and prepare outputs
|
||||
|
||||
Inspect writer handles, including the docs child. Confirm terminal completion or
|
||||
Before `finish`, inspect writer handles, including the docs child. Confirm completion or
|
||||
termination before another writer runs; timeout or cancellation acknowledgment
|
||||
alone means STOP until confirmed.
|
||||
|
||||
@@ -393,30 +395,28 @@ files and CI. Pass each to `finish` as `--build`. If none exists, record not app
|
||||
the inspected sources. A missing prerequisite or failed build stops shipping:
|
||||
report **Build failed or prerequisite missing**, with the command, error and needed
|
||||
repair. Never invent a substitute command.
|
||||
**If blocked:** Repair it, then repeat stage 1. After it passes, continue
|
||||
to stage 2; treat any content repair as a behavioral change there.
|
||||
**If blocked:** repair it, repeat stage 1, then continue to stage 2: a content repair is behavior there.
|
||||
|
||||
### 2. Choose the change route
|
||||
|
||||
Capture the current tree with `~/.claude/skills/gstack/bin/gstack-wtree`. Inspect
|
||||
`git diff <reviewed-tree> <current-tree>` against the snapshot saved before Step 12.
|
||||
Missing snapshots block this comparison, regardless of HEAD equality.
|
||||
`finish` runs `git diff <reviewed-tree> <current-tree>` (`--reviewed-tree`, saved before Step 12,
|
||||
against `~/.claude/skills/gstack/bin/gstack-wtree`) and prints `ROUTE:`. No saved tree: pass `review_binding.end_wtree` from Step 11.5's bound Step 9 record;
|
||||
with none, insert `9 → 10 → 11 → 11.5`.
|
||||
|
||||
Classify the comparison in this order:
|
||||
Its `STOP:` names the route:
|
||||
|
||||
1. **Behavior, tests or build inputs changed:** Prompts/templates count as behavior.
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17, then stop this step.
|
||||
This repair excludes Step 14.5 because the rebuild can change generated docs.
|
||||
Step 16 restarts at stage 1: rebuild and compare again before stage 3 decides
|
||||
documentation freshness. Further repairs use the same work list. A STOP naming a scoped-review packet
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17. It excludes Step 14.5 (a rebuild
|
||||
can change generated docs; compare before stage 3) and Step 15 (`finish` STOPs on an uncommitted
|
||||
non-release file: commit it by Step 15's rules, then rerun). A STOP naming a scoped-review packet
|
||||
instead takes its fix-check and `--context-reviewed` rerun; a blocking finding is this item.
|
||||
2. **Only authored docs or release metadata changed:** Keep Step 8's original child
|
||||
report and counts. Recheck affected plan items using their recorded verification
|
||||
and append current evidence to the invocation record. If a classification is no
|
||||
longer supported, run Step 8's audit and decision gates only, then return to
|
||||
Step 16 stage 1. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** Continue to stage 3
|
||||
without a new code review.
|
||||
Step 16 stage 1; else rerun with `--docs-rechecked`. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** `finish` continues to
|
||||
stage 3 without a new code review.
|
||||
|
||||
### 3. Resolve documentation freshness
|
||||
|
||||
@@ -448,33 +448,29 @@ Never run a third audit. Child return is not acceptance.
|
||||
Freeze inputs through verification and push. Run declared docs/link/generated-file
|
||||
checks; report any that are unavailable.
|
||||
|
||||
**Reuse a check when its inputs match.** Compare hashes or complete bytes of its
|
||||
saved and current consumed files, fixtures, dependencies and execution parameters.
|
||||
Changed or unknown dependencies require a rerun. For model judges, compare the complete
|
||||
expanded request, rubric, parameters and builder/runtime dependencies. Cite the original
|
||||
command, result/counts, timestamp and log, never resample. Mandatory reviews still run.
|
||||
**Reuse a check when its inputs match.** Same consumed files, fixtures, dependencies
|
||||
and parameters (for a model judge, the complete expanded request and rubric); unknown means
|
||||
rerun. Cite the original command, result, timestamp and log; never resample. Mandatory reviews still run.
|
||||
|
||||
**Check each test lane's receipt as well.** Use its actual Step 5 label/command:
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`. Inspect changes since the run;
|
||||
`--allow-paths` exempts only release metadata. A `package.json` version-only edit
|
||||
can qualify; scripts, dependencies and runtime configuration require live tests.
|
||||
Uncertain edits cannot be exempted. Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review; a Step 14 TODOS.md edit reruns them. Use this example only once
|
||||
every allowed edit is release metadata:
|
||||
**Check each test lane's receipt as well.** `finish` checks every `--lane` as
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`, like this example:
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-evidence check --label tests --expect-cmd '<tests>' --label vitest --expect-cmd '<vitest>' --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json,agents-digest/gstack-AGENTS.md
|
||||
```
|
||||
|
||||
`--allow-paths` exempts only release metadata (in `package.json`, only a version edit). Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review.
|
||||
|
||||
| Receipt result | Next action |
|
||||
|---|---|
|
||||
| FRESH (exit 0) | Cite the label, exit, timestamp, log and `tests_ran`. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.claude/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once. Handle failures as described below. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.claude/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once (`finish` does; a CI-mapped lane is carried, else `EVIDENCE: DEFERRED`). Still not FRESH: a failed lane. |
|
||||
| ZERO-RUN: the receipt's `tests_ran` is 0 | STALE-equivalent: use Step 5's ZERO-RUN triage (a failed lane), never FRESH, even with exit 0. |
|
||||
| `tests_ran: unknown` | Non-blocking: keep the exit-0 verdict, cite the lane as `count unavailable`. Never record it as ZERO-RUN or as a counted pass. |
|
||||
| Only receipt storage/readback failed | Prove unchanged final content, the same command and valid age from the successful run's evidence. Cite its exact command, exit, timestamp and log as **ledger unavailable**, never FRESH. Without that proof, use STALE/MISSING. |
|
||||
|
||||
No test lanes: require Step 5's explicit untested-scope approval for final content,
|
||||
No test lanes: rerun with `--no-lanes-approved` on Step 5's explicit untested-scope approval,
|
||||
or run Steps 5–15, including the no-tests decision, then return to Step 16 stage 1.
|
||||
Report the gap, never FRESH; builds must pass.
|
||||
|
||||
@@ -486,7 +482,8 @@ does not authorize a third attempt.
|
||||
### 5. Report, then push
|
||||
|
||||
`finish` made the release commit. Commit only verified outputs stage 1's
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit.
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit. It is
|
||||
content-preserving: no restart.
|
||||
Preserve unrelated user files.
|
||||
|
||||
Paste build/docs/test results. Reuse waivers only for the same verified
|
||||
@@ -501,7 +498,7 @@ its records:
|
||||
- Each test lane's `tests_ran` (N, ZERO-RUN or `count unavailable`).
|
||||
Write this report in the auditor's posture: this session's own gate edits are
|
||||
evidence for the reader to examine, not positions to defend; a kept gate
|
||||
states its reason and nothing more. Otherwise continue to Step 17.
|
||||
states its reason and nothing more. Then continue to Step 17.
|
||||
|
||||
---
|
||||
|
||||
@@ -602,7 +599,8 @@ It checks the branch, the offer, the gate above (`--gate-open <n>`; `--gate-open
|
||||
even with unchanged content before returning to Step 17. Never bypass failed guards.
|
||||
Never force-push. Only a successful push or verified `ALREADY_PUSHED` proceeds.
|
||||
|
||||
Continue to Step 18. No documentation writer runs after push.
|
||||
After `EVIDENCE: DEFERRED`, run Step 5's `gstack-ship-release accept`; a `STOP:` there
|
||||
is a failed lane (stage 4). Continue to Step 18. No documentation writer runs after push.
|
||||
|
||||
---
|
||||
|
||||
@@ -628,8 +626,7 @@ echoed): an open PR at HEAD takes pr-body's existing-PR path (body and title onl
|
||||
|
||||
## Step 20: Persist ship metrics
|
||||
|
||||
Log metrics for `/retro` through `gstack-review-log`; it handles project/branch paths,
|
||||
JSON validation, storage and sync and takes **no path argument**.
|
||||
Log metrics for `/retro` through `gstack-review-log`; it takes **no path argument**.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"ship","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","coverage_pct":COVERAGE_PCT,"coverage_schema":2,"coverage_pct_value":COVERAGE_PCT_VALUE,"weak_gaps":WEAK_GAPS,"tests_extended":TESTS_EXTENDED,"tests_rejected":TESTS_REJECTED,"regression_proof":REGRESSION_PROOF,"plan_items_total":PLAN_TOTAL,"plan_items_done":PLAN_DONE,"verification_result":"VERIFY_RESULT","version":"VERSION","branch":"'"$(git rev-parse --abbrev-ref HEAD)"'"}'
|
||||
@@ -676,7 +673,7 @@ The last line printed is the result line a parent greps (docs/unattended.md):
|
||||
|
||||
It binds the receipt to HEAD, writes the run record, prints `GSTACK_RESULT: skill=ship
|
||||
status=complete head=<sha> run=<dir>`; `QUEUE_RECEIPT_STALE`: HEAD moved past the receipt (rewrite,
|
||||
repost, rerun). A run that STOPs early ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
repost, rerun). A STOP before Step 19 publishes ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
|
||||
---
|
||||
|
||||
@@ -692,7 +689,6 @@ hand-roll VERSION/package.json writes.
|
||||
|
||||
Follow the numbered gates and their explicit exceptions.
|
||||
|
||||
- **Never force push.** Use regular `git push` only.
|
||||
- **An early Greptile PR stays up.** A stop after Step 6.5 opened it leaves the draft
|
||||
open with one comment saying why (greptile-early section); never close it.
|
||||
- **Use the configured version file's format** (4-digit for VERSION); under NO_VERSION,
|
||||
|
||||
@@ -11,7 +11,8 @@ reserve the planned voices as one batch (`gstack-ship-budget check --next dispat
|
||||
and add `--reservation <id>` to the `--start adversarial-review` call below.
|
||||
After `NEXT: voices` (gate class: Step 11 before any stop), Finish the adversarial phase takes neither
|
||||
decision 2 nor 3: rerun Step 9's repeat decision with `--adversarial-ran` (a queued blocking finding as
|
||||
`--blocking-open`); its `NEXT:` (the stop, or the owner's granted fix-check) stands.
|
||||
`--blocking-open`); its `NEXT:` stands: only `stop` (Step 9.4's decision 2)
|
||||
or a granted fix-check (item 3.5, then Step 11.5) follows voices.
|
||||
|
||||
## Step 11: Adversarial review
|
||||
|
||||
@@ -73,21 +74,21 @@ echo "CODEX_MODE: $_CODEX_MODE"
|
||||
```
|
||||
|
||||
Branch on the echoed `CODEX_MODE`:
|
||||
- **`disabled`** (or a send's `consent_missing` line) — `codex_reviews` is off or unreadable. Skip the Codex passes only; the Claude adversarial subagent below STILL runs (it is free and fast). Print: "Codex passes skipped (codex_reviews disabled) — running Claude adversarial only."
|
||||
- **`helper_unavailable`** — the probe is missing or not executable; relay the line above (cause and fix). Keep the required Claude adversarial pass; do not dispatch a duplicate.
|
||||
- **`not_installed`** — Codex CLI absent. Print: "Codex not installed; outside coverage unavailable. Install: `npm install -g @openai/codex`." Keep the required Claude adversarial pass; do not dispatch a duplicate.
|
||||
- **`disabled`** (or a send's `consent_missing` line) — `codex_reviews` is off or unreadable. Skip the Codex passes only; the Claude adversarial subagent below still follows its DISPATCH line. Print: "Codex passes skipped (codex_reviews disabled)."
|
||||
- **`helper_unavailable`** — the probe is missing or not executable; relay the line above (cause and fix). The Claude adversarial pass follows its own DISPATCH line.
|
||||
- **`not_installed`** — Codex CLI absent. Print: "Codex not installed; outside coverage unavailable. Install: `npm install -g @openai/codex`." The Claude adversarial pass follows its own DISPATCH line.
|
||||
- **`under_codex`** — stale artifact selected its own harness. Print: "Codex outside review unavailable: harness mismatch; no outside process started. Missing coverage. Repair: setup --host codex." Skip the outside invocation and follow the workflow's native-review instructions below. Conflicting inherited harness markers are not grounds to guess another provider.
|
||||
- **`not_authed`** — installed but no credentials. Print: "Codex not authenticated; outside coverage unavailable. Run `codex login` or set `$CODEX_API_KEY`." Keep the required Claude adversarial pass; do not dispatch a duplicate.
|
||||
- **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines. Keep the required Claude adversarial pass; do not dispatch a duplicate.
|
||||
- **`model_unusable`** — the selected model (see `CODEX_MODEL:`) is invalid or unavailable to the account (HTTP 400 on every call). Relay the probe's HINT lines and the fix (`GSTACK_CODEX_MODEL=<supported-model>` or config.toml `model`); never substitute a model. Keep the required Claude adversarial pass; do not dispatch a duplicate. The ~10s round trip is cached for 1h.
|
||||
- **`quota_exhausted`** — Codex usage limit: relay the probe's lines verbatim (reset time, retry); no more Codex calls this run. Keep the required Claude adversarial pass; do not dispatch a duplicate.
|
||||
- **`sandbox_unavailable`** — Codex's sandbox cannot start here (containers without user namespaces); the probe printed the reason and fix. No paid call ran; outside coverage is unavailable. Keep the required Claude adversarial pass; do not dispatch a duplicate.
|
||||
- **`not_authed`** — installed but no credentials. Print: "Codex not authenticated; outside coverage unavailable. Run `codex login` or set `$CODEX_API_KEY`." The Claude adversarial pass follows its own DISPATCH line.
|
||||
- **`broken_install`** — the CLI is on PATH but cannot execute (spawn ENOENT, non-executable binary, missing vendor payload). Print: "Codex is installed but its binary cannot run — Codex passes skipped. Reinstall: `npm install -g @openai/codex`." Relay the probe's HINT lines. The Claude adversarial pass follows its own DISPATCH line.
|
||||
- **`model_unusable`** — the selected model (see `CODEX_MODEL:`) is invalid or unavailable to the account (HTTP 400 on every call). Relay the probe's HINT lines and the fix (`GSTACK_CODEX_MODEL=<supported-model>` or config.toml `model`); never substitute a model. The Claude adversarial pass follows its own DISPATCH line. The ~10s round trip is cached for 1h.
|
||||
- **`quota_exhausted`** — Codex usage limit: relay the probe's lines verbatim (reset time, retry); no more Codex calls this run. The Claude adversarial pass follows its own DISPATCH line.
|
||||
- **`sandbox_unavailable`** — Codex's sandbox cannot start here (containers without user namespaces); the probe printed the reason and fix. No paid call ran; outside coverage is unavailable. The Claude adversarial pass follows its own DISPATCH line.
|
||||
- **`ready`** or **`unverified`** — run the Codex pass below. `unverified` means the model check timed out or, with `(rate_limited)`, hit a 429; say so, and let the pass's own verdict decide.
|
||||
|
||||
`CODEX_MODE: disabled` means skip the Codex passes ONLY.
|
||||
`ready` and `unverified` run them; every other mode skips them with the printed reason.
|
||||
`ready` and `unverified` run them on `DISPATCH: outside-voice`; every other mode skips them with the printed reason.
|
||||
|
||||
**User override:** If the user explicitly requested "full review", "structured review", or "P1 gate", also run the Codex structured review regardless of diff size (still requires `CODEX_MODE: ready` (or `unverified`)).
|
||||
**User override:** If the user explicitly requested "full review", "structured review", or "P1 gate", also run the Codex structured review regardless of diff size (still requires `DISPATCH: outside-voice` and `CODEX_MODE: ready` (or `unverified`)).
|
||||
|
||||
---
|
||||
|
||||
@@ -116,9 +117,9 @@ If the subagent fails or times out, record native coverage as incomplete. Contin
|
||||
|
||||
---
|
||||
|
||||
### Codex adversarial challenge (runs whenever `CODEX_MODE` is `ready` or `unverified`)
|
||||
### Codex adversarial challenge (on `DISPATCH: outside-voice`, when `CODEX_MODE` is `ready` or `unverified`)
|
||||
|
||||
If `CODEX_MODE` is `ready` or `unverified`:
|
||||
On `DISPATCH: outside-voice`, if `CODEX_MODE` is `ready` or `unverified`:
|
||||
|
||||
Outside prompt (supply repository context from the parent):
|
||||
|
||||
@@ -165,7 +166,7 @@ esac
|
||||
echo 'OUTSIDE_STATUS: completed provider=codex host=claude'
|
||||
```
|
||||
|
||||
Use Bash `timeout: 600000`; show the full response in a `tool-output` fence. Require successful execution and valid markers. Refusal, empty/malformed output, missing score/severity/completion markers, timeout or CLI failure means `outside_status: unavailable`. P0/P1 findings block like native ones; `OUTSIDE_STATUS: unverified` is missing coverage. Retain the required native pass without duplicating it; it cannot complete outside coverage. After either outcome, delete only your private prompt; scratch cleanup is automatic.
|
||||
Use Bash `timeout: 600000`; show the full response in a `tool-output` fence. Require successful execution and valid markers. Refusal, empty/malformed output, missing score/severity/completion markers, timeout or CLI failure means `outside_status: unavailable`. P0/P1 findings block like native ones; `OUTSIDE_STATUS: unverified` is missing coverage. A dispatched native pass runs once either way; outside output cannot complete it. After either outcome, delete only your private prompt; scratch cleanup is automatic.
|
||||
|
||||
Present the full output verbatim. A Critical, High or `Blocks: yes` finding is CRITICAL; `Blocks: no` never lowers one, and only a named policy ground drops it. An unavailable outside challenge does not block shipping by itself; supported findings still enter Step 11, and the structured P0/P1 and non-convergence gates still apply.
|
||||
|
||||
@@ -176,13 +177,13 @@ Present the full output verbatim. A Critical, High or `Blocks: yes` finding is C
|
||||
|
||||
|
||||
|
||||
For other modes, retain the native pass above; do not dispatch it again.
|
||||
Other modes skip it; the native pass follows its own DISPATCH line.
|
||||
|
||||
---
|
||||
|
||||
### Codex structured review (large diffs only, 200+ lines)
|
||||
### Codex structured review (on `DISPATCH: outside-voice`, 200+ lines)
|
||||
|
||||
If `CODEX_MODE` is `ready` or `unverified` and either `DIFF_TOTAL >= 200` or the user requested the override above:
|
||||
On `DISPATCH: outside-voice`, if `CODEX_MODE` is `ready` or `unverified` and either `DIFF_TOTAL >= 200` or the user requested the override above:
|
||||
|
||||
Prepare a structured review prompt requesting severity-tagged findings ([P0]-[P3]) or an explicit NO_FINDINGS conclusion. Preserve the base-branch scope including committed changes and working-tree changes.
|
||||
|
||||
@@ -227,7 +228,7 @@ esac
|
||||
echo 'OUTSIDE_STATUS: completed provider=codex host=claude'
|
||||
```
|
||||
|
||||
Use Bash `timeout: 600000`; show the full response in a `tool-output` fence. Require successful execution and valid markers. Refusal, empty/malformed output, missing score/severity/completion markers, timeout or CLI failure means `outside_status: unavailable`. P0/P1 findings block like native ones; `OUTSIDE_STATUS: unverified` is missing coverage. Retain the required native pass without duplicating it; it cannot complete outside coverage. Scratch cleanup is automatic.
|
||||
Use Bash `timeout: 600000`; show the full response in a `tool-output` fence. Require successful execution and valid markers. Refusal, empty/malformed output, missing score/severity/completion markers, timeout or CLI failure means `outside_status: unavailable`. P0/P1 findings block like native ones; `OUTSIDE_STATUS: unverified` is missing coverage. A dispatched native pass runs once either way; outside output cannot complete it. Scratch cleanup is automatic.
|
||||
|
||||
The Codex backend uses `codex review --base` without a positional prompt: those arguments are mutually exclusive. Never drop --base to resolve an argv error; prompt-only review changes the diff scope.
|
||||
|
||||
@@ -249,7 +250,7 @@ Read stderr for errors (same error handling as Codex adversarial above).
|
||||
|
||||
|
||||
|
||||
If `DIFF_TOTAL < 200` without that override, skip structured review; the adversarial passes still run.
|
||||
If `DIFF_TOTAL < 200` without that override, skip structured review; the dispatched adversarial passes still run.
|
||||
|
||||
---
|
||||
|
||||
@@ -323,7 +324,7 @@ in order before leaving Step 11:
|
||||
Otherwise insert Steps 9, 10 and 11 before the pending Step 11.5 in the work list.
|
||||
Step 9 completes full review before fixes; any further repair inserts its checks
|
||||
ahead of the remaining items. These fresh reviews after code edits are not recovery retries.
|
||||
Returning here never resets Step 9's three-cycle fix limit.
|
||||
Returning here never resets Step 9's three-cycle fix limit (under `frozen`, the plan's cap).
|
||||
3. **Native complete with no queued fixes, or not dispatched:** Finish the memory updates below,
|
||||
then continue to Step 11.5. Never jump directly to release preparation.
|
||||
|
||||
@@ -361,14 +362,13 @@ already knows. A good test: would this insight save time in a future session? If
|
||||
Step 8 used broad release terms. Before VERSION/CHANGELOG, search for versioning
|
||||
or changelog pitfalls tied to this branch's headline feature.
|
||||
|
||||
Use ONE noun naming the skill, module, feature or changed binary. The keyword must
|
||||
be alphanumeric or hyphen only; simplify other characters. For example, use
|
||||
`token-or-search`, not `feat: token-or search`.
|
||||
Use ONE alphanumeric-or-hyphen noun naming the skill, module, feature or changed
|
||||
binary: `token-or-search`, not `feat: token-or search`.
|
||||
|
||||
```bash
|
||||
{ _LE=$(~/.claude/skills/gstack/bin/gstack-learnings-search --query "<your-keyword>" --limit 5 2>&1 >&3 3>&-); _LR=$?; } 3>&1
|
||||
[ "$_LR" = 0 ] || { _LE=${_LE%%$'\n'*}; echo "LEARNINGS: unavailable (${_LE:-exit $_LR})"; }
|
||||
```
|
||||
|
||||
Name an applicable learning and its effect on the version bump or CHANGELOG in
|
||||
one sentence. If none applies, continue without a reference.
|
||||
Name an applicable learning and its effect on the bump or CHANGELOG in
|
||||
one sentence, or continue without one.
|
||||
@@ -9,7 +9,8 @@ reserve the planned voices as one batch (`gstack-ship-budget check --next dispat
|
||||
and add `--reservation <id>` to the `--start adversarial-review` call below.
|
||||
After `NEXT: voices` (gate class: Step 11 before any stop), Finish the adversarial phase takes neither
|
||||
decision 2 nor 3: rerun Step 9's repeat decision with `--adversarial-ran` (a queued blocking finding as
|
||||
`--blocking-open`); its `NEXT:` (the stop, or the owner's granted fix-check) stands.
|
||||
`--blocking-open`); its `NEXT:` stands: only `stop` (Step 9.4's decision 2)
|
||||
or a granted fix-check (item 3.5, then Step 11.5) follows voices.
|
||||
|
||||
{{ADVERSARIAL_STEP}}
|
||||
|
||||
@@ -22,14 +23,13 @@ decision 2 nor 3: rerun Step 9's repeat decision with `--adversarial-ran` (a que
|
||||
Step 8 used broad release terms. Before VERSION/CHANGELOG, search for versioning
|
||||
or changelog pitfalls tied to this branch's headline feature.
|
||||
|
||||
Use ONE noun naming the skill, module, feature or changed binary. The keyword must
|
||||
be alphanumeric or hyphen only; simplify other characters. For example, use
|
||||
`token-or-search`, not `feat: token-or search`.
|
||||
Use ONE alphanumeric-or-hyphen noun naming the skill, module, feature or changed
|
||||
binary: `token-or-search`, not `feat: token-or search`.
|
||||
|
||||
```bash
|
||||
{ _LE=$(~/.claude/skills/gstack/bin/gstack-learnings-search --query "<your-keyword>" --limit 5 2>&1 >&3 3>&-); _LR=$?; } 3>&1
|
||||
[ "$_LR" = 0 ] || { _LE=${_LE%%$'\n'*}; echo "LEARNINGS: unavailable (${_LE:-exit $_LR})"; }
|
||||
```
|
||||
|
||||
Name an applicable learning and its effect on the version bump or CHANGELOG in
|
||||
one sentence. If none applies, continue without a reference.
|
||||
Name an applicable learning and its effect on the bump or CHANGELOG in
|
||||
one sentence, or continue without one.
|
||||
@@ -3,8 +3,7 @@
|
||||
## Step 6.5: Early Greptile PR (after the free tests pass)
|
||||
|
||||
When the repo uses Greptile (and `greptile` is in a review-bot list), push and open the PR
|
||||
now so Greptile reviews while Steps 7–9 run; Step 10 collects its comments. Without Greptile
|
||||
nothing changes.
|
||||
now so Greptile reviews while Steps 7–9 run; Step 10 collects its comments.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-greptile-early detect
|
||||
@@ -18,8 +17,9 @@ nothing changes.
|
||||
|
||||
A) Push early for this repo (remembered) · B) Keep today's order for this repo (remembered).
|
||||
Run `~/.claude/skills/gstack/bin/gstack-greptile-early consent yes` (A) or `consent no` (B).
|
||||
B continues to Step 7.
|
||||
- **`GREPTILE_EARLY: on`**, or after A — show the user the printed `Greptile: found …` line, then follow 1-3 below.
|
||||
B continues to Step 7. Neither answer undoes Step 5's consent-free CI-carry push
|
||||
and draft PR.
|
||||
- **`GREPTILE_EARLY: on`**, or after A — show the user the printed `Greptile: found …` line, then follow 1-3.
|
||||
|
||||
**1.** Push: `git push -u origin <branch-name>`. If it fails, record
|
||||
"Greptile early review: not run (push failed)" and continue to Step 7; Step 17 pushes later.
|
||||
@@ -35,7 +35,7 @@ TITLE_FILE=$(mktemp "${_GT:?}/early-title.XXXXXX") || { echo "Not sent: mktemp f
|
||||
|
||||
Write the text into each printed file with your file-write tool (Claude Code's Write tool needs a Read of the empty file first), exactly as it should appear. The text never goes into a shell command, heredoc or quoted argument. If a write fails or is refused, do not send: print the cause, the file path and the command below for sending by hand.
|
||||
|
||||
**3.** Open the draft, substituting the printed name. Add `--ready` only when the user asked
|
||||
**3.** Open the draft with the printed name. Add `--ready` only when the user asked
|
||||
for a non-draft PR:
|
||||
|
||||
```bash
|
||||
@@ -43,16 +43,16 @@ TITLE_FILE="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.gstack/tmp/<tit
|
||||
~/.claude/skills/gstack/bin/gstack-greptile-early open --base <base> --title-file "$TITLE_FILE"
|
||||
```
|
||||
|
||||
It opens the PR through `gstack-post` with a body saying /ship opened it early, and
|
||||
It opens the PR through `gstack-post` (body: /ship opened it early) and
|
||||
posts one `@greptileai` comment when Greptile skips drafts. Save the printed
|
||||
`EARLY_PR` and `EARLY_PR_OPENED_AT` in the invocation record. `EARLY_PR: none` means a
|
||||
PR was already open: Step 10 triages it as before. Exit 1 or 2 means `gstack-post`
|
||||
PR was already open (Step 5's draft too): Step 10 triages it. Exit 1 or 2 means `gstack-post`
|
||||
flagged the provisional title: write a plainer one and rerun. Exit 3: record the error
|
||||
and continue without early review.
|
||||
|
||||
**If /ship stops after the early PR opened and before Step 19 publishes**, leave the
|
||||
draft open (never close or force-push it) and post one comment saying /ship stopped
|
||||
and why: write the reason into a private file with your file-write tool, then run
|
||||
and why: write the reason into a private file, then run
|
||||
`~/.claude/skills/gstack/bin/gstack-post pr-comment <pr-number> --body-file <that file>`.
|
||||
|
||||
---
|
||||
@@ -1,8 +1,7 @@
|
||||
## Step 6.5: Early Greptile PR (after the free tests pass)
|
||||
|
||||
When the repo uses Greptile (and `greptile` is in a review-bot list), push and open the PR
|
||||
now so Greptile reviews while Steps 7–9 run; Step 10 collects its comments. Without Greptile
|
||||
nothing changes.
|
||||
now so Greptile reviews while Steps 7–9 run; Step 10 collects its comments.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-greptile-early detect
|
||||
@@ -16,8 +15,9 @@ nothing changes.
|
||||
|
||||
A) Push early for this repo (remembered) · B) Keep today's order for this repo (remembered).
|
||||
Run `~/.claude/skills/gstack/bin/gstack-greptile-early consent yes` (A) or `consent no` (B).
|
||||
B continues to Step 7.
|
||||
- **`GREPTILE_EARLY: on`**, or after A — show the user the printed `Greptile: found …` line, then follow 1-3 below.
|
||||
B continues to Step 7. Neither answer undoes Step 5's consent-free CI-carry push
|
||||
and draft PR.
|
||||
- **`GREPTILE_EARLY: on`**, or after A — show the user the printed `Greptile: found …` line, then follow 1-3.
|
||||
|
||||
**1.** Push: `git push -u origin <branch-name>`. If it fails, record
|
||||
"Greptile early review: not run (push failed)" and continue to Step 7; Step 17 pushes later.
|
||||
@@ -26,7 +26,7 @@ nothing changes.
|
||||
|
||||
{{FREE_TEXT_FILE:TITLE_FILE=early-title}}
|
||||
|
||||
**3.** Open the draft, substituting the printed name. Add `--ready` only when the user asked
|
||||
**3.** Open the draft with the printed name. Add `--ready` only when the user asked
|
||||
for a non-draft PR:
|
||||
|
||||
```bash
|
||||
@@ -34,16 +34,16 @@ TITLE_FILE="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.gstack/tmp/<tit
|
||||
~/.claude/skills/gstack/bin/gstack-greptile-early open --base <base> --title-file "$TITLE_FILE"
|
||||
```
|
||||
|
||||
It opens the PR through `gstack-post` with a body saying /ship opened it early, and
|
||||
It opens the PR through `gstack-post` (body: /ship opened it early) and
|
||||
posts one `@greptileai` comment when Greptile skips drafts. Save the printed
|
||||
`EARLY_PR` and `EARLY_PR_OPENED_AT` in the invocation record. `EARLY_PR: none` means a
|
||||
PR was already open: Step 10 triages it as before. Exit 1 or 2 means `gstack-post`
|
||||
PR was already open (Step 5's draft too): Step 10 triages it. Exit 1 or 2 means `gstack-post`
|
||||
flagged the provisional title: write a plainer one and rerun. Exit 3: record the error
|
||||
and continue without early review.
|
||||
|
||||
**If /ship stops after the early PR opened and before Step 19 publishes**, leave the
|
||||
draft open (never close or force-push it) and post one comment saying /ship stopped
|
||||
and why: write the reason into a private file with your file-write tool, then run
|
||||
and why: write the reason into a private file, then run
|
||||
`~/.claude/skills/gstack/bin/gstack-post pr-comment <pr-number> --body-file <that file>`.
|
||||
|
||||
---
|
||||
@@ -230,12 +230,12 @@ at this exact, clean tree instead of running here: `LANE: <label> carried run=<i
|
||||
Before the first push that lane runs only targeted tests and the repro (the full suite too when the diff touches
|
||||
merge-check code: `lib/ship-*`, `lib/pregate/*`, the ship and pregate bins,
|
||||
`scripts/lib/shard-engine.ts`). Push early so CI runs beside the review: commit, `gstack-ship-release push
|
||||
--branch <branch> --early` (sealed, secrets and guards first; Step 6.5 asks only for Greptile), open a draft PR
|
||||
--branch <branch> --early` (sealed, secrets and guards first; no consent: Step 6.5 asks only for Greptile), open a draft PR
|
||||
(`gstack-post pr-create --base <base> --draft --title-file <f> --body-file <f>`), then `gstack-ci-carry wait` in
|
||||
the background; once it prints `CI_WAIT: green`, rerun `--tests-only` and the mapped lane is carried. A red
|
||||
run is a failed lane: triage it below. Batch review fixes into one commit and one push. `CI_CARRY: none
|
||||
label=<l> (<reason>)` names why a mapped lane ran here. Any other lane that already passed at this
|
||||
tree, command and runtime is reused (`reused=<time>`), never run twice. In Step 16, `finish` defers a mapped
|
||||
tree, command and runtime is reused (`reused=<time>`). In Step 16, `finish` defers a mapped
|
||||
lane it cannot carry (`EVIDENCE: DEFERRED`); after Step 17's push, `gstack-ship-release accept --base <base>
|
||||
--lane …` carries it from the green run at the final head and reruns the pregate there.
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ at this exact, clean tree instead of running here: `LANE: <label> carried run=<i
|
||||
Before the first push that lane runs only targeted tests and the repro (the full suite too when the diff touches
|
||||
merge-check code: `lib/ship-*`, `lib/pregate/*`, the ship and pregate bins,
|
||||
`scripts/lib/shard-engine.ts`). Push early so CI runs beside the review: commit, `gstack-ship-release push
|
||||
--branch <branch> --early` (sealed, secrets and guards first; Step 6.5 asks only for Greptile), open a draft PR
|
||||
--branch <branch> --early` (sealed, secrets and guards first; no consent: Step 6.5 asks only for Greptile), open a draft PR
|
||||
(`gstack-post pr-create --base <base> --draft --title-file <f> --body-file <f>`), then `gstack-ci-carry wait` in
|
||||
the background; once it prints `CI_WAIT: green`, rerun `--tests-only` and the mapped lane is carried. A red
|
||||
run is a failed lane: triage it below. Batch review fixes into one commit and one push. `CI_CARRY: none
|
||||
label=<l> (<reason>)` names why a mapped lane ran here. Any other lane that already passed at this
|
||||
tree, command and runtime is reused (`reused=<time>`), never run twice. In Step 16, `finish` defers a mapped
|
||||
tree, command and runtime is reused (`reused=<time>`). In Step 16, `finish` defers a mapped
|
||||
lane it cannot carry (`EVIDENCE: DEFERRED`); after Step 17's push, `gstack-ship-release accept --base <base>
|
||||
--lane …` carries it from the green run at the final head and reruns the pregate there.
|
||||
|
||||
|
||||
+48
-52
@@ -205,14 +205,14 @@ A review's **start token** is the opaque value returned by `gstack-review-log --
|
||||
before it reads the diff. Keep `REVIEW_START` for Step 9, a separate `PASS_START` for
|
||||
each Step 11 attempt, and `DESIGN_START` for design. Finish each pass with its original
|
||||
token; `--finish` stamps the binding fields automatically. Never borrow or replace a token.
|
||||
`gstack-wtree` prints a Git tree hash covering tracked and non-ignored untracked files,
|
||||
not a commit ID. Use `git diff <old-tree> <new-tree>` to compare these snapshots.
|
||||
`gstack-wtree` prints a Git tree hash of tracked and non-ignored untracked files (not a commit);
|
||||
compare two with `git diff <old-tree> <new-tree>`.
|
||||
|
||||
**Review policy** (docs/review-policy.md): only a finding that would fail a test,
|
||||
break production, or lose data or secrets blocks a pass; the rest is a PR-body
|
||||
note. Step 9's plan sets both reviews' depth (`--depth-floor standard|full` only
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds,
|
||||
fix-checks included. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds under `frozen`
|
||||
(fix-checks included), else Step 9.4's third fix cycle. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
is the knob; the receipt's `review_loop` records the outcome.
|
||||
|
||||
### Ship control flow
|
||||
@@ -307,7 +307,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
|
||||
---
|
||||
|
||||
`<base>` means the detected branch name for fetch/helper arguments;
|
||||
`origin/<base>` is its remote-tracking ref for comparisons. Step 1 fetches it.
|
||||
`origin/<base>` is its remote-tracking ref for comparisons.
|
||||
|
||||
|
||||
|
||||
@@ -334,11 +334,12 @@ act on each `STOP:` and `NEXT:` line.
|
||||
restore access. `DIFF:` is the stat and commit count.
|
||||
|
||||
4. **Carry check.** An open PR prints `PR: #<n>` and its `gstack-ship-receipt carry --pr <n> --base <base> --dry-run` line.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review, fix
|
||||
what it broke (CHANGELOG, size caps), run `gstack-pregate --allow-repo-commands`, then carry
|
||||
without `--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and
|
||||
ends the run. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review and Step 14.5,
|
||||
fix what it broke (CHANGELOG, size caps), commit, `gstack-ship-release push --branch <branch-name>
|
||||
--early`, `gstack-ci-carry wait --base <base>`, run `gstack-pregate --allow-repo-commands`, then carry without
|
||||
`--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and ends
|
||||
the run with its `GSTACK_RESULT:` line. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16. Steps 17–21 then publish.
|
||||
|
||||
5. Display historical readiness using the dashboard below, then finish Step 1.
|
||||
Prior CLEAR reviews or dashboard skips never replace Step 9's gates.
|
||||
@@ -522,7 +523,8 @@ runs items 1 and 3–5; item commands serve only a `STOP:`, which names its reru
|
||||
(`--bump`, `--accept-incomplete`, `--version <v>`, `--keep-current`, `--answer`).
|
||||
|
||||
`VERSION: skipped` or `VERSION: <v> kept (…; no write)` ends Step 12 with
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch.
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch
|
||||
(`kept`: VERSION stays `<v>`).
|
||||
|
||||
1. **Classify state** — pure reader, never writes:
|
||||
```bash
|
||||
@@ -629,7 +631,7 @@ write failures are non-blocking.
|
||||
## Step 14.5: Documentation audit (every ship)
|
||||
|
||||
**Doc-sync invariant:** Every ship dispatches the /document-release subagent before final
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes.
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes, but not a Step 1 carry.
|
||||
No edits means an executed audit, not a skip; report the section's verified outcome.
|
||||
|
||||
> **STOP.** Before auditing docs before final commit/verification (Step 14.5), on every ship, Read `sections/documentation.md` relative to the installed `gstack-ship` SKILL.md directory and execute it
|
||||
@@ -654,17 +656,17 @@ Make bisectable commits; if already committed, continue to Step 16. Never create
|
||||
|
||||
**IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
|
||||
|
||||
Stages run in order; 1–4's other commands are `STOP:` recoveries. Content
|
||||
changes during or after verification restart at stage 1 and complete all five
|
||||
stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
`finish` runs stages 1–4 in order; act on each `STOP:` by its recovery below, then rerun
|
||||
it. Content changes during or after verification restart at
|
||||
stage 1 and complete all five stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
|
||||
**One call for stages 1–4:** `~/.gemini/antigravity-cli/skills/gstack/bin/gstack-ship-release finish --base <base> --reviewed-tree <tree> --reviewed-base <mb> --docs-post <audit-id>-post.json --lane <label>=<Step 5 command>... [--build <cmd>]... --trailer '<trailer>'`
|
||||
makes Step 15's item-3 commit, runs stages 1–4 and the pregate; each `STOP:` is a recovery
|
||||
below (`--docs-rechecked`, `--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
also makes Step 15's item-3 commit and runs the pregate (`--docs-rechecked`,
|
||||
`--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
|
||||
### 1. Finish writers and prepare outputs
|
||||
|
||||
Inspect writer handles, including the docs child. Confirm terminal completion or
|
||||
Before `finish`, inspect writer handles, including the docs child. Confirm completion or
|
||||
termination before another writer runs; timeout or cancellation acknowledgment
|
||||
alone means STOP until confirmed.
|
||||
|
||||
@@ -673,30 +675,28 @@ files and CI. Pass each to `finish` as `--build`. If none exists, record not app
|
||||
the inspected sources. A missing prerequisite or failed build stops shipping:
|
||||
report **Build failed or prerequisite missing**, with the command, error and needed
|
||||
repair. Never invent a substitute command.
|
||||
**If blocked:** Repair it, then repeat stage 1. After it passes, continue
|
||||
to stage 2; treat any content repair as a behavioral change there.
|
||||
**If blocked:** repair it, repeat stage 1, then continue to stage 2: a content repair is behavior there.
|
||||
|
||||
### 2. Choose the change route
|
||||
|
||||
Capture the current tree with `~/.gemini/antigravity-cli/skills/gstack/bin/gstack-wtree`. Inspect
|
||||
`git diff <reviewed-tree> <current-tree>` against the snapshot saved before Step 12.
|
||||
Missing snapshots block this comparison, regardless of HEAD equality.
|
||||
`finish` runs `git diff <reviewed-tree> <current-tree>` (`--reviewed-tree`, saved before Step 12,
|
||||
against `~/.gemini/antigravity-cli/skills/gstack/bin/gstack-wtree`) and prints `ROUTE:`. No saved tree: pass `review_binding.end_wtree` from Step 11.5's bound Step 9 record;
|
||||
with none, insert `9 → 10 → 11 → 11.5`.
|
||||
|
||||
Classify the comparison in this order:
|
||||
Its `STOP:` names the route:
|
||||
|
||||
1. **Behavior, tests or build inputs changed:** Prompts/templates count as behavior.
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17, then stop this step.
|
||||
This repair excludes Step 14.5 because the rebuild can change generated docs.
|
||||
Step 16 restarts at stage 1: rebuild and compare again before stage 3 decides
|
||||
documentation freshness. Further repairs use the same work list. A STOP naming a scoped-review packet
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17. It excludes Step 14.5 (a rebuild
|
||||
can change generated docs; compare before stage 3) and Step 15 (`finish` STOPs on an uncommitted
|
||||
non-release file: commit it by Step 15's rules, then rerun). A STOP naming a scoped-review packet
|
||||
instead takes its fix-check and `--context-reviewed` rerun; a blocking finding is this item.
|
||||
2. **Only authored docs or release metadata changed:** Keep Step 8's original child
|
||||
report and counts. Recheck affected plan items using their recorded verification
|
||||
and append current evidence to the invocation record. If a classification is no
|
||||
longer supported, run Step 8's audit and decision gates only, then return to
|
||||
Step 16 stage 1. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** Continue to stage 3
|
||||
without a new code review.
|
||||
Step 16 stage 1; else rerun with `--docs-rechecked`. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** `finish` continues to
|
||||
stage 3 without a new code review.
|
||||
|
||||
### 3. Resolve documentation freshness
|
||||
|
||||
@@ -728,33 +728,29 @@ Never run a third audit. Child return is not acceptance.
|
||||
Freeze inputs through verification and push. Run declared docs/link/generated-file
|
||||
checks; report any that are unavailable.
|
||||
|
||||
**Reuse a check when its inputs match.** Compare hashes or complete bytes of its
|
||||
saved and current consumed files, fixtures, dependencies and execution parameters.
|
||||
Changed or unknown dependencies require a rerun. For model judges, compare the complete
|
||||
expanded request, rubric, parameters and builder/runtime dependencies. Cite the original
|
||||
command, result/counts, timestamp and log, never resample. Mandatory reviews still run.
|
||||
**Reuse a check when its inputs match.** Same consumed files, fixtures, dependencies
|
||||
and parameters (for a model judge, the complete expanded request and rubric); unknown means
|
||||
rerun. Cite the original command, result, timestamp and log; never resample. Mandatory reviews still run.
|
||||
|
||||
**Check each test lane's receipt as well.** Use its actual Step 5 label/command:
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`. Inspect changes since the run;
|
||||
`--allow-paths` exempts only release metadata. A `package.json` version-only edit
|
||||
can qualify; scripts, dependencies and runtime configuration require live tests.
|
||||
Uncertain edits cannot be exempted. Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review; a Step 14 TODOS.md edit reruns them. Use this example only once
|
||||
every allowed edit is release metadata:
|
||||
**Check each test lane's receipt as well.** `finish` checks every `--lane` as
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`, like this example:
|
||||
|
||||
```bash
|
||||
~/.gemini/antigravity-cli/skills/gstack/bin/gstack-evidence check --label tests --expect-cmd '<tests>' --label vitest --expect-cmd '<vitest>' --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json,agents-digest/gstack-AGENTS.md
|
||||
```
|
||||
|
||||
`--allow-paths` exempts only release metadata (in `package.json`, only a version edit). Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review.
|
||||
|
||||
| Receipt result | Next action |
|
||||
|---|---|
|
||||
| FRESH (exit 0) | Cite the label, exit, timestamp, log and `tests_ran`. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.gemini/antigravity-cli/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once. Handle failures as described below. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.gemini/antigravity-cli/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once (`finish` does; a CI-mapped lane is carried, else `EVIDENCE: DEFERRED`). Still not FRESH: a failed lane. |
|
||||
| ZERO-RUN: the receipt's `tests_ran` is 0 | STALE-equivalent: use Step 5's ZERO-RUN triage (a failed lane), never FRESH, even with exit 0. |
|
||||
| `tests_ran: unknown` | Non-blocking: keep the exit-0 verdict, cite the lane as `count unavailable`. Never record it as ZERO-RUN or as a counted pass. |
|
||||
| Only receipt storage/readback failed | Prove unchanged final content, the same command and valid age from the successful run's evidence. Cite its exact command, exit, timestamp and log as **ledger unavailable**, never FRESH. Without that proof, use STALE/MISSING. |
|
||||
|
||||
No test lanes: require Step 5's explicit untested-scope approval for final content,
|
||||
No test lanes: rerun with `--no-lanes-approved` on Step 5's explicit untested-scope approval,
|
||||
or run Steps 5–15, including the no-tests decision, then return to Step 16 stage 1.
|
||||
Report the gap, never FRESH; builds must pass.
|
||||
|
||||
@@ -766,7 +762,8 @@ does not authorize a third attempt.
|
||||
### 5. Report, then push
|
||||
|
||||
`finish` made the release commit. Commit only verified outputs stage 1's
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit.
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit. It is
|
||||
content-preserving: no restart.
|
||||
Preserve unrelated user files.
|
||||
|
||||
Paste build/docs/test results. Reuse waivers only for the same verified
|
||||
@@ -781,7 +778,7 @@ its records:
|
||||
- Each test lane's `tests_ran` (N, ZERO-RUN or `count unavailable`).
|
||||
Write this report in the auditor's posture: this session's own gate edits are
|
||||
evidence for the reader to examine, not positions to defend; a kept gate
|
||||
states its reason and nothing more. Otherwise continue to Step 17.
|
||||
states its reason and nothing more. Then continue to Step 17.
|
||||
|
||||
---
|
||||
|
||||
@@ -882,7 +879,8 @@ It checks the branch, the offer, the gate above (`--gate-open <n>`; `--gate-open
|
||||
even with unchanged content before returning to Step 17. Never bypass failed guards.
|
||||
Never force-push. Only a successful push or verified `ALREADY_PUSHED` proceeds.
|
||||
|
||||
Continue to Step 18. No documentation writer runs after push.
|
||||
After `EVIDENCE: DEFERRED`, run Step 5's `gstack-ship-release accept`; a `STOP:` there
|
||||
is a failed lane (stage 4). Continue to Step 18. No documentation writer runs after push.
|
||||
|
||||
---
|
||||
|
||||
@@ -910,8 +908,7 @@ echoed): an open PR at HEAD takes pr-body's existing-PR path (body and title onl
|
||||
|
||||
## Step 20: Persist ship metrics
|
||||
|
||||
Log metrics for `/retro` through `gstack-review-log`; it handles project/branch paths,
|
||||
JSON validation, storage and sync and takes **no path argument**.
|
||||
Log metrics for `/retro` through `gstack-review-log`; it takes **no path argument**.
|
||||
|
||||
```bash
|
||||
~/.gemini/antigravity-cli/skills/gstack/bin/gstack-review-log '{"skill":"ship","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","coverage_pct":COVERAGE_PCT,"coverage_schema":2,"coverage_pct_value":COVERAGE_PCT_VALUE,"weak_gaps":WEAK_GAPS,"tests_extended":TESTS_EXTENDED,"tests_rejected":TESTS_REJECTED,"regression_proof":REGRESSION_PROOF,"plan_items_total":PLAN_TOTAL,"plan_items_done":PLAN_DONE,"verification_result":"VERIFY_RESULT","version":"VERSION","branch":"'"$(git rev-parse --abbrev-ref HEAD)"'"}'
|
||||
@@ -958,7 +955,7 @@ The last line printed is the result line a parent greps (docs/unattended.md):
|
||||
|
||||
It binds the receipt to HEAD, writes the run record, prints `GSTACK_RESULT: skill=ship
|
||||
status=complete head=<sha> run=<dir>`; `QUEUE_RECEIPT_STALE`: HEAD moved past the receipt (rewrite,
|
||||
repost, rerun). A run that STOPs early ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
repost, rerun). A STOP before Step 19 publishes ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
|
||||
---
|
||||
|
||||
@@ -974,7 +971,6 @@ hand-roll VERSION/package.json writes.
|
||||
|
||||
Follow the numbered gates and their explicit exceptions.
|
||||
|
||||
- **Never force push.** Use regular `git push` only.
|
||||
- **An early Greptile PR stays up.** A stop after Step 6.5 opened it leaves the draft
|
||||
open with one comment saying why (greptile-early section); never close it.
|
||||
- **Use the configured version file's format** (4-digit for VERSION); under NO_VERSION,
|
||||
|
||||
+48
-52
@@ -204,14 +204,14 @@ A review's **start token** is the opaque value returned by `gstack-review-log --
|
||||
before it reads the diff. Keep `REVIEW_START` for Step 9, a separate `PASS_START` for
|
||||
each Step 11 attempt, and `DESIGN_START` for design. Finish each pass with its original
|
||||
token; `--finish` stamps the binding fields automatically. Never borrow or replace a token.
|
||||
`gstack-wtree` prints a Git tree hash covering tracked and non-ignored untracked files,
|
||||
not a commit ID. Use `git diff <old-tree> <new-tree>` to compare these snapshots.
|
||||
`gstack-wtree` prints a Git tree hash of tracked and non-ignored untracked files (not a commit);
|
||||
compare two with `git diff <old-tree> <new-tree>`.
|
||||
|
||||
**Review policy** (docs/review-policy.md): only a finding that would fail a test,
|
||||
break production, or lose data or secrets blocks a pass; the rest is a PR-body
|
||||
note. Step 9's plan sets both reviews' depth (`--depth-floor standard|full` only
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds,
|
||||
fix-checks included. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds under `frozen`
|
||||
(fix-checks included), else Step 9.4's third fix cycle. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
is the knob; the receipt's `review_loop` records the outcome.
|
||||
|
||||
### Ship control flow
|
||||
@@ -306,7 +306,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
|
||||
---
|
||||
|
||||
`<base>` means the detected branch name for fetch/helper arguments;
|
||||
`origin/<base>` is its remote-tracking ref for comparisons. Step 1 fetches it.
|
||||
`origin/<base>` is its remote-tracking ref for comparisons.
|
||||
|
||||
|
||||
|
||||
@@ -333,11 +333,12 @@ act on each `STOP:` and `NEXT:` line.
|
||||
restore access. `DIFF:` is the stat and commit count.
|
||||
|
||||
4. **Carry check.** An open PR prints `PR: #<n>` and its `gstack-ship-receipt carry --pr <n> --base <base> --dry-run` line.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review, fix
|
||||
what it broke (CHANGELOG, size caps), run `gstack-pregate --allow-repo-commands`, then carry
|
||||
without `--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and
|
||||
ends the run. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review and Step 14.5,
|
||||
fix what it broke (CHANGELOG, size caps), commit, `gstack-ship-release push --branch <branch-name>
|
||||
--early`, `gstack-ci-carry wait --base <base>`, run `gstack-pregate --allow-repo-commands`, then carry without
|
||||
`--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and ends
|
||||
the run with its `GSTACK_RESULT:` line. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16. Steps 17–21 then publish.
|
||||
|
||||
5. Display historical readiness using the dashboard below, then finish Step 1.
|
||||
Prior CLEAR reviews or dashboard skips never replace Step 9's gates.
|
||||
@@ -521,7 +522,8 @@ runs items 1 and 3–5; item commands serve only a `STOP:`, which names its reru
|
||||
(`--bump`, `--accept-incomplete`, `--version <v>`, `--keep-current`, `--answer`).
|
||||
|
||||
`VERSION: skipped` or `VERSION: <v> kept (…; no write)` ends Step 12 with
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch.
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch
|
||||
(`kept`: VERSION stays `<v>`).
|
||||
|
||||
1. **Classify state** — pure reader, never writes:
|
||||
```bash
|
||||
@@ -628,7 +630,7 @@ write failures are non-blocking.
|
||||
## Step 14.5: Documentation audit (every ship)
|
||||
|
||||
**Doc-sync invariant:** Every ship dispatches the /document-release subagent before final
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes.
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes, but not a Step 1 carry.
|
||||
No edits means an executed audit, not a skip; report the section's verified outcome.
|
||||
|
||||
> **STOP.** Before auditing docs before final commit/verification (Step 14.5), on every ship, Read `~/.claude/skills/gstack/ship/sections/documentation.md` and execute it
|
||||
@@ -653,17 +655,17 @@ Make bisectable commits; if already committed, continue to Step 16. Never create
|
||||
|
||||
**IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
|
||||
|
||||
Stages run in order; 1–4's other commands are `STOP:` recoveries. Content
|
||||
changes during or after verification restart at stage 1 and complete all five
|
||||
stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
`finish` runs stages 1–4 in order; act on each `STOP:` by its recovery below, then rerun
|
||||
it. Content changes during or after verification restart at
|
||||
stage 1 and complete all five stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
|
||||
**One call for stages 1–4:** `~/.claude/skills/gstack/bin/gstack-ship-release finish --base <base> --reviewed-tree <tree> --reviewed-base <mb> --docs-post <audit-id>-post.json --lane <label>=<Step 5 command>... [--build <cmd>]... --trailer '<trailer>'`
|
||||
makes Step 15's item-3 commit, runs stages 1–4 and the pregate; each `STOP:` is a recovery
|
||||
below (`--docs-rechecked`, `--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
also makes Step 15's item-3 commit and runs the pregate (`--docs-rechecked`,
|
||||
`--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
|
||||
### 1. Finish writers and prepare outputs
|
||||
|
||||
Inspect writer handles, including the docs child. Confirm terminal completion or
|
||||
Before `finish`, inspect writer handles, including the docs child. Confirm completion or
|
||||
termination before another writer runs; timeout or cancellation acknowledgment
|
||||
alone means STOP until confirmed.
|
||||
|
||||
@@ -672,30 +674,28 @@ files and CI. Pass each to `finish` as `--build`. If none exists, record not app
|
||||
the inspected sources. A missing prerequisite or failed build stops shipping:
|
||||
report **Build failed or prerequisite missing**, with the command, error and needed
|
||||
repair. Never invent a substitute command.
|
||||
**If blocked:** Repair it, then repeat stage 1. After it passes, continue
|
||||
to stage 2; treat any content repair as a behavioral change there.
|
||||
**If blocked:** repair it, repeat stage 1, then continue to stage 2: a content repair is behavior there.
|
||||
|
||||
### 2. Choose the change route
|
||||
|
||||
Capture the current tree with `~/.claude/skills/gstack/bin/gstack-wtree`. Inspect
|
||||
`git diff <reviewed-tree> <current-tree>` against the snapshot saved before Step 12.
|
||||
Missing snapshots block this comparison, regardless of HEAD equality.
|
||||
`finish` runs `git diff <reviewed-tree> <current-tree>` (`--reviewed-tree`, saved before Step 12,
|
||||
against `~/.claude/skills/gstack/bin/gstack-wtree`) and prints `ROUTE:`. No saved tree: pass `review_binding.end_wtree` from Step 11.5's bound Step 9 record;
|
||||
with none, insert `9 → 10 → 11 → 11.5`.
|
||||
|
||||
Classify the comparison in this order:
|
||||
Its `STOP:` names the route:
|
||||
|
||||
1. **Behavior, tests or build inputs changed:** Prompts/templates count as behavior.
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17, then stop this step.
|
||||
This repair excludes Step 14.5 because the rebuild can change generated docs.
|
||||
Step 16 restarts at stage 1: rebuild and compare again before stage 3 decides
|
||||
documentation freshness. Further repairs use the same work list. A STOP naming a scoped-review packet
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17. It excludes Step 14.5 (a rebuild
|
||||
can change generated docs; compare before stage 3) and Step 15 (`finish` STOPs on an uncommitted
|
||||
non-release file: commit it by Step 15's rules, then rerun). A STOP naming a scoped-review packet
|
||||
instead takes its fix-check and `--context-reviewed` rerun; a blocking finding is this item.
|
||||
2. **Only authored docs or release metadata changed:** Keep Step 8's original child
|
||||
report and counts. Recheck affected plan items using their recorded verification
|
||||
and append current evidence to the invocation record. If a classification is no
|
||||
longer supported, run Step 8's audit and decision gates only, then return to
|
||||
Step 16 stage 1. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** Continue to stage 3
|
||||
without a new code review.
|
||||
Step 16 stage 1; else rerun with `--docs-rechecked`. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** `finish` continues to
|
||||
stage 3 without a new code review.
|
||||
|
||||
### 3. Resolve documentation freshness
|
||||
|
||||
@@ -727,33 +727,29 @@ Never run a third audit. Child return is not acceptance.
|
||||
Freeze inputs through verification and push. Run declared docs/link/generated-file
|
||||
checks; report any that are unavailable.
|
||||
|
||||
**Reuse a check when its inputs match.** Compare hashes or complete bytes of its
|
||||
saved and current consumed files, fixtures, dependencies and execution parameters.
|
||||
Changed or unknown dependencies require a rerun. For model judges, compare the complete
|
||||
expanded request, rubric, parameters and builder/runtime dependencies. Cite the original
|
||||
command, result/counts, timestamp and log, never resample. Mandatory reviews still run.
|
||||
**Reuse a check when its inputs match.** Same consumed files, fixtures, dependencies
|
||||
and parameters (for a model judge, the complete expanded request and rubric); unknown means
|
||||
rerun. Cite the original command, result, timestamp and log; never resample. Mandatory reviews still run.
|
||||
|
||||
**Check each test lane's receipt as well.** Use its actual Step 5 label/command:
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`. Inspect changes since the run;
|
||||
`--allow-paths` exempts only release metadata. A `package.json` version-only edit
|
||||
can qualify; scripts, dependencies and runtime configuration require live tests.
|
||||
Uncertain edits cannot be exempted. Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review; a Step 14 TODOS.md edit reruns them. Use this example only once
|
||||
every allowed edit is release metadata:
|
||||
**Check each test lane's receipt as well.** `finish` checks every `--lane` as
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`, like this example:
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-evidence check --label tests --expect-cmd '<tests>' --label vitest --expect-cmd '<vitest>' --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json,agents-digest/gstack-AGENTS.md
|
||||
```
|
||||
|
||||
`--allow-paths` exempts only release metadata (in `package.json`, only a version edit). Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review.
|
||||
|
||||
| Receipt result | Next action |
|
||||
|---|---|
|
||||
| FRESH (exit 0) | Cite the label, exit, timestamp, log and `tests_ran`. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.claude/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once. Handle failures as described below. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `~/.claude/skills/gstack/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once (`finish` does; a CI-mapped lane is carried, else `EVIDENCE: DEFERRED`). Still not FRESH: a failed lane. |
|
||||
| ZERO-RUN: the receipt's `tests_ran` is 0 | STALE-equivalent: use Step 5's ZERO-RUN triage (a failed lane), never FRESH, even with exit 0. |
|
||||
| `tests_ran: unknown` | Non-blocking: keep the exit-0 verdict, cite the lane as `count unavailable`. Never record it as ZERO-RUN or as a counted pass. |
|
||||
| Only receipt storage/readback failed | Prove unchanged final content, the same command and valid age from the successful run's evidence. Cite its exact command, exit, timestamp and log as **ledger unavailable**, never FRESH. Without that proof, use STALE/MISSING. |
|
||||
|
||||
No test lanes: require Step 5's explicit untested-scope approval for final content,
|
||||
No test lanes: rerun with `--no-lanes-approved` on Step 5's explicit untested-scope approval,
|
||||
or run Steps 5–15, including the no-tests decision, then return to Step 16 stage 1.
|
||||
Report the gap, never FRESH; builds must pass.
|
||||
|
||||
@@ -765,7 +761,8 @@ does not authorize a third attempt.
|
||||
### 5. Report, then push
|
||||
|
||||
`finish` made the release commit. Commit only verified outputs stage 1's
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit.
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit. It is
|
||||
content-preserving: no restart.
|
||||
Preserve unrelated user files.
|
||||
|
||||
Paste build/docs/test results. Reuse waivers only for the same verified
|
||||
@@ -780,7 +777,7 @@ its records:
|
||||
- Each test lane's `tests_ran` (N, ZERO-RUN or `count unavailable`).
|
||||
Write this report in the auditor's posture: this session's own gate edits are
|
||||
evidence for the reader to examine, not positions to defend; a kept gate
|
||||
states its reason and nothing more. Otherwise continue to Step 17.
|
||||
states its reason and nothing more. Then continue to Step 17.
|
||||
|
||||
---
|
||||
|
||||
@@ -881,7 +878,8 @@ It checks the branch, the offer, the gate above (`--gate-open <n>`; `--gate-open
|
||||
even with unchanged content before returning to Step 17. Never bypass failed guards.
|
||||
Never force-push. Only a successful push or verified `ALREADY_PUSHED` proceeds.
|
||||
|
||||
Continue to Step 18. No documentation writer runs after push.
|
||||
After `EVIDENCE: DEFERRED`, run Step 5's `gstack-ship-release accept`; a `STOP:` there
|
||||
is a failed lane (stage 4). Continue to Step 18. No documentation writer runs after push.
|
||||
|
||||
---
|
||||
|
||||
@@ -909,8 +907,7 @@ echoed): an open PR at HEAD takes pr-body's existing-PR path (body and title onl
|
||||
|
||||
## Step 20: Persist ship metrics
|
||||
|
||||
Log metrics for `/retro` through `gstack-review-log`; it handles project/branch paths,
|
||||
JSON validation, storage and sync and takes **no path argument**.
|
||||
Log metrics for `/retro` through `gstack-review-log`; it takes **no path argument**.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"ship","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","coverage_pct":COVERAGE_PCT,"coverage_schema":2,"coverage_pct_value":COVERAGE_PCT_VALUE,"weak_gaps":WEAK_GAPS,"tests_extended":TESTS_EXTENDED,"tests_rejected":TESTS_REJECTED,"regression_proof":REGRESSION_PROOF,"plan_items_total":PLAN_TOTAL,"plan_items_done":PLAN_DONE,"verification_result":"VERIFY_RESULT","version":"VERSION","branch":"'"$(git rev-parse --abbrev-ref HEAD)"'"}'
|
||||
@@ -957,7 +954,7 @@ The last line printed is the result line a parent greps (docs/unattended.md):
|
||||
|
||||
It binds the receipt to HEAD, writes the run record, prints `GSTACK_RESULT: skill=ship
|
||||
status=complete head=<sha> run=<dir>`; `QUEUE_RECEIPT_STALE`: HEAD moved past the receipt (rewrite,
|
||||
repost, rerun). A run that STOPs early ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
repost, rerun). A STOP before Step 19 publishes ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
|
||||
---
|
||||
|
||||
@@ -973,7 +970,6 @@ hand-roll VERSION/package.json writes.
|
||||
|
||||
Follow the numbered gates and their explicit exceptions.
|
||||
|
||||
- **Never force push.** Use regular `git push` only.
|
||||
- **An early Greptile PR stays up.** A stop after Step 6.5 opened it leaves the draft
|
||||
open with one comment saying why (greptile-early section); never close it.
|
||||
- **Use the configured version file's format** (4-digit for VERSION); under NO_VERSION,
|
||||
|
||||
+48
-52
@@ -203,14 +203,14 @@ A review's **start token** is the opaque value returned by `gstack-review-log --
|
||||
before it reads the diff. Keep `REVIEW_START` for Step 9, a separate `PASS_START` for
|
||||
each Step 11 attempt, and `DESIGN_START` for design. Finish each pass with its original
|
||||
token; `--finish` stamps the binding fields automatically. Never borrow or replace a token.
|
||||
`gstack-wtree` prints a Git tree hash covering tracked and non-ignored untracked files,
|
||||
not a commit ID. Use `git diff <old-tree> <new-tree>` to compare these snapshots.
|
||||
`gstack-wtree` prints a Git tree hash of tracked and non-ignored untracked files (not a commit);
|
||||
compare two with `git diff <old-tree> <new-tree>`.
|
||||
|
||||
**Review policy** (docs/review-policy.md): only a finding that would fail a test,
|
||||
break production, or lose data or secrets blocks a pass; the rest is a PR-body
|
||||
note. Step 9's plan sets both reviews' depth (`--depth-floor standard|full` only
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds,
|
||||
fix-checks included. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds under `frozen`
|
||||
(fix-checks included), else Step 9.4's third fix cycle. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
is the knob; the receipt's `review_loop` records the outcome.
|
||||
|
||||
### Ship control flow
|
||||
@@ -305,7 +305,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
|
||||
---
|
||||
|
||||
`<base>` means the detected branch name for fetch/helper arguments;
|
||||
`origin/<base>` is its remote-tracking ref for comparisons. Step 1 fetches it.
|
||||
`origin/<base>` is its remote-tracking ref for comparisons.
|
||||
|
||||
|
||||
|
||||
@@ -332,11 +332,12 @@ act on each `STOP:` and `NEXT:` line.
|
||||
restore access. `DIFF:` is the stat and commit count.
|
||||
|
||||
4. **Carry check.** An open PR prints `PR: #<n>` and its `gstack-ship-receipt carry --pr <n> --base <base> --dry-run` line.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review, fix
|
||||
what it broke (CHANGELOG, size caps), run `gstack-pregate --allow-repo-commands`, then carry
|
||||
without `--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and
|
||||
ends the run. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review and Step 14.5,
|
||||
fix what it broke (CHANGELOG, size caps), commit, `gstack-ship-release push --branch <branch-name>
|
||||
--early`, `gstack-ci-carry wait --base <base>`, run `gstack-pregate --allow-repo-commands`, then carry without
|
||||
`--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and ends
|
||||
the run with its `GSTACK_RESULT:` line. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16. Steps 17–21 then publish.
|
||||
|
||||
5. Display historical readiness using the dashboard below, then finish Step 1.
|
||||
Prior CLEAR reviews or dashboard skips never replace Step 9's gates.
|
||||
@@ -521,7 +522,8 @@ runs items 1 and 3–5; item commands serve only a `STOP:`, which names its reru
|
||||
(`--bump`, `--accept-incomplete`, `--version <v>`, `--keep-current`, `--answer`).
|
||||
|
||||
`VERSION: skipped` or `VERSION: <v> kept (…; no write)` ends Step 12 with
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch.
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch
|
||||
(`kept`: VERSION stays `<v>`).
|
||||
|
||||
1. **Classify state** — pure reader, never writes:
|
||||
```bash
|
||||
@@ -631,7 +633,7 @@ write failures are non-blocking.
|
||||
## Step 14.5: Documentation audit (every ship)
|
||||
|
||||
**Doc-sync invariant:** Every ship dispatches the /document-release subagent before final
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes.
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes, but not a Step 1 carry.
|
||||
No edits means an executed audit, not a skip; report the section's verified outcome.
|
||||
|
||||
> **STOP.** Before auditing docs before final commit/verification (Step 14.5), on every ship, Read `sections/documentation.md` relative to the installed `gstack-ship` SKILL.md directory and execute it
|
||||
@@ -656,17 +658,17 @@ Make bisectable commits; if already committed, continue to Step 16. Never create
|
||||
|
||||
**IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
|
||||
|
||||
Stages run in order; 1–4's other commands are `STOP:` recoveries. Content
|
||||
changes during or after verification restart at stage 1 and complete all five
|
||||
stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
`finish` runs stages 1–4 in order; act on each `STOP:` by its recovery below, then rerun
|
||||
it. Content changes during or after verification restart at
|
||||
stage 1 and complete all five stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
|
||||
**One call for stages 1–4:** `$GSTACK_ROOT/bin/gstack-ship-release finish --base <base> --reviewed-tree <tree> --reviewed-base <mb> --docs-post <audit-id>-post.json --lane <label>=<Step 5 command>... [--build <cmd>]... --trailer '<trailer>'`
|
||||
makes Step 15's item-3 commit, runs stages 1–4 and the pregate; each `STOP:` is a recovery
|
||||
below (`--docs-rechecked`, `--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
also makes Step 15's item-3 commit and runs the pregate (`--docs-rechecked`,
|
||||
`--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
|
||||
### 1. Finish writers and prepare outputs
|
||||
|
||||
Inspect writer handles, including the docs child. Confirm terminal completion or
|
||||
Before `finish`, inspect writer handles, including the docs child. Confirm completion or
|
||||
termination before another writer runs; timeout or cancellation acknowledgment
|
||||
alone means STOP until confirmed.
|
||||
|
||||
@@ -675,30 +677,28 @@ files and CI. Pass each to `finish` as `--build`. If none exists, record not app
|
||||
the inspected sources. A missing prerequisite or failed build stops shipping:
|
||||
report **Build failed or prerequisite missing**, with the command, error and needed
|
||||
repair. Never invent a substitute command.
|
||||
**If blocked:** Repair it, then repeat stage 1. After it passes, continue
|
||||
to stage 2; treat any content repair as a behavioral change there.
|
||||
**If blocked:** repair it, repeat stage 1, then continue to stage 2: a content repair is behavior there.
|
||||
|
||||
### 2. Choose the change route
|
||||
|
||||
Capture the current tree with `$GSTACK_ROOT/bin/gstack-wtree`. Inspect
|
||||
`git diff <reviewed-tree> <current-tree>` against the snapshot saved before Step 12.
|
||||
Missing snapshots block this comparison, regardless of HEAD equality.
|
||||
`finish` runs `git diff <reviewed-tree> <current-tree>` (`--reviewed-tree`, saved before Step 12,
|
||||
against `$GSTACK_ROOT/bin/gstack-wtree`) and prints `ROUTE:`. No saved tree: pass `review_binding.end_wtree` from Step 11.5's bound Step 9 record;
|
||||
with none, insert `9 → 10 → 11 → 11.5`.
|
||||
|
||||
Classify the comparison in this order:
|
||||
Its `STOP:` names the route:
|
||||
|
||||
1. **Behavior, tests or build inputs changed:** Prompts/templates count as behavior.
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17, then stop this step.
|
||||
This repair excludes Step 14.5 because the rebuild can change generated docs.
|
||||
Step 16 restarts at stage 1: rebuild and compare again before stage 3 decides
|
||||
documentation freshness. Further repairs use the same work list. A STOP naming a scoped-review packet
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17. It excludes Step 14.5 (a rebuild
|
||||
can change generated docs; compare before stage 3) and Step 15 (`finish` STOPs on an uncommitted
|
||||
non-release file: commit it by Step 15's rules, then rerun). A STOP naming a scoped-review packet
|
||||
instead takes its fix-check and `--context-reviewed` rerun; a blocking finding is this item.
|
||||
2. **Only authored docs or release metadata changed:** Keep Step 8's original child
|
||||
report and counts. Recheck affected plan items using their recorded verification
|
||||
and append current evidence to the invocation record. If a classification is no
|
||||
longer supported, run Step 8's audit and decision gates only, then return to
|
||||
Step 16 stage 1. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** Continue to stage 3
|
||||
without a new code review.
|
||||
Step 16 stage 1; else rerun with `--docs-rechecked`. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** `finish` continues to
|
||||
stage 3 without a new code review.
|
||||
|
||||
### 3. Resolve documentation freshness
|
||||
|
||||
@@ -730,34 +730,30 @@ Never run a third audit. Child return is not acceptance.
|
||||
Freeze inputs through verification and push. Run declared docs/link/generated-file
|
||||
checks; report any that are unavailable.
|
||||
|
||||
**Reuse a check when its inputs match.** Compare hashes or complete bytes of its
|
||||
saved and current consumed files, fixtures, dependencies and execution parameters.
|
||||
Changed or unknown dependencies require a rerun. For model judges, compare the complete
|
||||
expanded request, rubric, parameters and builder/runtime dependencies. Cite the original
|
||||
command, result/counts, timestamp and log, never resample. Mandatory reviews still run.
|
||||
**Reuse a check when its inputs match.** Same consumed files, fixtures, dependencies
|
||||
and parameters (for a model judge, the complete expanded request and rubric); unknown means
|
||||
rerun. Cite the original command, result, timestamp and log; never resample. Mandatory reviews still run.
|
||||
|
||||
**Check each test lane's receipt as well.** Use its actual Step 5 label/command:
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`. Inspect changes since the run;
|
||||
`--allow-paths` exempts only release metadata. A `package.json` version-only edit
|
||||
can qualify; scripts, dependencies and runtime configuration require live tests.
|
||||
Uncertain edits cannot be exempted. Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review; a Step 14 TODOS.md edit reruns them. Use this example only once
|
||||
every allowed edit is release metadata:
|
||||
**Check each test lane's receipt as well.** `finish` checks every `--lane` as
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`, like this example:
|
||||
|
||||
```bash
|
||||
[ -d "${GSTACK_ROOT:-/-}/bin" ]&&[ -d "$GSTACK_ROOT/lib" ]||{ _r=$(git rev-parse --show-toplevel 2>/dev/null)/.agents/skills/gstack;[ -d "$_r/bin" ]||_r=${CODEX_HOME:-~/.codex}/skills/gstack;[ -d "$_r/bin" ]||{ echo "gstack: no install found (tried $_r). Fix: ./setup --host codex from your gstack checkout; ./setup --status shows it.">&2;exit 1;};GSTACK_ROOT=$_r;}
|
||||
$GSTACK_ROOT/bin/gstack-evidence check --label tests --expect-cmd '<tests>' --label vitest --expect-cmd '<vitest>' --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json,agents-digest/gstack-AGENTS.md
|
||||
```
|
||||
|
||||
`--allow-paths` exempts only release metadata (in `package.json`, only a version edit). Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review.
|
||||
|
||||
| Receipt result | Next action |
|
||||
|---|---|
|
||||
| FRESH (exit 0) | Cite the label, exit, timestamp, log and `tests_ran`. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `$GSTACK_ROOT/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once. Handle failures as described below. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `$GSTACK_ROOT/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once (`finish` does; a CI-mapped lane is carried, else `EVIDENCE: DEFERRED`). Still not FRESH: a failed lane. |
|
||||
| ZERO-RUN: the receipt's `tests_ran` is 0 | STALE-equivalent: use Step 5's ZERO-RUN triage (a failed lane), never FRESH, even with exit 0. |
|
||||
| `tests_ran: unknown` | Non-blocking: keep the exit-0 verdict, cite the lane as `count unavailable`. Never record it as ZERO-RUN or as a counted pass. |
|
||||
| Only receipt storage/readback failed | Prove unchanged final content, the same command and valid age from the successful run's evidence. Cite its exact command, exit, timestamp and log as **ledger unavailable**, never FRESH. Without that proof, use STALE/MISSING. |
|
||||
|
||||
No test lanes: require Step 5's explicit untested-scope approval for final content,
|
||||
No test lanes: rerun with `--no-lanes-approved` on Step 5's explicit untested-scope approval,
|
||||
or run Steps 5–15, including the no-tests decision, then return to Step 16 stage 1.
|
||||
Report the gap, never FRESH; builds must pass.
|
||||
|
||||
@@ -769,7 +765,8 @@ does not authorize a third attempt.
|
||||
### 5. Report, then push
|
||||
|
||||
`finish` made the release commit. Commit only verified outputs stage 1's
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit.
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit. It is
|
||||
content-preserving: no restart.
|
||||
Preserve unrelated user files.
|
||||
|
||||
Paste build/docs/test results. Reuse waivers only for the same verified
|
||||
@@ -784,7 +781,7 @@ its records:
|
||||
- Each test lane's `tests_ran` (N, ZERO-RUN or `count unavailable`).
|
||||
Write this report in the auditor's posture: this session's own gate edits are
|
||||
evidence for the reader to examine, not positions to defend; a kept gate
|
||||
states its reason and nothing more. Otherwise continue to Step 17.
|
||||
states its reason and nothing more. Then continue to Step 17.
|
||||
|
||||
---
|
||||
|
||||
@@ -888,7 +885,8 @@ It checks the branch, the offer, the gate above (`--gate-open <n>`; `--gate-open
|
||||
even with unchanged content before returning to Step 17. Never bypass failed guards.
|
||||
Never force-push. Only a successful push or verified `ALREADY_PUSHED` proceeds.
|
||||
|
||||
Continue to Step 18. No documentation writer runs after push.
|
||||
After `EVIDENCE: DEFERRED`, run Step 5's `gstack-ship-release accept`; a `STOP:` there
|
||||
is a failed lane (stage 4). Continue to Step 18. No documentation writer runs after push.
|
||||
|
||||
---
|
||||
|
||||
@@ -916,8 +914,7 @@ echoed): an open PR at HEAD takes pr-body's existing-PR path (body and title onl
|
||||
|
||||
## Step 20: Persist ship metrics
|
||||
|
||||
Log metrics for `/retro` through `gstack-review-log`; it handles project/branch paths,
|
||||
JSON validation, storage and sync and takes **no path argument**.
|
||||
Log metrics for `/retro` through `gstack-review-log`; it takes **no path argument**.
|
||||
|
||||
```bash
|
||||
[ -d "${GSTACK_ROOT:-/-}/bin" ]&&[ -d "$GSTACK_ROOT/lib" ]||{ _r=$(git rev-parse --show-toplevel 2>/dev/null)/.agents/skills/gstack;[ -d "$_r/bin" ]||_r=${CODEX_HOME:-~/.codex}/skills/gstack;[ -d "$_r/bin" ]||{ echo "gstack: no install found (tried $_r). Fix: ./setup --host codex from your gstack checkout; ./setup --status shows it.">&2;exit 1;};GSTACK_ROOT=$_r;}
|
||||
@@ -967,7 +964,7 @@ $GSTACK_ROOT/bin/gstack-ship-receipt result --pr <pr-number> # handoff: --body
|
||||
|
||||
It binds the receipt to HEAD, writes the run record, prints `GSTACK_RESULT: skill=ship
|
||||
status=complete head=<sha> run=<dir>`; `QUEUE_RECEIPT_STALE`: HEAD moved past the receipt (rewrite,
|
||||
repost, rerun). A run that STOPs early ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
repost, rerun). A STOP before Step 19 publishes ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
|
||||
---
|
||||
|
||||
@@ -983,7 +980,6 @@ hand-roll VERSION/package.json writes.
|
||||
|
||||
Follow the numbered gates and their explicit exceptions.
|
||||
|
||||
- **Never force push.** Use regular `git push` only.
|
||||
- **An early Greptile PR stays up.** A stop after Step 6.5 opened it leaves the draft
|
||||
open with one comment saying why (greptile-early section); never close it.
|
||||
- **Use the configured version file's format** (4-digit for VERSION); under NO_VERSION,
|
||||
|
||||
+48
-52
@@ -205,14 +205,14 @@ A review's **start token** is the opaque value returned by `gstack-review-log --
|
||||
before it reads the diff. Keep `REVIEW_START` for Step 9, a separate `PASS_START` for
|
||||
each Step 11 attempt, and `DESIGN_START` for design. Finish each pass with its original
|
||||
token; `--finish` stamps the binding fields automatically. Never borrow or replace a token.
|
||||
`gstack-wtree` prints a Git tree hash covering tracked and non-ignored untracked files,
|
||||
not a commit ID. Use `git diff <old-tree> <new-tree>` to compare these snapshots.
|
||||
`gstack-wtree` prints a Git tree hash of tracked and non-ignored untracked files (not a commit);
|
||||
compare two with `git diff <old-tree> <new-tree>`.
|
||||
|
||||
**Review policy** (docs/review-policy.md): only a finding that would fail a test,
|
||||
break production, or lose data or secrets blocks a pass; the rest is a PR-body
|
||||
note. Step 9's plan sets both reviews' depth (`--depth-floor standard|full` only
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds,
|
||||
fix-checks included. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
raises it). Pass 1 reads the diff, later passes the range; the cap is two rounds under `frozen`
|
||||
(fix-checks included), else Step 9.4's third fix cycle. `NO FINDINGS` is complete. `ship: review_scope` (Step 3)
|
||||
is the knob; the receipt's `review_loop` records the outcome.
|
||||
|
||||
### Ship control flow
|
||||
@@ -307,7 +307,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
|
||||
---
|
||||
|
||||
`<base>` means the detected branch name for fetch/helper arguments;
|
||||
`origin/<base>` is its remote-tracking ref for comparisons. Step 1 fetches it.
|
||||
`origin/<base>` is its remote-tracking ref for comparisons.
|
||||
|
||||
|
||||
|
||||
@@ -334,11 +334,12 @@ act on each `STOP:` and `NEXT:` line.
|
||||
restore access. `DIFF:` is the stat and commit count.
|
||||
|
||||
4. **Carry check.** An open PR prints `PR: #<n>` and its `gstack-ship-receipt carry --pr <n> --base <base> --dry-run` line.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review, fix
|
||||
what it broke (CHANGELOG, size caps), run `gstack-pregate --allow-repo-commands`, then carry
|
||||
without `--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and
|
||||
ends the run. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16.
|
||||
`CARRY: would carry` (base merge committed, same product patch-id): skip review and Step 14.5,
|
||||
fix what it broke (CHANGELOG, size caps), commit, `gstack-ship-release push --branch <branch-name>
|
||||
--early`, `gstack-ci-carry wait --base <base>`, run `gstack-pregate --allow-repo-commands`, then carry without
|
||||
`--dry-run` plus `--pregate .gstack/tmp/pregate.json`. `CARRY: carried` binds HEAD and ends
|
||||
the run with its `GSTACK_RESULT:` line. A failed check, HEAD moving after pregate, `current`, or `refused` with no
|
||||
`NEXT: carry route` re-runs Steps 2–16. Steps 17–21 then publish.
|
||||
|
||||
5. Display historical readiness using the dashboard below, then finish Step 1.
|
||||
Prior CLEAR reviews or dashboard skips never replace Step 9's gates.
|
||||
@@ -523,7 +524,8 @@ runs items 1 and 3–5; item commands serve only a `STOP:`, which names its reru
|
||||
(`--bump`, `--accept-incomplete`, `--version <v>`, `--keep-current`, `--answer`).
|
||||
|
||||
`VERSION: skipped` or `VERSION: <v> kept (…; no write)` ends Step 12 with
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch.
|
||||
`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch
|
||||
(`kept`: VERSION stays `<v>`).
|
||||
|
||||
1. **Classify state** — pure reader, never writes:
|
||||
```bash
|
||||
@@ -633,7 +635,7 @@ write failures are non-blocking.
|
||||
## Step 14.5: Documentation audit (every ship)
|
||||
|
||||
**Doc-sync invariant:** Every ship dispatches the /document-release subagent before final
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes.
|
||||
commit/verification/publication, including reruns, already-pushed branches, existing PRs and docs-only changes, but not a Step 1 carry.
|
||||
No edits means an executed audit, not a skip; report the section's verified outcome.
|
||||
|
||||
> **STOP.** Before auditing docs before final commit/verification (Step 14.5), on every ship, Read `sections/documentation.md` relative to the installed `gstack-ship` SKILL.md directory and execute it
|
||||
@@ -658,17 +660,17 @@ Make bisectable commits; if already committed, continue to Step 16. Never create
|
||||
|
||||
**IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
|
||||
|
||||
Stages run in order; 1–4's other commands are `STOP:` recoveries. Content
|
||||
changes during or after verification restart at stage 1 and complete all five
|
||||
stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
`finish` runs stages 1–4 in order; act on each `STOP:` by its recovery below, then rerun
|
||||
it. Content changes during or after verification restart at
|
||||
stage 1 and complete all five stages before Step 17. Content-preserving commits keep evidence valid.
|
||||
|
||||
**One call for stages 1–4:** `$GSTACK_ROOT/bin/gstack-ship-release finish --base <base> --reviewed-tree <tree> --reviewed-base <mb> --docs-post <audit-id>-post.json --lane <label>=<Step 5 command>... [--build <cmd>]... --trailer '<trailer>'`
|
||||
makes Step 15's item-3 commit, runs stages 1–4 and the pregate; each `STOP:` is a recovery
|
||||
below (`--docs-rechecked`, `--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
also makes Step 15's item-3 commit and runs the pregate (`--docs-rechecked`,
|
||||
`--no-lanes-approved` record stage 2.2 and Step 5's approval).
|
||||
|
||||
### 1. Finish writers and prepare outputs
|
||||
|
||||
Inspect writer handles, including the docs child. Confirm terminal completion or
|
||||
Before `finish`, inspect writer handles, including the docs child. Confirm completion or
|
||||
termination before another writer runs; timeout or cancellation acknowledgment
|
||||
alone means STOP until confirmed.
|
||||
|
||||
@@ -677,30 +679,28 @@ files and CI. Pass each to `finish` as `--build`. If none exists, record not app
|
||||
the inspected sources. A missing prerequisite or failed build stops shipping:
|
||||
report **Build failed or prerequisite missing**, with the command, error and needed
|
||||
repair. Never invent a substitute command.
|
||||
**If blocked:** Repair it, then repeat stage 1. After it passes, continue
|
||||
to stage 2; treat any content repair as a behavioral change there.
|
||||
**If blocked:** repair it, repeat stage 1, then continue to stage 2: a content repair is behavior there.
|
||||
|
||||
### 2. Choose the change route
|
||||
|
||||
Capture the current tree with `$GSTACK_ROOT/bin/gstack-wtree`. Inspect
|
||||
`git diff <reviewed-tree> <current-tree>` against the snapshot saved before Step 12.
|
||||
Missing snapshots block this comparison, regardless of HEAD equality.
|
||||
`finish` runs `git diff <reviewed-tree> <current-tree>` (`--reviewed-tree`, saved before Step 12,
|
||||
against `$GSTACK_ROOT/bin/gstack-wtree`) and prints `ROUTE:`. No saved tree: pass `review_binding.end_wtree` from Step 11.5's bound Step 9 record;
|
||||
with none, insert `9 → 10 → 11 → 11.5`.
|
||||
|
||||
Classify the comparison in this order:
|
||||
Its `STOP:` names the route:
|
||||
|
||||
1. **Behavior, tests or build inputs changed:** Prompts/templates count as behavior.
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17, then stop this step.
|
||||
This repair excludes Step 14.5 because the rebuild can change generated docs.
|
||||
Step 16 restarts at stage 1: rebuild and compare again before stage 3 decides
|
||||
documentation freshness. Further repairs use the same work list. A STOP naming a scoped-review packet
|
||||
Insert `5–11.5 → 12–14 → 16` before the pending Step 17. It excludes Step 14.5 (a rebuild
|
||||
can change generated docs; compare before stage 3) and Step 15 (`finish` STOPs on an uncommitted
|
||||
non-release file: commit it by Step 15's rules, then rerun). A STOP naming a scoped-review packet
|
||||
instead takes its fix-check and `--context-reviewed` rerun; a blocking finding is this item.
|
||||
2. **Only authored docs or release metadata changed:** Keep Step 8's original child
|
||||
report and counts. Recheck affected plan items using their recorded verification
|
||||
and append current evidence to the invocation record. If a classification is no
|
||||
longer supported, run Step 8's audit and decision gates only, then return to
|
||||
Step 16 stage 1. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** Continue to stage 3
|
||||
without a new code review.
|
||||
Step 16 stage 1; else rerun with `--docs-rechecked`. Never edit the child's counts yourself.
|
||||
3. **No changes, or the docs-only checks still support the plan:** `finish` continues to
|
||||
stage 3 without a new code review.
|
||||
|
||||
### 3. Resolve documentation freshness
|
||||
|
||||
@@ -732,34 +732,30 @@ Never run a third audit. Child return is not acceptance.
|
||||
Freeze inputs through verification and push. Run declared docs/link/generated-file
|
||||
checks; report any that are unavailable.
|
||||
|
||||
**Reuse a check when its inputs match.** Compare hashes or complete bytes of its
|
||||
saved and current consumed files, fixtures, dependencies and execution parameters.
|
||||
Changed or unknown dependencies require a rerun. For model judges, compare the complete
|
||||
expanded request, rubric, parameters and builder/runtime dependencies. Cite the original
|
||||
command, result/counts, timestamp and log, never resample. Mandatory reviews still run.
|
||||
**Reuse a check when its inputs match.** Same consumed files, fixtures, dependencies
|
||||
and parameters (for a model judge, the complete expanded request and rubric); unknown means
|
||||
rerun. Cite the original command, result, timestamp and log; never resample. Mandatory reviews still run.
|
||||
|
||||
**Check each test lane's receipt as well.** Use its actual Step 5 label/command:
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`. Inspect changes since the run;
|
||||
`--allow-paths` exempts only release metadata. A `package.json` version-only edit
|
||||
can qualify; scripts, dependencies and runtime configuration require live tests.
|
||||
Uncertain edits cannot be exempted. Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review; a Step 14 TODOS.md edit reruns them. Use this example only once
|
||||
every allowed edit is release metadata:
|
||||
**Check each test lane's receipt as well.** `finish` checks every `--lane` as
|
||||
`--label <lane> --expect-cmd '<exact Step 5 command>'`, like this example:
|
||||
|
||||
```bash
|
||||
[ -d "${GSTACK_ROOT:-/-}/bin" ]&&[ -d "$GSTACK_ROOT/lib" ]||{ _r=$(git rev-parse --show-toplevel 2>/dev/null)/.factory/skills/gstack;[ -d "$_r/bin" ]||_r=~/.factory/skills/gstack;[ -d "$_r/bin" ]||{ echo "gstack: no install found (tried $_r). Fix: ./setup --host factory from your gstack checkout; ./setup --status shows it.">&2;exit 1;};GSTACK_ROOT=$_r;}
|
||||
$GSTACK_ROOT/bin/gstack-evidence check --label tests --expect-cmd '<tests>' --label vitest --expect-cmd '<vitest>' --max-age 24 --allow-paths CHANGELOG.md,VERSION,package.json,agents-digest/gstack-AGENTS.md
|
||||
```
|
||||
|
||||
`--allow-paths` exempts only release metadata (in `package.json`, only a version edit). Docs, TODO edits, new/generated tests and fixes
|
||||
make evidence STALE even without a new code review.
|
||||
|
||||
| Receipt result | Next action |
|
||||
|---|---|
|
||||
| FRESH (exit 0) | Cite the label, exit, timestamp, log and `tests_ran`. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `$GSTACK_ROOT/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once. Handle failures as described below. |
|
||||
| STALE/MISSING: changed content, command or age, or no proven run | Run `$GSTACK_ROOT/bin/gstack-evidence run --label <lane> -- '<command>'`, read the result and recheck once (`finish` does; a CI-mapped lane is carried, else `EVIDENCE: DEFERRED`). Still not FRESH: a failed lane. |
|
||||
| ZERO-RUN: the receipt's `tests_ran` is 0 | STALE-equivalent: use Step 5's ZERO-RUN triage (a failed lane), never FRESH, even with exit 0. |
|
||||
| `tests_ran: unknown` | Non-blocking: keep the exit-0 verdict, cite the lane as `count unavailable`. Never record it as ZERO-RUN or as a counted pass. |
|
||||
| Only receipt storage/readback failed | Prove unchanged final content, the same command and valid age from the successful run's evidence. Cite its exact command, exit, timestamp and log as **ledger unavailable**, never FRESH. Without that proof, use STALE/MISSING. |
|
||||
|
||||
No test lanes: require Step 5's explicit untested-scope approval for final content,
|
||||
No test lanes: rerun with `--no-lanes-approved` on Step 5's explicit untested-scope approval,
|
||||
or run Steps 5–15, including the no-tests decision, then return to Step 16 stage 1.
|
||||
Report the gap, never FRESH; builds must pass.
|
||||
|
||||
@@ -771,7 +767,8 @@ does not authorize a third attempt.
|
||||
### 5. Report, then push
|
||||
|
||||
`finish` made the release commit. Commit only verified outputs stage 1's
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit.
|
||||
builds regenerated, grouped as in Step 15; never create an empty commit. It is
|
||||
content-preserving: no restart.
|
||||
Preserve unrelated user files.
|
||||
|
||||
Paste build/docs/test results. Reuse waivers only for the same verified
|
||||
@@ -786,7 +783,7 @@ its records:
|
||||
- Each test lane's `tests_ran` (N, ZERO-RUN or `count unavailable`).
|
||||
Write this report in the auditor's posture: this session's own gate edits are
|
||||
evidence for the reader to examine, not positions to defend; a kept gate
|
||||
states its reason and nothing more. Otherwise continue to Step 17.
|
||||
states its reason and nothing more. Then continue to Step 17.
|
||||
|
||||
---
|
||||
|
||||
@@ -890,7 +887,8 @@ It checks the branch, the offer, the gate above (`--gate-open <n>`; `--gate-open
|
||||
even with unchanged content before returning to Step 17. Never bypass failed guards.
|
||||
Never force-push. Only a successful push or verified `ALREADY_PUSHED` proceeds.
|
||||
|
||||
Continue to Step 18. No documentation writer runs after push.
|
||||
After `EVIDENCE: DEFERRED`, run Step 5's `gstack-ship-release accept`; a `STOP:` there
|
||||
is a failed lane (stage 4). Continue to Step 18. No documentation writer runs after push.
|
||||
|
||||
---
|
||||
|
||||
@@ -918,8 +916,7 @@ echoed): an open PR at HEAD takes pr-body's existing-PR path (body and title onl
|
||||
|
||||
## Step 20: Persist ship metrics
|
||||
|
||||
Log metrics for `/retro` through `gstack-review-log`; it handles project/branch paths,
|
||||
JSON validation, storage and sync and takes **no path argument**.
|
||||
Log metrics for `/retro` through `gstack-review-log`; it takes **no path argument**.
|
||||
|
||||
```bash
|
||||
[ -d "${GSTACK_ROOT:-/-}/bin" ]&&[ -d "$GSTACK_ROOT/lib" ]||{ _r=$(git rev-parse --show-toplevel 2>/dev/null)/.factory/skills/gstack;[ -d "$_r/bin" ]||_r=~/.factory/skills/gstack;[ -d "$_r/bin" ]||{ echo "gstack: no install found (tried $_r). Fix: ./setup --host factory from your gstack checkout; ./setup --status shows it.">&2;exit 1;};GSTACK_ROOT=$_r;}
|
||||
@@ -969,7 +966,7 @@ $GSTACK_ROOT/bin/gstack-ship-receipt result --pr <pr-number> # handoff: --body
|
||||
|
||||
It binds the receipt to HEAD, writes the run record, prints `GSTACK_RESULT: skill=ship
|
||||
status=complete head=<sha> run=<dir>`; `QUEUE_RECEIPT_STALE`: HEAD moved past the receipt (rewrite,
|
||||
repost, rerun). A run that STOPs early ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
repost, rerun). A STOP before Step 19 publishes ends with `GSTACK_RESULT: skill=ship status=refused run=-`.
|
||||
|
||||
---
|
||||
|
||||
@@ -985,7 +982,6 @@ hand-roll VERSION/package.json writes.
|
||||
|
||||
Follow the numbered gates and their explicit exceptions.
|
||||
|
||||
- **Never force push.** Use regular `git push` only.
|
||||
- **An early Greptile PR stays up.** A stop after Step 6.5 opened it leaves the draft
|
||||
open with one comment saying why (greptile-early section); never close it.
|
||||
- **Use the configured version file's format** (4-digit for VERSION); under NO_VERSION,
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"sha":"c623d65c4c53054108ac0166773c89233d76a25b0d35eb72d1c546f7bec4bdc9","replay":"GSTA-258-C"}
|
||||
{"sha":"09f01971dfc2d174ba739a6c5e745b2663e08bf1c22a19671acbfb6995f70640","replay":"GST-1346"}
|
||||
@@ -0,0 +1 @@
|
||||
{"replay":"GST-1346","justification":"GST-1346 brief-identity no-loss check (the brief-body test below): every reviewer brief lib/review-brief.ts cuts from ship/sections/adversarial.md is byte-identical to its pinned body, so no reviewer sees a changed byte; only lead instructions outside the cut spans changed, to say what the code already does: Step 11's Codex passes and CODEX_MODE lines follow the plan's DISPATCH lines (ship/DRIVER.md runs only the voices the last full-pass plan lists), the NEXT: voices outcome names its next step, and the learnings-refresh lines were trimmed to keep the file's size; ship/sections/review-army.md and review/sections/adversarial.md are unchanged"}
|
||||
@@ -24,8 +24,8 @@ test('adversarial outside failures retain the required native pass without dupli
|
||||
expect(preflight).not.toMatch(/fall(?:ing)? back to (?:a|the) .*subagent/i);
|
||||
const output = generateAdversarialStep(ctx);
|
||||
expect(output).toContain(skillName === 'ship' ? 'adversarial subagent (on `DISPATCH: adversarial-native`)' : 'adversarial subagent (always runs)');
|
||||
expectMentions(output, [['do not', 'dispatch', 'retain']], 'output');
|
||||
expect(output.match(/Retain the required native pass without duplicating it; it cannot complete outside coverage\./g)).toHaveLength(2);
|
||||
expectMentions(output, [skillName === 'ship' ? ['native', 'follows', 'DISPATCH'] : ['do not', 'dispatch', 'retain']], 'output');
|
||||
expect(output.match(skillName === 'ship' ? /A dispatched native pass runs once either way; outside output cannot complete it\./g : /Retain the required native pass without duplicating it; it cannot complete outside coverage\./g)).toHaveLength(2);
|
||||
expect(output).not.toContain("Use the caller's fallback");
|
||||
expectMentions(output, [['only', 'non-blocking', 'adversarial']], 'output');
|
||||
expect(output).toContain('GATE: MISSING COVERAGE');
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"bytes": -24,
|
||||
"why": "clarity-only repair of five judge-flagged ship workflow conflicts (GST-1346)"
|
||||
}
|
||||
Reference in new issue
Block a user