@rosthq/cli 0.5.31 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -41637,7 +41637,7 @@ The Compass is drafted, then activated by a human through supersession.
41637
41637
  order: 20,
41638
41638
  title: "Responsibility Graph playbook",
41639
41639
  summary: "How to build a functions-first graph with seats, owners, Stewards, vacancies, and clean authority.",
41640
- version: "2026-06-20.2",
41640
+ version: "2026-06-30.1",
41641
41641
  public: true,
41642
41642
  audiences: ["human", "cli", "mcp", "in_app_agent"],
41643
41643
  stages: ["graph_design", "staffing"],
@@ -41684,6 +41684,8 @@ Each entry opens the same conservative setup flow \u2014 seat placement, Steward
41684
41684
 
41685
41685
  The graph canvas fits the whole structure into the frame when it opens and refits whenever the frame changes \u2014 opening a side panel, resizing the window, or rotating a phone. Zoom moves between three altitudes: a constellation of seat dots when zoomed out, seat cards at the working zoom, and charter detail when zoomed in. Seat cards stay legible on small screens, and the canvas is the one always-dark surface in the otherwise light app. Search the toolbar to fly to any seat by name.
41686
41686
 
41687
+ Seat cards name their active occupants. When a seat has more than one occupant, the card shows the human/agent breakdown instead of only a count, and mixed human-plus-agent staffing is labelled. Use the occupants control on that card to open the detail panel, where each occupant is listed as either the human accountable for the seat or the agent executor, with the Steward chain shown for agent accountability.
41688
+
41687
41689
  The graph is also where you land after onboarding \u2014 it is the mission control for the company, not a separate dashboard. Switch lenses from the toolbar to recolour the same structure four ways:
41688
41690
 
41689
41691
  - **Structure** \u2014 seat type and reporting lines.
@@ -42148,7 +42150,7 @@ Decisions should be recorded as human decisions. Handoffs should attach to seats
42148
42150
  order: 45,
42149
42151
  title: "How agents work",
42150
42152
  summary: "How {{brand}} agents operate inside seats, use Charters, report work, and escalate beyond authority.",
42151
- version: "2026-06-27.1",
42153
+ version: "2026-06-30.1",
42152
42154
  public: true,
42153
42155
  audiences: ["human", "cli", "mcp", "in_app_agent"],
42154
42156
  stages: ["staffing", "operating_rhythm"],
@@ -42246,7 +42248,7 @@ Beyond each seat's own manifest, the company can set one ceiling on how much an
42246
42248
 
42247
42249
  ## What humans should review
42248
42250
 
42249
- The Agents page shows fleet health first: live state, recent runs, failed runs, open held actions, last activity, cost, and the next operator action. It also shows configuration completeness for each staffed agent seat: Steward chain, lane or runtime substrate, vaulted credentials, granted tools, model config, sandbox dry run, and go-live state, each with a remediation link when incomplete. A seat's Trust Card drills into the same facts: run history, one-run detail, tool-call outcomes, product-visible errors, transcript references, loaded Skill versions, and held confirmations or escalations. Open confirmations stay visible until they are decided or expire, even when they are older than the default activity window. Approving or rejecting a held confirmation from the seat page is scoped to that seat; rejection can include a short reason.
42251
+ The Agents page shows fleet health first: live state, work evidence, failed runs, open held actions, cost, and the next operator action. Work evidence distinguishes fresh real runs, stale runs, no completed run yet, queued or running work orders, and recent failures. A failure link opens the failed run itself; queued or stale rows route the operator to the seat's agent operations instead of pretending there is a hidden run to inspect. The page also shows configuration completeness for each staffed agent seat: Steward chain, lane or runtime substrate, vaulted credentials, granted tools, model config, sandbox dry run, and go-live state, each with a remediation link when incomplete. A seat's Trust Card drills into the same facts: run history, one-run detail, tool-call outcomes, product-visible errors, transcript references, loaded Skill versions, and held confirmations or escalations. Open confirmations stay visible until they are decided or expire, even when they are older than the default activity window. Approving or rejecting a held confirmation from the seat page is scoped to that seat; rejection can include a short reason. For a live agent, the seat page's agent operations panel can queue one immediate governed run through the same \`agent.run_now\` command path used by CLI and MCP; it does not expand authority or change the saved schedule.
42250
42252
 
42251
42253
  Review the first dry runs, fleet overview, tool-call audit rows, escalations, deliverables, and Signal impact. A seat's completed-work area combines explicit deliverables, work-log evidence, and successful run summaries into one operator-facing trail with safe links labelled as internal, Linear, GitHub, or external. The fleet view at \`/agents\` shows every staffed agent seat at a glance; the agent-native equivalents are \`{{cli}} command agent.list_fleet --json '{}'\` / \`rost_list_agent_fleet\` for the compact overview, and \`{{cli}} agent fleet-digest --json\` / \`agent.fleet_digest\` / \`rost_get_dogfood_fleet_health_digest\` for the daily dogfood evidence bundle. The digest returns live/idle state, 24h/7d turns, 7d/30d spend, recent failed runs, unresolved product errors, failed notifications, and a next action per seat.
42252
42254
 
@@ -42259,7 +42261,7 @@ Use the lower-level commands after health names a finding: \`agent.get_run\` for
42259
42261
  order: 46,
42260
42262
  title: "Tool access and vault",
42261
42263
  summary: "How to give agents access to tools without exposing raw credentials or expanding authority by accident.",
42262
- version: "2026-06-30.1",
42264
+ version: "2026-06-30.2",
42263
42265
  public: true,
42264
42266
  audiences: ["human", "cli", "mcp", "in_app_agent"],
42265
42267
  stages: ["staffing"],
@@ -42317,7 +42319,7 @@ Google can be connected from Settings once the workspace OAuth app is configured
42317
42319
 
42318
42320
  CLI and MCP can inspect connector readiness without seeing secrets: \`integration.list\` / \`rost_list_integrations\` lists connected providers and health metadata, \`integration.status\` / \`rost_get_integration_status\` reads one provider by id or name, and \`integration.test\` / \`rost_test_integration_connection\` runs the installed provider-specific health check. For Google, the test refreshes the vaulted OAuth credential and reads the Gmail profile, then records only account, scope, and health metadata.
42319
42321
 
42320
- \`integration.readiness\` / \`{{cli}} integration readiness --provider google --json\` / \`rost_check_integration_readiness\` returns the same setup checklist Settings shows: OAuth env and callback status, tenant connection state, granted scopes, latest test state, the demo-safe partner path, external verification/CASA caveats, handler availability, and the next Linear issue or action. The checklist is metadata-only. It never returns access tokens, refresh tokens, client secrets, vault refs, or raw provider responses.
42322
+ \`integration.readiness\` / \`{{cli}} integration readiness --provider google --json\` / \`rost_check_integration_readiness\` returns the operator setup checklist: app configuration status, tenant connection state, granted scopes, latest test state, the demo-safe partner path, external verification/CASA caveats, handler availability, and the next operator action. The checklist is metadata-only. It never returns access tokens, refresh tokens, client secrets, vault refs, or raw provider responses. Settings deliberately keeps the live Google card narrower: connected account, last successful test, granted capabilities, and connect/reconnect/test actions.
42321
42323
 
42322
42324
  ## One write-only credential flow across every surface
42323
42325
 
@@ -42401,7 +42403,7 @@ External connectors are being rolled out provider by provider, conservatively (r
42401
42403
  order: 48,
42402
42404
  title: "CLI and MCP installation guide",
42403
42405
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
42404
- version: "2026-06-30.2",
42406
+ version: "2026-06-30.6",
42405
42407
  public: true,
42406
42408
  audiences: ["human", "cli", "mcp", "in_app_agent"],
42407
42409
  stages: ["company_setup", "staffing"],
@@ -42509,6 +42511,8 @@ A headless agent cannot complete setup unattended. Two things always require a h
42509
42511
 
42510
42512
  Treat these as blocking prerequisites: the agent prepares the request and waits for the human approver.
42511
42513
 
42514
+ - **Secrets never travel through the CLI.** Raw-secret sinks (\`credential.ingress\`, \`tenant.anthropic_key.save\`) are refused on every CLI path \u2014 an ergonomic verb, \`--input\`, and \`{{cli}} command <id> --json\` all stop with guidance instead of accepting the secret, because a value in argv lands in shell history and process arguments before any redaction. Provide the secret through the vault-backed flow (web Settings or the integration connect flow); the CLI only ever carries the non-secret credential *name*, scope, and provider.
42515
+
42512
42516
  ## Placeholder legend
42513
42517
 
42514
42518
  Commands below use angle-bracket placeholders. The CLI prints the real, fully-resolved values at runtime \u2014 read them from the terminal, do not hand-construct them:
@@ -42524,9 +42528,10 @@ Commands below use angle-bracket placeholders. The CLI prints the real, fully-re
42524
42528
  A {{brand}} **account** (the human identity) is created with Google sign-in \u2014 in the browser at \`/signup\`, or headlessly via \`{{cli}} login --device\` (a human approves the code in any browser). A **company** (tenant) can then be created either way:
42525
42529
 
42526
42530
  - **Browser:** at \`/signup\`, name your company, then return to the CLI.
42527
- - **Headless (no browser step):** once logged in, run \`{{cli}} signup --company "<name>"\`. If the account has no active company yet, this provisions the first company for your session and makes it active, so \`{{cli}} onboard status\` and every other tenant-scoped command work immediately. This is the recommended path for an autonomous agent setting up from scratch.
42531
+ - **Headless first company (no browser step):** once logged in, run \`{{cli}} signup --company "<name>"\`. If the account has no active company yet, this provisions the first company for your session and makes it active, so \`{{cli}} onboard status\` and every other tenant-scoped command work immediately. This is the recommended path for an autonomous agent setting up from scratch.
42532
+ - **Additional entitled company:** from an existing active company session, run \`{{cli}} tenant create --company "<name>" [--json]\`. This creates a clean additional company only when the account has an active \`tenant.create.additional\` entitlement. A denied attempt returns a clean refusal and creates no tenant row.
42528
42533
 
42529
- If you run a tenant-scoped command before any company exists, the CLI tells you both options. \`{{cli}} signup --company\` is not a second-company creation command: running it again returns the active company, names the company you requested, and says that no new company was created. The default output is human-readable; add \`--json\` only when an automation needs the raw command output. To inspect or switch among companies you can already access, use \`{{cli}} tenants\` and \`{{cli}} use <tenant-slug-or-id>\`. Additional company creation is not exposed as a public self-serve CLI path in this milestone.
42534
+ If you run a tenant-scoped command before any company exists, the CLI tells you both first-company options. \`{{cli}} signup --company\` is not a second-company creation command: running it again returns the active company, names the company you requested, and says that no new company was created. The default output is human-readable; add \`--json\` only when an automation needs the raw command output. To inspect or switch among companies you can already access, use \`{{cli}} tenants\` and \`{{cli}} use <tenant-slug-or-id>\`.
42530
42535
 
42531
42536
  ## Install the CLI
42532
42537
 
@@ -42604,10 +42609,11 @@ This is the install/auth quickstart \u2014 it gets you logged in, MCP registered
42604
42609
  3. Create your company if you have none yet: \`{{cli}} signup --company "<name>"\` (no browser step)
42605
42610
  4. List tenants: \`{{cli}} tenants\`
42606
42611
  5. Select a tenant when needed: \`{{cli}} use <tenant-slug-or-id>\`
42607
- 6. Read the agent map: \`{{cli}} reference get agent-reference-map\` (the full canonical setup order lives here)
42608
- 7. Register MCP for the client (pick a scope \u2014 \`--scope\` is required): \`{{cli}} mcp install --client claude-code --scope tenant-admin\` for setup, or \`--scope seat --seat-id <id>\` for a narrower seat token
42609
- 8. Inspect onboarding: \`{{cli}} onboard status\`
42610
- 9. Get the guided agent prompt: \`{{cli}} onboard run\`
42612
+ 6. For an entitled additional clean company, create it from an active company session: \`{{cli}} tenant create --company "<name>"\`
42613
+ 7. Read the agent map: \`{{cli}} reference get agent-reference-map\` (the full canonical setup order lives here)
42614
+ 8. Register MCP for the client (pick a scope \u2014 \`--scope\` is required): \`{{cli}} mcp install --client claude-code --scope tenant-admin\` for setup, or \`--scope seat --seat-id <id>\` for a narrower seat token
42615
+ 9. Inspect onboarding: \`{{cli}} onboard status\`
42616
+ 10. Get the guided agent prompt: \`{{cli}} onboard run\`
42611
42617
 
42612
42618
  Or use the one-shot helper: \`{{cli}} init\` logs in when needed, optionally selects a tenant, installs MCP, and prints the onboarding prompt. It does not run every numbered step above (it does not create your company or call \`onboard status\`) \u2014 it gets you logged in, registered, and handed the onboarding prompt. As the first-run helper it defaults to a **tenant-admin** token (no seats exist yet), so unlike a direct \`mcp install\` it does not need \`--scope\`; pass \`--scope seat --seat-id <id>\` if you already have a seat to scope it to:
42613
42619
 
@@ -42791,6 +42797,7 @@ These are the security posture rules for operating after install \u2014 a checkl
42791
42797
  | \`{{cli}} login --device\` | Device-code login for a headless agent: prints a short code + URL, a human approves in any browser, the CLI polls until authorized \u2014 no browser session needed on the agent's machine. | User session | \`{{cli}} login --device\` |
42792
42798
  | \`{{cli}} logout\` | Clear the local CLI session. | Local session | \`{{cli}} logout\` |
42793
42799
  | \`{{cli}} signup [--company "<name>"] [--json]\` | With no flag, open/print the web signup page. With \`--company\`, bootstrap the first company headlessly for the logged-in session. If one is already active, it returns that company and says no new company was created. Add \`--json\` for machine-readable output. | Public (\`--company\` needs a login session) | \`{{cli}} signup --company "Acme"\` |
42800
+ | \`{{cli}} tenant create --company "<name>" [--json]\` | Create an additional clean company from an existing active company session. Requires \`tenant.create.additional\`; denied attempts create no tenant. Add \`--json\` for machine-readable output. | Logged-in tenant owner with entitlement | \`{{cli}} tenant create --company "Acme East"\` |
42794
42801
  | \`{{cli}} whoami\` | Show the authenticated user, accessible tenant roles, and the active tenant (\`current_tenant_id\`). | User | \`{{cli}} whoami\` |
42795
42802
  | \`{{cli}} tenants\` | List tenants the user can access; the active one is marked \`current\`. | User | \`{{cli}} tenants\` |
42796
42803
  | \`{{cli}} use <tenant>\` | Select a tenant slug or id as the active tenant for the session. It persists, so a following \`{{cli}} whoami\` reports it as \`current_tenant_id\`. | User | \`{{cli}} use acme-ops\` |
@@ -42838,6 +42845,8 @@ Ergonomic subcommands for everyday operation. Each wrapper is sugar over the sam
42838
42845
 
42839
42846
  These ergonomic wrappers (including the \`{{cli}} agent\` group) require **{{cli}} 0.2.0 or newer** \u2014 run \`npx {{cliPackage}}@latest \u2026\` to get them. Older versions can still reach every command through the \`{{cli}} command <id> --json\` floor, since command execution is server-side.
42840
42847
 
42848
+ **Generated verbs (0.6.0+).** Every registry command now has a first-class \`{{cli}} <namespace> <action>\` verb, projected directly from the command's input schema \u2014 so namespaces that previously had no ergonomic wrapper (for example \`{{cli}} measurable create\`, \`{{cli}} work_order enqueue\`, \`{{cli}} mcp_token create\`) are usable without dropping to the raw \`command <id>\` path. Flags follow the schema field names (\`--seat-id\`, \`--name\`, \u2026); read a command's exact input offline with \`{{cli}} <namespace> <action> --schema\` before calling it, and pass a nested payload with \`--input '<json>'\` when a field is a complex object. \`--json\` still selects machine output, \`--seat <id>\` still sets seat scope, and \`{{cli}} command <id> --json '<body>'\` remains the universal fallback.
42849
+
42841
42850
  The signed-in app exposes the same Skill command surface under **Skills** in the left sidebar. Use \`/skills\` to filter the tenant library, \`/skills/new\` to build canonical \`SKILL.md\` frontmatter with \`tool.catalog\` dependencies, \`/skills/import\` for bounded GitHub or upload imports, and each Skill detail page to review validation, publish, check Seat dependencies, and assign a published version. During \`/agents/new\`, \`agent_setup.get\` can return \`next_action: "choose_skills"\`; selected Skills are proposed immutable-version assignments and required Skill tools block sign-off/go-live until tool configuration is ready.
42842
42851
 
42843
42852
  | Command | Command ids | Purpose | Scope | Safe example |
@@ -43046,6 +43055,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
43046
43055
  | \`rost_confirm_signal_reading\` | \`signal.confirm_reading\` | Confirm an unconfirmed reading as human-verified. | Seat or tenant-admin | Humans confirm; call with \`{"reading_id":"<id>"}\`. |
43047
43056
  | \`rost_correct_signal_reading\` | \`signal.correct_reading\` | Overwrite a reading with a human-confirmed value. | Seat or tenant-admin | Manual correction; expect confirmation. |
43048
43057
  | \`rost_add_a_measurable\` | \`measurable.create\` | Add a measurable a seat owns (name, unit, direction, target, cadence). | Seat or tenant-admin | Call with \`{"seat_id":"<id>","name":"...","unit":"...","direction":"up_good","target":0,"cadence":"weekly"}\`. |
43058
+ | \`rost_import_signals_from_csv\` | \`signal.import\` | Bulk-import measurable definitions + trailing historical readings from a parsed scorecard export (e.g. a ninety CSV). Owners resolve to seats; readings are human-confirmed; re-import upserts by (measurable, period, cadence); a cross-cadence row is reported and skipped, not overwritten. | Tenant | Call with the parsed \`measurables\` array. |
43049
43059
  | \`rost_list_cascade_goals\` | \`goal.list\` | List Cascade goals, optionally by cycle or seat. | Seat or tenant-admin | Call with \`{}\` or \`{"cycle_id":"<id>"}\`. |
43050
43060
  | \`rost_create_cascade_goal\` | \`goal.create\` | Create a cycle goal under an objective. | Tenant | Call with cycle, seat, parent, title, definition of done. |
43051
43061
  | \`rost_update_cascade_goal\` | \`goal.update\` | Update a goal's title or definition of done. | Tenant | Call with \`goal_id\` and the changed fields. |
@@ -43060,6 +43070,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
43060
43070
  | \`rost_resolve_friction_issue\` | \`friction.resolve\` | Resolve an issue with a root cause and remediation task. | Tenant | Human decision; expect confirmation. |
43061
43071
  | \`rost_link_task_to_friction_issue\` | \`friction.link_task\` | Attach an existing task as an issue's action task. | Seat or tenant-admin | Call with \`issue_id\` and \`task_id\`. |
43062
43072
  | \`rost_create_task\` | \`task.create\` | Create a task (a commitment between seats). | Seat or tenant-admin | \`none\` \u2014 created directly; the owning seat accepts or declines. |
43073
+ | \`rost_update_task\` | \`task.update\` | Reschedule, reassign, or edit a non-terminal task. | Owner (tenant-admin) | Pass \`task_id\` plus at least one of \`due_on\`/\`owner_seat_id\`/\`title\`/\`description\`; terminal tasks reject. |
43063
43074
  | \`rost_compile_sync_brief\` | \`sync.brief.compile\` | Compile the weekly Sync Brief (idempotent per period). | Tenant | Call with \`{}\`. |
43064
43075
  | \`rost_get_sync_brief\` | \`sync.brief.get\` | Read the latest or a specific Sync Brief and agenda. | Seat or tenant-admin | Call with \`{}\` or \`{"sync_brief_id":"<id>"}\`. |
43065
43076
  | \`rost_start_sync_run\` | \`sync.run.start\` | Ensure a Sync Brief exists so the meeting can begin. | Tenant | Call with \`{}\`. |
@@ -43644,7 +43655,7 @@ Agents can suggest commitments and report progress. They should not create a new
43644
43655
  order: 61,
43645
43656
  title: "Signal guide",
43646
43657
  summary: "How to define and read measurables so the company runs on evidence instead of status theater.",
43647
- version: "2026-06-18.2",
43658
+ version: "2026-06-30.1",
43648
43659
  public: true,
43649
43660
  audiences: ["human", "cli", "mcp", "in_app_agent"],
43650
43661
  stages: ["operating_rhythm"],
@@ -43656,7 +43667,8 @@ Agents can suggest commitments and report progress. They should not create a new
43656
43667
  "signal.get",
43657
43668
  "signal.confirm_reading",
43658
43669
  "signal.correct_reading",
43659
- "measurable.create"
43670
+ "measurable.create",
43671
+ "signal.import"
43660
43672
  ],
43661
43673
  legal: {
43662
43674
  publicRisk: "low",
@@ -43698,6 +43710,10 @@ Avoid vanity numbers, manual-only status fields, and metrics nobody can act on.
43698
43710
 
43699
43711
  A human can run the whole loop from the Signal page. Each measurable has a "Log this period's number" control that records a human reading (the same \`signal.correct_reading\` path), and an "Add a measurable" form creates one against a seat (the \`measurable.create\` path). You do not need an agent to keep Signal current.
43700
43712
 
43713
+ ## Import a scorecard from CSV
43714
+
43715
+ To move off a spreadsheet or another operating tool, upload a scorecard export from the Signal page "Import from CSV" panel (the \`signal.import\` command, also available on CLI/MCP). Each row becomes a measurable owned by the seat whose name matches the row's owner, with its target, unit, direction, cadence, and trailing readings. Import is idempotent \u2014 re-importing upserts by period \u2014 and a row whose cadence conflicts with an existing measurable is reported and skipped, not overwritten.
43716
+
43701
43717
  ## When to stop for confirmation
43702
43718
 
43703
43719
  \`signal.correct_reading\` is \`human_required\`; overwriting a recorded measurable is a human judgment. \`signal.confirm_reading\` is \`none\`, so a seat can confirm its own readings directly. \`measurable.create\` is \`none\` \u2014 defining a measurable is not gated. An agent records readings with evidence; a human corrects when a value is wrong.
@@ -43913,7 +43929,7 @@ Stop before: approving a Charter, signing a manifest, connecting a tool or crede
43913
43929
  order: 72,
43914
43930
  title: "Settings guide",
43915
43931
  summary: "How to use Settings as the control plane for company access, channels, providers, tokens, and operating defaults.",
43916
- version: "2026-06-29.1",
43932
+ version: "2026-06-30.1",
43917
43933
  public: true,
43918
43934
  audiences: ["human", "cli", "mcp", "in_app_agent"],
43919
43935
  stages: ["company_setup", "staffing"],
@@ -43952,7 +43968,9 @@ When a settings source is temporarily unavailable, the app keeps the route open
43952
43968
 
43953
43969
  ## Integration health
43954
43970
 
43955
- \`integration.list\` lists connector metadata for CLI and MCP operators, \`integration.readiness\` returns the setup checklist, \`integration.status\` reads one provider or integration id, and \`integration.test\` runs the installed provider-specific health check. These commands return account labels, scopes, capabilities, timestamps, checklist status, DER-coded next actions, and health only; they never return vault references, access tokens, refresh tokens, client secrets, or raw provider responses. Google's test refreshes the vaulted OAuth credential and reads the Gmail profile as the minimal live check. Settings exposes the same Google readiness facts and test action beside Connect/Reconnect, showing whether OAuth env, callback registration, tenant connection, scopes, tests, Google verification/CASA, and Gmail/Sheets handlers are ready or still waiting on DER-880, DER-881, DER-866, or DER-867.
43971
+ \`integration.list\` lists connector metadata for CLI and MCP operators, \`integration.readiness\` returns the setup checklist, \`integration.status\` reads one provider or integration id, and \`integration.test\` runs the installed provider-specific health check. These commands return account labels, scopes, capabilities, timestamps, checklist status, and health only; they never return vault references, access tokens, refresh tokens, client secrets, or raw provider responses. Google's test refreshes the vaulted OAuth credential and reads the Gmail profile as the minimal live check. Settings keeps the client-facing Google card narrower: connected account, last successful test, granted capabilities, and connect, reconnect, or test actions.
43972
+
43973
+ Google production verification is a roadmap item planned after the first 100 users. Until then, live external Gmail send remains approval-gated and partner demos should use connected-account tests, sandbox previews, drafts, and approval-held examples rather than claiming unrestricted Google production send.
43956
43974
 
43957
43975
  Reconnects keep historical rows for audit, but provider status in Settings, CLI, and MCP prefers the current connected row first, then the latest error or disconnected row.
43958
43976
 
@@ -44705,7 +44723,7 @@ Agents should not teach EOS as EOS. They should use {{brand}}'s method. When a u
44705
44723
  order: 11,
44706
44724
  title: "Compass authoring guide",
44707
44725
  summary: "Field-by-field guidance for authoring a strong Compass document directly, with the full JSON contract and worked examples.",
44708
- version: "2026-06-20.1",
44726
+ version: "2026-06-30.1",
44709
44727
  public: true,
44710
44728
  audiences: ["cli", "mcp", "in_app_agent"],
44711
44729
  stages: ["company_setup"],
@@ -44760,7 +44778,7 @@ Each direction field (purpose, each principle, each goal title and definition of
44760
44778
 
44761
44779
  - **purpose** \u2014 why the company exists, beyond making money. Good: "Help small manufacturers ship quality products on time." Weak: "Be the best in our industry" (no one is served, nothing is testable).
44762
44780
  - **principles** (1\u20135) \u2014 the few operating beliefs that actually decide trade-offs. Good: "Customers feel the quality of every order." Weak: "Integrity" (a value label, not a decision rule). Keep it to the handful that change behavior; more than five dilutes them.
44763
- - **horizon_goals.three_year** and **horizon_goals.one_year** \u2014 each a goal object with a \`title\` and a \`definition_of_done\`, both "field" objects, plus a \`horizon\` of \`"three_year"\` or \`"one_year"\`. The definition of done must be checkable: "Trailing-12-month ARR \u2265 $3M and on-time delivery \u2265 99% for two consecutive quarters," not "grow a lot."
44781
+ - **horizon_goals.ten_year** (optional, schema_version 2), **horizon_goals.three_year**, and **horizon_goals.one_year** \u2014 each a goal object with a \`title\` and a \`definition_of_done\`, both "field" objects, plus a \`horizon\` of \`"ten_year"\`, \`"three_year"\`, or \`"one_year"\`. The 10-year horizon is additive: a human adds it through a new, superseding Compass version \u2014 never by editing an accepted doc. The definition of done must be checkable: "Trailing-12-month ARR \u2265 $3M and on-time delivery \u2265 99% for two consecutive quarters," not "grow a lot."
44764
44782
  - **cycle_objectives** (1\u20133) \u2014 the goals for the current cycle, each a goal object with \`horizon: "cycle"\`. These are what the company is actually working on now and should ladder up to the one-year goal.
44765
44783
  - **gaps** \u2014 questions the documents did not answer. Each gap has an \`id\`, the \`field\` it blocks, a \`question\`, a \`severity\` (\`required\` or \`recommended\`), and a \`reason\`. Record a gap rather than fabricating a value.
44766
44784
  - **follow_up_tasks** \u2014 concrete tasks that close a gap, each tied to a \`gap_id\` with \`acceptance_criteria\`.
@@ -44770,13 +44788,18 @@ Each direction field (purpose, each principle, each goal title and definition of
44770
44788
 
44771
44789
  \`\`\`json
44772
44790
  {
44773
- "schema_version": 1,
44791
+ "schema_version": 2,
44774
44792
  "purpose": { "value": "Help small manufacturers ship quality products on time.", "citations": [], "confidence": 0.9, "placeholder": false },
44775
44793
  "principles": [
44776
44794
  { "value": "Bias to action; decide with the information we have.", "citations": [], "confidence": 0.9, "placeholder": false },
44777
44795
  { "value": "Customers feel the quality of every order.", "citations": [], "confidence": 0.9, "placeholder": false }
44778
44796
  ],
44779
44797
  "horizon_goals": {
44798
+ "ten_year": {
44799
+ "title": { "value": "Reach $250M enterprise value", "citations": [], "confidence": 0.6, "placeholder": false },
44800
+ "definition_of_done": { "value": "An independent valuation is at or above $250M.", "citations": [], "confidence": 0.6, "placeholder": false },
44801
+ "horizon": "ten_year"
44802
+ },
44780
44803
  "three_year": {
44781
44804
  "title": { "value": "Reach $10M ARR with a 25-person team", "citations": [], "confidence": 0.8, "placeholder": false },
44782
44805
  "definition_of_done": { "value": "ARR is at or above $10M and headcount is 25 with no key-role gaps.", "citations": [], "confidence": 0.8, "placeholder": false },
@@ -45824,10 +45847,188 @@ function parseSemver(value) {
45824
45847
  };
45825
45848
  }
45826
45849
 
45827
- // src/operations.ts
45850
+ // src/generated/command-manifest.ts
45851
+ var COMMAND_MANIFEST = [
45852
+ { "id": "agent_setup.get", "namespace": "agent_setup", "action": "get", "title": "Get agent setup", "description": "Read the resumable agent-setup state: mode, parent, steward, template, lane, schedule, tool decisions, dry run, and next action.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "setup_id", "flag": "setup-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Read the resumable setup state: mode, parent, steward, lane, schedule, tool decisions, dry-run blockers, and the next action." },
45853
+ { "id": "agent_setup.start", "namespace": "agent_setup", "action": "start", "title": "Start agent setup", "description": "Start (or resume) a draft agent setup for a seat in template, custom, or existing mode.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "mode", "flag": "mode", "type": "enum", "required": true, "enumValues": ["template", "custom", "existing"] }, { "name": "template_slug", "flag": "template-slug", "type": "string", "required": false }], "hasComplexInput": false, "help": "Start a draft agent setup from a template, custom, or existing mode; the setup resumes from the draft agent and Charter, not a fresh start." },
45854
+ { "id": "agent_setup.update", "namespace": "agent_setup", "action": "update", "title": "Update agent setup", "description": "Update the draft agent's parent, steward, lane, schedule, operational answers, and tool decisions.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "parent_seat_id", "flag": "parent-seat-id", "type": "string", "required": false }, { "name": "steward_seat_id", "flag": "steward-seat-id", "type": "string", "required": false }, { "name": "lane", "flag": "lane", "type": "enum", "required": false, "enumValues": ["cloud", "mcp_session", "runner"] }, { "name": "schedule_cron", "flag": "schedule-cron", "type": "string", "required": false }, { "name": "answers", "flag": "answers", "type": "array", "required": false, "itemType": "string" }], "hasComplexInput": true, "help": "Update parent, steward, lane, schedule, answers, or tool decisions on the draft; steward and parent changes keep the no-orphan chain explicit." },
45855
+ { "id": "agent_template.list", "namespace": "agent_template", "action": "list", "title": "List agent templates", "description": "List stock agent templates and their responsibilities, default tools, and dry-run rehearsal.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List stock agent templates and their default tools and safety boundaries before starting a template setup." },
45856
+ { "id": "agent.configure_tools", "namespace": "agent", "action": "configure_tools", "title": "Configure agent tools", "description": "Save tool proposals, declines, and credential-ingress requests for a draft agent. Never stores or echoes secret material; vault refs only.", "requiredScope": "seat", "confirmation": "credential_flow", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Connect or decline proposed tools and stage credential-ingress requests; never place raw secrets here \u2014 secrets flow through vault-backed credential.ingress as vault refs only.", "example": { "seat_id": "0190aaaa-aaaa-7aaa-8aaa-aaaaaaaaaaaa", "tool_decisions": [{ "tool": "ap.invoices.read", "decision": "connect" }, { "tool": "email.draft", "decision": "connect" }] } },
45857
+ { "id": "agent.create_custom", "namespace": "agent", "action": "create_custom", "title": "Create custom agent", "description": "Create a draft custom agent shell and a draft Charter seed from operational answers (what it owns, success, never-do-alone, steward).", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "steward_seat_id", "flag": "steward-seat-id", "type": "string", "required": false }, { "name": "lane", "flag": "lane", "type": "enum", "required": false, "enumValues": ["cloud", "mcp_session", "runner"] }, { "name": "what_it_owns", "flag": "what-it-owns", "type": "string", "required": false }, { "name": "what_success_looks_like", "flag": "what-success-looks-like", "type": "string", "required": false }, { "name": "what_it_must_never_do_alone", "flag": "what-it-must-never-do-alone", "type": "string", "required": false }], "hasComplexInput": true, "help": "Create a draft custom agent from operational answers (what it owns, success, never-do-alone, steward); the Charter Builder owns the contract and go-live stays human-gated.", "example": { "seat_id": "0190aaaa-aaaa-7aaa-8aaa-aaaaaaaaaaaa", "steward_seat_id": "0190bbbb-bbbb-7bbb-8bbb-bbbbbbbbbbbb", "lane": "cloud", "what_it_owns": "Drafting AP invoice entries from inbound vendor emails for human review.", "what_success_looks_like": "Every inbound invoice is drafted within one business day with the correct GL coding.", "what_it_must_never_do_alone": "Never send payment or approve an invoice without a human sign-off." } },
45858
+ { "id": "agent.create_from_template", "namespace": "agent", "action": "create_from_template", "title": "Create agent from template", "description": "Create a draft stock agent and draft Charter from a stock template. Creates the agent occupancy only when a human steward chain resolves; the agent stays draft until a signed manifest, a passed dry run, and human go-live.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "template_slug", "flag": "template-slug", "type": "string", "required": true }, { "name": "expected_template_version", "flag": "expected-template-version", "type": "string", "required": false }], "hasComplexInput": false, "help": "Create a draft stock agent and draft Charter from a template; the agent occupancy is created only when a human steward chain resolves, and the agent stays draft until a signed manifest, a passed dry run, and human go-live." },
45859
+ { "id": "agent.decommission", "namespace": "agent", "action": "decommission", "title": "Decommission agent", "description": "Retire an agent occupancy safely. Blocks if it would leave another live agent without a human steward chain.", "requiredScope": "tenant", "confirmation": "dangerous", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "Retire an agent occupancy safely; the no-orphan guard blocks any decommission that would leave another live agent without a human steward chain." },
45860
+ { "id": "agent.fleet_digest", "namespace": "agent", "action": "fleet_digest", "title": "Get dogfood fleet health digest", "description": "Return a daily tenant fleet health digest with live/idle state, run counts, spend, failed runs, unresolved product errors, notification errors, and next actions.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "window_hours", "flag": "window-hours", "type": "integer", "required": false }, { "name": "error_limit", "flag": "error-limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Capture a daily dogfood fleet health digest with fleet state, run counts, spend, failed runs, unresolved errors, failed notifications, and next actions." },
45861
+ { "id": "agent.get_run", "namespace": "agent", "action": "get_run", "title": "Get agent run diagnostics", "description": "Return one seat run's diagnostic record: run status, transcript reference, token/cost usage, outcome, and linked product-visible run errors.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "run_id", "flag": "run-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Read one run's diagnostic record, transcript reference, token/cost usage, outcome, and linked product-visible errors." },
45862
+ { "id": "agent.go_live", "namespace": "agent", "action": "go_live", "title": "Go live", "description": "Promote a dry-run agent seat to live after the human approval gate.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Move an agent live only after dry-run evidence, signed permissions, and a human Steward chain are clear.", "example": { "seat_id": "0190aaaa-aaaa-7aaa-8aaa-aaaaaaaaaaaa", "charter_version_id": "0190cccc-cccc-7ccc-8ccc-cccccccccccc" } },
45863
+ { "id": "agent.list_fleet", "namespace": "agent", "action": "list_fleet", "title": "List agent fleet", "description": "Return every agent-occupied seat with lane, live state, last real turn, recent turn counts, top measurable status, open escalations, and 7-day real-run spend.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read every agent-occupied seat at once: lane, live state, last real turn, 24h/7d turns, measurable status, escalations, and spend." },
45864
+ { "id": "agent.list_runs", "namespace": "agent", "action": "list_runs", "title": "List agent runs", "description": "Return a seat's agent run history (status, lane, model, cost, per-run tool-call and guard-denial counts) plus the seat's run/tool-call rollup with held-action count.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Audit a seat's agent run history with per-run tool-call and guard-held counts (the Trust Card)." },
45865
+ { "id": "agent.list_tool_calls", "namespace": "agent", "action": "list_tool_calls", "title": "List agent tool calls", "description": "Return a seat's tool-call ledger (tool name, guard result, manifest clause, outcome) with the held-action count as the hero metric. Pass held_only to return only guard-held calls. Never returns argument summaries or secret material.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }, { "name": "held_only", "flag": "held-only", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Audit a seat's tool-call ledger with each call's guard result; held actions are the hero metric." },
45866
+ { "id": "agent.pause", "namespace": "agent", "action": "pause", "title": "Pause agent", "description": "Pause a live agent so it stops scheduled and on-demand runs. Reversible with agent.resume.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "Pause a live agent so it stops scheduled and on-demand runs; queued work orders are expired and a paused agent refuses to run until resumed. Reversible, unlike agent.decommission." },
45867
+ { "id": "agent.resume", "namespace": "agent", "action": "resume", "title": "Resume agent", "description": "Resume a paused agent back to live. Blocks if the steward chain no longer resolves to a human.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resume a paused agent back to live; the no-orphan guard blocks a resume whose steward chain no longer resolves to a human." },
45868
+ { "id": "agent.run_dry_run", "namespace": "agent", "action": "run_dry_run", "title": "Run agent dry run", "description": "Run the sandbox dry run for a draft agent. Durable and idempotent per Charter version; a passed result is reused, never re-run.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Run the sandbox dry run for a draft agent after the manifest is signed; the result is durable and idempotent per Charter version, and a passed run is reused.", "example": { "seat_id": "0190aaaa-aaaa-7aaa-8aaa-aaaaaaaaaaaa", "charter_version_id": "0190cccc-cccc-7ccc-8ccc-cccccccccccc" } },
45869
+ { "id": "agent.run_now", "namespace": "agent", "action": "run_now", "title": "Run agent now", "description": "Queue and dispatch an immediate work order for a live cloud or runner agent on a seat.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "task_id", "flag": "task-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Queue and dispatch an immediate live agent run without changing the agent's saved schedule." },
45870
+ { "id": "agent.show_markdown", "namespace": "agent", "action": "show_markdown", "title": "Show agent setup as markdown", "description": "Compose a seat's agent setup, steward, model, tools, and Charter into a clean, human-skimmable markdown card for review.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Render a seat's agent setup, model, steward, tools, and Charter as a clean markdown card to show your human a quick review." },
45871
+ { "id": "agent.status", "namespace": "agent", "action": "status", "title": "Get agent status", "description": "Return the agent occupancy, lane, schedule, live/offline state, steward chain, dry-run result, and Runner availability for a seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Check an agent's lane, live state, steward chain, dry-run result, and Runner availability before relying on it." },
45872
+ { "id": "agent.update_schedule", "namespace": "agent", "action": "update_schedule", "title": "Update agent schedule", "description": "Set or clear the scheduled execution cron for a draft or live agent on a seat.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "schedule_cron", "flag": "schedule-cron", "type": "string", "required": true }], "hasComplexInput": false, "help": "Set or clear an agent's scheduled execution; a live scheduled agent must keep a steward chain resolving to a human." },
45873
+ { "id": "charter.apply_seat_type_recommendation", "namespace": "charter", "action": "apply_seat_type_recommendation", "title": "Apply Charter seat-type recommendation", "description": "Apply the seat-type recommendation from a draft Charter.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Apply seat-type recommendations only after the Charter clarifies work shape, risk, and Steward accountability." },
45874
+ { "id": "charter.approve", "namespace": "charter", "action": "approve", "title": "Approve charter", "description": "Approve a draft Charter as a human owner.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": false }, { "name": "apply_seat_type", "flag": "apply-seat-type", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Charter approval is a human decision that activates the seat's operating contract." },
45875
+ { "id": "charter.draft", "namespace": "charter", "action": "draft", "title": "Draft charter", "description": "Create or fetch a draft Charter for a seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Draft Charters that define purpose, responsibilities, decision authority, measurables, tools, budget, and escalation; the charter authoring deep-dive shows what good looks like per field." },
45876
+ { "id": "charter.draft_all", "namespace": "charter", "action": "draft_all", "title": "Draft all charters", "description": "Draft Charters for every eligible seat in a tenant.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Draft Charters in onboarding order after the Responsibility Graph has enough seat clarity.", "example": {} },
45877
+ { "id": "charter.get", "namespace": "charter", "action": "get", "title": "Get Charter", "description": "Return a Charter version with its supersession history and latest dry-run status.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Read a Charter with its supersession history and dry-run status before approving or signing a manifest." },
45878
+ { "id": "charter.list", "namespace": "charter", "action": "list", "title": "List Charters", "description": "List Charter versions in the tenant, optionally filtered by seat or status.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["draft", "active", "superseded"] }], "hasComplexInput": false, "help": "List Charter versions to find the right draft or active version id before reading or amending it." },
45879
+ { "id": "charter.set", "namespace": "charter", "action": "set", "title": "Set charter", "description": "Create or replace a seat's draft Charter from a full document in one call; approve activates it as a human owner.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "approve", "flag": "approve", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Create or replace a seat's draft Charter from a full document in one call; read the charter authoring deep-dive first. Approving activates the seat's contract and is a human decision.", "example": { "seat_id": "0190aaaa-aaaa-7aaa-8aaa-aaaaaaaaaaaa", "doc": { "payload_version": 1, "purpose": "AP intake clerk: draft accounts-payable invoice entries from inbound vendor emails for human review.", "accountabilities": [{ "title": "Draft every inbound invoice", "description": "Convert each inbound vendor invoice into a draft AP entry with the correct vendor, amount, and GL coding within one business day." }, { "title": "Flag discrepancies", "description": "Surface duplicate, mismatched, or out-of-policy invoices as Friction issues instead of drafting them silently." }], "decision_authority": { "autonomous": [{ "action": "Draft AP entries and propose GL coding from inbound invoices", "condition": "Allowed when the vendor is known and the amount is within the standard purchase range.", "rationale": "Drafting is reversible and reviewed by a human before posting.", "unanswered_boundary": false }], "approval": [{ "action": "Post an invoice or send any vendor-facing message", "condition": "Require explicit human approval before posting or sending.", "rationale": "Posting and sending are durable, money-moving actions.", "unanswered_boundary": false }], "escalate": [{ "action": "Unknown vendor, payment over the approval threshold, or a suspected duplicate", "condition": "Always escalate to the Steward before acting.", "rationale": "Conservative default for ambiguous, irreversible, or financial exposure.", "unanswered_boundary": true }] }, "escalation_rules": ["Escalate any invoice over $5,000 or from a vendor not already in the ledger.", "Escalate when an invoice appears to duplicate one already drafted or posted."], "measurables": [{ "name": "Invoices drafted within one business day", "target": "100%", "cadence": "weekly", "source": "agent" }, { "name": "Discrepancies caught before posting", "target": "\u2265 95%", "cadence": "monthly", "source": "human" }], "permission_manifest": [{ "tool": "ap.invoices.read", "scope": "Read inbound invoices and the vendor ledger.", "granted": true, "rationale": "Needed to draft entries from source invoices." }, { "tool": "email.draft", "scope": "Draft vendor replies for human review; never send.", "granted": true, "rationale": "Lets the seat prepare clarifications without taking a send action." }], "budget": { "monthly_usd": null, "approval_required_over_usd": 0, "notes": "No autonomous spend; any spend requires Steward approval until a budget is set." }, "unanswered_boundaries": ["Approval threshold for auto-posting", "Vendor onboarding authority"], "seat_type_recommendation": { "recommendation": "agent", "rationale": "The work is high-volume, rule-bound, and fully reviewable, which suits a draft-and-confirm agent under a human Steward.", "confidence": 0.8 } }, "approve": false } },
45880
+ { "id": "charter.show_markdown", "namespace": "charter", "action": "show_markdown", "title": "Show Charter as markdown", "description": "Compose a seat's active or latest Charter into a clean, human-skimmable markdown card for review.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Render a seat's active or latest Charter as a clean markdown card to show your human a quick review." },
45881
+ { "id": "charter.sign_manifest", "namespace": "charter", "action": "sign_manifest", "title": "Sign charter manifest", "description": "Request human confirmation for a Charter permission manifest.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Sign tool manifests only when the Charter explains why the tool is needed and how it is bounded." },
45882
+ { "id": "charter.skip", "namespace": "charter", "action": "skip", "title": "Skip charter draft", "description": "Mark a draft Charter as skipped.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Skip a Charter only when the seat is intentionally out of scope for the current onboarding pass." },
45883
+ { "id": "charter.update_draft", "namespace": "charter", "action": "update_draft", "title": "Update charter draft", "description": "Update a draft Charter document.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "charter_version_id", "flag": "charter-version-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Submit the full Charter document directly (purpose, decision_authority, escalation_rules, measurables, budget, permission_manifest); read the charter authoring deep-dive for what good looks like per field. Durable authority changes still need human approval.", "example": { "charter_version_id": "0190cccc-cccc-7ccc-8ccc-cccccccccccc", "doc": { "payload_version": 1, "purpose": "AP intake clerk: draft accounts-payable invoice entries from inbound vendor emails for human review.", "accountabilities": [{ "title": "Draft every inbound invoice", "description": "Convert each inbound vendor invoice into a draft AP entry with the correct vendor, amount, and GL coding within one business day." }, { "title": "Flag discrepancies", "description": "Surface duplicate, mismatched, or out-of-policy invoices as Friction issues instead of drafting them silently." }], "decision_authority": { "autonomous": [{ "action": "Draft AP entries and propose GL coding from inbound invoices", "condition": "Allowed when the vendor is known and the amount is within the standard purchase range.", "rationale": "Drafting is reversible and reviewed by a human before posting.", "unanswered_boundary": false }], "approval": [{ "action": "Post an invoice or send any vendor-facing message", "condition": "Require explicit human approval before posting or sending.", "rationale": "Posting and sending are durable, money-moving actions.", "unanswered_boundary": false }], "escalate": [{ "action": "Unknown vendor, payment over the approval threshold, or a suspected duplicate", "condition": "Always escalate to the Steward before acting.", "rationale": "Conservative default for ambiguous, irreversible, or financial exposure.", "unanswered_boundary": true }] }, "escalation_rules": ["Escalate any invoice over $5,000 or from a vendor not already in the ledger.", "Escalate when an invoice appears to duplicate one already drafted or posted."], "measurables": [{ "name": "Invoices drafted within one business day", "target": "100%", "cadence": "weekly", "source": "agent" }, { "name": "Discrepancies caught before posting", "target": "\u2265 95%", "cadence": "monthly", "source": "human" }], "permission_manifest": [{ "tool": "ap.invoices.read", "scope": "Read inbound invoices and the vendor ledger.", "granted": true, "rationale": "Needed to draft entries from source invoices." }, { "tool": "email.draft", "scope": "Draft vendor replies for human review; never send.", "granted": true, "rationale": "Lets the seat prepare clarifications without taking a send action." }], "budget": { "monthly_usd": null, "approval_required_over_usd": 0, "notes": "No autonomous spend; any spend requires Steward approval until a budget is set." }, "unanswered_boundaries": ["Approval threshold for auto-posting", "Vendor onboarding authority"], "seat_type_recommendation": { "recommendation": "agent", "rationale": "The work is high-volume, rule-bound, and fully reviewable, which suits a draft-and-confirm agent under a human Steward.", "confidence": 0.8 } } } },
45884
+ { "id": "coach.draft_guide", "namespace": "coach", "action": "draft_guide", "title": "Draft accountability discussion guide", "description": "Draft a private discussion guide for the accountable human about a seat's commitment pattern. Read-only and human-only \u2014 it is never delivered, sent, or written to the coached person's record.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Draft a private accountability discussion guide for the accountable human from a seat's commitment pattern. Never delivered or written to the coached person's record." },
45885
+ { "id": "command.describe", "namespace": "command", "action": "describe", "title": "Describe command", "description": "Return a command's exact input/output JSON Schema, scope, confirmation gate, help pointer, guides, a validated example, and related commands. Run this before calling a mutating command.", "requiredScope": "user", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Run command.describe before calling a mutating command to read its exact input/output schema and a worked example; on a failure, read the error's help field and run the command it names." },
45886
+ { "id": "command.list", "namespace": "command", "action": "list", "title": "List commands", "description": "List every callable command id with its title, required scope, confirmation gate, and onboarding stages. Use 'command.describe' for a single command's full contract.", "requiredScope": "user", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List the callable command surface, then use command.describe for the exact contract of the one you need." },
45887
+ { "id": "compass.alignment", "namespace": "compass", "action": "alignment", "title": "Check Compass alignment", "description": "Advisory drift check: scores whether cycle goals still ladder up to the active vision and flags orphan/contradictory goals. Read-only \u2014 it never edits the Compass or any goal.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Advisory drift check: scores whether cycle goals still ladder to the active vision and flags orphan/contradictory goals. Read-only." },
45888
+ { "id": "compass.answer_gap", "namespace": "compass", "action": "answer_gap", "title": "Answer Compass gap", "description": "Record a human answer for a Compass gap and create a replacement draft.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "gap_id", "flag": "gap-id", "type": "string", "required": true }, { "name": "answer", "flag": "answer", "type": "string", "required": true }], "hasComplexInput": false, "help": "Answer Compass gaps with explicit human input before turning direction into graph, Charter, or Cascade decisions." },
45889
+ { "id": "compass.approve_version", "namespace": "compass", "action": "approve_version", "title": "Approve Compass version", "description": "Activate a Compass version by supersession.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "draft_id", "flag": "draft-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Compass approval is a human decision and should anchor later Cascade commitments." },
45890
+ { "id": "compass.draft", "namespace": "compass", "action": "draft", "title": "Draft Compass", "description": "Create a Compass draft version.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": true, "help": "Submit a full Compass document; read the Compass authoring guide for the field-by-field contract and worked examples before drafting. Drafting is safe for an agent; approving a version is a human act.", "example": { "doc": { "schema_version": 1, "purpose": { "value": "Help small manufacturers ship quality products on time.", "citations": [], "confidence": 0.9, "placeholder": false }, "principles": [{ "value": "Bias to action; decide with the information we have.", "citations": [], "confidence": 0.9, "placeholder": false }, { "value": "Customers feel the quality of every order.", "citations": [], "confidence": 0.9, "placeholder": false }], "horizon_goals": { "three_year": { "title": { "value": "Reach $10M ARR with a 25-person team", "citations": [], "confidence": 0.9, "placeholder": false }, "definition_of_done": { "value": "ARR is at or above $10M and team headcount is 25 with no key-role gaps.", "citations": [], "confidence": 0.9, "placeholder": false }, "horizon": "three_year" }, "one_year": { "title": { "value": "Hit $3M ARR and 99% on-time delivery", "citations": [], "confidence": 0.9, "placeholder": false }, "definition_of_done": { "value": "Trailing-12-month ARR \u2265 $3M and on-time delivery rate \u2265 99% for two consecutive quarters.", "citations": [], "confidence": 0.9, "placeholder": false }, "horizon": "one_year" } }, "cycle_objectives": [{ "title": { "value": "Cut order-to-ship cycle time by 20%", "citations": [], "confidence": 0.9, "placeholder": false }, "definition_of_done": { "value": "Median order-to-ship time is 20% lower than the prior cycle baseline.", "citations": [], "confidence": 0.9, "placeholder": false }, "horizon": "cycle" }], "gaps": [], "follow_up_tasks": [], "source_ids": [] } } },
45891
+ { "id": "compass.get_current", "namespace": "compass", "action": "get_current", "title": "Get current Compass", "description": "Return the active and draft Compass versions plus the source documents that informed them.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read the active and draft Compass before drafting goals or recommending direction changes." },
45892
+ { "id": "compass.list_gaps", "namespace": "compass", "action": "list_gaps", "title": "List Compass gaps", "description": "Return unanswered and answered Compass context gaps for the latest draft or active version.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List unanswered Compass gaps so a human can answer them before direction anchors graph or Cascade work." },
45893
+ { "id": "compass.reject_draft", "namespace": "compass", "action": "reject_draft", "title": "Reject Compass draft", "description": "Reject and remove a draft Compass version.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "draft_id", "flag": "draft-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Reject Compass drafts when the direction, language, or company intent is not ready to anchor implementation." },
45894
+ { "id": "compass.set", "namespace": "compass", "action": "set", "title": "Set Compass", "description": "Compatibility command for the DER-626 MCP Compass tool.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "draft_id", "flag": "draft-id", "type": "string", "required": false }, { "name": "approve", "flag": "approve", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Set Compass drafts in the product's own vocabulary and approve only with explicit human confirmation." },
45895
+ { "id": "compass.show_markdown", "namespace": "compass", "action": "show_markdown", "title": "Show Compass as markdown", "description": "Compose the current Compass and its open gaps into a clean, human-skimmable markdown card for review.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Render the current Compass and its open gaps as a clean markdown card to show your human a quick review." },
45896
+ { "id": "compass.update_draft", "namespace": "compass", "action": "update_draft", "title": "Update Compass draft", "description": "Replace a draft Compass document.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "draft_id", "flag": "draft-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Pass the compass_version_id returned by compass.draft as draft_id; update_draft replaces only an unpublished draft in this tenant." },
45897
+ { "id": "confirmation.approve", "namespace": "confirmation", "action": "approve", "title": "Approve pending confirmation", "description": "Approve an in-flight confirmation and execute the original command as the approving human.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "confirmation_id", "flag": "confirmation-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Approve pending confirmations only when the requested durable change is clear to the human owner." },
45898
+ { "id": "confirmation.reject", "namespace": "confirmation", "action": "reject", "title": "Reject pending confirmation", "description": "Reject an in-flight confirmation without executing the original command.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "confirmation_id", "flag": "confirmation-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "Reject pending confirmations when authority, evidence, or human intent is unclear." },
45899
+ { "id": "credential.ingress", "namespace": "credential", "action": "ingress", "title": "Store credential", "description": "Store a secret through the vault and persist only the credential vault reference.", "requiredScope": "seat", "confirmation": "credential_flow", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "provider", "flag": "provider", "type": "string", "required": true }, { "name": "scope_description", "flag": "scope-description", "type": "string", "required": true }, { "name": "secret_name", "flag": "secret-name", "type": "string", "required": true }], "hasComplexInput": false, "secretBlocked": true, "help": "Ingress credentials only through vault-backed flows; never place raw secrets in prompts, logs, or docs." },
45900
+ { "id": "deliverable.accept", "namespace": "deliverable", "action": "accept", "title": "Accept deliverable value", "description": "Record a human-confirmed accepted value (USD) on a deliverable. Humans decide; agents cannot self-accept. Re-accepting records a correction as a new event; prior events are never mutated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "deliverable_id", "flag": "deliverable-id", "type": "string", "required": true }, { "name": "impact_value_usd", "flag": "impact-value-usd", "type": "number", "required": true }], "hasComplexInput": false, "help": "Record a human-confirmed accepted value (USD) on a deliverable; owner-only and human-gated. Humans decide \u2014 agents cannot self-accept. Re-accepting records a correction as a new event." },
45901
+ { "id": "deliverable.attach", "namespace": "deliverable", "action": "attach", "title": "Attach agent deliverable", "description": "Attach a deliverable to a source run, task, or work order for the acting seat. Source refs are validated server-side.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "run_id", "flag": "run-id", "type": "string", "required": false }, { "name": "task_id", "flag": "task-id", "type": "string", "required": false }, { "name": "work_order_id", "flag": "work-order-id", "type": "string", "required": false }, { "name": "kind", "flag": "kind", "type": "enum", "required": false, "enumValues": ["brief", "work_evidence", "artifact", "report", "other"] }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "summary", "flag": "summary", "type": "string", "required": false }, { "name": "content", "flag": "content", "type": "string", "required": false }], "hasComplexInput": true, "help": "Attach a scrubbed deliverable to a source run, task, or work order that belongs to the acting seat." },
45902
+ { "id": "deliverable.create", "namespace": "deliverable", "action": "create", "title": "Create agent deliverable", "description": "Create an agent deliverable for the acting seat. The deliverable is scrubbed for secrets before storage.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "kind", "flag": "kind", "type": "enum", "required": false, "enumValues": ["brief", "work_evidence", "artifact", "report", "other"] }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "summary", "flag": "summary", "type": "string", "required": false }, { "name": "content", "flag": "content", "type": "string", "required": false }, { "name": "delivered_at", "flag": "delivered-at", "type": "string", "required": false }], "hasComplexInput": true, "help": "Create a scrubbed durable work output for the acting seat without making a durable company decision." },
45903
+ { "id": "deliverable.get", "namespace": "deliverable", "action": "get", "title": "Get agent deliverable", "description": "Return one agent deliverable by id for a seat.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Read one durable agent deliverable by id after checking seat-scoped access." },
45904
+ { "id": "deliverable.list", "namespace": "deliverable", "action": "list", "title": "List agent deliverables", "description": "Return agent deliverables for a seat, including derived entries from succeeded runs with outcome summaries.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "List durable agent deliverables for a seat, including explicit outputs and successful-run summaries." },
45905
+ { "id": "error_log.list", "namespace": "error_log", "action": "list", "title": "List error logs", "description": "List tenant error logs with optional filtering by seat, source, severity, and resolved state.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "source", "flag": "source", "type": "enum", "required": false, "enumValues": ["run", "llm", "tool", "mcp", "runner", "integration", "job", "web"] }, { "name": "severity", "flag": "severity", "type": "enum", "required": false, "enumValues": ["warning", "error", "critical"] }, { "name": "resolved", "flag": "resolved", "type": "enum", "required": false, "enumValues": ["active", "acknowledged", "resolved", "all"] }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "List product-visible error logs by source, severity, seat, and active/resolved disposition before closing stale failures." },
45906
+ { "id": "error_log.resolve", "namespace": "error_log", "action": "resolve", "title": "Resolve error log", "description": "Acknowledge or resolve an error log with a required reason and optional linked task, Friction issue, or PR reference.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "error_log_id", "flag": "error-log-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": true }, { "name": "disposition", "flag": "disposition", "type": "enum", "required": false, "enumValues": ["acknowledged", "resolved"] }, { "name": "linked_task_id", "flag": "linked-task-id", "type": "string", "required": false }, { "name": "linked_issue_id", "flag": "linked-issue-id", "type": "string", "required": false }, { "name": "linked_pr_ref", "flag": "linked-pr-ref", "type": "string", "required": false }], "hasComplexInput": false, "help": "Acknowledge or resolve a stale error log with a required human reason and optional task, issue, or PR evidence." },
45907
+ { "id": "error_log.supersede", "namespace": "error_log", "action": "supersede", "title": "Supersede error log", "description": "Mark an error log as superseded by a newer error log. Links the old error to the new one and records the reason.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "error_log_id", "flag": "error-log-id", "type": "string", "required": true }, { "name": "new_error_log_id", "flag": "new-error-log-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": true }, { "name": "linked_task_id", "flag": "linked-task-id", "type": "string", "required": false }, { "name": "linked_issue_id", "flag": "linked-issue-id", "type": "string", "required": false }, { "name": "linked_pr_ref", "flag": "linked-pr-ref", "type": "string", "required": false }], "hasComplexInput": false, "help": "Mark an older error log as superseded by a newer same-tenant error log while preserving history." },
45908
+ { "id": "escalation.get", "namespace": "escalation", "action": "get", "title": "Get escalation", "description": "Read a single escalation the caller is allowed to see (own steward chain for humans, own seat for agents).", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Read one escalation's evidence and recommendation before a human resolves or rejects it." },
45909
+ { "id": "escalation.list", "namespace": "escalation", "action": "list", "title": "List escalations", "description": "List Steward queue escalations routed to the caller's steward chain (human) or raised by the caller's seat (agent).", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "include_decided", "flag": "include-decided", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "List Steward queue escalations (own chain for humans, own seat for agents) before resolving or routing them." },
45910
+ { "id": "escalation.raise", "namespace": "escalation", "action": "raise", "title": "Raise escalation", "description": "Emit an escalation event and open a Steward queue item for the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "reason", "flag": "reason", "type": "string", "required": true }, { "name": "charter_clause", "flag": "charter-clause", "type": "string", "required": true }, { "name": "recommended_action", "flag": "recommended-action", "type": "string", "required": false }], "hasComplexInput": true, "help": "Raise an escalation to the seat's Steward when a decision exceeds the seat's authority; humans decide." },
45911
+ { "id": "escalation.reject", "namespace": "escalation", "action": "reject", "title": "Reject escalation", "description": "Override an open escalation so the agent must not proceed. Writes a human decision; agents cannot reject.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "Reject (override) an escalation so the agent must not proceed; the decision records the human decider. Agents cannot reject." },
45912
+ { "id": "escalation.resolve", "namespace": "escalation", "action": "resolve", "title": "Resolve escalation", "description": "Approve an open escalation (or convert it to Friction). Writes a human decision; agents cannot resolve.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }, { "name": "action", "flag": "action", "type": "enum", "required": false, "enumValues": ["approve", "convert_to_issue"] }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an escalation as a human Steward; the decision records decided_by as the approving human. Agents cannot resolve." },
45913
+ { "id": "friction.assist", "namespace": "friction", "action": "assist", "title": "Assist Friction issue", "description": "Advisory IDS assist for an issue: the most-similar prior resolved issues with their root causes and decisions, a recurring-pattern flag, and recommended options. Read-only \u2014 it never resolves the issue.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Advisory IDS assist: the most-similar prior resolved issues with their root causes and decisions, plus a recurring-pattern flag. Read-only \u2014 it never resolves the issue." },
45914
+ { "id": "friction.file_issue", "namespace": "friction", "action": "file_issue", "title": "File Friction issue", "description": "Emit an issue event and open a Friction issue raised by the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "summary", "flag": "summary", "type": "string", "required": true }, { "name": "blocking_goal_id", "flag": "blocking-goal-id", "type": "string", "required": false }, { "name": "broken_measurable_id", "flag": "broken-measurable-id", "type": "string", "required": false }, { "name": "severity", "flag": "severity", "type": "enum", "required": true, "enumValues": ["low", "med", "high", "critical"] }], "hasComplexInput": true, "help": "File a Friction issue with evidence when a goal or measurable is blocked or broken." },
45915
+ { "id": "friction.link_task", "namespace": "friction", "action": "link_task", "title": "Link task to Friction issue", "description": "Attach an existing tenant task as the action task for a non-terminal issue. Both ids must belong to the tenant.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "task_id", "flag": "task-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Attach an existing task as the action task for a non-terminal issue." },
45916
+ { "id": "friction.list", "namespace": "friction", "action": "list", "title": "List Friction issues", "description": "List Friction issues ranked by status, impact, and severity. Defaults to active (open + diagnosing).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["open", "diagnosing", "resolved", "dropped", "active", "all"] }], "hasComplexInput": false, "help": "List Friction issues ranked by impact and severity to find the issue id before updating or resolving it." },
45917
+ { "id": "friction.resolve", "namespace": "friction", "action": "resolve", "title": "Resolve Friction issue", "description": "Resolve an issue with a root cause and remediation task. This records a human decision (decided_by) and creates the follow-up task in one transaction.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "root_cause", "flag": "root-cause", "type": "string", "required": true }, { "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": true }, { "name": "task_title", "flag": "task-title", "type": "string", "required": true }, { "name": "task_description", "flag": "task-description", "type": "string", "required": true }, { "name": "done_by", "flag": "done-by", "type": "string", "required": true }, { "name": "resolving_seat_id", "flag": "resolving-seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an issue with a root cause and remediation task; resolution is a human decision." },
45918
+ { "id": "friction.update_status", "namespace": "friction", "action": "update_status", "title": "Update Friction issue status", "description": "Move a non-terminal issue between open and diagnosing. Terminal issues (resolved/dropped) cannot be reopened here.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": true, "enumValues": ["open", "diagnosing"] }], "hasComplexInput": false, "help": "Move a non-terminal issue between open and diagnosing while it is being worked." },
45919
+ { "id": "goal.create", "namespace": "goal", "action": "create", "title": "Create Cascade goal", "description": "Create a cycle goal under an existing objective. The parent chain must terminate at a Compass objective in the same cycle (enforced server-side).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": true }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "parent_goal_id", "flag": "parent-goal-id", "type": "string", "required": true }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "definition_of_done", "flag": "definition-of-done", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["on", "off"] }], "hasComplexInput": false, "help": "Create cycle goals under an existing objective; the parent chain must terminate at a Compass objective." },
45920
+ { "id": "goal.drop", "namespace": "goal", "action": "drop", "title": "Drop Cascade goal", "description": "Drop (retire) a goal by setting status to dropped. Dropping retires the commitment, so it is human-gated. The row is retained for audit (never deleted).", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Drop a goal to retire a commitment; the goal is retained for audit and dropping is human-gated." },
45921
+ { "id": "goal.list", "namespace": "goal", "action": "list", "title": "List Cascade goals", "description": "List goals in the tenant, optionally filtered by cycle or seat. Seat-scoped callers see only their own seat's goals.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List Cascade goals to find goal ids, parentage, and seat ownership before mutating the tree." },
45922
+ { "id": "goal.list_at_risk", "namespace": "goal", "action": "list_at_risk", "title": "List at-risk Cascade goals", "description": "List goals projected to miss their cycle pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals (no progress) are excluded.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List goals projected off pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals are excluded." },
45923
+ { "id": "goal.reparent", "namespace": "goal", "action": "reparent", "title": "Reparent Cascade goal", "description": "Move a goal under a different parent. Reparenting changes accountable structure, so it is human-gated. One-root and no-cycle are enforced server-side.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "parent_goal_id", "flag": "parent-goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Reparent a goal only when it clarifies accountable structure; reparenting changes authority and is human-gated." },
45924
+ { "id": "goal.set_progress", "namespace": "goal", "action": "set_progress", "title": "Set Cascade goal progress", "description": "Set a goal's quantified progress (0\u2013100). Seat-scoped callers may set progress only for their own goals. An agent's progress is a proposal a human approves before it lands.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "progress_pct", "flag": "progress-pct", "type": "integer", "required": true }], "hasComplexInput": false, "help": "Report a goal's quantified progress (0-100). An agent's progress is a proposal a human approves before the goal moves." },
45925
+ { "id": "goal.set_status", "namespace": "goal", "action": "set_status", "title": "Set Cascade goal status", "description": "Set a goal's status (on/off/done). Seat-scoped callers may set status only for their own goals.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": true, "enumValues": ["on", "off", "done"] }], "hasComplexInput": false, "help": "Set a goal's status; seat tokens may only set status for their own goals." },
45926
+ { "id": "goal.update", "namespace": "goal", "action": "update", "title": "Update Cascade goal", "description": "Update a goal's title or definition of done. Topology (parent/seat) and status have dedicated commands.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "title", "flag": "title", "type": "string", "required": false }, { "name": "definition_of_done", "flag": "definition-of-done", "type": "string", "required": false }], "hasComplexInput": false, "help": "Update a goal's title or definition of done; topology and status have dedicated commands." },
45927
+ { "id": "graph.get", "namespace": "graph", "action": "get", "title": "Get Responsibility Graph", "description": "Return the tenant's Responsibility Graph: seats, edges, root, occupants, and status rollups.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read the Responsibility Graph to discover seat ids, parentage, occupants, and status before mutating or routing work." },
45928
+ { "id": "integration.list", "namespace": "integration", "action": "list", "title": "List integrations", "description": "List tenant integration metadata and health status. Returns account/scopes/capabilities only; never secrets or vault refs.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "provider", "flag": "provider", "type": "string", "required": false }], "hasComplexInput": false, "help": "List connected integrations and their metadata-only health state before enabling a connector-backed tool." },
45929
+ { "id": "integration.readiness", "namespace": "integration", "action": "readiness", "title": "Check integration readiness", "description": "Return a safe connector setup checklist for operators and agents. Starts with Google and exposes no secrets.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "provider", "flag": "provider", "type": "enum", "required": false, "enumValues": ["google"] }], "hasComplexInput": false, "help": "Read the connector setup checklist before relying on Google-backed agent work; the checklist names missing config, connection, scopes, external verification, and handler blockers." },
45930
+ { "id": "integration.status", "namespace": "integration", "action": "status", "title": "Get integration status", "description": "Read one integration's metadata and latest health status. Returns no secret material.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "provider", "flag": "provider", "type": "string", "required": false }, { "name": "integration_id", "flag": "integration-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Read one integration's metadata-only status by provider or integration id." },
45931
+ { "id": "integration.test", "namespace": "integration", "action": "test", "title": "Test integration connection", "description": "Run the installed provider-specific connection test and update integration health. The command returns bounded metadata only.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "provider", "flag": "provider", "type": "string", "required": false }, { "name": "integration_id", "flag": "integration-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Run the provider-specific connection test and update integration health without exposing credentials." },
45932
+ { "id": "mcp_token.create", "namespace": "mcp_token", "action": "create", "title": "Create MCP token", "description": "Mint a tenant-admin or seat-scoped MCP token.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "scope", "flag": "scope", "type": "enum", "required": true, "enumValues": ["tenant_admin", "seat"] }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "expires_at", "flag": "expires-at", "type": "string", "required": false }, { "name": "expires_in_days", "flag": "expires-in-days", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Create MCP tokens with the narrowest scope needed, and tell agents where to retrieve reference docs." },
45933
+ { "id": "mcp_token.list", "namespace": "mcp_token", "action": "list", "title": "List MCP tokens", "description": "List MCP token metadata (id, scope, seat, created/last-used/revoked). Never returns token material.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "include_revoked", "flag": "include-revoked", "type": "boolean", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List MCP token metadata (never token material) to audit which seats hold active sessions." },
45934
+ { "id": "mcp_token.revoke", "namespace": "mcp_token", "action": "revoke", "title": "Revoke MCP token", "description": "Revoke an MCP token immediately.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "token_id", "flag": "token-id", "type": "string", "required": true }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Revoke MCP access when a local session ends or seat authority changes." },
45935
+ { "id": "measurable.create", "namespace": "measurable", "action": "create", "title": "Add a measurable", "description": "Create a measurable (a Signal a seat owns) with its target, unit, direction, and cadence. The seat owns it; readings attach to the measurable. Source is 'human' \u2014 a human-defined measurable a human logs.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "name", "flag": "name", "type": "string", "required": true }, { "name": "unit", "flag": "unit", "type": "string", "required": true }, { "name": "direction", "flag": "direction", "type": "enum", "required": true, "enumValues": ["up_good", "down_good"] }, { "name": "target", "flag": "target", "type": "number", "required": true }, { "name": "cadence", "flag": "cadence", "type": "enum", "required": true, "enumValues": ["daily", "weekly"] }], "hasComplexInput": false, "help": "Add a measurable a seat owns (name, unit, direction, target, cadence) before recording readings against it." },
45936
+ { "id": "member.invite", "namespace": "member", "action": "invite", "title": "Invite member", "description": "Create a pending tenant invite for a human teammate. The acceptance link is delivered out of band, not in the command result.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "email", "flag": "email", "type": "string", "required": true }, { "name": "role", "flag": "role", "type": "enum", "required": true, "enumValues": ["owner", "steward", "member"] }, { "name": "byo_key", "flag": "byo-key", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Invite humans to the company by seat-aware role; the invite token is never returned over CLI or MCP." },
45937
+ { "id": "member.remove", "namespace": "member", "action": "remove", "title": "Remove member", "description": "Remove a tenant member. Blocked when it would orphan an agent steward chain.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "member_id", "flag": "member-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Remove a member; the no-orphan-agent guard blocks removing the only steward in an agent chain." },
45938
+ { "id": "member.update", "namespace": "member", "action": "update", "title": "Update member role", "description": "Change a tenant member's role.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "member_id", "flag": "member-id", "type": "string", "required": true }, { "name": "role", "flag": "role", "type": "enum", "required": true, "enumValues": ["owner", "steward", "member"] }], "hasComplexInput": false, "help": "Change a member's role; role changes are human-gated." },
45939
+ { "id": "model.catalog", "namespace": "model", "action": "catalog", "title": "List model catalog", "description": "List the guided model tiers the agent builder reads \u2014 recommendation, token prices, cost band, effort, model id, and when to choose or avoid each tier.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List guided model tiers with recommendations, token prices, cost bands, best-fit work, and model ids before choosing --model for an agent." },
45940
+ { "id": "notification.list_errors", "namespace": "notification", "action": "list_errors", "title": "List notification errors", "description": "List recent failed notification deliveries for the tenant.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "List recent failed notification deliveries when diagnosing missed escalations or briefs." },
45941
+ { "id": "notification.settings.get", "namespace": "notification", "action": "settings.get", "title": "Get notification settings", "description": "Read tenant notification preferences (escalations, Sync brief, default channel).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read notification preferences before changing escalation or Sync brief delivery." },
45942
+ { "id": "notification.settings.update", "namespace": "notification", "action": "settings.update", "title": "Update notification settings", "description": "Update tenant notification preferences.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "escalations_enabled", "flag": "escalations-enabled", "type": "boolean", "required": false }, { "name": "sync_brief_enabled", "flag": "sync-brief-enabled", "type": "boolean", "required": false }, { "name": "default_channel", "flag": "default-channel", "type": "enum", "required": false, "enumValues": ["slack", "email", "in_app"] }], "hasComplexInput": false, "help": "Update notification preferences for escalations, Sync briefs, and the default channel." },
45943
+ { "id": "notification.test", "namespace": "notification", "action": "test", "title": "Send test notification", "description": "Emit an in-app test notification to the acting human to verify delivery is wired.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Send an in-app test notification to confirm the delivery path is wired." },
45944
+ { "id": "onboarding.advance_step", "namespace": "onboarding", "action": "advance_step", "title": "Advance onboarding step", "description": "Persist the current onboarding step after server-side validation.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "step", "flag": "step", "type": "string", "required": true }, { "name": "completed", "flag": "completed", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Advance onboarding only after the current setup step is represented in the tenant state." },
45945
+ { "id": "onboarding.attach_reference", "namespace": "onboarding", "action": "attach_reference", "title": "Attach reference document", "description": "Attach a company reference document (text/markdown) so Compass and Charters can cite it. Reference-only \u2014 it does not build a Compass; convert each meaningful doc to markdown and attach it with a title, kind, and source.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "text", "flag": "text", "type": "string", "required": true }, { "name": "filename", "flag": "filename", "type": "string", "required": false }, { "name": "mime_type", "flag": "mime-type", "type": "enum", "required": false, "enumValues": ["text/plain", "text/markdown", "text/csv"] }, { "name": "title", "flag": "title", "type": "string", "required": false }, { "name": "kind", "flag": "kind", "type": "enum", "required": false, "enumValues": ["plan", "financial", "org_chart", "process"] }, { "name": "source", "flag": "source", "type": "string", "required": false }], "hasComplexInput": false, "help": "Convert each meaningful company doc to markdown and attach it as a reference (title, kind, source) so Compass and Charters can cite it; this attaches a reference, it does not build a Compass \u2014 author Compass directly.", "example": { "text": "# Company handbook\n\nWe build precision components for the aerospace supply chain.", "filename": "handbook.md", "mime_type": "text/markdown", "title": "Company handbook", "kind": "plan", "source": "handbook/overview.md" } },
45946
+ { "id": "onboarding.create_invite", "namespace": "onboarding", "action": "create_invite", "title": "Create onboarding invite", "description": "Create a pending invite for an onboarding team member.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "email", "flag": "email", "type": "string", "required": true }, { "name": "role", "flag": "role", "type": "enum", "required": false, "enumValues": ["owner", "steward", "member"] }], "hasComplexInput": true, "help": "Invites should give humans access to the company without assigning work directly to people instead of seats." },
45947
+ { "id": "onboarding.finish", "namespace": "onboarding", "action": "finish", "title": "Finish onboarding", "description": "Mark onboarding complete after the existing onboarding requirements pass.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Finish onboarding when the graph, at least one Charter, and the first operating rhythm are clear." },
45948
+ { "id": "onboarding.status", "namespace": "onboarding", "action": "status", "title": "Onboard status", "description": "Return current onboarding progress, graph summary, and the next recommended actions.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Start by checking onboarding status, then use the implementation method guide to choose the next setup step." },
45949
+ { "id": "onboarding.upload_context", "namespace": "onboarding", "action": "upload_context", "title": "Upload org context", "description": "Compatibility alias for onboarding.attach_reference: attach a company reference document (text/markdown) that Compass and Charters can cite. Reference-only \u2014 it does not build a Compass.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "text", "flag": "text", "type": "string", "required": true }, { "name": "filename", "flag": "filename", "type": "string", "required": false }, { "name": "mime_type", "flag": "mime-type", "type": "enum", "required": false, "enumValues": ["text/plain", "text/markdown", "text/csv"] }, { "name": "title", "flag": "title", "type": "string", "required": false }, { "name": "kind", "flag": "kind", "type": "enum", "required": false, "enumValues": ["plan", "financial", "org_chart", "process"] }, { "name": "source", "flag": "source", "type": "string", "required": false }], "hasComplexInput": false, "help": "Compatibility alias for onboarding.attach_reference: attach a company reference document so Compass and Charters can cite it. It does not build a Compass.", "example": { "text": "# Company handbook\n\nWe build precision components for the aerospace supply chain.", "filename": "handbook.md", "mime_type": "text/markdown", "title": "Company handbook", "kind": "plan", "source": "handbook/overview.md" } },
45950
+ { "id": "runner.diagnose", "namespace": "runner", "action": "diagnose", "title": "Diagnose runner", "description": "Returns a runner's health, capabilities, and repair guidance without exposing secrets.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "runner_id", "flag": "runner-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Inspect a runner's health, capabilities, and get repair guidance without exposing secrets." },
45951
+ { "id": "runner.list", "namespace": "runner", "action": "list", "title": "List runners", "description": "List local runners registered to the tenant with online/offline/revoked state.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "include_revoked", "flag": "include-revoked", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "List local runners and their online/offline/revoked state before queueing runner work." },
45952
+ { "id": "runner.pairing.start", "namespace": "runner", "action": "pairing.start", "title": "Start runner pairing", "description": "Open a runner pairing session and return the human pairing code and URL. The runner bearer secret is never returned here.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "name", "flag": "name", "type": "string", "required": true }, { "name": "platform", "flag": "platform", "type": "string", "required": true }], "hasComplexInput": false, "help": "Open a runner pairing session and share the user code; the runner bearer secret is never surfaced here." },
45953
+ { "id": "runner.repair", "namespace": "runner", "action": "repair", "title": "Runner repair guidance", "description": "Returns actionable repair steps for a runner: restart, re-pair, revoke stale, or install missing CLI runtime. No secrets exposed.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "runner_id", "flag": "runner-id", "type": "string", "required": true }, { "name": "issue", "flag": "issue", "type": "enum", "required": false, "enumValues": ["restart", "re_pair", "revoke_stale", "missing_cli_runtime"] }], "hasComplexInput": false, "help": "Get focused repair steps for a runner: restart, re-pair, revoke a stale runner, or install missing CLI runtime." },
45954
+ { "id": "runner.revoke", "namespace": "runner", "action": "revoke", "title": "Revoke runner", "description": "Revoke a runner so it can no longer authenticate or claim work.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "runner_id", "flag": "runner-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Revoke a runner when a machine should no longer authenticate or claim work; this is a human-gated action." },
45955
+ { "id": "runner.status", "namespace": "runner", "action": "status", "title": "Runner status", "description": "Read a single runner's capability and online/offline/revoked state.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "runner_id", "flag": "runner-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Check a runner's capability and heartbeat state when diagnosing offline work." },
45956
+ { "id": "seat.create", "namespace": "seat", "action": "create", "title": "Create seat", "description": "Create a Responsibility Graph seat.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "name", "flag": "name", "type": "string", "required": true }, { "name": "parent_seat_id", "flag": "parent-seat-id", "type": "string", "required": false }, { "name": "seat_type", "flag": "seat-type", "type": "enum", "required": false, "enumValues": ["human", "agent", "hybrid"] }], "hasComplexInput": false, "help": "Create seats from functions before assigning people or agents." },
45957
+ { "id": "seat.decommission", "namespace": "seat", "action": "decommission", "title": "Decommission seat", "description": "Retire a seat: end occupancies, archive the active charter, revoke seat tokens/credentials, cancel schedules, and emit a tombstone event. Blocks if it would leave another live agent without a human steward chain.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Retiring a seat ends occupancies, archives the active Charter, revokes seat tokens and credentials, and emits a tombstone event. No-orphan guarded. To retire only the agent and keep the seat, use agent.decommission." },
45958
+ { "id": "seat.decommission_preview", "namespace": "seat", "action": "decommission_preview", "title": "Preview seat decommission", "description": "Show exactly what retiring a seat would end, revoke, archive, or expire without mutating state. The no-orphan steward guard is still checked when the real decommission executes.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Preview the occupancies, agents, Charter versions, tokens, credentials, work orders, and schedules that seat.decommission would affect without mutating state." },
45959
+ { "id": "seat.get", "namespace": "seat", "action": "get", "title": "Get seat detail", "description": "Return seat profile, steward chain, occupancy, Charter ids, agent status, token metadata, and open-work counts.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Inspect a seat's Charter ids, steward chain, occupancy, agent status, token metadata, and open-work counts before acting on it." },
45960
+ { "id": "seat.rename", "namespace": "seat", "action": "rename", "title": "Rename seat", "description": "Rename a Responsibility Graph seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "name", "flag": "name", "type": "string", "required": true }], "hasComplexInput": false, "help": "Seat names should describe the function and accountability clearly." },
45961
+ { "id": "seat.reparent", "namespace": "seat", "action": "reparent", "title": "Reparent seat", "description": "Move a Responsibility Graph seat under a new parent.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "new_parent_seat_id", "flag": "new-parent-seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Reparent seats only when it clarifies accountable structure and preserves a clean graph." },
45962
+ { "id": "seat.set_type", "namespace": "seat", "action": "set_type", "title": "Set seat type", "description": "Set a Responsibility Graph seat type.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "seat_type", "flag": "seat-type", "type": "enum", "required": true, "enumValues": ["human", "agent", "hybrid"] }], "hasComplexInput": false, "help": "Seat type should follow the work, risk, measurable, and stewardship model." },
45963
+ { "id": "settings.agent_policy.get", "namespace": "settings", "action": "agent_policy.get", "title": "Get company autonomy ceiling", "description": "Read this company's Company Guardrails ceiling (ADR-0007): the profile, enforcement mode, and the most an agent may do autonomously (max_autonomous_risk). Returns metadata only.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read this company's autonomy ceiling (Company Guardrails, ADR-0007): profile, enforcement mode, and the most an agent may do autonomously." },
45964
+ { "id": "settings.agent_policy.update", "namespace": "settings", "action": "agent_policy.update", "title": "Set company autonomy ceiling", "description": "Set the Company Guardrails ceiling (ADR-0007): a named profile (locked_down, balanced, high_autonomy) or custom + max_autonomous_risk. Tenant-admin and human-gated. An explicitly set ceiling is ENFORCED by default; pass enforcement=observe to stage a change without blocking.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "profile", "flag": "profile", "type": "enum", "required": true, "enumValues": ["locked_down", "balanced", "high_autonomy", "custom"] }, { "name": "max_autonomous_risk", "flag": "max-autonomous-risk", "type": "enum", "required": false, "enumValues": ["low", "medium", "high", "critical"] }, { "name": "enforcement", "flag": "enforcement", "type": "enum", "required": false, "enumValues": ["observe", "enforce"] }], "hasComplexInput": false, "help": "Set the company autonomy ceiling: a profile (locked_down, balanced, high_autonomy) or custom + max_autonomous_risk. Owner-only, human-gated, and enforced by default." },
45965
+ { "id": "settings.get", "namespace": "settings", "action": "get", "title": "Get tenant settings", "description": "Read tenant operating settings: plan, status, spend/budgets, integration status, and notification preferences. Returns metadata only.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read tenant operating settings: plan, spend, budgets, integration status, and notification preferences. No secrets." },
45966
+ { "id": "settings.product_learning.get", "namespace": "settings", "action": "product_learning.get", "title": "Get product-learning policy", "description": "Read whether product/page/recommendation analytics may be recorded for this tenant. Security and audit logs remain enabled in every mode.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read whether product/page/recommendation analytics are allowed for the tenant; security and audit logs always stay enabled." },
45967
+ { "id": "settings.product_learning.update", "namespace": "settings", "action": "product_learning.update", "title": "Update product-learning policy", "description": "Set tenant product-learning participation. Disabled and enterprise-contract modes block generic product analytics writes, but not security/audit logs.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "mode", "flag": "mode", "type": "enum", "required": true, "enumValues": ["enabled", "disabled", "enterprise_contract"] }], "hasComplexInput": false, "help": "Set tenant product-learning mode to enabled, disabled, or enterprise_contract; the change is human-gated." },
45968
+ { "id": "settings.sync_brief_scope.get", "namespace": "settings", "action": "sync_brief_scope.get", "title": "Get Sync Brief scope", "description": "Read the tenant's Sync Brief scope: company_wide (one weekly brief) or per_cluster (one brief per cluster).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read whether weekly Sync Briefs compile company-wide (one brief) or per cluster (one brief per cluster)." },
45969
+ { "id": "settings.sync_brief_scope.update", "namespace": "settings", "action": "sync_brief_scope.update", "title": "Update Sync Brief scope", "description": "Set the tenant's Sync Brief scope (company_wide or per_cluster). Per_cluster falls back to company-wide when the tenant has no clusters.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "sync_brief_scope", "flag": "sync-brief-scope", "type": "enum", "required": true, "enumValues": ["company_wide", "per_cluster"] }], "hasComplexInput": false, "help": "Set Sync Brief scope to company_wide or per_cluster; per_cluster falls back to company-wide when no clusters exist." },
45970
+ { "id": "settings.update", "namespace": "settings", "action": "update", "title": "Update tenant settings", "description": "Update tenant AI budget caps (soft/hard, USD). Budget changes are dangerous and gated.", "requiredScope": "tenant", "confirmation": "dangerous", "exposeOverMcp": true, "fields": [{ "name": "soft_cap_usd", "flag": "soft-cap-usd", "type": "string", "required": false }, { "name": "hard_cap_usd", "flag": "hard-cap-usd", "type": "string", "required": false }], "hasComplexInput": false, "help": "Update tenant AI budget caps; budget changes are dangerous and require human confirmation." },
45971
+ { "id": "signal.confirm_reading", "namespace": "signal", "action": "confirm_reading", "title": "Confirm Signal reading", "description": "Confirm an unconfirmed reading as human-verified. Humans confirm; agents cannot. Idempotent on an already-confirmed reading.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "reading_id", "flag": "reading-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Confirm an unconfirmed reading as human-verified; confirmation is a human act, not an agent one." },
45972
+ { "id": "signal.correct_reading", "namespace": "signal", "action": "correct_reading", "title": "Correct Signal reading", "description": "Overwrite a reading for a period with a human-confirmed value. A manual correction is a human decision and is gated behind confirmation.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "measurable_id", "flag": "measurable-id", "type": "string", "required": true }, { "name": "period_start", "flag": "period-start", "type": "string", "required": true }, { "name": "value", "flag": "value", "type": "number", "required": true }], "hasComplexInput": false, "help": "Correct a reading only as a human; manual corrections that change confirmed data require confirmation." },
45973
+ { "id": "signal.get", "namespace": "signal", "action": "get", "title": "Get Signal", "description": "Return a measurable definition with its full reading history (confirmed and unconfirmed).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "measurable_id", "flag": "measurable-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Read a measurable's full reading history before confirming or correcting a value." },
45974
+ { "id": "signal.import", "namespace": "signal", "action": "import", "title": "Import Signals from CSV", "description": "Bulk-import measurable definitions and their historical readings from a parsed scorecard export (e.g. a ninety CSV). Owners are seat names resolved to seats; readings are human-confirmed. Idempotent \u2014 re-import upserts by (measurable, period, cadence). Re-importing a measurable at a different cadence is rejected, not overwritten.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "dry_run", "flag": "dry-run", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Bulk-import measurables + historical readings from a parsed scorecard export (owners resolve to seats); idempotent, human-confirmed, re-import upserts by period." },
45975
+ { "id": "signal.list", "namespace": "signal", "action": "list", "title": "List Signals", "description": "List measurable definitions with their latest reading and on/off-track state. Seat-scoped callers see only their own seat.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List Signals to find measurable ids and current on/off-track state before recording or correcting readings." },
45976
+ { "id": "signup.provision_tenant", "namespace": "signup", "action": "provision_tenant", "title": "Create company", "description": "Provision a new company (tenant) for the authenticated CLI user with no web step.", "requiredScope": "user", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "company_name", "flag": "company-name", "type": "string", "required": true }], "hasComplexInput": false, "help": "Create the company headlessly when the CLI session has no tenant yet; it becomes the user's active tenant so the rest of setup runs with no web step." },
45977
+ { "id": "skill.assign_to_seat", "namespace": "skill", "action": "assign_to_seat", "title": "Assign skill to seat", "description": "Propose or human-approve a published immutable skill version for a Seat after checking required and optional tool dependencies.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "slug", "flag": "slug", "type": "string", "required": false }, { "name": "skill_version_id", "flag": "skill-version-id", "type": "string", "required": false }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["proposed", "approved"] }, { "name": "rationale", "flag": "rationale", "type": "string", "required": true }, { "name": "allow_blocked_proposal", "flag": "allow-blocked-proposal", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Propose or human-approve a published Skill for a Seat after dependency checks. Missing required tools block approval; optional tools are warnings only." },
45978
+ { "id": "skill.assigned.list", "namespace": "skill", "action": "assigned.list", "title": "List assigned skills", "description": "List approved skill assignments for a Seat, including immutable version, dependency status, rationale, and approval time. Seat-scoped callers can only read their own assignments.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List approved Skills assigned to a Seat before loading instructions into a run. A seat-scoped token can only read its own assigned Skills." },
45979
+ { "id": "skill.catalog", "namespace": "skill", "action": "catalog", "title": "List ROST skill catalog", "description": "List ROST-maintained catalog skills the active tenant is entitled to see. Private source URLs are never returned.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "query", "flag": "query", "type": "string", "required": false }, { "name": "include_unentitled", "flag": "include-unentitled", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "List entitled ROST catalog Skills. Private catalog source locations stay server-side; agents install from ROST APIs, not private GitHub." },
45980
+ { "id": "skill.check_dependencies", "namespace": "skill", "action": "check_dependencies", "title": "Check skill dependencies", "description": "Compare a skill version's required and optional tools against a Seat's active or draft Charter permission manifest. Returns ready, blocked, or warning plus suggested agent.configure_tools input; it does not grant permissions.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "skill_version_id", "flag": "skill-version-id", "type": "string", "required": false }, { "name": "slug", "flag": "slug", "type": "string", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Compare a Skill's required and optional tools with a Seat's signed Charter manifest. Missing tools must be connected through agent.configure_tools; the Skill never grants authority." },
45981
+ { "id": "skill.create", "namespace": "skill", "action": "create", "title": "Create skill", "description": "Create a tenant skill draft or pending-review skill from a bounded SKILL.md package. Skills store reusable know-how only; they do not grant tools.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["draft", "pending_review"] }], "hasComplexInput": true, "help": "Create a draft Skill from a bounded SKILL.md package only when the procedure is reusable operating know-how, not authorization or one-off task context." },
45982
+ { "id": "skill.enable_catalog", "namespace": "skill", "action": "enable_catalog", "title": "Enable ROST catalog skill", "description": "Human-gated enablement of an entitled ROST catalog skill into the tenant-owned Skills library, preserving catalog provenance and content hash.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "slug", "flag": "slug", "type": "string", "required": true }], "hasComplexInput": false, "help": "Enable an entitled ROST catalog Skill into the company library with human confirmation, preserving catalog provenance and immutable content hash." },
45983
+ { "id": "skill.file.get", "namespace": "skill", "action": "file.get", "title": "Get skill file", "description": "Read stored skill package file content by slug and package path. The path is resolved only inside the stored package payload; it never reads the server filesystem.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "slug", "flag": "slug", "type": "string", "required": true }, { "name": "path", "flag": "path", "type": "string", "required": true }], "hasComplexInput": false, "help": "Read a stored Skill package file by package path only; use SKILL.md for full instructions and supporting files only when the descriptor says they are needed." },
45984
+ { "id": "skill.get", "namespace": "skill", "action": "get", "title": "Get skill", "description": "Read one skill descriptor and latest stored version metadata. Seat-scoped callers can read only approved assigned published skills.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "slug", "flag": "slug", "type": "string", "required": true }], "hasComplexInput": false, "help": "Read a Skill descriptor and latest version metadata before deciding whether to reuse it, inspect its files, or create a new Skill." },
45985
+ { "id": "skill.import_github", "namespace": "skill", "action": "import_github", "title": "Import GitHub skill", "description": "Import a public GitHub skill package into pending review or draft after bounded package validation.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "url", "flag": "url", "type": "string", "required": true }, { "name": "ref", "flag": "ref", "type": "string", "required": false }, { "name": "path", "flag": "path", "type": "string", "required": false }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["draft", "pending_review"] }], "hasComplexInput": false, "help": "Import a public GitHub Skill package into draft or pending review after validation; imported Skills are untrusted until reviewed and published." },
45986
+ { "id": "skill.import_upload", "namespace": "skill", "action": "import_upload", "title": "Import uploaded skill", "description": "Import a bounded text skill package into the tenant library as a draft or pending-review skill.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["draft", "pending_review"] }], "hasComplexInput": true, "help": "Import a bounded text Skill package; never include secrets, private one-off task context, or authority rules that belong in the Charter." },
45987
+ { "id": "skill.install_local", "namespace": "skill", "action": "install_local", "title": "Install skill locally", "description": "Resolve an approved company skill or entitled ROST catalog skill for local CLI installation. The server returns package files; it never exposes private GitHub URLs or tokens.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "slug", "flag": "slug", "type": "string", "required": true }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "client", "flag": "client", "type": "enum", "required": true, "enumValues": ["claude-code", "codex", "cursor"] }, { "name": "version", "flag": "version", "type": "integer", "required": false }, { "name": "local_only", "flag": "local-only", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Resolve company or entitled ROST catalog Skill files for local CLI installation. The returned package comes from ROST APIs and never includes private GitHub tokens or URLs." },
45988
+ { "id": "skill.list", "namespace": "skill", "action": "list", "title": "List skills", "description": "List tenant skills with application descriptors, dependency metadata, source status, latest version, and assigned Seat count. Seat-scoped callers see only approved assigned published skills.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["draft", "pending_review", "published", "archived"] }, { "name": "visibility", "flag": "visibility", "type": "enum", "required": false, "enumValues": ["private", "seat", "tenant"] }, { "name": "query", "flag": "query", "type": "string", "required": false }, { "name": "include_archived", "flag": "include-archived", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "List reusable Skills before creating or assigning new agent operating knowledge. Seat-scoped callers only see assigned, approved, published Skills." },
45989
+ { "id": "skill.publish", "namespace": "skill", "action": "publish", "title": "Publish skill", "description": "Human-gated publication of a reviewed skill version. Published versions become immutable and can be assigned to Seats.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "slug", "flag": "slug", "type": "string", "required": false }, { "name": "skill_version_id", "flag": "skill-version-id", "type": "string", "required": false }, { "name": "allow_warnings", "flag": "allow-warnings", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Publish a reviewed Skill version only with human confirmation. Publishing makes the version immutable and assignable, but it still grants no tools." },
45990
+ { "id": "skill.revoke_from_seat", "namespace": "skill", "action": "revoke_from_seat", "title": "Revoke skill from seat", "description": "Human-gated revocation of a Seat skill assignment. Revocation stops future skill use without deleting historical run activations.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "assignment_id", "flag": "assignment-id", "type": "string", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "slug", "flag": "slug", "type": "string", "required": false }, { "name": "skill_version_id", "flag": "skill-version-id", "type": "string", "required": false }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "Revoke future use of an assigned Skill with human confirmation while preserving historical run activation records." },
45991
+ { "id": "skill.sync_local", "namespace": "skill", "action": "sync_local", "title": "Sync assigned skills locally", "description": "Resolve all approved published skills assigned to a Seat for local CLI installation. Revoked assignments are reported so the client can mark stale local copies.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "client", "flag": "client", "type": "enum", "required": true, "enumValues": ["claude-code", "codex", "cursor"] }], "hasComplexInput": false, "help": "Resolve all approved Skills assigned to a local agent Seat so the CLI can install or update unchanged-by-hash local copies." },
45992
+ { "id": "skill.update_draft", "namespace": "skill", "action": "update_draft", "title": "Update skill draft", "description": "Replace or create the current unpublished draft version for an existing skill from a bounded SKILL.md package.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "slug", "flag": "slug", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["draft", "pending_review"] }], "hasComplexInput": true, "help": "Update the current unpublished Skill draft; published versions stay immutable, so durable corrections should become reviewed new versions." },
45993
+ { "id": "staffing.assign", "namespace": "staffing", "action": "assign", "title": "Staff seat", "description": "Compatibility command for the DER-626 MCP staffing tool.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Staff a seat only after the function, Charter, and human accountability are clear." },
45994
+ { "id": "staffing.assign_agent_dry_run", "namespace": "staffing", "action": "assign_agent_dry_run", "title": "Assign dry-run agent to seat", "description": "Assign an agent occupancy while the agent remains in dry-run.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "agent_id", "flag": "agent-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Start agent staffing with dry runs and a named human Steward." },
45995
+ { "id": "staffing.assign_user", "namespace": "staffing", "action": "assign_user", "title": "Assign user to seat", "description": "Assign a human user occupancy to a seat.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "user_id", "flag": "user-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Assign humans to seats after the seat accountability is clear." },
45996
+ { "id": "status.record", "namespace": "status", "action": "record", "title": "Record status", "description": "Record a status event and readings/goal status for the acting seat's Signals and goals.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": true, "help": "Record Signal readings and goal status only for measurables and goals the seat owns; agent readings stay unconfirmed." },
45997
+ { "id": "sync.brief.compile", "namespace": "sync", "action": "brief.compile", "title": "Compile Sync Brief", "description": "Compile (or recompile) the weekly Sync Brief for the current period. Idempotent per (tenant, period, cluster): a second compile updates the existing brief.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cluster_id", "flag": "cluster-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Compile the weekly Sync Brief; compiling is idempotent per period." },
45998
+ { "id": "sync.brief.get", "namespace": "sync", "action": "brief.get", "title": "Get Sync Brief", "description": "Return a Sync Brief (a specific id, or the latest for the tenant) including its compiled agenda document.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "sync_brief_id", "flag": "sync-brief-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Read the latest or a specific Sync Brief and its agenda before running the meeting." },
45999
+ { "id": "sync.item.assign", "namespace": "sync", "action": "item.assign", "title": "Assign Sync follow-up", "description": "Create a follow-up task (a seat commitment) from a Sync agenda item. The brief and owner seat must belong to the tenant.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "sync_brief_id", "flag": "sync-brief-id", "type": "string", "required": true }, { "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": true }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "description", "flag": "description", "type": "string", "required": true }, { "name": "due_on", "flag": "due-on", "type": "string", "required": false }], "hasComplexInput": false, "help": "Create a follow-up task from a Sync agenda item so a seat owns the commitment." },
46000
+ { "id": "sync.run.complete", "namespace": "sync", "action": "run.complete", "title": "Complete Sync run", "description": "Record that the weekly Sync meeting completed against a brief, capturing the decisions and tasks created since it compiled. Idempotent: a second completion does not write a duplicate event.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "sync_brief_id", "flag": "sync-brief-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Record that the Sync meeting completed; completion is idempotent per brief." },
46001
+ { "id": "sync.run.start", "namespace": "sync", "action": "run.start", "title": "Start Sync run", "description": "Ensure a Sync Brief exists for the current period so the meeting can begin. Compiles the brief if needed (idempotent).", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cluster_id", "flag": "cluster-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Ensure a Sync Brief exists for the current period so the weekly meeting can begin." },
46002
+ { "id": "system.health", "namespace": "system", "action": "health", "title": "System health", "description": "Return a scoped health snapshot for agent runs, errors, Signals, Cascade setup, work loop, integrations, runners, notifications, and Sync Brief readiness.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Read a scoped system health snapshot across agent runs, errors, Signals, Cascade setup, work loop, integrations, runners, notifications, and Sync Brief readiness." },
46003
+ { "id": "task.accept", "namespace": "task", "action": "accept", "title": "Accept task", "description": "Accept an offered handoff task owned by the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Accept an offered task only when the seat can deliver it within its Charter." },
46004
+ { "id": "task.complete", "namespace": "task", "action": "complete", "title": "Complete task", "description": "Complete an accepted handoff task and emit a handoff event back to the requesting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }, { "name": "summary", "flag": "summary", "type": "string", "required": true }], "hasComplexInput": true, "help": "Complete an accepted task with a summary so the requesting seat receives the handoff." },
46005
+ { "id": "task.create", "namespace": "task", "action": "create", "title": "Create task", "description": "Create a task (a commitment between seats). Agent-created tasks land in draft for human confirmation; human-created tasks are offered (handoff) or in progress.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": true }, { "name": "from_seat_id", "flag": "from-seat-id", "type": "string", "required": false }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "description", "flag": "description", "type": "string", "required": true }, { "name": "goal_id", "flag": "goal-id", "type": "string", "required": false }, { "name": "acceptance_criteria", "flag": "acceptance-criteria", "type": "array", "required": false, "itemType": "string" }, { "name": "due_on", "flag": "due-on", "type": "string", "required": false }], "hasComplexInput": false, "help": "Create a task as a commitment between seats; agent proposals land in draft for human confirmation.", "example": { "owner_seat_id": "0190dddd-dddd-7ddd-8ddd-dddddddddddd", "from_seat_id": "0190eeee-eeee-7eee-8eee-eeeeeeeeeeee", "title": "Reconcile the March vendor statements", "description": "Match every March vendor statement line to a recorded invoice and flag discrepancies.", "goal_id": "0190ffff-ffff-7fff-8fff-ffffffffffff", "acceptance_criteria": ["All March statements reconciled", "Discrepancies filed as Friction issues"], "due_on": "2026-04-15" } },
46006
+ { "id": "task.decline", "namespace": "task", "action": "decline", "title": "Decline task", "description": "Decline an offered handoff task owned by the acting seat with a reason.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": true }], "hasComplexInput": false, "help": "Decline an offered task with a clear reason when it is out of scope for the seat." },
46007
+ { "id": "task.list", "namespace": "task", "action": "list", "title": "List seat tasks", "description": "List open handoff tasks owned by the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List the seat's open handoff tasks before accepting, declining, or completing work." },
46008
+ { "id": "task.update", "namespace": "task", "action": "update", "title": "Update task", "description": "Reschedule (due date), reassign (owner seat), or edit a non-terminal task's title, description, or acceptance criteria. Terminal tasks cannot be edited \u2014 a correction is a new task.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "task_id", "flag": "task-id", "type": "string", "required": true }, { "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": false }, { "name": "due_on", "flag": "due-on", "type": "string", "required": false }, { "name": "title", "flag": "title", "type": "string", "required": false }, { "name": "description", "flag": "description", "type": "string", "required": false }, { "name": "acceptance_criteria", "flag": "acceptance-criteria", "type": "array", "required": false, "itemType": "string" }], "hasComplexInput": false, "help": "Reschedule, reassign, or edit a non-terminal task; terminal tasks are immutable (a correction is a new task)." },
46009
+ { "id": "team.health_score", "namespace": "team", "action": "health_score", "title": "Team health score", "description": "Return the single rolled-up 0\u2013100 team-health score (latest month) with its band (green/yellow/red) and label. Honest insufficient-data state when no metrics exist yet.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Read the single rolled-up 0-100 team-health score (latest month) with its band and label." },
46010
+ { "id": "tenant.anthropic_key.save", "namespace": "tenant", "action": "anthropic_key.save", "title": "Save tenant Anthropic key", "description": "Store a tenant-scoped Anthropic key in the configured vault.", "requiredScope": "tenant", "confirmation": "credential_flow", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "secretBlocked": true, "help": "Save model-provider credentials only through vault-backed flows and keep raw keys out of prompts, logs, and command metadata." },
46011
+ { "id": "tenant.create", "namespace": "tenant", "action": "create", "title": "Create additional company", "description": "Create a new clean company for an already-provisioned account after checking tenant.create.additional entitlement.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "company_name", "flag": "company-name", "type": "string", "required": true }], "hasComplexInput": false, "help": "Create an additional clean company from an existing company session. Requires tenant.create.additional entitlement; first-company bootstrap stays signup.provision_tenant." },
46012
+ { "id": "tenant.rename", "namespace": "tenant", "action": "rename", "title": "Rename company", "description": "Rename the current tenant/company. The rename is human-gated and writes an audit event.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "company_name", "flag": "company-name", "type": "string", "required": true }], "hasComplexInput": false, "help": "Rename the current company; owner-only, human-gated, and audited as an event." },
46013
+ { "id": "tool.catalog", "namespace": "tool", "action": "catalog", "title": "List tool catalog", "description": "List the discoverable tool catalog the agent builder reads \u2014 tool id, title, provider, prescriptive description, default scope tiers, credential requirement, access policy, and execution-boundary guidance.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "provider", "flag": "provider", "type": "string", "required": false }], "hasComplexInput": false, "help": "List the tool catalog the builder reads \u2014 id, prescriptive description, scope tiers, credential requirement, access policy, and execution-boundary guidance." },
46014
+ { "id": "usage.report", "namespace": "usage", "action": "report", "title": "AI-workforce ROI report", "description": "Return the tenant's immutable per-period usage snapshots \u2014 agents ran, outputs, token/run cost, human-accepted value, exceptions, and approvals \u2014 for the AI-workforce ROI report.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Read the AI-workforce ROI report \u2014 per-period agents/outputs/token+run cost, human-accepted value, exceptions, and approvals \u2014 from immutable usage snapshots." },
46015
+ { "id": "usage.snapshot", "namespace": "usage", "action": "snapshot", "title": "Capture usage period snapshot", "description": "Freeze the current (or a given) period's usage and accepted-value totals into an immutable snapshot for the ROI report. Insert-only and idempotent \u2014 re-running a captured period changes nothing.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": true, "help": "Freeze the current period's usage and accepted-value totals into an immutable snapshot for the ROI report; insert-only and idempotent, so re-running a captured period changes nothing." },
46016
+ { "id": "user.tenants", "namespace": "user", "action": "tenants", "title": "List tenants", "description": "List tenants accessible to the authenticated CLI user.", "requiredScope": "user", "confirmation": "none", "exposeOverMcp": false, "fields": [], "hasComplexInput": false, "help": "List available companies before choosing the tenant where setup work should happen." },
46017
+ { "id": "user.use_tenant", "namespace": "user", "action": "use_tenant", "title": "Select tenant", "description": "Validate and return an active tenant selection for the authenticated CLI user.", "requiredScope": "user", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "tenant", "flag": "tenant", "type": "string", "required": true }], "hasComplexInput": false, "help": "Set the active tenant explicitly before running onboarding, graph, Charter, or staffing commands." },
46018
+ { "id": "user.whoami", "namespace": "user", "action": "whoami", "title": "Who am I", "description": "Return the authenticated CLI user and accessible tenant roles.", "requiredScope": "user", "confirmation": "none", "exposeOverMcp": false, "fields": [], "hasComplexInput": false, "help": "Use session identity checks before making tenant-scoped recommendations or setup changes." },
46019
+ { "id": "work_order.cancel", "namespace": "work_order", "action": "cancel", "title": "Cancel work order", "description": "Cancel a queued, claimed, or running work order. Already-terminal orders return a stable error.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "work_order_id", "flag": "work-order-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Cancel a queued, claimed, or running work order; this is a human-gated action." },
46020
+ { "id": "work_order.enqueue", "namespace": "work_order", "action": "enqueue", "title": "Enqueue work order", "description": "Queue a work order for a live scheduled agent. Idempotent per (agent, scheduled time).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "agent_id", "flag": "agent-id", "type": "string", "required": true }, { "name": "scheduled_for", "flag": "scheduled-for", "type": "string", "required": false }, { "name": "task_id", "flag": "task-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Queue a work order for a live scheduled agent; enqueue is idempotent per agent and scheduled time." },
46021
+ { "id": "work_order.list", "namespace": "work_order", "action": "list", "title": "List work orders", "description": "List runner/cloud work orders for the tenant, optionally filtered by status, agent, or runner.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["queued", "claimed", "running", "done", "failed", "expired"] }, { "name": "agent_id", "flag": "agent-id", "type": "string", "required": false }, { "name": "runner_id", "flag": "runner-id", "type": "string", "required": false }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Inspect queued, claimed, running, and expired work orders to understand runner activity." },
46022
+ { "id": "work.log", "namespace": "work", "action": "log", "title": "Log work", "description": "Write a lightweight activity breadcrumb event for the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "note", "flag": "note", "type": "string", "required": true }], "hasComplexInput": false, "help": "Log a lightweight work breadcrumb so the seat's activity is visible without durable side effects." }
46023
+ ];
46024
+
46025
+ // src/generator/groups.ts
45828
46026
  import { readFileSync as readFileSync2 } from "node:fs";
46027
+
46028
+ // src/generator/runtime.ts
45829
46029
  var UsageError = class extends Error {
45830
46030
  };
46031
+ var SECRET_ARGV_GUIDANCE = "This command stores a secret and cannot accept it from the command line. Provide the secret through the vault-backed flow \u2014 web Settings or the integration connect flow \u2014 never as a CLI argument (a flag, --input, or --json body would expose it in shell history and process arguments).";
45831
46032
  function parseFlags(args, booleanFlags = /* @__PURE__ */ new Set()) {
45832
46033
  const values = /* @__PURE__ */ new Map();
45833
46034
  const flags = /* @__PURE__ */ new Set();
@@ -45880,17 +46081,6 @@ function optionalValue(parsed, key) {
45880
46081
  const value = parsed.values.get(key);
45881
46082
  return value === void 0 || value.length === 0 ? void 0 : value;
45882
46083
  }
45883
- function optionalNumber(parsed, key) {
45884
- const raw = optionalValue(parsed, key);
45885
- if (raw === void 0) {
45886
- return void 0;
45887
- }
45888
- const parsedNumber = Number(raw);
45889
- if (!Number.isSafeInteger(parsedNumber)) {
45890
- throw new UsageError(`--${key} must be an integer.`);
45891
- }
45892
- return parsedNumber;
45893
- }
45894
46084
  function parseNumber(parsed, key, options) {
45895
46085
  const raw = parsed.values.get(key);
45896
46086
  if (raw === void 0 || raw.length === 0) {
@@ -45934,6 +46124,53 @@ function field(record2, key) {
45934
46124
  }
45935
46125
  return String(value);
45936
46126
  }
46127
+ function usageWithSchemaFooter(usage2, bin) {
46128
+ return `${usage2}
46129
+ discover a command's exact input with: ${bin} command schema <id>`;
46130
+ }
46131
+ async function dispatch(context, group, args, actions, usage2) {
46132
+ const usageText = usageWithSchemaFooter(usage2, context.binName);
46133
+ const action = args[0];
46134
+ if (action === "--help" || action === "-h" || action === "help") {
46135
+ context.io.stdout.write(`${usageText}
46136
+ `);
46137
+ return 0;
46138
+ }
46139
+ const handler = action === void 0 ? void 0 : actions[action];
46140
+ if (!handler) {
46141
+ context.io.stderr.write(`${usageText}
46142
+ `);
46143
+ return 1;
46144
+ }
46145
+ try {
46146
+ return await handler(context, args.slice(1));
46147
+ } catch (error51) {
46148
+ if (error51 instanceof UsageError) {
46149
+ context.io.stderr.write(`${error51.message}
46150
+ ${usageText}
46151
+ `);
46152
+ return 1;
46153
+ }
46154
+ throw error51;
46155
+ }
46156
+ }
46157
+ function execute(context, parsed, commandId, body, format) {
46158
+ const autoConfirm = parsed.flags.has("yes") || parsed.flags.has("y");
46159
+ const options = {
46160
+ ...parsed.seat === void 0 ? {} : { targetSeatId: parsed.seat },
46161
+ ...autoConfirm ? { autoConfirm: true } : {}
46162
+ };
46163
+ if (parsed.json) {
46164
+ return context.run(context.client, commandId, body, void 0, options);
46165
+ }
46166
+ return context.run(context.client, commandId, body, format, options);
46167
+ }
46168
+
46169
+ // src/generator/render.ts
46170
+ function markdownLine(output) {
46171
+ const markdown = asRecord(output).markdown;
46172
+ return typeof markdown === "string" ? markdown : JSON.stringify(output, null, 2);
46173
+ }
45937
46174
  function dryRunToolActionLabel(status) {
45938
46175
  switch (status) {
45939
46176
  case "intended":
@@ -45964,10 +46201,62 @@ function formatDryRunTranscript(value) {
45964
46201
  });
45965
46202
  return ["rehearsal:", ...lines, ...toolPreview.length > 0 ? ["tool preview:", ...toolPreview] : []].join("\n");
45966
46203
  }
45967
- function markdownLine(output) {
45968
- const markdown = asRecord(output).markdown;
45969
- return typeof markdown === "string" ? markdown : JSON.stringify(output, null, 2);
46204
+ function isScalar(value) {
46205
+ return value === null || ["string", "number", "boolean"].includes(typeof value);
46206
+ }
46207
+ function orderedEntries(record2) {
46208
+ const entries = Object.entries(record2);
46209
+ const idLike = (key) => key === "id" || key.endsWith("_id");
46210
+ return [...entries.filter(([key]) => idLike(key)), ...entries.filter(([key]) => !idLike(key))];
46211
+ }
46212
+ function renderRow(record2) {
46213
+ const parts = orderedEntries(record2).filter(([, value]) => isScalar(value)).map(([key, value]) => `${key}=${value === null ? "\u2014" : String(value)}`);
46214
+ return parts.join(" ");
46215
+ }
46216
+ function humanize(name) {
46217
+ return name.replace(/_/g, " ");
45970
46218
  }
46219
+ function renderCommandOutput(output) {
46220
+ if (Array.isArray(output)) {
46221
+ if (output.length === 0) {
46222
+ return "No results.";
46223
+ }
46224
+ return output.map((entry) => isScalar(entry) ? String(entry) : renderRow(asRecord(entry))).join("\n");
46225
+ }
46226
+ const record2 = asRecord(output);
46227
+ if (typeof record2.markdown === "string") {
46228
+ return record2.markdown;
46229
+ }
46230
+ const arrayEntries = Object.entries(record2).filter(([, value]) => Array.isArray(value));
46231
+ const scalarEntries = Object.entries(record2).filter(([, value]) => isScalar(value));
46232
+ if (arrayEntries.length === 1 && scalarEntries.length === 0) {
46233
+ const [name, list] = arrayEntries[0];
46234
+ if (list.length === 0) {
46235
+ return `No ${humanize(name)}.`;
46236
+ }
46237
+ return list.map((entry) => isScalar(entry) ? String(entry) : renderRow(asRecord(entry))).join("\n");
46238
+ }
46239
+ const lines = [];
46240
+ for (const [key, value] of orderedEntries(record2)) {
46241
+ if (isScalar(value)) {
46242
+ lines.push(`${key}=${value === null ? "\u2014" : String(value)}`);
46243
+ } else if (Array.isArray(value)) {
46244
+ lines.push(`${key}:`);
46245
+ if (value.length === 0) {
46246
+ lines.push(` (none)`);
46247
+ } else {
46248
+ for (const entry of value) {
46249
+ lines.push(` ${isScalar(entry) ? String(entry) : renderRow(asRecord(entry))}`);
46250
+ }
46251
+ }
46252
+ } else {
46253
+ lines.push(`${key}: ${renderRow(asRecord(value))}`);
46254
+ }
46255
+ }
46256
+ return lines.length > 0 ? lines.join("\n") : JSON.stringify(output, null, 2);
46257
+ }
46258
+
46259
+ // src/generator/groups.ts
45971
46260
  var CLI_MODEL_TIER_MAP = {
45972
46261
  triage: { model: "claude-haiku-4-5", effort: "low" },
45973
46262
  balanced: { model: "claude-sonnet-4-6", effort: "medium" },
@@ -45987,58 +46276,36 @@ function resolveModelConfig(model, effort) {
45987
46276
  ...resolvedEffort ? { effort: resolvedEffort } : {}
45988
46277
  };
45989
46278
  }
45990
- function usageWithSchemaFooter(usage2, bin) {
45991
- return `${usage2}
45992
- discover a command's exact input with: ${bin} command schema <id>`;
45993
- }
45994
- async function dispatch(context, group, args, actions, usage2) {
45995
- const usageText = usageWithSchemaFooter(usage2, context.binName);
45996
- const action = args[0];
45997
- if (action === "--help" || action === "-h" || action === "help") {
45998
- context.io.stdout.write(`${usageText}
45999
- `);
46000
- return 0;
46001
- }
46002
- const handler = action === void 0 ? void 0 : actions[action];
46003
- if (!handler) {
46004
- context.io.stderr.write(`${usageText}
46005
- `);
46006
- return 1;
46007
- }
46008
- try {
46009
- return await handler(context, args.slice(1));
46010
- } catch (error51) {
46011
- if (error51 instanceof UsageError) {
46012
- context.io.stderr.write(`${error51.message}
46013
- ${usageText}
46014
- `);
46015
- return 1;
46016
- }
46017
- throw error51;
46279
+ function renderTaskList(output) {
46280
+ const tasks = asArray(asRecord(output).tasks);
46281
+ if (tasks.length === 0) {
46282
+ return "No tasks in this seat's queue.";
46018
46283
  }
46284
+ return tasks.map((task) => {
46285
+ const record2 = asRecord(task);
46286
+ return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "title")}`;
46287
+ }).join("\n");
46019
46288
  }
46020
- function execute(context, parsed, commandId, body, format) {
46021
- const autoConfirm = parsed.flags.has("yes") || parsed.flags.has("y");
46022
- const options = {
46023
- ...parsed.seat === void 0 ? {} : { targetSeatId: parsed.seat },
46024
- ...autoConfirm ? { autoConfirm: true } : {}
46025
- };
46026
- if (parsed.json) {
46027
- return context.run(context.client, commandId, body, void 0, options);
46028
- }
46029
- return context.run(context.client, commandId, body, format, options);
46289
+ function renderTaskAccept(output) {
46290
+ const task = asRecord(asRecord(output).task);
46291
+ return `Accepted task ${field(task, "id")} (status ${field(task, "status")}).`;
46030
46292
  }
46031
- var graphWrapper = (context, args) => dispatch(context, "graph", args, {
46032
- show: (ctx, rest) => {
46033
- const parsed = parseFlags(rest);
46034
- return execute(ctx, parsed, "graph.get", {}, formatGraph);
46035
- },
46036
- get: (ctx, rest) => {
46037
- const parsed = parseFlags(rest);
46038
- return execute(ctx, parsed, "graph.get", {}, formatGraph);
46039
- }
46040
- }, graphUsage(context.binName));
46041
- function formatGraph(output) {
46293
+ function renderTaskDecline(output) {
46294
+ const task = asRecord(asRecord(output).task);
46295
+ return `Declined task ${field(task, "id")} (status ${field(task, "status")}).`;
46296
+ }
46297
+ function renderTaskComplete(output) {
46298
+ const record2 = asRecord(output);
46299
+ return `Completed task ${field(record2, "task_id")} (event ${field(record2, "event_id")}).`;
46300
+ }
46301
+ function renderTaskCreate(output) {
46302
+ const record2 = asRecord(output);
46303
+ return `Created task ${field(record2, "task_id")} for seat ${field(record2, "owner_seat_id")} (status ${field(record2, "status")}).`;
46304
+ }
46305
+ function renderStatusRecord(output) {
46306
+ return `Recorded status event ${field(asRecord(output), "event_id")}.`;
46307
+ }
46308
+ function renderGraph(output) {
46042
46309
  const record2 = asRecord(output);
46043
46310
  const nodes = asArray(record2.nodes);
46044
46311
  if (nodes.length === 0) {
@@ -46054,57 +46321,7 @@ function formatGraph(output) {
46054
46321
  }
46055
46322
  return lines.join("\n");
46056
46323
  }
46057
- function graphUsage(bin) {
46058
- return `Usage: ${bin} graph show|get [--json]
46059
- ${bin} graph show`;
46060
- }
46061
- var seatWrapper = (context, args) => dispatch(context, "seat", args, {
46062
- list: (ctx, rest) => {
46063
- const parsed = parseFlags(rest);
46064
- return execute(ctx, parsed, "graph.get", {}, formatSeatList);
46065
- },
46066
- get: (ctx, rest) => {
46067
- const parsed = parseFlags(rest);
46068
- const seatId = requireValue2(parsed, "seat-id");
46069
- return execute(ctx, parsed, "seat.get", { seat_id: seatId }, formatSeatDetail);
46070
- },
46071
- create: (ctx, rest) => {
46072
- const parsed = parseFlags(rest);
46073
- const body = withOptional({
46074
- name: requireValue2(parsed, "name"),
46075
- seat_type: requireValue2(parsed, "type")
46076
- }, {
46077
- parent_seat_id: optionalValue(parsed, "parent-seat-id")
46078
- });
46079
- return execute(ctx, parsed, "seat.create", body, formatSeatMutation);
46080
- },
46081
- rename: (ctx, rest) => {
46082
- const parsed = parseFlags(rest);
46083
- return execute(ctx, parsed, "seat.rename", {
46084
- seat_id: requireValue2(parsed, "seat-id"),
46085
- name: requireValue2(parsed, "name")
46086
- }, formatSeatMutation);
46087
- },
46088
- reparent: (ctx, rest) => {
46089
- const parsed = parseFlags(rest);
46090
- return execute(ctx, parsed, "seat.reparent", {
46091
- seat_id: requireValue2(parsed, "seat-id"),
46092
- new_parent_seat_id: requireValue2(parsed, "parent-seat-id")
46093
- }, formatSeatMutation);
46094
- },
46095
- decommission: (ctx, rest) => {
46096
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["dry-run", "preview"]));
46097
- if (parsed.flags.has("dry-run") || parsed.flags.has("preview")) {
46098
- return execute(ctx, parsed, "seat.decommission_preview", {
46099
- seat_id: requireValue2(parsed, "seat-id")
46100
- }, formatSeatDecommissionPreview);
46101
- }
46102
- return execute(ctx, parsed, "seat.decommission", {
46103
- seat_id: requireValue2(parsed, "seat-id")
46104
- }, formatSeatMutation);
46105
- }
46106
- }, seatUsage(context.binName));
46107
- function formatSeatList(output) {
46324
+ function renderSeatList(output) {
46108
46325
  const nodes = asArray(asRecord(output).nodes);
46109
46326
  if (nodes.length === 0) {
46110
46327
  return "No seats.";
@@ -46114,7 +46331,7 @@ function formatSeatList(output) {
46114
46331
  return `seat_id=${field(row, "seat_id")} parent_seat_id=${field(row, "parent_seat_id")} type=${field(row, "seat_type")} status=${field(row, "status")} name=${field(row, "name")}`;
46115
46332
  }).join("\n");
46116
46333
  }
46117
- function formatSeatDetail(output) {
46334
+ function renderSeatDetail(output) {
46118
46335
  const record2 = asRecord(output);
46119
46336
  const counts = asRecord(record2.counts);
46120
46337
  return [
@@ -46124,11 +46341,10 @@ function formatSeatDetail(output) {
46124
46341
  `counts: open_tasks=${field(counts, "open_tasks")} owned_goals=${field(counts, "owned_goals")} active_measurables=${field(counts, "active_measurables")} open_issues=${field(counts, "open_issues")}`
46125
46342
  ].join("\n");
46126
46343
  }
46127
- function formatSeatMutation(output) {
46128
- const record2 = asRecord(output);
46129
- return `seat_id=${field(record2, "seat_id")}`;
46344
+ function renderSeatMutation(output) {
46345
+ return `seat_id=${field(asRecord(output), "seat_id")}`;
46130
46346
  }
46131
- function formatSeatDecommissionPreview(output) {
46347
+ function renderSeatDecommissionPreview(output) {
46132
46348
  const record2 = asRecord(output);
46133
46349
  const effects = asArray(record2.effects).map((effect) => `- ${String(effect)}`);
46134
46350
  return [
@@ -46140,629 +46356,224 @@ function formatSeatDecommissionPreview(output) {
46140
46356
  ...effects
46141
46357
  ].join("\n");
46142
46358
  }
46143
- function seatUsage(bin) {
46144
- return `Usage: ${bin} seat list|get|create|rename|reparent|decommission [--json] [--yes]
46145
- ${bin} seat list
46146
- ${bin} seat get --seat-id <id>
46147
- ${bin} seat create --name <text> --type human|agent|hybrid [--parent-seat-id <id>]
46148
- ${bin} seat rename --seat-id <id> --name <text>
46149
- ${bin} seat reparent --seat-id <id> --parent-seat-id <id> [--yes]
46150
- ${bin} seat decommission --seat-id <id> [--dry-run] [--yes]`;
46151
- }
46152
- var taskWrapper = (context, args) => dispatch(context, "task", args, {
46153
- list: (ctx, rest) => {
46154
- const parsed = parseFlags(rest);
46155
- return execute(ctx, parsed, "task.list", {}, (output) => {
46156
- const tasks = asArray(asRecord(output).tasks);
46157
- if (tasks.length === 0) {
46158
- return "No tasks in this seat's queue.";
46159
- }
46160
- return tasks.map((task) => {
46161
- const record2 = asRecord(task);
46162
- return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "title")}`;
46163
- }).join("\n");
46164
- });
46165
- },
46166
- accept: (ctx, rest) => {
46167
- const parsed = parseFlags(rest);
46168
- const id = requireValue2(parsed, "id");
46169
- return execute(ctx, parsed, "task.accept", { id }, (output) => {
46170
- const task = asRecord(asRecord(output).task);
46171
- return `Accepted task ${field(task, "id")} (status ${field(task, "status")}).`;
46172
- });
46173
- },
46174
- decline: (ctx, rest) => {
46175
- const parsed = parseFlags(rest);
46176
- const id = requireValue2(parsed, "id");
46177
- const reason = requireValue2(parsed, "reason");
46178
- return execute(ctx, parsed, "task.decline", { id, reason }, (output) => {
46179
- const task = asRecord(asRecord(output).task);
46180
- return `Declined task ${field(task, "id")} (status ${field(task, "status")}).`;
46181
- });
46182
- },
46183
- complete: (ctx, rest) => {
46184
- const parsed = parseFlags(rest);
46185
- const id = requireValue2(parsed, "id");
46186
- const summary = requireValue2(parsed, "summary");
46187
- const body = withOptional({ id, summary }, {
46188
- artifacts: parseList(parsed, "artifacts")
46189
- });
46190
- return execute(ctx, parsed, "task.complete", body, (output) => {
46191
- const record2 = asRecord(output);
46192
- return `Completed task ${field(record2, "task_id")} (event ${field(record2, "event_id")}).`;
46193
- });
46194
- },
46195
- create: (ctx, rest) => {
46196
- const parsed = parseFlags(rest);
46197
- const body = withOptional({
46198
- owner_seat_id: requireValue2(parsed, "owner-seat-id"),
46199
- title: requireValue2(parsed, "title"),
46200
- description: requireValue2(parsed, "description")
46201
- }, {
46202
- from_seat_id: optionalValue(parsed, "from-seat-id"),
46203
- goal_id: optionalValue(parsed, "goal-id"),
46204
- due_on: optionalValue(parsed, "due-on"),
46205
- acceptance_criteria: parseList(parsed, "acceptance-criteria")
46206
- });
46207
- return execute(ctx, parsed, "task.create", body, (output) => {
46208
- const record2 = asRecord(output);
46209
- return `Created task ${field(record2, "task_id")} for seat ${field(record2, "owner_seat_id")} (status ${field(record2, "status")}).`;
46210
- });
46211
- }
46212
- }, taskUsage(context.binName));
46213
- function taskUsage(bin) {
46214
- return `Usage: ${bin} task list|accept|decline|complete|create [--seat <id>] [--json]
46215
- ${bin} task list [--seat <id>]
46216
- ${bin} task accept --id <task-id> [--seat <id>]
46217
- ${bin} task decline --id <task-id> --reason <text> [--seat <id>]
46218
- ${bin} task complete --id <task-id> --summary <text> [--artifacts a,b] [--seat <id>]
46219
- ${bin} task create --owner-seat-id <id> --title <t> --description <d> [--from-seat-id <id>] [--goal-id <id>] [--due-on YYYY-MM-DD] [--acceptance-criteria a,b]`;
46220
- }
46221
- var statusWrapper = (context, args) => dispatch(context, "status", args, {
46222
- record: (ctx, rest) => {
46223
- const parsed = parseFlags(rest);
46224
- const measurableId = optionalValue(parsed, "measurable-id");
46225
- const goalId = optionalValue(parsed, "goal-id");
46226
- const body = {};
46227
- if (measurableId !== void 0) {
46228
- const value = parseNumber(parsed, "value", { required: true });
46229
- body.measurables = [{ id: measurableId, value }];
46230
- }
46231
- if (goalId !== void 0) {
46232
- const state = requireValue2(parsed, "goal-state");
46233
- if (state !== "on" && state !== "off") {
46234
- throw new UsageError("--goal-state must be on or off.");
46235
- }
46236
- const note = optionalValue(parsed, "goal-note");
46237
- body.goals = [withOptional({ id: goalId, state }, { note })];
46238
- }
46239
- if (measurableId === void 0 && goalId === void 0) {
46240
- throw new UsageError("Provide --measurable-id (with --value) and/or --goal-id (with --goal-state).");
46241
- }
46242
- return execute(ctx, parsed, "status.record", body, (output) => {
46243
- const record2 = asRecord(output);
46244
- return `Recorded status event ${field(record2, "event_id")}.`;
46245
- });
46359
+ function renderSignalList(output) {
46360
+ const signals = asArray(asRecord(output).signals);
46361
+ if (signals.length === 0) {
46362
+ return "No Signals defined.";
46246
46363
  }
46247
- }, statusUsage(context.binName));
46248
- function statusUsage(bin) {
46249
- return `Usage: ${bin} status record [--seat <id>] [--json]
46250
- ${bin} status record --measurable-id <id> --value <n> [--seat <id>]
46251
- ${bin} status record --goal-id <id> --goal-state on|off [--goal-note <text>] [--seat <id>]`;
46252
- }
46253
- var signalWrapper = (context, args) => dispatch(context, "signal", args, {
46254
- list: (ctx, rest) => {
46255
- const parsed = parseFlags(rest);
46256
- const body = withOptional({}, { seat_id: optionalValue(parsed, "seat-id") });
46257
- return execute(ctx, parsed, "signal.list", body, (output) => {
46258
- const signals = asArray(asRecord(output).signals);
46259
- if (signals.length === 0) {
46260
- return "No Signals defined.";
46261
- }
46262
- return signals.map((signal) => {
46263
- const record2 = asRecord(signal);
46264
- return `${field(record2, "measurable_id")} ${field(record2, "state")} ${field(record2, "name")} (latest ${field(record2, "latest_value")} / target ${field(record2, "target")})`;
46265
- }).join("\n");
46266
- });
46267
- },
46268
- get: (ctx, rest) => {
46269
- const parsed = parseFlags(rest);
46270
- const measurableId = requireValue2(parsed, "measurable-id");
46271
- return execute(ctx, parsed, "signal.get", { measurable_id: measurableId }, (output) => {
46272
- const record2 = asRecord(output);
46273
- const readings = asArray(record2.readings);
46274
- const head2 = `${field(record2, "measurable_id")} ${field(record2, "state")} ${field(record2, "name")} (target ${field(record2, "target")})`;
46275
- const lines = readings.map((reading) => {
46276
- const r = asRecord(reading);
46277
- return ` ${field(r, "reading_id")} ${field(r, "period_start")} ${field(r, "value")} confirmed=${field(r, "confirmed")}`;
46278
- });
46279
- return [head2, ...lines].join("\n");
46280
- });
46281
- },
46282
- confirm: (ctx, rest) => {
46283
- const parsed = parseFlags(rest);
46284
- const readingId = requireValue2(parsed, "reading-id");
46285
- return execute(ctx, parsed, "signal.confirm_reading", { reading_id: readingId }, (output) => {
46286
- const record2 = asRecord(output);
46287
- return `Confirmed reading ${field(record2, "reading_id")}.`;
46288
- });
46289
- },
46290
- correct: (ctx, rest) => {
46291
- const parsed = parseFlags(rest);
46292
- const body = {
46293
- measurable_id: requireValue2(parsed, "measurable-id"),
46294
- period_start: requireValue2(parsed, "period-start"),
46295
- value: parseNumber(parsed, "value", { required: true })
46296
- };
46297
- return execute(ctx, parsed, "signal.correct_reading", body, (output) => {
46298
- const record2 = asRecord(output);
46299
- return `Corrected reading ${field(record2, "reading_id")} for measurable ${field(record2, "measurable_id")} (${field(record2, "period_start")} = ${field(record2, "value")}).`;
46300
- });
46364
+ return signals.map((signal) => {
46365
+ const record2 = asRecord(signal);
46366
+ return `${field(record2, "measurable_id")} ${field(record2, "state")} ${field(record2, "name")} (latest ${field(record2, "latest_value")} / target ${field(record2, "target")})`;
46367
+ }).join("\n");
46368
+ }
46369
+ function renderSignalGet(output) {
46370
+ const record2 = asRecord(output);
46371
+ const readings = asArray(record2.readings);
46372
+ const head2 = `${field(record2, "measurable_id")} ${field(record2, "state")} ${field(record2, "name")} (target ${field(record2, "target")})`;
46373
+ const lines = readings.map((reading) => {
46374
+ const r = asRecord(reading);
46375
+ return ` ${field(r, "reading_id")} ${field(r, "period_start")} ${field(r, "value")} confirmed=${field(r, "confirmed")}`;
46376
+ });
46377
+ return [head2, ...lines].join("\n");
46378
+ }
46379
+ function renderSignalConfirm(output) {
46380
+ return `Confirmed reading ${field(asRecord(output), "reading_id")}.`;
46381
+ }
46382
+ function renderSignalCorrect(output) {
46383
+ const record2 = asRecord(output);
46384
+ return `Corrected reading ${field(record2, "reading_id")} for measurable ${field(record2, "measurable_id")} (${field(record2, "period_start")} = ${field(record2, "value")}).`;
46385
+ }
46386
+ function renderGoalList(output) {
46387
+ const goals = asArray(asRecord(output).goals);
46388
+ if (goals.length === 0) {
46389
+ return "No goals in this Cascade.";
46301
46390
  }
46302
- }, signalUsage(context.binName));
46303
- function signalUsage(bin) {
46304
- return `Usage: ${bin} signal list|get|confirm|correct [--json]
46305
- ${bin} signal list [--seat-id <id>]
46306
- ${bin} signal get --measurable-id <id>
46307
- ${bin} signal confirm --reading-id <id>
46308
- ${bin} signal correct --measurable-id <id> --period-start YYYY-MM-DD --value <n>`;
46309
- }
46310
- var goalWrapper = (context, args) => dispatch(context, "goal", args, {
46311
- list: (ctx, rest) => {
46312
- const parsed = parseFlags(rest);
46313
- const body = withOptional({}, {
46314
- cycle_id: optionalValue(parsed, "cycle-id"),
46315
- seat_id: optionalValue(parsed, "seat-id")
46316
- });
46317
- return execute(ctx, parsed, "goal.list", body, (output) => {
46318
- const goals = asArray(asRecord(output).goals);
46319
- if (goals.length === 0) {
46320
- return "No goals in this Cascade.";
46321
- }
46322
- return goals.map((goal) => {
46323
- const record2 = asRecord(goal);
46324
- return `${field(record2, "goal_id")} ${field(record2, "status")} ${field(record2, "title")}`;
46325
- }).join("\n");
46326
- });
46327
- },
46328
- create: (ctx, rest) => {
46329
- const parsed = parseFlags(rest);
46330
- const body = withOptional({
46331
- cycle_id: requireValue2(parsed, "cycle-id"),
46332
- seat_id: requireValue2(parsed, "seat-id"),
46333
- parent_goal_id: requireValue2(parsed, "parent-goal-id"),
46334
- title: requireValue2(parsed, "title"),
46335
- definition_of_done: requireValue2(parsed, "definition-of-done")
46336
- }, {
46337
- status: optionalValue(parsed, "status")
46338
- });
46339
- return execute(ctx, parsed, "goal.create", body, (output) => {
46340
- const record2 = asRecord(output);
46341
- return `Created goal ${field(record2, "goal_id")} (status ${field(record2, "status")}).`;
46342
- });
46343
- },
46344
- update: (ctx, rest) => {
46345
- const parsed = parseFlags(rest);
46346
- const rejectBlank = (key, label) => {
46347
- const raw = parsed.values.get(key);
46348
- if (raw !== void 0 && raw.trim().length === 0) {
46349
- throw new UsageError(`${label} must not be empty.`);
46350
- }
46351
- };
46352
- rejectBlank("title", "--title");
46353
- rejectBlank("definition-of-done", "--definition-of-done");
46354
- const title = optionalValue(parsed, "title");
46355
- const definitionOfDone = optionalValue(parsed, "definition-of-done");
46356
- if (title === void 0 && definitionOfDone === void 0) {
46357
- throw new UsageError("Provide --title and/or --definition-of-done.");
46358
- }
46359
- const body = withOptional({
46360
- goal_id: requireValue2(parsed, "goal-id")
46361
- }, {
46362
- title,
46363
- definition_of_done: definitionOfDone
46364
- });
46365
- return execute(ctx, parsed, "goal.update", body, (output) => {
46366
- const record2 = asRecord(output);
46367
- return `Updated goal ${field(record2, "goal_id")}.`;
46368
- });
46369
- },
46370
- status: (ctx, rest) => {
46371
- const parsed = parseFlags(rest);
46372
- const body = {
46373
- goal_id: requireValue2(parsed, "goal-id"),
46374
- status: requireValue2(parsed, "status")
46375
- };
46376
- return execute(ctx, parsed, "goal.set_status", body, (output) => {
46377
- const record2 = asRecord(output);
46378
- return `Goal ${field(record2, "goal_id")} status set to ${field(record2, "status")}.`;
46379
- });
46380
- },
46381
- reparent: (ctx, rest) => {
46382
- const parsed = parseFlags(rest);
46383
- const body = {
46384
- goal_id: requireValue2(parsed, "goal-id"),
46385
- parent_goal_id: requireValue2(parsed, "parent-goal-id")
46386
- };
46387
- return execute(ctx, parsed, "goal.reparent", body, (output) => {
46388
- const record2 = asRecord(output);
46389
- return `Goal ${field(record2, "goal_id")} reparented under ${field(record2, "parent_goal_id")}.`;
46390
- });
46391
- },
46392
- drop: (ctx, rest) => {
46393
- const parsed = parseFlags(rest);
46394
- const body = { goal_id: requireValue2(parsed, "goal-id") };
46395
- return execute(ctx, parsed, "goal.drop", body, (output) => {
46396
- const record2 = asRecord(output);
46397
- return `Dropped goal ${field(record2, "goal_id")} (status ${field(record2, "status")}).`;
46398
- });
46391
+ return goals.map((goal) => {
46392
+ const record2 = asRecord(goal);
46393
+ return `${field(record2, "goal_id")} ${field(record2, "status")} ${field(record2, "title")}`;
46394
+ }).join("\n");
46395
+ }
46396
+ function renderGoalCreate(output) {
46397
+ const record2 = asRecord(output);
46398
+ return `Created goal ${field(record2, "goal_id")} (status ${field(record2, "status")}).`;
46399
+ }
46400
+ function renderGoalUpdate(output) {
46401
+ return `Updated goal ${field(asRecord(output), "goal_id")}.`;
46402
+ }
46403
+ function renderGoalStatus(output) {
46404
+ const record2 = asRecord(output);
46405
+ return `Goal ${field(record2, "goal_id")} status set to ${field(record2, "status")}.`;
46406
+ }
46407
+ function renderGoalReparent(output) {
46408
+ const record2 = asRecord(output);
46409
+ return `Goal ${field(record2, "goal_id")} reparented under ${field(record2, "parent_goal_id")}.`;
46410
+ }
46411
+ function renderGoalDrop(output) {
46412
+ const record2 = asRecord(output);
46413
+ return `Dropped goal ${field(record2, "goal_id")} (status ${field(record2, "status")}).`;
46414
+ }
46415
+ function renderFrictionList(output) {
46416
+ const issues = asArray(asRecord(output).issues);
46417
+ if (issues.length === 0) {
46418
+ return "No Friction issues.";
46399
46419
  }
46400
- }, goalUsage(context.binName));
46401
- function goalUsage(bin) {
46402
- return `Usage: ${bin} goal list|create|update|status|reparent|drop [--json]
46403
- ${bin} goal list [--cycle-id <id>] [--seat-id <id>]
46404
- ${bin} goal create --cycle-id <id> --seat-id <id> --parent-goal-id <id> --title <t> --definition-of-done <d> [--status on|off]
46405
- ${bin} goal update --goal-id <id> [--title <t>] [--definition-of-done <d>]
46406
- ${bin} goal status --goal-id <id> --status on|off|done
46407
- ${bin} goal reparent --goal-id <id> --parent-goal-id <id>
46408
- ${bin} goal drop --goal-id <id>`;
46409
- }
46410
- var frictionWrapper = (context, args) => dispatch(context, "friction", args, {
46411
- list: (ctx, rest) => {
46412
- const parsed = parseFlags(rest);
46413
- const body = withOptional({}, { status: optionalValue(parsed, "status") });
46414
- return execute(ctx, parsed, "friction.list", body, (output) => {
46415
- const issues = asArray(asRecord(output).issues);
46416
- if (issues.length === 0) {
46417
- return "No Friction issues.";
46418
- }
46419
- return issues.map((issue2) => {
46420
- const record2 = asRecord(issue2);
46421
- return `${field(record2, "issue_id")} ${field(record2, "status")} ${field(record2, "severity")} ${field(record2, "summary")}`;
46422
- }).join("\n");
46423
- });
46424
- },
46425
- file: (ctx, rest) => {
46426
- const parsed = parseFlags(rest);
46427
- const body = withOptional({
46428
- summary: requireValue2(parsed, "summary"),
46429
- severity: requireValue2(parsed, "severity"),
46430
- evidence: parseList(parsed, "evidence") ?? []
46431
- }, {
46432
- blocking_goal_id: optionalValue(parsed, "blocking-goal-id"),
46433
- broken_measurable_id: optionalValue(parsed, "broken-measurable-id")
46434
- });
46435
- return execute(ctx, parsed, "friction.file_issue", body, (output) => {
46436
- const record2 = asRecord(output);
46437
- return `Filed Friction issue ${field(record2, "issue_id")} (event ${field(record2, "event_id")}).`;
46438
- });
46439
- },
46440
- resolve: (ctx, rest) => {
46441
- const parsed = parseFlags(rest);
46442
- const body = withOptional({
46443
- issue_id: requireValue2(parsed, "issue-id"),
46444
- root_cause: requireValue2(parsed, "root-cause"),
46445
- owner_seat_id: requireValue2(parsed, "owner-seat-id"),
46446
- task_title: requireValue2(parsed, "task-title"),
46447
- task_description: requireValue2(parsed, "task-description"),
46448
- done_by: requireValue2(parsed, "done-by")
46449
- }, {
46450
- resolving_seat_id: optionalValue(parsed, "resolving-seat-id")
46451
- });
46452
- return execute(ctx, parsed, "friction.resolve", body, (output) => {
46453
- const record2 = asRecord(output);
46454
- return `Resolved issue ${field(record2, "issue_id")} \u2192 action task ${field(record2, "action_task_id")} (decision ${field(record2, "decision_id")}).`;
46455
- });
46456
- },
46457
- link: (ctx, rest) => {
46458
- const parsed = parseFlags(rest);
46459
- const body = {
46460
- issue_id: requireValue2(parsed, "issue-id"),
46461
- task_id: requireValue2(parsed, "task-id")
46462
- };
46463
- return execute(ctx, parsed, "friction.link_task", body, (output) => {
46464
- const record2 = asRecord(output);
46465
- return `Linked task ${field(record2, "action_task_id")} to issue ${field(record2, "issue_id")}.`;
46466
- });
46420
+ return issues.map((issue2) => {
46421
+ const record2 = asRecord(issue2);
46422
+ return `${field(record2, "issue_id")} ${field(record2, "status")} ${field(record2, "severity")} ${field(record2, "summary")}`;
46423
+ }).join("\n");
46424
+ }
46425
+ function renderFrictionFile(output) {
46426
+ const record2 = asRecord(output);
46427
+ return `Filed Friction issue ${field(record2, "issue_id")} (event ${field(record2, "event_id")}).`;
46428
+ }
46429
+ function renderFrictionResolve(output) {
46430
+ const record2 = asRecord(output);
46431
+ return `Resolved issue ${field(record2, "issue_id")} \u2192 action task ${field(record2, "action_task_id")} (decision ${field(record2, "decision_id")}).`;
46432
+ }
46433
+ function renderFrictionLink(output) {
46434
+ const record2 = asRecord(output);
46435
+ return `Linked task ${field(record2, "action_task_id")} to issue ${field(record2, "issue_id")}.`;
46436
+ }
46437
+ function renderEscalationList(output) {
46438
+ const escalations = asArray(asRecord(output).escalations);
46439
+ if (escalations.length === 0) {
46440
+ return "No escalations on this steward chain.";
46467
46441
  }
46468
- }, frictionUsage(context.binName));
46469
- function frictionUsage(bin) {
46470
- return `Usage: ${bin} friction list|file|resolve|link [--json]
46471
- ${bin} friction list [--status open|diagnosing|resolved|dropped|active|all]
46472
- ${bin} friction file --summary <text> --severity low|med|high|critical [--evidence a,b] [--blocking-goal-id <id>] [--broken-measurable-id <id>]
46473
- ${bin} friction resolve --issue-id <id> --root-cause <text> --owner-seat-id <id> --task-title <t> --task-description <d> --done-by YYYY-MM-DD [--resolving-seat-id <id>]
46474
- ${bin} friction link --issue-id <id> --task-id <id>`;
46475
- }
46476
- var escalationWrapper = (context, args) => dispatch(context, "escalation", args, {
46477
- list: (ctx, rest) => {
46478
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["include-decided"]));
46479
- const body = parsed.flags.has("include-decided") ? { include_decided: true } : {};
46480
- return execute(ctx, parsed, "escalation.list", body, (output) => {
46481
- const escalations = asArray(asRecord(output).escalations);
46482
- if (escalations.length === 0) {
46483
- return "No escalations on this steward chain.";
46484
- }
46485
- return escalations.map((escalation) => {
46486
- const record2 = asRecord(escalation);
46487
- return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "seat_name")}: ${field(record2, "reason")}`;
46488
- }).join("\n");
46489
- });
46490
- },
46491
- get: (ctx, rest) => {
46492
- const parsed = parseFlags(rest);
46493
- const id = requireValue2(parsed, "id");
46494
- return execute(ctx, parsed, "escalation.get", { id }, (output) => {
46495
- const record2 = asRecord(asRecord(output).escalation);
46496
- return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "seat_name")}
46442
+ return escalations.map((escalation) => {
46443
+ const record2 = asRecord(escalation);
46444
+ return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "seat_name")}: ${field(record2, "reason")}`;
46445
+ }).join("\n");
46446
+ }
46447
+ function renderEscalationGet(output) {
46448
+ const record2 = asRecord(asRecord(output).escalation);
46449
+ return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "seat_name")}
46497
46450
  reason: ${field(record2, "reason")}
46498
46451
  recommended: ${field(record2, "recommended_action")}`;
46499
- });
46500
- },
46501
- resolve: (ctx, rest) => {
46502
- const parsed = parseFlags(rest);
46503
- const body = withOptional({ id: requireValue2(parsed, "id") }, {
46504
- action: optionalValue(parsed, "action"),
46505
- rationale: optionalValue(parsed, "rationale")
46506
- });
46507
- return execute(ctx, parsed, "escalation.resolve", body, (output) => {
46508
- const record2 = asRecord(output);
46509
- return `Resolved escalation ${field(record2, "escalation_id")} (status ${field(record2, "status")}, decision ${field(record2, "decision_id")}).`;
46510
- });
46511
- },
46512
- reject: (ctx, rest) => {
46513
- const parsed = parseFlags(rest);
46514
- const body = withOptional({ id: requireValue2(parsed, "id") }, {
46515
- rationale: optionalValue(parsed, "rationale")
46516
- });
46517
- return execute(ctx, parsed, "escalation.reject", body, (output) => {
46518
- const record2 = asRecord(output);
46519
- return `Rejected escalation ${field(record2, "escalation_id")} (status ${field(record2, "status")}, decision ${field(record2, "decision_id")}).`;
46520
- });
46521
- }
46522
- }, escalationUsage(context.binName));
46523
- function escalationUsage(bin) {
46524
- return `Usage: ${bin} escalation list|get|resolve|reject [--json]
46525
- ${bin} escalation list [--include-decided]
46526
- ${bin} escalation get --id <id>
46527
- ${bin} escalation resolve --id <id> [--action approve|convert_to_issue] [--rationale <text>]
46528
- ${bin} escalation reject --id <id> [--rationale <text>]`;
46529
- }
46530
- var syncWrapper = (context, args) => dispatch(context, "sync", args, {
46531
- brief: (ctx, rest) => {
46532
- const parsed = parseFlags(rest);
46533
- const body = withOptional({}, { sync_brief_id: optionalValue(parsed, "sync-brief-id") });
46534
- return execute(ctx, parsed, "sync.brief.get", body, (output) => {
46535
- const record2 = asRecord(output);
46536
- return `Sync brief ${field(record2, "sync_brief_id")} (${field(record2, "period_start")} \u2192 ${field(record2, "period_end")})
46452
+ }
46453
+ function renderEscalationResolve(output) {
46454
+ const record2 = asRecord(output);
46455
+ return `Resolved escalation ${field(record2, "escalation_id")} (status ${field(record2, "status")}, decision ${field(record2, "decision_id")}).`;
46456
+ }
46457
+ function renderEscalationReject(output) {
46458
+ const record2 = asRecord(output);
46459
+ return `Rejected escalation ${field(record2, "escalation_id")} (status ${field(record2, "status")}, decision ${field(record2, "decision_id")}).`;
46460
+ }
46461
+ function renderSyncBrief(output) {
46462
+ const record2 = asRecord(output);
46463
+ return `Sync brief ${field(record2, "sync_brief_id")} (${field(record2, "period_start")} \u2192 ${field(record2, "period_end")})
46537
46464
  ${field(record2, "summary")}`;
46538
- });
46539
- },
46540
- compile: (ctx, rest) => {
46541
- const parsed = parseFlags(rest);
46542
- const body = withOptional({}, { cluster_id: optionalValue(parsed, "cluster-id") });
46543
- return execute(ctx, parsed, "sync.brief.compile", body, (output) => {
46544
- const record2 = asRecord(output);
46545
- return `Compiled sync brief ${field(record2, "sync_brief_id")} (${field(record2, "period_start")} \u2192 ${field(record2, "period_end")}, degraded=${field(record2, "degraded")}).`;
46546
- });
46547
- },
46548
- complete: (ctx, rest) => {
46549
- const parsed = parseFlags(rest);
46550
- const body = { sync_brief_id: requireValue2(parsed, "sync-brief-id") };
46551
- return execute(ctx, parsed, "sync.run.complete", body, (output) => {
46552
- const record2 = asRecord(output);
46553
- const decisions = asArray(record2.decision_ids).length;
46554
- const tasks = asArray(record2.task_ids).length;
46555
- return `Completed sync run for brief ${field(record2, "sync_brief_id")} (event ${field(record2, "event_id")}, ${decisions} decisions, ${tasks} tasks).`;
46556
- });
46557
- }
46558
- }, syncUsage(context.binName));
46559
- function syncUsage(bin) {
46560
- return `Usage: ${bin} sync brief|compile|complete [--json]
46561
- ${bin} sync brief [--sync-brief-id <id>]
46562
- ${bin} sync compile [--cluster-id <id>]
46563
- ${bin} sync complete --sync-brief-id <id>`;
46564
- }
46565
- var runnerWrapper = (context, args) => dispatch(context, "runner", args, {
46566
- list: (ctx, rest) => {
46567
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["include-revoked"]));
46568
- const body = parsed.flags.has("include-revoked") ? { include_revoked: true } : {};
46569
- return execute(ctx, parsed, "runner.list", body, (output) => {
46570
- const runners = asArray(asRecord(output).runners);
46571
- if (runners.length === 0) {
46572
- return "No runners paired.";
46573
- }
46574
- return runners.map((runner) => {
46575
- const record2 = asRecord(runner);
46576
- return `${field(record2, "id")} ${field(record2, "health")} ${field(record2, "name")} (${field(record2, "platform")})`;
46577
- }).join("\n");
46578
- });
46579
- },
46580
- status: (ctx, rest) => {
46581
- const parsed = parseFlags(rest);
46582
- const runnerId = requireValue2(parsed, "runner-id");
46583
- return execute(ctx, parsed, "runner.status", { runner_id: runnerId }, (output) => {
46584
- const record2 = asRecord(output);
46585
- return `${field(record2, "id")} ${field(record2, "health")} ${field(record2, "name")} (last heartbeat ${field(record2, "last_heartbeat_at")}).`;
46586
- });
46587
- },
46588
- diagnose: (ctx, rest) => {
46589
- const parsed = parseFlags(rest);
46590
- const runnerId = requireValue2(parsed, "runner-id");
46591
- return execute(ctx, parsed, "runner.diagnose", { runner_id: runnerId }, (output) => {
46592
- const record2 = asRecord(output);
46593
- const guidance = asArray(record2.repair_guidance);
46594
- const lines = [
46595
- `Runner ${field(record2, "name")} (${field(record2, "id")})`,
46596
- `health: ${field(record2, "health")} platform: ${field(record2, "platform")}`,
46597
- `paired_at: ${field(record2, "paired_at")} last_heartbeat: ${field(record2, "last_heartbeat_at")}`,
46598
- `capabilities: claude=${String(asRecord(record2.capabilities).claude)} codex=${String(asRecord(record2.capabilities).codex)}`,
46599
- `revocation_state: ${field(record2, "revocation_state")}`
46600
- ];
46601
- if (guidance.length > 0) {
46602
- lines.push("repair_guidance:");
46603
- guidance.forEach((step) => {
46604
- const s = asRecord(step);
46605
- lines.push(` ${field(s, "action")}: ${field(s, "detail")}`);
46606
- });
46607
- }
46608
- return lines.join("\n");
46609
- });
46610
- },
46611
- repair: (ctx, rest) => {
46612
- const parsed = parseFlags(rest);
46613
- const runnerId = requireValue2(parsed, "runner-id");
46614
- const issue2 = optionalValue(parsed, "issue");
46615
- const body = issue2 ? { runner_id: runnerId, issue: issue2 } : { runner_id: runnerId };
46616
- return execute(ctx, parsed, "runner.repair", body, (output) => {
46617
- const record2 = asRecord(output);
46618
- const steps = asArray(record2.repair_steps);
46619
- const lines = [
46620
- `Runner ${field(record2, "runner_name")} (${field(record2, "runner_id")}) health: ${field(record2, "runner_health")}`,
46621
- `requires_human: ${field(record2, "requires_human")}`
46622
- ];
46623
- if (steps.length > 0) {
46624
- lines.push("repair_steps:");
46625
- steps.forEach((step) => {
46626
- const s = asRecord(step);
46627
- lines.push(` ${field(s, "action")}`);
46628
- lines.push(` command: ${field(s, "command")}`);
46629
- lines.push(` detail: ${field(s, "detail")}`);
46630
- });
46631
- }
46632
- return lines.join("\n");
46633
- });
46634
- },
46635
- "work-orders": (ctx, rest) => {
46636
- const parsed = parseFlags(rest);
46637
- const body = withOptional({}, {
46638
- status: optionalValue(parsed, "status"),
46639
- agent_id: optionalValue(parsed, "agent-id"),
46640
- runner_id: optionalValue(parsed, "runner-id"),
46641
- limit: parseNumber(parsed, "limit", { required: false })
46642
- });
46643
- return execute(ctx, parsed, "work_order.list", body, (output) => {
46644
- const workOrders = asArray(asRecord(output).work_orders);
46645
- if (workOrders.length === 0) {
46646
- return "No work orders.";
46647
- }
46648
- return workOrders.map((workOrder) => {
46649
- const record2 = asRecord(workOrder);
46650
- return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "lane")} agent ${field(record2, "agent_id")}`;
46651
- }).join("\n");
46652
- });
46653
- },
46654
- revoke: (ctx, rest) => {
46655
- const parsed = parseFlags(rest);
46656
- const runnerId = requireValue2(parsed, "runner-id");
46657
- return execute(ctx, parsed, "runner.revoke", { runner_id: runnerId }, (output) => {
46658
- const record2 = asRecord(output);
46659
- return `Revoked runner ${field(record2, "runner_id")} (revoked=${field(record2, "revoked")}).`;
46465
+ }
46466
+ function renderSyncCompile(output) {
46467
+ const record2 = asRecord(output);
46468
+ return `Compiled sync brief ${field(record2, "sync_brief_id")} (${field(record2, "period_start")} \u2192 ${field(record2, "period_end")}, degraded=${field(record2, "degraded")}).`;
46469
+ }
46470
+ function renderSyncComplete(output) {
46471
+ const record2 = asRecord(output);
46472
+ const decisions = asArray(record2.decision_ids).length;
46473
+ const tasks = asArray(record2.task_ids).length;
46474
+ return `Completed sync run for brief ${field(record2, "sync_brief_id")} (event ${field(record2, "event_id")}, ${decisions} decisions, ${tasks} tasks).`;
46475
+ }
46476
+ function renderRunnerList(output) {
46477
+ const runners = asArray(asRecord(output).runners);
46478
+ if (runners.length === 0) {
46479
+ return "No runners paired.";
46480
+ }
46481
+ return runners.map((runner) => {
46482
+ const record2 = asRecord(runner);
46483
+ return `${field(record2, "id")} ${field(record2, "health")} ${field(record2, "name")} (${field(record2, "platform")})`;
46484
+ }).join("\n");
46485
+ }
46486
+ function renderRunnerStatus(output) {
46487
+ const record2 = asRecord(output);
46488
+ return `${field(record2, "id")} ${field(record2, "health")} ${field(record2, "name")} (last heartbeat ${field(record2, "last_heartbeat_at")}).`;
46489
+ }
46490
+ function renderRunnerDiagnose(output) {
46491
+ const record2 = asRecord(output);
46492
+ const guidance = asArray(record2.repair_guidance);
46493
+ const lines = [
46494
+ `Runner ${field(record2, "name")} (${field(record2, "id")})`,
46495
+ `health: ${field(record2, "health")} platform: ${field(record2, "platform")}`,
46496
+ `paired_at: ${field(record2, "paired_at")} last_heartbeat: ${field(record2, "last_heartbeat_at")}`,
46497
+ `capabilities: claude=${String(asRecord(record2.capabilities).claude)} codex=${String(asRecord(record2.capabilities).codex)}`,
46498
+ `revocation_state: ${field(record2, "revocation_state")}`
46499
+ ];
46500
+ if (guidance.length > 0) {
46501
+ lines.push("repair_guidance:");
46502
+ guidance.forEach((step) => {
46503
+ const s = asRecord(step);
46504
+ lines.push(` ${field(s, "action")}: ${field(s, "detail")}`);
46660
46505
  });
46661
46506
  }
46662
- }, runnerUsage(context.binName));
46663
- function runnerUsage(bin) {
46664
- return `Usage: ${bin} runner list|status|diagnose|repair|work-orders|revoke|serve [--json]
46665
- ${bin} runner list [--include-revoked]
46666
- ${bin} runner status --runner-id <id>
46667
- ${bin} runner diagnose --runner-id <id>
46668
- ${bin} runner repair --runner-id <id> [--issue restart|re_pair|revoke_stale|missing_cli_runtime]
46669
- ${bin} runner work-orders [--status <s>] [--agent-id <id>] [--runner-id <id>] [--limit <n>]
46670
- ${bin} runner revoke --runner-id <id>
46671
- ${bin} runner serve [--name <text>] [--state-file <path>] [--heartbeat-ms <n>] [--once] [--execute]`;
46672
- }
46673
- var notificationWrapper = (context, args) => dispatch(context, "notification", args, {
46674
- settings: (ctx, rest) => {
46675
- const parsed = parseFlags(rest);
46676
- return execute(ctx, parsed, "notification.settings.get", {}, (output) => {
46677
- const record2 = asRecord(output);
46678
- return `escalations=${field(record2, "escalations_enabled")} sync_brief=${field(record2, "sync_brief_enabled")} default_channel=${field(record2, "default_channel")}`;
46679
- });
46680
- },
46681
- test: (ctx, rest) => {
46682
- const parsed = parseFlags(rest);
46683
- return execute(ctx, parsed, "notification.test", {}, (output) => {
46684
- const record2 = asRecord(output);
46685
- return `Test notification ${field(record2, "notification_id")} (delivered=${field(record2, "delivered")}).`;
46686
- });
46687
- },
46688
- errors: (ctx, rest) => {
46689
- const parsed = parseFlags(rest);
46690
- const body = withOptional({}, { limit: optionalNumber(parsed, "limit") });
46691
- return execute(ctx, parsed, "notification.list_errors", body, (output) => {
46692
- const errors = asArray(asRecord(output).errors);
46693
- if (errors.length === 0) {
46694
- return "No failed notification deliveries.";
46695
- }
46696
- return errors.map((entry) => {
46697
- const record2 = asRecord(entry);
46698
- return `${field(record2, "created_at")} ${field(record2, "channel")} source=${field(record2, "source")} seat=${field(record2, "seat_id")} run=${field(record2, "run_id")} ${field(record2, "error_message")}`;
46699
- }).join("\n");
46507
+ return lines.join("\n");
46508
+ }
46509
+ function renderRunnerRepair(output) {
46510
+ const record2 = asRecord(output);
46511
+ const steps = asArray(record2.repair_steps);
46512
+ const lines = [
46513
+ `Runner ${field(record2, "runner_name")} (${field(record2, "runner_id")}) health: ${field(record2, "runner_health")}`,
46514
+ `requires_human: ${field(record2, "requires_human")}`
46515
+ ];
46516
+ if (steps.length > 0) {
46517
+ lines.push("repair_steps:");
46518
+ steps.forEach((step) => {
46519
+ const s = asRecord(step);
46520
+ lines.push(` ${field(s, "action")}`);
46521
+ lines.push(` command: ${field(s, "command")}`);
46522
+ lines.push(` detail: ${field(s, "detail")}`);
46700
46523
  });
46701
46524
  }
46702
- }, notificationUsage(context.binName));
46703
- function notificationUsage(bin) {
46704
- return `Usage: ${bin} notification settings|test|errors [--json]
46705
- ${bin} notification settings
46706
- ${bin} notification test
46707
- ${bin} notification errors [--limit <n>]`;
46708
- }
46709
- var integrationWrapper = (context, args) => dispatch(context, "integration", args, {
46710
- list: (ctx, rest) => {
46711
- const parsed = parseFlags(rest);
46712
- const body = withOptional({}, { provider: optionalValue(parsed, "provider") });
46713
- return execute(ctx, parsed, "integration.list", body, (output) => {
46714
- const integrations = asArray(asRecord(output).integrations);
46715
- if (integrations.length === 0) {
46716
- return "No integrations are connected.";
46717
- }
46718
- return integrations.map((entry) => formatIntegrationLine(asRecord(entry))).join("\n");
46719
- });
46720
- },
46721
- readiness: (ctx, rest) => {
46722
- const parsed = parseFlags(rest);
46723
- const body = withOptional({}, { provider: optionalValue(parsed, "provider") });
46724
- return execute(ctx, parsed, "integration.readiness", body, (output) => {
46725
- const connectors = asArray(asRecord(output).connectors);
46726
- if (connectors.length === 0) {
46727
- return "No connector readiness facts found.";
46728
- }
46729
- return connectors.map((entry) => formatIntegrationReadiness(asRecord(entry))).join("\n\n");
46730
- });
46731
- },
46732
- status: (ctx, rest) => {
46733
- const parsed = parseFlags(rest);
46734
- const body = integrationLookupBody(parsed);
46735
- return execute(ctx, parsed, "integration.status", body, (output) => {
46736
- const integration = asRecord(output).integration;
46737
- if (integration === null) {
46738
- return "Integration not found.";
46739
- }
46740
- return formatIntegrationLine(asRecord(integration));
46741
- });
46742
- },
46743
- test: (ctx, rest) => {
46744
- const parsed = parseFlags(rest);
46745
- const body = integrationLookupBody(parsed);
46746
- return execute(ctx, parsed, "integration.test", body, (output) => {
46747
- const record2 = asRecord(output);
46748
- return `${field(record2, "provider")} ${field(record2, "status")} (ok=${field(record2, "ok")}) ${field(record2, "message")}`;
46749
- });
46525
+ return lines.join("\n");
46526
+ }
46527
+ function renderWorkOrders(output) {
46528
+ const workOrders = asArray(asRecord(output).work_orders);
46529
+ if (workOrders.length === 0) {
46530
+ return "No work orders.";
46750
46531
  }
46751
- }, integrationUsage(context.binName));
46752
- function integrationLookupBody(parsed) {
46753
- const body = withOptional({}, {
46754
- provider: optionalValue(parsed, "provider"),
46755
- integration_id: optionalValue(parsed, "integration-id")
46756
- });
46757
- if (Object.keys(body).length === 0) {
46758
- throw new UsageError("Provide --provider or --integration-id.");
46532
+ return workOrders.map((workOrder) => {
46533
+ const record2 = asRecord(workOrder);
46534
+ return `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "lane")} agent ${field(record2, "agent_id")}`;
46535
+ }).join("\n");
46536
+ }
46537
+ function renderRunnerRevoke(output) {
46538
+ const record2 = asRecord(output);
46539
+ return `Revoked runner ${field(record2, "runner_id")} (revoked=${field(record2, "revoked")}).`;
46540
+ }
46541
+ function renderNotificationSettings(output) {
46542
+ const record2 = asRecord(output);
46543
+ return `escalations=${field(record2, "escalations_enabled")} sync_brief=${field(record2, "sync_brief_enabled")} default_channel=${field(record2, "default_channel")}`;
46544
+ }
46545
+ function renderNotificationTest(output) {
46546
+ const record2 = asRecord(output);
46547
+ return `Test notification ${field(record2, "notification_id")} (delivered=${field(record2, "delivered")}).`;
46548
+ }
46549
+ function renderNotificationErrors(output) {
46550
+ const errors = asArray(asRecord(output).errors);
46551
+ if (errors.length === 0) {
46552
+ return "No failed notification deliveries.";
46759
46553
  }
46760
- return body;
46554
+ return errors.map((entry) => {
46555
+ const record2 = asRecord(entry);
46556
+ return `${field(record2, "created_at")} ${field(record2, "channel")} source=${field(record2, "source")} seat=${field(record2, "seat_id")} run=${field(record2, "run_id")} ${field(record2, "error_message")}`;
46557
+ }).join("\n");
46761
46558
  }
46762
46559
  function formatIntegrationLine(record2) {
46763
46560
  return `${field(record2, "provider")} status=${field(record2, "status")} account=${field(record2, "account_email")} last_test=${field(record2, "last_test_result")} id=${field(record2, "id")}`;
46764
46561
  }
46765
- function formatIntegrationReadiness(record2) {
46562
+ function renderIntegrationList(output) {
46563
+ const integrations = asArray(asRecord(output).integrations);
46564
+ if (integrations.length === 0) {
46565
+ return "No integrations are connected.";
46566
+ }
46567
+ return integrations.map((entry) => formatIntegrationLine(asRecord(entry))).join("\n");
46568
+ }
46569
+ function renderIntegrationReadiness(output) {
46570
+ const connectors = asArray(asRecord(output).connectors);
46571
+ if (connectors.length === 0) {
46572
+ return "No connector readiness facts found.";
46573
+ }
46574
+ return connectors.map((entry) => formatIntegrationReadinessLine(asRecord(entry))).join("\n\n");
46575
+ }
46576
+ function formatIntegrationReadinessLine(record2) {
46766
46577
  const checks = asArray(record2.checks).map((entry) => {
46767
46578
  const check2 = asRecord(entry);
46768
46579
  const issue2 = field(check2, "linear_issue") === "\u2014" ? "" : ` ${field(check2, "linear_issue")}`;
@@ -46776,142 +46587,58 @@ function formatIntegrationReadiness(record2) {
46776
46587
  actions.length > 0 ? ["next:", ...actions].join("\n") : ""
46777
46588
  ].filter((line) => line.length > 0).join("\n");
46778
46589
  }
46779
- function integrationUsage(bin) {
46780
- return `Usage: ${bin} integration list|readiness|status|test [--json]
46781
- ${bin} integration list [--provider <name>]
46782
- ${bin} integration readiness [--provider google]
46783
- ${bin} integration status --provider <name>
46784
- ${bin} integration test --provider <name>`;
46785
- }
46786
- var settingsWrapper = (context, args) => dispatch(context, "settings", args, {
46787
- "product-learning": (ctx, rest) => dispatch(ctx, "settings product-learning", rest, {
46788
- get: (innerCtx, innerRest) => {
46789
- const parsed = parseFlags(innerRest);
46790
- return execute(innerCtx, parsed, "settings.product_learning.get", {}, (output) => {
46791
- const policy = asRecord(asRecord(output).product_learning);
46792
- return `product_learning ${field(policy, "mode")} product_analytics_enabled=${field(policy, "product_analytics_enabled")} security_audit_logs_enabled=${field(policy, "security_audit_logs_enabled")}`;
46793
- });
46794
- },
46795
- update: (innerCtx, innerRest) => {
46796
- const parsed = parseFlags(innerRest);
46797
- const mode = optionalValue(parsed, "mode");
46798
- if (mode !== "enabled" && mode !== "disabled" && mode !== "enterprise_contract") {
46799
- throw new UsageError("Provide --mode enabled|disabled|enterprise_contract.");
46800
- }
46801
- return execute(innerCtx, parsed, "settings.product_learning.update", { mode }, (output) => {
46802
- const policy = asRecord(asRecord(output).product_learning);
46803
- return `Updated product-learning policy to ${field(policy, "mode")} (product_analytics_enabled=${field(policy, "product_analytics_enabled")}).`;
46804
- });
46805
- }
46806
- }, settingsUsage(ctx.binName)),
46807
- "agent-policy": (ctx, rest) => dispatch(ctx, "settings agent-policy", rest, {
46808
- get: (innerCtx, innerRest) => {
46809
- const parsed = parseFlags(innerRest);
46810
- return execute(innerCtx, parsed, "settings.agent_policy.get", {}, (output) => {
46811
- const policy = asRecord(asRecord(output).agent_policy);
46812
- return `agent_policy profile=${field(policy, "profile")} enforcement=${field(policy, "enforcement")} max_autonomous_risk=${field(policy, "max_autonomous_risk")} explicit=${field(policy, "explicit")}`;
46813
- });
46814
- },
46815
- set: (innerCtx, innerRest) => {
46816
- const parsed = parseFlags(innerRest);
46817
- const profile = optionalValue(parsed, "profile");
46818
- if (profile !== "locked_down" && profile !== "balanced" && profile !== "high_autonomy" && profile !== "custom") {
46819
- throw new UsageError("Provide --profile locked_down|balanced|high_autonomy|custom.");
46820
- }
46821
- const body = withOptional({ profile }, {
46822
- max_autonomous_risk: optionalValue(parsed, "max-autonomous-risk"),
46823
- enforcement: optionalValue(parsed, "enforcement")
46824
- });
46825
- return execute(innerCtx, parsed, "settings.agent_policy.update", body, (output) => {
46826
- const policy = asRecord(asRecord(output).agent_policy);
46827
- return `Set company autonomy ceiling to ${field(policy, "profile")} (max_autonomous_risk=${field(policy, "max_autonomous_risk")}, enforcement=${field(policy, "enforcement")}).`;
46828
- });
46829
- }
46830
- }, settingsUsage(ctx.binName)),
46831
- get: (ctx, rest) => {
46832
- const parsed = parseFlags(rest);
46833
- return execute(ctx, parsed, "settings.get", {}, (output) => {
46834
- const record2 = asRecord(output);
46835
- const spend = asRecord(record2.spend);
46836
- const policy = asRecord(record2.product_learning);
46837
- return `tenant ${field(record2, "tenant_id")} plan=${field(record2, "plan")} status=${field(record2, "status")} spend=$${field(spend, "spend_usd")} has_anthropic_key=${field(record2, "has_anthropic_key")} product_learning=${field(policy, "mode")}`;
46838
- });
46839
- },
46840
- update: (ctx, rest) => {
46841
- const parsed = parseFlags(rest);
46842
- const body = withOptional({}, {
46843
- soft_cap_usd: optionalValue(parsed, "soft-cap-usd"),
46844
- hard_cap_usd: optionalValue(parsed, "hard-cap-usd")
46845
- });
46846
- if (Object.keys(body).length === 0) {
46847
- throw new UsageError("Provide --soft-cap-usd and/or --hard-cap-usd.");
46848
- }
46849
- return execute(ctx, parsed, "settings.update", body, (output) => {
46850
- const spend = asRecord(asRecord(output).spend);
46851
- return `Updated budget caps (soft=$${field(spend, "soft_cap_usd")}, hard=$${field(spend, "hard_cap_usd")}).`;
46852
- });
46853
- },
46854
- rename: (ctx, rest) => {
46855
- const parsed = parseFlags(rest);
46856
- const companyName = optionalValue(parsed, "company");
46857
- if (!companyName) {
46858
- throw new UsageError("Provide --company <name>.");
46859
- }
46860
- return execute(ctx, parsed, "tenant.rename", { company_name: companyName }, (output) => {
46861
- const record2 = asRecord(output);
46862
- return `Renamed company from ${field(record2, "previous_name")} to ${field(record2, "name")}.`;
46863
- });
46864
- }
46865
- }, settingsUsage(context.binName));
46866
- function settingsUsage(bin) {
46867
- return `Usage: ${bin} settings get|update|product-learning|agent-policy|rename [--json]
46868
- ${bin} settings get
46869
- ${bin} settings update [--soft-cap-usd <n>] [--hard-cap-usd <n>]
46870
- ${bin} settings product-learning get
46871
- ${bin} settings product-learning update --mode enabled|disabled|enterprise_contract
46872
- ${bin} settings agent-policy get
46873
- ${bin} settings agent-policy set --profile locked_down|balanced|high_autonomy|custom [--max-autonomous-risk low|medium|high|critical] [--enforcement enforce|observe]
46874
- ${bin} settings rename --company <name>`;
46875
- }
46876
- var memberWrapper = (context, args) => dispatch(context, "member", args, {
46877
- invite: (ctx, rest) => {
46878
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["byo-key"]));
46879
- const body = withOptional({
46880
- email: requireValue2(parsed, "email"),
46881
- role: requireValue2(parsed, "role")
46882
- }, {
46883
- byo_key: parsed.flags.has("byo-key") ? true : void 0
46884
- });
46885
- return execute(ctx, parsed, "member.invite", body, (output) => {
46886
- const record2 = asRecord(output);
46887
- return `Invited ${field(record2, "email")} as ${field(record2, "role")} (invite ${field(record2, "invite_id")}).`;
46888
- });
46889
- },
46890
- update: (ctx, rest) => {
46891
- const parsed = parseFlags(rest);
46892
- const body = {
46893
- member_id: requireValue2(parsed, "member-id"),
46894
- role: requireValue2(parsed, "role")
46895
- };
46896
- return execute(ctx, parsed, "member.update", body, (output) => {
46897
- const record2 = asRecord(output);
46898
- return `Updated member ${field(record2, "member_id")} \u2192 ${field(record2, "role")}.`;
46899
- });
46900
- },
46901
- remove: (ctx, rest) => {
46902
- const parsed = parseFlags(rest);
46903
- const body = { member_id: requireValue2(parsed, "member-id") };
46904
- return execute(ctx, parsed, "member.remove", body, (output) => {
46905
- const record2 = asRecord(output);
46906
- return `Removed member ${field(record2, "member_id")} (removed=${field(record2, "removed")}).`;
46907
- });
46590
+ function renderIntegrationStatus(output) {
46591
+ const integration = asRecord(output).integration;
46592
+ if (integration === null) {
46593
+ return "Integration not found.";
46908
46594
  }
46909
- }, memberUsage(context.binName));
46910
- function memberUsage(bin) {
46911
- return `Usage: ${bin} member invite|update|remove [--json]
46912
- ${bin} member invite --email <email> --role owner|steward|member [--byo-key]
46913
- ${bin} member update --member-id <id> --role owner|steward|member
46914
- ${bin} member remove --member-id <id>`;
46595
+ return formatIntegrationLine(asRecord(integration));
46596
+ }
46597
+ function renderIntegrationTest(output) {
46598
+ const record2 = asRecord(output);
46599
+ return `${field(record2, "provider")} ${field(record2, "status")} (ok=${field(record2, "ok")}) ${field(record2, "message")}`;
46600
+ }
46601
+ function renderSettingsGet(output) {
46602
+ const record2 = asRecord(output);
46603
+ const spend = asRecord(record2.spend);
46604
+ const policy = asRecord(record2.product_learning);
46605
+ return `tenant ${field(record2, "tenant_id")} plan=${field(record2, "plan")} status=${field(record2, "status")} spend=$${field(spend, "spend_usd")} has_anthropic_key=${field(record2, "has_anthropic_key")} product_learning=${field(policy, "mode")}`;
46606
+ }
46607
+ function renderSettingsUpdate(output) {
46608
+ const spend = asRecord(asRecord(output).spend);
46609
+ return `Updated budget caps (soft=$${field(spend, "soft_cap_usd")}, hard=$${field(spend, "hard_cap_usd")}).`;
46610
+ }
46611
+ function renderTenantRename(output) {
46612
+ const record2 = asRecord(output);
46613
+ return `Renamed company from ${field(record2, "previous_name")} to ${field(record2, "name")}.`;
46614
+ }
46615
+ function renderProductLearningGet(output) {
46616
+ const policy = asRecord(asRecord(output).product_learning);
46617
+ return `product_learning ${field(policy, "mode")} product_analytics_enabled=${field(policy, "product_analytics_enabled")} security_audit_logs_enabled=${field(policy, "security_audit_logs_enabled")}`;
46618
+ }
46619
+ function renderProductLearningUpdate(output) {
46620
+ const policy = asRecord(asRecord(output).product_learning);
46621
+ return `Updated product-learning policy to ${field(policy, "mode")} (product_analytics_enabled=${field(policy, "product_analytics_enabled")}).`;
46622
+ }
46623
+ function renderAgentPolicyGet(output) {
46624
+ const policy = asRecord(asRecord(output).agent_policy);
46625
+ return `agent_policy profile=${field(policy, "profile")} enforcement=${field(policy, "enforcement")} max_autonomous_risk=${field(policy, "max_autonomous_risk")} explicit=${field(policy, "explicit")}`;
46626
+ }
46627
+ function renderAgentPolicySet(output) {
46628
+ const policy = asRecord(asRecord(output).agent_policy);
46629
+ return `Set company autonomy ceiling to ${field(policy, "profile")} (max_autonomous_risk=${field(policy, "max_autonomous_risk")}, enforcement=${field(policy, "enforcement")}).`;
46630
+ }
46631
+ function renderMemberInvite(output) {
46632
+ const record2 = asRecord(output);
46633
+ return `Invited ${field(record2, "email")} as ${field(record2, "role")} (invite ${field(record2, "invite_id")}).`;
46634
+ }
46635
+ function renderMemberUpdate(output) {
46636
+ const record2 = asRecord(output);
46637
+ return `Updated member ${field(record2, "member_id")} \u2192 ${field(record2, "role")}.`;
46638
+ }
46639
+ function renderMemberRemove(output) {
46640
+ const record2 = asRecord(output);
46641
+ return `Removed member ${field(record2, "member_id")} (removed=${field(record2, "removed")}).`;
46915
46642
  }
46916
46643
  function agentSetupStateLine(output) {
46917
46644
  const record2 = asRecord(output);
@@ -46928,236 +46655,204 @@ function agentSetupStateLine(output) {
46928
46655
  }
46929
46656
  return lines.join("\n");
46930
46657
  }
46931
- var agentWrapper = (context, args) => dispatch(context, "agent", args, {
46932
- templates: (ctx, rest) => {
46933
- const parsed = parseFlags(rest);
46934
- return execute(ctx, parsed, "agent_template.list", {}, (output) => {
46935
- const templates = asArray(asRecord(output).templates);
46936
- if (templates.length === 0) {
46937
- return "No stock agent templates available.";
46938
- }
46939
- return templates.map((template) => {
46940
- const record2 = asRecord(template);
46941
- return `${field(record2, "slug")} ${field(record2, "tier")} ${field(record2, "display_name")} \u2014 ${field(record2, "function")}`;
46942
- }).join("\n");
46943
- });
46944
- },
46945
- create: (ctx, rest) => {
46946
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["custom"]));
46947
- const templateSlug = optionalValue(parsed, "template");
46948
- const seatId = requireValue2(parsed, "seat-id");
46949
- if (parsed.flags.has("custom")) {
46950
- if (templateSlug !== void 0) {
46951
- throw new UsageError("Use either --template <slug> or --custom, not both.");
46952
- }
46953
- const body2 = withOptional({ seat_id: seatId }, {
46954
- steward_seat_id: optionalValue(parsed, "steward-seat-id"),
46955
- lane: optionalValue(parsed, "lane"),
46956
- model_config: resolveModelConfig(optionalValue(parsed, "model"), optionalValue(parsed, "effort")),
46957
- what_it_owns: optionalValue(parsed, "owns"),
46958
- what_success_looks_like: optionalValue(parsed, "success"),
46959
- what_it_must_never_do_alone: optionalValue(parsed, "never-alone")
46960
- });
46961
- return execute(ctx, parsed, "agent.create_custom", body2, agentSetupStateLine);
46962
- }
46963
- if (templateSlug === void 0) {
46964
- throw new UsageError("Provide --template <slug> or --custom.");
46965
- }
46966
- const body = withOptional({ seat_id: seatId, template_slug: templateSlug }, {
46967
- expected_template_version: optionalValue(parsed, "expected-version")
46968
- });
46969
- return execute(ctx, parsed, "agent.create_from_template", body, agentSetupStateLine);
46970
- },
46971
- setup: (ctx, rest) => dispatch(ctx, "agent setup", rest, {
46972
- status: (innerCtx, innerRest) => {
46973
- const parsed = parseFlags(innerRest);
46974
- const body = withOptional({}, {
46975
- setup_id: optionalValue(parsed, "setup-id"),
46976
- seat_id: optionalValue(parsed, "seat-id")
46977
- });
46978
- if (Object.keys(body).length === 0) {
46979
- throw new UsageError("Provide --setup-id or --seat-id.");
46980
- }
46981
- return execute(innerCtx, parsed, "agent_setup.get", body, agentSetupStateLine);
46982
- },
46983
- answer: (innerCtx, innerRest) => {
46984
- const parsed = parseFlags(innerRest);
46985
- const body = withOptional({ seat_id: requireValue2(parsed, "seat-id") }, {
46986
- parent_seat_id: optionalValue(parsed, "parent-seat-id"),
46987
- steward_seat_id: optionalValue(parsed, "steward-seat-id"),
46988
- lane: optionalValue(parsed, "lane"),
46989
- schedule_cron: optionalValue(parsed, "schedule-cron"),
46990
- // DER-787 (H1): --model sets the structured model config (tier or id).
46991
- model_config: resolveModelConfig(optionalValue(parsed, "model"), optionalValue(parsed, "effort")),
46992
- answers: parseList(parsed, "answers")
46993
- });
46994
- if (Object.keys(body).length <= 1) {
46995
- throw new UsageError("Provide at least one of --parent-seat-id, --steward-seat-id, --lane, --schedule-cron, --model, --answers.");
46996
- }
46997
- return execute(innerCtx, parsed, "agent_setup.update", body, agentSetupStateLine);
46998
- }
46999
- }, agentSetupUsage(ctx.binName)),
47000
- tools: (ctx, rest) => dispatch(ctx, "agent tools", rest, {
47001
- connect: (innerCtx, innerRest) => agentConfigureTools(innerCtx, innerRest, "connect"),
47002
- decline: (innerCtx, innerRest) => agentConfigureTools(innerCtx, innerRest, "decline")
47003
- }, agentToolsUsage(ctx.binName)),
47004
- "dry-run": (ctx, rest) => {
47005
- const parsed = parseFlags(rest);
47006
- const body = {
47007
- seat_id: requireValue2(parsed, "seat-id"),
47008
- charter_version_id: requireValue2(parsed, "charter-version-id")
47009
- };
47010
- return execute(ctx, parsed, "agent.run_dry_run", body, (output) => {
47011
- const record2 = asRecord(output);
47012
- const header = `dry run for seat ${field(record2, "seat_id")} (charter ${field(record2, "charter_version_id")}): ${field(record2, "status")} (reused=${field(record2, "reused")})
46658
+ function renderAgentTemplates(output) {
46659
+ const templates = asArray(asRecord(output).templates);
46660
+ if (templates.length === 0) {
46661
+ return "No stock agent templates available.";
46662
+ }
46663
+ return templates.map((template) => {
46664
+ const record2 = asRecord(template);
46665
+ return `${field(record2, "slug")} ${field(record2, "tier")} ${field(record2, "display_name")} \u2014 ${field(record2, "function")}`;
46666
+ }).join("\n");
46667
+ }
46668
+ function renderAgentDryRun(output) {
46669
+ const record2 = asRecord(output);
46670
+ const header = `dry run for seat ${field(record2, "seat_id")} (charter ${field(record2, "charter_version_id")}): ${field(record2, "status")} (reused=${field(record2, "reused")})
47013
46671
  ${field(record2, "summary")}`;
47014
- return [header, formatDryRunTranscript(record2.transcript)].filter((part) => part.length > 0).join("\n");
47015
- });
47016
- },
47017
- "go-live": (ctx, rest) => {
47018
- const parsed = parseFlags(rest);
47019
- const body = {
47020
- seat_id: requireValue2(parsed, "seat-id"),
47021
- charter_version_id: requireValue2(parsed, "charter-version-id")
47022
- };
47023
- return execute(ctx, parsed, "agent.go_live", body, (output) => {
47024
- const record2 = asRecord(output);
47025
- return `agent seat ${field(record2, "seat_id")} is now ${field(record2, "status")} (charter ${field(record2, "charter_version_id")}).`;
47026
- });
47027
- },
47028
- status: (ctx, rest) => {
47029
- const parsed = parseFlags(rest);
47030
- const seatId = requireValue2(parsed, "seat-id");
47031
- return execute(ctx, parsed, "agent.status", { seat_id: seatId }, (output) => {
47032
- const record2 = asRecord(output);
47033
- return `agent seat ${field(record2, "seat_id")} status=${field(record2, "status")} live=${field(record2, "live")} lane=${field(record2, "lane")}`;
47034
- });
47035
- },
47036
- "run-now": (ctx, rest) => {
47037
- const parsed = parseFlags(rest);
47038
- const body = withOptional({ seat_id: requireValue2(parsed, "seat-id") }, {
47039
- task_id: optionalValue(parsed, "task-id")
47040
- });
47041
- return execute(ctx, parsed, "agent.run_now", body, (output) => {
47042
- const workOrder = asRecord(asRecord(output).work_order);
47043
- return `queued ${field(workOrder, "lane")} work order ${field(workOrder, "id")} for agent ${field(workOrder, "agent_id")} (${field(workOrder, "status")})`;
47044
- });
47045
- },
47046
- "fleet-digest": (ctx, rest) => {
47047
- const parsed = parseFlags(rest);
47048
- const body = withOptional({}, {
47049
- window_hours: optionalNumber(parsed, "window-hours"),
47050
- error_limit: optionalNumber(parsed, "error-limit")
47051
- });
47052
- return execute(ctx, parsed, "agent.fleet_digest", body, (output) => {
47053
- const record2 = asRecord(output);
47054
- const summary = asRecord(record2.summary);
47055
- const agents = asArray(record2.agents);
47056
- const header = `fleet ${field(summary, "fleet_count")} seats live=${field(summary, "live_count")} idle=${field(summary, "idle_count")} turns24h=${field(summary, "turns_24h")} failed24h=${field(summary, "failed_runs_24h")} spend7d=$${field(summary, "spend_7d_usd")}`;
47057
- const lines = agents.map((agent) => {
47058
- const r = asRecord(agent);
47059
- return `${field(r, "seat_name")} ${field(r, "health_status")} live=${field(r, "live")} turns24h=${field(r, "turns_24h")} failed=${field(r, "failed_runs_24h")} next=${field(r, "suggested_next_action")}`;
47060
- });
47061
- return [header, ...lines].join("\n");
47062
- });
47063
- },
47064
- "get-run": (ctx, rest) => {
47065
- const parsed = parseFlags(rest);
47066
- const body = {
47067
- seat_id: requireValue2(parsed, "seat-id"),
47068
- run_id: requireValue2(parsed, "run-id")
47069
- };
47070
- return execute(ctx, parsed, "agent.get_run", body, (output) => {
47071
- const run2 = asRecord(asRecord(output).run);
47072
- const errors = asArray(run2.error_logs);
47073
- const errorLine = errors.length === 0 ? "errors=0" : `errors=${errors.length} first=${field(asRecord(errors[0]), "message")}`;
47074
- return `run ${field(run2, "run_id")} status=${field(run2, "status")} lane=${field(run2, "lane")} cost=$${field(run2, "cost_usd")}
46672
+ return [header, formatDryRunTranscript(record2.transcript)].filter((part) => part.length > 0).join("\n");
46673
+ }
46674
+ function renderAgentGoLive(output) {
46675
+ const record2 = asRecord(output);
46676
+ return `agent seat ${field(record2, "seat_id")} is now ${field(record2, "status")} (charter ${field(record2, "charter_version_id")}).`;
46677
+ }
46678
+ function renderAgentStatus(output) {
46679
+ const record2 = asRecord(output);
46680
+ return `agent seat ${field(record2, "seat_id")} status=${field(record2, "status")} live=${field(record2, "live")} lane=${field(record2, "lane")}`;
46681
+ }
46682
+ function renderAgentRunNow(output) {
46683
+ const workOrder = asRecord(asRecord(output).work_order);
46684
+ return `queued ${field(workOrder, "lane")} work order ${field(workOrder, "id")} for agent ${field(workOrder, "agent_id")} (${field(workOrder, "status")})`;
46685
+ }
46686
+ function renderAgentFleetDigest(output) {
46687
+ const record2 = asRecord(output);
46688
+ const summary = asRecord(record2.summary);
46689
+ const agents = asArray(record2.agents);
46690
+ const header = `fleet ${field(summary, "fleet_count")} seats live=${field(summary, "live_count")} idle=${field(summary, "idle_count")} turns24h=${field(summary, "turns_24h")} failed24h=${field(summary, "failed_runs_24h")} spend7d=$${field(summary, "spend_7d_usd")}`;
46691
+ const lines = agents.map((agent) => {
46692
+ const r = asRecord(agent);
46693
+ return `${field(r, "seat_name")} ${field(r, "health_status")} live=${field(r, "live")} turns24h=${field(r, "turns_24h")} failed=${field(r, "failed_runs_24h")} next=${field(r, "suggested_next_action")}`;
46694
+ });
46695
+ return [header, ...lines].join("\n");
46696
+ }
46697
+ function renderAgentGetRun(output) {
46698
+ const run2 = asRecord(asRecord(output).run);
46699
+ const errors = asArray(run2.error_logs);
46700
+ const errorLine = errors.length === 0 ? "errors=0" : `errors=${errors.length} first=${field(asRecord(errors[0]), "message")}`;
46701
+ return `run ${field(run2, "run_id")} status=${field(run2, "status")} lane=${field(run2, "lane")} cost=$${field(run2, "cost_usd")}
47075
46702
  transcript=${field(run2, "transcript_ref")}
47076
46703
  ${errorLine}`;
47077
- });
47078
- },
47079
- // DER-787 (H8): markdown readout for a seat's agent setup. `--markdown` (or
47080
- // default) prints the composed card; `--json` returns the { markdown } object.
47081
- show: (ctx, rest) => {
47082
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["markdown"]));
47083
- const seatId = requireValue2(parsed, "seat-id");
47084
- return execute(ctx, parsed, "agent.show_markdown", { seat_id: seatId }, markdownLine);
47085
- }
47086
- }, agentUsage(context.binName));
47087
- function agentConfigureTools(ctx, rest, decision) {
47088
- const parsed = parseFlags(rest);
47089
- const seatId = requireValue2(parsed, "seat-id");
47090
- const tool = requireValue2(parsed, "tool");
47091
- const body = {
47092
- seat_id: seatId,
47093
- tool_decisions: [{ tool, decision }]
47094
- };
47095
- return execute(ctx, parsed, "agent.configure_tools", body, (output) => {
47096
- const record2 = asRecord(output);
47097
- const decisions = asArray(record2.tool_decisions).map((entry) => {
47098
- const r = asRecord(entry);
47099
- return ` ${field(r, "tool")} ${field(r, "decision")}`;
47100
- }).join("\n");
47101
- return [`Configured tools for seat ${field(record2, "seat_id")} (agent ${field(record2, "agent_id")}).`, decisions].filter((line) => line.length > 0).join("\n");
47102
- });
47103
- }
47104
- function agentUsage(bin) {
47105
- return `Usage: ${bin} agent templates|create|setup|tools|dry-run|go-live|status|run-now|fleet-digest|get-run|show [--json]
47106
- ${bin} agent templates
47107
- ${bin} agent create --seat-id <id> --template <slug> [--expected-version <v>]
47108
- ${bin} agent create --seat-id <id> --custom [--steward-seat-id <id>] [--lane cloud|mcp_session|runner] [--model triage|balanced|complex|hardest|<id>] [--effort low|medium|high|xhigh|max] [--owns <text>] [--success <text>] [--never-alone <text>]
47109
- ${bin} agent setup status [--setup-id <id>] [--seat-id <id>]
47110
- ${bin} agent setup answer --seat-id <id> [--parent-seat-id <id>] [--steward-seat-id <id>] [--lane <lane>] [--model <tier|id>] [--effort <level>] [--schedule-cron <cron>] [--answers a,b]
47111
- ${bin} agent tools connect|decline --seat-id <id> --tool <name>
47112
- ${bin} agent dry-run --seat-id <id> --charter-version-id <id>
47113
- ${bin} agent go-live --seat-id <id> --charter-version-id <id>
47114
- ${bin} agent status --seat-id <id>
47115
- ${bin} agent run-now --seat-id <id> [--task-id <id>]
47116
- ${bin} agent fleet-digest [--window-hours <n>] [--error-limit <n>]
47117
- ${bin} agent get-run --seat-id <id> --run-id <id>
47118
- ${bin} agent show --seat-id <id> [--markdown]`;
47119
- }
47120
- function agentSetupUsage(bin) {
47121
- return `Usage: ${bin} agent setup status|answer [--json]
47122
- ${bin} agent setup status [--setup-id <id>] [--seat-id <id>]
47123
- ${bin} agent setup answer --seat-id <id> [--parent-seat-id <id>] [--steward-seat-id <id>] [--lane <lane>] [--model <tier|id>] [--effort <level>] [--schedule-cron <cron>] [--answers a,b]`;
47124
- }
47125
- function agentToolsUsage(bin) {
47126
- return `Usage: ${bin} agent tools connect|decline [--json]
47127
- ${bin} agent tools connect --seat-id <id> --tool <name>
47128
- ${bin} agent tools decline --seat-id <id> --tool <name>`;
47129
- }
47130
- var toolsWrapper = (context, args) => dispatch(context, "tools", args, {
47131
- list: (ctx, rest) => {
47132
- const parsed = parseFlags(rest);
47133
- const body = withOptional({}, { provider: optionalValue(parsed, "provider") });
47134
- return execute(ctx, parsed, "tool.catalog", body, (output) => {
47135
- const record2 = asRecord(output);
47136
- const tools = asArray(record2.tools);
47137
- const header = `# Tool catalog
46704
+ }
46705
+ function renderAgentConfigureTools(output) {
46706
+ const record2 = asRecord(output);
46707
+ const decisions = asArray(record2.tool_decisions).map((entry) => {
46708
+ const r = asRecord(entry);
46709
+ return ` ${field(r, "tool")} ${field(r, "decision")}`;
46710
+ }).join("\n");
46711
+ return [`Configured tools for seat ${field(record2, "seat_id")} (agent ${field(record2, "agent_id")}).`, decisions].filter((line) => line.length > 0).join("\n");
46712
+ }
46713
+ function renderToolCatalog(output) {
46714
+ const record2 = asRecord(output);
46715
+ const tools = asArray(record2.tools);
46716
+ const header = `# Tool catalog
47138
46717
 
47139
46718
  ${field(record2, "note")}
47140
46719
  `;
47141
- if (tools.length === 0) {
47142
- return `${header}
46720
+ if (tools.length === 0) {
46721
+ return `${header}
47143
46722
  No tools in the catalog.`;
47144
- }
47145
- const lines = tools.map((entry) => {
47146
- const r = asRecord(entry);
47147
- const cred = r.credential_required === true ? " (credential required)" : "";
47148
- return `- \`${field(r, "id")}\` [${field(r, "provider")} \xB7 ${field(r, "default_scope_tier")} \xB7 ${field(r, "default_access_policy")}]${cred}
46723
+ }
46724
+ const lines = tools.map((entry) => {
46725
+ const r = asRecord(entry);
46726
+ const cred = r.credential_required === true ? " (credential required)" : "";
46727
+ return `- \`${field(r, "id")}\` [${field(r, "provider")} \xB7 ${field(r, "default_scope_tier")} \xB7 ${field(r, "default_access_policy")}]${cred}
47149
46728
  ${field(r, "description")}`;
47150
- });
47151
- return `${header}
46729
+ });
46730
+ return `${header}
47152
46731
  ${lines.join("\n")}`;
47153
- });
46732
+ }
46733
+ function renderModelCatalog(output) {
46734
+ const record2 = asRecord(output);
46735
+ const tiers = asArray(record2.tiers);
46736
+ const header = `# Model tiers
46737
+
46738
+ ${field(record2, "note")}
46739
+ `;
46740
+ if (tiers.length === 0) {
46741
+ return `${header}
46742
+ No model tiers are configured.`;
46743
+ }
46744
+ const defaultTier = field(record2, "default_tier");
46745
+ const lines = tiers.map((entry) => {
46746
+ const r = asRecord(entry);
46747
+ const tier = field(r, "tier");
46748
+ const recommended = r.recommended === true || tier === defaultTier ? " recommended" : "";
46749
+ const bestFor = asArray(r.best_for).map(String).join(", ");
46750
+ return [
46751
+ `- \`${tier}\` [${field(r, "provider")}/${field(r, "model")} \xB7 effort ${field(r, "effort")} \xB7 cost ${field(r, "cost_band")}${recommended}]`,
46752
+ ` ${field(r, "description")}`,
46753
+ ` Best for: ${bestFor}`,
46754
+ ` Price: $${field(r, "input_usd_per_million_tokens")}/1M input \xB7 $${field(r, "output_usd_per_million_tokens")}/1M output`,
46755
+ ` Cost: ${field(r, "cost_note")}`,
46756
+ ` Avoid for: ${field(r, "avoid_for")}`
46757
+ ].join("\n");
46758
+ });
46759
+ return `${header}
46760
+ ${lines.join("\n")}`;
46761
+ }
46762
+ function renderErrorList(output) {
46763
+ const record2 = asRecord(output);
46764
+ const errors = asArray(record2.errors);
46765
+ if (errors.length === 0) {
46766
+ return "No error logs matching the filter.";
46767
+ }
46768
+ return errors.map((entry) => {
46769
+ const r = asRecord(entry);
46770
+ const disposition = field(r, "disposition");
46771
+ const marker = disposition === "active" ? "*" : " ";
46772
+ const severityLabel = field(r, "severity").charAt(0).toUpperCase();
46773
+ return `${marker} ${field(r, "error_log_id")} [${severityLabel}] ${field(r, "source")} ${disposition} ${field(r, "code")} ${field(r, "message")} ${field(r, "created_at")}`;
46774
+ }).join("\n") + (field(record2, "total") !== "" ? `
46775
+ Total: ${field(record2, "total")}` : "");
46776
+ }
46777
+ function renderErrorResolve(output) {
46778
+ const record2 = asRecord(output);
46779
+ return `Resolved error ${field(record2, "error_log_id")} as ${field(record2, "disposition")} at ${field(record2, "resolved_at")}.`;
46780
+ }
46781
+ function renderErrorSupersede(output) {
46782
+ const record2 = asRecord(output);
46783
+ return `Superseded error ${field(record2, "error_log_id")} \u2192 ${field(record2, "superseded_by_id")} at ${field(record2, "resolved_at")}.`;
46784
+ }
46785
+ function renderDeliverableList(output) {
46786
+ const deliverables = asArray(asRecord(output).deliverables);
46787
+ if (deliverables.length === 0) {
46788
+ return "No deliverables for this seat.";
46789
+ }
46790
+ return deliverables.map((entry) => {
46791
+ const r = asRecord(entry);
46792
+ const summary = field(r, "summary") === "\u2014" ? "" : ` \u2014 ${field(r, "summary")}`;
46793
+ return `${field(r, "id")} [${field(r, "kind")}] ${field(r, "title")}${summary}`;
46794
+ }).join("\n");
46795
+ }
46796
+ function renderDeliverableDetail(output) {
46797
+ const d = asRecord(asRecord(output).deliverable);
46798
+ const links = asArray(d.links).map((entry) => {
46799
+ const l = asRecord(entry);
46800
+ return ` ${field(l, "kind")}: ${field(l, "label")} <${field(l, "url")}>`;
46801
+ }).join("\n");
46802
+ return [
46803
+ `# ${field(d, "title")} [${field(d, "kind")}]`,
46804
+ field(d, "id"),
46805
+ field(d, "summary") === "\u2014" ? "" : field(d, "summary"),
46806
+ field(d, "content") === "\u2014" ? "" : `content:
46807
+ ${field(d, "content")}`,
46808
+ `delivered: ${field(d, "delivered_at")}`,
46809
+ `run: ${field(d, "source_run_status")} ${field(d, "source_run_model")}`,
46810
+ `task: ${field(d, "source_task_title")}`,
46811
+ links.length > 0 ? `links:
46812
+ ${links}` : ""
46813
+ ].filter((line) => line.length > 0).join("\n");
46814
+ }
46815
+ function renderDeliverableWrite(output) {
46816
+ return `deliverable ${field(asRecord(output), "deliverable_id")} recorded.`;
46817
+ }
46818
+ function formatSystemHealth(output) {
46819
+ const record2 = asRecord(output);
46820
+ const scope = asRecord(record2.scope);
46821
+ const sections = asRecord(record2.sections);
46822
+ const actions = asArray(record2.top_actions);
46823
+ const findings = asArray(record2.findings);
46824
+ const lines = [
46825
+ `verdict: ${field(record2, "verdict")} scope: ${field(scope, "mode")} seats: ${field(scope, "total_seat_count")} findings: ${findings.length}`
46826
+ ];
46827
+ if (actions.length > 0) {
46828
+ lines.push("top_actions:");
46829
+ for (const action of actions) {
46830
+ const item = asRecord(action);
46831
+ lines.push(` ${field(item, "label")} command=${field(item, "command_id")} schema=${field(item, "schema_ref")} cli=${field(item, "cli")}`);
46832
+ if (field(item, "help") !== "\u2014") {
46833
+ lines.push(` ${field(item, "help")}`);
46834
+ }
46835
+ }
47154
46836
  }
47155
- }, toolsUsage(context.binName));
47156
- function toolsUsage(bin) {
47157
- return `Usage: ${bin} tools list [--provider <name>] [--json]
47158
- ${bin} tools list \u2014 the discoverable tool catalog the builder reads; live handlers execute only behind signed manifests, guards, credentials, and bindings.`;
46837
+ const fleet = asRecord(sections.fleet);
46838
+ const runs = asRecord(sections.runs);
46839
+ const signals = asRecord(sections.signals);
46840
+ const cascade = asRecord(sections.cascade_setup);
46841
+ const workLoop = asRecord(sections.work_loop);
46842
+ const connectivity = asRecord(sections.connectivity);
46843
+ const sync = asRecord(sections.sync);
46844
+ lines.push(
46845
+ `fleet: agents=${field(fleet, "agent_count")} live=${field(fleet, "live_count")} stale=${field(fleet, "stale_count")} setup_gaps=${field(fleet, "setup_gap_count")}`,
46846
+ `runs: failed_24h=${field(runs, "failed_24h")} failed_7d=${field(runs, "failed_7d")} unresolved_errors=${field(runs, "unresolved_error_count")}`,
46847
+ `signals: off_track=${field(signals, "off_track_count")} pending=${field(signals, "pending_count")}`,
46848
+ `cascade: recommendations=${field(cascade, "recommendation_count")} warnings=${field(cascade, "warning_count")}`,
46849
+ `work_loop: open_issues=${field(workLoop, "open_issue_count")} friction_without_task=${field(workLoop, "friction_without_task_count")} open_or_stalled_tasks=${field(workLoop, "open_or_stalled_task_count")}`,
46850
+ `connectivity: runners=${field(connectivity, "runner_count")} offline_runners=${field(connectivity, "offline_runner_count")} not_ready_runners=${field(connectivity, "not_execute_ready_runner_count")} integrations=${field(connectivity, "integration_count")} disconnected_integrations=${field(connectivity, "disconnected_integration_count")} failed_notifications=${field(connectivity, "failed_notification_count")}`,
46851
+ `sync: latest_brief=${field(sync, "latest_brief_at")} missing_latest_brief=${field(sync, "missing_latest_brief")} flagged_gaps=${field(sync, "flagged_gap_count")}`
46852
+ );
46853
+ return lines.join("\n");
47159
46854
  }
47160
- function formatSkillList(output) {
46855
+ function renderSkillList(output) {
47161
46856
  const skills = asArray(asRecord(output).skills);
47162
46857
  if (skills.length === 0) {
47163
46858
  return "No skills found.";
@@ -47171,7 +46866,7 @@ function formatSkillList(output) {
47171
46866
  })
47172
46867
  ].join("\n");
47173
46868
  }
47174
- function formatSkillDetail(output) {
46869
+ function renderSkillDetail(output) {
47175
46870
  const skill = asRecord(asRecord(output).skill);
47176
46871
  const required2 = asArray(skill.required_tools).map((entry) => field(asRecord(entry), "tool")).join(", ") || "none";
47177
46872
  const optional2 = asArray(skill.optional_tools).map((entry) => field(asRecord(entry), "tool")).join(", ") || "none";
@@ -47185,7 +46880,7 @@ function formatSkillDetail(output) {
47185
46880
  `files: SKILL.md${files === "SKILL.md" ? "" : `, ${files}`}`
47186
46881
  ].join("\n");
47187
46882
  }
47188
- function formatAssignedSkills(output) {
46883
+ function renderAssignedSkills(output) {
47189
46884
  const record2 = asRecord(output);
47190
46885
  const assignments = asArray(record2.assignments);
47191
46886
  if (assignments.length === 0) {
@@ -47200,7 +46895,7 @@ function formatAssignedSkills(output) {
47200
46895
  })
47201
46896
  ].join("\n");
47202
46897
  }
47203
- function formatDependencyCheck(output) {
46898
+ function renderDependencyCheck(output) {
47204
46899
  const record2 = asRecord(output);
47205
46900
  const render = (label, items) => {
47206
46901
  if (items.length === 0) {
@@ -47222,12 +46917,10 @@ function formatDependencyCheck(output) {
47222
46917
  render("optional", asArray(record2.optional))
47223
46918
  ].join("\n");
47224
46919
  }
47225
- function packageFromSkillFile(filePath) {
47226
- return {
47227
- files: [{ path: "SKILL.md", content: readFileSync2(filePath, "utf8") }]
47228
- };
46920
+ function renderSkillFile(output) {
46921
+ return field(asRecord(output), "content");
47229
46922
  }
47230
- function formatSkillWrite(label) {
46923
+ function renderSkillWrite(label) {
47231
46924
  return (output) => {
47232
46925
  const skill = asRecord(asRecord(output).skill);
47233
46926
  const warnings = asArray(asRecord(skill.validation).warnings).length;
@@ -47239,7 +46932,7 @@ function formatSkillWrite(label) {
47239
46932
  ].join("\n");
47240
46933
  };
47241
46934
  }
47242
- function formatAssignment(output) {
46935
+ function renderAssignment(output) {
47243
46936
  const record2 = asRecord(output);
47244
46937
  const assignment = asRecord(record2.assignment);
47245
46938
  return [
@@ -47250,7 +46943,7 @@ function formatAssignment(output) {
47250
46943
  `next: ${field(record2, "local_sync_next_step")}`
47251
46944
  ].join("\n");
47252
46945
  }
47253
- function formatRevocation(output) {
46946
+ function renderRevocation(output) {
47254
46947
  const record2 = asRecord(output);
47255
46948
  return [
47256
46949
  `Skill assignment revoked: \`${field(record2, "slug")}\` from seat ${field(record2, "seat_id")}`,
@@ -47259,468 +46952,751 @@ function formatRevocation(output) {
47259
46952
  `next: ${field(record2, "local_sync_next_step")}`
47260
46953
  ].join("\n");
47261
46954
  }
47262
- var skillsWrapper = (context, args) => dispatch(context, "skills", args, {
47263
- create: (ctx, rest) => {
47264
- const parsed = parseFlags(rest);
47265
- const body = withOptional({ package: packageFromSkillFile(requireValue2(parsed, "file")) }, {
46955
+ function packageFromSkillFile(filePath) {
46956
+ return { files: [{ path: "SKILL.md", content: readFileSync2(filePath, "utf8") }] };
46957
+ }
46958
+ function bespoke(commandId, build, render, booleanFlags = /* @__PURE__ */ new Set()) {
46959
+ return (context, rest) => {
46960
+ const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["yes", "y", ...booleanFlags]));
46961
+ const body = build(parsed, rest);
46962
+ return execute(context, parsed, commandId, body, render);
46963
+ };
46964
+ }
46965
+ var statusRecordHandler = bespoke("status.record", (parsed) => {
46966
+ const measurableId = optionalValue(parsed, "measurable-id");
46967
+ const goalId = optionalValue(parsed, "goal-id");
46968
+ const body = {};
46969
+ if (measurableId !== void 0) {
46970
+ const value = parseNumber(parsed, "value", { required: true });
46971
+ body.measurables = [{ id: measurableId, value }];
46972
+ }
46973
+ if (goalId !== void 0) {
46974
+ const state = requireValue2(parsed, "goal-state");
46975
+ if (state !== "on" && state !== "off") {
46976
+ throw new UsageError("--goal-state must be on or off.");
46977
+ }
46978
+ const note = optionalValue(parsed, "goal-note");
46979
+ body.goals = [withOptional({ id: goalId, state }, { note })];
46980
+ }
46981
+ if (measurableId === void 0 && goalId === void 0) {
46982
+ throw new UsageError("Provide --measurable-id (with --value) and/or --goal-id (with --goal-state).");
46983
+ }
46984
+ return body;
46985
+ }, renderStatusRecord);
46986
+ var agentCreateHandler = (context, rest) => {
46987
+ const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["custom", "yes", "y"]));
46988
+ const templateSlug = optionalValue(parsed, "template");
46989
+ const seatId = requireValue2(parsed, "seat-id");
46990
+ if (parsed.flags.has("custom")) {
46991
+ if (templateSlug !== void 0) {
46992
+ throw new UsageError("Use either --template <slug> or --custom, not both.");
46993
+ }
46994
+ const body2 = withOptional({ seat_id: seatId }, {
46995
+ steward_seat_id: optionalValue(parsed, "steward-seat-id"),
46996
+ lane: optionalValue(parsed, "lane"),
46997
+ model_config: resolveModelConfig(optionalValue(parsed, "model"), optionalValue(parsed, "effort")),
46998
+ what_it_owns: optionalValue(parsed, "owns"),
46999
+ what_success_looks_like: optionalValue(parsed, "success"),
47000
+ what_it_must_never_do_alone: optionalValue(parsed, "never-alone")
47001
+ });
47002
+ return execute(context, parsed, "agent.create_custom", body2, agentSetupStateLine);
47003
+ }
47004
+ if (templateSlug === void 0) {
47005
+ throw new UsageError("Provide --template <slug> or --custom.");
47006
+ }
47007
+ const body = withOptional({ seat_id: seatId, template_slug: templateSlug }, {
47008
+ expected_template_version: optionalValue(parsed, "expected-version")
47009
+ });
47010
+ return execute(context, parsed, "agent.create_from_template", body, agentSetupStateLine);
47011
+ };
47012
+ var agentSetupAnswerHandler = bespoke("agent_setup.update", (parsed) => {
47013
+ const body = withOptional({ seat_id: requireValue2(parsed, "seat-id") }, {
47014
+ parent_seat_id: optionalValue(parsed, "parent-seat-id"),
47015
+ steward_seat_id: optionalValue(parsed, "steward-seat-id"),
47016
+ lane: optionalValue(parsed, "lane"),
47017
+ schedule_cron: optionalValue(parsed, "schedule-cron"),
47018
+ model_config: resolveModelConfig(optionalValue(parsed, "model"), optionalValue(parsed, "effort")),
47019
+ answers: parseList(parsed, "answers")
47020
+ });
47021
+ if (Object.keys(body).length <= 1) {
47022
+ throw new UsageError("Provide at least one of --parent-seat-id, --steward-seat-id, --lane, --schedule-cron, --model, --answers.");
47023
+ }
47024
+ return body;
47025
+ }, agentSetupStateLine);
47026
+ function agentConfigureToolsHandler(decision) {
47027
+ return bespoke("agent.configure_tools", (parsed) => ({
47028
+ seat_id: requireValue2(parsed, "seat-id"),
47029
+ tool_decisions: [{ tool: requireValue2(parsed, "tool"), decision }]
47030
+ }), renderAgentConfigureTools);
47031
+ }
47032
+ var skillCreateHandler = bespoke(
47033
+ "skill.create",
47034
+ (parsed) => withOptional({ package: packageFromSkillFile(requireValue2(parsed, "file")) }, { status: optionalValue(parsed, "status") }),
47035
+ renderSkillWrite("Skill draft created")
47036
+ );
47037
+ var skillUpdateDraftHandler = bespoke(
47038
+ "skill.update_draft",
47039
+ (parsed) => withOptional({ slug: requireValue2(parsed, "slug"), package: packageFromSkillFile(requireValue2(parsed, "file")) }, { status: optionalValue(parsed, "status") }),
47040
+ renderSkillWrite("Skill draft updated")
47041
+ );
47042
+ var skillPublishHandler = bespoke("skill.publish", (parsed) => withOptional({ allow_warnings: parsed.flags.has("allow-warnings") }, {
47043
+ slug: optionalValue(parsed, "slug"),
47044
+ skill_version_id: optionalValue(parsed, "skill-version-id")
47045
+ }), renderSkillWrite("Skill published"), /* @__PURE__ */ new Set(["allow-warnings"]));
47046
+ var skillImportHandler = (context, rest) => {
47047
+ const [kind, ...remaining] = rest;
47048
+ if (kind === "github") {
47049
+ const parsed = parseFlags(remaining, /* @__PURE__ */ new Set(["yes", "y"]));
47050
+ const body = withOptional({ url: requireValue2(parsed, "url") }, {
47051
+ ref: optionalValue(parsed, "ref"),
47052
+ path: optionalValue(parsed, "path"),
47266
47053
  status: optionalValue(parsed, "status")
47267
47054
  });
47268
- return execute(ctx, parsed, "skill.create", body, formatSkillWrite("Skill draft created"));
47055
+ return execute(context, parsed, "skill.import_github", body, renderSkillWrite("GitHub skill imported"));
47056
+ }
47057
+ if (kind === "upload") {
47058
+ const parsed = parseFlags(remaining, /* @__PURE__ */ new Set(["yes", "y"]));
47059
+ const body = withOptional({ package: packageFromSkillFile(requireValue2(parsed, "file")) }, { status: optionalValue(parsed, "status") });
47060
+ return execute(context, parsed, "skill.import_upload", body, renderSkillWrite("Uploaded skill imported"));
47061
+ }
47062
+ throw new UsageError(`Usage: ${context.binName} skills import github|upload ...`);
47063
+ };
47064
+ var skillAssignHandler = bespoke("skill.assign_to_seat", (parsed) => withOptional({
47065
+ seat_id: requireValue2(parsed, "seat-id"),
47066
+ status: parsed.flags.has("approve") ? "approved" : "proposed",
47067
+ rationale: optionalValue(parsed, "rationale") ?? "Skill assignment requested from the CLI.",
47068
+ allow_blocked_proposal: parsed.flags.has("allow-blocked-proposal")
47069
+ }, {
47070
+ slug: optionalValue(parsed, "slug") ?? optionalValue(parsed, "skill"),
47071
+ skill_version_id: optionalValue(parsed, "skill-version-id")
47072
+ }), renderAssignment, /* @__PURE__ */ new Set(["approve", "allow-blocked-proposal"]));
47073
+ var skillRevokeHandler = bespoke("skill.revoke_from_seat", (parsed) => withOptional({}, {
47074
+ assignment_id: optionalValue(parsed, "assignment-id"),
47075
+ seat_id: optionalValue(parsed, "seat-id"),
47076
+ slug: optionalValue(parsed, "slug") ?? optionalValue(parsed, "skill"),
47077
+ skill_version_id: optionalValue(parsed, "skill-version-id"),
47078
+ rationale: optionalValue(parsed, "rationale")
47079
+ }), renderRevocation);
47080
+ var skillListHandler = bespoke("skill.list", (parsed) => withOptional({}, {
47081
+ status: optionalValue(parsed, "status"),
47082
+ visibility: optionalValue(parsed, "visibility"),
47083
+ query: optionalValue(parsed, "query"),
47084
+ include_archived: parsed.flags.has("include-archived") ? true : void 0
47085
+ }), renderSkillList, /* @__PURE__ */ new Set(["include-archived"]));
47086
+ var frictionFileHandler = bespoke("friction.file_issue", (parsed) => withOptional({
47087
+ summary: requireValue2(parsed, "summary"),
47088
+ severity: requireValue2(parsed, "severity"),
47089
+ evidence: parseList(parsed, "evidence") ?? []
47090
+ }, {
47091
+ blocking_goal_id: optionalValue(parsed, "blocking-goal-id"),
47092
+ broken_measurable_id: optionalValue(parsed, "broken-measurable-id")
47093
+ }), renderFrictionFile);
47094
+ function integrationLookupBody(parsed) {
47095
+ const body = withOptional({}, {
47096
+ provider: optionalValue(parsed, "provider"),
47097
+ integration_id: optionalValue(parsed, "integration-id")
47098
+ });
47099
+ if (Object.keys(body).length === 0) {
47100
+ throw new UsageError("Provide --provider or --integration-id.");
47101
+ }
47102
+ return body;
47103
+ }
47104
+ var integrationStatusHandler = bespoke("integration.status", integrationLookupBody, renderIntegrationStatus);
47105
+ var integrationTestHandler = bespoke("integration.test", integrationLookupBody, renderIntegrationTest);
47106
+ var settingsUpdateHandler = bespoke("settings.update", (parsed) => {
47107
+ const body = withOptional({}, {
47108
+ soft_cap_usd: optionalValue(parsed, "soft-cap-usd"),
47109
+ hard_cap_usd: optionalValue(parsed, "hard-cap-usd")
47110
+ });
47111
+ if (Object.keys(body).length === 0) {
47112
+ throw new UsageError("Provide --soft-cap-usd and/or --hard-cap-usd.");
47113
+ }
47114
+ return body;
47115
+ }, renderSettingsUpdate);
47116
+ var settingsRenameHandler = bespoke("tenant.rename", (parsed) => {
47117
+ const companyName = optionalValue(parsed, "company");
47118
+ if (!companyName) {
47119
+ throw new UsageError("Provide --company <name>.");
47120
+ }
47121
+ return { company_name: companyName };
47122
+ }, renderTenantRename);
47123
+ var goalUpdateHandler = bespoke("goal.update", (parsed) => {
47124
+ const rejectBlank = (key, label) => {
47125
+ const raw = parsed.values.get(key);
47126
+ if (raw !== void 0 && raw.trim().length === 0) {
47127
+ throw new UsageError(`${label} must not be empty.`);
47128
+ }
47129
+ };
47130
+ rejectBlank("title", "--title");
47131
+ rejectBlank("definition-of-done", "--definition-of-done");
47132
+ const title = optionalValue(parsed, "title");
47133
+ const definitionOfDone = optionalValue(parsed, "definition-of-done");
47134
+ if (title === void 0 && definitionOfDone === void 0) {
47135
+ throw new UsageError("Provide --title and/or --definition-of-done.");
47136
+ }
47137
+ return withOptional({ goal_id: requireValue2(parsed, "goal-id") }, { title, definition_of_done: definitionOfDone });
47138
+ }, renderGoalUpdate);
47139
+ var productLearningUpdateHandler = bespoke("settings.product_learning.update", (parsed) => {
47140
+ const mode = optionalValue(parsed, "mode");
47141
+ if (mode !== "enabled" && mode !== "disabled" && mode !== "enterprise_contract") {
47142
+ throw new UsageError("Provide --mode enabled|disabled|enterprise_contract.");
47143
+ }
47144
+ return { mode };
47145
+ }, renderProductLearningUpdate);
47146
+ var agentPolicySetHandler = bespoke("settings.agent_policy.update", (parsed) => {
47147
+ const profile = optionalValue(parsed, "profile");
47148
+ if (profile !== "locked_down" && profile !== "balanced" && profile !== "high_autonomy" && profile !== "custom") {
47149
+ throw new UsageError("Provide --profile locked_down|balanced|high_autonomy|custom.");
47150
+ }
47151
+ return withOptional({ profile }, {
47152
+ max_autonomous_risk: optionalValue(parsed, "max-autonomous-risk"),
47153
+ enforcement: optionalValue(parsed, "enforcement")
47154
+ });
47155
+ }, renderAgentPolicySet);
47156
+ var seatDecommissionHandler = (context, rest) => {
47157
+ const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["dry-run", "preview", "yes", "y"]));
47158
+ if (parsed.flags.has("dry-run") || parsed.flags.has("preview")) {
47159
+ return execute(context, parsed, "seat.decommission_preview", { seat_id: requireValue2(parsed, "seat-id") }, renderSeatDecommissionPreview);
47160
+ }
47161
+ return execute(context, parsed, "seat.decommission", { seat_id: requireValue2(parsed, "seat-id") }, renderSeatMutation);
47162
+ };
47163
+ var settingsProductLearningHandler = (context, rest) => dispatch(context, "settings product-learning", rest, {
47164
+ get: (ctx, r) => {
47165
+ const parsed = parseFlags(r, /* @__PURE__ */ new Set(["yes", "y"]));
47166
+ return execute(ctx, parsed, "settings.product_learning.get", {}, renderProductLearningGet);
47269
47167
  },
47270
- "update-draft": (ctx, rest) => {
47271
- const parsed = parseFlags(rest);
47272
- const body = withOptional({
47273
- slug: requireValue2(parsed, "slug"),
47274
- package: packageFromSkillFile(requireValue2(parsed, "file"))
47275
- }, {
47276
- status: optionalValue(parsed, "status")
47277
- });
47278
- return execute(ctx, parsed, "skill.update_draft", body, formatSkillWrite("Skill draft updated"));
47168
+ update: (ctx, r) => productLearningUpdateHandler(ctx, r)
47169
+ }, `Usage: ${context.binName} settings product-learning get|update --mode enabled|disabled|enterprise_contract`);
47170
+ var settingsAgentPolicyHandler = (context, rest) => dispatch(context, "settings agent-policy", rest, {
47171
+ get: (ctx, r) => {
47172
+ const parsed = parseFlags(r, /* @__PURE__ */ new Set(["yes", "y"]));
47173
+ return execute(ctx, parsed, "settings.agent_policy.get", {}, renderAgentPolicyGet);
47279
47174
  },
47280
- publish: (ctx, rest) => {
47281
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["allow-warnings"]));
47282
- const body = withOptional({ allow_warnings: parsed.flags.has("allow-warnings") }, {
47283
- slug: optionalValue(parsed, "slug"),
47284
- skill_version_id: optionalValue(parsed, "skill-version-id")
47175
+ set: (ctx, r) => agentPolicySetHandler(ctx, r)
47176
+ }, `Usage: ${context.binName} settings agent-policy get|set --profile locked_down|balanced|high_autonomy|custom [--max-autonomous-risk <r>] [--enforcement enforce|observe]`);
47177
+ var agentSetupHandler = (context, rest) => dispatch(context, "agent setup", rest, {
47178
+ status: (ctx, r) => {
47179
+ const parsed = parseFlags(r, /* @__PURE__ */ new Set(["yes", "y"]));
47180
+ const body = withOptional({}, {
47181
+ setup_id: optionalValue(parsed, "setup-id"),
47182
+ seat_id: optionalValue(parsed, "seat-id")
47285
47183
  });
47286
- return execute(ctx, parsed, "skill.publish", body, formatSkillWrite("Skill published"));
47184
+ if (Object.keys(body).length === 0) {
47185
+ throw new UsageError("Provide --setup-id or --seat-id.");
47186
+ }
47187
+ return execute(ctx, parsed, "agent_setup.get", body, agentSetupStateLine);
47287
47188
  },
47288
- import: (ctx, rest) => {
47289
- const [kind, ...remaining] = rest;
47290
- if (kind === "github") {
47291
- const parsed = parseFlags(remaining);
47292
- const body = withOptional({ url: requireValue2(parsed, "url") }, {
47293
- ref: optionalValue(parsed, "ref"),
47294
- path: optionalValue(parsed, "path"),
47295
- status: optionalValue(parsed, "status")
47296
- });
47297
- return execute(ctx, parsed, "skill.import_github", body, formatSkillWrite("GitHub skill imported"));
47189
+ answer: (ctx, r) => agentSetupAnswerHandler(ctx, r)
47190
+ }, `Usage: ${context.binName} agent setup status|answer ...`);
47191
+ var agentToolsHandler = (context, rest) => dispatch(context, "agent tools", rest, {
47192
+ connect: agentConfigureToolsHandler("connect"),
47193
+ decline: agentConfigureToolsHandler("decline")
47194
+ }, `Usage: ${context.binName} agent tools connect|decline --seat-id <id> --tool <name>`);
47195
+ var systemHealthHandler = bespoke("system.health", (parsed) => withOptional({}, { seat_id: parsed.seat }), formatSystemHealth);
47196
+ var deliverableGetHandler = bespoke("deliverable.get", (parsed) => ({
47197
+ seat_id: requireValue2(parsed, "seat-id"),
47198
+ deliverable_id: requireValue2(parsed, "deliverable-id")
47199
+ }), renderDeliverableDetail);
47200
+ var GROUP_SPECS = {
47201
+ graph: {
47202
+ verbs: {
47203
+ show: { commandId: "graph.get", render: renderGraph },
47204
+ get: { commandId: "graph.get", render: renderGraph }
47298
47205
  }
47299
- if (kind === "upload") {
47300
- const parsed = parseFlags(remaining);
47301
- const body = withOptional({ package: packageFromSkillFile(requireValue2(parsed, "file")) }, {
47302
- status: optionalValue(parsed, "status")
47303
- });
47304
- return execute(ctx, parsed, "skill.import_upload", body, formatSkillWrite("Uploaded skill imported"));
47206
+ },
47207
+ seat: {
47208
+ verbs: {
47209
+ list: { commandId: "graph.get", render: renderSeatList, usage: "seat list" },
47210
+ get: { commandId: "seat.get", render: renderSeatDetail, primaryPositional: "seat_id" },
47211
+ create: { commandId: "seat.create", render: renderSeatMutation, flagAliases: { type: "seat_type" } },
47212
+ rename: { commandId: "seat.rename", render: renderSeatMutation },
47213
+ reparent: { commandId: "seat.reparent", render: renderSeatMutation, flagAliases: { "parent-seat-id": "new_parent_seat_id" } },
47214
+ decommission: { commandId: "seat.decommission", render: renderSeatMutation, handler: seatDecommissionHandler }
47305
47215
  }
47306
- throw new UsageError(`Usage: ${ctx.binName} skills import github|upload ...`);
47307
47216
  },
47308
- list: (ctx, rest) => {
47309
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["include-archived"]));
47310
- const body = withOptional({}, {
47311
- status: optionalValue(parsed, "status"),
47312
- visibility: optionalValue(parsed, "visibility"),
47313
- query: optionalValue(parsed, "query"),
47314
- include_archived: parsed.flags.has("include-archived") ? true : void 0
47315
- });
47316
- return execute(ctx, parsed, "skill.list", body, formatSkillList);
47217
+ task: {
47218
+ verbs: {
47219
+ list: { commandId: "task.list", render: renderTaskList },
47220
+ accept: { commandId: "task.accept", render: renderTaskAccept, primaryPositional: "id" },
47221
+ decline: { commandId: "task.decline", render: renderTaskDecline },
47222
+ complete: { commandId: "task.complete", render: renderTaskComplete },
47223
+ create: { commandId: "task.create", render: renderTaskCreate }
47224
+ }
47225
+ },
47226
+ status: {
47227
+ verbs: {
47228
+ record: { commandId: "status.record", handler: statusRecordHandler, render: renderStatusRecord, usage: "status record --measurable-id <id> --value <n> | --goal-id <id> --goal-state on|off [--goal-note <text>]" }
47229
+ }
47317
47230
  },
47318
- get: (ctx, rest) => {
47319
- const parsed = parseFlags(rest);
47320
- return execute(ctx, parsed, "skill.get", { slug: requireValue2(parsed, "slug") }, formatSkillDetail);
47231
+ signal: {
47232
+ verbs: {
47233
+ list: { commandId: "signal.list", render: renderSignalList },
47234
+ get: { commandId: "signal.get", render: renderSignalGet, primaryPositional: "measurable_id" },
47235
+ confirm: { commandId: "signal.confirm_reading", render: renderSignalConfirm },
47236
+ correct: { commandId: "signal.correct_reading", render: renderSignalCorrect }
47237
+ }
47321
47238
  },
47322
- file: (ctx, rest) => {
47323
- const parsed = parseFlags(rest);
47324
- const body = { slug: requireValue2(parsed, "slug"), path: requireValue2(parsed, "path") };
47325
- return execute(ctx, parsed, "skill.file.get", body, (output) => field(asRecord(output), "content"));
47239
+ goal: {
47240
+ verbs: {
47241
+ list: { commandId: "goal.list", render: renderGoalList },
47242
+ create: { commandId: "goal.create", render: renderGoalCreate },
47243
+ update: { commandId: "goal.update", handler: goalUpdateHandler, render: renderGoalUpdate },
47244
+ status: { commandId: "goal.set_status", render: renderGoalStatus },
47245
+ reparent: { commandId: "goal.reparent", render: renderGoalReparent },
47246
+ drop: { commandId: "goal.drop", render: renderGoalDrop }
47247
+ }
47326
47248
  },
47327
- assigned: (ctx, rest) => {
47328
- const parsed = parseFlags(rest);
47329
- const body = withOptional({}, { seat_id: optionalValue(parsed, "seat-id") });
47330
- return execute(ctx, parsed, "skill.assigned.list", body, formatAssignedSkills);
47249
+ friction: {
47250
+ verbs: {
47251
+ list: { commandId: "friction.list", render: renderFrictionList },
47252
+ file: { commandId: "friction.file_issue", handler: frictionFileHandler, render: renderFrictionFile },
47253
+ resolve: { commandId: "friction.resolve", render: renderFrictionResolve },
47254
+ link: { commandId: "friction.link_task", render: renderFrictionLink }
47255
+ }
47331
47256
  },
47332
- "check-dependencies": (ctx, rest) => {
47333
- const parsed = parseFlags(rest);
47334
- const body = withOptional({ seat_id: requireValue2(parsed, "seat-id") }, {
47335
- slug: optionalValue(parsed, "slug"),
47336
- skill_version_id: optionalValue(parsed, "skill-version-id")
47337
- });
47338
- return execute(ctx, parsed, "skill.check_dependencies", body, formatDependencyCheck);
47257
+ escalation: {
47258
+ verbs: {
47259
+ list: { commandId: "escalation.list", render: renderEscalationList },
47260
+ get: { commandId: "escalation.get", render: renderEscalationGet, primaryPositional: "id" },
47261
+ resolve: { commandId: "escalation.resolve", render: renderEscalationResolve },
47262
+ reject: { commandId: "escalation.reject", render: renderEscalationReject }
47263
+ }
47339
47264
  },
47340
- assign: (ctx, rest) => {
47341
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["approve", "allow-blocked-proposal"]));
47342
- const body = withOptional({
47343
- seat_id: requireValue2(parsed, "seat-id"),
47344
- status: parsed.flags.has("approve") ? "approved" : "proposed",
47345
- rationale: optionalValue(parsed, "rationale") ?? "Skill assignment requested from the CLI.",
47346
- allow_blocked_proposal: parsed.flags.has("allow-blocked-proposal")
47347
- }, {
47348
- slug: optionalValue(parsed, "slug") ?? optionalValue(parsed, "skill"),
47349
- skill_version_id: optionalValue(parsed, "skill-version-id")
47350
- });
47351
- return execute(ctx, parsed, "skill.assign_to_seat", body, formatAssignment);
47265
+ sync: {
47266
+ verbs: {
47267
+ brief: { commandId: "sync.brief.get", render: renderSyncBrief },
47268
+ compile: { commandId: "sync.brief.compile", render: renderSyncCompile },
47269
+ complete: { commandId: "sync.run.complete", render: renderSyncComplete }
47270
+ }
47352
47271
  },
47353
- revoke: (ctx, rest) => {
47354
- const parsed = parseFlags(rest);
47355
- const body = withOptional({}, {
47356
- assignment_id: optionalValue(parsed, "assignment-id"),
47357
- seat_id: optionalValue(parsed, "seat-id"),
47358
- slug: optionalValue(parsed, "slug") ?? optionalValue(parsed, "skill"),
47359
- skill_version_id: optionalValue(parsed, "skill-version-id"),
47360
- rationale: optionalValue(parsed, "rationale")
47361
- });
47362
- return execute(ctx, parsed, "skill.revoke_from_seat", body, formatRevocation);
47363
- }
47364
- }, skillsUsage(context.binName));
47365
- function skillsUsage(bin) {
47366
- return `Usage: ${bin} skills create|update-draft|publish|import|list|get|file|assigned|check-dependencies|assign|revoke [--json]
47367
- ${bin} skills create --file ./SKILL.md [--status draft|pending_review]
47368
- ${bin} skills update-draft --slug <slug> --file ./SKILL.md [--status draft|pending_review]
47369
- ${bin} skills import github --url <github-url> [--ref <ref>] [--path <dir>] [--status draft|pending_review]
47370
- ${bin} skills import upload --file ./SKILL.md [--status draft|pending_review]
47371
- ${bin} skills publish (--slug <slug>|--skill-version-id <id>) [--allow-warnings]
47372
- ${bin} skills list [--status draft|pending_review|published|archived] [--visibility private|seat|tenant] [--query <text>]
47373
- ${bin} skills get --slug <slug>
47374
- ${bin} skills file --slug <slug> --path SKILL.md
47375
- ${bin} skills assigned [--seat-id <id>] [--seat <id>]
47376
- ${bin} skills check-dependencies --seat-id <id> (--slug <slug>|--skill-version-id <id>)
47377
- ${bin} skills assign --seat-id <id> (--slug <slug>|--skill-version-id <id>) [--approve] [--allow-blocked-proposal]
47378
- ${bin} skills revoke (--assignment-id <id>|--seat-id <id> --slug <slug>)`;
47379
- }
47380
- var modelWrapper = (context, args) => dispatch(context, "model", args, {
47381
- list: (ctx, rest) => {
47382
- const parsed = parseFlags(rest);
47383
- return execute(ctx, parsed, "model.catalog", {}, (output) => {
47384
- const record2 = asRecord(output);
47385
- const tiers = asArray(record2.tiers);
47386
- const header = `# Model tiers
47272
+ runner: {
47273
+ verbs: {
47274
+ list: { commandId: "runner.list", render: renderRunnerList },
47275
+ status: { commandId: "runner.status", render: renderRunnerStatus },
47276
+ diagnose: { commandId: "runner.diagnose", render: renderRunnerDiagnose },
47277
+ repair: { commandId: "runner.repair", render: renderRunnerRepair },
47278
+ "work-orders": { commandId: "work_order.list", render: renderWorkOrders },
47279
+ revoke: { commandId: "runner.revoke", render: renderRunnerRevoke }
47280
+ }
47281
+ },
47282
+ notification: {
47283
+ verbs: {
47284
+ settings: { commandId: "notification.settings.get", render: renderNotificationSettings },
47285
+ test: { commandId: "notification.test", render: renderNotificationTest },
47286
+ errors: { commandId: "notification.list_errors", render: renderNotificationErrors }
47287
+ }
47288
+ },
47289
+ integration: {
47290
+ verbs: {
47291
+ list: { commandId: "integration.list", render: renderIntegrationList },
47292
+ readiness: { commandId: "integration.readiness", render: renderIntegrationReadiness },
47293
+ status: { commandId: "integration.status", handler: integrationStatusHandler, render: renderIntegrationStatus },
47294
+ test: { commandId: "integration.test", handler: integrationTestHandler, render: renderIntegrationTest }
47295
+ }
47296
+ },
47297
+ settings: {
47298
+ verbs: {
47299
+ get: { commandId: "settings.get", render: renderSettingsGet },
47300
+ update: { commandId: "settings.update", handler: settingsUpdateHandler, render: renderSettingsUpdate },
47301
+ "product-learning": { commandId: "settings.product_learning.get", handler: settingsProductLearningHandler },
47302
+ "agent-policy": { commandId: "settings.agent_policy.get", handler: settingsAgentPolicyHandler },
47303
+ rename: { commandId: "tenant.rename", handler: settingsRenameHandler, render: renderTenantRename }
47304
+ }
47305
+ },
47306
+ member: {
47307
+ verbs: {
47308
+ invite: { commandId: "member.invite", render: renderMemberInvite },
47309
+ update: { commandId: "member.update", render: renderMemberUpdate },
47310
+ remove: { commandId: "member.remove", render: renderMemberRemove }
47311
+ }
47312
+ },
47313
+ agent: {
47314
+ verbs: {
47315
+ templates: { commandId: "agent_template.list", render: renderAgentTemplates },
47316
+ create: { commandId: "agent.create_from_template", handler: agentCreateHandler, usage: "agent create --seat-id <id> (--template <slug> | --custom [--model <tier|id>] [--owns <t>] [--success <t>] [--never-alone <t>])" },
47317
+ setup: { commandId: "agent_setup.get", handler: agentSetupHandler, usage: "agent setup status|answer ..." },
47318
+ tools: { commandId: "agent.configure_tools", handler: agentToolsHandler, usage: "agent tools connect|decline --seat-id <id> --tool <name>" },
47319
+ "dry-run": { commandId: "agent.run_dry_run", render: renderAgentDryRun },
47320
+ "go-live": { commandId: "agent.go_live", render: renderAgentGoLive },
47321
+ status: { commandId: "agent.status", render: renderAgentStatus, primaryPositional: "seat_id" },
47322
+ "run-now": { commandId: "agent.run_now", render: renderAgentRunNow },
47323
+ "fleet-digest": { commandId: "agent.fleet_digest", render: renderAgentFleetDigest },
47324
+ "get-run": { commandId: "agent.get_run", render: renderAgentGetRun },
47325
+ show: { commandId: "agent.show_markdown", render: markdownLine }
47326
+ }
47327
+ },
47328
+ tools: {
47329
+ verbs: {
47330
+ list: { commandId: "tool.catalog", render: renderToolCatalog }
47331
+ }
47332
+ },
47333
+ skills: {
47334
+ verbs: {
47335
+ create: { commandId: "skill.create", handler: skillCreateHandler },
47336
+ "update-draft": { commandId: "skill.update_draft", handler: skillUpdateDraftHandler },
47337
+ publish: { commandId: "skill.publish", handler: skillPublishHandler },
47338
+ import: { commandId: "skill.import_upload", handler: skillImportHandler, usage: "skills import github|upload ..." },
47339
+ list: { commandId: "skill.list", handler: skillListHandler },
47340
+ get: { commandId: "skill.get", render: renderSkillDetail },
47341
+ file: { commandId: "skill.file.get", render: renderSkillFile },
47342
+ assigned: { commandId: "skill.assigned.list", render: renderAssignedSkills },
47343
+ "check-dependencies": { commandId: "skill.check_dependencies", render: renderDependencyCheck },
47344
+ assign: { commandId: "skill.assign_to_seat", handler: skillAssignHandler },
47345
+ revoke: { commandId: "skill.revoke_from_seat", handler: skillRevokeHandler }
47346
+ }
47347
+ },
47348
+ model: {
47349
+ verbs: {
47350
+ list: { commandId: "model.catalog", render: renderModelCatalog }
47351
+ }
47352
+ },
47353
+ error: {
47354
+ verbs: {
47355
+ list: { commandId: "error_log.list", render: renderErrorList },
47356
+ resolve: { commandId: "error_log.resolve", render: renderErrorResolve },
47357
+ supersede: { commandId: "error_log.supersede", render: renderErrorSupersede }
47358
+ }
47359
+ },
47360
+ compass: {
47361
+ verbs: {
47362
+ show: { commandId: "compass.show_markdown", render: markdownLine }
47363
+ }
47364
+ },
47365
+ charter: {
47366
+ verbs: {
47367
+ show: { commandId: "charter.show_markdown", render: markdownLine }
47368
+ }
47369
+ },
47370
+ deliverable: {
47371
+ verbs: {
47372
+ list: { commandId: "deliverable.list", render: renderDeliverableList },
47373
+ get: { commandId: "deliverable.get", handler: deliverableGetHandler, render: renderDeliverableDetail },
47374
+ create: { commandId: "deliverable.create", render: renderDeliverableWrite, defaults: { kind: "other" } },
47375
+ attach: { commandId: "deliverable.attach", render: renderDeliverableWrite, defaults: { kind: "other" } }
47376
+ }
47377
+ },
47378
+ system: {
47379
+ verbs: {
47380
+ health: { commandId: "system.health", handler: systemHealthHandler, render: formatSystemHealth }
47381
+ }
47382
+ }
47383
+ };
47387
47384
 
47388
- ${field(record2, "note")}
47389
- `;
47390
- if (tiers.length === 0) {
47391
- return `${header}
47392
- No model tiers are configured.`;
47385
+ // src/generator/flags.ts
47386
+ function booleanFlagsFor(entry, overrides = {}) {
47387
+ const booleanFields = new Set(entry.fields.filter((field3) => field3.type === "boolean").map((field3) => field3.name));
47388
+ const flags = /* @__PURE__ */ new Set(["yes", "y"]);
47389
+ for (const field3 of entry.fields) {
47390
+ if (field3.type === "boolean") {
47391
+ flags.add(field3.flag);
47392
+ }
47393
+ }
47394
+ for (const [aliasFlag, fieldName] of Object.entries(overrides.flagAliases ?? {})) {
47395
+ if (booleanFields.has(fieldName)) {
47396
+ flags.add(aliasFlag);
47397
+ }
47398
+ }
47399
+ return flags;
47400
+ }
47401
+ function coerceScalar(field3, raw) {
47402
+ switch (field3.type) {
47403
+ case "integer": {
47404
+ const value = Number(raw);
47405
+ if (!Number.isSafeInteger(value)) {
47406
+ throw new UsageError(`--${field3.flag} must be an integer.`);
47393
47407
  }
47394
- const defaultTier = field(record2, "default_tier");
47395
- const lines = tiers.map((entry) => {
47396
- const r = asRecord(entry);
47397
- const tier = field(r, "tier");
47398
- const recommended = r.recommended === true || tier === defaultTier ? " recommended" : "";
47399
- const bestFor = asArray(r.best_for).map(String).join(", ");
47400
- return [
47401
- `- \`${tier}\` [${field(r, "provider")}/${field(r, "model")} \xB7 effort ${field(r, "effort")} \xB7 cost ${field(r, "cost_band")}${recommended}]`,
47402
- ` ${field(r, "description")}`,
47403
- ` Best for: ${bestFor}`,
47404
- ` Price: $${field(r, "input_usd_per_million_tokens")}/1M input \xB7 $${field(r, "output_usd_per_million_tokens")}/1M output`,
47405
- ` Cost: ${field(r, "cost_note")}`,
47406
- ` Avoid for: ${field(r, "avoid_for")}`
47407
- ].join("\n");
47408
- });
47409
- return `${header}
47410
- ${lines.join("\n")}`;
47411
- });
47408
+ return value;
47409
+ }
47410
+ case "number": {
47411
+ const value = Number(raw);
47412
+ if (!Number.isFinite(value)) {
47413
+ throw new UsageError(`--${field3.flag} must be a finite number.`);
47414
+ }
47415
+ return value;
47416
+ }
47417
+ case "array":
47418
+ return raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
47419
+ default:
47420
+ return raw;
47412
47421
  }
47413
- }, modelUsage(context.binName));
47414
- function modelUsage(bin) {
47415
- return `Usage: ${bin} model list [--json]
47416
- ${bin} model list \u2014 guided model tiers with recommendations, token prices, cost bands, and model ids for --model.`;
47417
47422
  }
47418
- var errorWrapper = (context, args) => dispatch(context, "error", args, {
47419
- list: (ctx, rest) => {
47420
- const parsed = parseFlags(rest);
47421
- const body = withOptional({}, {
47422
- seat_id: optionalValue(parsed, "seat-id"),
47423
- source: optionalValue(parsed, "source"),
47424
- severity: optionalValue(parsed, "severity"),
47425
- resolved: optionalValue(parsed, "resolved"),
47426
- limit: optionalNumber(parsed, "limit")
47427
- });
47428
- return execute(ctx, parsed, "error_log.list", body, (output) => {
47429
- const record2 = asRecord(output);
47430
- const errors = asArray(record2.errors);
47431
- if (errors.length === 0) {
47432
- return "No error logs matching the filter.";
47423
+ function rawValueForField(entry, field3, parsed, aliasFlags) {
47424
+ const canonical = parsed.values.get(field3.flag);
47425
+ if (canonical !== void 0) {
47426
+ return canonical;
47427
+ }
47428
+ for (const [aliasFlag, targetField] of aliasFlags) {
47429
+ if (targetField === field3.name) {
47430
+ const value = parsed.values.get(aliasFlag);
47431
+ if (value !== void 0) {
47432
+ return value;
47433
47433
  }
47434
- return errors.map((entry) => {
47435
- const r = asRecord(entry);
47436
- const disposition = field(r, "disposition");
47437
- const marker = disposition === "active" ? "*" : " ";
47438
- const severityLabel = field(r, "severity").charAt(0).toUpperCase();
47439
- return `${marker} ${field(r, "error_log_id")} [${severityLabel}] ${field(r, "source")} ${disposition} ${field(r, "code")} ${field(r, "message")} ${field(r, "created_at")}`;
47440
- }).join("\n") + (field(record2, "total") !== "" ? `
47441
- Total: ${field(record2, "total")}` : "");
47442
- });
47443
- },
47444
- resolve: (ctx, rest) => {
47445
- const parsed = parseFlags(rest);
47446
- const errorLogId = requireValue2(parsed, "error-log-id");
47447
- const reason = requireValue2(parsed, "reason");
47448
- const body = withOptional({
47449
- error_log_id: errorLogId,
47450
- reason
47451
- }, {
47452
- disposition: optionalValue(parsed, "disposition"),
47453
- linked_task_id: optionalValue(parsed, "linked-task-id"),
47454
- linked_issue_id: optionalValue(parsed, "linked-issue-id"),
47455
- linked_pr_ref: optionalValue(parsed, "linked-pr-ref")
47456
- });
47457
- return execute(ctx, parsed, "error_log.resolve", body, (output) => {
47458
- const record2 = asRecord(output);
47459
- return `Resolved error ${field(record2, "error_log_id")} as ${field(record2, "disposition")} at ${field(record2, "resolved_at")}.`;
47460
- });
47461
- },
47462
- supersede: (ctx, rest) => {
47463
- const parsed = parseFlags(rest);
47464
- const body = withOptional({
47465
- error_log_id: requireValue2(parsed, "error-log-id"),
47466
- new_error_log_id: requireValue2(parsed, "new-error-log-id"),
47467
- reason: requireValue2(parsed, "reason")
47468
- }, {
47469
- linked_task_id: optionalValue(parsed, "linked-task-id"),
47470
- linked_issue_id: optionalValue(parsed, "linked-issue-id"),
47471
- linked_pr_ref: optionalValue(parsed, "linked-pr-ref")
47472
- });
47473
- return execute(ctx, parsed, "error_log.supersede", body, (output) => {
47474
- const record2 = asRecord(output);
47475
- return `Superseded error ${field(record2, "error_log_id")} \u2192 ${field(record2, "superseded_by_id")} at ${field(record2, "resolved_at")}.`;
47476
- });
47434
+ }
47477
47435
  }
47478
- }, errorUsage(context.binName));
47479
- function errorUsage(bin) {
47480
- return `Usage: ${bin} error list|resolve|supersede [--json]
47481
- ${bin} error list [--seat-id <id>] [--source run|llm|tool|mcp|runner|integration|job|web] [--severity warning|error|critical] [--resolved active|acknowledged|resolved|all] [--limit <n>]
47482
- ${bin} error resolve --error-log-id <id> --reason <text> [--disposition acknowledged|resolved] [--linked-task-id <id>] [--linked-issue-id <id>] [--linked-pr-ref <url>]
47483
- ${bin} error supersede --error-log-id <id> --new-error-log-id <id> --reason <text> [--linked-task-id <id>] [--linked-issue-id <id>] [--linked-pr-ref <url>]`;
47484
- }
47485
- var compassWrapper = (context, args) => dispatch(context, "compass", args, {
47486
- show: (ctx, rest) => {
47487
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["markdown"]));
47488
- return execute(ctx, parsed, "compass.show_markdown", {}, markdownLine);
47489
- }
47490
- }, compassUsage(context.binName));
47491
- function compassUsage(bin) {
47492
- return `Usage: ${bin} compass show [--markdown] [--json]
47493
- ${bin} compass show --markdown \u2014 render the current Compass and its open gaps as a markdown card.`;
47494
- }
47495
- var charterWrapper = (context, args) => dispatch(context, "charter", args, {
47496
- show: (ctx, rest) => {
47497
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["markdown"]));
47498
- const seatId = requireValue2(parsed, "seat-id");
47499
- return execute(ctx, parsed, "charter.show_markdown", { seat_id: seatId }, markdownLine);
47500
- }
47501
- }, charterUsage(context.binName));
47502
- function charterUsage(bin) {
47503
- return `Usage: ${bin} charter show --seat-id <id> [--markdown] [--json]
47504
- ${bin} charter show --seat-id <id> --markdown \u2014 render a seat's active or latest Charter as a markdown card.`;
47505
- }
47506
- function formatDeliverableList(output) {
47507
- const deliverables = asArray(asRecord(output).deliverables);
47508
- if (deliverables.length === 0) {
47509
- return "No deliverables for this seat.";
47436
+ return void 0;
47437
+ }
47438
+ function buildBodyFromFlags(entry, parsed, positional, overrides = {}) {
47439
+ if (entry.secretBlocked) {
47440
+ throw new UsageError(SECRET_ARGV_GUIDANCE);
47510
47441
  }
47511
- return deliverables.map((entry) => {
47512
- const r = asRecord(entry);
47513
- const summary = field(r, "summary") === "\u2014" ? "" : ` \u2014 ${field(r, "summary")}`;
47514
- return `${field(r, "id")} [${field(r, "kind")}] ${field(r, "title")}${summary}`;
47515
- }).join("\n");
47442
+ const inputJson = parsed.values.get("input") ?? parsed.values.get("body");
47443
+ if (inputJson !== void 0) {
47444
+ let parsedInput;
47445
+ try {
47446
+ parsedInput = JSON.parse(inputJson);
47447
+ } catch {
47448
+ throw new UsageError("--input must be valid JSON.");
47449
+ }
47450
+ if (typeof parsedInput !== "object" || parsedInput === null || Array.isArray(parsedInput)) {
47451
+ throw new UsageError("--input must be a JSON object.");
47452
+ }
47453
+ return parsedInput;
47454
+ }
47455
+ const aliasFlags = new Map(Object.entries(overrides.flagAliases ?? {}));
47456
+ const body = {};
47457
+ for (const field3 of entry.fields) {
47458
+ if (field3.type === "boolean") {
47459
+ if (parsed.flags.has(field3.flag)) {
47460
+ body[field3.name] = true;
47461
+ } else {
47462
+ for (const [aliasFlag, targetField] of aliasFlags) {
47463
+ if (targetField === field3.name && parsed.flags.has(aliasFlag)) {
47464
+ body[field3.name] = true;
47465
+ break;
47466
+ }
47467
+ }
47468
+ }
47469
+ continue;
47470
+ }
47471
+ let raw = rawValueForField(entry, field3, parsed, aliasFlags);
47472
+ if (raw === void 0 && positional !== void 0 && overrides.primaryPositional === field3.name) {
47473
+ raw = positional;
47474
+ }
47475
+ if (raw === void 0 || raw.length === 0) {
47476
+ continue;
47477
+ }
47478
+ body[field3.name] = coerceScalar(field3, raw);
47479
+ }
47480
+ for (const [fieldName, value] of Object.entries(overrides.defaults ?? {})) {
47481
+ if (!(fieldName in body)) {
47482
+ body[fieldName] = value;
47483
+ }
47484
+ }
47485
+ const missing = entry.fields.find((field3) => field3.required && !(field3.name in body));
47486
+ if (missing) {
47487
+ throw new UsageError(`Missing required --${missing.flag} value.`);
47488
+ }
47489
+ return body;
47516
47490
  }
47517
- function formatDeliverableDetail(output) {
47518
- const d = asRecord(asRecord(output).deliverable);
47519
- const links = asArray(d.links).map((entry) => {
47520
- const l = asRecord(entry);
47521
- return ` ${field(l, "kind")}: ${field(l, "label")} <${field(l, "url")}>`;
47522
- }).join("\n");
47523
- return [
47524
- `# ${field(d, "title")} [${field(d, "kind")}]`,
47525
- field(d, "id"),
47526
- field(d, "summary") === "\u2014" ? "" : field(d, "summary"),
47527
- field(d, "content") === "\u2014" ? "" : `content:
47528
- ${field(d, "content")}`,
47529
- `delivered: ${field(d, "delivered_at")}`,
47530
- `run: ${field(d, "source_run_status")} ${field(d, "source_run_model")}`,
47531
- `task: ${field(d, "source_task_title")}`,
47532
- links.length > 0 ? `links:
47533
- ${links}` : ""
47534
- ].filter((line) => line.length > 0).join("\n");
47491
+
47492
+ // src/generator/verbs.ts
47493
+ var MANIFEST_BY_ID = new Map(COMMAND_MANIFEST.map((entry) => [entry.id, entry]));
47494
+ function renderVerbSchema(entry) {
47495
+ const lines = [
47496
+ `${entry.id} \u2014 ${entry.title}`,
47497
+ entry.description,
47498
+ `scope: ${entry.requiredScope} confirmation: ${entry.confirmation} mcp: ${entry.exposeOverMcp}`
47499
+ ];
47500
+ if (entry.help) {
47501
+ lines.push(`help: ${entry.help}`);
47502
+ }
47503
+ lines.push("", "input:");
47504
+ if (entry.fields.length === 0 && !entry.hasComplexInput) {
47505
+ lines.push(" no input fields");
47506
+ } else {
47507
+ for (const field3 of entry.fields) {
47508
+ const req = field3.required ? "required" : "optional";
47509
+ const en = field3.type === "enum" && field3.enumValues ? ` enum=${field3.enumValues.join("|")}` : "";
47510
+ const desc = field3.description ? ` \u2014 ${field3.description}` : "";
47511
+ lines.push(` --${field3.flag} (${req}): ${field3.type}${en}${desc}`);
47512
+ }
47513
+ if (entry.hasComplexInput) {
47514
+ lines.push(" --input '<json>' \u2014 nested payload (this command has complex input fields)");
47515
+ }
47516
+ }
47517
+ if (entry.example !== void 0) {
47518
+ lines.push("", "example input:", JSON.stringify(entry.example, null, 2));
47519
+ }
47520
+ return lines.join("\n");
47535
47521
  }
47536
- function formatDeliverableWrite(output) {
47537
- const record2 = asRecord(output);
47538
- return `deliverable ${field(record2, "deliverable_id")} recorded.`;
47522
+ function verbUsageLine(bin, group, verb, entry) {
47523
+ const parts = entry.fields.map((field3) => {
47524
+ const token = field3.type === "boolean" ? `--${field3.flag}` : `--${field3.flag} <${field3.type === "enum" && field3.enumValues ? field3.enumValues.join("|") : field3.name}>`;
47525
+ return field3.required ? token : `[${token}]`;
47526
+ });
47527
+ const complex = entry.hasComplexInput ? " [--input '<json>']" : "";
47528
+ return ` ${bin} ${group} ${verb} ${parts.join(" ")}${complex}`.replace(/\s+$/, "");
47539
47529
  }
47540
- var deliverableWrapper = (context, args) => dispatch(context, "deliverable", args, {
47541
- list: (ctx, rest) => {
47542
- const parsed = parseFlags(rest);
47543
- const seatId = requireValue2(parsed, "seat-id");
47544
- return execute(ctx, parsed, "deliverable.list", { seat_id: seatId }, formatDeliverableList);
47545
- },
47546
- get: (ctx, rest) => {
47547
- const parsed = parseFlags(rest);
47548
- const body = {
47549
- seat_id: requireValue2(parsed, "seat-id"),
47550
- deliverable_id: requireValue2(parsed, "deliverable-id")
47530
+ function groupUsage(bin, group, spec) {
47531
+ const verbs = Object.keys(spec.verbs);
47532
+ const header = spec.summary ?? `Usage: ${bin} ${group} ${verbs.join("|")} [--seat <id>] [--json]`;
47533
+ const lines = [header];
47534
+ for (const [verb, verbSpec] of Object.entries(spec.verbs)) {
47535
+ const entry = MANIFEST_BY_ID.get(verbSpec.commandId);
47536
+ if (verbSpec.usage) {
47537
+ lines.push(` ${verbSpec.usage}`);
47538
+ } else if (entry) {
47539
+ lines.push(verbUsageLine(bin, group, verb, entry));
47540
+ }
47541
+ }
47542
+ return lines.join("\n");
47543
+ }
47544
+ function makeVerb(commandId, verbSpec) {
47545
+ if (verbSpec.handler) {
47546
+ return verbSpec.handler;
47547
+ }
47548
+ return (context, rest) => {
47549
+ const entry = MANIFEST_BY_ID.get(commandId);
47550
+ if (!entry) {
47551
+ throw new UsageError(`Unknown command ${commandId}.`);
47552
+ }
47553
+ if (entry.secretBlocked) {
47554
+ context.io.stderr.write(`${SECRET_ARGV_GUIDANCE}
47555
+ `);
47556
+ return Promise.resolve(1);
47557
+ }
47558
+ if (rest.includes("--schema")) {
47559
+ context.io.stdout.write(`${renderVerbSchema(entry)}
47560
+ `);
47561
+ return Promise.resolve(0);
47562
+ }
47563
+ const overrides = {
47564
+ ...verbSpec.flagAliases ? { flagAliases: verbSpec.flagAliases } : {},
47565
+ ...verbSpec.defaults ? { defaults: verbSpec.defaults } : {},
47566
+ ...verbSpec.primaryPositional ? { primaryPositional: verbSpec.primaryPositional } : {}
47551
47567
  };
47552
- return execute(ctx, parsed, "deliverable.get", body, formatDeliverableDetail);
47553
- },
47554
- create: (ctx, rest) => {
47555
- const parsed = parseFlags(rest, /* @__PURE__ */ new Set(["json"]));
47556
- const body = withOptional({
47557
- kind: optionalValue(parsed, "kind") ?? "other",
47558
- title: requireValue2(parsed, "title")
47559
- }, {
47560
- summary: optionalValue(parsed, "summary"),
47561
- content: optionalValue(parsed, "content"),
47562
- delivered_at: optionalValue(parsed, "delivered-at")
47563
- });
47564
- return execute(ctx, parsed, "deliverable.create", body, formatDeliverableWrite);
47565
- },
47566
- attach: (ctx, rest) => {
47567
- const parsed = parseFlags(rest);
47568
- const body = withOptional({
47569
- kind: optionalValue(parsed, "kind") ?? "other",
47570
- title: requireValue2(parsed, "title")
47571
- }, {
47572
- run_id: optionalValue(parsed, "run-id"),
47573
- task_id: optionalValue(parsed, "task-id"),
47574
- work_order_id: optionalValue(parsed, "work-order-id"),
47575
- summary: optionalValue(parsed, "summary"),
47576
- content: optionalValue(parsed, "content")
47577
- });
47578
- return execute(ctx, parsed, "deliverable.attach", body, formatDeliverableWrite);
47568
+ const hasPositional = verbSpec.primaryPositional !== void 0 && rest[0] !== void 0 && !rest[0].startsWith("--");
47569
+ const positional = hasPositional ? rest[0] : void 0;
47570
+ const flagArgs = hasPositional ? rest.slice(1) : rest;
47571
+ const parsed = parseFlags(flagArgs, booleanFlagsFor(entry, overrides));
47572
+ const body = buildBodyFromFlags(entry, parsed, positional, overrides);
47573
+ const render = verbSpec.render ?? renderCommandOutput;
47574
+ return execute(context, parsed, commandId, body, render);
47575
+ };
47576
+ }
47577
+ function makeGroupWrapper(group, spec) {
47578
+ const actions = {};
47579
+ for (const [verb, verbSpec] of Object.entries(spec.verbs)) {
47580
+ actions[verb] = makeVerb(verbSpec.commandId, verbSpec);
47579
47581
  }
47580
- }, deliverableUsage(context.binName));
47581
- function deliverableUsage(bin) {
47582
- return `Usage: ${bin} deliverable list|get|create|attach [--json]
47583
- ${bin} deliverable list --seat-id <id>
47584
- ${bin} deliverable get --seat-id <id> --deliverable-id <id>
47585
- ${bin} deliverable create --title <text> [--kind brief|work_evidence|artifact|report|other] [--summary <text>] [--content <text>] [--delivered-at <iso>]
47586
- ${bin} deliverable attach --title <text> [--run-id <id>] [--task-id <id>] [--work-order-id <id>] [--kind brief|work_evidence|artifact|report|other] [--summary <text>] [--content <text>]`;
47582
+ return (context, args) => dispatch(context, group, args, actions, groupUsage(context.binName, group, spec));
47587
47583
  }
47588
- function formatSystemHealth(output) {
47589
- const record2 = asRecord(output);
47590
- const scope = asRecord(record2.scope);
47591
- const sections = asRecord(record2.sections);
47592
- const actions = asArray(record2.top_actions);
47593
- const findings = asArray(record2.findings);
47594
- const lines = [
47595
- `verdict: ${field(record2, "verdict")} scope: ${field(scope, "mode")} seats: ${field(scope, "total_seat_count")} findings: ${findings.length}`
47596
- ];
47597
- if (actions.length > 0) {
47598
- lines.push("top_actions:");
47599
- for (const action of actions) {
47600
- const item = asRecord(action);
47601
- lines.push(` ${field(item, "label")} command=${field(item, "command_id")} schema=${field(item, "schema_ref")} cli=${field(item, "cli")}`);
47602
- if (field(item, "help") !== "\u2014") {
47603
- lines.push(` ${field(item, "help")}`);
47604
- }
47584
+
47585
+ // src/operations.ts
47586
+ var SKIP_NAMESPACES = /* @__PURE__ */ new Set([
47587
+ "user",
47588
+ // whoami / tenants / use
47589
+ "command",
47590
+ // rost command <id>
47591
+ "signup",
47592
+ // rost signup
47593
+ "onboarding",
47594
+ // rost onboard
47595
+ "confirmation",
47596
+ // internal confirm-replay
47597
+ "tenant",
47598
+ // rost tenant create / settings rename (also owns the secret-blocked tenant.anthropic_key.save)
47599
+ "credential"
47600
+ // DER-1046 invariant #5: credential.ingress sinks a raw secret; ingress only via the vault-backed web flow, never CLI argv
47601
+ ]);
47602
+ var NAMESPACE_TO_GROUP = {
47603
+ error_log: "error",
47604
+ tool: "tools",
47605
+ skill: "skills"
47606
+ };
47607
+ var EXTRA_SURFACED = /* @__PURE__ */ new Set([
47608
+ "seat.decommission_preview",
47609
+ // seat decommission --dry-run
47610
+ "agent.create_custom",
47611
+ // agent create --custom
47612
+ "agent_setup.update",
47613
+ // agent setup answer
47614
+ "settings.product_learning.update",
47615
+ // settings product-learning update
47616
+ "settings.agent_policy.update",
47617
+ // settings agent-policy set
47618
+ "skill.import_github"
47619
+ // skills import github
47620
+ ]);
47621
+ function buildMergedSpecs() {
47622
+ const merged = {};
47623
+ for (const [group, spec] of Object.entries(GROUP_SPECS)) {
47624
+ merged[group] = { verbs: { ...spec.verbs }, ...spec.summary ? { summary: spec.summary } : {} };
47625
+ }
47626
+ const surfaced = new Set(EXTRA_SURFACED);
47627
+ for (const spec of Object.values(GROUP_SPECS)) {
47628
+ for (const verb of Object.values(spec.verbs)) {
47629
+ surfaced.add(verb.commandId);
47605
47630
  }
47606
47631
  }
47607
- const fleet = asRecord(sections.fleet);
47608
- const runs = asRecord(sections.runs);
47609
- const signals = asRecord(sections.signals);
47610
- const cascade = asRecord(sections.cascade_setup);
47611
- const workLoop = asRecord(sections.work_loop);
47612
- const connectivity = asRecord(sections.connectivity);
47613
- const sync = asRecord(sections.sync);
47614
- lines.push(
47615
- `fleet: agents=${field(fleet, "agent_count")} live=${field(fleet, "live_count")} stale=${field(fleet, "stale_count")} setup_gaps=${field(fleet, "setup_gap_count")}`,
47616
- `runs: failed_24h=${field(runs, "failed_24h")} failed_7d=${field(runs, "failed_7d")} unresolved_errors=${field(runs, "unresolved_error_count")}`,
47617
- `signals: off_track=${field(signals, "off_track_count")} pending=${field(signals, "pending_count")}`,
47618
- `cascade: recommendations=${field(cascade, "recommendation_count")} warnings=${field(cascade, "warning_count")}`,
47619
- `work_loop: open_issues=${field(workLoop, "open_issue_count")} friction_without_task=${field(workLoop, "friction_without_task_count")} open_or_stalled_tasks=${field(workLoop, "open_or_stalled_task_count")}`,
47620
- `connectivity: runners=${field(connectivity, "runner_count")} offline_runners=${field(connectivity, "offline_runner_count")} not_ready_runners=${field(connectivity, "not_execute_ready_runner_count")} integrations=${field(connectivity, "integration_count")} disconnected_integrations=${field(connectivity, "disconnected_integration_count")} failed_notifications=${field(connectivity, "failed_notification_count")}`,
47621
- `sync: latest_brief=${field(sync, "latest_brief_at")} missing_latest_brief=${field(sync, "missing_latest_brief")} flagged_gaps=${field(sync, "flagged_gap_count")}`
47622
- );
47623
- return lines.join("\n");
47632
+ for (const entry of COMMAND_MANIFEST) {
47633
+ if (entry.secretBlocked || surfaced.has(entry.id) || SKIP_NAMESPACES.has(entry.namespace)) {
47634
+ continue;
47635
+ }
47636
+ const group = NAMESPACE_TO_GROUP[entry.namespace] ?? entry.namespace;
47637
+ const verb = entry.action.replace(/[_.]/g, "-");
47638
+ const spec = merged[group] ?? (merged[group] = { verbs: {} });
47639
+ if (!(verb in spec.verbs)) {
47640
+ const verbSpec = { commandId: entry.id };
47641
+ spec.verbs[verb] = verbSpec;
47642
+ }
47643
+ }
47644
+ return merged;
47624
47645
  }
47625
- var systemWrapper = (context, args) => dispatch(context, "system", args, {
47626
- health: (ctx, rest) => {
47627
- const parsed = parseFlags(rest);
47628
- const body = withOptional({}, { seat_id: parsed.seat });
47629
- return execute(ctx, parsed, "system.health", body, formatSystemHealth);
47630
- }
47631
- }, systemUsage(context.binName));
47632
- function systemUsage(bin) {
47633
- return `Usage: ${bin} system health [--seat <id>] [--json]
47634
- ${bin} system health [--seat <id>]`;
47635
- }
47636
- var OPERATION_GROUPS = [
47637
- "task",
47638
- "status",
47639
- "signal",
47640
- "goal",
47641
- "friction",
47642
- "escalation",
47643
- "error",
47644
- "sync",
47645
- "runner",
47646
- "notification",
47647
- "integration",
47648
- "settings",
47649
- "member",
47650
- "agent",
47651
- "tools",
47652
- "skills",
47653
- "model",
47654
- "compass",
47655
- "charter",
47656
- "deliverable",
47657
- "system",
47658
- "graph",
47659
- "seat"
47660
- ];
47661
- var wrappers = {
47662
- task: taskWrapper,
47663
- status: statusWrapper,
47664
- signal: signalWrapper,
47665
- goal: goalWrapper,
47666
- friction: frictionWrapper,
47667
- escalation: escalationWrapper,
47668
- error: errorWrapper,
47669
- sync: syncWrapper,
47670
- runner: runnerWrapper,
47671
- notification: notificationWrapper,
47672
- integration: integrationWrapper,
47673
- settings: settingsWrapper,
47674
- member: memberWrapper,
47675
- agent: agentWrapper,
47676
- tools: toolsWrapper,
47677
- skills: skillsWrapper,
47678
- model: modelWrapper,
47679
- compass: compassWrapper,
47680
- charter: charterWrapper,
47681
- deliverable: deliverableWrapper,
47682
- system: systemWrapper,
47683
- graph: graphWrapper,
47684
- seat: seatWrapper
47685
- };
47646
+ var MERGED_SPECS = buildMergedSpecs();
47647
+ var WRAPPERS = {};
47648
+ for (const [group, spec] of Object.entries(MERGED_SPECS)) {
47649
+ WRAPPERS[group] = makeGroupWrapper(group, spec);
47650
+ }
47651
+ var OPERATION_GROUPS = Object.keys(MERGED_SPECS).sort();
47686
47652
  function isOperationGroup(value) {
47687
- return value !== void 0 && OPERATION_GROUPS.includes(value);
47688
- }
47689
- var groupUsageBuilders = {
47690
- task: taskUsage,
47691
- status: statusUsage,
47692
- signal: signalUsage,
47693
- goal: goalUsage,
47694
- friction: frictionUsage,
47695
- escalation: escalationUsage,
47696
- error: errorUsage,
47697
- sync: syncUsage,
47698
- runner: runnerUsage,
47699
- notification: notificationUsage,
47700
- integration: integrationUsage,
47701
- settings: settingsUsage,
47702
- member: memberUsage,
47703
- agent: agentUsage,
47704
- tools: toolsUsage,
47705
- skills: skillsUsage,
47706
- model: modelUsage,
47707
- compass: compassUsage,
47708
- charter: charterUsage,
47709
- deliverable: deliverableUsage,
47710
- system: systemUsage,
47711
- graph: graphUsage,
47712
- seat: seatUsage
47713
- };
47653
+ return value !== void 0 && Object.prototype.hasOwnProperty.call(WRAPPERS, value);
47654
+ }
47655
+ var SECRET_BLOCKED_COMMAND_IDS = new Set(
47656
+ COMMAND_MANIFEST.filter((entry) => entry.secretBlocked === true).map((entry) => entry.id)
47657
+ );
47658
+ function isSecretBlockedCommand(commandId) {
47659
+ return commandId !== void 0 && SECRET_BLOCKED_COMMAND_IDS.has(commandId);
47660
+ }
47661
+ var SECRET_BLOCKED_NAMESPACES = (() => {
47662
+ const totals = /* @__PURE__ */ new Map();
47663
+ for (const entry of COMMAND_MANIFEST) {
47664
+ const record2 = totals.get(entry.namespace) ?? { total: 0, blocked: 0 };
47665
+ record2.total += 1;
47666
+ if (entry.secretBlocked === true) {
47667
+ record2.blocked += 1;
47668
+ }
47669
+ totals.set(entry.namespace, record2);
47670
+ }
47671
+ const result = /* @__PURE__ */ new Set();
47672
+ for (const [namespace, { total, blocked }] of totals) {
47673
+ if (blocked > 0 && blocked === total) {
47674
+ result.add(namespace);
47675
+ }
47676
+ }
47677
+ return result;
47678
+ })();
47679
+ function isSecretBlockedNamespace(namespace) {
47680
+ return namespace !== void 0 && SECRET_BLOCKED_NAMESPACES.has(namespace);
47681
+ }
47714
47682
  function operationGroupUsage(group, bin) {
47715
- return usageWithSchemaFooter(groupUsageBuilders[group](bin), bin);
47683
+ const spec = MERGED_SPECS[group];
47684
+ if (!spec) {
47685
+ return `Unknown group ${group}.`;
47686
+ }
47687
+ return usageWithSchemaFooter(groupUsage(bin, group, spec), bin);
47716
47688
  }
47717
47689
  async function runOperation(group, args, context) {
47718
- return wrappers[group]({
47719
- io: context.io,
47720
- client: context.client,
47721
- binName: context.binName,
47722
- run: context.run
47723
- }, args);
47690
+ const wrapper = WRAPPERS[group];
47691
+ if (!wrapper) {
47692
+ context.io.stderr.write(`Unknown group ${group}.
47693
+ `);
47694
+ return 1;
47695
+ }
47696
+ return wrapper(
47697
+ { io: context.io, client: context.client, binName: context.binName, run: context.run },
47698
+ args
47699
+ );
47724
47700
  }
47725
47701
  function operationUsageLines(bin) {
47726
47702
  return [
@@ -47777,6 +47753,13 @@ var signupProvisionOutputSchema = external_exports.object({
47777
47753
  name: external_exports.string().min(1),
47778
47754
  created: external_exports.boolean()
47779
47755
  }).loose();
47756
+ var tenantCreateOutputSchema = signupProvisionOutputSchema.extend({
47757
+ source_tenant_id: external_exports.string().min(1),
47758
+ entitlement_id: external_exports.string().min(1),
47759
+ accounting_event_id: external_exports.string().min(1),
47760
+ active: external_exports.boolean(),
47761
+ next_action: external_exports.string().min(1)
47762
+ }).loose();
47780
47763
  async function runSignupProvision(io, client, companyName, run2, options = {}) {
47781
47764
  const exitCode = await run2(io, client, "signup.provision_tenant", { company_name: companyName });
47782
47765
  if (exitCode.exitCode === 0) {
@@ -47803,6 +47786,40 @@ async function runSignupProvision(io, client, companyName, run2, options = {}) {
47803
47786
  }
47804
47787
  return exitCode.exitCode;
47805
47788
  }
47789
+ async function runTenantCreate(io, client, args, run2) {
47790
+ const [action, ...rest] = args;
47791
+ if (action !== "create") {
47792
+ io.stderr.write(`Usage: ${cliBrand.binName} tenant create --company "<name>" [--json]
47793
+ `);
47794
+ return 1;
47795
+ }
47796
+ const json2 = rest.includes("--json");
47797
+ const companyIndex = rest.indexOf("--company");
47798
+ const companyName = companyIndex === -1 ? void 0 : rest[companyIndex + 1];
47799
+ if (!companyName || companyName.startsWith("--") || companyName.trim() === "") {
47800
+ io.stderr.write(`--company requires a value, e.g. ${cliBrand.binName} tenant create --company "Acme Ops"
47801
+ `);
47802
+ return 1;
47803
+ }
47804
+ const exitCode = await run2(io, client, "tenant.create", { company_name: companyName });
47805
+ if (exitCode.exitCode === 0) {
47806
+ const parsed = tenantCreateOutputSchema.safeParse(exitCode.output);
47807
+ if (!parsed.success) {
47808
+ io.stderr.write("tenant.create returned an unexpected response shape.\n");
47809
+ return 1;
47810
+ }
47811
+ if (json2) {
47812
+ io.stdout.write(`${JSON.stringify(parsed.data, null, 2)}
47813
+ `);
47814
+ return exitCode.exitCode;
47815
+ }
47816
+ io.stdout.write(
47817
+ `Company '${parsed.data.name}' is ready and active (${parsed.data.slug}). ${parsed.data.next_action}
47818
+ `
47819
+ );
47820
+ }
47821
+ return exitCode.exitCode;
47822
+ }
47806
47823
  async function runSignup(io, appUrl2, openBrowser2 = tryOpenBrowser) {
47807
47824
  const url2 = signupUrl(appUrl2);
47808
47825
  await openBrowser2(url2);
@@ -47844,7 +47861,7 @@ import path2 from "node:path";
47844
47861
  var UsageError2 = class extends Error {
47845
47862
  };
47846
47863
  var CLIENTS = /* @__PURE__ */ new Set(["claude-code", "codex", "cursor"]);
47847
- function skillsUsage2(binName = cliBrand.binName) {
47864
+ function skillsUsage(binName = cliBrand.binName) {
47848
47865
  return [
47849
47866
  `${binName} skills list [--json]`,
47850
47867
  `${binName} skills catalog [--json]`,
@@ -47862,7 +47879,7 @@ async function runSkills(context, args, env = process.env) {
47862
47879
  try {
47863
47880
  const [action, ...rest] = args;
47864
47881
  if (action === "help" || action === "--help" || action === "-h" || action === void 0) {
47865
- context.io.stdout.write(`${skillsUsage2(context.binName)}
47882
+ context.io.stdout.write(`${skillsUsage(context.binName)}
47866
47883
  `);
47867
47884
  return action === void 0 ? 1 : 0;
47868
47885
  }
@@ -47877,7 +47894,7 @@ async function runSkills(context, args, env = process.env) {
47877
47894
  }
47878
47895
  if (action === "get") {
47879
47896
  const parsed = parseFlags2(rest);
47880
- return context.run(context.client, "skill.get", { slug: requireValue3(parsed, "slug") }, parsed.json ? void 0 : formatSkillDetail2);
47897
+ return context.run(context.client, "skill.get", { slug: requireValue3(parsed, "slug") }, parsed.json ? void 0 : formatSkillDetail);
47881
47898
  }
47882
47899
  if (action === "file") {
47883
47900
  const parsed = parseFlags2(rest);
@@ -47914,7 +47931,7 @@ async function runSkills(context, args, env = process.env) {
47914
47931
  slug: optionalValue2(parsed, "skill") ?? optionalValue2(parsed, "slug"),
47915
47932
  skill_version_id: optionalValue2(parsed, "skill-version-id")
47916
47933
  });
47917
- return context.run(context.client, "skill.assign_to_seat", body, parsed.json ? void 0 : formatAssignment2, { targetSeatId: body.seat_id });
47934
+ return context.run(context.client, "skill.assign_to_seat", body, parsed.json ? void 0 : formatAssignment, { targetSeatId: body.seat_id });
47918
47935
  }
47919
47936
  if (action === "revoke") {
47920
47937
  const parsed = parseFlags2(rest);
@@ -48200,7 +48217,7 @@ function formatCatalog(output) {
48200
48217
  return `${record2.catalog_slug} [${record2.tier}/${record2.entitlement_status}] ${record2.name}`;
48201
48218
  }).join("\n");
48202
48219
  }
48203
- function formatSkillDetail2(output) {
48220
+ function formatSkillDetail(output) {
48204
48221
  const skill = asRecord2(asRecord2(output).skill);
48205
48222
  return `${skill.slug} v${skill.latest_version ?? "\u2014"} [${skill.status}] ${skill.name}
48206
48223
  ${skill.description}`;
@@ -48210,7 +48227,7 @@ function formatEnable(output) {
48210
48227
  const catalog = asRecord2(asRecord2(output).catalog);
48211
48228
  return `Enabled ${catalog.catalog_slug} as ${skill.slug} v${skill.version} (${skill.skill_version_id})`;
48212
48229
  }
48213
- function formatAssignment2(output) {
48230
+ function formatAssignment(output) {
48214
48231
  const assignment = asRecord2(asRecord2(output).assignment);
48215
48232
  return `${assignment.status} ${assignment.slug} for seat ${assignment.seat_id}; sync: ${String(asRecord2(output).local_sync_next_step)}`;
48216
48233
  }
@@ -48696,6 +48713,11 @@ async function main(argv = process.argv.slice(2), options = {}) {
48696
48713
  const refreshSession = options.refreshSession ?? refreshCliSessionIfNeeded;
48697
48714
  const [rawCommand, ...args] = argv;
48698
48715
  const command = rawCommand === "--help" || rawCommand === "-h" ? "help" : rawCommand;
48716
+ if (isSecretBlockedNamespace(command)) {
48717
+ io.stderr.write(`${SECRET_ARGV_GUIDANCE}
48718
+ `);
48719
+ return 1;
48720
+ }
48699
48721
  if (!isCommand(command) && !isOperationGroup(command)) {
48700
48722
  printUsage(io);
48701
48723
  return command ? 1 : 0;
@@ -48860,6 +48882,9 @@ Run ${cliBrand.binName} login --device again if the next command asks you to aut
48860
48882
  if (command === "signup") {
48861
48883
  return runSignupProvision(io, client, signupCompany, (signupIo, signupClient, commandId, body) => executeCommandWithResult(signupIo, signupClient, commandId, body), { json: signupJson });
48862
48884
  }
48885
+ if (command === "tenant") {
48886
+ return runTenantCreate(io, client, args, (tenantIo, tenantClient, commandId, body) => executeCommandWithResult(tenantIo, tenantClient, commandId, body));
48887
+ }
48863
48888
  if (command === "whoami") {
48864
48889
  return printCommandOutput(io, client, "user.whoami");
48865
48890
  }
@@ -48942,6 +48967,11 @@ async function executeDirectCommand(io, client, args) {
48942
48967
  );
48943
48968
  }
48944
48969
  const commandId = first;
48970
+ if (isSecretBlockedCommand(commandId)) {
48971
+ io.stderr.write(`${SECRET_ARGV_GUIDANCE}
48972
+ `);
48973
+ return 1;
48974
+ }
48945
48975
  let seat;
48946
48976
  let autoConfirm = false;
48947
48977
  let rest;
@@ -49256,7 +49286,7 @@ function parseJsonBody(args) {
49256
49286
  return JSON.parse(body);
49257
49287
  }
49258
49288
  function isCommand(value) {
49259
- return value === "login" || value === "logout" || value === "signup" || value === "whoami" || value === "tenants" || value === "use" || value === "command" || value === "onboard" || value === "mcp" || value === "skills" || value === "init" || value === "docs" || value === "reference" || value === "doctor" || value === "help";
49289
+ return value === "login" || value === "logout" || value === "signup" || value === "tenant" || value === "whoami" || value === "tenants" || value === "use" || value === "command" || value === "onboard" || value === "mcp" || value === "skills" || value === "init" || value === "docs" || value === "reference" || value === "doctor" || value === "help";
49260
49290
  }
49261
49291
  function printUsage(io) {
49262
49292
  io.stdout.write([
@@ -49264,6 +49294,7 @@ function printUsage(io) {
49264
49294
  `${cliBrand.binName} login --device`,
49265
49295
  `${cliBrand.binName} logout`,
49266
49296
  `${cliBrand.binName} signup [--company "<name>"]`,
49297
+ `${cliBrand.binName} tenant create --company "<name>" [--json]`,
49267
49298
  `${cliBrand.binName} whoami`,
49268
49299
  `${cliBrand.binName} tenants`,
49269
49300
  `${cliBrand.binName} use <tenant>`,
@@ -49277,7 +49308,7 @@ function printUsage(io) {
49277
49308
  `${cliBrand.binName} mcp install --client claude-code|codex|cursor --scope tenant-admin|seat [--seat-id <id>] [--expires-in <days>|--no-expiry] [--skip-permissions]`,
49278
49309
  `${cliBrand.binName} mcp install --client claude-code|codex|cursor --rotate <old-token-id> (inherits the old token's scope; no --scope)`,
49279
49310
  `${cliBrand.binName} mcp install ... --skip-permissions (or ${cliBrand.envPrefix}_CLI_SKIP_PERMISSIONS=1 \u2014 auto-approves the token-mint confirmation in a non-interactive session)`,
49280
- skillsUsage2(cliBrand.binName),
49311
+ skillsUsage(cliBrand.binName),
49281
49312
  `${cliBrand.binName} init [--client claude-code|codex|cursor] (defaults --scope tenant-admin)`,
49282
49313
  `${cliBrand.binName} docs`,
49283
49314
  `${cliBrand.binName} reference <list|search|get> [options]`,