cool-workflow 0.1.78

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 (193) hide show
  1. package/.claude-plugin/plugin.json +20 -0
  2. package/.codex-plugin/mcp.json +10 -0
  3. package/.codex-plugin/plugin.json +38 -0
  4. package/.mcp.json +10 -0
  5. package/LICENSE +24 -0
  6. package/README.md +638 -0
  7. package/apps/architecture-review/app.json +51 -0
  8. package/apps/architecture-review/workflow.js +116 -0
  9. package/apps/end-to-end-golden-path/app.json +30 -0
  10. package/apps/end-to-end-golden-path/workflow.js +33 -0
  11. package/apps/pr-review-fix-ci/app.json +59 -0
  12. package/apps/pr-review-fix-ci/workflow.js +90 -0
  13. package/apps/release-cut/app.json +54 -0
  14. package/apps/release-cut/workflow.js +82 -0
  15. package/apps/research-synthesis/app.json +50 -0
  16. package/apps/research-synthesis/workflow.js +76 -0
  17. package/apps/workflow-app-framework-demo/app.json +29 -0
  18. package/apps/workflow-app-framework-demo/workflow.js +44 -0
  19. package/dist/agent-config.js +223 -0
  20. package/dist/candidate-scoring.js +715 -0
  21. package/dist/capability-core.js +630 -0
  22. package/dist/capability-dispatcher.js +86 -0
  23. package/dist/capability-registry.js +523 -0
  24. package/dist/cli.js +1276 -0
  25. package/dist/collaboration.js +727 -0
  26. package/dist/commit.js +570 -0
  27. package/dist/contract-migration.js +234 -0
  28. package/dist/coordinator.js +1163 -0
  29. package/dist/daemon.js +44 -0
  30. package/dist/dispatch.js +201 -0
  31. package/dist/drive.js +503 -0
  32. package/dist/error-feedback.js +415 -0
  33. package/dist/evidence-grounding.js +179 -0
  34. package/dist/evidence-reasoning.js +733 -0
  35. package/dist/execution-backend.js +1279 -0
  36. package/dist/harness.js +61 -0
  37. package/dist/mcp-server.js +1615 -0
  38. package/dist/multi-agent-eval.js +857 -0
  39. package/dist/multi-agent-host.js +764 -0
  40. package/dist/multi-agent-operator-ux.js +537 -0
  41. package/dist/multi-agent-trust.js +366 -0
  42. package/dist/multi-agent.js +1173 -0
  43. package/dist/node-snapshot.js +270 -0
  44. package/dist/observability.js +922 -0
  45. package/dist/operator-ux.js +971 -0
  46. package/dist/orchestrator/audit-operations.js +182 -0
  47. package/dist/orchestrator/candidate-operations.js +117 -0
  48. package/dist/orchestrator/cli-options.js +288 -0
  49. package/dist/orchestrator/collaboration-operations.js +86 -0
  50. package/dist/orchestrator/feedback-operations.js +81 -0
  51. package/dist/orchestrator/host-operations.js +78 -0
  52. package/dist/orchestrator/lifecycle-operations.js +462 -0
  53. package/dist/orchestrator/migration-operations.js +44 -0
  54. package/dist/orchestrator/multi-agent-operations.js +362 -0
  55. package/dist/orchestrator/report.js +369 -0
  56. package/dist/orchestrator/topology-operations.js +84 -0
  57. package/dist/orchestrator.js +874 -0
  58. package/dist/pipeline-contract.js +92 -0
  59. package/dist/pipeline-runner.js +285 -0
  60. package/dist/reclamation.js +882 -0
  61. package/dist/result-normalize.js +194 -0
  62. package/dist/run-export.js +64 -0
  63. package/dist/run-registry.js +1347 -0
  64. package/dist/run-state-schema.js +67 -0
  65. package/dist/sandbox-profile.js +471 -0
  66. package/dist/scheduler.js +266 -0
  67. package/dist/scheduling.js +184 -0
  68. package/dist/schema-validate.js +98 -0
  69. package/dist/state-explosion.js +1213 -0
  70. package/dist/state-migrations.js +463 -0
  71. package/dist/state-node.js +301 -0
  72. package/dist/state.js +308 -0
  73. package/dist/telemetry-attestation.js +156 -0
  74. package/dist/telemetry-ledger.js +145 -0
  75. package/dist/topology.js +527 -0
  76. package/dist/triggers.js +159 -0
  77. package/dist/trust-audit.js +475 -0
  78. package/dist/types/blackboard.js +2 -0
  79. package/dist/types/boundary.js +29 -0
  80. package/dist/types/candidate.js +2 -0
  81. package/dist/types/collaboration.js +2 -0
  82. package/dist/types/core.js +2 -0
  83. package/dist/types/drive.js +10 -0
  84. package/dist/types/error-feedback.js +2 -0
  85. package/dist/types/evidence-reasoning.js +2 -0
  86. package/dist/types/execution-backend.js +2 -0
  87. package/dist/types/multi-agent.js +2 -0
  88. package/dist/types/observability.js +2 -0
  89. package/dist/types/pipeline.js +2 -0
  90. package/dist/types/reclamation.js +8 -0
  91. package/dist/types/result.js +2 -0
  92. package/dist/types/run-registry.js +2 -0
  93. package/dist/types/run.js +2 -0
  94. package/dist/types/sandbox.js +2 -0
  95. package/dist/types/schedule.js +2 -0
  96. package/dist/types/state-node.js +2 -0
  97. package/dist/types/topology.js +2 -0
  98. package/dist/types/trust.js +2 -0
  99. package/dist/types/workbench.js +2 -0
  100. package/dist/types/worker.js +2 -0
  101. package/dist/types/workflow-app.js +2 -0
  102. package/dist/types.js +43 -0
  103. package/dist/verifier-registry.js +46 -0
  104. package/dist/verifier.js +78 -0
  105. package/dist/version.js +8 -0
  106. package/dist/workbench-host.js +172 -0
  107. package/dist/workbench.js +190 -0
  108. package/dist/worker-isolation.js +1028 -0
  109. package/dist/workflow-api.js +98 -0
  110. package/dist/workflow-app-framework.js +626 -0
  111. package/docs/agent-delegation-drive.7.md +190 -0
  112. package/docs/agent-framework.md +176 -0
  113. package/docs/candidate-scoring.7.md +106 -0
  114. package/docs/canonical-workflow-apps.7.md +137 -0
  115. package/docs/capability-topology-registry.7.md +168 -0
  116. package/docs/cli-mcp-parity.7.md +373 -0
  117. package/docs/contract-migration-tooling.7.md +123 -0
  118. package/docs/control-plane-scheduling.7.md +110 -0
  119. package/docs/coordinator-blackboard.7.md +183 -0
  120. package/docs/dogfood/architecture-review-cool-workflow.md +16 -0
  121. package/docs/dogfood-one-real-repo.7.md +168 -0
  122. package/docs/durable-state-and-locking.7.md +107 -0
  123. package/docs/end-to-end-golden-path.7.md +117 -0
  124. package/docs/error-feedback.7.md +153 -0
  125. package/docs/evidence-adoption-reasoning-chain.7.md +270 -0
  126. package/docs/execution-backends.7.md +300 -0
  127. package/docs/getting-started.md +99 -0
  128. package/docs/index.md +41 -0
  129. package/docs/mcp-app-surface.7.md +235 -0
  130. package/docs/multi-agent-cli-mcp-surface.7.md +265 -0
  131. package/docs/multi-agent-eval-replay-harness.7.md +302 -0
  132. package/docs/multi-agent-operator-ux.7.md +314 -0
  133. package/docs/multi-agent-runtime-core.7.md +231 -0
  134. package/docs/multi-agent-topologies.7.md +103 -0
  135. package/docs/multi-agent-trust-policy-audit.7.md +154 -0
  136. package/docs/node-snapshot-diff-replay.7.md +135 -0
  137. package/docs/observability-cost-accounting.7.md +194 -0
  138. package/docs/operator-ux.7.md +180 -0
  139. package/docs/pipeline-runner.7.md +136 -0
  140. package/docs/project-index.md +261 -0
  141. package/docs/real-execution-backends.7.md +142 -0
  142. package/docs/release-and-migration.7.md +280 -0
  143. package/docs/release-tooling.7.md +159 -0
  144. package/docs/routines.md +48 -0
  145. package/docs/run-registry-control-plane.7.md +312 -0
  146. package/docs/run-retention-reclamation.7.md +191 -0
  147. package/docs/sandbox-profiles.7.md +137 -0
  148. package/docs/scheduled-tasks.md +80 -0
  149. package/docs/security-trust-hardening.7.md +117 -0
  150. package/docs/state-explosion-management.7.md +264 -0
  151. package/docs/state-node.7.md +96 -0
  152. package/docs/team-collaboration.7.md +207 -0
  153. package/docs/unix-principles.md +192 -0
  154. package/docs/verifier-gated-commit.7.md +140 -0
  155. package/docs/web-desktop-workbench.7.md +215 -0
  156. package/docs/worker-isolation.7.md +167 -0
  157. package/docs/workflow-app-framework.7.md +274 -0
  158. package/manifest/README.md +43 -0
  159. package/manifest/plugin.manifest.json +316 -0
  160. package/manifest/pricing.policy.json +14 -0
  161. package/package.json +79 -0
  162. package/scripts/agents/claude-p-agent.js +104 -0
  163. package/scripts/agents/claude-p-agent.sh +9 -0
  164. package/scripts/agents/cw-attest-keygen.js +55 -0
  165. package/scripts/agents/cw-attest-wrap.js +143 -0
  166. package/scripts/block-unapproved-tag.sh +39 -0
  167. package/scripts/bump-version.js +249 -0
  168. package/scripts/canonical-apps.js +171 -0
  169. package/scripts/cw.js +4 -0
  170. package/scripts/dist-drift-check.js +79 -0
  171. package/scripts/dogfood-architecture-review.js +237 -0
  172. package/scripts/dogfood-release.js +624 -0
  173. package/scripts/forward-ref-docs.js +73 -0
  174. package/scripts/gen-manifests.js +232 -0
  175. package/scripts/golden-path.js +300 -0
  176. package/scripts/mcp-server.js +4 -0
  177. package/scripts/new-feature.js +121 -0
  178. package/scripts/parity-check.js +213 -0
  179. package/scripts/release-check.js +118 -0
  180. package/scripts/release-flow.js +272 -0
  181. package/scripts/release-gate.sh +85 -0
  182. package/scripts/sync-project-index.js +387 -0
  183. package/scripts/validate-run-state-schema.js +126 -0
  184. package/scripts/verify-container-selfref.js +64 -0
  185. package/scripts/version-sync-check.js +237 -0
  186. package/skills/cool-workflow/SKILL.md +162 -0
  187. package/skills/cool-workflow/references/commands.md +282 -0
  188. package/tsconfig.json +16 -0
  189. package/ui/workbench/app.css +76 -0
  190. package/ui/workbench/app.js +159 -0
  191. package/ui/workbench/index.html +32 -0
  192. package/workflows/architecture-review.workflow.js +84 -0
  193. package/workflows/research-synthesis.workflow.js +47 -0
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // dist-drift-check — fail closed if dist/ is not the exact output of building
5
+ // the current src/.
6
+ //
7
+ // Why this exists: dist/ is committed so the runtime is usable without a build
8
+ // step (see README "inspect the bundled runtime immediately"). That makes dist/
9
+ // a generated artifact living in source control, so it can silently drift from
10
+ // src/ when someone edits TypeScript and forgets to rebuild. CI rebuilds before
11
+ // testing, so the tests pass against a fresh build while the committed dist/
12
+ // stays stale — the drift is invisible. This is the same fail-closed drift
13
+ // discipline the vendor manifests already use (gen:manifests --check).
14
+ //
15
+ // Approach: snapshot dist/, rebuild, diff the snapshot against the rebuild. This
16
+ // is git-independent — it asks the only question that matters ("is the dist on
17
+ // disk the build of the src on disk?"), so it does NOT punish a consistent but
18
+ // uncommitted working tree the way a `git diff HEAD` would. Committed-vs-built
19
+ // drift is enforced separately by the porcelain step in ci.yml on a clean
20
+ // checkout. Portable: node + npm only.
21
+
22
+ const { spawnSync } = require("node:child_process");
23
+ const fs = require("node:fs");
24
+ const path = require("node:path");
25
+
26
+ const packageDir = path.resolve(__dirname, "..");
27
+ const distDir = path.join(packageDir, "dist");
28
+
29
+ function snapshot(dir) {
30
+ const files = new Map();
31
+ if (!fs.existsSync(dir)) return files;
32
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
33
+ const full = path.join(dir, entry.name);
34
+ if (entry.isDirectory()) {
35
+ for (const [rel, content] of snapshot(full)) files.set(path.join(entry.name, rel), content);
36
+ } else {
37
+ files.set(entry.name, fs.readFileSync(full, "utf8"));
38
+ }
39
+ }
40
+ return files;
41
+ }
42
+
43
+ function fail(message, detail) {
44
+ process.stderr.write(`dist drift check: ${message}\n`);
45
+ if (detail) process.stderr.write(`${detail}\n`);
46
+ process.exit(1);
47
+ }
48
+
49
+ // 1) Snapshot the dist/ that is on disk right now (i.e. what is committed).
50
+ const before = snapshot(distDir);
51
+
52
+ // 2) Rebuild from the current src/.
53
+ const build = spawnSync("npm", ["run", "build"], {
54
+ cwd: packageDir,
55
+ encoding: "utf8",
56
+ stdio: ["ignore", "pipe", "pipe"],
57
+ });
58
+ if (build.error) fail("build failed to start", build.error.message);
59
+ if (build.status !== 0) fail("build failed", `${build.stdout || ""}${build.stderr || ""}`);
60
+
61
+ // 3) Anything the build changed means the pre-build dist/ was stale.
62
+ const after = snapshot(distDir);
63
+ const drifted = [];
64
+ for (const [file, content] of after) {
65
+ if (!before.has(file)) drifted.push(`added: ${file}`);
66
+ else if (before.get(file) !== content) drifted.push(`changed: ${file}`);
67
+ }
68
+ for (const file of before.keys()) {
69
+ if (!after.has(file)) drifted.push(`removed: ${file}`);
70
+ }
71
+
72
+ if (drifted.length > 0) {
73
+ fail(
74
+ `dist/ is stale — ${drifted.length} file(s) differ from a fresh build of src/.`,
75
+ ["Rebuild and commit the output:", " npm run build && git add dist/", "", ...drifted.map((d) => ` ${d}`)].join("\n"),
76
+ );
77
+ }
78
+
79
+ process.stdout.write("dist drift check: dist/ matches a fresh build of src/.\n");
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // Dogfood: architecture-review driven END-TO-END by the agent backend (v0.1.38).
5
+ //
6
+ // TWO HALVES (mirrors dogfood-one-real-repo.7.md discipline):
7
+ // --smoke : CI-VERIFIABLE. A hermetic STUB agent (no live binary, no second
8
+ // repo, no network) drives the real architecture-review app to
9
+ // completion. Emits { ok, mode:"smoke", reportPath, auditSummaryPath,
10
+ // verdictAccepted, agentDelegationEvents }. Run under `npm test`.
11
+ // (default): MAINTAINER-RUN, OUT OF CI. A REAL configured agent (CW_AGENT_COMMAND
12
+ // / --agent-command, e.g. `claude -p` / `codex exec`) drives ONE real
13
+ // external repo (--repo) and writes a committed audited report +
14
+ // a docs/dogfood/architecture-review-<repo>.md provenance note. This
15
+ // depends on a live agent binary + a second repo, which CI cannot have.
16
+ //
17
+ // THE RED LINE: the model runs in the external agent's process. This script spawns
18
+ // the agent and records its attested output; it imports no model SDK and holds no
19
+ // API key.
20
+
21
+ const fs = require("node:fs");
22
+ const os = require("node:os");
23
+ const path = require("node:path");
24
+
25
+ const pluginRoot = path.resolve(__dirname, "..");
26
+ const { CoolWorkflowRunner } = require(path.join(pluginRoot, "dist/orchestrator.js"));
27
+ const { drive } = require(path.join(pluginRoot, "dist/drive.js"));
28
+ const { resolveAgentConfig } = require(path.join(pluginRoot, "dist/agent-config.js"));
29
+
30
+ const argv = process.argv.slice(2);
31
+ const flags = new Set(argv.filter((a) => a.startsWith("--")));
32
+ const json = flags.has("--json");
33
+ const smoke = flags.has("--smoke");
34
+
35
+ function argValue(name, fallback) {
36
+ const i = argv.indexOf(name);
37
+ return i >= 0 && i + 1 < argv.length ? argv[i + 1] : fallback;
38
+ }
39
+
40
+ // Deterministic injected now keeps the smoke reproducible (scheduling/backoff).
41
+ const FIXED_NOW = "2026-06-09T00:00:00.000Z";
42
+
43
+ function writeStubAgent(dir) {
44
+ const file = path.join(dir, "stub-agent.js");
45
+ // A vendor-neutral stub standing in for `claude -p` / `codex exec`: it reads the
46
+ // worker result path (argv[2]), writes a VALID cw:result with durable evidence,
47
+ // and reports a model + usage on stdout (the attested model, never CW_AGENT_MODEL).
48
+ fs.writeFileSync(
49
+ file,
50
+ [
51
+ 'const fs = require("fs");',
52
+ "const fence = String.fromCharCode(96).repeat(3);",
53
+ "const resultPath = process.argv[2];",
54
+ "const evidence = [process.cwd() + '/README.md:1'];",
55
+ 'const body = "# Worker Result\\n\\nStub agent synthesized this audited section.\\n\\n" + fence + "cw:result\\n" + JSON.stringify({ summary: "stub agent audited section", findings: [], evidence }) + "\\n" + fence + "\\n";',
56
+ "fs.writeFileSync(resultPath, body);",
57
+ 'process.stdout.write(JSON.stringify({ model: "stub-agent/architecture-review", usage: { input_tokens: 12, output_tokens: 8 } }));'
58
+ ].join("\n"),
59
+ "utf8"
60
+ );
61
+ return file;
62
+ }
63
+
64
+ function auditSummaryFor(runner, run) {
65
+ const audit = runner.auditSummary(run.id);
66
+ const byKind = audit.byKind || (audit.summary && audit.summary.byKind) || {};
67
+ const auditDir = path.join(run.paths.runDir, "audit");
68
+ fs.mkdirSync(auditDir, { recursive: true });
69
+ const auditSummaryPath = path.join(auditDir, "summary.json");
70
+ fs.writeFileSync(auditSummaryPath, `${JSON.stringify(audit, null, 2)}\n`, "utf8");
71
+ return { audit, byKind, auditSummaryPath };
72
+ }
73
+
74
+ function runSmoke() {
75
+ const work = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), "cw-dogfood-archreview-")));
76
+ fs.writeFileSync(path.join(work, "README.md"), "# smoke target repo\n", "utf8");
77
+ const stub = writeStubAgent(work);
78
+ const cwd0 = process.cwd();
79
+ process.chdir(work);
80
+ try {
81
+ // The run artifacts (report + audit summary) are LEFT IN PLACE under `work` so
82
+ // the gate can existsSync them — the caller cleans up `summary.workspace`.
83
+ const runner = new CoolWorkflowRunner({ pluginRoot });
84
+ const run = runner.plan("architecture-review", { repo: work, question: "Smoke: is the control plane sound?" });
85
+ const result = drive(runner, run.id, {
86
+ now: FIXED_NOW,
87
+ agentConfig: { schemaVersion: 1, command: process.execPath, args: [stub, "{{result}}"], model: "smoke-operator-pick", source: "flag" }
88
+ });
89
+ const final = runner.loadRun(run.id);
90
+ const { byKind, auditSummaryPath } = auditSummaryFor(runner, final);
91
+ const verdict = final.tasks.find((task) => /^verdict[:/]/i.test(task.id));
92
+ const verdictAccepted = Boolean(verdict && verdict.status === "completed");
93
+ const agentDelegationEvents = byKind["worker.agent-delegation"] || 0;
94
+ const reportedModels = Array.from(
95
+ new Set(
96
+ final.nodes
97
+ .filter((node) => node.kind === "result" && node.metadata && node.metadata.agentDelegation)
98
+ .map((node) => node.metadata.agentDelegation.model)
99
+ )
100
+ );
101
+ const ok =
102
+ result.status === "complete" &&
103
+ result.completedWorkers === result.plannedWorkers &&
104
+ verdictAccepted &&
105
+ agentDelegationEvents >= 1 &&
106
+ Boolean(result.commitId) &&
107
+ fs.existsSync(final.paths.report) &&
108
+ fs.existsSync(auditSummaryPath);
109
+ const summary = {
110
+ ok,
111
+ mode: "smoke",
112
+ runId: run.id,
113
+ workflowId: final.workflow.id,
114
+ workspace: work,
115
+ plannedWorkers: result.plannedWorkers,
116
+ completedWorkers: result.completedWorkers,
117
+ verdictAccepted,
118
+ agentDelegationEvents,
119
+ reportedModels,
120
+ commitId: result.commitId,
121
+ statePath: final.paths.state,
122
+ reportPath: final.paths.report,
123
+ auditSummaryPath
124
+ };
125
+ return summary;
126
+ } finally {
127
+ process.chdir(cwd0);
128
+ }
129
+ }
130
+
131
+ function runLive() {
132
+ const repo = argValue("--repo");
133
+ const question = argValue("--question", "Audit this repository's architecture and rank the real risks.");
134
+ if (!repo) throw new Error("live dogfood requires --repo <path-to-real-repo> (and a configured agent via CW_AGENT_COMMAND or --agent-command)");
135
+ const repoAbs = path.resolve(repo);
136
+ if (!fs.existsSync(repoAbs) || !fs.statSync(repoAbs).isDirectory()) {
137
+ throw new Error(`--repo is not an existing directory: ${repoAbs} (pass a real repository path, e.g. --repo "$(pwd)/../..")`);
138
+ }
139
+ const agentConfig = resolveAgentConfig({
140
+ agentCommand: argValue("--agent-command"),
141
+ agentEndpoint: argValue("--agent-endpoint"),
142
+ agentModel: argValue("--agent-model")
143
+ });
144
+ if (!agentConfig.command && !agentConfig.endpoint) {
145
+ throw new Error("live dogfood requires a configured agent: set CW_AGENT_COMMAND or pass --agent-command (a wrapper that reads {{input}} and writes {{result}} — see docs/agent-delegation-drive.7.md)");
146
+ }
147
+ const runner = new CoolWorkflowRunner({ pluginRoot });
148
+ const run = runner.plan("architecture-review", { repo: repoAbs, question });
149
+ // The run lives under the repo's .cw/ and every runner verb resolves a run from
150
+ // the process cwd, so drive WITH the repo as cwd (the agent also reads the repo).
151
+ const cwd0 = process.cwd();
152
+ let result;
153
+ let final;
154
+ let byKind;
155
+ let auditSummaryPath;
156
+ try {
157
+ if (repoAbs !== process.cwd()) process.chdir(repoAbs);
158
+ result = drive(runner, run.id, { now: argValue("--now"), agentConfig });
159
+ final = runner.loadRun(run.id);
160
+ ({ byKind, auditSummaryPath } = auditSummaryFor(runner, final));
161
+ } finally {
162
+ if (process.cwd() !== cwd0) process.chdir(cwd0);
163
+ }
164
+ const reportedModels = Array.from(
165
+ new Set(
166
+ final.nodes
167
+ .filter((node) => node.kind === "result" && node.metadata && node.metadata.agentDelegation)
168
+ .map((node) => node.metadata.agentDelegation.model)
169
+ )
170
+ );
171
+ // Maintainer/self-referential artifact: a committed file recording the repo name
172
+ // + the agent-reported model id (the proof, OUT of CI).
173
+ const repoName = path.basename(path.resolve(repo));
174
+ const provenanceDir = path.join(pluginRoot, "docs", "dogfood");
175
+ fs.mkdirSync(provenanceDir, { recursive: true });
176
+ const provenancePath = path.join(provenanceDir, `architecture-review-${repoName}.md`);
177
+ // The committed proof artifact: self-contained (CW version, date, agent-reported
178
+ // usage totals), so the note evidences WHICH pipeline completed with a REAL
179
+ // agent without needing the local run directory.
180
+ const cwVersion = JSON.parse(fs.readFileSync(path.join(pluginRoot, "package.json"), "utf8")).version;
181
+ const usageTotals = (final.workers || [])
182
+ .filter((worker) => worker.usage)
183
+ .reduce(
184
+ (acc, worker) => ({
185
+ workers: acc.workers + 1,
186
+ inputTokens: acc.inputTokens + (worker.usage.inputTokens || 0),
187
+ outputTokens: acc.outputTokens + (worker.usage.outputTokens || 0)
188
+ }),
189
+ { workers: 0, inputTokens: 0, outputTokens: 0 }
190
+ );
191
+ fs.writeFileSync(
192
+ provenancePath,
193
+ [
194
+ `# Dogfood: architecture-review --drive on ${repoName} (CW v${cwVersion})`,
195
+ "",
196
+ "Maintainer-run live proof (OUT of CI): a real external agent drove the whole",
197
+ "architecture-review workflow end-to-end with zero hand-written result.md. The",
198
+ "model ran in the agent's process; CW spawned it and recorded the attested",
199
+ "output. CW holds no API key and imports no model SDK.",
200
+ "",
201
+ `- Date: ${new Date().toISOString().slice(0, 10)}`,
202
+ `- Run: ${run.id}`,
203
+ `- Status: ${result.status}`,
204
+ `- Workers driven: ${result.completedWorkers}/${result.plannedWorkers} (zero hand-written result.md)`,
205
+ `- Agent-reported model(s): ${reportedModels.join(", ") || "unreported"} — sourced solely from the agent's own report, never CW_AGENT_MODEL`,
206
+ `- Agent-reported usage: ${usageTotals.workers}/${result.plannedWorkers} workers reported tokens (${usageTotals.inputTokens} in / ${usageTotals.outputTokens} out)`,
207
+ `- agent-delegation audit events: ${byKind["worker.agent-delegation"] || 0}`,
208
+ `- Commit: ${result.commitId || "none"}`,
209
+ `- Agent template: scripts/agents/claude-p-agent.js (read-only claude; the wrapper persists result.md and forwards model+usage)`,
210
+ ""
211
+ ].join("\n"),
212
+ "utf8"
213
+ );
214
+ return {
215
+ ok: result.status === "complete",
216
+ mode: "live",
217
+ runId: run.id,
218
+ repo: path.resolve(repo),
219
+ plannedWorkers: result.plannedWorkers,
220
+ completedWorkers: result.completedWorkers,
221
+ reportedModels,
222
+ commitId: result.commitId,
223
+ reportPath: final.paths.report,
224
+ auditSummaryPath,
225
+ provenancePath
226
+ };
227
+ }
228
+
229
+ function main() {
230
+ const summary = smoke ? runSmoke() : runLive();
231
+ if (json) process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
232
+ else process.stdout.write(`dogfood-architecture-review (${summary.mode}): ${summary.ok ? "ok" : "FAILED"} — ${summary.completedWorkers}/${summary.plannedWorkers} workers, commit ${summary.commitId || "none"}\n`);
233
+ if (!summary.ok) process.exitCode = 1;
234
+ return summary;
235
+ }
236
+
237
+ main();