Skip to content

Add HeadsDown call renderer#6

Merged
jsmestad merged 1 commit into
mainfrom
agent-control/901-cli-call-renderer
Apr 25, 2026
Merged

Add HeadsDown call renderer#6
jsmestad merged 1 commit into
mainfrom
agent-control/901-cli-call-renderer

Conversation

@jsmestad
Copy link
Copy Markdown
Contributor

TL;DR

Adds the CLI slice of the shared HeadsDown call renderer so terminal output can render canonical backend calls without inventing local vocabulary. This is one repo-specific slice of #901, so the issue stays open for iOS, Android, and Pi.

Part of headsdownapp/heads_down#901

Context

Gate A requires every client to render canonical HeadsDown calls consistently. The app/web slice is in headsdownapp/heads_down#966. This PR adds the equivalent display contract helper for the Rust CLI.

The CLI helper is intentionally display-only. It does not compute a call from status, availability, proposals, or local policy. It accepts a backend call key plus explicit unknown-call signals and turns that into terminal-ready copy and CTA metadata.

Changes

  • Adds src/contract/calls.rs with a CallDisplay and CallCta model for CLI rendering.
  • Covers every canonical call key: good_to_run, keep_it_tight, not_worth_starting_now, off_the_clock, rabbit_hole_detected, ready_to_resume, all_contained, and needs_your_yes.
  • Keeps backend action keys separate from non-mutating UI intents.
  • Handles unknown future call keys conservatively:
    • needs_your_yes for action, risk, boundary, or ambiguous signals.
    • keep_it_tight for limit, scope, or validation uncertainty.
    • all_contained only when no action is needed and the run is explicitly in bounds.
  • Adds terminal formatting for call output.
  • Exports the calls contract module through src/contract/mod.rs.

Verification

Run these commands from the CLI worktree:

  1. cargo fmt
  2. cargo test contract::calls
  3. cargo test

Validation already run:

  • cargo test contract::calls, 10 tests passed.
  • cargo test, 79 tests passed across unit, backend parity, GraphQL contract, and integration tests.

Acceptance Criteria Addressed

  • CLI has human-readable labels for every canonical call key. ✅
  • Unknown call key fallback uses safe language and does not crash for the CLI slice. ✅
  • Renderer does not compute calls locally. It renders backend/contract values and explicit fallback signals. ✅
  • Backend action keys remain separate from UI intents. ✅

Still Remaining For #901

  • iOS call display model for every canonical call key.
  • Android call display model for every canonical call key.
  • Pi prompt/output copy for every canonical call key.

@jsmestad jsmestad merged commit d3c8c7b into main Apr 25, 2026
3 checks passed
@jsmestad jsmestad deleted the agent-control/901-cli-call-renderer branch April 25, 2026 15:25
jsmestad added a commit to headsdownapp/headsdown-pi that referenced this pull request Apr 25, 2026
# TL;DR
Adds the Pi slice of the shared HeadsDown call renderer so Pi prompt and
tool output can render canonical backend calls without inventing local
vocabulary. This is one repo-specific slice of
headsdownapp/heads_down#901, so the issue stays open for iOS and
Android.

Part of headsdownapp/heads_down#901

## Context
Gate A requires every client to render canonical HeadsDown calls
consistently. The app/web slice is in headsdownapp/heads_down#966, and
the CLI slice merged in headsdownapp/headsdown-cli#6. This PR adds the
equivalent display contract helper for the Pi package.

The Pi helper is display-only. It does not derive calls from
availability, status, proposals, or local policy. It accepts a backend
call key plus explicit unknown-call signals and returns prompt-ready
copy with backend action keys separated from UI intents.

## Changes
- Adds `extensions/headsdown/call-renderer.ts` with canonical HeadsDown
call rendering for Pi.
- Covers every canonical call key: `good_to_run`, `keep_it_tight`,
`not_worth_starting_now`, `off_the_clock`, `rabbit_hole_detected`,
`ready_to_resume`, `all_contained`, and `needs_your_yes`.
- Adds prompt/output formatting that labels action transport clearly,
for example `action=keep_queued` vs `ui_intent=review_request`.
- Handles unknown future call keys conservatively:
- `needs_your_yes` for action, approval, risk, boundary, spend, external
side effect, escalation, or ambiguous signals.
- `keep_it_tight` for limit, scope, validation, or low-confidence
uncertainty.
- `all_contained` only when no action is needed and the run is
explicitly in bounds.
- Adds focused Vitest coverage for canonical rendering, GraphQL
enum-style key normalization, unknown fallback precedence,
server-provided copy, and prompt formatting.

## Verification
Run these commands from the Pi package worktree:

1. `npm run format`
2. `npm test -- test/call-renderer.test.ts`
3. `npm run typecheck`
4. `npm test`
5. `npm run lint`

Validation already run:
- `npm test -- test/call-renderer.test.ts`, 12 tests passed.
- `npm test`, 139 tests passed.
- `npm run typecheck`, passed.
- `npm run lint`, passed.
- `git diff --check`, passed.

## Acceptance Criteria Addressed
- Pi has prompt/output copy for every canonical call key. ✅
- Unknown call key fallback uses safe language and does not crash for
the Pi slice. ✅
- Renderer does not compute calls locally. It renders backend/contract
values and explicit fallback signals. ✅
- Backend action keys remain separate from UI intents. ✅

## Still Remaining For #901
- iOS call display model for every canonical call key.
- Android call display model for every canonical call key.
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