cool-workflow 0.2.1 → 0.2.3

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.
Files changed (156) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/apps/architecture-review/app.json +1 -1
  4. package/apps/architecture-review-fast/app.json +1 -1
  5. package/apps/end-to-end-golden-path/app.json +1 -1
  6. package/apps/pr-review-fix-ci/app.json +1 -1
  7. package/apps/release-cut/app.json +1 -1
  8. package/apps/research-synthesis/app.json +1 -1
  9. package/dist/cli/dispatch.js +29 -91
  10. package/dist/cli/entry.js +41 -1
  11. package/dist/cli/io.js +6 -2
  12. package/dist/cli/parseargv.js +6 -2
  13. package/dist/core/capability-data.js +271 -0
  14. package/dist/core/capability-table.js +16 -3504
  15. package/dist/core/format/completion.js +68 -0
  16. package/dist/core/format/help.js +50 -8
  17. package/dist/core/format/safe-json.js +73 -0
  18. package/dist/core/format/state-explosion-text.js +1 -1
  19. package/dist/core/multi-agent/candidate-scoring.js +5 -1
  20. package/dist/core/multi-agent/collaboration.js +6 -5
  21. package/dist/core/multi-agent/coordinator.js +9 -8
  22. package/dist/core/multi-agent/runtime.js +4 -4
  23. package/dist/core/multi-agent/topology.js +3 -3
  24. package/dist/core/pipeline/commit-gate.js +2 -1
  25. package/dist/core/pipeline/dispatch.js +18 -4
  26. package/dist/core/pipeline/drive-decide.js +2 -1
  27. package/dist/core/state/migrations.js +16 -1
  28. package/dist/core/state/state-explosion/digest.js +16 -15
  29. package/dist/core/state/state-explosion/graph.js +26 -19
  30. package/dist/core/state/state-explosion/helpers.js +2 -1
  31. package/dist/core/state/state-explosion/report.js +6 -6
  32. package/dist/core/trust/ledger.js +2 -1
  33. package/dist/core/types/execution-backend.js +18 -0
  34. package/dist/core/types/observability.js +7 -0
  35. package/dist/core/util/collate.js +23 -0
  36. package/dist/core/util/numeric-flag.js +40 -0
  37. package/dist/core/version.js +1 -1
  38. package/dist/mcp/server.js +99 -11
  39. package/dist/shell/audit-cli.js +99 -23
  40. package/dist/shell/commit-summary.js +2 -1
  41. package/dist/shell/coordinator-io.js +73 -13
  42. package/dist/shell/dispatch.js +1 -1
  43. package/dist/shell/doctor.js +80 -1
  44. package/dist/shell/drive.js +269 -59
  45. package/dist/shell/eval-text.js +2 -2
  46. package/dist/shell/evidence-reasoning.js +8 -7
  47. package/dist/shell/execution-backend/agent.js +20 -1
  48. package/dist/shell/execution-backend/container.js +4 -1
  49. package/dist/shell/execution-backend/local.js +4 -1
  50. package/dist/shell/execution-backend/registry.js +2 -1
  51. package/dist/shell/execution-backend/types.js +0 -9
  52. package/dist/shell/feedback-cli.js +6 -6
  53. package/dist/shell/fs-atomic.js +232 -30
  54. package/dist/shell/man-cli.js +6 -0
  55. package/dist/shell/metrics-cli.js +2 -1
  56. package/dist/shell/multi-agent-cli.js +367 -323
  57. package/dist/shell/multi-agent-host.js +9 -9
  58. package/dist/shell/multi-agent-operator-ux.js +82 -39
  59. package/dist/shell/node-store.js +10 -4
  60. package/dist/shell/observability.js +13 -12
  61. package/dist/shell/onramp.js +17 -1
  62. package/dist/shell/operator-ux-text.js +24 -23
  63. package/dist/shell/operator-ux.js +22 -20
  64. package/dist/shell/orchestrator.js +49 -38
  65. package/dist/shell/pipeline-cli.js +168 -111
  66. package/dist/shell/reclamation-io.js +16 -5
  67. package/dist/shell/registry-cli.js +19 -17
  68. package/dist/shell/remote-source.js +13 -8
  69. package/dist/shell/report-cli.js +45 -0
  70. package/dist/shell/report.js +4 -2
  71. package/dist/shell/run-registry-io.js +77 -19
  72. package/dist/shell/run-store.js +91 -2
  73. package/dist/shell/scheduling-io.js +12 -13
  74. package/dist/shell/state-cli.js +2 -7
  75. package/dist/shell/state-explosion-cli.js +19 -10
  76. package/dist/shell/topology-io.js +38 -6
  77. package/dist/shell/trust-audit.js +264 -23
  78. package/dist/shell/trust-policy-io.js +1 -1
  79. package/dist/shell/worker-cli.js +41 -29
  80. package/dist/shell/worker-isolation.js +34 -9
  81. package/dist/shell/workflow-app-loader.js +3 -2
  82. package/dist/wiring/capability-table/basics.js +91 -0
  83. package/dist/wiring/capability-table/exec-backend.js +171 -0
  84. package/dist/wiring/capability-table/index.js +42 -0
  85. package/dist/wiring/capability-table/multi-agent.js +630 -0
  86. package/dist/wiring/capability-table/parity.js +467 -0
  87. package/dist/wiring/capability-table/pipeline.js +292 -0
  88. package/dist/wiring/capability-table/registry-core.js +208 -0
  89. package/dist/wiring/capability-table/reporting.js +435 -0
  90. package/dist/wiring/capability-table/scheduling-registry.js +592 -0
  91. package/dist/wiring/capability-table/state.js +181 -0
  92. package/dist/wiring/capability-table/trust-ledger.js +158 -0
  93. package/dist/wiring/capability-table/workflow-apps.js +381 -0
  94. package/docs/agent-delegation-drive.7.md +4 -0
  95. package/docs/candidate-scoring.7.md +1 -1
  96. package/docs/canonical-workflow-apps.7.md +7 -7
  97. package/docs/cli-mcp-parity.7.md +13 -3
  98. package/docs/contract-migration-tooling.7.md +4 -0
  99. package/docs/control-plane-scheduling.7.md +4 -0
  100. package/docs/coordinator-blackboard.7.md +17 -17
  101. package/docs/dogfood-one-real-repo.7.md +11 -11
  102. package/docs/durable-state-and-locking.7.md +24 -0
  103. package/docs/end-to-end-golden-path.7.md +14 -14
  104. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  105. package/docs/execution-backends.7.md +4 -0
  106. package/docs/getting-started.md +37 -37
  107. package/docs/index.md +1 -0
  108. package/docs/multi-agent-cli-mcp-surface.7.md +21 -17
  109. package/docs/multi-agent-eval-replay-harness.7.md +17 -13
  110. package/docs/multi-agent-operator-ux.7.md +23 -19
  111. package/docs/multi-agent-runtime-core.7.md +22 -22
  112. package/docs/multi-agent-topologies.7.md +6 -6
  113. package/docs/multi-agent-trust-policy-audit.7.md +11 -11
  114. package/docs/node-snapshot-diff-replay.7.md +4 -0
  115. package/docs/observability-cost-accounting.7.md +4 -0
  116. package/docs/operator-ux.7.md +34 -34
  117. package/docs/pipeline-runner.7.md +4 -4
  118. package/docs/project-index.md +48 -5
  119. package/docs/real-execution-backends.7.md +4 -0
  120. package/docs/release-and-migration.7.md +5 -1
  121. package/docs/release-tooling.7.md +4 -0
  122. package/docs/routines.md +4 -4
  123. package/docs/run-registry-control-plane.7.md +23 -19
  124. package/docs/run-retention-reclamation.7.md +4 -0
  125. package/docs/scheduled-tasks.md +14 -14
  126. package/docs/security-trust-hardening.7.md +43 -13
  127. package/docs/state-explosion-management.7.md +14 -10
  128. package/docs/team-collaboration.7.md +4 -0
  129. package/docs/trust-audit-anchor.7.md +71 -0
  130. package/docs/unix-principles.md +3 -1
  131. package/docs/verifier-gated-commit.7.md +1 -1
  132. package/docs/web-desktop-workbench.7.md +4 -0
  133. package/docs/workflow-app-framework.7.md +13 -13
  134. package/manifest/plugin.manifest.json +1 -1
  135. package/package.json +4 -2
  136. package/scripts/agents/claude-p-agent.js +2 -2
  137. package/scripts/block-unapproved-tag.sh +23 -2
  138. package/scripts/bump-version.js +24 -2
  139. package/scripts/canonical-apps.js +4 -4
  140. package/scripts/children/batch-delegate-child.js +52 -2
  141. package/scripts/dogfood-release.js +1 -1
  142. package/scripts/fake-date-for-reproduction.js +44 -0
  143. package/scripts/golden-path.js +4 -4
  144. package/scripts/purity-baseline.json +71 -0
  145. package/scripts/purity-gate.js +239 -0
  146. package/scripts/release-check.js +8 -1
  147. package/scripts/release-flow.js +57 -1
  148. package/scripts/verdict-keygen.js +83 -0
  149. package/scripts/verify-bump-reproduction.sh +148 -0
  150. package/scripts/verify-verdict-signature.js +61 -0
  151. package/scripts/version-sync-check.js +33 -12
  152. package/skills/cool-workflow/SKILL.md +9 -9
  153. package/skills/cool-workflow/references/commands.md +89 -88
  154. package/ui/workbench/app.css +37 -1
  155. package/ui/workbench/app.js +124 -6
  156. package/workflows/README.md +19 -0
@@ -20,7 +20,7 @@ const repoRoot = path.resolve(pluginRoot, "..", "..");
20
20
  // CI checks out HEAD, so HEAD === the tree it is releasing.
21
21
  //
22
22
  // Fallback to the filesystem only when we cannot read from HEAD: not a git work
23
- // tree, or the path is not tracked at HEAD (e.g. the gitignored package-lock).
23
+ // tree, or the path is not tracked at HEAD.
24
24
  // node + git only — no ripgrep (CI portability rule).
25
25
  const insideGitWorkTree = (() => {
26
26
  const r = spawnSync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: repoRoot, encoding: "utf8" });
@@ -36,7 +36,7 @@ function readReleaseSource(relativePath) {
36
36
  maxBuffer: 1024 * 1024 * 32
37
37
  });
38
38
  if (r.status === 0) return { text: r.stdout, exists: true, fromHead: true };
39
- // Not tracked at HEAD — fall through to the working tree (e.g. package-lock).
39
+ // Not tracked at HEAD — fall through to the working tree.
40
40
  }
41
41
  const abs = path.join(repoRoot, relativePath);
42
42
  if (!fs.existsSync(abs)) return { text: null, exists: false, fromHead: false };
@@ -56,9 +56,14 @@ const canonicalApps = CANONICAL_APP_IDS;
56
56
  function main() {
57
57
  const checks = [];
58
58
  checkJson("plugins/cool-workflow/package.json", "version", VERSION, checks);
59
- // package-lock.json is a gitignored install artifact (the documented install
60
- // uses `npm install --no-package-lock`), so only validate it when present.
59
+ // package-lock.json is tracked now, but the documented install still works
60
+ // without it (`npm install --no-package-lock`), so only validate it when
61
+ // present. Check BOTH version fields: the top-level one and the root-package
62
+ // entry packages[""].version — the second one is the field npm keeps in step
63
+ // with package.json on `npm install`, and it is the one that went stale
64
+ // (0.1.97) through the v0.2.0/v0.2.1 cuts while only the first was checked.
61
65
  checkJsonIfPresent("plugins/cool-workflow/package-lock.json", "version", VERSION, checks);
66
+ checkNestedJsonIfPresent("plugins/cool-workflow/package-lock.json", ["packages", "", "version"], VERSION, checks);
62
67
  checkJson("plugins/cool-workflow/.codex-plugin/plugin.json", "version", VERSION, checks);
63
68
  checkJson("plugins/cool-workflow/server.json", "version", VERSION, checks);
64
69
  checkNestedJson("plugins/cool-workflow/server.json", ["packages", 0, "version"], VERSION, checks);
@@ -160,7 +165,7 @@ function main() {
160
165
  checkIncludes("plugins/cool-workflow/docs/run-retention-reclamation.7.md", VERSION, checks);
161
166
  checkIncludes("plugins/cool-workflow/docs/index.md", "run-retention-reclamation.7.md", checks);
162
167
  checkIncludes("plugins/cool-workflow/test/run-retention-reclamation-smoke.js", "run-retention-reclamation-smoke", checks);
163
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "gc.plan", checks);
168
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/scheduling-registry.ts", "gc.plan", checks);
164
169
  checkIncludes("plugins/cool-workflow/docs/durable-state-and-locking.7.md", "Durable State & Locking", checks);
165
170
  checkIncludes("plugins/cool-workflow/docs/durable-state-and-locking.7.md", VERSION, checks);
166
171
  checkIncludes("plugins/cool-workflow/docs/index.md", "durable-state-and-locking.7.md", checks);
@@ -168,33 +173,37 @@ function main() {
168
173
  checkIncludes("plugins/cool-workflow/src/shell/fs-atomic.ts", "withFileLock", checks);
169
174
  checkIncludes("plugins/cool-workflow/src/shell/drive.ts", "driveStep", checks);
170
175
  checkIncludes("plugins/cool-workflow/dist/shell/drive.js", "driveStep", checks);
171
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "run.drive", checks);
176
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/pipeline.ts", "run.drive", checks);
172
177
  checkIncludes("plugins/cool-workflow/src/shell/collaboration-io.ts", "deriveReviewState", checks);
173
178
  checkIncludes("plugins/cool-workflow/dist/shell/collaboration-io.js", "deriveReviewState", checks);
174
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "review.status", checks);
179
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/multi-agent.ts", "review.status", checks);
175
180
  checkIncludes("plugins/cool-workflow/src/shell/observability.ts", "deriveMetricsReport", checks);
176
181
  checkIncludes("plugins/cool-workflow/dist/shell/observability.js", "deriveMetricsReport", checks);
177
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "metrics.show", checks);
182
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/reporting.ts", "metrics.show", checks);
178
183
  checkIncludes("plugins/cool-workflow/manifest/pricing.policy.json", "schemaVersion", checks);
179
184
  checkIncludes("plugins/cool-workflow/src/shell/workbench.ts", "buildWorkbenchRunView", checks);
180
185
  checkIncludes("plugins/cool-workflow/dist/shell/workbench.js", "buildWorkbenchRunView", checks);
181
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "workbench.view", checks);
186
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/reporting.ts", "workbench.view", checks);
182
187
  checkIncludes("plugins/cool-workflow/src/shell/execution-backend/registry.ts", "ExecutionBackend", checks);
183
188
  checkIncludes("plugins/cool-workflow/dist/shell/execution-backend/registry.js", "ExecutionBackend", checks);
184
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "backend.list", checks);
189
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/exec-backend.ts", "backend.list", checks);
185
190
  checkIncludes("plugins/cool-workflow/src/shell/run-registry-io.ts", "RunRegistry", checks);
186
191
  checkIncludes("plugins/cool-workflow/dist/shell/run-registry-io.js", "RunRegistry", checks);
187
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "registry.refresh", checks);
192
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/scheduling-registry.ts", "registry.refresh", checks);
188
193
  checkIncludes("plugins/cool-workflow/package.json", "parity:check", checks);
189
194
  checkIncludes("plugins/cool-workflow/scripts/parity-check.js", "buildParityReport", checks);
190
195
  checkIncludes("plugins/cool-workflow/test/cli-mcp-parity-smoke.js", "cli-mcp-parity-smoke", checks);
191
- checkIncludes("plugins/cool-workflow/src/core/capability-table.ts", "export const REGISTRY", checks);
196
+ checkIncludes("plugins/cool-workflow/src/wiring/capability-table/registry-core.ts", "export const REGISTRY", checks);
192
197
  checkIncludes("plugins/cool-workflow/src/shell/pipeline-cli.ts", "planSummary", checks);
193
198
  checkIncludes("plugins/cool-workflow/dist/core/capability-table.js", "REGISTRY", checks);
194
199
  checkIncludes("plugins/cool-workflow/docs/multi-agent-runtime-core.7.md", "Multi-Agent Runtime Core", checks);
195
200
  checkIncludes("plugins/cool-workflow/docs/dogfood-one-real-repo.7.md", "Dogfood One Real Repo", checks);
196
201
  checkIncludes("plugins/cool-workflow/docs/getting-started.md", "npm run release:check", checks);
197
202
  checkIncludes("plugins/cool-workflow/package.json", "eval:replay", checks);
203
+ checkIncludes("plugins/cool-workflow/docs/trust-audit-anchor.7.md", "Trust Audit Anchor", checks);
204
+ checkIncludes("plugins/cool-workflow/docs/trust-audit-anchor.7.md", VERSION, checks);
205
+ checkIncludes("plugins/cool-workflow/docs/index.md", "trust-audit-anchor.7.md", checks);
206
+ checkIncludes("plugins/cool-workflow/test/trust-audit-anchor-smoke.js", "trust-audit-anchor-smoke", checks);
198
207
  checkIncludes("plugins/cool-workflow/docs/release-and-migration.7.md", VERSION, checks);
199
208
  checkIncludes("CHANGELOG.md", `## ${VERSION}`, checks);
200
209
  checkIncludes("RELEASE.md", VERSION, checks);
@@ -227,6 +236,18 @@ function checkNestedJson(relativePath, keyPath, expected, checks) {
227
236
  checks.push({ path: relativePath, key: keyPath.join("."), value });
228
237
  }
229
238
 
239
+ function checkNestedJsonIfPresent(relativePath, keyPath, expected, checks) {
240
+ const src = readReleaseSource(relativePath);
241
+ if (!src.exists) {
242
+ checks.push({ path: relativePath, key: keyPath.join("."), skipped: "absent" });
243
+ return;
244
+ }
245
+ let value = JSON.parse(src.text);
246
+ for (const key of keyPath) value = value?.[key];
247
+ assert.equal(value, expected, `${relativePath}.${keyPath.join(".")} must be ${expected}`);
248
+ checks.push({ path: relativePath, key: keyPath.join("."), value });
249
+ }
250
+
230
251
  function checkJsonIfPresent(relativePath, key, expected, checks) {
231
252
  const src = readReleaseSource(relativePath);
232
253
  if (!src.exists) {
@@ -62,16 +62,16 @@ Use this loop to explain workflow progress when reporting status.
62
62
  ## Operating Loop
63
63
 
64
64
  1. Pick or create a workflow.
65
- 2. `node scripts/cw.js plan <workflow-id> ...` from the plugin root (or the
65
+ 2. `cw plan <workflow-id> ...` from the plugin root (or the
66
66
  absolute plugin script path).
67
- 3. `node scripts/cw.js dispatch <run-id> --limit N` to create a dispatch
67
+ 3. `cw dispatch <run-id> --limit N` to create a dispatch
68
68
  manifest for the current phase. Add `--sandbox <profile-id>` when an explicit
69
69
  worker policy profile is needed.
70
70
  4. If — and only if — the user explicitly asked for agents, spawn one subagent
71
71
  per dispatched task with disjoint scopes.
72
72
  5. Save each subagent summary to `.cw/runs/<run-id>/results/<task-id>.md`.
73
- 6. `node scripts/cw.js result <run-id> <task-id> <result-file>`.
74
- 7. When all required work is complete, `node scripts/cw.js report <run-id>`.
73
+ 6. `cw result <run-id> <task-id> <result-file>`.
74
+ 7. When all required work is complete, `cw report <run-id>`.
75
75
  8. Synthesize the final user-facing answer from the report and verified
76
76
  evidence.
77
77
 
@@ -114,11 +114,11 @@ report chain. See `references/commands.md` for the exact invocations.
114
114
  ## Essential Commands
115
115
 
116
116
  ```bash
117
- node scripts/cw.js list
118
- node scripts/cw.js plan architecture-review --repo /path/to/repo --question "Is this architecture sound?"
119
- node scripts/cw.js dispatch <run-id> --limit 6
120
- node scripts/cw.js result <run-id> <task-id> /path/to/result.md
121
- node scripts/cw.js report <run-id> --show
117
+ cw list
118
+ cw plan architecture-review --repo /path/to/repo --question "Is this architecture sound?"
119
+ cw dispatch <run-id> --limit 6
120
+ cw result <run-id> <task-id> /path/to/result.md
121
+ cw report <run-id> --show
122
122
  ```
123
123
 
124
124
  When working in this repository, the plugin root is `plugins/cool-workflow`.
@@ -26,19 +26,20 @@ absolute plugin script path. Run data is written to `.cw/runs/<run-id>/` under
26
26
  ## Discovery & apps
27
27
 
28
28
  ```bash
29
- node scripts/cw.js list
30
- node scripts/cw.js app list
31
- node scripts/cw.js app show architecture-review
32
- node scripts/cw.js app show pr-review-fix-ci
33
- node scripts/cw.js app show release-cut
34
- node scripts/cw.js app show research-synthesis
35
- node scripts/cw.js app validate apps/architecture-review/app.json
36
- node scripts/cw.js app show workflow-app-framework-demo
37
- node scripts/cw.js app validate apps/workflow-app-framework-demo/app.json
38
- node scripts/cw.js app validate end-to-end-golden-path
39
- node scripts/cw.js app package workflow-app-framework-demo
40
- node scripts/cw.js app init my-app --title "My App"
41
- node scripts/cw.js init my-workflow --title "My Workflow"
29
+ cw list
30
+ cw search architecture
31
+ cw app list
32
+ cw app show architecture-review
33
+ cw app show pr-review-fix-ci
34
+ cw app show release-cut
35
+ cw app show research-synthesis
36
+ cw app validate apps/architecture-review/app.json
37
+ cw app show workflow-app-framework-demo
38
+ cw app validate apps/workflow-app-framework-demo/app.json
39
+ cw app validate end-to-end-golden-path
40
+ cw app package workflow-app-framework-demo
41
+ cw app init my-app --title "My App"
42
+ cw init my-workflow --title "My Workflow"
42
43
  ```
43
44
 
44
45
  The canonical app ids are `architecture-review`, `pr-review-fix-ci`,
@@ -62,16 +63,16 @@ harness; the reviewer is delegated via `CW_AGENT_COMMAND`/`CW_AGENT_ENDPOINT`
62
63
  ## Plan / dispatch / result / report
63
64
 
64
65
  ```bash
65
- node scripts/cw.js plan architecture-review --repo /path/to/repo --question "Is this architecture sound?"
66
- node scripts/cw.js status <run-id>
67
- node scripts/cw.js status <run-id> --json
68
- node scripts/cw.js graph <run-id>
69
- node scripts/cw.js graph <run-id> --json
70
- node scripts/cw.js dispatch <run-id> --limit 6
71
- node scripts/cw.js dispatch <run-id> --sandbox readonly
72
- node scripts/cw.js result <run-id> <task-id> /path/to/result.md
73
- node scripts/cw.js report <run-id>
74
- node scripts/cw.js report <run-id> --show
66
+ cw plan architecture-review --repo /path/to/repo --question "Is this architecture sound?"
67
+ cw status <run-id>
68
+ cw status <run-id> --json
69
+ cw graph <run-id>
70
+ cw graph <run-id> --json
71
+ cw dispatch <run-id> --limit 6
72
+ cw dispatch <run-id> --sandbox readonly
73
+ cw result <run-id> <task-id> /path/to/result.md
74
+ cw report <run-id>
75
+ cw report <run-id> --show
75
76
  ```
76
77
 
77
78
  Operator UX is human-readable by default for `status`, `graph`, report
@@ -87,12 +88,12 @@ role, group, fanout/fanin, blackboard, coordinator, candidate, commit, and audit
87
88
  records — deterministic recipes, not hidden autonomous coordination.
88
89
 
89
90
  ```bash
90
- node scripts/cw.js topology list
91
- node scripts/cw.js topology show map-reduce
92
- node scripts/cw.js topology validate map-reduce
93
- node scripts/cw.js topology apply <run-id> map-reduce --task task-id --mapper-count 2
94
- node scripts/cw.js topology summary <run-id>
95
- node scripts/cw.js topology graph <run-id>
91
+ cw topology list
92
+ cw topology show map-reduce
93
+ cw topology validate map-reduce
94
+ cw topology apply <run-id> map-reduce --task task-id --mapper-count 2
95
+ cw topology summary <run-id>
96
+ cw topology graph <run-id>
96
97
  ```
97
98
 
98
99
  ## Multi-agent host surface
@@ -103,22 +104,22 @@ plumbing. It wraps the topology, multi-agent, blackboard, candidate, commit, and
103
104
  audit primitives; it does not replace them.
104
105
 
105
106
  ```bash
106
- node scripts/cw.js multi-agent run <run-id> --topology judge-panel --task task-id
107
- node scripts/cw.js multi-agent status <run-id>
108
- node scripts/cw.js multi-agent step <run-id> --sandbox readonly
109
- node scripts/cw.js multi-agent blackboard <run-id> summary
110
- node scripts/cw.js multi-agent score <run-id> candidate-id --criterion correctness=1 --evidence ref
111
- node scripts/cw.js multi-agent select <run-id> candidate-id --reason "verified winner"
107
+ cw multi-agent run <run-id> --topology judge-panel --task task-id
108
+ cw multi-agent status <run-id>
109
+ cw multi-agent step <run-id> --sandbox readonly
110
+ cw multi-agent blackboard <run-id> summary
111
+ cw multi-agent score <run-id> candidate-id --criterion correctness=1 --evidence ref
112
+ cw multi-agent select <run-id> candidate-id --reason "verified winner"
112
113
  ```
113
114
 
114
115
  Operator views (who depends on whom, who is blocked, which evidence was adopted):
115
116
 
116
117
  ```bash
117
- node scripts/cw.js multi-agent summary <run-id>
118
- node scripts/cw.js multi-agent graph <run-id>
119
- node scripts/cw.js multi-agent dependencies <run-id>
120
- node scripts/cw.js multi-agent failures <run-id>
121
- node scripts/cw.js multi-agent evidence <run-id>
118
+ cw multi-agent summary <run-id>
119
+ cw multi-agent graph <run-id>
120
+ cw multi-agent dependencies <run-id>
121
+ cw multi-agent failures <run-id>
122
+ cw multi-agent evidence <run-id>
122
123
  ```
123
124
 
124
125
  State Explosion Management — when a run grows too large to read, use derived,
@@ -126,11 +127,11 @@ provenance-backed digests (they never delete raw records and fail closed when
126
127
  stale; every synthetic node carries source ids and an expansion command):
127
128
 
128
129
  ```bash
129
- node scripts/cw.js summary refresh <run-id>
130
- node scripts/cw.js summary show <run-id>
131
- node scripts/cw.js blackboard summarize <run-id>
132
- node scripts/cw.js multi-agent summarize <run-id>
133
- node scripts/cw.js multi-agent graph <run-id> --view compact|critical-path|failures|... [--focus <id>] [--depth <n>]
130
+ cw summary refresh <run-id>
131
+ cw summary show <run-id>
132
+ cw blackboard summarize <run-id>
133
+ cw multi-agent summarize <run-id>
134
+ cw multi-agent graph <run-id> --view compact|critical-path|failures|... [--focus <id>] [--depth <n>]
134
135
  ```
135
136
 
136
137
  Trust / Policy / Audit — inspect role authority, message provenance, blackboard
@@ -138,11 +139,11 @@ write decisions, judge rationale, panel decisions, and why a result is trusted
138
139
  (missing policy/evidence/provenance/rationale fail closed):
139
140
 
140
141
  ```bash
141
- node scripts/cw.js audit multi-agent <run-id>
142
- node scripts/cw.js audit policy <run-id>
143
- node scripts/cw.js audit role <run-id>
144
- node scripts/cw.js audit blackboard <run-id>
145
- node scripts/cw.js audit judge <run-id>
142
+ cw audit multi-agent <run-id>
143
+ cw audit policy <run-id>
144
+ cw audit role <run-id>
145
+ cw audit blackboard <run-id>
146
+ cw audit judge <run-id>
146
147
  ```
147
148
 
148
149
  ## Multi-agent low-level state
@@ -154,12 +155,12 @@ transitions, duplicate memberships, ambiguous dispatch attachment, and missing
154
155
  fanin evidence fail closed.
155
156
 
156
157
  ```bash
157
- node scripts/cw.js multi-agent run <run-id> --id ma --objective "coordinated work"
158
- node scripts/cw.js multi-agent role <run-id> role --multi-agent-run ma --responsibility "do work" --required-evidence "result evidence"
159
- node scripts/cw.js multi-agent group <run-id> group --multi-agent-run ma --task task-id
160
- node scripts/cw.js multi-agent fanout <run-id> fanout --group group --reason "split work" --role role --task task-id
161
- node scripts/cw.js dispatch <run-id> --multi-agent-run ma --multi-agent-group group --multi-agent-role role --multi-agent-fanout fanout
162
- node scripts/cw.js multi-agent fanin <run-id> fanin --group group --fanout fanout --required-role role
158
+ cw multi-agent run <run-id> --id ma --objective "coordinated work"
159
+ cw multi-agent role <run-id> role --multi-agent-run ma --responsibility "do work" --required-evidence "result evidence"
160
+ cw multi-agent group <run-id> group --multi-agent-run ma --task task-id
161
+ cw multi-agent fanout <run-id> fanout --group group --reason "split work" --role role --task task-id
162
+ cw dispatch <run-id> --multi-agent-run ma --multi-agent-group group --multi-agent-role role --multi-agent-fanout fanout
163
+ cw multi-agent fanin <run-id> fanin --group group --fanout fanout --required-role role
163
164
  ```
164
165
 
165
166
  ## Eval & replay
@@ -168,12 +169,12 @@ Use when a topology-backed multi-agent run needs release-gate evidence.
168
169
  Artifacts live under `.cw/evals/<suite-id>/` as plain JSON plus `report.md`.
169
170
 
170
171
  ```bash
171
- node scripts/cw.js eval snapshot <run-id> --id suite-id
172
- node scripts/cw.js eval replay .cw/evals/suite-id/snapshot.json
173
- node scripts/cw.js eval compare .cw/evals/suite-id/snapshot.json .cw/evals/suite-id/replay-run.json
174
- node scripts/cw.js eval score .cw/evals/suite-id/replay-run.json
175
- node scripts/cw.js eval gate .cw/evals/suite-id
176
- node scripts/cw.js eval report .cw/evals/suite-id/replay-run.json
172
+ cw eval snapshot <run-id> --id suite-id
173
+ cw eval replay .cw/evals/suite-id/snapshot.json
174
+ cw eval compare .cw/evals/suite-id/snapshot.json .cw/evals/suite-id/replay-run.json
175
+ cw eval score .cw/evals/suite-id/replay-run.json
176
+ cw eval gate .cw/evals/suite-id
177
+ cw eval report .cw/evals/suite-id/replay-run.json
177
178
  ```
178
179
 
179
180
  ## Blackboard & coordinator
@@ -183,14 +184,14 @@ context frames, artifact refs, snapshots, and coordinator decisions under
183
184
  `.cw/runs/<run-id>/blackboard/`.
184
185
 
185
186
  ```bash
186
- node scripts/cw.js blackboard summary <run-id>
187
- node scripts/cw.js blackboard topic create <run-id> --id topic --title "Shared context"
188
- node scripts/cw.js blackboard message post <run-id> --topic topic --body "message"
189
- node scripts/cw.js blackboard context put <run-id> --topic topic --kind fact --key finding --value "evidence-backed fact"
190
- node scripts/cw.js blackboard artifact add <run-id> --topic topic --path /path/to/result.md --kind worker-result
191
- node scripts/cw.js blackboard snapshot <run-id>
192
- node scripts/cw.js coordinator summary <run-id>
193
- node scripts/cw.js coordinator decision <run-id> --kind conflict-resolution --outcome accepted --reason "evidence supports this"
187
+ cw blackboard summary <run-id>
188
+ cw blackboard topic create <run-id> --id topic --title "Shared context"
189
+ cw blackboard message post <run-id> --topic topic --body "message"
190
+ cw blackboard context put <run-id> --topic topic --kind fact --key finding --value "evidence-backed fact"
191
+ cw blackboard artifact add <run-id> --topic topic --path /path/to/result.md --kind worker-result
192
+ cw blackboard snapshot <run-id>
193
+ cw coordinator summary <run-id>
194
+ cw coordinator decision <run-id> --kind conflict-resolution --outcome accepted --reason "evidence supports this"
194
195
  ```
195
196
 
196
197
  ## Sandbox profiles
@@ -201,10 +202,10 @@ CW enforces profile validation and worker result acceptance; the agent host
201
202
  enforces OS/process/network/environment controls.
202
203
 
203
204
  ```bash
204
- node scripts/cw.js sandbox list
205
- node scripts/cw.js sandbox show readonly
206
- node scripts/cw.js sandbox validate ./site-sandbox.json
207
- node scripts/cw.js worker manifest <run-id> <worker-id>
205
+ cw sandbox list
206
+ cw sandbox show readonly
207
+ cw sandbox validate ./site-sandbox.json
208
+ cw worker manifest <run-id> <worker-id>
208
209
  ```
209
210
 
210
211
  ## Commit, state & summaries
@@ -214,14 +215,14 @@ dry-runs migration and normalization; newer unsupported schemas fail closed and
214
215
  unknown user data is preserved.
215
216
 
216
217
  ```bash
217
- node scripts/cw.js commit <run-id> --verifier <node-id> --reason "verified result"
218
- node scripts/cw.js commit <run-id> --selection <selection-id> --reason "verified winner"
219
- node scripts/cw.js commit <run-id> --allow-unverified-checkpoint --reason "manual checkpoint"
220
- node scripts/cw.js worker summary <run-id>
221
- node scripts/cw.js candidate summary <run-id>
222
- node scripts/cw.js feedback summary <run-id>
223
- node scripts/cw.js commit summary <run-id>
224
- node scripts/cw.js state check <run-id>
218
+ cw commit <run-id> --verifier <node-id> --reason "verified result"
219
+ cw commit <run-id> --selection <selection-id> --reason "verified winner"
220
+ cw commit <run-id> --allow-unverified-checkpoint --reason "manual checkpoint"
221
+ cw worker summary <run-id>
222
+ cw candidate summary <run-id>
223
+ cw feedback summary <run-id>
224
+ cw commit summary <run-id>
225
+ cw state check <run-id>
225
226
  ```
226
227
 
227
228
  ## Scheduling & routines
@@ -232,12 +233,12 @@ prompt is handled. `routine create`/`routine fire` handle API/GitHub trigger
232
233
  events.
233
234
 
234
235
  ```bash
235
- node scripts/cw.js loop --intervalMinutes 30 --prompt "Continue this workflow."
236
- node scripts/cw.js schedule create --kind loop --intervalMinutes 30 --prompt "Continue this workflow."
237
- node scripts/cw.js schedule due
238
- node scripts/cw.js schedule daemon --once
239
- node scripts/cw.js routine create --kind github --prompt "Handle this GitHub event."
240
- node scripts/cw.js routine fire github payload.json
236
+ cw loop --intervalMinutes 30 --prompt "Continue this workflow."
237
+ cw schedule create --kind loop --intervalMinutes 30 --prompt "Continue this workflow."
238
+ cw schedule due
239
+ cw schedule daemon --once
240
+ cw routine create --kind github --prompt "Handle this GitHub event."
241
+ cw routine fire github payload.json
241
242
  ```
242
243
 
243
244
  ## Release & maintenance npm scripts
@@ -12,6 +12,20 @@
12
12
  --absent: #d29922;
13
13
  --bad: #f85149;
14
14
  }
15
+ @media (prefers-color-scheme: light) {
16
+ :root {
17
+ --bg: #f6f7f9;
18
+ --panel: #ffffff;
19
+ --panel-2: #eef0f4;
20
+ --ink: #1b1f27;
21
+ --muted: #5b6472;
22
+ --line: #d7dce4;
23
+ --accent: #1a6fd6;
24
+ --present: #1a7f37;
25
+ --absent: #9a6700;
26
+ --bad: #cf222e;
27
+ }
28
+ }
15
29
  * { box-sizing: border-box; }
16
30
  body {
17
31
  margin: 0;
@@ -45,8 +59,17 @@ input[type="search"] {
45
59
  }
46
60
  .run-list li:hover { border-color: var(--accent); }
47
61
  .run-list li.active { border-color: var(--accent); background: var(--panel-2); }
48
- .run-list .rid { font-family: ui-monospace, monospace; font-size: 12px; }
62
+ .run-list .rid { font-family: ui-monospace, monospace; font-size: 12px; display: flex; align-items: center; gap: 6px; }
49
63
  .run-list .meta { color: var(--muted); font-size: 11px; margin-top: 2px; }
64
+ .status-dot {
65
+ display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none;
66
+ background: var(--muted);
67
+ }
68
+ .status-dot.running { background: var(--accent); }
69
+ .status-dot.completed { background: var(--present); }
70
+ .status-dot.queued, .status-dot.archived, .status-dot.reclaimed { background: var(--muted); }
71
+ .status-dot.blocked { background: var(--absent); }
72
+ .status-dot.failed { background: var(--bad); }
50
73
  .detail { overflow-y: auto; padding: 16px 20px; }
51
74
  .detail .empty { color: var(--muted); }
52
75
  .tabs { display: flex; gap: 6px; flex-wrap: wrap; border-bottom: 1px solid var(--line); padding-bottom: 8px; margin-bottom: 12px; }
@@ -74,3 +97,16 @@ pre.json {
74
97
  .kv { display: flex; gap: 16px; flex-wrap: wrap; padding: 8px 12px; font-size: 12px; color: var(--muted); }
75
98
  .kv b { color: var(--ink); font-weight: 600; }
76
99
  .err { color: var(--bad); }
100
+ .struct-block { padding: 10px 12px; border-top: 1px solid var(--line); }
101
+ .struct-block:first-child { border-top: none; }
102
+ .struct-block .struct-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 6px; }
103
+ .struct-table { width: 100%; border-collapse: collapse; font-size: 12px; }
104
+ .struct-table th, .struct-table td {
105
+ text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--line);
106
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace; vertical-align: top;
107
+ }
108
+ .struct-table th { color: var(--muted); font-weight: 400; }
109
+ .struct-edges { list-style: none; margin: 0; padding: 0; font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
110
+ .struct-edges li { padding: 3px 0; }
111
+ .struct-edges .arrow { color: var(--muted); padding: 0 6px; }
112
+ .struct-empty { color: var(--muted); font-size: 12px; }
@@ -62,20 +62,22 @@ async function loadIndex() {
62
62
  const reg = view.registry || {};
63
63
  const fresh = document.getElementById("registry-freshness");
64
64
  fresh.innerHTML = "";
65
- fresh.append("registry ", freshnessBadge(reg.freshness), ` · scope ${view.scope}`);
65
+ fresh.append("registry ", freshnessBadge(reg.freshness && reg.freshness.status), ` · scope ${view.scope}`);
66
66
  const records = (view.runs && view.runs.records) || [];
67
67
  if (!records.length) {
68
68
  list.appendChild(el("li", { class: "muted", text: "no runs indexed in this scope" }));
69
69
  return;
70
70
  }
71
71
  for (const record of records) {
72
+ const lifecycle = record.lifecycle || record.status || "";
72
73
  const li = el("li", { class: state.activeRunId === record.runId ? "active" : "" }, [
73
- el("div", { class: "rid", text: record.runId }),
74
+ el("div", { class: "rid" }, [
75
+ el("span", { class: `status-dot ${lifecycle}`, title: lifecycle || "unknown" }),
76
+ document.createTextNode(record.runId)
77
+ ]),
74
78
  el("div", {
75
79
  class: "meta",
76
- text: [record.appId || record.workflowId, record.lifecycle || record.status, record.repo]
77
- .filter(Boolean)
78
- .join(" · ")
80
+ text: [record.appId || record.workflowId, lifecycle, record.repo].filter(Boolean).join(" · ")
79
81
  })
80
82
  ]);
81
83
  li.addEventListener("click", () => selectRun(record.runId));
@@ -138,13 +140,129 @@ function renderPanel(name, panel) {
138
140
  card.appendChild(head);
139
141
  card.appendChild(el("div", { class: "kv" }, [el("span", { class: "src", text: panel.cli }), el("span", { class: "src", text: panel.mcp })]));
140
142
  if (panel.status === "present") {
141
- card.appendChild(el("pre", { class: "json", text: JSON.stringify(panel.data, null, 2) }));
143
+ card.appendChild(renderStructured(panel.data) || el("pre", { class: "json", text: JSON.stringify(panel.data, null, 2) }));
142
144
  } else {
143
145
  card.appendChild(el("div", { class: "absent-note", text: `absent — ${panel.error || "source unreadable"}` }));
144
146
  }
145
147
  return card;
146
148
  }
147
149
 
150
+ // Purely presentational shape-detection: recognizes the two payload shapes
151
+ // that recur across several capabilities (a nodes/edges graph, and one or
152
+ // more TrustAuditEvent[] arrays) and tables them instead of dumping raw
153
+ // JSON. Anything that doesn't match either shape falls back to the plain
154
+ // JSON dump in renderPanel — no per-capability special-casing.
155
+ function isNodeEdgeGraph(data) {
156
+ return !!data && Array.isArray(data.nodes) && Array.isArray(data.edges);
157
+ }
158
+
159
+ function isEventArray(value) {
160
+ return (
161
+ Array.isArray(value) &&
162
+ value.length > 0 &&
163
+ value.every((item) => item && typeof item === "object" && typeof item.kind === "string" && typeof item.decision === "string")
164
+ );
165
+ }
166
+
167
+ function renderStructured(data) {
168
+ if (isNodeEdgeGraph(data)) return renderGraph(data);
169
+ if (data && typeof data === "object" && !Array.isArray(data)) {
170
+ const eventKeys = Object.keys(data).filter((key) => isEventArray(data[key]));
171
+ if (eventKeys.length > 0) return renderEventGroups(data, eventKeys);
172
+ }
173
+ return null;
174
+ }
175
+
176
+ function renderGraph(data) {
177
+ const wrap = el("div");
178
+ const nodesBlock = el("div", { class: "struct-block" }, [el("div", { class: "struct-title", text: `nodes (${data.nodes.length})` })]);
179
+ if (data.nodes.length === 0) {
180
+ nodesBlock.appendChild(el("div", { class: "struct-empty", text: "none" }));
181
+ } else {
182
+ const table = el("table", { class: "struct-table" }, [
183
+ el("tr", {}, ["id", "kind", "status", "label"].map((h) => el("th", { text: h })))
184
+ ]);
185
+ for (const node of data.nodes) {
186
+ table.appendChild(
187
+ el("tr", {}, [
188
+ el("td", { text: node.id }),
189
+ el("td", { text: node.kind }),
190
+ el("td", { text: node.status }),
191
+ el("td", { text: node.label })
192
+ ])
193
+ );
194
+ }
195
+ nodesBlock.appendChild(table);
196
+ }
197
+ wrap.appendChild(nodesBlock);
198
+
199
+ const edgesBlock = el("div", { class: "struct-block" }, [el("div", { class: "struct-title", text: `edges (${data.edges.length})` })]);
200
+ if (data.edges.length === 0) {
201
+ edgesBlock.appendChild(el("div", { class: "struct-empty", text: "none" }));
202
+ } else {
203
+ const list = el("ul", { class: "struct-edges" });
204
+ for (const edge of data.edges) {
205
+ list.appendChild(
206
+ el("li", {}, [
207
+ document.createTextNode(edge.from),
208
+ el("span", { class: "arrow", text: edge.label ? `--${edge.label}-->` : "-->" }),
209
+ document.createTextNode(edge.to)
210
+ ])
211
+ );
212
+ }
213
+ edgesBlock.appendChild(list);
214
+ }
215
+ wrap.appendChild(edgesBlock);
216
+ return wrap;
217
+ }
218
+
219
+ function humanizeKey(key) {
220
+ return key.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
221
+ }
222
+
223
+ function renderEventGroups(data, confirmedEventKeys) {
224
+ // At least one sibling array on this object is confirmed TrustAuditEvent-
225
+ // shaped -- so its OTHER array fields that happen to be empty (e.g. a
226
+ // healthy `policyViolations: []`) are almost certainly the same family
227
+ // and read better as their own "(0)" table than buried in the raw
228
+ // "other fields" JSON below. An empty array can't self-identify by
229
+ // content, so this only widens the match within an already-confirmed
230
+ // object, never anywhere else.
231
+ const eventKeys = Object.keys(data).filter(
232
+ (key) => confirmedEventKeys.includes(key) || (Array.isArray(data[key]) && data[key].length === 0)
233
+ );
234
+ const wrap = el("div");
235
+ for (const key of eventKeys) {
236
+ const events = [...data[key]].sort((a, b) => String(a.createdAt || "").localeCompare(String(b.createdAt || "")));
237
+ const block = el("div", { class: "struct-block" }, [el("div", { class: "struct-title", text: `${humanizeKey(key)} (${events.length})` })]);
238
+ const table = el("table", { class: "struct-table" }, [
239
+ el("tr", {}, ["time", "kind", "decision", "source", "actor"].map((h) => el("th", { text: h })))
240
+ ]);
241
+ for (const event of events) {
242
+ table.appendChild(
243
+ el("tr", {}, [
244
+ el("td", { text: event.createdAt || "" }),
245
+ el("td", { text: event.kind || "" }),
246
+ el("td", { text: event.decision || "" }),
247
+ el("td", { text: event.source || "" }),
248
+ el("td", { text: event.actor || event.workerId || event.taskId || "" })
249
+ ])
250
+ );
251
+ }
252
+ block.appendChild(table);
253
+ wrap.appendChild(block);
254
+ }
255
+ const rest = Object.keys(data).filter((key) => !eventKeys.includes(key) && key !== "schemaVersion" && key !== "runId");
256
+ const restData = {};
257
+ for (const key of rest) restData[key] = data[key];
258
+ if (Object.keys(restData).length > 0) {
259
+ const block = el("div", { class: "struct-block" }, [el("div", { class: "struct-title", text: "other fields" })]);
260
+ block.appendChild(el("pre", { class: "json", text: JSON.stringify(restData, null, 2) }));
261
+ wrap.appendChild(block);
262
+ }
263
+ return wrap;
264
+ }
265
+
148
266
  document.getElementById("refresh").addEventListener("click", loadIndex);
149
267
  document.getElementById("filter").addEventListener("input", debounce(loadIndex, 200));
150
268