cool-workflow 0.1.84 → 0.1.86

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 (63) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +47 -331
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/architecture-review-fast/workflow.js +2 -0
  7. package/apps/end-to-end-golden-path/app.json +1 -1
  8. package/apps/pr-review-fix-ci/app.json +1 -1
  9. package/apps/release-cut/app.json +1 -1
  10. package/apps/research-synthesis/app.json +1 -1
  11. package/dist/capability-core.js +220 -5
  12. package/dist/capability-registry.js +90 -51
  13. package/dist/cli/command-surface.js +47 -2
  14. package/dist/doctor.js +37 -1
  15. package/dist/mcp/tool-call.js +428 -0
  16. package/dist/mcp/tool-definitions.js +1027 -0
  17. package/dist/mcp-surface.js +5 -1416
  18. package/dist/onramp.js +421 -0
  19. package/dist/orchestrator.js +20 -15
  20. package/dist/run-export.js +139 -1
  21. package/dist/telemetry-demo.js +119 -0
  22. package/dist/types/report-bundle.js +6 -0
  23. package/dist/types.js +1 -0
  24. package/dist/version.js +1 -1
  25. package/dist/workbench-host.js +1 -8
  26. package/docs/agent-delegation-drive.7.md +23 -2
  27. package/docs/cli-mcp-parity.7.md +38 -7
  28. package/docs/contract-migration-tooling.7.md +4 -0
  29. package/docs/control-plane-scheduling.7.md +4 -0
  30. package/docs/dogfood-one-real-repo.7.md +9 -1
  31. package/docs/durable-state-and-locking.7.md +4 -0
  32. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  33. package/docs/execution-backends.7.md +4 -0
  34. package/docs/getting-started.md +40 -2
  35. package/docs/index.md +51 -37
  36. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  37. package/docs/multi-agent-eval-replay-harness.7.md +4 -0
  38. package/docs/multi-agent-operator-ux.7.md +4 -0
  39. package/docs/node-snapshot-diff-replay.7.md +4 -0
  40. package/docs/observability-cost-accounting.7.md +4 -0
  41. package/docs/project-index.md +23 -7
  42. package/docs/real-execution-backends.7.md +4 -0
  43. package/docs/release-and-migration.7.md +5 -1
  44. package/docs/release-history.md +342 -0
  45. package/docs/release-tooling.7.md +18 -0
  46. package/docs/report-verifiable-bundle.7.md +123 -0
  47. package/docs/run-registry-control-plane.7.md +4 -0
  48. package/docs/run-retention-reclamation.7.md +4 -0
  49. package/docs/state-explosion-management.7.md +4 -0
  50. package/docs/team-collaboration.7.md +4 -0
  51. package/docs/web-desktop-workbench.7.md +4 -0
  52. package/manifest/plugin.manifest.json +1 -1
  53. package/manifest/source-context-profiles.json +1 -1
  54. package/package.json +2 -1
  55. package/scripts/architecture-review-fast.js +44 -2
  56. package/scripts/canonical-apps.js +4 -4
  57. package/scripts/dogfood-release.js +55 -133
  58. package/scripts/golden-path.js +4 -4
  59. package/scripts/onramp-check.js +47 -0
  60. package/scripts/parity-check.js +740 -2
  61. package/scripts/release-check.js +2 -0
  62. package/scripts/source-context.js +31 -5
  63. package/scripts/version-sync-check.js +4 -2
@@ -83,7 +83,7 @@ const canonicalApps = [
83
83
  "--source",
84
84
  "plugins/cool-workflow/docs/workflow-app-framework.7.md",
85
85
  "--scope",
86
- "Cool Workflow v0.1.84",
86
+ "Cool Workflow v0.1.86",
87
87
  "--freshness",
88
88
  "as of release preparation"
89
89
  ]
@@ -117,14 +117,14 @@ function main() {
117
117
  assert.ok(summary, `${app.id} must appear in app list`);
118
118
  assert.equal(summary.sourceKind, "app-directory");
119
119
  assert.equal(summary.legacy, false);
120
- assert.equal(summary.version, "0.1.84");
120
+ assert.equal(summary.version, "0.1.86");
121
121
 
122
122
  const validation = runJson(["app", "validate", manifestPath]);
123
123
  assert.equal(validation.valid, true, `${app.id} manifest must validate`);
124
124
 
125
125
  const shown = runJson(["app", "show", app.id]);
126
126
  assert.equal(shown.app.id, app.id);
127
- assert.equal(shown.app.version, "0.1.84");
127
+ assert.equal(shown.app.version, "0.1.86");
128
128
  assert.ok(shown.app.metadata.canonical, `${app.id} must be marked canonical`);
129
129
  assert.ok(shown.app.sandboxProfiles.length > 0, `${app.id} must declare sandbox profiles`);
130
130
  assertTaskIdsUnique(shown);
@@ -135,7 +135,7 @@ function main() {
135
135
  const plan = runJson(["plan", app.id, ...app.args(workspace)]);
136
136
  const state = JSON.parse(fs.readFileSync(plan.statePath, "utf8"));
137
137
  assert.equal(state.workflow.app.id, app.id);
138
- assert.equal(state.workflow.app.version, "0.1.84");
138
+ assert.equal(state.workflow.app.version, "0.1.86");
139
139
  assert.equal(state.workflow.app.metadata.canonical, true);
140
140
  assert.ok(state.tasks.some((task) => task.requiresEvidence), `${app.id} plan must include evidence gates`);
141
141
  assert.ok(state.tasks.every((task) => task.sandboxProfileId), `${app.id} plan must include sandbox hints`);
@@ -4,8 +4,9 @@
4
4
  const { spawnSync } = require("node:child_process");
5
5
  const fs = require("node:fs");
6
6
  const path = require("node:path");
7
+ const { CoolWorkflowRunner } = require("../dist/orchestrator.js");
7
8
 
8
- const TARGET_VERSION = "0.1.84";
9
+ const TARGET_VERSION = "0.1.86";
9
10
  const PREVIOUS_VERSION = "0.1.31";
10
11
  const pluginRoot = path.resolve(__dirname, "..");
11
12
  const repoRoot = path.resolve(pluginRoot, "..", "..");
@@ -17,30 +18,22 @@ function main() {
17
18
  const dryRun = !options.execute;
18
19
  enforceReleaseActionGate(options, dryRun);
19
20
 
20
- const plan = cwJson(
21
- [
22
- "plan",
23
- "release-cut",
24
- "--repo",
25
- repoRoot,
26
- "--version",
27
- TARGET_VERSION,
28
- "--previousVersion",
29
- PREVIOUS_VERSION,
30
- "--releaseBranch",
31
- currentBranch(),
32
- "--dryRun",
33
- String(dryRun)
34
- ],
35
- repoRoot
36
- );
21
+ const runner = new CoolWorkflowRunner({ pluginRoot }).withBaseDir(repoRoot);
22
+ const plan = runner.plan("release-cut", {
23
+ repo: repoRoot,
24
+ version: TARGET_VERSION,
25
+ previousVersion: PREVIOUS_VERSION,
26
+ releaseBranch: currentBranch(),
27
+ dryRun: String(dryRun)
28
+ });
37
29
 
38
30
  const context = {
31
+ runner,
39
32
  options,
40
33
  dryRun,
41
- runId: plan.runId,
42
- reportPath: plan.reportPath,
43
- statePath: plan.statePath,
34
+ runId: plan.id,
35
+ reportPath: plan.paths.report,
36
+ statePath: plan.paths.state,
44
37
  commandResults: [],
45
38
  workerIds: [],
46
39
  taskWorkers: {},
@@ -63,85 +56,48 @@ function main() {
63
56
  const candidateId = `dogfood-release-${TARGET_VERSION}`;
64
57
  const evidence = compactEvidence(context.commandResults.map((result) => result.locator));
65
58
 
66
- const candidate = cwJson(
67
- ["candidate", "register", context.runId, "--worker", verdictWorkerId, "--id", candidateId, "--kind", "release"],
68
- repoRoot
69
- );
59
+ const candidate = runner.registerCandidate(context.runId, { worker: verdictWorkerId, id: candidateId, kind: "release" });
70
60
 
71
- const scoreArgs = [
72
- "candidate",
73
- "score",
74
- context.runId,
75
- candidateId,
76
- "--criterion",
77
- `correctness=${allPassed ? 10 : 0}`,
78
- "--criterion",
79
- `completeness=${requiredEvidencePresent(context) ? 10 : 0}`,
80
- "--criterion",
81
- `releaseSafety=${dryRun && context.externalActions.length === 0 ? 10 : 0}`,
82
- "--criterion",
83
- `auditability=${context.workerIds.length >= 6 ? 10 : 0}`,
84
- "--criterion",
85
- `reproducibility=${allPassed ? 10 : 4}`,
86
- "--maxTotal",
87
- "50",
88
- "--verdict",
89
- allPassed ? "pass" : "fail",
90
- "--notes",
91
- allPassed
61
+ const score = runner.scoreCandidate(context.runId, candidateId, {
62
+ criterion: [
63
+ `correctness=${allPassed ? 10 : 0}`,
64
+ `completeness=${requiredEvidencePresent(context) ? 10 : 0}`,
65
+ `releaseSafety=${dryRun && context.externalActions.length === 0 ? 10 : 0}`,
66
+ `auditability=${context.workerIds.length >= 6 ? 10 : 0}`,
67
+ `reproducibility=${allPassed ? 10 : 4}`
68
+ ],
69
+ maxTotal: 50,
70
+ verdict: allPassed ? "pass" : "fail",
71
+ notes: allPassed
92
72
  ? "Dogfood release candidate accepted: all real dry-run evidence commands passed."
93
- : "Dogfood release candidate held: at least one real evidence command failed."
94
- ];
95
- for (const locator of evidence.slice(0, 20)) scoreArgs.push("--evidence", locator);
96
- const score = cwJson(scoreArgs, repoRoot);
73
+ : "Dogfood release candidate held: at least one real evidence command failed.",
74
+ evidence: evidence.slice(0, 20)
75
+ });
97
76
 
98
77
  let selection = null;
99
78
  let commit = null;
100
79
  let releaseVerdict = "hold";
101
80
  if (allPassed) {
102
- selection = cwJson(
103
- [
104
- "candidate",
105
- "select",
106
- context.runId,
107
- candidateId,
108
- "--reason",
109
- `Dogfood release ${TARGET_VERSION} selected after verifier-backed dry-run evidence.`
110
- ],
111
- repoRoot
112
- );
113
- const commitResult = cwJson(
114
- [
115
- "commit",
116
- context.runId,
117
- "--selection",
118
- selection.id,
119
- "--reason",
120
- `Dogfood One Real Repo ${TARGET_VERSION} verifier-gated checkpoint`
121
- ],
122
- repoRoot
123
- );
81
+ selection = runner.selectCandidate(context.runId, candidateId, {
82
+ reason: `Dogfood release ${TARGET_VERSION} selected after verifier-backed dry-run evidence.`
83
+ });
84
+ const commitResult = runner.commit(context.runId, {
85
+ selection: selection.id,
86
+ reason: `Dogfood One Real Repo ${TARGET_VERSION} verifier-gated checkpoint`
87
+ });
124
88
  commit = commitResult.commit;
125
89
  releaseVerdict = "ready-dry-run";
126
90
  } else {
127
- const checkpoint = cwJson(
128
- [
129
- "commit",
130
- context.runId,
131
- "--allow-unverified-checkpoint",
132
- "--reason",
133
- `Dogfood One Real Repo ${TARGET_VERSION} held; evidence commands failed.`
134
- ],
135
- repoRoot
136
- );
91
+ const checkpoint = runner.commit(context.runId, {
92
+ allowUnverifiedCheckpoint: true,
93
+ reason: `Dogfood One Real Repo ${TARGET_VERSION} held; evidence commands failed.`
94
+ });
137
95
  commit = checkpoint.commit;
138
96
  }
139
97
 
140
- const auditSummary = cwJson(["audit", "summary", context.runId], repoRoot);
141
- const provenanceArgs = ["audit", "provenance", context.runId];
142
- if (commit && commit.id) provenanceArgs.push("--commit", commit.id);
143
- const provenance = cwJson(provenanceArgs, repoRoot);
144
- const reportPath = cwText(["report", context.runId], repoRoot).trim();
98
+ const auditSummary = runner.auditSummary(context.runId);
99
+ const provenance = runner.evidenceProvenance(context.runId, commit && commit.id ? { commit: commit.id } : {});
100
+ const reportPath = runner.report(context.runId).path;
145
101
 
146
102
  const summary = {
147
103
  ok: allPassed,
@@ -205,7 +161,7 @@ function main() {
205
161
  }
206
162
 
207
163
  function runTask(context, expectedTaskId) {
208
- const dispatch = cwJson(["dispatch", context.runId, "--limit", "1"], repoRoot);
164
+ const dispatch = context.runner.dispatch(context.runId, { limit: 1 });
209
165
  if (!dispatch.tasks || dispatch.tasks.length !== 1) {
210
166
  throw new Error(`Expected one dispatched task for ${expectedTaskId}`);
211
167
  }
@@ -215,7 +171,7 @@ function runTask(context, expectedTaskId) {
215
171
  context.workerIds.push(workerId);
216
172
  context.taskWorkers[task.id] = workerId;
217
173
 
218
- const manifest = cwJson(["worker", "manifest", context.runId, workerId], repoRoot);
174
+ const manifest = context.runner.showWorkerManifest(context.runId, workerId);
219
175
  const commandResults = executeCommandsForTask(context, task.id, manifest);
220
176
  const taskEvidence = evidenceForTask(task.id, commandResults, context);
221
177
  const findings = commandResults
@@ -237,7 +193,7 @@ function runTask(context, expectedTaskId) {
237
193
  smoke: context.options.smoke
238
194
  });
239
195
  fs.writeFileSync(manifest.resultPath, resultMarkdown, "utf8");
240
- cwJson(["worker", "output", context.runId, workerId, manifest.resultPath], repoRoot);
196
+ context.runner.recordWorkerOutput(context.runId, workerId, manifest.resultPath);
241
197
  }
242
198
 
243
199
  function executeCommandsForTask(context, taskId, manifest) {
@@ -247,23 +203,13 @@ function executeCommandsForTask(context, taskId, manifest) {
247
203
  const result = runEvidenceCommand(command, manifest, context);
248
204
  results.push(result);
249
205
  context.commandResults.push(result);
250
- cwJson(
251
- [
252
- "audit",
253
- "attest",
254
- context.runId,
255
- "--worker",
256
- manifest.id,
257
- "--hostEnforced",
258
- "true",
259
- "--command",
260
- result.command,
261
- "--note",
262
- `dogfood ${taskId} command status=${result.status}`
263
- ],
264
- repoRoot
265
- );
266
- cwJson(["audit", "decision", context.runId, manifest.id, "--command", result.command], repoRoot);
206
+ context.runner.recordAuditAttestation(context.runId, {
207
+ worker: manifest.id,
208
+ hostEnforced: true,
209
+ command: result.command,
210
+ note: `dogfood ${taskId} command status=${result.status}`
211
+ });
212
+ context.runner.recordAuditDecision(context.runId, manifest.id, { command: result.command });
267
213
  }
268
214
  return results;
269
215
  }
@@ -378,7 +324,6 @@ function commandsForTask(taskId, context) {
378
324
  case "package:artifacts":
379
325
  if (smoke) {
380
326
  return [
381
- { id: "app-validate-release-cut", cwd: pluginRoot, command: [node, ["scripts/cw.js", "app", "validate", "release-cut"]] },
382
327
  { id: "npm-pack-dry-run", cwd: pluginRoot, command: packDryRunCommand() }
383
328
  ];
384
329
  }
@@ -389,8 +334,7 @@ function commandsForTask(taskId, context) {
389
334
  case "verify:package":
390
335
  if (smoke) {
391
336
  return [
392
- { id: "canonical-apps", cwd: pluginRoot, command: ["npm", ["run", "canonical-apps"]] },
393
- { id: "golden-path", cwd: pluginRoot, command: ["npm", ["run", "golden-path"]] }
337
+ { id: "app-validate-release-cut", cwd: pluginRoot, command: [node, ["scripts/cw.js", "app", "validate", "release-cut"]] }
394
338
  ];
395
339
  }
396
340
  return [
@@ -526,7 +470,7 @@ function renderWorkerResult({ task, manifest, commandResults, findings, evidence
526
470
 
527
471
  function requiredEvidencePresent(context) {
528
472
  const required = context.options.smoke
529
- ? ["git-status", "version-sync", "release-docs", "app-validate-release-cut", "canonical-apps", "golden-path"]
473
+ ? ["git-status", "version-sync", "release-docs", "npm-pack-dry-run", "app-validate-release-cut"]
530
474
  : [
531
475
  "git-status",
532
476
  "version-sync",
@@ -560,28 +504,6 @@ function currentBranch() {
560
504
  return (result.stdout || "").trim() || "main";
561
505
  }
562
506
 
563
- function cwJson(args, cwd) {
564
- const text = cwText(args, cwd);
565
- try {
566
- return JSON.parse(text);
567
- } catch (error) {
568
- throw new Error(`cw JSON parse failed for ${args.join(" ")}\n${text}`);
569
- }
570
- }
571
-
572
- function cwText(args, cwd) {
573
- const result = spawnSync(node, [cli, ...args], {
574
- cwd,
575
- encoding: "utf8",
576
- env: process.env,
577
- maxBuffer: 1024 * 1024 * 20
578
- });
579
- if (result.status !== 0) {
580
- throw new Error(`cw ${args.join(" ")} exited ${result.status}\n${result.stdout}\n${result.stderr}`);
581
- }
582
- return result.stdout;
583
- }
584
-
585
507
  function parseArgs(argv) {
586
508
  const options = {
587
509
  smoke: false,
@@ -33,7 +33,7 @@ function main() {
33
33
  const appValidation = runJson(["app", "validate", "end-to-end-golden-path"], pluginRoot);
34
34
  assert.equal(appValidation.valid, true);
35
35
  assert.equal(appValidation.summary.id, "end-to-end-golden-path");
36
- assert.equal(appValidation.summary.version, "0.1.84");
36
+ assert.equal(appValidation.summary.version, "0.1.86");
37
37
 
38
38
  const plan = runJson(
39
39
  [
@@ -42,7 +42,7 @@ function main() {
42
42
  "--repo",
43
43
  tmp,
44
44
  "--question",
45
- "Prove the deterministic v0.1.84 end-to-end golden path."
45
+ "Prove the deterministic v0.1.86 end-to-end golden path."
46
46
  ],
47
47
  pluginRoot
48
48
  );
@@ -52,7 +52,7 @@ function main() {
52
52
 
53
53
  let state = readJson(plan.statePath);
54
54
  assert.equal(state.workflow.app.id, "end-to-end-golden-path");
55
- assert.equal(state.workflow.app.version, "0.1.84");
55
+ assert.equal(state.workflow.app.version, "0.1.86");
56
56
  assert.equal(state.loopStage, "interpret");
57
57
 
58
58
  const dispatch = runJson(["dispatch", plan.runId, "--limit", "1", "--sandbox", "readonly"], tmp);
@@ -195,7 +195,7 @@ function main() {
195
195
  assert.equal(reportPath, plan.reportPath);
196
196
  assert.ok(fs.existsSync(reportPath));
197
197
  const report = fs.readFileSync(reportPath, "utf8");
198
- assert.match(report, /Workflow App: end-to-end-golden-path@0\.1\.84/);
198
+ assert.match(report, /Workflow App: end-to-end-golden-path@0\.1\.86/);
199
199
  assert.match(report, /## Candidates/);
200
200
  assert.match(report, /## Trust Audit/);
201
201
  assert.match(report, /## Acceptance Rationale/);
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // onramp-check — fail closed when a change batch violates the local development
5
+ // contract: behavior changes need smoke coverage, surface changes need docs, and
6
+ // source/app/script changes need an iteration-log row.
7
+
8
+ const path = require("node:path");
9
+ const { evaluateOnrampContract, resolveChangedFiles } = require("../dist/onramp.js");
10
+
11
+ const pluginRoot = path.resolve(__dirname, "..");
12
+
13
+ function argValue(name) {
14
+ const eq = process.argv.find((arg) => arg.startsWith(`${name}=`));
15
+ if (eq) return eq.slice(name.length + 1);
16
+ const index = process.argv.indexOf(name);
17
+ return index >= 0 ? process.argv[index + 1] : undefined;
18
+ }
19
+
20
+ function main() {
21
+ const check = process.argv.includes("--check");
22
+ const changedFrom = argValue("--changed-from");
23
+ const changed = resolveChangedFiles({ cwd: pluginRoot, changedFrom, env: process.env });
24
+ const contract = evaluateOnrampContract(changed.files, { cwd: pluginRoot });
25
+ const report = {
26
+ schemaVersion: 1,
27
+ baseRef: changed.baseRef,
28
+ ...contract
29
+ };
30
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
31
+ if (check && !contract.ok) {
32
+ process.stderr.write("\nonramp contract failed:\n");
33
+ for (const issue of contract.issues) {
34
+ process.stderr.write(` - ${issue.code}: ${issue.detail}\n`);
35
+ process.stderr.write(` fix: ${issue.fix}\n`);
36
+ if (issue.files.length) process.stderr.write(` files: ${issue.files.join(", ")}\n`);
37
+ }
38
+ process.exitCode = 1;
39
+ }
40
+ }
41
+
42
+ try {
43
+ main();
44
+ } catch (error) {
45
+ process.stderr.write(`onramp-check: ${error && error.message ? error.message : String(error)}\n`);
46
+ process.exitCode = 1;
47
+ }