Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/dashboard/smoke/frontstage-route-smoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ includes(dataSource, 'schema_version: "goal_channel_projection_v0"', "goal chann
includes(dataSource, "goalChannelProjectionSchema", "goal channel zod schema");
includes(dataSource, 'mode: "read_only"', "read-only mode");
includes(dataSource, 'claimed_by: "codex-side-bypass"', "side-agent claim fixture");
includes(dataSource, 'scheduler_rrule: "FREQ=MINUTELY;INTERVAL=3"', "scheduler cadence fixture");
includes(dataSource, 'pause_policy: "control-plane policy only"', "pause policy fixture");
includes(dataSource, "raw_or_private_material_omitted", "source warning fixture");
includes(statusSource, "goal_channel_projection: goalChannelProjectionSchema", "status projection parser");
includes(statusSource, "local_dashboard_api", "local dashboard API status parser");
Expand Down Expand Up @@ -94,6 +96,10 @@ includes(frontstageSource, "read-only default", "read-only default copy");
includes(frontstageSource, "Write affordances require explicit loopback opt-in", "loopback opt-in copy");
includes(frontstageSource, "TanStack Query", "TanStack Query copy");
includes(frontstageSource, 'data-testid="frontstage-operations-strip"', "operations signal strip");
includes(frontstageSource, 'data-testid="frontstage-budget-governance"', "budget governance panel");
includes(frontstageSource, "Budget & Governance", "budget governance panel title");
includes(frontstageSource, "Cadence changes, final checks, and monitor-only polls are no-spend.", "no-spend governance copy");
includes(frontstageSource, "Audit through todo ids, run history, and quota spend events.", "budget evidence audit copy");
includes(frontstageSource, 'data-testid="frontstage-goal-select"', "goal selector");
includes(frontstageSource, "resolveFrontstageOpsStatusUrl", "ops status URL resolver");
includes(frontstageSource, "statusContractFreshnessIssue", "schema freshness gate");
Expand Down
7 changes: 7 additions & 0 deletions apps/dashboard/src/data/goal-channel-frontstage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,14 @@ export const sampleGoalChannelProjection: GoalChannelProjection = {
},
quota: {
allowed_slots: "10",
cadence_class: "active_work",
latest_evidence_ref: "run:validated_progress_fixture",
no_spend_for_cadence_change: true,
override_policy: "fresh quota guard required",
pause_policy: "control-plane policy only",
reason: "synthetic fixture has quota",
scheduler_reset_token: "fixture-reset-token",
scheduler_rrule: "FREQ=MINUTELY;INTERVAL=3",
spend_policy: "spend after validated writeback",
spent_slots: "2",
state: "eligible",
Expand Down
48 changes: 48 additions & 0 deletions apps/dashboard/src/views/frontstage-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,38 @@ function FrontstageRoute({
: filterTodosByQuery(projection.agent_todos, normalizedTodoQuery);
const visibleTodoCount = filteredUserTodos.length + filteredAgentTodos.length;
const totalTodoCount = projection.user_todos.length + projection.agent_todos.length;
const budgetGovernanceRows = [
{
label: "budget",
value: quotaUsed,
helper: `quota state: ${stringifyScalar(projection.quota.state)}`,
tone: statusTone(stringifyScalar(projection.quota.state)),
},
{
label: "cadence",
value: stringifyScalar(projection.quota.scheduler_rrule ?? projection.quota.cadence_class ?? "scheduler hint"),
helper: `reset token: ${stringifyScalar(projection.quota.scheduler_reset_token ?? "not projected")}`,
tone: "info",
},
{
label: "spend rule",
value: stringifyScalar(projection.quota.spend_policy),
helper: "Cadence changes, final checks, and monitor-only polls are no-spend.",
tone: "success",
},
{
label: "controls",
value: stringifyScalar(projection.quota.override_policy ?? "preview gated"),
helper: stringifyScalar(projection.quota.pause_policy ?? "writes require CLI or loopback opt-in"),
tone: "warning",
},
{
label: "evidence",
value: stringifyScalar(projection.quota.latest_evidence_ref ?? projection.source_refs.latest_run_generated_at ?? "run history"),
helper: "Audit through todo ids, run history, and quota spend events.",
tone: "neutral",
},
] satisfies Array<{ label: string; value: string; helper: string; tone: BadgeTone }>;

return (
<main
Expand Down Expand Up @@ -1880,6 +1912,22 @@ function FrontstageRoute({
</Panel>
</div>

<Panel icon={BarChart3} title="Budget & Governance">
<div className="grid gap-2 p-4 sm:grid-cols-2 xl:grid-cols-5" data-testid="frontstage-budget-governance">
{budgetGovernanceRows.map((row) => (
<div className="min-w-0 rounded-md border border-slate-200 bg-slate-50 px-3 py-3" key={row.label}>
<div className="text-[11px] font-semibold uppercase tracking-normal text-slate-500">{row.label}</div>
<div className="mt-2 break-words text-sm font-semibold leading-6 text-slate-950">
{row.value}
</div>
<div className="mt-2">
<Badge variant={row.tone}>{row.helper}</Badge>
</div>
</div>
))}
</div>
</Panel>

<div className="grid gap-4 lg:grid-cols-2">
<div
className="frontstage-ops-command-strip rounded-lg border border-slate-200 bg-white p-4 shadow-sm lg:col-span-2"
Expand Down
4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ incident report, or launch draft.
for Codex App, Codex CLI TUI, Claude Code loop, shell, HTTP, and worker
bridge connectors.
- [Quota allocation](quota-allocation.md): should-run and spend semantics.
- [Dashboard budget governance](dashboard-budget-governance-contract.md):
operator-facing budget, cadence, controls, and evidence mapping for the ops
frontstage.
- [Status data contract](status-data-contract.md): dashboard/status payload
shape.
- [Public/private boundary](public-private-boundary.md): what may be committed,
Expand Down Expand Up @@ -74,6 +77,7 @@ incident report, or launch draft.
- [Worker bridge install contract](worker-bridge-install-contract.md)
- [Lark Kanban control-plane adapter](lark-kanban-control-plane-adapter.md)
- [Dashboard reward write boundary](dashboard-reward-write-boundary.md)
- [Dashboard budget governance](dashboard-budget-governance-contract.md)
- [Complex project read-only adapter](complex-project-readonly-adapter.md)
- [Protocol contracts](reference/protocols/README.md)

Expand Down
78 changes: 78 additions & 0 deletions docs/dashboard-budget-governance-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Dashboard Budget Governance Contract

Status: public-safe v0 contract for the LoopX ops dashboard.

LoopX budget and governance are already present in the kernel objects: quota,
scheduler hints, todo ownership, gates, run history, and evidence pointers. The
dashboard contract turns those machine fields into operator concepts without
creating a browser-side source of truth.

## Operator Concepts

| Operator concept | Source fields | Meaning in the dashboard |
| --- | --- | --- |
| Budget | `quota.compute`, `quota.allowed_slots`, `quota.spent_slots`, `quota.state` | How much automatic agent time this goal may consume in the current quota window, and whether it can run now. |
| Cadence | `scheduler_hint.codex_app`, `scheduler_hint.local_scheduler`, `scheduler_hint.reset_policy` | How often the host should wake the agent, when backoff applies, and when user feedback or new work resets the interval. |
| Spend rule | `interaction_contract.cli_channel.spend_policy`, `scheduler_hint.*.no_spend_*`, `work_lane_contract` | Which transitions spend quota and which lifecycle checks are no-spend. |
| Human controls | user todos, operator gates, `local_dashboard_api`, future control-plane dry-run/apply paths | What a human can approve, pause, override, or resume, and whether the browser is allowed to preview or apply a change. |
| Evidence | todo ids, run ids, quota spend events, compact artifacts, source warnings | Why the dashboard believes the current budget/governance state and where to audit it. |

The dashboard should phrase these concepts for operators, but drill-down views
may still show the exact machine tokens for debugging.

## Control Semantics

- **Pause automatic work:** projected as a quota/control-plane policy change,
not as a hidden browser flag. Apply paths require local loopback opt-in and a
preview id, or the equivalent CLI command.
- **Run now / override cadence:** starts with a fresh `quota should-run`; it
does not skip gates, claims, write scope, or capability checks.
- **Reset cadence:** follows `scheduler_hint.reset_policy`. User feedback, new
or reassigned todos, gate resolution, and material state transitions reset the
host interval to the profile's initial value before backoff resumes.
- **Stop or final-check loops:** Codex CLI TUI and Claude Code loop final
checks, loop exits, cadence changes, and monitor-only quiet polls are
no-spend transitions unless they produce validated work and writeback.
- **Spend quota:** only after durable writeback: todo/state/evidence update,
`refresh-state`, then one `quota spend-slot` event.

## Dashboard Projection

The ops frontstage may render a compact `Budget & Governance` panel derived
from `goal_channel_projection_v0`:

```json
{
"quota": {
"state": "eligible",
"spent_slots": "2",
"allowed_slots": "10",
"scheduler_rrule": "FREQ=MINUTELY;INTERVAL=3",
"scheduler_reset_token": "fixture-reset-token",
"spend_policy": "spend after validated writeback",
"pause_policy": "control-plane policy only",
"override_policy": "fresh quota guard required",
"latest_evidence_ref": "run:validated_progress_fixture"
}
}
```

The panel is read-only. It may link to todo ids, run events, local dry-run
capabilities, and source warnings, but it must not mutate project truth directly.

## Acceptance Anchors

- `frontstage-budget-governance` renders budget, cadence, spend rule, controls,
and evidence from compact projection fields.
- The copy says cadence/final-check/monitor-only transitions are no-spend.
- Write affordances remain behind `local_dashboard_api` loopback opt-in and
preview-locked APIs.
- Public docs link this contract from the dashboard/status docs index.

## Related Contracts

- [Quota allocation](quota-allocation.md)
- [Status data contract](status-data-contract.md)
- [Long-task cadence policy](long-task-cadence-policy.md)
- [Frontstage dashboard interaction baseline](product/frontstage-dashboard-interaction-baseline.md)
- [Runtime connector catalog](runtime-connector-catalog.md)
2 changes: 2 additions & 0 deletions docs/product/frontstage-dashboard-interaction-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ The route currently exposes these durable anchors:
`frontstage-todo-result-count` for reviewable todo projection slices.
- `frontstage-role-map`, `frontstage-active-claims`, `frontstage-open-gates`,
`frontstage-artifacts`, and `frontstage-timeline` for the operator workspace.
- `frontstage-budget-governance` for the ops budget, cadence, no-spend control,
and evidence-link contract.
- `frontstage-showcase-motion-beam` and `frontstage-state-flow-beam` for
human-gate and state-flow animation checks.
- `frontstage-self-iteration-timeline`, `frontstage-self-iteration-lane`,
Expand Down
Loading