cool-workflow 0.2.2 → 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 (136) 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 +11 -5
  10. package/dist/cli/entry.js +41 -1
  11. package/dist/cli/io.js +6 -2
  12. package/dist/cli/parseargv.js +1 -0
  13. package/dist/core/capability-data.js +1 -0
  14. package/dist/core/format/completion.js +68 -0
  15. package/dist/core/format/help.js +25 -6
  16. package/dist/core/format/safe-json.js +73 -0
  17. package/dist/core/format/state-explosion-text.js +1 -1
  18. package/dist/core/multi-agent/candidate-scoring.js +5 -1
  19. package/dist/core/multi-agent/collaboration.js +3 -3
  20. package/dist/core/multi-agent/coordinator.js +5 -5
  21. package/dist/core/multi-agent/runtime.js +4 -4
  22. package/dist/core/multi-agent/topology.js +3 -3
  23. package/dist/core/pipeline/dispatch.js +18 -4
  24. package/dist/core/pipeline/drive-decide.js +2 -1
  25. package/dist/core/state/migrations.js +16 -1
  26. package/dist/core/state/state-explosion/digest.js +13 -13
  27. package/dist/core/state/state-explosion/graph.js +17 -11
  28. package/dist/core/state/state-explosion/report.js +6 -6
  29. package/dist/core/util/numeric-flag.js +40 -0
  30. package/dist/core/version.js +1 -1
  31. package/dist/mcp/server.js +99 -11
  32. package/dist/shell/audit-cli.js +57 -25
  33. package/dist/shell/coordinator-io.js +73 -13
  34. package/dist/shell/dispatch.js +1 -1
  35. package/dist/shell/doctor.js +80 -1
  36. package/dist/shell/drive.js +243 -49
  37. package/dist/shell/eval-text.js +2 -2
  38. package/dist/shell/evidence-reasoning.js +4 -4
  39. package/dist/shell/execution-backend/agent.js +20 -1
  40. package/dist/shell/execution-backend/container.js +4 -1
  41. package/dist/shell/execution-backend/local.js +4 -1
  42. package/dist/shell/feedback-cli.js +6 -6
  43. package/dist/shell/fs-atomic.js +218 -29
  44. package/dist/shell/man-cli.js +6 -0
  45. package/dist/shell/metrics-cli.js +2 -1
  46. package/dist/shell/multi-agent-cli.js +367 -323
  47. package/dist/shell/multi-agent-host.js +9 -9
  48. package/dist/shell/multi-agent-operator-ux.js +80 -38
  49. package/dist/shell/node-store.js +10 -4
  50. package/dist/shell/observability.js +1 -1
  51. package/dist/shell/operator-ux-text.js +22 -22
  52. package/dist/shell/operator-ux.js +15 -14
  53. package/dist/shell/orchestrator.js +49 -38
  54. package/dist/shell/pipeline-cli.js +87 -40
  55. package/dist/shell/reclamation-io.js +14 -4
  56. package/dist/shell/registry-cli.js +19 -17
  57. package/dist/shell/remote-source.js +13 -8
  58. package/dist/shell/report-cli.js +45 -0
  59. package/dist/shell/report.js +2 -1
  60. package/dist/shell/run-registry-io.js +77 -19
  61. package/dist/shell/run-store.js +74 -2
  62. package/dist/shell/scheduling-io.js +12 -13
  63. package/dist/shell/state-cli.js +2 -7
  64. package/dist/shell/state-explosion-cli.js +17 -9
  65. package/dist/shell/topology-io.js +36 -5
  66. package/dist/shell/trust-audit.js +224 -22
  67. package/dist/shell/trust-policy-io.js +1 -1
  68. package/dist/shell/worker-cli.js +35 -31
  69. package/dist/wiring/capability-table/basics.js +33 -8
  70. package/dist/wiring/capability-table/exec-backend.js +20 -11
  71. package/dist/wiring/capability-table/multi-agent.js +172 -165
  72. package/dist/wiring/capability-table/parity.js +1 -0
  73. package/dist/wiring/capability-table/pipeline.js +54 -42
  74. package/dist/wiring/capability-table/registry-core.js +29 -10
  75. package/dist/wiring/capability-table/reporting.js +137 -96
  76. package/dist/wiring/capability-table/scheduling-registry.js +195 -161
  77. package/dist/wiring/capability-table/state.js +36 -28
  78. package/dist/wiring/capability-table/trust-ledger.js +46 -22
  79. package/dist/wiring/capability-table/workflow-apps.js +83 -68
  80. package/docs/agent-delegation-drive.7.md +2 -0
  81. package/docs/candidate-scoring.7.md +1 -1
  82. package/docs/canonical-workflow-apps.7.md +7 -7
  83. package/docs/cli-mcp-parity.7.md +8 -3
  84. package/docs/contract-migration-tooling.7.md +2 -0
  85. package/docs/control-plane-scheduling.7.md +2 -0
  86. package/docs/coordinator-blackboard.7.md +17 -17
  87. package/docs/dogfood-one-real-repo.7.md +11 -11
  88. package/docs/durable-state-and-locking.7.md +2 -0
  89. package/docs/end-to-end-golden-path.7.md +14 -14
  90. package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
  91. package/docs/execution-backends.7.md +2 -0
  92. package/docs/getting-started.md +37 -37
  93. package/docs/multi-agent-cli-mcp-surface.7.md +19 -17
  94. package/docs/multi-agent-eval-replay-harness.7.md +15 -13
  95. package/docs/multi-agent-operator-ux.7.md +21 -19
  96. package/docs/multi-agent-runtime-core.7.md +22 -22
  97. package/docs/multi-agent-topologies.7.md +6 -6
  98. package/docs/multi-agent-trust-policy-audit.7.md +11 -11
  99. package/docs/node-snapshot-diff-replay.7.md +2 -0
  100. package/docs/observability-cost-accounting.7.md +2 -0
  101. package/docs/operator-ux.7.md +34 -34
  102. package/docs/pipeline-runner.7.md +4 -4
  103. package/docs/project-index.md +27 -4
  104. package/docs/real-execution-backends.7.md +2 -0
  105. package/docs/release-and-migration.7.md +3 -1
  106. package/docs/release-tooling.7.md +2 -0
  107. package/docs/routines.md +4 -4
  108. package/docs/run-registry-control-plane.7.md +21 -19
  109. package/docs/run-retention-reclamation.7.md +2 -0
  110. package/docs/scheduled-tasks.md +14 -14
  111. package/docs/security-trust-hardening.7.md +15 -15
  112. package/docs/state-explosion-management.7.md +12 -10
  113. package/docs/team-collaboration.7.md +2 -0
  114. package/docs/trust-audit-anchor.7.md +2 -0
  115. package/docs/unix-principles.md +3 -1
  116. package/docs/verifier-gated-commit.7.md +1 -1
  117. package/docs/web-desktop-workbench.7.md +2 -0
  118. package/docs/workflow-app-framework.7.md +13 -13
  119. package/manifest/plugin.manifest.json +1 -1
  120. package/package.json +2 -2
  121. package/scripts/agents/claude-p-agent.js +2 -2
  122. package/scripts/block-unapproved-tag.sh +23 -2
  123. package/scripts/canonical-apps.js +4 -4
  124. package/scripts/children/batch-delegate-child.js +52 -2
  125. package/scripts/dogfood-release.js +1 -1
  126. package/scripts/fake-date-for-reproduction.js +44 -0
  127. package/scripts/golden-path.js +4 -4
  128. package/scripts/purity-baseline.json +3 -0
  129. package/scripts/release-flow.js +57 -1
  130. package/scripts/verdict-keygen.js +83 -0
  131. package/scripts/verify-bump-reproduction.sh +148 -0
  132. package/scripts/verify-verdict-signature.js +61 -0
  133. package/skills/cool-workflow/SKILL.md +9 -9
  134. package/skills/cool-workflow/references/commands.md +89 -88
  135. package/ui/workbench/app.css +37 -1
  136. package/ui/workbench/app.js +124 -6
@@ -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