cool-workflow 0.2.5 → 0.2.6
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/.gemini-plugin/plugin.json +1 -1
- package/.opencode-plugin/plugin.json +1 -1
- package/README.md +5 -3
- 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/core/state/run-paths.js +3 -30
- package/dist/core/version.js +1 -1
- package/dist/mcp/server.js +95 -27
- package/dist/mcp/tool-process.js +181 -0
- package/dist/mcp-server.js +8 -1
- package/dist/shell/agent-config.js +11 -2
- package/dist/shell/audit-cli.js +1 -1
- package/dist/shell/drive.js +99 -89
- package/dist/shell/execution-backend/agent.js +18 -15
- package/dist/shell/execution-backend/local.js +1 -0
- package/dist/shell/fs-atomic.js +3 -0
- package/dist/shell/metrics-cli.js +1 -1
- package/dist/shell/multi-agent-cli.js +4 -1
- package/dist/shell/multi-agent-operator-ux.js +1 -1
- package/dist/shell/observability.js +7 -4
- package/dist/shell/operator-ux.js +1 -1
- package/dist/shell/perf-trace.js +136 -0
- package/dist/shell/pipeline.js +1 -1
- package/dist/shell/report-view-cli.js +2 -0
- package/dist/shell/run-export-cli.js +5 -2
- package/dist/shell/run-export.js +241 -27
- package/dist/shell/run-registry-io.js +8 -0
- package/dist/shell/run-store.js +27 -3
- package/dist/shell/state-explosion-cli.js +4 -1
- package/dist/shell/telemetry-demo.js +1 -1
- package/dist/shell/trust-audit.js +91 -43
- package/dist/shell/workbench.js +4 -1
- package/dist/wiring/capability-table/parity.js +10 -5
- package/docs/agent-delegation-drive.7.md +2 -0
- package/docs/cli-mcp-parity.7.md +21 -5
- package/docs/contract-migration-tooling.7.md +2 -0
- package/docs/control-plane-scheduling.7.md +2 -0
- package/docs/durable-state-and-locking.7.md +2 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
- package/docs/execution-backends.7.md +2 -0
- package/docs/mcp-app-surface.7.md +21 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +2 -0
- package/docs/multi-agent-eval-replay-harness.7.md +2 -0
- package/docs/multi-agent-operator-ux.7.md +2 -0
- package/docs/node-snapshot-diff-replay.7.md +2 -0
- package/docs/observability-cost-accounting.7.md +2 -0
- package/docs/project-index.md +18 -4
- package/docs/real-execution-backends.7.md +2 -0
- package/docs/release-and-migration.7.md +2 -0
- package/docs/release-tooling.7.md +10 -0
- package/docs/run-registry-control-plane.7.md +35 -9
- package/docs/run-retention-reclamation.7.md +2 -0
- package/docs/state-explosion-management.7.md +2 -0
- package/docs/team-collaboration.7.md +2 -0
- package/docs/trust-audit-anchor.7.md +2 -0
- package/docs/web-desktop-workbench.7.md +48 -0
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +3 -2
- package/scripts/canonical-apps.js +4 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/gen-manifests.js +32 -61
- package/scripts/golden-path.js +4 -4
- package/scripts/parity-check.js +42 -23
- package/scripts/purity-baseline.json +0 -3
- package/scripts/release-flow.js +43 -13
- package/scripts/release-gate.js +30 -6
- package/scripts/schema-version-inventory.json +31 -0
- package/scripts/validate-run-state-schema.js +95 -4
- package/scripts/verify-release-verdict.js +139 -0
- package/ui/workbench/app.css +15 -7
- package/ui/workbench/app.js +118 -16
- package/ui/workbench/index.html +2 -0
- package/ui/workbench/inspection.js +51 -0
- package/ui/workbench/navigation.js +44 -0
|
@@ -413,20 +413,25 @@ function lintRegistry() {
|
|
|
413
413
|
}
|
|
414
414
|
/**
|
|
415
415
|
* Compare the declared registry against the ACTUAL surfaces and report every
|
|
416
|
-
* fail-closed gap. `mcpTools` is the live `tools/list` result
|
|
417
|
-
*
|
|
416
|
+
* fail-closed gap. `mcpTools` is the live `tools/list` result. `cliTokens` is
|
|
417
|
+
* optional test input for an independent token source; the table-driven live
|
|
418
|
+
* gate leaves it out and probes dispatcher reachability instead.
|
|
418
419
|
*/
|
|
419
420
|
function buildParityReport(input) {
|
|
420
421
|
const declaredTools = new Set((0, registry_core_1.declaredMcpTools)());
|
|
421
422
|
const actualTools = new Set(input.mcpTools);
|
|
422
423
|
const declaredTokens = new Set(declaredCliTokens());
|
|
423
|
-
const actualTokens = new Set(input.cliTokens);
|
|
424
|
+
const actualTokens = new Set(input.cliTokens || []);
|
|
424
425
|
const declaredHelpTokens = new Set(declaredCliHelpTokens());
|
|
425
426
|
const actualHelpTokens = new Set(input.helpTokens || []);
|
|
426
427
|
const missingMcpTools = [...declaredTools].filter((tool) => !actualTools.has(tool)).sort();
|
|
427
428
|
const undeclaredMcpTools = [...actualTools].filter((tool) => !declaredTools.has(tool)).sort();
|
|
428
|
-
const missingCliTokens =
|
|
429
|
-
|
|
429
|
+
const missingCliTokens = input.cliTokens
|
|
430
|
+
? [...declaredTokens].filter((token) => !actualTokens.has(token)).sort()
|
|
431
|
+
: [];
|
|
432
|
+
const undeclaredCliTokens = input.cliTokens
|
|
433
|
+
? [...actualTokens].filter((token) => !declaredTokens.has(token)).sort()
|
|
434
|
+
: [];
|
|
430
435
|
const helpMissingCliTokens = input.helpTokens
|
|
431
436
|
? [...declaredHelpTokens].filter((token) => !actualHelpTokens.has(token)).sort()
|
|
432
437
|
: [];
|
package/docs/cli-mcp-parity.7.md
CHANGED
|
@@ -97,6 +97,20 @@ and any other request falls back to the newest supported entry (see
|
|
|
97
97
|
`SUPPORTED_PROTOCOL_VERSIONS` in `src/mcp/server.ts`). With today's
|
|
98
98
|
one-entry list the reply bytes are unchanged.
|
|
99
99
|
|
|
100
|
+
## MCP Tool Authority
|
|
101
|
+
|
|
102
|
+
`CW_MCP_ENABLED_TOOLS` and `CW_MCP_DISABLED_TOOLS` are optional comma lists of
|
|
103
|
+
exact MCP tool names. Space at either end of a name is taken out, and a second
|
|
104
|
+
name has no effect. The enabled list is an allowlist. The disabled list is then
|
|
105
|
+
applied, so deny has the last word. With both values unset, the server keeps its
|
|
106
|
+
full `tools/list` output and present tool access.
|
|
107
|
+
|
|
108
|
+
An empty name or a name not in the live registry stops server start with a
|
|
109
|
+
stderr diagnostic and a non-zero exit. Under a good policy, `tools/list` keeps
|
|
110
|
+
the registry order and shows only allowed tools. A call to a filtered tool gives
|
|
111
|
+
the normal MCP `isError: true` result and does not start its handler. This is a
|
|
112
|
+
server control, not an OS sandbox or an approval system.
|
|
113
|
+
|
|
100
114
|
## The Parity Matrix
|
|
101
115
|
|
|
102
116
|
The matrix below is made from the live registry — one row per capability,
|
|
@@ -463,11 +477,11 @@ The shared arg helpers (`required`, `optionalArg`, `wantsJson`) live in
|
|
|
463
477
|
`src/core/util/cli-args.ts`, a pure module used by the CLI and MCP sides of
|
|
464
478
|
every wiring slice; they were moved out of `cli/io.ts` because the purity
|
|
465
479
|
gate's layer rule says `wiring/` may not take imports from `cli/`. The parity
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
480
|
+
gate does not use a token list made from the registry as proof of that same
|
|
481
|
+
registry. It runs real `cw help`, checks every declared CLI path through the
|
|
482
|
+
dispatcher lookup used by `dispatch(args)`, reads MCP `tools/list` from a live
|
|
483
|
+
server, and runs CLI-process to MCP payload probes. There is no grep over built
|
|
484
|
+
dispatch source.
|
|
471
485
|
|
|
472
486
|
`test/cli-mcp-parity-smoke.js` proves the contract from end to end. It checks
|
|
473
487
|
registry ⇄ CLI ⇄ MCP coverage (every declared capability is found on its declared
|
|
@@ -668,3 +682,5 @@ CLI golden-path fixes: `cw -q "…"` routes the question (was read as an app id
|
|
|
668
682
|
0.2.4
|
|
669
683
|
|
|
670
684
|
0.2.5
|
|
685
|
+
|
|
686
|
+
0.2.6
|
|
@@ -21,6 +21,27 @@ The bridge keeps to CW's base-system rules:
|
|
|
21
21
|
protocol errors to the model still lets it read the message and try
|
|
22
22
|
again
|
|
23
23
|
|
|
24
|
+
## Control and Tool Processes
|
|
25
|
+
|
|
26
|
+
The MCP parent process reads JSON-RPC, writes JSON-RPC, and answers `ping`.
|
|
27
|
+
One child process runs `tools/call` work in order. A file lock wait or a long
|
|
28
|
+
agent call in that child does not stop the parent from answering `ping`.
|
|
29
|
+
|
|
30
|
+
The child sends back the same JSON text that the old in-process tool call gave
|
|
31
|
+
back. Tool names, input names, output shapes, run files, and CLI parity stay
|
|
32
|
+
the same.
|
|
33
|
+
|
|
34
|
+
If the child stops during a tool call, CW gives an `isError: true` result for
|
|
35
|
+
that call. CW does not run the call again, because it may have written part of
|
|
36
|
+
a run. Read the saved run state before you try the call again. The next tool
|
|
37
|
+
call starts a new child process.
|
|
38
|
+
|
|
39
|
+
When stdin ends, CW keeps the ordered tool queue to its end and then stops the
|
|
40
|
+
child. This lets a client send a last batch and close stdin without losing its
|
|
41
|
+
replies. On `SIGINT` or `SIGTERM`, CW stops the child at once and then ends by
|
|
42
|
+
the same signal. A tool waiting on a file lock cannot wake later and write
|
|
43
|
+
state after its parent has ended.
|
|
44
|
+
|
|
24
45
|
## App Run Flow
|
|
25
46
|
|
|
26
47
|
Use `cw_app_list`, `cw_app_show`, and `cw_app_validate` to look at app
|
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-07-
|
|
3
|
+
Generated from the current repository code on 2026-07-14 by `npm run sync:project-index`.
|
|
4
4
|
|
|
5
5
|
## Snapshot
|
|
6
6
|
|
|
7
7
|
- Package: `cool-workflow`
|
|
8
|
-
- Version: `0.2.
|
|
9
|
-
- Source modules: `
|
|
8
|
+
- Version: `0.2.6`
|
|
9
|
+
- Source modules: `153`
|
|
10
10
|
- Workflow apps: `8`
|
|
11
11
|
- Docs: `58`
|
|
12
|
-
- Smoke tests: `
|
|
12
|
+
- Smoke tests: `248`
|
|
13
13
|
- Repository: https://github.com/coo1white/cool-workflow
|
|
14
14
|
|
|
15
15
|
## Architecture
|
|
@@ -125,6 +125,7 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
125
125
|
- [core/util/numeric-flag.ts](../src/core/util/numeric-flag.ts)
|
|
126
126
|
- [mcp/dispatch.ts](../src/mcp/dispatch.ts)
|
|
127
127
|
- [mcp/server.ts](../src/mcp/server.ts)
|
|
128
|
+
- [mcp/tool-process.ts](../src/mcp/tool-process.ts)
|
|
128
129
|
- [shell/agent-config.ts](../src/shell/agent-config.ts)
|
|
129
130
|
- [shell/app-run-cli.ts](../src/shell/app-run-cli.ts)
|
|
130
131
|
- [shell/audit-cli.ts](../src/shell/audit-cli.ts)
|
|
@@ -166,6 +167,7 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
166
167
|
- [shell/observability.ts](../src/shell/observability.ts)
|
|
167
168
|
- [shell/onramp.ts](../src/shell/onramp.ts)
|
|
168
169
|
- [shell/operator-ux-text.ts](../src/shell/operator-ux-text.ts)
|
|
170
|
+
- [shell/perf-trace.ts](../src/shell/perf-trace.ts)
|
|
169
171
|
- [shell/pipeline-cli.ts](../src/shell/pipeline-cli.ts)
|
|
170
172
|
- [shell/pipeline.ts](../src/shell/pipeline.ts)
|
|
171
173
|
- [shell/reclamation-io.ts](../src/shell/reclamation-io.ts)
|
|
@@ -282,6 +284,7 @@ multi-agent host -> topology -> blackboard/coordinator
|
|
|
282
284
|
|
|
283
285
|
Smoke tests mirror the public contracts. The high-signal suites are:
|
|
284
286
|
|
|
287
|
+
- [agent-auto-detect-gemini-native-smoke.js](../test/agent-auto-detect-gemini-native-smoke.js)
|
|
285
288
|
- [agent-backend-concurrent-user-env-smoke.js](../test/agent-backend-concurrent-user-env-smoke.js)
|
|
286
289
|
- [agent-backend-sandbox-deny-smoke.js](../test/agent-backend-sandbox-deny-smoke.js)
|
|
287
290
|
- [agent-backend-user-env-smoke.js](../test/agent-backend-user-env-smoke.js)
|
|
@@ -382,13 +385,18 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
382
385
|
- [ledger-verify-smoke.js](../test/ledger-verify-smoke.js)
|
|
383
386
|
- [loop-bounded-expansion-smoke.js](../test/loop-bounded-expansion-smoke.js)
|
|
384
387
|
- [man-run-registry-traversal-smoke.js](../test/man-run-registry-traversal-smoke.js)
|
|
388
|
+
- [manifest-vendor-registry-failclosed-smoke.js](../test/manifest-vendor-registry-failclosed-smoke.js)
|
|
385
389
|
- [mcp-app-surface-smoke.js](../test/mcp-app-surface-smoke.js)
|
|
390
|
+
- [mcp-control-process-responsiveness-smoke.js](../test/mcp-control-process-responsiveness-smoke.js)
|
|
386
391
|
- [mcp-ping-and-arg-coercion-smoke.js](../test/mcp-ping-and-arg-coercion-smoke.js)
|
|
387
392
|
- [mcp-protocol-version-smoke.js](../test/mcp-protocol-version-smoke.js)
|
|
388
393
|
- [mcp-queue-epipe-smoke.js](../test/mcp-queue-epipe-smoke.js)
|
|
389
394
|
- [mcp-surface-registry-smoke.js](../test/mcp-surface-registry-smoke.js)
|
|
395
|
+
- [mcp-tool-authority-policy-smoke.js](../test/mcp-tool-authority-policy-smoke.js)
|
|
390
396
|
- [mcp-tool-call-coverage-smoke.js](../test/mcp-tool-call-coverage-smoke.js)
|
|
391
397
|
- [mcp-tool-call-error-isresult-smoke.js](../test/mcp-tool-call-error-isresult-smoke.js)
|
|
398
|
+
- [mcp-tool-process-lifecycle-smoke.js](../test/mcp-tool-process-lifecycle-smoke.js)
|
|
399
|
+
- [mcp-tool-shutdown-containment-smoke.js](../test/mcp-tool-shutdown-containment-smoke.js)
|
|
392
400
|
- [mcp-untrusted-content-advisory-smoke.js](../test/mcp-untrusted-content-advisory-smoke.js)
|
|
393
401
|
- [metrics-summary-limit-smoke.js](../test/metrics-summary-limit-smoke.js)
|
|
394
402
|
- [missing-artifact-gate-live-smoke.js](../test/missing-artifact-gate-live-smoke.js)
|
|
@@ -416,6 +424,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
416
424
|
- [operator-ux-smoke.js](../test/operator-ux-smoke.js)
|
|
417
425
|
- [orphan-runs-gc-smoke.js](../test/orphan-runs-gc-smoke.js)
|
|
418
426
|
- [parallel-onramp-smoke.js](../test/parallel-onramp-smoke.js)
|
|
427
|
+
- [parity-cli-reachability-smoke.js](../test/parity-cli-reachability-smoke.js)
|
|
419
428
|
- [parity-doc-sync-smoke.js](../test/parity-doc-sync-smoke.js)
|
|
420
429
|
- [parse-guard-smoke.js](../test/parse-guard-smoke.js)
|
|
421
430
|
- [parse-hardening-round2-smoke.js](../test/parse-hardening-round2-smoke.js)
|
|
@@ -456,14 +465,17 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
456
465
|
- [robustness-hardening-smoke.js](../test/robustness-hardening-smoke.js)
|
|
457
466
|
- [run-all-agent-env-hermetic-smoke.js](../test/run-all-agent-env-hermetic-smoke.js)
|
|
458
467
|
- [run-all-json-summary-smoke.js](../test/run-all-json-summary-smoke.js)
|
|
468
|
+
- [run-archive-intake-limits-smoke.js](../test/run-archive-intake-limits-smoke.js)
|
|
459
469
|
- [run-export-cross-machine-smoke.js](../test/run-export-cross-machine-smoke.js)
|
|
460
470
|
- [run-export-import-smoke.js](../test/run-export-import-smoke.js)
|
|
461
471
|
- [run-export-restore-rerun-smoke.js](../test/run-export-restore-rerun-smoke.js)
|
|
462
472
|
- [run-export-restore-resume-smoke.js](../test/run-export-restore-resume-smoke.js)
|
|
463
473
|
- [run-fixture-compat-smoke.js](../test/run-fixture-compat-smoke.js)
|
|
474
|
+
- [run-import-canonical-table-smoke.js](../test/run-import-canonical-table-smoke.js)
|
|
464
475
|
- [run-import-path-traversal-smoke.js](../test/run-import-path-traversal-smoke.js)
|
|
465
476
|
- [run-import-tamper-failclosed-smoke.js](../test/run-import-tamper-failclosed-smoke.js)
|
|
466
477
|
- [run-inspect-archive-smoke.js](../test/run-inspect-archive-smoke.js)
|
|
478
|
+
- [run-paths-shell-boundary-smoke.js](../test/run-paths-shell-boundary-smoke.js)
|
|
467
479
|
- [run-registry-control-plane-smoke.js](../test/run-registry-control-plane-smoke.js)
|
|
468
480
|
- [run-restore-failclosed-smoke.js](../test/run-restore-failclosed-smoke.js)
|
|
469
481
|
- [run-resume-drive-smoke.js](../test/run-resume-drive-smoke.js)
|
|
@@ -477,6 +489,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
477
489
|
- [schedule-routine-daemon-smoke.js](../test/schedule-routine-daemon-smoke.js)
|
|
478
490
|
- [scheduling-routine-lock-concurrency-smoke.js](../test/scheduling-routine-lock-concurrency-smoke.js)
|
|
479
491
|
- [schema-validation-smoke.js](../test/schema-validation-smoke.js)
|
|
492
|
+
- [schema-version-definition-guard-smoke.js](../test/schema-version-definition-guard-smoke.js)
|
|
480
493
|
- [security-trust-hardening-smoke.js](../test/security-trust-hardening-smoke.js)
|
|
481
494
|
- [self-audit-hardening-smoke.js](../test/self-audit-hardening-smoke.js)
|
|
482
495
|
- [sigint-sigterm-drive-loop-smoke.js](../test/sigint-sigterm-drive-loop-smoke.js)
|
|
@@ -513,6 +526,7 @@ Smoke tests mirror the public contracts. The high-signal suites are:
|
|
|
513
526
|
- [verify-import-audit-chain-smoke.js](../test/verify-import-audit-chain-smoke.js)
|
|
514
527
|
- [web-desktop-workbench-smoke.js](../test/web-desktop-workbench-smoke.js)
|
|
515
528
|
- [wiring-lazy-shell-imports-smoke.js](../test/wiring-lazy-shell-imports-smoke.js)
|
|
529
|
+
- [workbench-load-smoke.js](../test/workbench-load-smoke.js)
|
|
516
530
|
- [workbench-port-range-smoke.js](../test/workbench-port-range-smoke.js)
|
|
517
531
|
- [worker-accept-path-architecture-smoke.js](../test/worker-accept-path-architecture-smoke.js)
|
|
518
532
|
- [worker-isolation-smoke.js](../test/worker-isolation-smoke.js)
|
|
@@ -169,6 +169,14 @@ LLM step (the reviewer) is **delegated** through CW's agent backend, so whicheve
|
|
|
169
169
|
model you set up does the review. CW starts the agent argv-style (`shell:false`),
|
|
170
170
|
takes on the agent's own credentials, and pulls in no model SDK — the red line.
|
|
171
171
|
|
|
172
|
+
The control plane runs the deterministic gate once. It keeps a failed child
|
|
173
|
+
command's short tail on stderr for the operator, but never puts that tail in a
|
|
174
|
+
saved verdict. The reviewer does not run that gate again. It checks judgment
|
|
175
|
+
questions the gate cannot check. A reviewer rejection has exact `REJECTED`,
|
|
176
|
+
`kind: semantic-review`, and numbered facts with repo-relative `file:line`
|
|
177
|
+
places. Other rejection text is invalid reviewer output: the cut stops, no tag
|
|
178
|
+
is made, and it is not a verified code rejection.
|
|
179
|
+
|
|
172
180
|
```bash
|
|
173
181
|
# the operator's one-command release (scripts/release-oneclick.js — preflight,
|
|
174
182
|
# gated cut, tag-only push, CI wait, npm confirmation, verdict-record PR):
|
|
@@ -322,3 +330,5 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
|
|
|
322
330
|
0.2.4
|
|
323
331
|
|
|
324
332
|
0.2.5
|
|
333
|
+
|
|
334
|
+
0.2.6
|
|
@@ -123,6 +123,11 @@ adds the drive outcome to the result under a `drive` field. The default (no
|
|
|
123
123
|
gives `drive.status="blocked"` (fail-closed, never a made-up completion); CW
|
|
124
124
|
hands worker execution to your agent and never runs a model itself.
|
|
125
125
|
|
|
126
|
+
Human output with `--drive` or `--once` prints the drive status, worker counts,
|
|
127
|
+
each drive step, and the terminal commit id when there is one. This makes a
|
|
128
|
+
blocked or failed drive clear without `--json`. Bare `run resume` keeps its old
|
|
129
|
+
text as it is.
|
|
130
|
+
|
|
126
131
|
## Queue
|
|
127
132
|
|
|
128
133
|
`queue add` adds a durable entry to the end of `$CW_HOME/registry/queue.json` with an
|
|
@@ -177,6 +182,15 @@ whose top-level integrity block is *absent* — closing the legacy fail-open sea
|
|
|
177
182
|
where a stripped-integrity archive imported unverified. Unset (the default) keeps
|
|
178
183
|
legacy integrity-less archives byte-identical; the flag is mechanism, not policy.
|
|
179
184
|
|
|
185
|
+
An operator can also set `CW_MAX_RUN_ARCHIVE_BYTES`,
|
|
186
|
+
`CW_MAX_RUN_ARCHIVE_FILES`, or `CW_MAX_RUN_ARCHIVE_CONTENT_BYTES`. Each value
|
|
187
|
+
has to be a positive safe integer. The first sets a raw file byte limit before
|
|
188
|
+
the archive is read. The second sets a normalized file row limit. The last sets
|
|
189
|
+
the total decoded content byte limit, checked from declared sizes before decode
|
|
190
|
+
and again while content is decoded. A bad setting or over-limit archive stops
|
|
191
|
+
before a run directory is made. With all three unset, import, inspect, restore,
|
|
192
|
+
and offline bundle check keep their present behavior.
|
|
193
|
+
|
|
180
194
|
The archive's run id becomes a directory name under `DIR/.cw/runs/`, so import
|
|
181
195
|
also refuses any run id that is not a single safe path segment (`[A-Za-z0-9._-]`,
|
|
182
196
|
with no separator and not the `.` or `..` component) and asserts the resolved run
|
|
@@ -216,11 +230,20 @@ before importing a bad archive. It is a true preview of import: under
|
|
|
216
230
|
turn away) also inspects as `ok:false`; with the env unset (default) an absent integrity
|
|
217
231
|
block is only reported, not failed.
|
|
218
232
|
|
|
233
|
+
The file table is checked before any write. Every row needs a known role, a
|
|
234
|
+
safe size, a sha256 value, and a relative path. Paths are made portable and
|
|
235
|
+
then have to be unique. `state.json`, `import-manifest.json`, and lock files
|
|
236
|
+
are made by the restore work and are not accepted from an archive. A bad row
|
|
237
|
+
or two rows with the same path make inspect, import, and restore fail closed.
|
|
238
|
+
No run directory is made for that input.
|
|
239
|
+
|
|
219
240
|
**Restore in one fail-closed step.** `run restore PATH --target DIR [--json]`
|
|
220
|
-
does the whole move-a-run-to-another-machine flow as
|
|
221
|
-
step
|
|
222
|
-
|
|
223
|
-
|
|
241
|
+
does the whole move-a-run-to-another-machine flow as one atomic, fail-closed
|
|
242
|
+
step. It integrity-**inspects** the bundle first, imports it into a same-disk
|
|
243
|
+
staging tree, and checks the file, telemetry, trust-audit, and run-state records there.
|
|
244
|
+
Only then does it put final paths into state and publish the run with one
|
|
245
|
+
directory rename. It reports `ok:true` only after a check of the published
|
|
246
|
+
tree. This closes a real gap: `run import` runs a
|
|
224
247
|
verification (it re-proves restored file digests, the **telemetry ledger**, and
|
|
225
248
|
the **trust-audit hash chain**) and reports it, but does NOT fail on it — it
|
|
226
249
|
exits `0` even when that chain does not verify. So a run whose telemetry or
|
|
@@ -229,13 +252,14 @@ made-up success. `run restore` refuses exactly that: it fails closed on the same
|
|
|
229
252
|
verification `import` only reports. A bundle that fails the up-front integrity
|
|
230
253
|
inspect is refused **before any import**, so nothing is written and the run is
|
|
231
254
|
never left part-restored; the result carries `imported:null` and `verify:null`.
|
|
232
|
-
A bundle that imports but fails
|
|
233
|
-
`ok:false`
|
|
255
|
+
A bundle that imports in staging but fails a chain check is reported with
|
|
256
|
+
`ok:false`, `imported:null`, and no final run. A final run with the same id is
|
|
257
|
+
never merged or replaced. A staging write fault is cleaned up. It exits `1`
|
|
258
|
+
whenever `ok:false`, so `cw run restore <path>` is a
|
|
234
259
|
single command that either lands a fully-proven run or refuses with a non-zero
|
|
235
|
-
exit — never a made-up success. The result is structured
|
|
260
|
+
exit — never a made-up success or a half-written final run. The result is structured
|
|
236
261
|
(`{ schemaVersion, ok, target, inspect, imported, verify, registry }`) so it is
|
|
237
|
-
scriptable. `run import` and `run inspect-archive` are unchanged
|
|
238
|
-
thin composition of `inspectArchive` + `importRun` (reusing its verification).
|
|
262
|
+
scriptable. `run import` and `run inspect-archive` are unchanged.
|
|
239
263
|
|
|
240
264
|
MCP gives the same mechanisms as `cw_run_export`, `cw_run_import`,
|
|
241
265
|
`cw_run_verify_import`, `cw_run_inspect_archive`, and `cw_run_restore`; the CLI
|
|
@@ -484,3 +508,5 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
|
|
|
484
508
|
0.2.4
|
|
485
509
|
|
|
486
510
|
0.2.5
|
|
511
|
+
|
|
512
|
+
0.2.6
|
|
@@ -10,6 +10,28 @@ speed and the MCP server (JSON-RPC over stdio) showed things for machine context
|
|
|
10
10
|
Workbench lets a person look at a run quickly — and adds NOTHING else. It works out,
|
|
11
11
|
decides, and keeps nothing that the CLI/MCP cannot already make.
|
|
12
12
|
|
|
13
|
+
## Simple UI rules
|
|
14
|
+
|
|
15
|
+
The Workbench follows three public sets of rules:
|
|
16
|
+
|
|
17
|
+
- FreeBSD [style(9)](https://man.freebsd.org/cgi/man.cgi?query=style&sektion=9)
|
|
18
|
+
says that usage text has to agree with the man page and that error text has
|
|
19
|
+
to be easy to find. CW keeps command words and error words clear and fixed.
|
|
20
|
+
- FreeBSD [hier(7)](https://man.freebsd.org/cgi/man.cgi?query=hier&sektion=7)
|
|
21
|
+
gives each sort of file one place. The Workbench keeps no state; `.cw/`
|
|
22
|
+
stays the one state source.
|
|
23
|
+
- Homebrew [brew(1)](https://docs.brew.sh/Manpage) puts its essential commands
|
|
24
|
+
before its full command list, and gives `help`, `doctor`, `info`, and
|
|
25
|
+
`search`. CW gives one clear next command in place of a hidden recovery
|
|
26
|
+
action. Homebrew [External Commands](https://docs.brew.sh/External-Commands)
|
|
27
|
+
also shows how a front door may be added without a change to the tool's
|
|
28
|
+
inside parts. The Workbench stays a view over present CW capabilities.
|
|
29
|
+
- Codex [Best practices](https://learn.chatgpt.com/guides/best-practices.md)
|
|
30
|
+
puts context, checks, and review in the work path. Its
|
|
31
|
+
[app commands](https://learn.chatgpt.com/docs/reference/commands.md) keep
|
|
32
|
+
search, key movement, and Back/Forward movement close at hand. The
|
|
33
|
+
Workbench keeps the run and panel in the page address for the same reason.
|
|
34
|
+
|
|
13
35
|
## The third front door (mechanism vs policy)
|
|
14
36
|
|
|
15
37
|
The kernel and the durable `.cw/` state are the MECHANISM. The CLI, the MCP
|
|
@@ -85,6 +107,7 @@ The host has least privilege and is local by default:
|
|
|
85
107
|
|
|
86
108
|
- it binds the loopback interface `127.0.0.1` ONLY — never a public address
|
|
87
109
|
- it is READ-ONLY: every route is `GET`; any write verb is turned away with `405`
|
|
110
|
+
- a read view makes no audit, metrics, or other derived file under `.cw/`
|
|
88
111
|
- it turns away non-localhost `Host` headers (a DNS-rebinding defense) with `403`
|
|
89
112
|
- it turns away path traversal out of `ui/workbench/` with `403`
|
|
90
113
|
- it serves nothing past the current user's `.cw/` scope and the Run Registry's
|
|
@@ -120,6 +143,29 @@ cw workbench view <run-id> [--json] # five-panel WorkbenchRunView for on
|
|
|
120
143
|
cw workbench serve [--port N] [--scope repo|home] [--once|--json] [--require-token]
|
|
121
144
|
```
|
|
122
145
|
|
|
146
|
+
The page address may name one run and one panel:
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
#run=<encoded-run-id>&tab=<graph|blackboard|worker|candidate|audit|metrics|collaboration>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The `run` value is needed for a run view. With no `tab`, the page uses
|
|
153
|
+
`graph`. A bad tab name is changed to `graph`. Back, Forward, and page reload
|
|
154
|
+
keep the named view. The Workbench token stays in the page query and is never
|
|
155
|
+
put in this fragment.
|
|
156
|
+
|
|
157
|
+
The run list and panels work with a keyboard. Left and Right move through the
|
|
158
|
+
panel tabs; Home and End go to the first and last tab. The active tab and its
|
|
159
|
+
panel are joined with the standard ARIA tab and tabpanel links.
|
|
160
|
+
|
|
161
|
+
When a present panel payload has an `integrity`, `problems`,
|
|
162
|
+
`missingEvidence`, `nextAction`, or `nextActions` fact, the page puts a small
|
|
163
|
+
`What matters` block before the full panel record. It copies only source
|
|
164
|
+
values. It does not make a new state, rank, or action. An empty problem or
|
|
165
|
+
missing-evidence list is shown as `none`. A field with a shape the page does
|
|
166
|
+
not know is left out of the block. The full structured view or JSON stays
|
|
167
|
+
under the block.
|
|
168
|
+
|
|
123
169
|
`cw workbench serve` with `--once`/`--json` prints the serve descriptor (bind
|
|
124
170
|
host/port, scope, routes) and stops without starting a server; the default starts
|
|
125
171
|
the localhost host (like `schedule daemon`). The MCP tools `cw_workbench_view` and
|
|
@@ -304,3 +350,5 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
|
|
|
304
350
|
next-step line when a run is blocked or failed.
|
|
305
351
|
|
|
306
352
|
0.2.5
|
|
353
|
+
|
|
354
|
+
0.2.6
|
|
@@ -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.2.
|
|
5
|
+
"version": "0.2.6",
|
|
6
6
|
"license": "BSD-2-Clause",
|
|
7
7
|
"homepage": "https://github.com/coo1white/cool-workflow",
|
|
8
8
|
"author": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cool-workflow",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"bin": {
|
|
5
5
|
"cool-workflow": "scripts/cw.js",
|
|
6
6
|
"cw": "scripts/cw.js"
|
|
@@ -75,7 +75,8 @@
|
|
|
75
75
|
"test:unit": "node dist/cli.js version > /dev/null && node test/run-unit.js",
|
|
76
76
|
"eval:replay": "tsc -p tsconfig.json && node test/multi-agent-eval-replay-harness-smoke.js",
|
|
77
77
|
"ci": "npm run build && npm run check && npm run test && npm run release:check",
|
|
78
|
-
"validate:schema": "node scripts/validate-run-state-schema.js"
|
|
78
|
+
"validate:schema": "node scripts/validate-run-state-schema.js",
|
|
79
|
+
"bench:workbench:deep": "node ../../scripts/bench/workbench-load.js"
|
|
79
80
|
},
|
|
80
81
|
"devDependencies": {
|
|
81
82
|
"@types/node": "^26.1.1",
|
|
@@ -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.2.
|
|
86
|
+
"Cool Workflow v0.2.6",
|
|
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.2.
|
|
120
|
+
assert.equal(summary.version, "0.2.6");
|
|
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.2.
|
|
127
|
+
assert.equal(shown.app.version, "0.2.6");
|
|
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.2.
|
|
138
|
+
assert.equal(state.workflow.app.version, "0.2.6");
|
|
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`);
|
|
@@ -6,7 +6,7 @@ const fs = require("node:fs");
|
|
|
6
6
|
const path = require("node:path");
|
|
7
7
|
const { CoolWorkflowRunner } = require("../dist/shell/orchestrator.js");
|
|
8
8
|
|
|
9
|
-
const TARGET_VERSION = "0.2.
|
|
9
|
+
const TARGET_VERSION = "0.2.6";
|
|
10
10
|
const PREVIOUS_VERSION = "0.1.31";
|
|
11
11
|
const pluginRoot = path.resolve(__dirname, "..");
|
|
12
12
|
const repoRoot = path.resolve(pluginRoot, "..", "..");
|