@jaggerxtrm/specialists 3.17.0 → 3.18.1
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/README.md +268 -134
- package/config/mandatory-rules/executor-delivery.md +4 -0
- package/config/mandatory-rules/json-only-final-output.md +13 -0
- package/config/mandatory-rules/service-skills-diff-scan-mandatory.md +26 -0
- package/config/mandatory-rules/service-skills-gitnexus-triage.md +5 -0
- package/config/mandatory-rules/test-runner-execution-scope.md +4 -0
- package/config/skills/setup-specialists/SKILL.md +556 -0
- package/config/skills/specialists-creator/SKILL.md +132 -4
- package/config/skills/specialists-creator/scripts/audit-spec-uniformity.mjs +1 -1
- package/config/skills/using-specialists-v3/SKILL.md +80 -20
- package/config/specialists/bare.specialist.json +3 -3
- package/config/specialists/changelog-drafter.specialist.json +5 -4
- package/config/specialists/changelog-keeper.specialist.json +7 -6
- package/config/specialists/debugger.specialist.json +2 -2
- package/config/specialists/executor.specialist.json +2 -2
- package/config/specialists/explorer.specialist.json +4 -4
- package/config/specialists/memory-processor.specialist.json +3 -3
- package/config/specialists/node-coordinator.specialist.json +3 -3
- package/config/specialists/obligations-scanner.specialist.json +67 -17
- package/config/specialists/overthinker.specialist.json +3 -3
- package/config/specialists/planner.specialist.json +4 -4
- package/config/specialists/quant-methodologist.specialist.json +145 -0
- package/config/specialists/quant-researcher.specialist.json +144 -0
- package/config/specialists/researcher.specialist.json +5 -5
- package/config/specialists/reviewer.specialist.json +1 -1
- package/config/specialists/seconder.specialist.json +2 -2
- package/config/specialists/security-auditor.specialist.json +2 -2
- package/config/specialists/service-skills-sync.specialist.json +90 -75
- package/config/specialists/specialists-creator.specialist.json +4 -4
- package/config/specialists/sync-docs.specialist.json +4 -4
- package/config/specialists/test-engineer.specialist.json +3 -3
- package/config/specialists/test-runner.specialist.json +7 -7
- package/config/specialists/transcriber.specialist.json +3 -3
- package/config/specialists/xt-merge.specialist.json +4 -4
- package/dist/asset-contract.json +22 -3
- package/dist/index.js +28711 -18517
- package/dist/lib.js +10020 -6150
- package/dist/types/cli/console/components.d.ts +83 -0
- package/dist/types/cli/console/components.d.ts.map +1 -0
- package/dist/types/cli/console/config-source.d.ts +58 -0
- package/dist/types/cli/console/config-source.d.ts.map +1 -0
- package/dist/types/cli/console/forensic.d.ts +11 -0
- package/dist/types/cli/console/forensic.d.ts.map +1 -0
- package/dist/types/cli/console/git.d.ts +28 -0
- package/dist/types/cli/console/git.d.ts.map +1 -0
- package/dist/types/cli/console/help.d.ts +2 -0
- package/dist/types/cli/console/help.d.ts.map +1 -0
- package/dist/types/cli/console/log.d.ts +13 -0
- package/dist/types/cli/console/log.d.ts.map +1 -0
- package/dist/types/cli/console/repo-config.d.ts +26 -0
- package/dist/types/cli/console/repo-config.d.ts.map +1 -0
- package/dist/types/cli/console/repo-discovery.d.ts +12 -0
- package/dist/types/cli/console/repo-discovery.d.ts.map +1 -0
- package/dist/types/cli/console/runtime.d.ts +12 -0
- package/dist/types/cli/console/runtime.d.ts.map +1 -0
- package/dist/types/cli/console/subscribe-prototype.d.ts +18 -0
- package/dist/types/cli/console/subscribe-prototype.d.ts.map +1 -0
- package/dist/types/cli/console/theme.d.ts +91 -0
- package/dist/types/cli/console/theme.d.ts.map +1 -0
- package/dist/types/cli/console/types.d.ts +231 -0
- package/dist/types/cli/console/types.d.ts.map +1 -0
- package/dist/types/cli/console/view-model.d.ts +252 -0
- package/dist/types/cli/console/view-model.d.ts.map +1 -0
- package/dist/types/cli/console.d.ts +2 -0
- package/dist/types/cli/console.d.ts.map +1 -0
- package/dist/types/cli/db.d.ts.map +1 -1
- package/dist/types/cli/doctor.d.ts.map +1 -1
- package/dist/types/cli/edit.d.ts.map +1 -1
- package/dist/types/cli/epic.d.ts.map +1 -1
- package/dist/types/cli/feed.d.ts.map +1 -1
- package/dist/types/cli/forensic.d.ts +2 -0
- package/dist/types/cli/forensic.d.ts.map +1 -0
- package/dist/types/cli/format-helpers.d.ts +4 -2
- package/dist/types/cli/format-helpers.d.ts.map +1 -1
- package/dist/types/cli/help.d.ts.map +1 -1
- package/dist/types/cli/init.d.ts +10 -0
- package/dist/types/cli/init.d.ts.map +1 -1
- package/dist/types/cli/list.d.ts.map +1 -1
- package/dist/types/cli/log.d.ts.map +1 -1
- package/dist/types/cli/merge.d.ts.map +1 -1
- package/dist/types/cli/metrics.d.ts +2 -0
- package/dist/types/cli/metrics.d.ts.map +1 -0
- package/dist/types/cli/ps.d.ts.map +1 -1
- package/dist/types/cli/result.d.ts.map +1 -1
- package/dist/types/cli/run.d.ts +20 -0
- package/dist/types/cli/run.d.ts.map +1 -1
- package/dist/types/cli/script.d.ts +3 -0
- package/dist/types/cli/script.d.ts.map +1 -1
- package/dist/types/cli/serve.d.ts.map +1 -1
- package/dist/types/cli/setup.d.ts +19 -1
- package/dist/types/cli/setup.d.ts.map +1 -1
- package/dist/types/cli/status.d.ts.map +1 -1
- package/dist/types/cli/version-check.d.ts +1 -0
- package/dist/types/cli/version-check.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/pi/session.d.ts +12 -1
- package/dist/types/pi/session.d.ts.map +1 -1
- package/dist/types/server.d.ts +15 -0
- package/dist/types/server.d.ts.map +1 -1
- package/dist/types/specialist/benchmarks.d.ts +37 -0
- package/dist/types/specialist/benchmarks.d.ts.map +1 -0
- package/dist/types/specialist/chain-identity.d.ts +7 -1
- package/dist/types/specialist/chain-identity.d.ts.map +1 -1
- package/dist/types/specialist/control.d.ts.map +1 -1
- package/dist/types/specialist/dead-job-audit.d.ts +20 -0
- package/dist/types/specialist/dead-job-audit.d.ts.map +1 -0
- package/dist/types/specialist/forensic-events.d.ts +138 -0
- package/dist/types/specialist/forensic-events.d.ts.map +1 -0
- package/dist/types/specialist/forensic-renderer.d.ts +34 -0
- package/dist/types/specialist/forensic-renderer.d.ts.map +1 -0
- package/dist/types/specialist/git-diff-evidence.d.ts +28 -0
- package/dist/types/specialist/git-diff-evidence.d.ts.map +1 -0
- package/dist/types/specialist/global-config.d.ts +389 -0
- package/dist/types/specialist/global-config.d.ts.map +1 -0
- package/dist/types/specialist/launch.d.ts +9 -0
- package/dist/types/specialist/launch.d.ts.map +1 -1
- package/dist/types/specialist/live-aggregates.d.ts +46 -0
- package/dist/types/specialist/live-aggregates.d.ts.map +1 -0
- package/dist/types/specialist/loader.d.ts +50 -1
- package/dist/types/specialist/loader.d.ts.map +1 -1
- package/dist/types/specialist/model-chain.d.ts +7 -0
- package/dist/types/specialist/model-chain.d.ts.map +1 -0
- package/dist/types/specialist/model-probes.d.ts +28 -0
- package/dist/types/specialist/model-probes.d.ts.map +1 -0
- package/dist/types/specialist/node-contract.d.ts +18 -18
- package/dist/types/specialist/node-supervisor.d.ts.map +1 -1
- package/dist/types/specialist/observability-db.d.ts +1 -1
- package/dist/types/specialist/observability-db.d.ts.map +1 -1
- package/dist/types/specialist/observability-sqlite.d.ts +101 -0
- package/dist/types/specialist/observability-sqlite.d.ts.map +1 -1
- package/dist/types/specialist/pr-drift-refresh.d.ts +17 -0
- package/dist/types/specialist/pr-drift-refresh.d.ts.map +1 -0
- package/dist/types/specialist/preset-resolver.d.ts +56 -0
- package/dist/types/specialist/preset-resolver.d.ts.map +1 -0
- package/dist/types/specialist/prometheus-projection.d.ts +25 -0
- package/dist/types/specialist/prometheus-projection.d.ts.map +1 -0
- package/dist/types/specialist/runner.d.ts +29 -1
- package/dist/types/specialist/runner.d.ts.map +1 -1
- package/dist/types/specialist/schema.d.ts +163 -54
- package/dist/types/specialist/schema.d.ts.map +1 -1
- package/dist/types/specialist/script-runner.d.ts +5 -1
- package/dist/types/specialist/script-runner.d.ts.map +1 -1
- package/dist/types/specialist/snapshot-diff.d.ts +8 -0
- package/dist/types/specialist/snapshot-diff.d.ts.map +1 -0
- package/dist/types/specialist/source-queue.d.ts +13 -0
- package/dist/types/specialist/source-queue.d.ts.map +1 -0
- package/dist/types/specialist/status-load.d.ts.map +1 -1
- package/dist/types/specialist/supervisor.d.ts +25 -1
- package/dist/types/specialist/supervisor.d.ts.map +1 -1
- package/dist/types/specialist/timeline-events.d.ts +70 -1
- package/dist/types/specialist/timeline-events.d.ts.map +1 -1
- package/dist/types/tools/specialist/resume_specialist.tool.d.ts +4 -4
- package/dist/types/tools/specialist/specialist_status.tool.d.ts +1 -1
- package/dist/types/tools/specialist/steer_specialist.tool.d.ts +4 -4
- package/dist/types/tools/specialist/use_specialist.tool.d.ts +16 -16
- package/docs/ARCHITECTURE.md +1176 -0
- package/docs/TODO.md +9 -0
- package/docs/architecture.md +11 -0
- package/docs/archive/2026-03-13-bd-decision-context-template-plan.md +96 -0
- package/docs/archive/AGENT-HANDOFF.md +351 -0
- package/docs/archive/PARITY-ANALYSIS.md +296 -0
- package/docs/archive/SPECIALISTS_REFACTOR.md.md +30 -0
- package/docs/archive/cc-programmatic.md +216 -0
- package/docs/archive/claude-agent-sdk.md +594 -0
- package/docs/archive/decision-specialist-directory.md +41 -0
- package/docs/archive/discoveries.md +148 -0
- package/docs/archive/executor-benchmark-protocol.md +198 -0
- package/docs/archive/future-features.md +66 -0
- package/docs/archive/gzrx-completion-critique.md +183 -0
- package/docs/archive/gzrx-research-notes.md +401 -0
- package/docs/archive/gzrx-tool-catalog.md +760 -0
- package/docs/archive/iron-review-hardening-qa-chain-substrate.md +322 -0
- package/docs/archive/iron-review-hardening.html +1004 -0
- package/docs/archive/issuetracking.md +312 -0
- package/docs/archive/qa-v3.0.2.md +220 -0
- package/docs/archive/restructure.md +231 -0
- package/docs/archive/script-specialists.md +1254 -0
- package/docs/archive/spec-v3.md +792 -0
- package/docs/archive/specialist-stats.md +127 -0
- package/docs/archive/specialists-friction-audit.md +1347 -0
- package/docs/archive/specialists-runtime-critique.md +170 -0
- package/docs/archive/specialists-service-evaluation.md +713 -0
- package/docs/archive/specialists-substrate-alignment.md +255 -0
- package/docs/archive/substrate-review.md +1288 -0
- package/docs/archive/test-writer-specialist.md +254 -0
- package/docs/archive/using-specialists-v3-improvements-2026-05-09.md +600 -0
- package/docs/archive/xtrm-specialists-analysis.md +314 -0
- package/docs/authoring.md +701 -0
- package/docs/background-jobs.md +203 -0
- package/docs/bare-specialists.md +83 -0
- package/docs/benchmarks/executor-benchmark-runner.md +66 -0
- package/docs/bootstrap.md +161 -0
- package/docs/cli-reference.md +1645 -0
- package/docs/deploying-alongside.md +155 -0
- package/docs/design/README.md +36 -0
- package/docs/design/darth-feedor-migration.md +290 -0
- package/docs/design/roadmap/README.md +32 -0
- package/docs/design/roadmap/chain-templates/README.md +146 -0
- package/docs/design/roadmap/chain-templates/code-quick.formula.json +27 -0
- package/docs/design/roadmap/chain-templates/code-standard.formula.json +126 -0
- package/docs/design/roadmap/chain-templates/code-with-advisors.formula.json +128 -0
- package/docs/design/roadmap/chain-templates/code-with-tests.formula.json +76 -0
- package/docs/design/roadmap/chain-templates/debug.formula.json +128 -0
- package/docs/design/roadmap/chain-templates/doc-sync.formula.json +28 -0
- package/docs/design/roadmap/chain-templates/memory-hygiene.formula.json +27 -0
- package/docs/design/roadmap/chain-templates/planning.formula.json +27 -0
- package/docs/design/roadmap/chain-templates/premortem.formula.json +26 -0
- package/docs/design/roadmap/chain-templates/release-prep.formula.json +36 -0
- package/docs/design/roadmap/chain-templates/research-only.formula.json +28 -0
- package/docs/design/roadmap/chain-templates/restitch.formula.json +125 -0
- package/docs/design/roadmap/chain-templates/security-deep.formula.json +161 -0
- package/docs/design/roadmap/chain-templates/test-only.formula.json +52 -0
- package/docs/design/roadmap/chain-templates/triage.formula.json +35 -0
- package/docs/design/roadmap/history/handoff-from-substrate-design.md +87 -0
- package/docs/design/roadmap/history/substrate-reconciliation.md +105 -0
- package/docs/design/roadmap/specialists-roadmap.md +1261 -0
- package/docs/design/sp-console-subscribe-via-materializer.md +231 -0
- package/docs/design/sp-console-tui-mock-v2.html +293 -0
- package/docs/design/sp-console-tui-mock.html +120 -0
- package/docs/design/sp-console-tui.md +340 -0
- package/docs/design/specialist-agentops-suite.md +323 -0
- package/docs/design/substrate/channels.md +14 -0
- package/docs/design/substrate/devops-platform-engineering-prd.md +446 -0
- package/docs/design/substrate/html-design-example.md +339 -0
- package/docs/design/xtrm-tiers-architecture.svg +132 -0
- package/docs/devops/dependency-verdict-materialization.md +46 -0
- package/docs/epic-readiness.md +75 -0
- package/docs/examples/mercury-atomic-summarizer.specialist.json +26 -0
- package/docs/examples/smoke-echo-text-expected-keys.specialist.json +25 -0
- package/docs/examples/smoke-echo.specialist.json +25 -0
- package/docs/features.md +1577 -0
- package/docs/hooks.md +81 -0
- package/docs/installation.md +142 -0
- package/docs/manifest.md +184 -0
- package/docs/mcp-servers.md +73 -0
- package/docs/mcp-tools.md +71 -0
- package/docs/nodes.md +231 -0
- package/docs/observability-metrics.md +152 -0
- package/docs/operator/sp-console-v2-walkthrough.md +410 -0
- package/docs/overrides-guide.md +306 -0
- package/docs/pi-rpc-boundary.md +118 -0
- package/docs/pi-session.md +195 -0
- package/docs/release.md +22 -0
- package/docs/skills.md +132 -0
- package/docs/specialists/handoff-schema.md +181 -0
- package/docs/specialists-catalog.md +99 -0
- package/docs/specialists-service-install.md +226 -0
- package/docs/specialists-service.md +363 -0
- package/docs/surface-ownership.md +138 -0
- package/docs/upgrade-notes/kan-90-global-user-config.md +114 -0
- package/docs/upgrade-notes/kan-91-expanded-overrides.md +261 -0
- package/docs/workflow.md +114 -0
- package/docs/worktree.md +71 -0
- package/docs/worktrees.md +309 -0
- package/package.json +7 -4
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>sp console grounded mock</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
10
|
+
<style>
|
|
11
|
+
:root{
|
|
12
|
+
--bg:#181818;--txt:#c8c8c8;--bright:#e4e4e4;--dim:#7d7d7d;--rail:#3a3a3a;--sel:#262626;
|
|
13
|
+
--running:#c39a5e;--done:#8caa6a;--reviewing:#9f88bf;--waiting:#8095a8;--idle:#4a4a4a;--blocked:#c4806f;
|
|
14
|
+
--mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--lh:1.2;
|
|
15
|
+
}
|
|
16
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
17
|
+
html,body{height:100%}
|
|
18
|
+
body{height:100vh;background:var(--bg);color:var(--txt);font-family:var(--mono);font-size:12.5px;line-height:var(--lh);font-weight:400;letter-spacing:.15px;display:flex;flex-direction:column;overflow:hidden;outline:none}
|
|
19
|
+
.ctx,.stats,.keys,.filter{flex:0 0 auto;padding:0 10px;white-space:pre;overflow:hidden}
|
|
20
|
+
.ctx{color:var(--dim)}.ctx b{color:var(--bright);font-weight:500}
|
|
21
|
+
.main{flex:1 1 auto;min-height:0;overflow:auto;scrollbar-width:thin}.main::-webkit-scrollbar{width:6px}.main::-webkit-scrollbar-thumb{background:#2c2c2c;border-radius:3px}
|
|
22
|
+
.ln{display:flex;align-items:stretch;line-height:var(--lh);padding:0 10px;white-space:pre}.ln.sel{background:var(--sel)}
|
|
23
|
+
.rail{flex:0 0 2ch;border-left:1px solid var(--rail)}.rail.blank{border-left-color:transparent}.c{white-space:pre}.dim{color:var(--dim)}.bright{color:var(--bright)}
|
|
24
|
+
.id,.meta,.payload,.bead,.next{color:var(--dim)}.group{color:var(--bright)}.branch{color:var(--dim)}
|
|
25
|
+
.running{color:var(--running)}.done{color:var(--done)}.reviewing{color:var(--reviewing)}.waiting{color:var(--waiting)}.idle{color:var(--idle)}.blocked,.error{color:var(--blocked)}
|
|
26
|
+
.stats{color:var(--dim)}.stats .ok{color:var(--done)}.stats .warn{color:var(--running)}.stats .bad{color:var(--blocked)}
|
|
27
|
+
.keys{color:var(--dim)}.keys .k{color:var(--txt)}.filter{color:var(--txt)}.filter .p{color:var(--dim)}.hidden{display:none}
|
|
28
|
+
</style>
|
|
29
|
+
</head>
|
|
30
|
+
<body tabindex="0">
|
|
31
|
+
<div class="ctx" id="ctx"></div>
|
|
32
|
+
<div class="main" id="main"></div>
|
|
33
|
+
<div class="filter hidden" id="filter"></div>
|
|
34
|
+
<div class="stats" id="stats"></div>
|
|
35
|
+
<div class="keys" id="keys"></div>
|
|
36
|
+
<script>
|
|
37
|
+
const E=s=>String(s??'').replace(/[&<>]/g,c=>({'&':'&','<':'<','>':'>'}[c]));
|
|
38
|
+
const padR=(s,n)=>{s=String(s??'');return s.length>=n?s.slice(0,n):s+' '.repeat(n-s.length)};
|
|
39
|
+
const padL=(s,n)=>{s=String(s??'');return s.length>=n?s.slice(0,n):' '.repeat(n-s.length)+s};
|
|
40
|
+
const trunc=(s,n)=>{s=String(s??'');return s.length>n?s.slice(0,Math.max(0,n-1))+'…':s};
|
|
41
|
+
const GLY={running:'●',waiting:'◐',starting:'◐',done:'○',error:'✕',cancelled:'○',dead:'✕'};
|
|
42
|
+
const CLS={running:'running',waiting:'waiting',starting:'waiting',done:'done',error:'error',cancelled:'idle',dead:'blocked'};
|
|
43
|
+
const REPOS=[{name:'specialists',path:'/home/dawid/dev/specialists'},{name:'mercury',path:'/home/dawid/projects/mercury'},{name:'gitboard',path:'/home/dawid/dev/gitboard'}];
|
|
44
|
+
const rows=[
|
|
45
|
+
{kind:'epic',d:0,id:'unitAI-ye5s9',label:'release distribution hardening',state:'blocked',summary:'prep 1/2 done · chains 2/3 pass'},
|
|
46
|
+
{kind:'label',d:1,label:'Prep'},
|
|
47
|
+
{kind:'job',d:2,id:'8f31aa',spec:'researcher',status:'done',ctx:18,elapsed:'4m12s 3t·8tc·42ktok',payload:'31.0kb',ptok:'8.4kt',bead:'unitAI-prep1',next:'result',title:'npm-pack validation research'},
|
|
48
|
+
{kind:'label',d:1,label:'Chains'},
|
|
49
|
+
{kind:'chain',d:2,id:'chain:0db4',label:'root: unitAI-9b2dn · pass'},
|
|
50
|
+
{kind:'branch',d:3,label:'fix/unitAI-9b2dn-pack-smoke'},
|
|
51
|
+
{kind:'job',d:4,id:'0db4c1',spec:'executor',status:'done',ctx:41,elapsed:'7m03s 5t·19tc·91ktok',payload:'44.2kb',ptok:'12.1kt',bead:'unitAI-9b2dn',next:'result',title:'add npm pack smoke'},
|
|
52
|
+
{kind:'job',d:4,id:'3a912e',spec:'reviewer',status:'waiting',ctx:63,elapsed:'1m28s 2t·4tc·28ktok',payload:'38.5kb',ptok:'10.8kt',bead:'unitAI-9b2dn',next:'resume',title:'review npm pack smoke'},
|
|
53
|
+
{kind:'chain',d:2,id:'chain:71ab',label:'root: unitAI-yq31q · running'},
|
|
54
|
+
{kind:'branch',d:3,label:'fix/unitAI-yq31q-fresh-install'},
|
|
55
|
+
{kind:'job',d:4,id:'71ab09',spec:'executor',status:'running',ctx:57,elapsed:'2m19s 2t·7tc·36ktok',payload:'40.0kb',ptok:'11.5kt',bead:'unitAI-yq31q',next:'feed',title:'fresh install smoke paths'},
|
|
56
|
+
{kind:'node',d:0,id:'node:research',label:'node-coordinator · running · 3 members'},
|
|
57
|
+
{kind:'job',d:1,id:'44ac01',spec:'researcher',status:'running',ctx:24,elapsed:'0m51s 1t·2tc·12ktok',payload:'22.3kb',ptok:'6.2kt',bead:'unitAI-eoqxp',next:'feed',title:'AgentOps telemetry patterns'},
|
|
58
|
+
{kind:'worktree',d:0,label:'docs/unitAI-i29fm-sp-console-tui-grounding · unitAI-i29fm'},
|
|
59
|
+
{kind:'job',d:1,id:'b710da',spec:'explorer',status:'done',ctx:35,elapsed:'3m10s 3t·5tc·21ktok',payload:'19.8kb',ptok:'5.4kt',bead:'unitAI-i29fm',next:'result',title:'map sp ps/feed runtime'},
|
|
60
|
+
];
|
|
61
|
+
const feeds={
|
|
62
|
+
'71ab09':[
|
|
63
|
+
['run_start','executor/gpt-5.3-codex','bead=unitAI-yq31q branch=fix/unitAI-yq31q-fresh-install chain=chain:71ab'],
|
|
64
|
+
['payload_breakdown','executor/gpt-5.3-codex','payload: 40.0kb · 11.5kt across 7 components'],
|
|
65
|
+
['tool','executor/gpt-5.3-codex','start bash bun run build'],
|
|
66
|
+
['token_usage','executor/gpt-5.3-codex','input=18240 · output=2310 · total=20550'],
|
|
67
|
+
['status_change','executor/gpt-5.3-codex','running → waiting? no · current_tool=bash'],
|
|
68
|
+
],
|
|
69
|
+
'3a912e':[
|
|
70
|
+
['run_start','reviewer/gpt-5.4-mini','bead=unitAI-9b2dn reused=0db4c1 chain_root_bead=unitAI-9b2dn'],
|
|
71
|
+
['tool','reviewer/gpt-5.4-mini','start read docs/pack-smoke.md'],
|
|
72
|
+
['status_change','reviewer/gpt-5.4-mini','waiting'],
|
|
73
|
+
['WAIT','reviewer/gpt-5.4-mini','reviewer (3a912e) is waiting for input. Use: sp resume 3a912e "..."'],
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
const results={
|
|
77
|
+
'0db4c1':[
|
|
78
|
+
['section','startup context'],['job_id','0db4c1'],['specialist','executor'],['bead_id','unitAI-9b2dn'],['chain_id','chain:0db4'],
|
|
79
|
+
['section','result'],['text','Implemented npm-pack smoke and verified package asset resolution from a packed install.'],
|
|
80
|
+
['section','metrics'],['tokens','input=52000 · output=3900 · total=55900'],['cost_usd','$0.0841'],
|
|
81
|
+
],
|
|
82
|
+
'3a912e':[
|
|
83
|
+
['section','latest completed output'],['text','Reviewer reached a waiting state after checking docs/pack-smoke.md. Needs operator input before final verdict.'],
|
|
84
|
+
['section','waiting'],['resume','sp resume 3a912e "..."'],
|
|
85
|
+
],
|
|
86
|
+
'71ab09':[
|
|
87
|
+
['section','running'],['text','No final result yet. Use feed for live progress; previous turn output will appear here when persisted.'],
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
let S={repo:0,view:'ps',sel:0,filtering:false,filter:'',job:null,follow:false,scroll:0,history:'default'};
|
|
91
|
+
function visible(){const q=S.filter.toLowerCase();if(!q)return rows;return rows.filter(r=>r.kind!=='label'&&(r.id+' '+r.label+' '+r.spec+' '+r.title+' '+r.bead+' '+r.status).toLowerCase().includes(q));}
|
|
92
|
+
function rails(d){let h='';for(let i=0;i<d;i++)h+='<span class="rail"></span>';return h}
|
|
93
|
+
function rowHtml(r,selected){
|
|
94
|
+
let body='';
|
|
95
|
+
if(r.kind==='job'){
|
|
96
|
+
const cls=CLS[r.status], glyph=GLY[r.status];
|
|
97
|
+
const left=`<span class="${cls}">${glyph}</span> <span class="id">${padR(r.id,8)}</span> <span>${padR(r.spec,13)}</span> <span class="${cls}">${padR(r.status,9)}</span>`;
|
|
98
|
+
body=left+` <span class="meta">${padL(r.ctx+'%',4)}</span> <span class="meta">${padR(r.elapsed,20)}</span> <span class="payload">${padR(r.payload,8)} ${padR(r.ptok,7)}</span> <span class="bead">${padR(r.bead,14)}</span> <span class="next">${padR(r.next,7)}</span><span class="dim">${E(trunc(r.title,42))}</span>`;
|
|
99
|
+
} else if(r.kind==='epic') body=`<span class="group">◆ ${r.id} · ${r.label}</span> <span class="${CLS[r.state]}">${r.state}</span> <span class="dim">· ${r.summary}</span>`;
|
|
100
|
+
else if(r.kind==='node') body=`<span class="group">⬢ ${r.id}</span> <span class="dim">· ${r.label}</span>`;
|
|
101
|
+
else if(r.kind==='chain') body=`<span class="group">◇ ${r.id}</span> <span class="dim">· ${r.label}</span>`;
|
|
102
|
+
else if(r.kind==='branch'||r.kind==='worktree') body=`<span class="branch">${r.label}</span>`;
|
|
103
|
+
else body=`<span class="dim">${r.label}</span>`;
|
|
104
|
+
return `<div class="ln${selected?' sel':''}">${rails(r.d)}<span class="c">${body}</span></div>`;
|
|
105
|
+
}
|
|
106
|
+
function feedRows(){return feeds[S.job]||[['run_start','sp feed',`job ${S.job} has no mock feed rows`]]}
|
|
107
|
+
function feedHtml(f,i){return `<div class="ln${i===S.scroll?' sel':''}"><span class="c"><span class="dim">${padR(String(i+1),4)}</span> <span class="bright">${padR(f[0],18)}</span> <span class="dim">${padR(f[1],24)}</span> ${E(f[2])}</span></div>`}
|
|
108
|
+
function beadHtml(item){if(item[0]==='section')return `<div class="ln"><span class="c"><span class="dim">── ${E(item[1])} ──</span></span></div>`;if(item[0]==='text')return `<div class="ln"><span class="c">${E(item[1])}</span></div>`;return `<div class="ln"><span class="c"><span class="dim">${padR(item[0],12)}</span>${E(item[1])}</span></div>`}
|
|
109
|
+
function selectedJob(){return visible().filter(r=>r.kind==='job')[0]&&visible()[S.sel]?.kind==='job'?visible()[S.sel]:null}
|
|
110
|
+
function setCtx(){const repo=REPOS[S.repo];document.getElementById('ctx').innerHTML=`<b>${S.view}</b> · ${repo.name} · ${repo.path}${S.job?' · '+S.job:''}`}
|
|
111
|
+
function setStats(){document.getElementById('stats').innerHTML=`health <span class="ok">OK</span> rss=512MB cpu=3.1% · jobs 6 visible/42 total · running 2 waiting 1 · history ${S.history} · epics 1 nodes 1 worktrees 3 · ctx max <span class="warn">63%</span> · tokens 184k · orphans 0`}
|
|
112
|
+
function key(k,d){return `<span class="k">${k}</span> ${d} `}
|
|
113
|
+
function setKeys(){const el=document.getElementById('keys');if(S.view==='ps')el.innerHTML=key('↑↓','nav')+key('↵','feed')+key('r','result')+key('i','inspect')+key('h','history')+key('a','all')+key('/','filter')+key('⇥','repo')+key('q','quit');else if(S.view==='feed')el.innerHTML=key('↑↓','scroll')+key('f','follow')+key('⌫','back')+key('g/G','top/end')+key('q','quit');else el.innerHTML=key('↑↓','scroll')+key('⌫','back')+key('q','quit')}
|
|
114
|
+
function render(){setCtx();setStats();setKeys();const main=document.getElementById('main');if(S.view==='ps'){const vis=visible();S.sel=Math.max(0,Math.min(S.sel,vis.length-1));main.innerHTML=vis.map((r,i)=>rowHtml(r,i===S.sel)).join('')||'<div class="ln"><span class="c dim">no matches</span></div>'}else if(S.view==='feed'){main.innerHTML=feedRows().map(feedHtml).join('')}else if(S.view==='job'){const r=rows.find(x=>x.id===S.job);main.innerHTML=[['job',r?.id],['specialist',r?.spec],['status',r?.status],['bead',r?.bead],['worktree','fix/'+(r?.bead||'none')],['chain_id','from worktree_owner_job_id'],['elapsed',r?.elapsed],['context',r?.ctx+'%'],['next',r?.next]].map(beadHtml).join('')}else{main.innerHTML=(results[S.job]||[['section','result'],['text','No persisted result yet. Use feed for timeline replay.']]).map(beadHtml).join('')}const fl=document.getElementById('filter');if(S.filtering){fl.classList.remove('hidden');fl.innerHTML=`<span class="p">/</span>${E(S.filter)}_`}else fl.classList.add('hidden');const sel=main.querySelector('.sel');if(sel)sel.scrollIntoView({block:'nearest'})}
|
|
115
|
+
function move(d){if(S.view==='ps'){S.sel=Math.max(0,Math.min(visible().length-1,S.sel+d))}else{const max=(S.view==='feed'?feedRows().length:20)-1;S.scroll=Math.max(0,Math.min(max,S.scroll+d));document.getElementById('main').scrollBy(0,d*16)}}
|
|
116
|
+
window.addEventListener('keydown',e=>{if(S.filtering){if(e.key==='Escape'){S.filtering=false;S.filter=''}else if(e.key==='Enter'){S.filtering=false}else if(e.key==='Backspace'){S.filter=S.filter.slice(0,-1)}else if(e.key.length===1){S.filter+=e.key}else return;e.preventDefault();render();return}const r=visible()[S.sel];switch(e.key){case'ArrowDown':case'j':move(1);break;case'ArrowUp':case'k':move(-1);break;case'Enter':if(S.view==='ps'&&r?.kind==='job'){S.view='feed';S.job=r.id;S.scroll=0}break;case'r':if(S.view==='ps'&&r?.kind==='job'){S.view='result';S.job=r.id;S.scroll=0}break;case'i':if(S.view==='ps'&&r?.kind==='job'){S.view='job';S.job=r.id;S.scroll=0}break;case'h':if(S.view==='ps'){S.history=S.history==='default'?'history':S.history==='history'?'all':'default'}break;case'a':if(S.view==='ps'){S.history=S.history==='all'?'default':'all'}break;case'Escape':case'Backspace':case'ArrowLeft':if(S.view!=='ps'){S.view='ps';S.job=null}break;case'/':if(S.view==='ps')S.filtering=true;break;case'f':if(S.view==='feed')S.follow=!S.follow;break;case'Tab':S.repo=(S.repo+1)%REPOS.length;S.view='ps';S.sel=0;break;case'1':case'2':case'3':S.repo=Number(e.key)-1;S.view='ps';S.sel=0;break;case'g':S.sel=0;S.scroll=0;document.getElementById('main').scrollTop=0;break;case'G':S.sel=visible().length-1;document.getElementById('main').scrollTop=document.getElementById('main').scrollHeight;break;default:return}e.preventDefault();render()});
|
|
117
|
+
document.body.focus();window.addEventListener('click',()=>document.body.focus());render();
|
|
118
|
+
</script>
|
|
119
|
+
</body>
|
|
120
|
+
</html>
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# `sp console` — grounded TUI design
|
|
2
|
+
|
|
3
|
+
> Design target for a future `sp console` command in this repo.
|
|
4
|
+
>
|
|
5
|
+
> This is **not** a substrate mock. Bind the UI to the runtime that exists today: `sp ps`, `sp feed`, `sp result`, `sp resume/steer/stop`, `sp epic`, `sp node`, and beads (`bd`). The companion HTML is only a visual mock for density, rail, palette, and key feel.
|
|
6
|
+
|
|
7
|
+
## 0. Reality anchors
|
|
8
|
+
|
|
9
|
+
Read these before implementation and keep the design in sync with them:
|
|
10
|
+
|
|
11
|
+
| Surface | Source of truth | What `sp console` must mirror |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Process dashboard | `src/cli/ps.ts` | visibility rules, grouping, status icons, columns, next-action hints |
|
|
14
|
+
| Event stream | `src/cli/feed.ts`, `src/specialist/timeline-events.ts`, `src/specialist/timeline-query.ts` | DB-backed timeline, cursor/follow behavior, event filtering |
|
|
15
|
+
| Job state | `src/specialist/supervisor.ts`, `src/specialist/status-load.ts` | `SupervisorStatus`, metrics, context health, worktree/chain/epic fields |
|
|
16
|
+
| Runtime DB | `src/specialist/observability-sqlite.ts`, `src/specialist/observability-db.ts` | `.specialists/db/observability.db` as normal runtime store |
|
|
17
|
+
| Beads | `src/specialist/beads.ts`, `bd list --json` / `bd show --json` (post-v1 browser) | v1 displays linked `bead_id`/title from job status; full bead browsing is post-v1 |
|
|
18
|
+
| Existing TUI stack | `src/cli/chat.ts`, `src/cli/attach-tui.ts`, `src/cli/chat/feed.ts`, `src/cli/chat/status.ts` | `@earendil-works/pi-tui` lifecycle and component patterns |
|
|
19
|
+
|
|
20
|
+
Non-negotiable corrections from older mockups:
|
|
21
|
+
|
|
22
|
+
- Use **TypeScript + Bun + `@earendil-works/pi-tui`**, not Ink.
|
|
23
|
+
- Do **not** invent substrate containers, steps, contracts, tethers, mailboxes, or waves.
|
|
24
|
+
- Current `sp` does have `epic_id`, derived epic readiness, node runs, worktree reuse chains, and bead-linked jobs. Render those real entities only.
|
|
25
|
+
- **V1 traceability includes terminal jobs**: history toggles, completed feed replay, and result inspection.
|
|
26
|
+
- `bd show` / bead browser navigation is **post-v1**. V1 shows linked bead id/title in job rows but does not open bead detail.
|
|
27
|
+
- The performance/status strip stays one line at the bottom, immediately above shortcuts.
|
|
28
|
+
|
|
29
|
+
## 1. Product shape
|
|
30
|
+
|
|
31
|
+
`sp console` is a full-viewport, read-mostly operator TUI for one or more specialists repos. It is a navigable version of:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
sp ps --follow
|
|
35
|
+
sp feed <job-id> --follow
|
|
36
|
+
sp ps <job-id>
|
|
37
|
+
sp result <job-id>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
One view is visible at a time. No sidebar, no split panes.
|
|
41
|
+
|
|
42
|
+
Views:
|
|
43
|
+
|
|
44
|
+
1. **ProcessView** — default dashboard, shaped by `sp ps`.
|
|
45
|
+
2. **FeedView** — compact job timeline, shaped by `sp feed`.
|
|
46
|
+
3. **JobView** — focused job inspect, shaped by `sp ps <id>`.
|
|
47
|
+
4. **ResultView** — final/latest assistant output, shaped by `sp result <id>`.
|
|
48
|
+
|
|
49
|
+
## 2. Runtime architecture
|
|
50
|
+
|
|
51
|
+
Use one seam between UI and runtime. Views never shell out directly and never open SQLite directly.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
App/pi-tui components
|
|
55
|
+
↓ dispatch actions
|
|
56
|
+
Store/reducer
|
|
57
|
+
↓ calls
|
|
58
|
+
RuntimeClient
|
|
59
|
+
↓ uses existing repo modules / safe bd subprocess args
|
|
60
|
+
specialists runtime + bd
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2.1 `RuntimeClient`
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
interface RuntimeClient {
|
|
67
|
+
listRepos(): Promise<RepoRef[]>;
|
|
68
|
+
|
|
69
|
+
// ProcessView = sp ps parity.
|
|
70
|
+
listProcessSnapshot(repo: RepoId, opts: ProcessFilter): Promise<ProcessSnapshot>;
|
|
71
|
+
subscribeProcessSnapshot(repo: RepoId, cb: () => void): Unsubscribe;
|
|
72
|
+
|
|
73
|
+
// FeedView = sp feed parity.
|
|
74
|
+
readFeed(args: { repo: RepoId; jobId: string; fromSeq?: number; limit?: number }): Promise<FeedEvent[]>;
|
|
75
|
+
subscribeFeed(args: { repo: RepoId; jobId?: string; nodeId?: string }, cb: (event: FeedEvent) => void): Unsubscribe;
|
|
76
|
+
|
|
77
|
+
// JobView = sp ps <id> parity.
|
|
78
|
+
inspectJob(repo: RepoId, jobIdPrefix: string): Promise<JobInspect>;
|
|
79
|
+
|
|
80
|
+
// ResultView = sp result parity.
|
|
81
|
+
readResult(repo: RepoId, jobIdPrefix: string): Promise<JobResult>;
|
|
82
|
+
|
|
83
|
+
// Post-v1 bead browser; not required for traceability v1.
|
|
84
|
+
listBeads?(repo: RepoId, opts: BeadListFilter): Promise<BeadListSnapshot>;
|
|
85
|
+
showBead?(repo: RepoId, beadId: string): Promise<BeadDetail>;
|
|
86
|
+
|
|
87
|
+
// Bottom StatsLine.
|
|
88
|
+
readHealth(repo: RepoId): Promise<ProcessHealthSnapshot>;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Implementation guidance:
|
|
93
|
+
|
|
94
|
+
- Prefer importing repo modules (`loadStatuses`, `collectProcessHealth`, `queryTimeline`, `createObservabilitySqliteClient`) over spawning `sp` and parsing text.
|
|
95
|
+
- `bd` access can shell out with `spawnSync`/`spawn` **argument arrays only**, matching `BeadsClient`; never interpolate shell strings.
|
|
96
|
+
- Keep the CLI outputs as parity references. If `sp ps` semantics change, update `RuntimeClient` and this doc together.
|
|
97
|
+
|
|
98
|
+
### 2.2 Store
|
|
99
|
+
|
|
100
|
+
A single reducer owns navigation state and buffered feed rows.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
type View = 'ps' | 'feed' | 'job' | 'result';
|
|
104
|
+
|
|
105
|
+
interface State {
|
|
106
|
+
repo: RepoId;
|
|
107
|
+
view: View;
|
|
108
|
+
selectedRow: number;
|
|
109
|
+
filter: string;
|
|
110
|
+
filtering: boolean;
|
|
111
|
+
selectedJobId?: string;
|
|
112
|
+
feed: Record<string, FeedEvent[]>;
|
|
113
|
+
historyMode: 'default' | 'history' | 'all';
|
|
114
|
+
follow: boolean;
|
|
115
|
+
health?: ProcessHealthSnapshot;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Components are pure renderers over state. Async subscriptions dispatch actions and call `tui.requestRender()`.
|
|
120
|
+
|
|
121
|
+
## 3. Process model to render
|
|
122
|
+
|
|
123
|
+
Render the same hierarchy `sp ps` builds today:
|
|
124
|
+
|
|
125
|
+
1. **System health** — source: `collectProcessHealth()`; in console this becomes the bottom StatsLine, not a top block.
|
|
126
|
+
2. **Epic groups** — jobs with `epic_id`, grouped into prep jobs and chains; readiness comes from `loadEpicReadinessSummary()` and is derived, not hand-entered.
|
|
127
|
+
3. **Node groups** — jobs with `node_id`, using node run names/statuses from the observability DB.
|
|
128
|
+
4. **Worktree trees** — jobs sharing `worktree_owner_job_id`; reused jobs appear as children via `reused_from_job_id`.
|
|
129
|
+
5. **Standalone jobs** — no node/epic/worktree grouping.
|
|
130
|
+
|
|
131
|
+
Job row columns must stay aligned with `sp ps` fields:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
st id specialist status ctx elapsed+metrics payload bead next title
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use these real fields from `SupervisorStatus`:
|
|
138
|
+
|
|
139
|
+
- identity: `id`, `specialist`, `bead_id`, `bead_title`, `node_id`
|
|
140
|
+
- lifecycle: `status`, `pid`, liveness/dead flag
|
|
141
|
+
- workspace: `worktree_path`, `branch`, `worktree_owner_job_id`, `reused_from_job_id`
|
|
142
|
+
- chain/epic: `chain_kind`, `chain_id`, `chain_root_job_id`, `chain_root_bead_id`, `epic_id`
|
|
143
|
+
- observability: `elapsed_s`, `context_pct`, `context_health`, `metrics`, `startup_payload_json`
|
|
144
|
+
|
|
145
|
+
Do not render a row as an "issue step" unless the runtime exposes that as a job row. The selectable unit is a **job**.
|
|
146
|
+
|
|
147
|
+
## 4. Feed model to render
|
|
148
|
+
|
|
149
|
+
FeedView is a navigable `sp feed`:
|
|
150
|
+
|
|
151
|
+
- Source events from `observability.db`; file reads are fallback/legacy only.
|
|
152
|
+
- Preserve cursor semantics (`jobId:seq` / `--from`) and follow semantics.
|
|
153
|
+
- Human mode should use the same suppression principle as `sp feed`: hide high-noise turn/message rows by default, show actionable lifecycle/tool/error/status rows.
|
|
154
|
+
- JSON/raw mode can be a future toggle; default is compact human progress.
|
|
155
|
+
|
|
156
|
+
Important real event families:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
run_start, status_change, meta, payload_breakdown, tool, text, thinking,
|
|
160
|
+
token_usage, finish_reason, turn_summary, compaction, retry, error,
|
|
161
|
+
extension_error, model_change, run_complete
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Waiting jobs should show the real next action:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
WAIT reviewer/gpt-5.4-mini (49adda) is waiting for input. Use: sp resume 49adda "..."
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 5. V1 traceability
|
|
171
|
+
|
|
172
|
+
Traceability is part of v1 and is grounded in current CLI behavior. It is **not** a post-v1 nice-to-have.
|
|
173
|
+
|
|
174
|
+
### 5.1 History visibility
|
|
175
|
+
|
|
176
|
+
ProcessView must expose the same visibility modes as `sp ps`:
|
|
177
|
+
|
|
178
|
+
- default: active jobs plus unresolved terminal problems
|
|
179
|
+
- history: active plus uncleaned terminal history (`--include-terminal`)
|
|
180
|
+
- all: full audit view (`--all`, including cleaned/dead/history)
|
|
181
|
+
- optional cleaned toggle: rows hidden by `sp clean --ps` (`--include-cleaned`)
|
|
182
|
+
|
|
183
|
+
Use `h` / `a` or an equivalent compact cycle:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
active/default → history → all
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 5.2 Feed replay after completion
|
|
190
|
+
|
|
191
|
+
`sp feed <job>` is DB-backed in normal runtime and can replay events after a job is done. FeedView must therefore work for running, waiting, done, error, and cancelled jobs. Follow mode only follows live jobs; terminal jobs open as replay.
|
|
192
|
+
|
|
193
|
+
### 5.3 Result inspection
|
|
194
|
+
|
|
195
|
+
ResultView is v1. It mirrors `sp result <job>` semantics:
|
|
196
|
+
|
|
197
|
+
- `done` → show final result plus metrics/footer
|
|
198
|
+
- `waiting` → show latest completed output when available plus the real resume footer
|
|
199
|
+
- `running` / `starting` → show latest completed output if available, otherwise guide to feed
|
|
200
|
+
- `error` / `cancelled` → show terminal reason and log/feed hints where available
|
|
201
|
+
|
|
202
|
+
### 5.4 Next-action mapping
|
|
203
|
+
|
|
204
|
+
The row's `next` action should drive the default affordance:
|
|
205
|
+
|
|
206
|
+
| Job state | Primary action | Secondary action |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| `starting` / `running` | feed | result if previous output exists |
|
|
209
|
+
| `waiting` | result | resume hint / feed replay |
|
|
210
|
+
| `done` | result | feed replay |
|
|
211
|
+
| `error` | result/error detail | feed/log replay |
|
|
212
|
+
| `cancelled` / dead | log/feed replay | result if persisted |
|
|
213
|
+
|
|
214
|
+
### 5.5 Beads in v1 vs post-v1
|
|
215
|
+
|
|
216
|
+
V1 keeps bead traceability in job rows (`bead_id`, bead title, chain root bead) but does **not** open `bd show`. Full bead navigation is post-v1:
|
|
217
|
+
|
|
218
|
+
- `bd list --json` / `bd query --json` for a navigable bead list
|
|
219
|
+
- `bd show <id> --json` for expanded detail
|
|
220
|
+
- dependency rows selectable from detail
|
|
221
|
+
- breadcrumb/back stack
|
|
222
|
+
- repo-aware `bd` execution in selected repo cwd
|
|
223
|
+
|
|
224
|
+
## 6. `@earendil-works/pi-tui` implementation rules
|
|
225
|
+
|
|
226
|
+
Use the runtime's existing TUI stack:
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
import { TUI, ProcessTerminal, Container, Input, matchesKey, Key, truncateToWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Patterns to follow from existing code:
|
|
233
|
+
|
|
234
|
+
- Instantiate `const terminal = new ProcessTerminal(); const tui = new TUI(terminal);`.
|
|
235
|
+
- Mount children with `tui.addChild(root)`; do **not** assign `tui.root`.
|
|
236
|
+
- `Container` is vertical composition; add custom components with `addChild()`.
|
|
237
|
+
- Components implement `render(width): string[]`, optional `handleInput(data)`, and `invalidate()`.
|
|
238
|
+
- Every rendered line must be `<= width`; use `truncateToWidth()` and `wrapTextWithAnsi()`.
|
|
239
|
+
- After state changes, call `tui.requestRender()`.
|
|
240
|
+
- Use `matchesKey(data, Key.up)` / `Key.down` / `Key.enter` / `Key.shift('enter')` patterns instead of raw escape matching where possible.
|
|
241
|
+
- Cache rendered rows by width and invalidate on data/theme changes.
|
|
242
|
+
|
|
243
|
+
Do not use Ink concepts like `<Static>`. For append-only feed performance, implement the same idea with a cached line buffer like `ChatFeed`: append new wrapped rows, trim to a max, and request render.
|
|
244
|
+
|
|
245
|
+
## 7. Layout
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
ps · specialists · /home/dawid/dev/specialists
|
|
249
|
+
<main view fills available rows>
|
|
250
|
+
health OK rss=512MB cpu=3.1% · jobs 6 visible/42 total · running 2 waiting 1 · history default · ctx max 61% · tokens 184k
|
|
251
|
+
↑↓ nav ↵ feed r result i inspect h history a all / filter tab repo q quit
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Rules:
|
|
255
|
+
|
|
256
|
+
- One top context line: view, repo name, repo path.
|
|
257
|
+
- Main area fills the viewport.
|
|
258
|
+
- One bottom StatsLine. It must use metrics the runtime already computes: process health, visible/total jobs, running/waiting counts, max context%, token/cost totals when available, node/worktree/epic counts.
|
|
259
|
+
- One bottom KeyBar, contextual to the current view.
|
|
260
|
+
- No empty rows.
|
|
261
|
+
|
|
262
|
+
## 8. Style contract
|
|
263
|
+
|
|
264
|
+
This style is intentionally terminal-native.
|
|
265
|
+
|
|
266
|
+
- No panels, boxes, bordered cards, sidebars, or decorative separators.
|
|
267
|
+
- Monospace rows with fixed-width padded columns.
|
|
268
|
+
- Continuous vertical rail for nesting. The current `sp ps` text uses `├─/└─`; console may use a subtler `│` rail, but it must represent the same grouping.
|
|
269
|
+
- One desaturated status color; all metadata stays gray.
|
|
270
|
+
- Selection is a muted background bar, not saturated color.
|
|
271
|
+
- KeyBar is plain text; key glyph brighter than descriptions.
|
|
272
|
+
|
|
273
|
+
Palette single source (`theme.ts`):
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
export const colors = {
|
|
277
|
+
bg: '#181818', bright: '#e4e4e4', txt: '#c8c8c8', dim: '#7d7d7d',
|
|
278
|
+
rail: '#3a3a3a', selected: '#262626',
|
|
279
|
+
running: '#c39a5e', done: '#8caa6a', reviewing: '#9f88bf',
|
|
280
|
+
waiting: '#8095a8', idle: '#4a4a4a', blocked: '#c4806f', error: '#c4806f',
|
|
281
|
+
};
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Status glyphs should map from actual `SupervisorStatus.status`:
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
running ● waiting ◐ starting ◐ done ○ error ✕ cancelled ○ dead ✕
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## 9. Keybindings
|
|
291
|
+
|
|
292
|
+
| Key | ProcessView | FeedView | JobView | ResultView |
|
|
293
|
+
|---|---|---|---|---|
|
|
294
|
+
| `↑↓` / `j k` | move selection | scroll | scroll | scroll |
|
|
295
|
+
| `Enter` | open feed replay/follow for selected job | - | - | - |
|
|
296
|
+
| `r` | open result for selected job | - | - | - |
|
|
297
|
+
| `i` | inspect selected job (`sp ps <id>` parity) | - | - | - |
|
|
298
|
+
| `h` | cycle default/history | - | - | - |
|
|
299
|
+
| `a` | toggle all audit rows | - | - | - |
|
|
300
|
+
| `Esc` / `←` / `Backspace` | - | back to ps | back to ps | back to ps |
|
|
301
|
+
| `f` | toggle dashboard follow | toggle feed follow for live jobs | - | - |
|
|
302
|
+
| `/` | filter visible jobs | - | - | - |
|
|
303
|
+
| `g` / `G` | top/end | top/end | top/end | top/end |
|
|
304
|
+
| `Tab` / `1-9` | switch repo | switch repo → ps | switch repo → ps | switch repo → ps |
|
|
305
|
+
| `q` | quit | quit | quit | quit |
|
|
306
|
+
|
|
307
|
+
## 10. Module sketch
|
|
308
|
+
|
|
309
|
+
```text
|
|
310
|
+
src/cli/console.ts # command entry; creates TUI and RuntimeClient
|
|
311
|
+
src/cli/console/App.ts # root component/router
|
|
312
|
+
src/cli/console/theme.ts # colors, glyphs, widths, ANSI helpers
|
|
313
|
+
src/cli/console/store.ts # reducer and actions
|
|
314
|
+
src/cli/console/client.ts # RuntimeClient interface
|
|
315
|
+
src/cli/console/local.ts # implementation via existing runtime modules + bd
|
|
316
|
+
src/cli/console/views/
|
|
317
|
+
ProcessView.ts
|
|
318
|
+
FeedView.ts
|
|
319
|
+
JobView.ts
|
|
320
|
+
ResultView.ts
|
|
321
|
+
# post-v1: BeadsView.ts / BeadDetailView.ts
|
|
322
|
+
src/cli/console/components/
|
|
323
|
+
Row.ts
|
|
324
|
+
StatsLine.ts
|
|
325
|
+
KeyBar.ts
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## 11. Definition of done
|
|
329
|
+
|
|
330
|
+
- [ ] `sp console` uses `@earendil-works/pi-tui`, not Ink.
|
|
331
|
+
- [ ] ProcessView matches `sp ps` grouping, visibility rules, columns, and next actions.
|
|
332
|
+
- [ ] FeedView reads the DB-backed timeline and matches `sp feed` follow/cursor behavior.
|
|
333
|
+
- [ ] JobView matches `sp ps <id>` fields.
|
|
334
|
+
- [ ] ResultView mirrors `sp result` for done/waiting/running/error/cancelled jobs.
|
|
335
|
+
- [ ] V1 history modes cover default, terminal history, and all audit rows.
|
|
336
|
+
- [ ] `bd show` / full bead browser is explicitly post-v1, not required for traceability v1.
|
|
337
|
+
- [ ] StatsLine is one bottom line and contains only real runtime metrics.
|
|
338
|
+
- [ ] No substrate-only concepts appear in labels or mock data.
|
|
339
|
+
- [ ] All rows are width-safe (`truncateToWidth` / `wrapTextWithAnsi`).
|
|
340
|
+
- [ ] Palette, glyphs, and column widths live in one theme module.
|