mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
* ship: poll readers in-program, never wait on wakes; 32 KB returns; gated fix program; unattended push defers the guard offer; calls meter (GSTA-167 calls PR 1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (inventory lib/ship-release.ts as a GSTACK_SESSION_KIND reader) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship-budget): document calls and dotted --step notes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ship: judge treats a missing severity as invalid; Capy passes rendered briefs via cat (replay C1-34 breaks) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: keep the Capy skill under its context budget after the main merge Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
58 lines
4.0 KiB
TypeScript
Executable File
58 lines
4.0 KiB
TypeScript
Executable File
#!/usr/bin/env -S bun --no-env-file --config=/dev/null
|
|
/**
|
|
* gstack-ship-budget — the /ship token budget and fresh-context handoff
|
|
* (docs/ship-budget.md). An admission cap: no step or dispatch starts unless
|
|
* used + open reservations + unknown + its projection + the tail and stop
|
|
* reserve fit under the cap. --mode observe (ship/DRIVER.md) only records:
|
|
* note at each program's end, and the cap is one hard stop. Every --reading
|
|
* takes --credits <cost.credits> beside it.
|
|
*
|
|
* start --record <path> [--token-cap <n|none>] [--mode admit|observe] [--meter capy|claude|estimate] [--reading <n>] [--credits <c>]
|
|
* [--prior-reading <n>] [--session <id>|--nonce <v>] [--reserve <n>] [--delegate auto|never] [--calibration <file>] [--ledger <path>]
|
|
* note --run|--record --step <id> [--label <text>] --reading <n> [--credits <c>] [--dispatched-at <n> [--dispatched-credits <c>] --readers <k>]
|
|
* check --run <id>|--record <path> --step <id> --next <id|dispatch:<role>[,<role>...]> [--reading <n>] [--credits <c>] [--prior-reading <n>]
|
|
* [--returned <id>[,<id>...]] [--runtime-lines <n>] [--dispatched-at <n> --readers <k>]
|
|
* settle --run|--record --reservation <id> [--unknown] [--reading <n>] [--credits <c>] [--dispatched-at <n> --readers <k>]
|
|
* release --run|--record --reservation <id>
|
|
* handoff --run|--record --from <step> --to <step> --base origin/<base> [--reviewed-tree <t>] [--trail <f> --trail-run <id>]
|
|
* [--sub-cap <n>] [--reading <n>] [--child-session <id>]
|
|
* launch --in <brief> (Claude Code: background headless child with explicit permissions)
|
|
* verify-handoff --in <brief> [--reading <n>] [--session <id>]
|
|
* return --run <child> --to <step> [--changed <sections>] [--status complete|refused|incomplete] [--reading <n>]
|
|
* reconcile --run|--record (--return <file>|--handoff <sha256>) [--reading <n>]
|
|
* resume --record <path>|--run <id> [--reading <n>] [--meter <m>] [--session <id>] [--token-cap <n> --approved-by <who> --words <text>]
|
|
* [--rebuild-from-record]
|
|
* close --run|--record [--reading <n>] [--approved-by <who> --words <text>]
|
|
* calls --events <file> [--since <iso>] [--until <iso>] (the host's transcript items: one CALLS: line, lib/ship-calls.ts)
|
|
*
|
|
* Exit: 0 continue/delegate · 3 stop (the next step does not start) · 2 usage
|
|
* or validation (stderr). Logic: lib/ship-budget.ts, lib/ship-budget-cli.ts,
|
|
* lib/ship-handoff.ts.
|
|
*/
|
|
import { BudgetError } from '../lib/ship-budget';
|
|
import { cmdCalls, cmdCheck, cmdClose, cmdNote, cmdResume, cmdSettle, cmdStart, type Outcome } from '../lib/ship-budget-cli';
|
|
import { cmdHandoff, cmdLaunch, cmdReconcile, cmdReturn, cmdVerifyHandoff } from '../lib/ship-handoff';
|
|
|
|
const [command, ...rest] = process.argv.slice(2);
|
|
const ctx = { env: process.env, cwd: process.cwd() };
|
|
const commands: Record<string, () => Outcome> = {
|
|
start: () => cmdStart(rest, ctx), note: () => cmdNote(rest, ctx), check: () => cmdCheck(rest, ctx), settle: () => cmdSettle(rest, ctx), release: () => cmdSettle(rest, ctx, true),
|
|
handoff: () => cmdHandoff(rest, ctx), launch: () => cmdLaunch(rest, ctx), 'verify-handoff': () => cmdVerifyHandoff(rest, ctx), return: () => cmdReturn(rest, ctx),
|
|
reconcile: () => cmdReconcile(rest, ctx), resume: () => cmdResume(rest, ctx), close: () => cmdClose(rest, ctx), calls: () => cmdCalls(rest),
|
|
};
|
|
if (!command || command === '--help' || command === '-h' || !commands[command]) {
|
|
const lines = (await Bun.file(import.meta.path).text()).split('\n');
|
|
const text = lines.slice(2, lines.indexOf(' */')).map(l => l.replace(/^ \* ?/, '')).join('\n');
|
|
(command && command !== '--help' && command !== '-h' ? console.error : console.log)(text);
|
|
process.exit(command && command !== '--help' && command !== '-h' ? 2 : 0);
|
|
}
|
|
try {
|
|
const out = commands[command]!();
|
|
if (out.stdout.length) console.log(out.stdout.join('\n'));
|
|
process.exit(out.exit);
|
|
} catch (e) {
|
|
if (!(e instanceof BudgetError)) throw e;
|
|
if (e.exit === 3) console.log(e.message); else console.error(e.message);
|
|
process.exit(e.exit);
|
|
}
|