v1.92.40.0 ship-budget: a subagent's /ship cost says it is the root counter, an upper bound (GST-467) (#3696)

* gstack-ship-budget start --meter-scope self|tree: label tree-scoped cost lines, refuse METER_SCOPE_PARENT (GST-467)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ship-budget: a ledger rebuilt from its record keeps meter_scope=tree; document the cap on a tree run

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ship-budget: a re-start asking for tree upgrades an open run; tree labels reach the return file, drift and reconcile lines; reading-missing fix names the subagent route

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs/ship-budget.md: GSTACK_SHIP_SUBAGENT=1 stands in for --subagent only

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>
This commit is contained in:
Garry Tanandcapy-ai[bot] authored and GitHub committed 2026-11-01 20:45:39 +00:00
1 parent 77fe28c397
commit 6ffbfb8ef1
15 files changed
+248 -25

No files matched your search

+9 -2
View File
@@ -76,8 +76,14 @@ one program measure nothing: Capy books a call after its program ends.
A jam's own counter includes its own subagents, outside voices too (measured 2026-10-30: +10.92M
across a six-reader dispatch with two ~0.35M parent calls between). `"this"` is the root thread,
whose counter also holds every sibling tree, so a subagent running /ship passes its own jam id;
a root thread's own jam id is its `"this"`. A Capy handoff child cannot read its own jam id, so it
whose counter also holds every sibling tree. A subagent running /ship cannot read its own jam id, so it
reads `"this"` and starts with `--subagent --reading-from this --meter-scope tree` (`GSTACK_SHIP_SUBAGENT=1` in its
brief stands in for `--subagent` only; `--reading-from this` is still required): the run is tree-scoped, and every BUDGET, NOTE, BUDGET_FINAL
and BUDGET_TIMELINE line it prints is followed by `METER: tree (root counter, upper bound)`. A
subagent that asks for `--meter-scope self` while reading `"this"` is refused
(`METER_SCOPE_PARENT`). A `--token-cap` on a tree-scoped run stops on that upper bound, so sibling
lanes count against it. Exact per-run cost comes from a root replay thread: a root thread that runs
only that /ship, whose `"this"` is its own counter. A root thread's own jam id is its `"this"`. A Capy handoff child cannot read its own jam id, so it
verifies with no reading and prints `METER: parent`; the parent's handoff and reconcile readings,
taken on its own counter (which holds the child), measure it.
@@ -286,6 +292,7 @@ stop rules) before claiming a saving from the cap or from delegation.
[BUDGET_CAP_REACHED](troubleshooting.md#budget-cap-reached) ·
[BUDGET_READING_MISSING](troubleshooting.md#budget-reading-missing) ·
[METER_SCOPE_PARENT](troubleshooting.md#meter-scope-parent) ·
[BUDGET_READING_REJECTED](troubleshooting.md#budget-reading-rejected) ·
[BUDGET_METER_UNAVAILABLE](troubleshooting.md#budget-meter-unavailable) ·
[BUDGET_LEDGER_INVALID](troubleshooting.md#budget-ledger-invalid) ·
+12
View File
@@ -1942,6 +1942,18 @@ owner's call: run the printed `RECOVER:` line; its resume needs
**Fix.** In the execute program that runs the command, read
`(await tools.thread.get({ thread_id: "<your own jam id>" })).cost.tokens` and pass it as `--reading <n>`.
<a id="meter-scope-parent"></a>
### `gstack-ship-budget: ... (METER_SCOPE_PARENT)`
**Meaning.** `start` was told the run is a subagent (`--subagent` or `GSTACK_SHIP_SUBAGENT=1`) reading
`"this"` (`--reading-from this`), the root thread's counter, which also holds every sibling lane, and
asked for `--meter-scope self`. A self scope would print that counter as the run's own cost. Exit 2;
no run started.
**Fix.** Start with `--meter-scope tree`. Every cost line then prints
`METER: tree (root counter, upper bound)`. Exact per-run cost comes from a root replay thread
(`docs/ship-budget.md`).
<a id="budget-reading-rejected"></a>
### `gstack-ship-budget: ... (BUDGET_READING_REJECTED)`