cool-workflow 0.1.81 → 0.1.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/candidate-scoring.js +20 -26
- package/dist/capability-core.js +64 -85
- package/dist/capability-registry.js +22 -3
- package/dist/commit.js +212 -203
- package/dist/coordinator/util.js +6 -9
- package/dist/dispatch.js +11 -3
- package/dist/evidence-reasoning.js +4 -1
- package/dist/execution-backend/agent.js +11 -48
- package/dist/execution-backend.js +11 -31
- package/dist/gates.js +48 -0
- package/dist/multi-agent/helpers.js +6 -10
- package/dist/multi-agent/ids.js +20 -0
- package/dist/multi-agent-eval.js +27 -1
- package/dist/multi-agent-host.js +53 -21
- package/dist/multi-agent-operator-ux.js +2 -1
- package/dist/multi-agent-trust.js +5 -5
- package/dist/node-projection.js +59 -0
- package/dist/node-snapshot.js +8 -18
- package/dist/orchestrator/lifecycle-operations.js +22 -1
- package/dist/orchestrator.js +16 -2
- package/dist/reclamation.js +8 -36
- package/dist/scheduler.js +34 -4
- package/dist/topology.js +25 -4
- package/dist/trust-audit.js +70 -38
- package/dist/validation.js +328 -0
- package/dist/version.js +1 -1
- package/dist/worker-isolation.js +143 -58
- package/docs/agent-delegation-drive.7.md +1 -0
- package/docs/cli-mcp-parity.7.md +1 -0
- package/docs/contract-migration-tooling.7.md +1 -0
- package/docs/control-plane-scheduling.7.md +1 -0
- package/docs/durable-state-and-locking.7.md +1 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +1 -0
- package/docs/execution-backends.7.md +1 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +1 -0
- package/docs/multi-agent-eval-replay-harness.7.md +1 -0
- package/docs/multi-agent-operator-ux.7.md +1 -0
- package/docs/node-snapshot-diff-replay.7.md +1 -0
- package/docs/observability-cost-accounting.7.md +1 -0
- package/docs/project-index.md +8 -4
- package/docs/real-execution-backends.7.md +1 -0
- package/docs/release-and-migration.7.md +1 -0
- package/docs/release-tooling.7.md +33 -2
- package/docs/run-registry-control-plane.7.md +1 -0
- package/docs/run-retention-reclamation.7.md +1 -0
- package/docs/state-explosion-management.7.md +1 -0
- package/docs/team-collaboration.7.md +1 -0
- package/docs/web-desktop-workbench.7.md +1 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +1 -1
- package/package.json +1 -1
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +58 -0
- package/scripts/children/http-delegate-child.js +39 -0
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/release-flow.js +181 -5
package/dist/worker-isolation.js
CHANGED
|
@@ -34,6 +34,7 @@ const telemetry_ledger_1 = require("./telemetry-ledger");
|
|
|
34
34
|
const coordinator_1 = require("./coordinator");
|
|
35
35
|
const helpers_1 = require("./worker-isolation/helpers");
|
|
36
36
|
const paths_1 = require("./worker-isolation/paths");
|
|
37
|
+
const validation_1 = require("./validation");
|
|
37
38
|
exports.WORKER_ISOLATION_SCHEMA_VERSION = 1;
|
|
38
39
|
function allocateWorkerScope(run, task, options = {}) {
|
|
39
40
|
ensureWorkerState(run);
|
|
@@ -269,11 +270,31 @@ function getWorkerScope(run, workerId) {
|
|
|
269
270
|
const file = node_path_1.default.join(workerRoot(run), (0, state_1.safeFileName)(workerId), paths_1.WORKER_SCOPE_FILE);
|
|
270
271
|
if (!node_fs_1.default.existsSync(file))
|
|
271
272
|
return undefined;
|
|
272
|
-
const scope = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
|
|
273
|
+
const scope = (0, validation_1.validateWorkerScope)(JSON.parse(node_fs_1.default.readFileSync(file, "utf8")));
|
|
273
274
|
upsertWorkerScope(run, scope);
|
|
274
275
|
return scope;
|
|
275
276
|
}
|
|
276
277
|
function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
278
|
+
// Accept-path orchestrator. The recorded order + side effects of these ordered
|
|
279
|
+
// steps are load-bearing (replay determinism + the hash-chained audit/telemetry
|
|
280
|
+
// ledgers cross-link by parent event ids), so each helper runs exactly where it
|
|
281
|
+
// did before and mutates the shared `accept` context in place. Do NOT reorder.
|
|
282
|
+
const accept = validateWorkerResult(run, workerId, resultPath, options);
|
|
283
|
+
const delegation = attestWorkerDelegation(accept);
|
|
284
|
+
acceptWorkerResult(accept, delegation);
|
|
285
|
+
recordWorkerDelegationLedger(accept, delegation);
|
|
286
|
+
runWorkerVerify(accept);
|
|
287
|
+
recordWorkerCompletion(accept, delegation);
|
|
288
|
+
fanOutWorkerOutput(accept);
|
|
289
|
+
if (options.persist !== false)
|
|
290
|
+
(0, state_1.saveCheckpoint)(run);
|
|
291
|
+
return accept.output;
|
|
292
|
+
}
|
|
293
|
+
/** Step 1 — validateResult: resolve scope/task, enforce the sandbox boundary, the
|
|
294
|
+
* result-file existence, the envelope contract, and (opt-in) resolvable evidence.
|
|
295
|
+
* Fail-closed: any guard records a worker failure and throws BEFORE accept-side
|
|
296
|
+
* state mutation. Returns the partially-filled accept context on success. */
|
|
297
|
+
function validateWorkerResult(run, workerId, resultPath, options) {
|
|
277
298
|
const scope = requireWorkerScope(run, workerId);
|
|
278
299
|
const task = requireWorkerTask(run, scope);
|
|
279
300
|
const absoluteResultPath = node_path_1.default.resolve(resultPath);
|
|
@@ -316,6 +337,30 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
316
337
|
throw new Error(error.message);
|
|
317
338
|
}
|
|
318
339
|
}
|
|
340
|
+
return {
|
|
341
|
+
run,
|
|
342
|
+
workerId,
|
|
343
|
+
options,
|
|
344
|
+
scope,
|
|
345
|
+
task,
|
|
346
|
+
absoluteResultPath,
|
|
347
|
+
rawResult,
|
|
348
|
+
parsedResult,
|
|
349
|
+
destination: "",
|
|
350
|
+
pathAuditId: "",
|
|
351
|
+
acceptedAuditId: "",
|
|
352
|
+
resultNode: undefined,
|
|
353
|
+
verifierNodeId: "",
|
|
354
|
+
verifierStatus: "",
|
|
355
|
+
output: undefined
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/** Step 2 — attestSandbox/attestDelegation: verify the agent's signed telemetry
|
|
359
|
+
* BEFORE recording it, enforce the opt-in require-attested-telemetry gate (still
|
|
360
|
+
* fail-closed, pre-mutation), and build the agent-hop provenance. Non-agent hops
|
|
361
|
+
* return an empty delegation. */
|
|
362
|
+
function attestWorkerDelegation(accept) {
|
|
363
|
+
const { run, workerId, options, task, absoluteResultPath, rawResult } = accept;
|
|
319
364
|
// Agent Delegation Drive (v0.1.38): if this worker's result.md was produced by an
|
|
320
365
|
// EXTERNAL agent, record the agent-hop attestation AS PROVENANCE — the agent
|
|
321
366
|
// (kind:process) handle, the agent-REPORTED model (never CW_AGENT_MODEL), the
|
|
@@ -355,6 +400,16 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
355
400
|
...(telemetry ? { usageAttestation: telemetry.status, usageAttestationReason: telemetry.reason } : {})
|
|
356
401
|
}
|
|
357
402
|
: undefined;
|
|
403
|
+
return { agentDelegation, telemetry };
|
|
404
|
+
}
|
|
405
|
+
/** Step 3 — recordStateNode/audit: the irreversible accept. Records the allowed
|
|
406
|
+
* path decision, copies the result into the run results dir, completes the task,
|
|
407
|
+
* builds + appends the result node, emits the accepted audit event, re-normalizes
|
|
408
|
+
* node evidence against both audit ids, and surfaces the empty-capture warning.
|
|
409
|
+
* Writes destination/pathAuditId/acceptedAuditId/resultNode back into `accept`. */
|
|
410
|
+
function acceptWorkerResult(accept, delegation) {
|
|
411
|
+
const { run, workerId, scope, task, absoluteResultPath, parsedResult } = accept;
|
|
412
|
+
const { agentDelegation } = delegation;
|
|
358
413
|
const pathAudit = (0, trust_audit_1.recordSandboxPathDecision)(run, {
|
|
359
414
|
workerId,
|
|
360
415
|
taskId: task.id,
|
|
@@ -443,58 +498,75 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
443
498
|
metadata: { reason: "no findings or evidence captured from result.md", resultPath: destination }
|
|
444
499
|
});
|
|
445
500
|
}
|
|
501
|
+
accept.destination = destination;
|
|
502
|
+
accept.pathAuditId = pathAudit.id;
|
|
503
|
+
accept.acceptedAuditId = acceptedAudit.id;
|
|
504
|
+
accept.resultNode = resultNode;
|
|
505
|
+
}
|
|
506
|
+
/** Step 4 — recordTelemetryLedger: the agent-hop attestation. Binds the telemetry
|
|
507
|
+
* verdict into the append-only hash-chained ledger BEFORE the audit event (so the
|
|
508
|
+
* event can cross-link the record hash), then emits the worker.agent-delegation
|
|
509
|
+
* audit event. No-op for non-agent hops. */
|
|
510
|
+
function recordWorkerDelegationLedger(accept, delegation) {
|
|
511
|
+
const { agentDelegation } = delegation;
|
|
446
512
|
// The agent-hop attestation event — hung off worker.output, alongside
|
|
447
513
|
// worker.backend. Recorded in trust-audit/provenance, NEVER in node evidence.
|
|
448
|
-
if (agentDelegation)
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
promptDigest: agentDelegation.promptDigest,
|
|
458
|
-
reportedUsage: agentDelegation.reportedUsage,
|
|
459
|
-
usageSignature: agentDelegation.usageSignature,
|
|
460
|
-
attestation: agentDelegation.usageAttestation,
|
|
461
|
-
attestationReason: agentDelegation.usageAttestationReason
|
|
462
|
-
})
|
|
463
|
-
: undefined;
|
|
464
|
-
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
465
|
-
kind: "worker.agent-delegation",
|
|
466
|
-
decision: "recorded",
|
|
467
|
-
source: "host-attested",
|
|
514
|
+
if (!agentDelegation)
|
|
515
|
+
return;
|
|
516
|
+
const { run, workerId, scope, task, resultNode, acceptedAuditId } = accept;
|
|
517
|
+
// Track 1 (tamper-evidence): bind this verdict into the append-only,
|
|
518
|
+
// hash-chained telemetry ledger BEFORE the audit event, so the event can
|
|
519
|
+
// cross-link the record hash. Editing the recorded verdict/usage later breaks
|
|
520
|
+
// the chain (verifyTelemetryLedger). Only when a verdict was computed.
|
|
521
|
+
const ledgerRecord = agentDelegation.usageAttestation
|
|
522
|
+
? (0, telemetry_ledger_1.appendTelemetryAttestation)(run, {
|
|
468
523
|
workerId,
|
|
469
524
|
taskId: task.id,
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
525
|
+
promptDigest: agentDelegation.promptDigest,
|
|
526
|
+
reportedUsage: agentDelegation.reportedUsage,
|
|
527
|
+
usageSignature: agentDelegation.usageSignature,
|
|
528
|
+
attestation: agentDelegation.usageAttestation,
|
|
529
|
+
attestationReason: agentDelegation.usageAttestationReason
|
|
530
|
+
})
|
|
531
|
+
: undefined;
|
|
532
|
+
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
533
|
+
kind: "worker.agent-delegation",
|
|
534
|
+
decision: "recorded",
|
|
535
|
+
source: "host-attested",
|
|
536
|
+
workerId,
|
|
537
|
+
taskId: task.id,
|
|
538
|
+
nodeId: resultNode.id,
|
|
539
|
+
sandboxProfileId: scope.sandboxProfileId,
|
|
540
|
+
policySnapshot: scope.sandboxPolicy,
|
|
541
|
+
parentEventIds: [acceptedAuditId],
|
|
542
|
+
metadata: {
|
|
543
|
+
backendId: agentDelegation.backendId,
|
|
544
|
+
handleKind: agentDelegation.handle.kind,
|
|
545
|
+
handleRef: agentDelegation.handle.ref,
|
|
546
|
+
model: agentDelegation.model,
|
|
547
|
+
promptDigest: agentDelegation.promptDigest,
|
|
548
|
+
resultDigest: agentDelegation.resultDigest,
|
|
549
|
+
command: agentDelegation.command,
|
|
550
|
+
args: agentDelegation.args,
|
|
551
|
+
exitCode: agentDelegation.exitCode,
|
|
552
|
+
// Track 1: the telemetry verdict travels with the agent-hop event so the
|
|
553
|
+
// audit report can surface `unattested` usage loudly. Absent ⇒ no usage.
|
|
554
|
+
...(agentDelegation.usageAttestation
|
|
555
|
+
? {
|
|
556
|
+
telemetryAttestation: agentDelegation.usageAttestation,
|
|
557
|
+
...(agentDelegation.usageAttestationReason ? { telemetryAttestationReason: agentDelegation.usageAttestationReason } : {}),
|
|
558
|
+
...(agentDelegation.reportedUsage ? { reportedUsage: agentDelegation.reportedUsage } : {}),
|
|
559
|
+
// Cross-link to the hash-chained ledger entry (tamper-evidence).
|
|
560
|
+
...(ledgerRecord ? { telemetryRecordId: ledgerRecord.recordId, telemetryRecordHash: ledgerRecord.recordHash, telemetryPrevHash: ledgerRecord.prevHash } : {})
|
|
561
|
+
}
|
|
562
|
+
: {})
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
/** Step 5 — runVerify: drive the verify pipeline stage off the accepted result node
|
|
567
|
+
* and record the verifier node id on the task + accept context. */
|
|
568
|
+
function runWorkerVerify(accept) {
|
|
569
|
+
const { run, workerId, scope, task, parsedResult, destination, resultNode } = accept;
|
|
498
570
|
const verifierResult = (0, pipeline_runner_1.createPipelineRunner)({ persist: false }).runPipelineStage(run, "verify", resultNode.id, {
|
|
499
571
|
outputNodeId: `${run.id}:verifier:${task.id}`,
|
|
500
572
|
outputStatus: "verified",
|
|
@@ -507,14 +579,24 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
507
579
|
metadata: { taskId: task.id, workerId, resultNodeId: resultNode.id, sandboxProfileId: scope.sandboxProfileId }
|
|
508
580
|
});
|
|
509
581
|
task.verifierNodeId = verifierResult.outputNodeId;
|
|
582
|
+
accept.verifierNodeId = verifierResult.outputNodeId;
|
|
583
|
+
// Carry the verify verdict for the scope-status transition in recordWorkerCompletion.
|
|
584
|
+
accept.verifierStatus = verifierResult.status;
|
|
585
|
+
}
|
|
586
|
+
/** Step 6 — recordStateNode (worker record): assemble the worker output record +
|
|
587
|
+
* host-attested usage record, then persist the worker scope with the verify-derived
|
|
588
|
+
* status, output digest/size, and (when present) usage. */
|
|
589
|
+
function recordWorkerCompletion(accept, delegation) {
|
|
590
|
+
const { run, workerId, scope, task, absoluteResultPath, rawResult, resultNode, verifierNodeId, verifierStatus, pathAuditId, acceptedAuditId } = accept;
|
|
591
|
+
const { agentDelegation, telemetry } = delegation;
|
|
510
592
|
const output = {
|
|
511
593
|
workerId,
|
|
512
594
|
taskId: task.id,
|
|
513
595
|
resultPath: absoluteResultPath,
|
|
514
596
|
recordedAt: new Date().toISOString(),
|
|
515
597
|
stateNodeId: resultNode.id,
|
|
516
|
-
verifierNodeId
|
|
517
|
-
auditEventIds: [
|
|
598
|
+
verifierNodeId,
|
|
599
|
+
auditEventIds: [pathAuditId, acceptedAuditId]
|
|
518
600
|
};
|
|
519
601
|
// Host-attested usage rides on the worker record. Recorded when the agent
|
|
520
602
|
// REPORTED a model OR token usage — `unreported`/absent stays ABSENT (never
|
|
@@ -537,7 +619,7 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
537
619
|
updateWorkerScope(run, {
|
|
538
620
|
...scope,
|
|
539
621
|
updatedAt: new Date().toISOString(),
|
|
540
|
-
status:
|
|
622
|
+
status: verifierStatus === "advanced" ? "verified" : "completed",
|
|
541
623
|
resultNodeId: resultNode.id,
|
|
542
624
|
output,
|
|
543
625
|
// Output integrity (v0.1.63): SHA256 digest + file size
|
|
@@ -545,20 +627,23 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
545
627
|
outputSizeBytes: Buffer.byteLength(rawResult, "utf8"),
|
|
546
628
|
...(usageRecord ? { usage: usageRecord } : {})
|
|
547
629
|
});
|
|
548
|
-
|
|
630
|
+
accept.output = output;
|
|
631
|
+
}
|
|
632
|
+
/** Step 7 — fanOut: publish the accepted output to the blackboard and record the
|
|
633
|
+
* multi-agent worker output (linking the blackboard message/artifact refs). */
|
|
634
|
+
function fanOutWorkerOutput(accept) {
|
|
635
|
+
const { run, workerId, scope, task, absoluteResultPath, parsedResult, destination, resultNode, verifierNodeId, acceptedAuditId } = accept;
|
|
636
|
+
const blackboardLinks = publishWorkerOutputToBlackboard(run, scope, task, parsedResult.summary, destination, absoluteResultPath, resultNode.evidence, acceptedAuditId);
|
|
549
637
|
(0, multi_agent_1.recordMultiAgentWorkerOutput)(run, {
|
|
550
638
|
workerId,
|
|
551
639
|
taskId: task.id,
|
|
552
640
|
resultNodeId: resultNode.id,
|
|
553
|
-
verifierNodeId
|
|
641
|
+
verifierNodeId,
|
|
554
642
|
evidence: resultNode.evidence,
|
|
555
643
|
artifactPaths: [destination, absoluteResultPath],
|
|
556
644
|
blackboardMessageIds: blackboardLinks.messageIds,
|
|
557
645
|
blackboardArtifactRefIds: blackboardLinks.artifactRefIds
|
|
558
646
|
});
|
|
559
|
-
if (options.persist !== false)
|
|
560
|
-
(0, state_1.saveCheckpoint)(run);
|
|
561
|
-
return output;
|
|
562
647
|
}
|
|
563
648
|
function recordWorkerFailure(run, workerId, error, options = {}) {
|
|
564
649
|
const scope = requireWorkerScope(run, workerId);
|
|
@@ -786,7 +871,7 @@ function loadWorkerScopesFromDisk(run) {
|
|
|
786
871
|
.filter((entry) => entry.isDirectory())
|
|
787
872
|
.map((entry) => node_path_1.default.join(workerRoot(run), entry.name, paths_1.WORKER_SCOPE_FILE))
|
|
788
873
|
.filter((file) => node_fs_1.default.existsSync(file))
|
|
789
|
-
.map((file) => JSON.parse(node_fs_1.default.readFileSync(file, "utf8")));
|
|
874
|
+
.map((file) => (0, validation_1.validateWorkerScope)(JSON.parse(node_fs_1.default.readFileSync(file, "utf8"))));
|
|
790
875
|
}
|
|
791
876
|
function requireWorkerScope(run, workerId) {
|
|
792
877
|
const scope = getWorkerScope(run, workerId);
|
|
@@ -261,3 +261,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
261
261
|
## Resumable Drive & Resume Routing (v0.1.81)
|
|
262
262
|
|
|
263
263
|
Adds `run resume <id> --drive/--once` alongside `quickstart --resume`: a stopped pipeline resumes in-place, advancing to completion (`--drive`) or one deterministic step (`--once`) over the same plan->dispatch->agent-fulfill->accept->commit lifecycle, echoing `resumedFrom: <id>`. Fixes the `run resume --drive` CLI routing so the drive flag reaches the resumed run instead of being read as an app name. Replay determinism and the agent evidence triple are unchanged.
|
|
264
|
+
_No behavioral change in v0.1.82 (drive/quickstart resolve the run repo via an explicit base directory rather than process.chdir; delegation behavior is unchanged)._
|
package/docs/cli-mcp-parity.7.md
CHANGED
|
@@ -389,3 +389,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
389
389
|
## Re-Prove Verbs on Both Surfaces (v0.1.81)
|
|
390
390
|
|
|
391
391
|
v0.1.81 grows the parity surface with two new both-surface, fail-closed verbs declared once in the capability registry: `cw audit verify` / `cw_audit_verify` re-proves the trust-audit chain and exits non-zero on any unverified or corrupt chain, and `cw run inspect-archive` / `cw_run_inspect_archive` is a read-only archive integrity check. Each `cw <cmd> --json` is schema-identical to its `cw_<tool>` and validated by the same parity gate.
|
|
392
|
+
_No changes in v0.1.82._
|
|
@@ -129,3 +129,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
129
129
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
130
130
|
|
|
131
131
|
_No changes to the contract-migration subsystem in v0.1.81._
|
|
132
|
+
_No changes in v0.1.82._
|
|
@@ -116,3 +116,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
116
116
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
117
117
|
|
|
118
118
|
_No changes to the control-plane scheduling surface in v0.1.81._
|
|
119
|
+
_No behavioral change in v0.1.82 (schedule/run ids are now deterministic-but-unique via a monotonic counter + pid instead of Math.random; ids stay collision-free)._
|
|
@@ -115,3 +115,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
115
115
|
## Deterministic Tombstone Hash (v0.1.81)
|
|
116
116
|
|
|
117
117
|
The reclamation tombstone's freed-manifest is now path-sorted before it feeds `tombstoneHash`, so the same freed set always yields the same hash regardless of filesystem enumeration order. This removes a non-determinism from the write-ahead chain (v0.1.39/v0.1.40), keeping the per-run tombstone hash-chain replayable and stable across hosts. Atomicity, locking, and the durable re-point seam are unchanged. v0.1.81 also adds import-time refusal (`CW_REQUIRE_ARCHIVE_INTEGRITY=1`) and restore-time trust-audit re-proving — see run-registry-control-plane(7).
|
|
118
|
+
_No changes in v0.1.82._
|
|
@@ -276,3 +276,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
276
276
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
277
277
|
|
|
278
278
|
_No changes to the Evidence Adoption Reasoning Chain surface in v0.1.81. The v0.1.81 trust-audit `computeEventHash` fix hardens the underlying audit records this chain links to by reference, but the derived reasoning view, its commands, and its eval gates are unchanged._
|
|
279
|
+
_No changes in v0.1.82._
|
|
@@ -306,3 +306,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
306
306
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
307
307
|
|
|
308
308
|
_No changes to the execution-backends surface in v0.1.81._
|
|
309
|
+
_No behavioral change in v0.1.82 (the delegated child programs moved from inline `node -e` strings to `scripts/children/`; spawn argv and shell:false behavior are byte-identical)._
|
|
@@ -273,3 +273,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
273
273
|
## New Both-Surface Verbs (v0.1.81)
|
|
274
274
|
|
|
275
275
|
v0.1.81 adds `audit verify` (`cw_audit_verify`) and `run inspect-archive` (`cw_run_inspect_archive`) — both declared once in the capability registry and exposed identically on the CLI and MCP, fail-closed (non-zero exit / `ok:false` on an unverified chain or a tampered archive).
|
|
276
|
+
_No changes in v0.1.82._
|
|
@@ -308,3 +308,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
308
308
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
309
309
|
|
|
310
310
|
_No changes to the multi-agent eval/replay harness in v0.1.81 (the multi-agent-eval module was carved into behavior-preserving siblings; replay output is byte-identical)._
|
|
311
|
+
_v0.1.82 — replay now RE-DERIVES the projection from the raw captured state instead of copying the baseline, so a nondeterministic projection is caught instead of silently passing; a new regression smoke (including an intrinsic-nondeterminism case) proves the moat has teeth._
|
|
@@ -320,3 +320,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
320
320
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
321
321
|
|
|
322
322
|
_No changes to the multi-agent operator UX surface in v0.1.81 (the operator-ux module was carved into behavior-preserving siblings; output is byte-identical)._
|
|
323
|
+
_No changes in v0.1.82._
|
|
@@ -141,3 +141,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
141
141
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
142
142
|
|
|
143
143
|
_No changes to node-snapshot diff/replay in v0.1.81._
|
|
144
|
+
_No behavioral change in v0.1.82 (the node projection field set was unified into one source of truth; snapshot/replay digests are byte-identical)._
|
|
@@ -200,3 +200,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
200
200
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
201
201
|
|
|
202
202
|
_No changes to the observability + cost-accounting surface in v0.1.81 (the observability module was carved into behavior-preserving siblings; output is byte-identical)._
|
|
203
|
+
_No changes in v0.1.82._
|
package/docs/project-index.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Cool Workflow Project Index
|
|
2
2
|
|
|
3
|
-
Generated from the current repository code on 2026-06-
|
|
3
|
+
Generated from the current repository code on 2026-06-15 by `npm run sync:project-index`.
|
|
4
4
|
|
|
5
5
|
## Snapshot
|
|
6
6
|
|
|
7
7
|
- Package: `cool-workflow`
|
|
8
|
-
- Version: `0.1.
|
|
9
|
-
- Source modules: `
|
|
8
|
+
- Version: `0.1.82`
|
|
9
|
+
- Source modules: `61`
|
|
10
10
|
- Workflow apps: `7`
|
|
11
11
|
- Docs: `49`
|
|
12
|
-
- Smoke tests: `
|
|
12
|
+
- Smoke tests: `87`
|
|
13
13
|
- Repository: https://github.com/coo1white/cool-workflow
|
|
14
14
|
|
|
15
15
|
## Architecture
|
|
@@ -90,9 +90,11 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
90
90
|
- [evidence-grounding.ts](../src/evidence-grounding.ts)
|
|
91
91
|
- [evidence-reasoning.ts](../src/evidence-reasoning.ts)
|
|
92
92
|
- [execution-backend.ts](../src/execution-backend.ts)
|
|
93
|
+
- [gates.ts](../src/gates.ts)
|
|
93
94
|
- [multi-agent-eval.ts](../src/multi-agent-eval.ts)
|
|
94
95
|
- [multi-agent-operator-ux.ts](../src/multi-agent-operator-ux.ts)
|
|
95
96
|
- [multi-agent-trust.ts](../src/multi-agent-trust.ts)
|
|
97
|
+
- [node-projection.ts](../src/node-projection.ts)
|
|
96
98
|
- [node-snapshot.ts](../src/node-snapshot.ts)
|
|
97
99
|
- [observability.ts](../src/observability.ts)
|
|
98
100
|
- [reclamation.ts](../src/reclamation.ts)
|
|
@@ -107,6 +109,7 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
107
109
|
- [telemetry-attestation.ts](../src/telemetry-attestation.ts)
|
|
108
110
|
- [telemetry-demo.ts](../src/telemetry-demo.ts)
|
|
109
111
|
- [telemetry-ledger.ts](../src/telemetry-ledger.ts)
|
|
112
|
+
- [validation.ts](../src/validation.ts)
|
|
110
113
|
- [verifier-registry.ts](../src/verifier-registry.ts)
|
|
111
114
|
- [workbench-host.ts](../src/workbench-host.ts)
|
|
112
115
|
- [workbench.ts](../src/workbench.ts)
|
|
@@ -210,6 +213,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
210
213
|
- [h7-custom-profile-persist-smoke.js](../test/h7-custom-profile-persist-smoke.js)
|
|
211
214
|
- [mcp-app-surface-smoke.js](../test/mcp-app-surface-smoke.js)
|
|
212
215
|
- [multi-agent-cli-mcp-surface-smoke.js](../test/multi-agent-cli-mcp-surface-smoke.js)
|
|
216
|
+
- [multi-agent-eval-determinism-regression-smoke.js](../test/multi-agent-eval-determinism-regression-smoke.js)
|
|
213
217
|
- [multi-agent-eval-replay-harness-smoke.js](../test/multi-agent-eval-replay-harness-smoke.js)
|
|
214
218
|
- [multi-agent-eval-replay-smoke.js](../test/multi-agent-eval-replay-smoke.js)
|
|
215
219
|
- [multi-agent-operator-ux-smoke.js](../test/multi-agent-operator-ux-smoke.js)
|
|
@@ -148,3 +148,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
148
148
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
149
149
|
|
|
150
150
|
_No changes to the real execution backends in v0.1.81._
|
|
151
|
+
_No behavioral change in v0.1.82 (delegated child programs extracted to `scripts/children/`; spawn behavior byte-identical)._
|
|
@@ -288,3 +288,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
288
288
|
## Migration Compatibility (v0.1.81)
|
|
289
289
|
|
|
290
290
|
v0.1.81 is additive: every change is a new flag/verb/env (`audit verify`, `run inspect-archive`, `verify-import --strict`, `CW_REQUIRE_ARCHIVE_INTEGRITY`, `quickstart --resume`, `run resume --drive`) or an internal behavior-preserving carve. Run-state schema, existing outputs, files, and exit codes are byte-identical, so runs and archives from prior versions load and verify unchanged. No migration action is required.
|
|
291
|
+
_No changes in v0.1.82._
|
|
@@ -133,8 +133,10 @@ inherits the agent's own credentials, and imports no model SDK — the red line.
|
|
|
133
133
|
```bash
|
|
134
134
|
# check only (gate + independent review, no mutation):
|
|
135
135
|
node plugins/cool-workflow/scripts/release-flow.js --check
|
|
136
|
-
# cut a tag once review is green:
|
|
137
|
-
node plugins/cool-workflow/scripts/release-flow.js --cut --version 0.1.77 [--push]
|
|
136
|
+
# cut a tag once review is green (when --push, also creates the GitHub Release):
|
|
137
|
+
node plugins/cool-workflow/scripts/release-flow.js --cut --version 0.1.77 [--push] [--no-release]
|
|
138
|
+
# backfill / re-create the GitHub Release for an already-pushed tag (no gate/cut):
|
|
139
|
+
node plugins/cool-workflow/scripts/release-flow.js --release --version 0.1.77 [--soft]
|
|
138
140
|
```
|
|
139
141
|
|
|
140
142
|
The per-platform difference is config, not code — set the reviewer agent:
|
|
@@ -152,6 +154,34 @@ also get generated MCP manifests (`.gemini-plugin/`, `.opencode-plugin/`) so the
|
|
|
152
154
|
`cw_*` tools are available as MCP tools in those hosts. The verdict path
|
|
153
155
|
(`.cw-release/review-<sha>.verdict`) and the tag-push CI backstop are unchanged.
|
|
154
156
|
|
|
157
|
+
### GitHub Release finishing step
|
|
158
|
+
|
|
159
|
+
A `--cut --push` finishes by creating the **GitHub Release** for the tag, and
|
|
160
|
+
`--release --version x.y.z` creates-or-skips one for an already-pushed tag
|
|
161
|
+
(backfill). The notes body is assembled from the `## x.y.z` CHANGELOG section as
|
|
162
|
+
shipped at the tag, the independent reviewer's one-line capability, and a
|
|
163
|
+
"Provenance & audit" footer linking the reviewed commit, the **committed** reviewer
|
|
164
|
+
verdict, the full diff, and the provenance-attested npm version.
|
|
165
|
+
|
|
166
|
+
This step is **distribution upside, not a correctness gate**: the load-bearing
|
|
167
|
+
artifacts (the tag and the provenance-attested npm publish) already exist when it
|
|
168
|
+
runs. Therefore `gh` is **not** part of the node/git portability floor — it runs
|
|
169
|
+
ONLY in the human `--cut --push` / `--release` paths (never a gate or CI path) and
|
|
170
|
+
is **idempotent** (skips if the Release already exists).
|
|
171
|
+
|
|
172
|
+
Failure semantics differ by mode: in the **`--cut --push` finishing step** an
|
|
173
|
+
absent/unauthenticated/erroring `gh` **skips with a stderr note and never fails the
|
|
174
|
+
cut** (the tag and npm publish stand) — opt out entirely with `--no-release`. In the
|
|
175
|
+
explicit **`--release` backfill** it **fails closed** (exit 1) with guidance, since
|
|
176
|
+
the operator asked for it directly; add `--soft` to downgrade `--release` to the same
|
|
177
|
+
best-effort skip-not-fail behavior.
|
|
178
|
+
|
|
179
|
+
Honesty: the notes claim the gated flow ("independent release-reviewer, verdict
|
|
180
|
+
above") **only when a committed `APPROVED` verdict is found at the tag**; backfilling
|
|
181
|
+
an ungated tag emits a neutral caveat instead and warns on stderr — the notes never
|
|
182
|
+
assert a review that isn't there. Test seam: `CW_RELEASE_FLOW_GH_CMD` swaps the `gh`
|
|
183
|
+
binary for a stub (spawned `shell:false`) so the smoke exercises it offline.
|
|
184
|
+
|
|
155
185
|
0.1.51
|
|
156
186
|
|
|
157
187
|
0.1.76
|
|
@@ -165,3 +195,4 @@ also get generated MCP manifests (`.gemini-plugin/`, `.opencode-plugin/`) so the
|
|
|
165
195
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
166
196
|
|
|
167
197
|
_No changes to the release-flow tooling in v0.1.81; this release was cut through the existing gate->review->tag flow._
|
|
198
|
+
_No changes to the release-tooling contract in v0.1.82._
|
|
@@ -399,3 +399,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
399
399
|
## Resume Drive, Inspect-Archive & Restore Re-Prove (v0.1.81)
|
|
400
400
|
|
|
401
401
|
v0.1.81 adds `run resume <id> --drive/--once` (continue an interrupted run via the agent-drive loop; default resume stays read-only and byte-identical), `run inspect-archive PATH` (read-only archive integrity check that names any offending file without importing), and restore-time hardening: `verify-import` now re-proves the trust-audit chain on restore and gains `--strict`, and `CW_REQUIRE_ARCHIVE_INTEGRITY=1` refuses a stripped-integrity archive before any write.
|
|
402
|
+
_No behavioral change in v0.1.82 (run resolution now threads an explicit base directory via CoolWorkflowRunner.withBaseDir instead of mutating process.cwd; the resolved run is unchanged)._
|
|
@@ -199,3 +199,4 @@ Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, dif
|
|
|
199
199
|
## Deterministic Freed Manifest (v0.1.81)
|
|
200
200
|
|
|
201
201
|
The freed manifest is path-sorted before it feeds `tombstoneHash`, so reclamation's write-ahead tombstone hash-chain is reproducible across hosts regardless of filesystem enumeration order. Reclaimed tiers, the re-point seam, and the default (reclaim-nothing) policy are unchanged.
|
|
202
|
+
_No changes in v0.1.82._
|
|
@@ -277,3 +277,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
277
277
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
278
278
|
|
|
279
279
|
_No changes to the state-explosion management surface in v0.1.81 (the module was carved into behavior-preserving siblings; output is byte-identical)._
|
|
280
|
+
_No changes in v0.1.82._
|
|
@@ -213,3 +213,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
213
213
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
214
214
|
|
|
215
215
|
_No changes to the team-collaboration surface in v0.1.81._
|
|
216
|
+
_No changes in v0.1.82._
|
|
@@ -221,3 +221,4 @@ Migration DAG with reversible edges (v0.1.45), capability auto-discovery (v0.1.4
|
|
|
221
221
|
Adds the opt-in fast architecture-review lane: scoped JSONL source contexts, diff-aware exports, reusable Map and Assess results, measurable wrapper metrics, actionable background full-review handoff, and userland model policy flags for routing fast/strong workers without changing the full review contract.
|
|
222
222
|
|
|
223
223
|
_No changes to the Web / Desktop Workbench in v0.1.81._
|
|
224
|
+
_No changes in v0.1.82._
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"_comment": "SINGLE SOURCE OF TRUTH for every vendor manifest. Edit THIS file, then run `npm run gen:manifests`. Do NOT hand-edit the generated vendor manifests (.claude-plugin/, .codex-plugin/, .agents/, .mcp.json) — `npm run gen:manifests -- --check` (run by release:check) will fail if they drift from this source.",
|
|
3
3
|
"identity": {
|
|
4
4
|
"name": "cool-workflow",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.82",
|
|
6
6
|
"license": "BSD-2-Clause",
|
|
7
7
|
"homepage": "https://github.com/coo1white/cool-workflow",
|
|
8
8
|
"author": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"runtime": {
|
|
27
27
|
"description": "Runtime-kernel source context for state, orchestration, scheduling, execution, and shared types.",
|
|
28
|
-
"maxLines":
|
|
28
|
+
"maxLines": 42000,
|
|
29
29
|
"include": [
|
|
30
30
|
"plugins/cool-workflow/src/**",
|
|
31
31
|
"plugins/cool-workflow/package.json",
|
package/package.json
CHANGED
|
@@ -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.
|
|
86
|
+
"Cool Workflow v0.1.82",
|
|
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.
|
|
120
|
+
assert.equal(summary.version, "0.1.82");
|
|
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.
|
|
127
|
+
assert.equal(shown.app.version, "0.1.82");
|
|
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.
|
|
138
|
+
assert.equal(state.workflow.app.version, "0.1.82");
|
|
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`);
|