docs: add HUD status control contract (#1821)

This commit is contained in:
Affaan Mustafa
2026-05-12 16:09:18 -04:00
committed by GitHub
parent 4d42917cfb
commit 0598af70a5
7 changed files with 298 additions and 7 deletions

View File

@@ -30,7 +30,7 @@ As of 2026-05-12:
Linear project status updates remain the active tracking surfaces until the
workspace is upgraded or issue capacity is freed.
- `npm run harness:audit -- --format json` reports 70/70 on current `main`.
- `npm run observability:ready` reports 14/14 readiness on current `main`.
- `npm run observability:ready` reports 16/16 readiness on current `main`.
- `docs/architecture/harness-adapter-compliance.md` maps Claude Code, Codex,
OpenCode, Cursor, Gemini, Zed-adjacent, dmux, Orca, Superset, Ghast, and
terminal-only support to install paths, verification commands, and risk
@@ -153,7 +153,7 @@ As of 2026-05-12:
- Keep public PRs and issues below 20, with zero as the preferred release-lane
target.
- Maintain 70/70 harness audit and 14/14 observability readiness after every
- Maintain 70/70 harness audit and 16/16 observability readiness after every
GA-readiness batch.
- Do not publish release or social announcements until the GitHub release,
npm/package state, billing state, and plugin submission surfaces are verified
@@ -187,7 +187,7 @@ is not complete unless the evidence column exists and has been freshly verified.
| Linear roadmap is detailed | Linear project status plus repo mirror | Repo mirror exists; issue creation was retried on 2026-05-12 and remains blocked by the workspace free issue limit | Needs recurring status updates after each merge batch |
| Flow separation and progress tracking | Flow lanes with owner artifacts and update cadence | This roadmap defines lanes below | Active |
| Realtime Linear sync | Project updates while issue limit is blocked; issues later | ECC-Tools #39 implements opt-in Linear API sync for deferred follow-up backlog items | Needs workspace capacity/config rollout |
| Observability for self-use | Local readiness gate, traces, status snapshots, risk ledger | `npm run observability:ready` reports 14/14 | Complete for local gate |
| Observability for self-use | Local readiness gate, traces, status snapshots, HUD/status contract, risk ledger | `npm run observability:ready` reports 16/16 | Complete for local gate |
| Proper release and notifications | Release tag, npm publish state, plugin state, social posts | Publication readiness gate exists | Not complete |
## Execution Lanes And Tracking Contract
@@ -275,7 +275,7 @@ Target: 2026-06-07
Acceptance:
- Observability readiness remains 14/14 and is backed by JSONL traces, status
- Observability readiness remains 16/16 and is backed by JSONL traces, status
snapshots, risk ledger, and exportable handoff contracts.
- HUD/status model covers context, tool calls, active agents, todos, checks,
cost, risk, and queue state.

View File

@@ -0,0 +1,80 @@
# HUD Status And Session Control Contract
This contract defines the portable status payload ECC uses for local operator
surfaces, handoffs, and future HUDs. It is intentionally harness-neutral: a
Claude Code statusline, Codex pane, dmux session, OpenCode run, or terminal-only
workflow can emit partial data without changing field names.
The canonical example lives at
[`examples/hud-status-contract.json`](../../examples/hud-status-contract.json).
## Payload Shape
Every status payload uses `schema_version: "ecc.hud-status.v1"` and keeps these
top-level sections stable:
| Field | Purpose | Primary Source |
|---|---|---|
| `context` | Model, harness, repo, branch, worktree, session id, and context-window pressure | statusline stdin, git, session adapters |
| `toolCalls` | Recent tool counts, pending calls, stale calls, and last tool event | `loop-status`, `tool-usage.jsonl`, hook bridge |
| `activeAgents` | Current workers/subagents, runtime state, branch, worktree, objective, and handoff paths | dmux/orchestration snapshots |
| `todos` | Current in-progress task and todo counts | Claude todos, local task files, plan metadata |
| `checks` | Local and remote validation status with command/check URLs when available | CI, local commands, release gates |
| `cost` | Session spend, token counts, budget, and trend | cost tracker, metrics bridge |
| `risk` | Attention state, conflict pressure, stale calls, dirty worktree, and manual-review flags | readiness gates, git, queue state |
| `queueState` | GitHub PR/issue/discussion counts, conflict queue, merge queue, and stale-salvage queue | GitHub sync, work items |
| `sessionControls` | Supported operator actions for the current target | ECC CLI, dmux, git/GitHub |
| `sync` | Linear, GitHub, and handoff publication state | status updates, work items, handoff writer |
Fields can be `null`, empty arrays, or `"unknown"` when a harness cannot expose
the signal. Producers should not invent incompatible names. Consumers should
render missing sections as unavailable, not as green.
## Session Controls
The minimum session-control vocabulary is:
| Control | Meaning |
|---|---|
| `create` | Start a new isolated run, worktree, or orchestration plan |
| `resume` | Reattach to an existing session or historical target |
| `status` | Emit the current payload without mutating state |
| `stop` | Request a graceful stop or mark the session completed |
| `diff` | Show current working-tree or worker diff |
| `pr` | Open or inspect the linked pull request |
| `mergeQueue` | Show merge-ready, blocked, and waiting-check items |
| `conflictQueue` | Show dirty/conflicting PRs or worktrees needing integration |
`sessionControls.supported` lists the controls available for the current
harness. `sessionControls.blocked` explains unavailable controls, for example a
missing GitHub token, no tmux session, or a read-only adapter.
## Sync Contract
The sync section separates durable trackers:
- `Linear` records project status update id, health, and whether issue creation
is blocked by workspace capacity.
- `GitHub` records the current repo, PR/issue/discussion queue counts, and the
latest merged or open PR tied to the session.
- `handoff` records the durable Markdown handoff path and whether it has been
written after the latest batch.
This makes real-time progress tracking explicit without requiring every run to
create Linear issues or GitHub comments. When Linear issue capacity is blocked,
the status payload can still prove progress through project updates and repo
handoffs.
## Current Implementations
- `ecc status --json` exposes readiness, active sessions, skill runs, install
health, governance, and linked work items from the SQLite state store.
- `ecc loop-status --json --write-dir <dir>` writes live transcript snapshots
and attention signals for long-running loops.
- `ecc session-inspect <target> --write <path>` emits canonical session
snapshots from dmux and Claude-history adapters.
- `scripts/hooks/ecc-statusline.js` renders compact model, task, cost, tool,
file, duration, directory, and context pressure signals inside Claude Code.
The `ecc.hud-status.v1` payload is the common outer contract these surfaces can
project into before ECC grows a dedicated full-screen HUD.

View File

@@ -19,6 +19,10 @@ operator needs.
- Live status: `scripts/loop-status.js` can emit JSON, watch active loops, and
write snapshots for dashboards or handoffs.
- HUD/status contract: `docs/architecture/hud-status-session-control.md` and
`examples/hud-status-contract.json` define the portable payload for context,
tool calls, active agents, todos, checks, cost, risk, queues, session
controls, and tracker sync.
- Session traces: `scripts/session-inspect.js` can inspect Claude, dmux, and
adapter-backed sessions, then write canonical snapshots.
- Harness baseline: `scripts/harness-audit.js` provides a repeatable scorecard
@@ -56,9 +60,11 @@ later, but only after the local event model is useful enough to trust.
scorecard.
3. Run `node scripts/loop-status.js --json --write-dir .ecc/loop-status`
during longer autonomous batches.
4. Run `node scripts/session-inspect.js --list-adapters` to confirm which
4. Review `examples/hud-status-contract.json` before wiring a new HUD or
operator dashboard.
5. Run `node scripts/session-inspect.js --list-adapters` to confirm which
session surfaces are available.
5. Use ECC2 tool logs for risky operations, conflict analysis, and handoff
6. Use ECC2 tool logs for risky operations, conflict analysis, and handoff
review before increasing autonomy.
The end-state is practical: before asking ECC to run larger multi-agent loops,

View File

@@ -45,7 +45,7 @@ Record the exact commit SHA and command output before any publication action:
| Clean release branch | `git status --short --branch` | On intended release commit; no unrelated files | Pending |
| Harness audit | `npm run harness:audit -- --format json` | 70/70 passing | Pending |
| Adapter scorecard | `npm run harness:adapters -- --check` | PASS | Pending |
| Observability readiness | `npm run observability:ready` | 14/14 passing | Pending |
| Observability readiness | `npm run observability:ready` | 16/16 passing | Pending |
| Root suite | `node tests/run-all.js` | 0 failures | Pending |
| Markdown lint | `npx markdownlint-cli '**/*.md' --ignore node_modules` | 0 failures | Pending |
| Package surface | `node tests/scripts/npm-publish-surface.test.js` | 0 failures | Pending |

View File

@@ -0,0 +1,117 @@
{
"schema_version": "ecc.hud-status.v1",
"generatedAt": "2026-05-12T00:00:00.000Z",
"context": {
"harness": "codex",
"model": "gpt-5",
"repo": "affaan-m/everything-claude-code",
"branch": "main",
"worktree": "/repo/everything-claude-code",
"sessionId": "session-active",
"contextWindow": {
"remainingPct": 62,
"pressure": "normal"
}
},
"toolCalls": {
"total": 47,
"pending": 0,
"stale": 0,
"lastTool": {
"name": "gh-pr-view",
"status": "success",
"finishedAt": "2026-05-12T00:00:00.000Z"
}
},
"activeAgents": [
{
"id": "worker-release-docs",
"state": "completed",
"branch": "codex/release-docs",
"worktree": "/tmp/ecc-release-docs",
"objective": "Update release readiness docs",
"handoffPath": "/tmp/ecc-release-docs/handoff.md"
}
],
"todos": {
"inProgress": "Verify release publication matrix",
"counts": {
"pending": 2,
"inProgress": 1,
"completed": 6
}
},
"checks": {
"local": [
{
"command": "npm run observability:ready",
"status": "pass"
}
],
"remote": [
{
"name": "CI",
"status": "pass",
"url": "https://github.com/affaan-m/everything-claude-code/actions"
}
]
},
"cost": {
"sessionUsd": 1.23,
"budgetUsd": 10,
"trend": "within-budget"
},
"risk": {
"status": "attention",
"reasons": [
"release tag not published"
],
"dirtyWorktree": false,
"conflicts": 0,
"manualReviewRequired": true
},
"queueState": {
"github": {
"openPullRequests": 0,
"openIssues": 0,
"openDiscussions": 0
},
"mergeQueue": [],
"conflictQueue": [],
"staleSalvageQueue": [
{
"sourcePullRequest": 1310,
"status": "landed"
}
]
},
"sessionControls": {
"supported": [
"create",
"resume",
"status",
"stop",
"diff",
"pr",
"mergeQueue",
"conflictQueue"
],
"blocked": []
},
"sync": {
"Linear": {
"project": "ECC 2.0 GA",
"health": "atRisk",
"issueCapacityBlocked": true,
"latestStatusUpdateId": "status-update-id"
},
"GitHub": {
"repo": "affaan-m/everything-claude-code",
"latestPullRequest": 1820
},
"handoff": {
"path": "~/.cluster-swarm/handoffs/ecc-update.md",
"written": true
}
}
}

View File

@@ -103,6 +103,13 @@ function includesAll(text, needles) {
return needles.every(needle => text.includes(needle));
}
function hasObjectKeys(value, keys) {
return value
&& typeof value === 'object'
&& !Array.isArray(value)
&& keys.every(key => Object.prototype.hasOwnProperty.call(value, key));
}
function buildChecks(rootDir) {
const packageJsonText = readText(rootDir, 'package.json');
const packageJson = safeParseJson(packageJsonText) || {};
@@ -116,6 +123,8 @@ function buildChecks(rootDir) {
const sessionStoreRust = readText(rootDir, 'ecc2/src/session/store.rs');
const sessionManagerRust = readText(rootDir, 'ecc2/src/session/manager.rs');
const readinessDoc = readText(rootDir, 'docs/architecture/observability-readiness.md');
const hudStatusContract = readText(rootDir, 'docs/architecture/hud-status-session-control.md');
const hudStatusFixture = safeParseJson(readText(rootDir, 'examples/hud-status-contract.json')) || {};
const quickstart = readText(rootDir, 'docs/releases/2.0.0-rc.1/quickstart.md');
const releaseNotes = readText(rootDir, 'docs/releases/2.0.0-rc.1/release-notes.md');
@@ -130,6 +139,50 @@ function buildChecks(rootDir) {
&& includesAll(loopStatus, ['--json', '--watch', '--write-dir']),
fix: 'Restore loop-status JSON/watch/write-dir support.'
},
{
id: 'hud-status-control-contract',
category: 'Live Status',
points: 2,
path: 'docs/architecture/hud-status-session-control.md',
description: 'HUD/status and session-control surfaces have a portable JSON contract',
pass: fileExists(rootDir, 'docs/architecture/hud-status-session-control.md')
&& fileExists(rootDir, 'examples/hud-status-contract.json')
&& includesAll(hudStatusContract, [
'context',
'toolCalls',
'activeAgents',
'todos',
'checks',
'cost',
'risk',
'queueState',
'create',
'resume',
'status',
'stop',
'diff',
'pr',
'mergeQueue',
'conflictQueue',
'Linear',
'GitHub',
'handoff'
])
&& hudStatusFixture.schema_version === 'ecc.hud-status.v1'
&& hasObjectKeys(hudStatusFixture, [
'context',
'toolCalls',
'activeAgents',
'todos',
'checks',
'cost',
'risk',
'queueState',
'sessionControls',
'sync'
]),
fix: 'Add the HUD/status session-control contract doc and example JSON fixture.'
},
{
id: 'session-inspect-adapter-registry',
category: 'Session Trace',

View File

@@ -62,6 +62,24 @@ function seedMinimalRepo(rootDir, overrides = {}) {
'ecc2/src/session/store.rs': 'insert_tool_log query_tool_logs',
'ecc2/src/session/manager.rs': 'sync_tool_activity_metrics tool-usage.jsonl',
'docs/architecture/observability-readiness.md': 'node scripts/observability-readiness.js --format json',
'docs/architecture/hud-status-session-control.md': [
'context toolCalls activeAgents todos checks cost risk queueState',
'create resume status stop diff pr mergeQueue conflictQueue',
'Linear GitHub handoff'
].join('\n'),
'examples/hud-status-contract.json': JSON.stringify({
schema_version: 'ecc.hud-status.v1',
context: {},
toolCalls: {},
activeAgents: [],
todos: {},
checks: {},
cost: {},
risk: {},
queueState: {},
sessionControls: {},
sync: {}
}, null, 2),
'docs/releases/2.0.0-rc.1/quickstart.md': 'observability-readiness.md',
'docs/releases/2.0.0-rc.1/release-notes.md': 'observability-readiness.md'
};
@@ -195,6 +213,23 @@ function runTests() {
}
})) passed++; else failed++;
if (test('missing HUD status contract fails without disturbing core tool checks', () => {
const projectRoot = createTempDir('observability-readiness-hud-fail-');
try {
seedMinimalRepo(projectRoot, {
'examples/hud-status-contract.json': null
});
const report = buildReport(projectRoot);
assert.strictEqual(report.ready, false);
assert.ok(report.checks.some(check => check.id === 'hud-status-control-contract' && !check.pass));
assert.ok(report.checks.some(check => check.id === 'loop-status-live-signal' && check.pass));
} finally {
cleanup(projectRoot);
}
})) passed++; else failed++;
console.log('\nResults:');
console.log(` Passed: ${passed}`);
console.log(` Failed: ${failed}`);