Skip to content

grants: ✨ Counted judge grants, cross-tree adoption, and downstream spending - #277

Merged
yasyf merged 2 commits into
mainfrom
feat/grants-owner-asks
Oct 3, 2026
Merged

yasyf merged 2 commits into
mainfrom
feat/grants-owner-asks

Conversation

@yasyf

@yasyf yasyf commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Why

The owner asked for these changes to the grants design:

1, but allow it to be specified as multi-spend, and it should use cc-slack, you can build whatever daemon stuff you need into there

Allow cross-root sharing by agents

What

  • Add GrantVerdict.uses to mint counted grants from the owner's quoted words.
  • Use one approval key for standing, counted, and one-shot mints. The same words resolve to one grant per kind and tree, preserving its remaining budget.
  • Add capt-hook grant adopt, which agents can run to share a grant across roots. Both roots spend from the same budget. The adoptions table logs the destination tree, timestamp, session, and agent.
  • Add Grants(spent_by=...) to name a covering grant without reserving a use, and capt-hook grant spend to commit the use downstream. The command returns the grant and remaining uses as JSON, or exits non-zero with a reason when it cannot spend. The first spender is the cc-slack daemon, with integration in a follow-up monorepo PR.
  • Make grant show lead with remaining uses or the reason the grant is unusable, followed by its record, adoptions, and spends.
  • Update the grants guide with counted grants, adoption, and downstream spending.

Tests

  • Add four tests in tests/test_grants.py covering counted grants, adoption with a shared budget, downstream spending through the CLI, and refusal to spend from another tree without adoption.
  • 635 tests passed across tests/test_grants.py, tests/test_dispatch.py, and tests/test_public_api.py.

…pending

Context: the owner approved the grants design with changes: multi-spend, Slack enforcement in cc-slack, and agent cross-root sharing.
Summary: GrantVerdict.uses mints an N-use grant from quoted words; capt-hook grant adopt shares a grant into another tree with a logged adoption; Grants(spent_by=...) names a grant without reserving and capt-hook grant spend lets the downstream system pay.
Motivation: cc-slack must enforce and spend Slack grants itself, and lanes in other roots must use what the owner gave the root.
Details: one approval now keys standing, counted, and one-shot mints alike, so the same words never mint twice; grant show leads with the remaining uses.
… name unknown grants

Context: the cc-slack lane consuming #277 found three defects.
Summary: the inline-test LLM stub fills None-default fields with None; a spent_by check lets a one-shot retry of the same payload through; grant spend on an unknown id exits with its reason.
Motivation: the stub filled GrantVerdict.uses with an empty string, failing every judge-stubbed hook test, and a lost reply could never be retried through cc-slack.
Details: two tests cover the retry and the unknown id; Slack hook (399) and general pack (941) inline tests pass.
@yasyf
yasyf merged commit 86287e5 into main Oct 3, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant