cool-workflow 0.1.97 → 0.2.0
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 +11 -2
- 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/cli/dispatch.js +236 -0
- package/dist/cli/entry.js +120 -0
- package/dist/cli/io.js +21 -4
- package/dist/cli/parseargv.js +157 -0
- package/dist/cli.js +6 -33
- package/dist/core/capability-table.js +3534 -0
- package/dist/core/format/help.js +314 -0
- package/dist/{state-explosion/format.js → core/format/state-explosion-text.js} +10 -1
- package/dist/core/hash.js +137 -0
- package/dist/core/multi-agent/candidate-scoring.js +219 -0
- package/dist/core/multi-agent/collaboration.js +481 -0
- package/dist/core/multi-agent/coordinator.js +515 -0
- package/dist/core/multi-agent/eval-replay.js +306 -0
- package/dist/core/multi-agent/runtime.js +929 -0
- package/dist/core/multi-agent/topology.js +298 -0
- package/dist/core/multi-agent/trust-policy.js +197 -0
- package/dist/core/pipeline/commit-gate.js +320 -0
- package/dist/{pipeline-contract.js → core/pipeline/contract.js} +24 -37
- package/dist/core/pipeline/dispatch.js +103 -0
- package/dist/core/pipeline/drive-decide.js +227 -0
- package/dist/core/pipeline/error-feedback.js +161 -0
- package/dist/core/pipeline/loop-expansion.js +124 -0
- package/dist/{result-normalize.js → core/pipeline/result-normalize.js} +14 -37
- package/dist/core/pipeline/runner.js +230 -0
- package/dist/{contract-migration.js → core/state/contract-migration.js} +68 -92
- package/dist/{state-migrations.js → core/state/migrations.js} +103 -96
- package/dist/core/state/node-projection.js +95 -0
- package/dist/core/state/node-snapshot.js +230 -0
- package/dist/core/state/run-paths.js +93 -0
- package/dist/{schema-validate.js → core/state/schema-validate.js} +35 -28
- package/dist/core/state/schema.js +50 -0
- package/dist/core/state/state-explosion/digest.js +243 -0
- package/dist/core/state/state-explosion/graph.js +527 -0
- package/dist/{state-explosion → core/state/state-explosion}/helpers.js +34 -3
- package/dist/core/state/state-explosion/report.js +187 -0
- package/dist/{state-explosion → core/state/state-explosion}/size.js +25 -7
- package/dist/{state-node.js → core/state/state-node.js} +90 -113
- package/dist/core/state/types.js +19 -0
- package/dist/{validation.js → core/state/validation.js} +64 -131
- package/dist/core/trust/evidence-grounding.js +134 -0
- package/dist/core/trust/ledger.js +199 -0
- package/dist/{telemetry-attestation.js → core/trust/telemetry-attestation.js} +94 -68
- package/dist/core/trust/telemetry-ledger.js +127 -0
- package/dist/core/types.js +20 -0
- package/dist/core/version.js +16 -0
- package/dist/{workflow-app-framework.js → core/workflow-apps/app-schema.js} +337 -426
- package/dist/mcp/dispatch.js +104 -0
- package/dist/mcp/server.js +144 -0
- package/dist/mcp-server.js +6 -84
- package/dist/{agent-config.js → shell/agent-config.js} +118 -71
- package/dist/shell/app-run-cli.js +88 -0
- package/dist/shell/audit-cli.js +259 -0
- package/dist/shell/audit-provenance.js +83 -0
- package/dist/shell/candidate-scoring-io.js +459 -0
- package/dist/shell/collaboration-io.js +264 -0
- package/dist/shell/commit-summary.js +104 -0
- package/dist/shell/commit.js +290 -0
- package/dist/shell/coordinator-io.js +476 -0
- package/dist/shell/demo-cli.js +19 -0
- package/dist/shell/dispatch.js +162 -0
- package/dist/{doctor.js → shell/doctor.js} +123 -56
- package/dist/shell/drive.js +873 -0
- package/dist/shell/error-feedback-io.js +305 -0
- package/dist/shell/eval-io.js +473 -0
- package/dist/{multi-agent-eval/format.js → shell/eval-text.js} +78 -49
- package/dist/{evidence-reasoning.js → shell/evidence-reasoning.js} +124 -255
- package/dist/shell/exec-backend-cli.js +88 -0
- package/dist/shell/execution-backend/agent.js +475 -0
- package/dist/shell/execution-backend/ci.js +15 -0
- package/dist/shell/execution-backend/container.js +69 -0
- package/dist/shell/execution-backend/envelopes.js +55 -0
- package/dist/shell/execution-backend/local.js +113 -0
- package/dist/shell/execution-backend/probes.js +175 -0
- package/dist/shell/execution-backend/registry.js +402 -0
- package/dist/shell/execution-backend/remote.js +128 -0
- package/dist/shell/execution-backend/types.js +11 -0
- package/dist/shell/feedback-cli.js +81 -0
- package/dist/shell/feedback-operations.js +48 -0
- package/dist/shell/fs-atomic.js +276 -0
- package/dist/shell/harness.js +98 -0
- package/dist/shell/ledger-cli.js +212 -0
- package/dist/shell/ledger-io.js +169 -0
- package/dist/shell/man-cli.js +89 -0
- package/dist/shell/metrics-cli.js +98 -0
- package/dist/shell/multi-agent-cli.js +1002 -0
- package/dist/shell/multi-agent-host.js +563 -0
- package/dist/shell/multi-agent-io.js +387 -0
- package/dist/{multi-agent-operator-ux.js → shell/multi-agent-operator-ux.js} +234 -191
- package/dist/shell/node-store.js +124 -0
- package/dist/{observability/format.js → shell/observability-format.js} +7 -1
- package/dist/{observability/intake.js → shell/observability-intake.js} +79 -56
- package/dist/{observability.js → shell/observability.js} +159 -332
- package/dist/{onramp.js → shell/onramp.js} +11 -0
- package/dist/{operator-ux/format.js → shell/operator-ux-text.js} +250 -239
- package/dist/shell/operator-ux.js +431 -0
- package/dist/shell/orchestrator.js +231 -0
- package/dist/shell/pipeline-cli.js +667 -0
- package/dist/shell/pipeline.js +217 -0
- package/dist/shell/reclamation-io.js +1366 -0
- package/dist/shell/registry-cli.js +329 -0
- package/dist/{remote-source.js → shell/remote-source.js} +12 -5
- package/dist/shell/report-cli.js +101 -0
- package/dist/shell/report-view-cli.js +117 -0
- package/dist/{orchestrator → shell}/report.js +289 -282
- package/dist/shell/reporter.js +62 -0
- package/dist/shell/run-export-cli.js +106 -0
- package/dist/shell/run-export.js +680 -0
- package/dist/shell/run-registry-io.js +1014 -0
- package/dist/shell/run-store.js +164 -0
- package/dist/{sandbox-profile.js → shell/sandbox-profile.js} +134 -95
- package/dist/{scheduler.js → shell/scheduler-io.js} +248 -48
- package/dist/shell/scheduling-io.js +311 -0
- package/dist/shell/state-cli.js +181 -0
- package/dist/shell/state-explosion-cli.js +197 -0
- package/dist/shell/telemetry-cli.js +85 -0
- package/dist/{telemetry-demo.js → shell/telemetry-demo.js} +149 -119
- package/dist/shell/telemetry-ledger-io.js +132 -0
- package/dist/{term.js → shell/term.js} +36 -46
- package/dist/shell/topology-io.js +361 -0
- package/dist/shell/trust-audit.js +471 -0
- package/dist/{multi-agent-trust.js → shell/trust-policy-io.js} +67 -205
- package/dist/shell/verifier.js +48 -0
- package/dist/shell/workbench-host.js +250 -0
- package/dist/shell/workbench-text.js +18 -0
- package/dist/shell/workbench.js +175 -0
- package/dist/shell/worker-cli.js +124 -0
- package/dist/shell/worker-isolation.js +852 -0
- package/dist/shell/workflow-app-loader.js +650 -0
- package/docs/agent-delegation-drive.7.md +4 -0
- package/docs/cli-mcp-parity.7.md +284 -211
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +4 -0
- package/docs/cross-agent-ledger.7.md +217 -0
- package/docs/designs/handoff-ledger.md +145 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
- package/docs/execution-backends.7.md +4 -0
- package/docs/handoff-setup.md +120 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +4 -0
- package/docs/multi-agent-operator-ux.7.md +4 -0
- package/docs/node-snapshot-diff-replay.7.md +4 -0
- package/docs/observability-cost-accounting.7.md +4 -0
- package/docs/project-index.md +143 -71
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +4 -0
- package/docs/run-registry-control-plane.7.md +4 -0
- package/docs/run-retention-reclamation.7.md +25 -0
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/web-desktop-workbench.7.md +4 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +9 -13
- package/package.json +1 -1
- package/scripts/agents/codex-agent.js +34 -4
- package/scripts/agents/cw-attest-wrap.js +2 -2
- package/scripts/bump-version.js +4 -3
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +30 -10
- package/scripts/dogfood-architecture-review.js +2 -3
- package/scripts/dogfood-release.js +3 -3
- package/scripts/gen-parity-doc.js +15 -2
- package/scripts/golden-path.js +4 -4
- package/scripts/onramp-check.js +1 -1
- package/scripts/parity-check.js +38 -21
- package/scripts/release-flow.js +9 -3
- package/scripts/sync-project-index.js +51 -27
- package/scripts/validate-run-state-schema.js +2 -2
- package/scripts/version-sync-check.js +30 -30
- package/dist/candidate-scoring.js +0 -729
- package/dist/capability-core.js +0 -1186
- package/dist/capability-registry.js +0 -879
- package/dist/cli/command-surface.js +0 -490
- package/dist/cli/format.js +0 -56
- package/dist/cli/handlers/audit.js +0 -82
- package/dist/cli/handlers/blackboard.js +0 -81
- package/dist/cli/handlers/candidate.js +0 -40
- package/dist/cli/handlers/clones.js +0 -34
- package/dist/cli/handlers/collaboration.js +0 -61
- package/dist/cli/handlers/eval.js +0 -40
- package/dist/cli/handlers/maintenance.js +0 -107
- package/dist/cli/handlers/multi-agent.js +0 -165
- package/dist/cli/handlers/node.js +0 -41
- package/dist/cli/handlers/operational.js +0 -155
- package/dist/cli/handlers/operator.js +0 -146
- package/dist/cli/handlers/registry.js +0 -68
- package/dist/cli/handlers/run.js +0 -153
- package/dist/cli/handlers/scheduling.js +0 -132
- package/dist/cli/handlers/workbench.js +0 -41
- package/dist/cli/handlers/worker.js +0 -45
- package/dist/cli/run-summary.js +0 -45
- package/dist/clones.js +0 -162
- package/dist/collaboration.js +0 -726
- package/dist/commit.js +0 -592
- package/dist/compare.js +0 -18
- package/dist/coordinator/classify.js +0 -45
- package/dist/coordinator/paths.js +0 -42
- package/dist/coordinator/util.js +0 -126
- package/dist/coordinator.js +0 -990
- package/dist/daemon.js +0 -44
- package/dist/dispatch.js +0 -250
- package/dist/drive.js +0 -827
- package/dist/error-feedback.js +0 -419
- package/dist/evidence-grounding.js +0 -184
- package/dist/execution-backend/agent.js +0 -294
- package/dist/execution-backend/probes.js +0 -112
- package/dist/execution-backend/util.js +0 -47
- package/dist/execution-backend.js +0 -961
- package/dist/gates.js +0 -48
- package/dist/harness.js +0 -61
- package/dist/loop-expansion.js +0 -60
- package/dist/mcp/tool-call.js +0 -434
- package/dist/mcp/tool-definitions.js +0 -1040
- package/dist/mcp-surface.js +0 -30
- package/dist/multi-agent/graph.js +0 -84
- package/dist/multi-agent/helpers.js +0 -141
- package/dist/multi-agent/ids.js +0 -20
- package/dist/multi-agent/paths.js +0 -22
- package/dist/multi-agent-eval/normalize.js +0 -51
- package/dist/multi-agent-eval.js +0 -678
- package/dist/multi-agent-host.js +0 -777
- package/dist/multi-agent.js +0 -984
- package/dist/node-projection.js +0 -59
- package/dist/node-snapshot.js +0 -260
- package/dist/operator-ux.js +0 -631
- package/dist/orchestrator/app-operations.js +0 -211
- package/dist/orchestrator/audit-operations.js +0 -182
- package/dist/orchestrator/candidate-operations.js +0 -117
- package/dist/orchestrator/cli-options.js +0 -294
- package/dist/orchestrator/collaboration-operations.js +0 -86
- package/dist/orchestrator/feedback-operations.js +0 -81
- package/dist/orchestrator/host-operations.js +0 -78
- package/dist/orchestrator/lifecycle-operations.js +0 -626
- package/dist/orchestrator/migration-operations.js +0 -44
- package/dist/orchestrator/multi-agent-operations.js +0 -362
- package/dist/orchestrator/topology-operations.js +0 -84
- package/dist/orchestrator.js +0 -917
- package/dist/pipeline-runner.js +0 -285
- package/dist/reclamation/hash.js +0 -72
- package/dist/reclamation.js +0 -812
- package/dist/reporter.js +0 -67
- package/dist/run-export.js +0 -784
- package/dist/run-registry/derive.js +0 -175
- package/dist/run-registry/format.js +0 -124
- package/dist/run-registry/gc.js +0 -251
- package/dist/run-registry/policy.js +0 -16
- package/dist/run-registry/queue.js +0 -115
- package/dist/run-registry.js +0 -850
- package/dist/run-state-schema.js +0 -68
- package/dist/scheduling.js +0 -184
- package/dist/state-explosion.js +0 -1014
- package/dist/state.js +0 -367
- package/dist/telemetry-ledger.js +0 -196
- package/dist/topology.js +0 -565
- package/dist/triggers.js +0 -184
- package/dist/trust-audit.js +0 -644
- package/dist/types/blackboard.js +0 -2
- package/dist/types/candidate.js +0 -2
- package/dist/types/collaboration.js +0 -2
- package/dist/types/core.js +0 -2
- package/dist/types/drive.js +0 -10
- package/dist/types/error-feedback.js +0 -2
- package/dist/types/evidence-reasoning.js +0 -2
- package/dist/types/execution-backend.js +0 -2
- package/dist/types/multi-agent.js +0 -2
- package/dist/types/observability.js +0 -2
- package/dist/types/pipeline.js +0 -2
- package/dist/types/reclamation.js +0 -8
- package/dist/types/report-bundle.js +0 -6
- package/dist/types/result.js +0 -2
- package/dist/types/run-registry.js +0 -2
- package/dist/types/run.js +0 -2
- package/dist/types/sandbox.js +0 -2
- package/dist/types/schedule.js +0 -2
- package/dist/types/state-node.js +0 -2
- package/dist/types/topology.js +0 -2
- package/dist/types/trust.js +0 -2
- package/dist/types/workbench.js +0 -2
- package/dist/types/worker.js +0 -2
- package/dist/types/workflow-app.js +0 -2
- package/dist/types.js +0 -44
- package/dist/util/fingerprint.js +0 -19
- package/dist/util/fingerprint.test.js +0 -27
- package/dist/verifier.js +0 -78
- package/dist/version.js +0 -8
- package/dist/workbench-host.js +0 -182
- package/dist/workbench.js +0 -192
- package/dist/worker-accept/acceptance.js +0 -114
- package/dist/worker-accept/blackboard-fanout.js +0 -80
- package/dist/worker-accept/blackboard-linkage.js +0 -19
- package/dist/worker-accept/context.js +0 -2
- package/dist/worker-accept/telemetry-ledger.js +0 -126
- package/dist/worker-accept/validation.js +0 -77
- package/dist/worker-accept/verifier-completion.js +0 -73
- package/dist/worker-isolation/helpers.js +0 -51
- package/dist/worker-isolation/paths.js +0 -46
- package/dist/worker-isolation.js +0 -656
- package/dist/workflow-api.js +0 -131
- /package/dist/{types → core/types}/boundary.js +0 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// shell/operator-ux.ts — the operator console surface: `cw status`,
|
|
3
|
+
// `cw graph`, `cw operator status|report|graph`.
|
|
4
|
+
//
|
|
5
|
+
// MILESTONE 11 (reporting/observability). A scoped-but-real port of the
|
|
6
|
+
// old build's src/operator-ux.ts + src/orchestrator/report.ts's
|
|
7
|
+
// `summarizeRun`: every summary here reads real run state through the
|
|
8
|
+
// same summarizers report.ts and the multi-agent/candidate/trust shell
|
|
9
|
+
// modules already use (no duplicate logic, no fabricated fields). The
|
|
10
|
+
// old build's deeper multi-agent-operator-ux / topology-trust cross-
|
|
11
|
+
// summaries are folded in at a scoped level sufficient for this
|
|
12
|
+
// milestone's conformance surface (candidates/feedback/commits/trust/
|
|
13
|
+
// nextActions on `operator status`, the deterministic run graph) rather
|
|
14
|
+
// than ported in full — a later milestone can extend these without
|
|
15
|
+
// changing this file's exported shapes.
|
|
16
|
+
//
|
|
17
|
+
// Evidence: SPEC/reporting-ux.md "Operator UX human text", "Exit codes";
|
|
18
|
+
// plugins/cool-workflow/src/operator-ux.ts:1-788,
|
|
19
|
+
// plugins/cool-workflow/src/orchestrator/report.ts:120-149 (byte-exact
|
|
20
|
+
// source for the ported pieces).
|
|
21
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
24
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
25
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
26
|
+
}
|
|
27
|
+
Object.defineProperty(o, k2, desc);
|
|
28
|
+
}) : (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
o[k2] = m[k];
|
|
31
|
+
}));
|
|
32
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
33
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
34
|
+
}) : function(o, v) {
|
|
35
|
+
o["default"] = v;
|
|
36
|
+
});
|
|
37
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
38
|
+
var ownKeys = function(o) {
|
|
39
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
40
|
+
var ar = [];
|
|
41
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
42
|
+
return ar;
|
|
43
|
+
};
|
|
44
|
+
return ownKeys(o);
|
|
45
|
+
};
|
|
46
|
+
return function (mod) {
|
|
47
|
+
if (mod && mod.__esModule) return mod;
|
|
48
|
+
var result = {};
|
|
49
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
50
|
+
__setModuleDefault(result, mod);
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
})();
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.summarizeRun = summarizeRun;
|
|
56
|
+
exports.adviseNoRun = adviseNoRun;
|
|
57
|
+
exports.summarizeCandidateOperatorRecords = summarizeCandidateOperatorRecords;
|
|
58
|
+
exports.summarizeOperatorRun = summarizeOperatorRun;
|
|
59
|
+
exports.buildOperatorGraph = buildOperatorGraph;
|
|
60
|
+
const path = __importStar(require("node:path"));
|
|
61
|
+
const dispatch_1 = require("../core/pipeline/dispatch");
|
|
62
|
+
const candidate_scoring_io_1 = require("./candidate-scoring-io");
|
|
63
|
+
const trust_audit_1 = require("./trust-audit");
|
|
64
|
+
const multi_agent_io_1 = require("./multi-agent-io");
|
|
65
|
+
const coordinator_io_1 = require("./coordinator-io");
|
|
66
|
+
const topology_io_1 = require("./topology-io");
|
|
67
|
+
const multi_agent_operator_ux_1 = require("./multi-agent-operator-ux");
|
|
68
|
+
const trust_policy_io_1 = require("./trust-policy-io");
|
|
69
|
+
function countBy(values, key) {
|
|
70
|
+
const counts = {};
|
|
71
|
+
for (const value of values)
|
|
72
|
+
counts[key(value)] = (counts[key(value)] || 0) + 1;
|
|
73
|
+
return counts;
|
|
74
|
+
}
|
|
75
|
+
function firstRunnablePhase(run) {
|
|
76
|
+
return run.phases.find((phase) => phase.status === "pending" || phase.status === "running");
|
|
77
|
+
}
|
|
78
|
+
function summarizeWorkersCounts(run) {
|
|
79
|
+
const workers = run.workers || [];
|
|
80
|
+
return { total: workers.length, byStatus: countBy(workers, (w) => w.status) };
|
|
81
|
+
}
|
|
82
|
+
/** `summarizeRun` — byte-exact port of the old build's
|
|
83
|
+
* src/orchestrator/report.ts:120-149. Used by `cw status <id> --json`
|
|
84
|
+
* and `cw report <id>`'s internals. */
|
|
85
|
+
function summarizeRun(run) {
|
|
86
|
+
(0, dispatch_1.updatePhaseStatuses)(run);
|
|
87
|
+
const workerSummary = summarizeWorkersCounts(run);
|
|
88
|
+
const createdAtMs = Date.parse(run.createdAt);
|
|
89
|
+
const updatedAtMs = Date.parse(run.updatedAt);
|
|
90
|
+
const durationMs = Number.isFinite(createdAtMs) && Number.isFinite(updatedAtMs) ? Math.max(0, updatedAtMs - createdAtMs) : undefined;
|
|
91
|
+
return {
|
|
92
|
+
runId: run.id,
|
|
93
|
+
workflowId: run.workflow.id,
|
|
94
|
+
app: run.workflow.app,
|
|
95
|
+
phases: run.phases,
|
|
96
|
+
tasks: {
|
|
97
|
+
total: run.tasks.length,
|
|
98
|
+
pending: run.tasks.filter((t) => t.status === "pending").length,
|
|
99
|
+
running: run.tasks.filter((t) => t.status === "running").length,
|
|
100
|
+
failed: run.tasks.filter((t) => t.status === "failed").length,
|
|
101
|
+
completed: run.tasks.filter((t) => t.status === "completed").length,
|
|
102
|
+
},
|
|
103
|
+
loopStage: run.loopStage,
|
|
104
|
+
durationMs,
|
|
105
|
+
progressPercent: run.tasks.length ? Math.round((run.tasks.filter((t) => t.status === "completed").length / run.tasks.length) * 100) : 0,
|
|
106
|
+
next: firstRunnablePhase(run)?.name || null,
|
|
107
|
+
reportPath: run.paths.report,
|
|
108
|
+
commits: run.commits,
|
|
109
|
+
workers: workerSummary,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/** `cw status` with no run id: the fixed advice (byte-exact to the old
|
|
113
|
+
* build's adviseNoRun). */
|
|
114
|
+
function adviseNoRun() {
|
|
115
|
+
return [
|
|
116
|
+
{
|
|
117
|
+
command: "node scripts/cw.js plan <workflow-id> --repo <path>",
|
|
118
|
+
reason: "No run id is available yet; create a workflow run before dispatching or recording evidence.",
|
|
119
|
+
priority: "high",
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
function summarizePhases(run) {
|
|
124
|
+
return run.phases.map((phase) => {
|
|
125
|
+
const phaseTasks = run.tasks.filter((t) => phase.taskIds.includes(t.id));
|
|
126
|
+
const byStatus = countBy(phaseTasks, (t) => t.status);
|
|
127
|
+
return { id: phase.id, name: phase.name, status: phase.status, tasks: { total: phaseTasks.length, ...byStatus } };
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function summarizeTasks(tasks) {
|
|
131
|
+
const byId = (status) => tasks.filter((t) => t.status === status).map((t) => t.id);
|
|
132
|
+
return {
|
|
133
|
+
total: tasks.length,
|
|
134
|
+
byStatus: countBy(tasks, (t) => t.status),
|
|
135
|
+
pending: byId("pending"),
|
|
136
|
+
running: byId("running"),
|
|
137
|
+
failed: byId("failed"),
|
|
138
|
+
completed: byId("completed"),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/** Port of the old build's summarizeOperatorCandidates: the counts PLUS the
|
|
142
|
+
* selected/readyForCommit/problems/candidates detail the `candidate summary`
|
|
143
|
+
* verb and operator panel both read. */
|
|
144
|
+
function summarizeOperatorCandidates(run) {
|
|
145
|
+
const counts = (0, candidate_scoring_io_1.summarizeCandidates)(run);
|
|
146
|
+
const candidates = [...(run.candidates || [])].sort((left, right) => left.id.localeCompare(right.id));
|
|
147
|
+
const selections = [...(run.candidateSelections || [])].sort((left, right) => left.id.localeCompare(right.id));
|
|
148
|
+
const commits = run.commits || [];
|
|
149
|
+
const selectedIds = new Set(selections.map((selection) => selection.candidateId));
|
|
150
|
+
const readyForCommit = selections
|
|
151
|
+
.filter((selection) => {
|
|
152
|
+
const candidate = candidates.find((item) => item.id === selection.candidateId);
|
|
153
|
+
if (!candidate || candidate.status !== "verified" || !selection.scoreId)
|
|
154
|
+
return false;
|
|
155
|
+
return !commits.some((commit) => commit.verifierGated && commit.selectionId === selection.id);
|
|
156
|
+
})
|
|
157
|
+
.map((selection) => ({ candidateId: selection.candidateId, selectionId: selection.id, scoreId: selection.scoreId, verifierNodeId: selection.verifierNodeId }));
|
|
158
|
+
const problems = [];
|
|
159
|
+
for (const candidate of candidates) {
|
|
160
|
+
if ((candidate.status === "registered" || candidate.status === "scored") && !(candidate.evidence || []).length)
|
|
161
|
+
problems.push(`candidate ${candidate.id} has no evidence`);
|
|
162
|
+
if (candidate.status === "registered" && !(candidate.scores || []).length)
|
|
163
|
+
problems.push(`candidate ${candidate.id} has not been scored`);
|
|
164
|
+
if ((candidate.status === "selected" || candidate.status === "verified") && !selections.some((selection) => selection.candidateId === candidate.id))
|
|
165
|
+
problems.push(`candidate ${candidate.id} status is ${candidate.status} but no selection record exists`);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
...counts,
|
|
169
|
+
latestRankingPath: counts.rankingPath,
|
|
170
|
+
selected: selections.map((selection) => ({ selectionId: selection.id, candidateId: selection.candidateId, scoreId: selection.scoreId, verifierNodeId: selection.verifierNodeId })),
|
|
171
|
+
readyForCommit,
|
|
172
|
+
problems: problems.sort(),
|
|
173
|
+
candidates: candidates.map((candidate) => ({ id: candidate.id, kind: candidate.kind, status: candidate.status, scoreCount: (candidate.scores || []).length, selected: selectedIds.has(candidate.id), feedbackIds: candidate.feedbackIds || [], resultPath: candidate.resultPath })),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/** `cw candidate summary <run>` — the operator candidate summary (with
|
|
177
|
+
* readyForCommit/selected/problems). Exported so the candidate.summary CLI
|
|
178
|
+
* verb returns the same rich shape the old build's
|
|
179
|
+
* summarizeCandidateOperatorRecords did. */
|
|
180
|
+
function summarizeCandidateOperatorRecords(run) {
|
|
181
|
+
return summarizeOperatorCandidates(run);
|
|
182
|
+
}
|
|
183
|
+
function summarizeOperatorFeedback(run) {
|
|
184
|
+
const records = (run.feedback || []);
|
|
185
|
+
return {
|
|
186
|
+
total: records.length,
|
|
187
|
+
byStatus: countBy(records, (r) => r.status),
|
|
188
|
+
bySeverity: countBy(records, (r) => r.severity),
|
|
189
|
+
byClassification: countBy(records, (r) => r.classification),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function summarizeOperatorCommits(run) {
|
|
193
|
+
const commits = [...(run.commits || [])].sort((left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id));
|
|
194
|
+
return {
|
|
195
|
+
total: commits.length,
|
|
196
|
+
verifierGated: commits.filter((c) => c.verifierGated).length,
|
|
197
|
+
checkpoints: commits.filter((c) => !c.verifierGated).length,
|
|
198
|
+
latest: commits.at(-1),
|
|
199
|
+
commits,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function summarizeOperatorWorkers(run) {
|
|
203
|
+
const workers = (run.workers || []).slice().sort((a, b) => a.id.localeCompare(b.id));
|
|
204
|
+
return {
|
|
205
|
+
total: workers.length,
|
|
206
|
+
byStatus: countBy(workers, (w) => w.status),
|
|
207
|
+
workers: workers.map((w) => ({ id: w.id, taskId: w.taskId, status: w.status, manifestPath: w.workerDir, resultPath: w.resultPath })),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/** Next-action advice: a scoped-but-real subset of the old build's
|
|
211
|
+
* priority-ordered advice ladder (open feedback -> failed worker ->
|
|
212
|
+
* running tasks -> pending tasks -> ready-for-commit -> fallback
|
|
213
|
+
* `report --show`). */
|
|
214
|
+
/** Next-action advice — port of the old build's adviseNextSteps
|
|
215
|
+
* (src/operator-ux.ts): a single ordered chain of guard arms, each
|
|
216
|
+
* returning as soon as it fires so the operator sees the ONE next step
|
|
217
|
+
* the run is waiting on. The candidate lifecycle arms (register -> score
|
|
218
|
+
* -> rank/select -> commit) are the part v2's earlier scoped port dropped;
|
|
219
|
+
* the operator-ux smoke walks that whole chain. Reads candidate/selection
|
|
220
|
+
* state off `run` directly, same as the old build. */
|
|
221
|
+
function adviseNextSteps(run, ctx) {
|
|
222
|
+
const actions = [];
|
|
223
|
+
const feedbackRecords = (run.feedback || []);
|
|
224
|
+
const openFeedback = feedbackRecords.filter((record) => record.status === "open");
|
|
225
|
+
if (openFeedback.length) {
|
|
226
|
+
const feedback = openFeedback[0];
|
|
227
|
+
actions.push({ command: `node scripts/cw.js feedback show ${run.id} ${feedback.id}`, reason: `Open ${feedback.severity} ${feedback.classification} feedback should be inspected before more dispatch.`, priority: "high" });
|
|
228
|
+
actions.push({ command: `node scripts/cw.js feedback task ${run.id} ${feedback.id}`, reason: "Create a correction task if the feedback is actionable.", priority: "normal" });
|
|
229
|
+
return actions;
|
|
230
|
+
}
|
|
231
|
+
const failedWorker = ctx.workers.workers.find((w) => w.status === "failed" || w.status === "rejected");
|
|
232
|
+
if (failedWorker) {
|
|
233
|
+
actions.push({ command: `node scripts/cw.js feedback list ${run.id}`, reason: `Worker ${failedWorker.id} is ${failedWorker.status}; inspect linked feedback before retrying.`, priority: "high" });
|
|
234
|
+
return actions;
|
|
235
|
+
}
|
|
236
|
+
if (ctx.tasks.running.length) {
|
|
237
|
+
const worker = ctx.workers.workers.find((w) => w.status === "running" || w.status === "allocated");
|
|
238
|
+
actions.push({ command: worker ? `node scripts/cw.js worker manifest ${run.id} ${worker.id}` : `node scripts/cw.js worker list ${run.id}`, reason: "Running workers need their manifests inspected and final output recorded.", priority: "high" });
|
|
239
|
+
if (worker && worker.resultPath) {
|
|
240
|
+
actions.push({ command: `node scripts/cw.js worker output ${run.id} ${worker.id} ${worker.resultPath}`, reason: "Record the worker result after its result.md is ready.", priority: "normal" });
|
|
241
|
+
}
|
|
242
|
+
return actions;
|
|
243
|
+
}
|
|
244
|
+
if (ctx.tasks.pending.length) {
|
|
245
|
+
const limit = Math.min(ctx.tasks.pending.length, run.workflow.limits?.maxConcurrentAgents || 4);
|
|
246
|
+
actions.push({ command: `node scripts/cw.js dispatch ${run.id} --limit ${limit}`, reason: `${ctx.tasks.pending.length} pending task(s) are ready for the active phase.`, priority: "high" });
|
|
247
|
+
return actions;
|
|
248
|
+
}
|
|
249
|
+
const candidateRecords = (run.candidates || []);
|
|
250
|
+
const selectionRecords = (run.candidateSelections || []);
|
|
251
|
+
const completedWithoutCandidate = (run.tasks || []).find((task) => task.status === "completed" && task.workerId && !candidateRecords.some((candidate) => candidate.workerId === task.workerId));
|
|
252
|
+
if (completedWithoutCandidate?.workerId) {
|
|
253
|
+
actions.push({ command: `node scripts/cw.js candidate register ${run.id} --worker ${completedWithoutCandidate.workerId}`, reason: "A completed worker result is available but has not been registered as a candidate.", priority: "high" });
|
|
254
|
+
return actions;
|
|
255
|
+
}
|
|
256
|
+
const unscored = candidateRecords.find((candidate) => candidate.status === "registered" && !(candidate.scores || []).length);
|
|
257
|
+
if (unscored) {
|
|
258
|
+
actions.push({ command: `node scripts/cw.js candidate score ${run.id} ${unscored.id} --criterion correctness=1 --evidence <path-or-locator>`, reason: "Registered candidates need score evidence before ranking or selection.", priority: "high" });
|
|
259
|
+
return actions;
|
|
260
|
+
}
|
|
261
|
+
const scoredWithoutSelection = candidateRecords.find((candidate) => candidate.status === "scored" && !selectionRecords.some((selection) => selection.candidateId === candidate.id));
|
|
262
|
+
if (scoredWithoutSelection) {
|
|
263
|
+
actions.push({ command: `node scripts/cw.js candidate rank ${run.id}`, reason: "Scored candidates can be ranked before selection.", priority: "high" });
|
|
264
|
+
actions.push({ command: `node scripts/cw.js candidate select ${run.id} ${scoredWithoutSelection.id}`, reason: "Select the candidate once the ranking supports it.", priority: "normal" });
|
|
265
|
+
return actions;
|
|
266
|
+
}
|
|
267
|
+
if (ctx.candidates.readyForCommit.length) {
|
|
268
|
+
const ready = ctx.candidates.readyForCommit[0];
|
|
269
|
+
actions.push({ command: `node scripts/cw.js commit ${run.id} --selection ${ready.selectionId}`, reason: "A verified selected candidate is ready for a verifier-gated commit.", priority: "high" });
|
|
270
|
+
return actions;
|
|
271
|
+
}
|
|
272
|
+
actions.push({ command: `node scripts/cw.js report ${run.id} --show`, reason: "All tracked phases are complete or no further operator action is currently available.", priority: "normal" });
|
|
273
|
+
return actions;
|
|
274
|
+
}
|
|
275
|
+
/** `cw operator status <id> --json` — a wider payload than `summarizeRun`
|
|
276
|
+
* (different capability, per SPEC/reporting-ux.md: "cw operator status
|
|
277
|
+
* <id> --json is a DIFFERENT, wider payload than cw status --json"). */
|
|
278
|
+
function summarizeOperatorRun(run) {
|
|
279
|
+
(0, dispatch_1.updatePhaseStatuses)(run);
|
|
280
|
+
const app = run.workflow.app;
|
|
281
|
+
const phases = summarizePhases(run);
|
|
282
|
+
const tasks = summarizeTasks(run.tasks);
|
|
283
|
+
const workers = summarizeOperatorWorkers(run);
|
|
284
|
+
const candidates = summarizeOperatorCandidates(run);
|
|
285
|
+
const feedback = summarizeOperatorFeedback(run);
|
|
286
|
+
const commits = summarizeOperatorCommits(run);
|
|
287
|
+
const multiAgent = (0, multi_agent_io_1.summarizeMultiAgent)(run);
|
|
288
|
+
const multiAgentOperator = (0, multi_agent_operator_ux_1.summarizeMultiAgentOperator)(run);
|
|
289
|
+
const multiAgentTrust = (0, trust_policy_io_1.summarizeMultiAgentTrust)(run);
|
|
290
|
+
const blackboard = (0, coordinator_io_1.summarizeBlackboard)(run);
|
|
291
|
+
const trust = (0, trust_audit_1.summarizeTrustAudit)(run);
|
|
292
|
+
const activePhase = phases.find((p) => p.status === "running") || phases.find((p) => p.status === "pending");
|
|
293
|
+
const blockedReasons = [];
|
|
294
|
+
for (const worker of workers.workers) {
|
|
295
|
+
if (worker.status === "failed" || worker.status === "rejected")
|
|
296
|
+
blockedReasons.push(`worker ${worker.id} ${worker.status}`);
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
runId: run.id,
|
|
300
|
+
workflowId: run.workflow.id,
|
|
301
|
+
workflowTitle: run.workflow.title,
|
|
302
|
+
appId: app?.id,
|
|
303
|
+
appVersion: app?.version,
|
|
304
|
+
loopStage: run.loopStage,
|
|
305
|
+
activePhase: activePhase?.name,
|
|
306
|
+
blocked: blockedReasons.length > 0,
|
|
307
|
+
blockedReasons,
|
|
308
|
+
phases,
|
|
309
|
+
tasks,
|
|
310
|
+
workers,
|
|
311
|
+
candidates,
|
|
312
|
+
feedback,
|
|
313
|
+
commits,
|
|
314
|
+
multiAgent,
|
|
315
|
+
multiAgentOperator,
|
|
316
|
+
multiAgentTrust,
|
|
317
|
+
blackboard,
|
|
318
|
+
trust,
|
|
319
|
+
reportPath: run.paths.report,
|
|
320
|
+
nextActions: adviseNextSteps(run, { tasks, workers, feedback, candidates }),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function workerManifestPath(worker) {
|
|
324
|
+
return path.join(worker.workerDir, "manifest.json");
|
|
325
|
+
}
|
|
326
|
+
/** `cw graph <id>` — a scoped-but-real port of the old build's
|
|
327
|
+
* buildOperatorGraph. Nodes/edges sort deterministically (kind then id
|
|
328
|
+
* for nodes; from/to/label for edges, de-duplicated), per SPEC/
|
|
329
|
+
* reporting-ux.md invariant 12. */
|
|
330
|
+
function buildOperatorGraph(run) {
|
|
331
|
+
const nodes = new Map();
|
|
332
|
+
const edgeKeys = new Set();
|
|
333
|
+
const edges = [];
|
|
334
|
+
const addNode = (id, kind, status, label, pathValue) => {
|
|
335
|
+
nodes.set(id, { id, kind, status, label, path: pathValue });
|
|
336
|
+
};
|
|
337
|
+
const addEdge = (from, to, label) => {
|
|
338
|
+
if (!from || !to)
|
|
339
|
+
return;
|
|
340
|
+
const key = `${from}\0${to}\0${label || ""}`;
|
|
341
|
+
if (edgeKeys.has(key))
|
|
342
|
+
return;
|
|
343
|
+
edgeKeys.add(key);
|
|
344
|
+
edges.push({ from, to, label });
|
|
345
|
+
};
|
|
346
|
+
addNode(`${run.id}:run`, "run", run.loopStage, run.id, run.paths.state);
|
|
347
|
+
for (const phase of run.phases || []) {
|
|
348
|
+
const phaseId = `${run.id}:phase:${phase.id}`;
|
|
349
|
+
addNode(phaseId, "phase", phase.status, phase.name);
|
|
350
|
+
addEdge(`${run.id}:run`, phaseId);
|
|
351
|
+
for (const taskId of phase.taskIds)
|
|
352
|
+
addEdge(phaseId, `${run.id}:task:${taskId}`);
|
|
353
|
+
}
|
|
354
|
+
for (const task of run.tasks || []) {
|
|
355
|
+
addNode(`${run.id}:task:${task.id}`, "task", task.status, task.id, task.taskPath);
|
|
356
|
+
if (task.dispatchId)
|
|
357
|
+
addEdge(`${run.id}:task:${task.id}`, `${run.id}:dispatch:${task.dispatchId}`);
|
|
358
|
+
if (task.resultNodeId)
|
|
359
|
+
addEdge(`${run.id}:task:${task.id}`, task.resultNodeId);
|
|
360
|
+
if (task.verifierNodeId)
|
|
361
|
+
addEdge(`${run.id}:task:${task.id}`, task.verifierNodeId);
|
|
362
|
+
}
|
|
363
|
+
for (const dispatch of run.dispatches || []) {
|
|
364
|
+
addNode(`${run.id}:dispatch:${dispatch.id}`, "dispatch", "completed", dispatch.id, dispatch.manifestPath);
|
|
365
|
+
for (const workerId of dispatch.workerIds || [])
|
|
366
|
+
addEdge(`${run.id}:dispatch:${dispatch.id}`, `${run.id}:worker:${workerId}`);
|
|
367
|
+
}
|
|
368
|
+
for (const workerRaw of run.workers || []) {
|
|
369
|
+
const worker = workerRaw;
|
|
370
|
+
addNode(`${run.id}:worker:${worker.id}`, "worker", worker.status, worker.id, workerManifestPath(worker));
|
|
371
|
+
if (worker.resultNodeId)
|
|
372
|
+
addEdge(`${run.id}:worker:${worker.id}`, worker.resultNodeId);
|
|
373
|
+
for (const feedbackId of worker.feedbackIds || [])
|
|
374
|
+
addEdge(`${run.id}:worker:${worker.id}`, `${run.id}:feedback:${feedbackId}`);
|
|
375
|
+
}
|
|
376
|
+
for (const candidate of (0, candidate_scoring_io_1.listCandidates)(run)) {
|
|
377
|
+
addNode(`${run.id}:candidate:${candidate.id}`, "candidate", candidate.status, candidate.id, candidate.resultPath);
|
|
378
|
+
if (candidate.resultNodeId)
|
|
379
|
+
addEdge(candidate.resultNodeId, `${run.id}:candidate:${candidate.id}`);
|
|
380
|
+
if (candidate.verifierNodeId)
|
|
381
|
+
addEdge(candidate.verifierNodeId, `${run.id}:candidate:${candidate.id}`, "gate");
|
|
382
|
+
for (const feedbackId of candidate.feedbackIds || [])
|
|
383
|
+
addEdge(`${run.id}:candidate:${candidate.id}`, `${run.id}:feedback:${feedbackId}`);
|
|
384
|
+
}
|
|
385
|
+
for (const selectionRaw of run.candidateSelections || []) {
|
|
386
|
+
const selection = selectionRaw;
|
|
387
|
+
addNode(`${run.id}:selection:${selection.id}`, "selection", "verified", selection.id, selection.rankingPath);
|
|
388
|
+
addEdge(`${run.id}:candidate:${selection.candidateId}`, `${run.id}:selection:${selection.id}`);
|
|
389
|
+
if (selection.verifierNodeId)
|
|
390
|
+
addEdge(selection.verifierNodeId, `${run.id}:selection:${selection.id}`, "verifier");
|
|
391
|
+
}
|
|
392
|
+
for (const commit of run.commits || []) {
|
|
393
|
+
const commitNodeId = commit.stateNodeId || `${run.id}:commit:${commit.id}`;
|
|
394
|
+
addNode(commitNodeId, "commit", commit.verifierGated ? "committed" : "completed", commit.id, commit.snapshotPath);
|
|
395
|
+
if (commit.verifierNodeId)
|
|
396
|
+
addEdge(commit.verifierNodeId, commitNodeId, "verifier");
|
|
397
|
+
if (commit.selectionId)
|
|
398
|
+
addEdge(`${run.id}:selection:${commit.selectionId}`, commitNodeId, "selection");
|
|
399
|
+
}
|
|
400
|
+
for (const feedbackRaw of run.feedback || []) {
|
|
401
|
+
const feedback = feedbackRaw;
|
|
402
|
+
addNode(`${run.id}:feedback:${feedback.id}`, "feedback", feedback.status, `${feedback.severity} ${feedback.classification}`);
|
|
403
|
+
if (feedback.nodeId)
|
|
404
|
+
addEdge(feedback.nodeId, `${run.id}:feedback:${feedback.id}`);
|
|
405
|
+
if (feedback.taskId)
|
|
406
|
+
addEdge(`${run.id}:task:${feedback.taskId}`, `${run.id}:feedback:${feedback.id}`);
|
|
407
|
+
}
|
|
408
|
+
// Fold the topology + multi-agent + blackboard graphs into the operator
|
|
409
|
+
// graph, per the old build's buildOperatorGraph (operator-ux.ts:411-419): a
|
|
410
|
+
// run's top-level `cw graph` shows topology-run, multi-agent-run/agent-group/
|
|
411
|
+
// agent-role/agent-membership/agent-fanout/agent-fanin, and the blackboard
|
|
412
|
+
// topic/message/artifact nodes alongside the pipeline nodes.
|
|
413
|
+
const topologyGraph = (0, topology_io_1.buildTopologyGraph)(run);
|
|
414
|
+
for (const node of topologyGraph.nodes)
|
|
415
|
+
addNode(node.id, node.kind, node.status, node.label, node.path);
|
|
416
|
+
for (const edge of topologyGraph.edges)
|
|
417
|
+
addEdge(edge.from, edge.to, edge.label);
|
|
418
|
+
const multiAgentGraph = (0, multi_agent_io_1.buildMultiAgentGraph)(run);
|
|
419
|
+
for (const node of multiAgentGraph.nodes)
|
|
420
|
+
addNode(node.id, node.kind, node.status, node.label, node.path);
|
|
421
|
+
for (const edge of multiAgentGraph.edges)
|
|
422
|
+
addEdge(edge.from, edge.to, edge.label);
|
|
423
|
+
const blackboardGraph = (0, coordinator_io_1.buildBlackboardGraph)(run);
|
|
424
|
+
for (const node of blackboardGraph.nodes)
|
|
425
|
+
addNode(node.id, node.kind, node.status, node.label, node.path);
|
|
426
|
+
for (const edge of blackboardGraph.edges)
|
|
427
|
+
addEdge(edge.from, edge.to, edge.label);
|
|
428
|
+
const sortedNodes = [...nodes.values()].sort((a, b) => a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id));
|
|
429
|
+
const sortedEdges = edges.slice().sort((a, b) => a.from.localeCompare(b.from) || a.to.localeCompare(b.to) || (a.label || "").localeCompare(b.label || ""));
|
|
430
|
+
return { runId: run.id, nodes: sortedNodes, edges: sortedEdges };
|
|
431
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// shell/orchestrator.ts — a THIN, SCOPED CoolWorkflowRunner facade for the two
|
|
3
|
+
// shipping tooling scripts (scripts/dogfood-release.js and
|
|
4
|
+
// scripts/dogfood-architecture-review.js) that still `require` the old flat
|
|
5
|
+
// build's `dist/orchestrator.js` and drive a run through
|
|
6
|
+
// `new CoolWorkflowRunner({ pluginRoot }).<verb>(...)`.
|
|
7
|
+
//
|
|
8
|
+
// v2 dismantled the old wide facade into core/shell functions, so this module
|
|
9
|
+
// restores ONLY the ~15 verbs those two scripts call, each a thin
|
|
10
|
+
// `loadRun -> delegate` over an EXISTING v2 shell function (mostly the
|
|
11
|
+
// `*Cli(args)` byte-behavior ports, which already replicate the old build's
|
|
12
|
+
// option-key normalization). It is a standalone tooling module: it is NOT wired
|
|
13
|
+
// into the CLI/MCP capability table and registers no capability, so the
|
|
14
|
+
// CLI<->MCP parity gate and the black-box conformance suite stay untouched.
|
|
15
|
+
//
|
|
16
|
+
// The facade is an intentional keep, not a god-class to dismantle (see the
|
|
17
|
+
// project memory note "Orchestrator facade is intentional").
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.CoolWorkflowRunner = void 0;
|
|
53
|
+
exports.drive = drive;
|
|
54
|
+
const path = __importStar(require("node:path"));
|
|
55
|
+
const run_store_1 = require("./run-store");
|
|
56
|
+
const workflow_app_loader_1 = require("./workflow-app-loader");
|
|
57
|
+
const pipeline_1 = require("./pipeline");
|
|
58
|
+
const dispatch_1 = require("./dispatch");
|
|
59
|
+
const worker_isolation_1 = require("./worker-isolation");
|
|
60
|
+
const run_store_2 = require("./run-store");
|
|
61
|
+
const trust_audit_1 = require("./trust-audit");
|
|
62
|
+
const audit_provenance_1 = require("./audit-provenance");
|
|
63
|
+
const audit_cli_1 = require("./audit-cli");
|
|
64
|
+
const multi_agent_cli_1 = require("./multi-agent-cli");
|
|
65
|
+
const commit_1 = require("./commit");
|
|
66
|
+
const report_1 = require("./report");
|
|
67
|
+
class CoolWorkflowRunner {
|
|
68
|
+
// Kept for API compatibility with the old constructor shape the scripts use
|
|
69
|
+
// (`new CoolWorkflowRunner({ pluginRoot })`). v2's workflow-app-loader finds
|
|
70
|
+
// the plugin root itself (walks up from __dirname), so this value is inert
|
|
71
|
+
// here — the run-resolving cwd is `baseDir` (below).
|
|
72
|
+
pluginRoot;
|
|
73
|
+
// The directory a run is resolved against; undefined falls back to
|
|
74
|
+
// process.cwd(). Mirrors the old F7 withBaseDir (no process.chdir).
|
|
75
|
+
baseDir;
|
|
76
|
+
constructor(opts = {}) {
|
|
77
|
+
this.pluginRoot = opts.pluginRoot;
|
|
78
|
+
this.baseDir = opts.baseDir ? path.resolve(opts.baseDir) : undefined;
|
|
79
|
+
}
|
|
80
|
+
/** Return a runner that resolves runs against `dir` instead of
|
|
81
|
+
* process.cwd(), WITHOUT chdir-ing the process. Same instance when the dir
|
|
82
|
+
* is unchanged. Matches the old orchestrator withBaseDir. */
|
|
83
|
+
withBaseDir(dir) {
|
|
84
|
+
const resolved = dir ? path.resolve(dir) : undefined;
|
|
85
|
+
if (resolved === this.baseDir)
|
|
86
|
+
return this;
|
|
87
|
+
return new CoolWorkflowRunner({ pluginRoot: this.pluginRoot, baseDir: resolved });
|
|
88
|
+
}
|
|
89
|
+
/** The cwd a run is resolved against (baseDir or process.cwd()). */
|
|
90
|
+
cwd() {
|
|
91
|
+
return this.baseDir || process.cwd();
|
|
92
|
+
}
|
|
93
|
+
/** Load a run from the runner's baseDir (or process.cwd()). Public because
|
|
94
|
+
* dogfood-architecture-review calls `runner.loadRun(run.id)`. */
|
|
95
|
+
loadRun(runId) {
|
|
96
|
+
return (0, run_store_1.loadRunFromCwd)(runId, this.cwd());
|
|
97
|
+
}
|
|
98
|
+
/** `plan` — load the workflow app by id, then plan a brand-new run. */
|
|
99
|
+
plan(workflowId, options = {}) {
|
|
100
|
+
return (0, pipeline_1.plan)((0, workflow_app_loader_1.loadWorkflowApp)(workflowId), options);
|
|
101
|
+
}
|
|
102
|
+
/** `dispatch` — build the next dispatch manifest (persisting through
|
|
103
|
+
* createDispatchManifest's own writes) and checkpoint. */
|
|
104
|
+
dispatch(runId, options = {}) {
|
|
105
|
+
const run = this.loadRun(runId);
|
|
106
|
+
const limit = numberOption(options.limit);
|
|
107
|
+
const manifest = (0, dispatch_1.createDispatchManifest)(run, limit, {
|
|
108
|
+
sandboxProfileId: stringOption(options.sandbox) || stringOption(options.sandboxProfile) || stringOption(options.sandboxProfileId),
|
|
109
|
+
backendId: stringOption(options.backend) || stringOption(options.backendId) || stringOption(options.executionBackend),
|
|
110
|
+
multiAgentRunId: stringOption(options.multiAgentRun || options.multiAgentRunId || options["multi-agent-run"]),
|
|
111
|
+
multiAgentGroupId: stringOption(options.multiAgentGroup || options.multiAgentGroupId || options.group || options["multi-agent-group"]),
|
|
112
|
+
multiAgentRoleId: stringOption(options.multiAgentRole || options.multiAgentRoleId || options.role || options["multi-agent-role"]),
|
|
113
|
+
multiAgentFanoutId: stringOption(options.multiAgentFanout || options.multiAgentFanoutId || options.fanout || options["multi-agent-fanout"]),
|
|
114
|
+
});
|
|
115
|
+
(0, run_store_2.saveCheckpoint)(run);
|
|
116
|
+
return manifest;
|
|
117
|
+
}
|
|
118
|
+
/** `showWorkerManifest` — write + return a worker's manifest. */
|
|
119
|
+
showWorkerManifest(runId, workerId) {
|
|
120
|
+
const run = this.loadRun(runId);
|
|
121
|
+
const scope = (0, worker_isolation_1.getWorkerScope)(run, workerId);
|
|
122
|
+
if (!scope)
|
|
123
|
+
throw new Error(`Unknown worker id for run ${runId}: ${workerId}`);
|
|
124
|
+
return (0, worker_isolation_1.writeWorkerManifest)(run, scope);
|
|
125
|
+
}
|
|
126
|
+
/** `recordWorkerOutput` — accept a worker's result and checkpoint. Mirrors
|
|
127
|
+
* v2's workerOutputCli: recordWorkerOutput + saveCheckpoint. */
|
|
128
|
+
recordWorkerOutput(runId, workerId, resultPath, options = {}) {
|
|
129
|
+
const run = this.loadRun(runId);
|
|
130
|
+
const output = (0, worker_isolation_1.recordWorkerOutput)(run, workerId, this.resolveFromBase(resultPath), options);
|
|
131
|
+
(0, run_store_2.saveCheckpoint)(run);
|
|
132
|
+
return output;
|
|
133
|
+
}
|
|
134
|
+
/** `auditSummary` — the trust-audit rollup. */
|
|
135
|
+
auditSummary(runId) {
|
|
136
|
+
return (0, trust_audit_1.summarizeTrustAudit)(this.loadRun(runId));
|
|
137
|
+
}
|
|
138
|
+
/** `evidenceProvenance` — the evidence chain + audit events, filtered. */
|
|
139
|
+
evidenceProvenance(runId, options = {}) {
|
|
140
|
+
return (0, audit_provenance_1.evidenceProvenance)(this.loadRun(runId), {
|
|
141
|
+
workerId: stringOption(options.worker || options.workerId),
|
|
142
|
+
candidateId: stringOption(options.candidate || options.candidateId),
|
|
143
|
+
commitId: stringOption(options.commit || options.commitId),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** `recordAuditAttestation` — host/operator sandbox attestation. Delegates
|
|
147
|
+
* to auditAttestCli, which loads the run, applies the old option-key
|
|
148
|
+
* normalization, records the event, and checkpoints. */
|
|
149
|
+
recordAuditAttestation(runId, options = {}) {
|
|
150
|
+
return (0, audit_cli_1.auditAttestCli)(runId, { ...options, runId, cwd: this.cwd() });
|
|
151
|
+
}
|
|
152
|
+
/** `recordAuditDecision` — validate + record a sandbox policy decision.
|
|
153
|
+
* Delegates to auditDecisionCli (worker lookup + sandbox validation +
|
|
154
|
+
* fail-closed feedback + checkpoint). */
|
|
155
|
+
recordAuditDecision(runId, workerId, options = {}) {
|
|
156
|
+
return (0, audit_cli_1.auditDecisionCli)(runId, workerId, { ...options, runId, cwd: this.cwd() });
|
|
157
|
+
}
|
|
158
|
+
/** `registerCandidate` — register a candidate from a worker/manual source.
|
|
159
|
+
* Delegates to candidateRegisterCli (old worker-scope read + persist). */
|
|
160
|
+
registerCandidate(runId, options = {}) {
|
|
161
|
+
return (0, multi_agent_cli_1.candidateRegisterCli)({ ...options, runId, cwd: this.cwd() });
|
|
162
|
+
}
|
|
163
|
+
/** `scoreCandidate` — score a candidate. Delegates to candidateScoreCli. */
|
|
164
|
+
scoreCandidate(runId, candidateId, options = {}) {
|
|
165
|
+
return (0, multi_agent_cli_1.candidateScoreCli)({ ...options, runId, cwd: this.cwd() }, candidateId);
|
|
166
|
+
}
|
|
167
|
+
/** `selectCandidate` — select a candidate. Delegates to candidateSelectCli. */
|
|
168
|
+
selectCandidate(runId, candidateId, options = {}) {
|
|
169
|
+
return (0, multi_agent_cli_1.candidateSelectCli)({ ...options, runId, cwd: this.cwd() }, candidateId);
|
|
170
|
+
}
|
|
171
|
+
/** `commit` — verifier-gated (or explicit-checkpoint) state commit. Returns
|
|
172
|
+
* `{ runId, commit }` to match the old orchestrator's shape (the scripts
|
|
173
|
+
* read `commitResult.commit`). */
|
|
174
|
+
commit(runId, input = {}) {
|
|
175
|
+
const run = this.loadRun(runId);
|
|
176
|
+
const options = typeof input === "string" ? { reason: input } : input;
|
|
177
|
+
const allowCheckpoint = Boolean(options.allowUnverifiedCheckpoint || options["allow-unverified-checkpoint"]);
|
|
178
|
+
const hasGateOption = Boolean(options.verifier || options.verifierNode || options["verifier-node"] || options.candidate || options.selection);
|
|
179
|
+
try {
|
|
180
|
+
const commit = (0, commit_1.commitState)(run, {
|
|
181
|
+
reason: stringOption(options.reason) || "manual",
|
|
182
|
+
verifierNodeId: stringOption(options.verifier) || stringOption(options.verifierNode) || stringOption(options["verifier-node"]),
|
|
183
|
+
candidateId: stringOption(options.candidate),
|
|
184
|
+
selectionId: stringOption(options.selection),
|
|
185
|
+
verifierGated: hasGateOption || !allowCheckpoint,
|
|
186
|
+
allowUnverifiedCheckpoint: allowCheckpoint,
|
|
187
|
+
source: "cli",
|
|
188
|
+
});
|
|
189
|
+
(0, report_1.writeReport)(run);
|
|
190
|
+
(0, run_store_2.saveCheckpoint)(run);
|
|
191
|
+
return { runId: run.id, commit };
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
(0, report_1.writeReport)(run);
|
|
195
|
+
(0, run_store_2.saveCheckpoint)(run);
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** `report` — write the run's report.md; returns `{ path }` (old shape). */
|
|
200
|
+
report(runId) {
|
|
201
|
+
return { path: (0, report_1.writeReport)(this.loadRun(runId)) };
|
|
202
|
+
}
|
|
203
|
+
/** Resolve a possibly-relative path against the runner's cwd (old
|
|
204
|
+
* resolveFromBase). */
|
|
205
|
+
resolveFromBase(target) {
|
|
206
|
+
return path.resolve(this.cwd(), target);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.CoolWorkflowRunner = CoolWorkflowRunner;
|
|
210
|
+
function stringOption(value) {
|
|
211
|
+
if (value === undefined || value === null || value === true)
|
|
212
|
+
return undefined;
|
|
213
|
+
return String(value);
|
|
214
|
+
}
|
|
215
|
+
function numberOption(value) {
|
|
216
|
+
if (value === undefined || value === null || value === true)
|
|
217
|
+
return undefined;
|
|
218
|
+
const parsed = Number(value);
|
|
219
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
220
|
+
}
|
|
221
|
+
// Back-compat `drive` for scripts/dogfood-architecture-review.js, which calls
|
|
222
|
+
// `drive(runner, run.id, { now, agentConfig })` — the OLD drive arg order.
|
|
223
|
+
// v2's shell/drive.ts drive is `drive(runId, cwd, options)` and never uses a
|
|
224
|
+
// runner object (it resolves the run from cwd), so this adapter forwards the
|
|
225
|
+
// runner's cwd. The script's require for `drive` points at THIS module so its
|
|
226
|
+
// call shape stays unchanged (require-path change only).
|
|
227
|
+
const drive_1 = require("./drive");
|
|
228
|
+
function drive(runner, runId, options = {}) {
|
|
229
|
+
const cwd = (runner && runner.baseDir) || process.cwd();
|
|
230
|
+
return (0, drive_1.drive)(runId, cwd, options);
|
|
231
|
+
}
|