cool-workflow 0.2.3 → 0.2.5
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/mcp.json +10 -0
- package/.gemini-plugin/plugin.json +40 -0
- package/.opencode-plugin/mcp.json +10 -0
- package/.opencode-plugin/plugin.json +40 -0
- package/README.md +202 -48
- 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 +33 -4
- package/dist/cli/entry.js +11 -19
- package/dist/cli/global-flags.js +113 -0
- package/dist/cli/io.js +6 -20
- package/dist/cli/parseargv.js +7 -1
- package/dist/core/capability-data.js +339 -10
- package/dist/core/format/help.js +80 -4
- package/dist/core/format/recovery-hint.js +32 -0
- package/dist/core/multi-agent/collaboration.js +35 -6
- package/dist/core/multi-agent/runtime.js +7 -0
- package/dist/core/multi-agent/trust-policy.js +7 -1
- package/dist/core/pipeline/contract.js +7 -0
- package/dist/core/pipeline/error-feedback.js +2 -2
- package/dist/core/trust/evidence-grounding.js +13 -1
- package/dist/core/util/cli-args.js +55 -0
- package/dist/core/version.js +1 -1
- package/dist/mcp/dispatch.js +22 -2
- package/dist/mcp/server.js +124 -13
- package/dist/mcp-server.js +20 -0
- package/dist/shell/commit.js +8 -2
- package/dist/shell/coordinator-io.js +73 -1
- package/dist/shell/drive.js +129 -64
- package/dist/shell/error-feedback-io.js +6 -0
- package/dist/shell/execution-backend/agent.js +205 -24
- package/dist/shell/execution-backend/container.js +44 -10
- package/dist/shell/execution-backend/local.js +47 -10
- package/dist/shell/fs-atomic.js +93 -12
- package/dist/shell/ledger-cli.js +9 -2
- package/dist/shell/multi-agent-cli.js +5 -1
- package/dist/shell/onramp.js +48 -5
- package/dist/shell/pipeline-cli.js +20 -2
- package/dist/shell/pipeline.js +2 -1
- package/dist/shell/reclamation-io.js +76 -7
- package/dist/shell/registry-cli.js +4 -0
- package/dist/shell/run-export.js +52 -4
- package/dist/shell/run-registry-io.js +1 -0
- package/dist/shell/run-store.js +156 -0
- package/dist/shell/scheduler-io.js +101 -10
- package/dist/shell/telemetry-ledger-io.js +36 -24
- package/dist/shell/trust-audit.js +104 -10
- package/dist/shell/workbench-host.js +121 -10
- package/dist/shell/workbench.js +79 -5
- package/dist/shell/worker-isolation.js +1 -1
- package/dist/shell/workflow-app-loader.js +67 -1
- package/dist/wiring/capability-table/basics.js +7 -2
- package/dist/wiring/capability-table/exec-backend.js +42 -24
- package/dist/wiring/capability-table/multi-agent.js +69 -69
- package/dist/wiring/capability-table/pipeline.js +60 -28
- package/dist/wiring/capability-table/registry-core.js +29 -6
- package/dist/wiring/capability-table/reporting.js +45 -39
- package/dist/wiring/capability-table/scheduling-registry.js +66 -60
- package/dist/wiring/capability-table/state.js +34 -34
- package/dist/wiring/capability-table/trust-ledger.js +66 -24
- package/dist/wiring/capability-table/workflow-apps.js +15 -15
- package/docs/agent-delegation-drive.7.md +17 -0
- package/docs/cli-mcp-parity.7.md +43 -13
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +38 -0
- package/docs/cross-agent-ledger.7.md +20 -8
- 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/fix.7.md +4 -4
- package/docs/getting-started.md +40 -32
- package/docs/index.md +17 -0
- package/docs/launch/demo.tape +4 -3
- package/docs/mcp-app-surface.7.md +6 -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 +43 -9
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +22 -0
- package/docs/routine.7.md +22 -0
- package/docs/run-registry-control-plane.7.md +4 -0
- package/docs/run-retention-reclamation.7.md +28 -3
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/trust-audit-anchor.7.md +4 -0
- package/docs/web-desktop-workbench.7.md +26 -2
- package/docs/workflow-app-framework.7.md +31 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +4 -3
- package/package.json +5 -2
- package/scripts/agents/agent-adapter-core.js +26 -0
- package/scripts/agents/claude-p-agent.js +4 -1
- package/scripts/agents/codex-agent.js +4 -0
- package/scripts/agents/cw-attest-wrap.js +1 -1
- package/scripts/agents/gemini-agent.js +4 -0
- package/scripts/agents/opencode-agent.js +5 -0
- package/scripts/block-unapproved-tag.js +160 -0
- package/scripts/bump-version.js +27 -10
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +72 -4
- package/scripts/children/http-batch-delegate-child.js +132 -0
- package/scripts/children/http-delegate-child.js +8 -0
- package/scripts/dogfood-release.js +2 -2
- package/scripts/fake-date-for-reproduction.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/lang-policy-check.js +82 -0
- package/scripts/purity-baseline.json +0 -30
- package/scripts/purity-gate.js +16 -3
- package/scripts/release-check.js +2 -1
- package/scripts/release-flow.js +264 -41
- package/scripts/release-gate.js +184 -0
- package/scripts/release-oneclick.js +438 -0
- package/scripts/release-tags.js +47 -0
- package/scripts/verdict-keygen.js +2 -2
- package/scripts/verify-bump-reproduction.js +193 -0
- package/scripts/verify-verdict-signature.js +1 -1
- package/scripts/version-sync-check.js +39 -22
- package/ui/workbench/app.css +41 -9
- package/ui/workbench/app.js +160 -27
- package/ui/workbench/index.html +2 -2
- package/docs/agent-framework.md +0 -177
- package/docs/designs/handoff-ledger.md +0 -145
- package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +0 -40
- package/docs/launch/launch-kit.md +0 -195
- package/docs/launch/pre-launch-checklist.md +0 -53
- package/docs/readme-v0.1.87-full.md +0 -301
- package/docs/routines.md +0 -101
- package/docs/scheduled-tasks.md +0 -80
- package/scripts/agents/claude-p-agent.sh +0 -9
- package/scripts/block-unapproved-tag.sh +0 -60
- package/scripts/release-gate.sh +0 -94
- package/scripts/verify-bump-reproduction.sh +0 -148
- package/scripts/verify-container-selfref.js +0 -64
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// verify-bump-reproduction.js — closes the HEAD~1 verdict-replay bypass.
|
|
4
|
+
//
|
|
5
|
+
// release-gate.yml / npm-publish.yml tolerate a verdict written for the tag
|
|
6
|
+
// commit's PARENT (release-flow.js's cut() reviews content, then adds a
|
|
7
|
+
// mechanical version-bump + the verdict as a NEW child commit that actually
|
|
8
|
+
// gets tagged). A validly-signed verdict at the parent proves someone once
|
|
9
|
+
// approved THAT commit — it does NOT prove the child (the thing actually being
|
|
10
|
+
// tagged) is the deterministic bump cut() would have produced, rather than an
|
|
11
|
+
// attacker's own commit smuggling in arbitrary changes on top of an old,
|
|
12
|
+
// genuinely-approved parent (a real signature on a REPLAYED verdict).
|
|
13
|
+
//
|
|
14
|
+
// This script independently reproduces the bump: checks out the approved
|
|
15
|
+
// parent into a scratch worktree, runs the SAME bump:version/sync:project-index
|
|
16
|
+
// steps cut() runs, stages the SAME way cut() stages (git add -u + the
|
|
17
|
+
// explicit verdict/.sig paths, never -A), and requires the resulting tree to
|
|
18
|
+
// match the ACTUAL tagged commit's tree byte-for-byte. Any difference —
|
|
19
|
+
// anywhere, including a single added file — fails closed.
|
|
20
|
+
//
|
|
21
|
+
// (Node port of the former verify-bump-reproduction.sh; behavior kept line
|
|
22
|
+
// for line — same steps, same messages, same exit map.)
|
|
23
|
+
//
|
|
24
|
+
// Usage: verify-bump-reproduction.js <approved-parent-sha> <tagged-sha> <verdict-repo-relative-path> [sig-repo-relative-path]
|
|
25
|
+
//
|
|
26
|
+
// Exit 0: the tagged commit's tree matches the reproduced bump exactly.
|
|
27
|
+
// Exit 1: mismatch, or any step failed (install, bump, sync, worktree, etc).
|
|
28
|
+
|
|
29
|
+
const fs = require("node:fs");
|
|
30
|
+
const os = require("node:os");
|
|
31
|
+
const path = require("node:path");
|
|
32
|
+
const { spawnSync } = require("node:child_process");
|
|
33
|
+
|
|
34
|
+
// Where THIS SCRIPT ITSELF lives — distinct from REPO_ROOT (the git repo being
|
|
35
|
+
// operated ON, resolved below from the invocation cwd). These coincide in
|
|
36
|
+
// ordinary production use (the script runs from within the same checkout it
|
|
37
|
+
// verifies), but conflating them is wrong: REPO_ROOT could be an ARBITRARY git
|
|
38
|
+
// context (e.g. a test harness's throwaway clone of old history, which never
|
|
39
|
+
// has this script's own sibling files, since they postdate whatever was
|
|
40
|
+
// cloned). Sibling files this script depends on must be found relative to
|
|
41
|
+
// where it is installed, never relative to the repo it happens to be pointed at.
|
|
42
|
+
const SCRIPT_DIR = __dirname;
|
|
43
|
+
|
|
44
|
+
function err(msg) {
|
|
45
|
+
process.stderr.write(`${msg}\n`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const [, , PARENT, TAGGED, VERDICT_REL, SIG_REL = ""] = process.argv;
|
|
49
|
+
if (!PARENT || !TAGGED || !VERDICT_REL) {
|
|
50
|
+
err("usage: verify-bump-reproduction.js <parent-sha> <tagged-sha> <verdict-rel-path> [sig-rel-path]");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function run(cmd, args, opts = {}) {
|
|
55
|
+
return spawnSync(cmd, args, { encoding: "utf8", ...opts });
|
|
56
|
+
}
|
|
57
|
+
function gitIn(dir, args, opts = {}) {
|
|
58
|
+
return run("git", ["-C", dir, ...args], opts);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const top = run("git", ["rev-parse", "--show-toplevel"]);
|
|
62
|
+
if (top.status !== 0) process.exit(1);
|
|
63
|
+
const REPO_ROOT = top.stdout.trim();
|
|
64
|
+
|
|
65
|
+
const SCRATCH_PARENT = fs.mkdtempSync(path.join(os.tmpdir(), "cw-bump-repro-"));
|
|
66
|
+
const SCRATCH = path.join(SCRATCH_PARENT, "wt");
|
|
67
|
+
function cleanup() {
|
|
68
|
+
gitIn(REPO_ROOT, ["worktree", "remove", "--force", SCRATCH], { stdio: "ignore" });
|
|
69
|
+
fs.rmSync(SCRATCH_PARENT, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function main() {
|
|
73
|
+
const wt = gitIn(REPO_ROOT, ["worktree", "add", "--quiet", "--detach", SCRATCH, PARENT], { stdio: "ignore" });
|
|
74
|
+
if (wt.status !== 0) {
|
|
75
|
+
err(`verify-bump-reproduction: could not create a scratch worktree at ${PARENT}`);
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The target version comes from the TAGGED commit (not the parent, which may
|
|
80
|
+
// still be pre-bump) — read via git plumbing, no separate checkout needed.
|
|
81
|
+
const pkgShow = gitIn(REPO_ROOT, ["show", `${TAGGED}:plugins/cool-workflow/package.json`]);
|
|
82
|
+
let VERSION = "";
|
|
83
|
+
if (pkgShow.status === 0) {
|
|
84
|
+
try {
|
|
85
|
+
VERSION = JSON.parse(pkgShow.stdout).version || "";
|
|
86
|
+
} catch {
|
|
87
|
+
VERSION = "";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!VERSION) {
|
|
91
|
+
err(`verify-bump-reproduction: could not read package.json version from tagged commit ${TAGGED}`);
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// sync-project-index.js embeds a wall-clock "Generated on <date>" line. Pin it
|
|
96
|
+
// to the TAGGED commit's own committer date (UTC) via a Node --require preload
|
|
97
|
+
// that overrides the global Date constructor (fake-date-for-reproduction.js),
|
|
98
|
+
// NOT an application-level env var: the scratch worktree runs the APPROVED
|
|
99
|
+
// PARENT's OWN checked-out copy of sync-project-index.js, which for every
|
|
100
|
+
// release cut before this mechanism existed has no idea any such env var is
|
|
101
|
+
// meant to be read — an app-level opt-in is a no-op against code that doesn't
|
|
102
|
+
// know to opt in, so it can only ever "work" for releases cut after the
|
|
103
|
+
// mechanism landed (confirmed empirically: re-running an already-shipped
|
|
104
|
+
// release's real approved-parent/tagged pair on a later calendar day produced
|
|
105
|
+
// a tree mismatch whose ONLY diff was that one date line). A global override
|
|
106
|
+
// of the Date constructor, injected before any application code runs, is
|
|
107
|
+
// transparent to the code being executed regardless of which version it is.
|
|
108
|
+
const dateShow = gitIn(REPO_ROOT, ["show", "-s", "--format=%cd", "--date=format-local:%Y-%m-%d", TAGGED], {
|
|
109
|
+
env: { ...process.env, TZ: "UTC" },
|
|
110
|
+
});
|
|
111
|
+
const CUT_DATE = dateShow.status === 0 ? dateShow.stdout.trim() : "";
|
|
112
|
+
if (!CUT_DATE) {
|
|
113
|
+
err("verify-bump-reproduction: could not read the tagged commit's committer date");
|
|
114
|
+
return 1;
|
|
115
|
+
}
|
|
116
|
+
const FAKE_DATE_PRELOAD = path.join(SCRIPT_DIR, "fake-date-for-reproduction.js");
|
|
117
|
+
|
|
118
|
+
// Each step's exit code is checked EXPLICITLY and immediately (not via one
|
|
119
|
+
// combined chain) — a chain's overall success can silently survive an earlier
|
|
120
|
+
// step's failure if a future edit ever loosens it, which would flip this
|
|
121
|
+
// fail-closed gate to fail-open without changing its outward shape.
|
|
122
|
+
// stdout/stderr from each step are captured (not discarded) so a real
|
|
123
|
+
// failure — a transient npm registry hiccup vs. an actual reproduction
|
|
124
|
+
// mismatch — is distinguishable in the workflow log instead of both
|
|
125
|
+
// collapsing into the same generic message.
|
|
126
|
+
const stepCwd = path.join(SCRATCH, "plugins", "cool-workflow");
|
|
127
|
+
const stepEnv = {
|
|
128
|
+
...process.env,
|
|
129
|
+
NODE_OPTIONS: `--require ${FAKE_DATE_PRELOAD}`,
|
|
130
|
+
CW_FAKE_DATE: CUT_DATE,
|
|
131
|
+
};
|
|
132
|
+
function runStep(label, cmd, args) {
|
|
133
|
+
const r = run(cmd, args, { cwd: stepCwd, env: stepEnv });
|
|
134
|
+
const out = (r.stdout || "") + (r.stderr || "");
|
|
135
|
+
const code = r.error ? 1 : r.status;
|
|
136
|
+
if (code !== 0) {
|
|
137
|
+
err(`verify-bump-reproduction: ${label} failed (exit ${code}):`);
|
|
138
|
+
err(out);
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const bumpOk =
|
|
145
|
+
runStep("npm install", "npm", ["install", "--no-package-lock", "--ignore-scripts"]) &&
|
|
146
|
+
runStep("bump:version", "npm", ["run", "bump:version", "--", VERSION]) &&
|
|
147
|
+
runStep("sync:project-index", "npm", ["run", "sync:project-index", "--", "--repo-only"]);
|
|
148
|
+
if (!bumpOk) {
|
|
149
|
+
err(`verify-bump-reproduction: reproducing the bump for ${PARENT} -> v${VERSION} failed`);
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
fs.mkdirSync(path.join(SCRATCH, ".cw-release"), { recursive: true });
|
|
154
|
+
try {
|
|
155
|
+
fs.copyFileSync(path.join(REPO_ROOT, VERDICT_REL), path.join(SCRATCH, VERDICT_REL));
|
|
156
|
+
} catch {
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
if (SIG_REL && fs.existsSync(path.join(REPO_ROOT, SIG_REL))) {
|
|
160
|
+
try {
|
|
161
|
+
fs.copyFileSync(path.join(REPO_ROOT, SIG_REL), path.join(SCRATCH, SIG_REL));
|
|
162
|
+
} catch {
|
|
163
|
+
return 1;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Mirror cut()'s OWN staging exactly (git-add -u + the explicit verdict/.sig
|
|
168
|
+
// paths) — never -A, so an untracked stray left by npm/tooling in the scratch
|
|
169
|
+
// worktree can never silently ride into what we compare.
|
|
170
|
+
gitIn(SCRATCH, ["add", "-u"]);
|
|
171
|
+
gitIn(SCRATCH, ["add", "--", VERDICT_REL]);
|
|
172
|
+
if (SIG_REL && fs.existsSync(path.join(SCRATCH, SIG_REL))) {
|
|
173
|
+
gitIn(SCRATCH, ["add", "--", SIG_REL]);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const EXPECTED_TREE = gitIn(SCRATCH, ["write-tree"]).stdout.trim();
|
|
177
|
+
const ACTUAL_TREE = gitIn(REPO_ROOT, ["rev-parse", `${TAGGED}^{tree}`]).stdout.trim();
|
|
178
|
+
|
|
179
|
+
if (EXPECTED_TREE !== ACTUAL_TREE) {
|
|
180
|
+
err(`verify-bump-reproduction: ${TAGGED}'s tree (${ACTUAL_TREE}) does not match the deterministic bump reproduced from approved parent ${PARENT} (${EXPECTED_TREE}) — refusing`);
|
|
181
|
+
return 1;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
let code = 1;
|
|
188
|
+
try {
|
|
189
|
+
code = main();
|
|
190
|
+
} finally {
|
|
191
|
+
cleanup();
|
|
192
|
+
}
|
|
193
|
+
process.exit(code);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// verify-verdict-signature.js — verify an ed25519 signature over a committed
|
|
5
5
|
// release verdict file, against the committed public key
|
|
6
6
|
// (.cw-release/verdict-signing.pub). Portable (node + node:crypto only) so
|
|
7
|
-
// CI (release-gate.yml, npm-publish.yml) and the local block-unapproved-tag.
|
|
7
|
+
// CI (release-gate.yml, npm-publish.yml) and the local block-unapproved-tag.js
|
|
8
8
|
// hook can all shell out to the SAME check instead of three drifting copies.
|
|
9
9
|
//
|
|
10
10
|
// Exit 0: signature verifies. Exit 1: missing file, unreadable key, or a
|
|
@@ -106,68 +106,68 @@ function main() {
|
|
|
106
106
|
// above (version.ts/dist/package.json/manifests/docs) still pin the release.
|
|
107
107
|
checkIncludes("plugins/cool-workflow/docs/index.md", "release and migration", checks);
|
|
108
108
|
checkIncludes("plugins/cool-workflow/docs/multi-agent-topologies.7.md", "Multi-Agent Topologies", checks);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/multi-agent-cli-mcp-surface.7.md", VERSION, checks);
|
|
110
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/multi-agent-operator-ux.7.md", VERSION, checks);
|
|
111
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/multi-agent-eval-replay-harness.7.md", VERSION, checks);
|
|
112
112
|
checkIncludes("plugins/cool-workflow/docs/state-explosion-management.7.md", "State Explosion Management", checks);
|
|
113
|
-
|
|
113
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/state-explosion-management.7.md", VERSION, checks);
|
|
114
114
|
checkIncludes("plugins/cool-workflow/docs/evidence-adoption-reasoning-chain.7.md", "Evidence Adoption Reasoning Chain", checks);
|
|
115
|
-
|
|
115
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/evidence-adoption-reasoning-chain.7.md", VERSION, checks);
|
|
116
116
|
checkIncludes("plugins/cool-workflow/docs/coordinator-blackboard.7.md", "Coordinator / Blackboard", checks);
|
|
117
117
|
checkIncludes("plugins/cool-workflow/docs/cli-mcp-parity.7.md", "CLI", checks);
|
|
118
|
-
|
|
118
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/cli-mcp-parity.7.md", VERSION, checks);
|
|
119
119
|
checkIncludes("plugins/cool-workflow/docs/index.md", "cli-mcp-parity.7.md", checks);
|
|
120
120
|
checkIncludes("plugins/cool-workflow/docs/run-registry-control-plane.7.md", "Run Registry / Control Plane", checks);
|
|
121
|
-
|
|
121
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/run-registry-control-plane.7.md", VERSION, checks);
|
|
122
122
|
checkIncludes("plugins/cool-workflow/docs/index.md", "run-registry-control-plane.7.md", checks);
|
|
123
123
|
checkIncludes("plugins/cool-workflow/test/run-registry-control-plane-smoke.js", "run-registry-control-plane-smoke", checks);
|
|
124
124
|
checkIncludes("plugins/cool-workflow/docs/execution-backends.7.md", "Execution Backends", checks);
|
|
125
|
-
|
|
125
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/execution-backends.7.md", VERSION, checks);
|
|
126
126
|
checkIncludes("plugins/cool-workflow/docs/index.md", "execution-backends.7.md", checks);
|
|
127
127
|
checkIncludes("plugins/cool-workflow/test/execution-backends-smoke.js", "execution-backends-smoke", checks);
|
|
128
128
|
checkIncludes("plugins/cool-workflow/docs/web-desktop-workbench.7.md", "Web / Desktop Workbench", checks);
|
|
129
|
-
|
|
129
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/web-desktop-workbench.7.md", VERSION, checks);
|
|
130
130
|
checkIncludes("plugins/cool-workflow/docs/index.md", "web-desktop-workbench.7.md", checks);
|
|
131
131
|
checkIncludes("plugins/cool-workflow/test/web-desktop-workbench-smoke.js", "web-desktop-workbench-smoke", checks);
|
|
132
132
|
checkIncludes("plugins/cool-workflow/docs/observability-cost-accounting.7.md", "Observability + Cost Accounting", checks);
|
|
133
|
-
|
|
133
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/observability-cost-accounting.7.md", VERSION, checks);
|
|
134
134
|
checkIncludes("plugins/cool-workflow/docs/index.md", "observability-cost-accounting.7.md", checks);
|
|
135
135
|
checkIncludes("plugins/cool-workflow/test/observability-cost-accounting-smoke.js", "observability-cost-accounting-smoke", checks);
|
|
136
136
|
checkIncludes("plugins/cool-workflow/docs/team-collaboration.7.md", "Team Collaboration", checks);
|
|
137
|
-
|
|
137
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/team-collaboration.7.md", VERSION, checks);
|
|
138
138
|
checkIncludes("plugins/cool-workflow/docs/index.md", "team-collaboration.7.md", checks);
|
|
139
139
|
checkIncludes("plugins/cool-workflow/test/team-collaboration-smoke.js", "team-collaboration-smoke", checks);
|
|
140
140
|
checkIncludes("plugins/cool-workflow/docs/release-tooling.7.md", "Release Tooling", checks);
|
|
141
|
-
|
|
141
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/release-tooling.7.md", VERSION, checks);
|
|
142
142
|
checkIncludes("plugins/cool-workflow/docs/index.md", "release-tooling.7.md", checks);
|
|
143
143
|
checkIncludes("plugins/cool-workflow/test/release-tooling-smoke.js", "release-tooling-smoke", checks);
|
|
144
144
|
checkIncludes("plugins/cool-workflow/docs/real-execution-backends.7.md", "Real Execution Backend Integrations", checks);
|
|
145
|
-
|
|
145
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/real-execution-backends.7.md", VERSION, checks);
|
|
146
146
|
checkIncludes("plugins/cool-workflow/docs/index.md", "real-execution-backends.7.md", checks);
|
|
147
147
|
checkIncludes("plugins/cool-workflow/test/real-execution-backends-smoke.js", "real-execution-backends-smoke", checks);
|
|
148
148
|
checkIncludes("plugins/cool-workflow/docs/node-snapshot-diff-replay.7.md", "Node Snapshot / Diff / Replay", checks);
|
|
149
|
-
|
|
149
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/node-snapshot-diff-replay.7.md", VERSION, checks);
|
|
150
150
|
checkIncludes("plugins/cool-workflow/docs/index.md", "node-snapshot-diff-replay.7.md", checks);
|
|
151
151
|
checkIncludes("plugins/cool-workflow/test/node-snapshot-diff-replay-smoke.js", "node-snapshot-diff-replay-smoke", checks);
|
|
152
152
|
checkIncludes("plugins/cool-workflow/docs/contract-migration-tooling.7.md", "Contract Migration Tooling", checks);
|
|
153
|
-
|
|
153
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/contract-migration-tooling.7.md", VERSION, checks);
|
|
154
154
|
checkIncludes("plugins/cool-workflow/docs/index.md", "contract-migration-tooling.7.md", checks);
|
|
155
155
|
checkIncludes("plugins/cool-workflow/test/contract-migration-tooling-smoke.js", "contract-migration-tooling-smoke", checks);
|
|
156
156
|
checkIncludes("plugins/cool-workflow/docs/control-plane-scheduling.7.md", "Control-Plane Scheduling", checks);
|
|
157
|
-
|
|
157
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/control-plane-scheduling.7.md", VERSION, checks);
|
|
158
158
|
checkIncludes("plugins/cool-workflow/docs/index.md", "control-plane-scheduling.7.md", checks);
|
|
159
159
|
checkIncludes("plugins/cool-workflow/test/control-plane-scheduling-smoke.js", "control-plane-scheduling-smoke", checks);
|
|
160
160
|
checkIncludes("plugins/cool-workflow/docs/agent-delegation-drive.7.md", "Agent Delegation Drive", checks);
|
|
161
|
-
|
|
161
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/agent-delegation-drive.7.md", VERSION, checks);
|
|
162
162
|
checkIncludes("plugins/cool-workflow/docs/index.md", "agent-delegation-drive.7.md", checks);
|
|
163
163
|
checkIncludes("plugins/cool-workflow/test/agent-delegation-drive-smoke.js", "agent-delegation-drive-smoke", checks);
|
|
164
164
|
checkIncludes("plugins/cool-workflow/docs/run-retention-reclamation.7.md", "Run Retention & Provable Reclamation", checks);
|
|
165
|
-
|
|
165
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/run-retention-reclamation.7.md", VERSION, checks);
|
|
166
166
|
checkIncludes("plugins/cool-workflow/docs/index.md", "run-retention-reclamation.7.md", checks);
|
|
167
167
|
checkIncludes("plugins/cool-workflow/test/run-retention-reclamation-smoke.js", "run-retention-reclamation-smoke", checks);
|
|
168
168
|
checkIncludes("plugins/cool-workflow/src/wiring/capability-table/scheduling-registry.ts", "gc.plan", checks);
|
|
169
169
|
checkIncludes("plugins/cool-workflow/docs/durable-state-and-locking.7.md", "Durable State & Locking", checks);
|
|
170
|
-
|
|
170
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/durable-state-and-locking.7.md", VERSION, checks);
|
|
171
171
|
checkIncludes("plugins/cool-workflow/docs/index.md", "durable-state-and-locking.7.md", checks);
|
|
172
172
|
checkIncludes("plugins/cool-workflow/test/durable-atomic-write-smoke.js", "durable-atomic-write-smoke", checks);
|
|
173
173
|
checkIncludes("plugins/cool-workflow/src/shell/fs-atomic.ts", "withFileLock", checks);
|
|
@@ -201,12 +201,12 @@ function main() {
|
|
|
201
201
|
checkIncludes("plugins/cool-workflow/docs/getting-started.md", "npm run release:check", checks);
|
|
202
202
|
checkIncludes("plugins/cool-workflow/package.json", "eval:replay", checks);
|
|
203
203
|
checkIncludes("plugins/cool-workflow/docs/trust-audit-anchor.7.md", "Trust Audit Anchor", checks);
|
|
204
|
-
|
|
204
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/trust-audit-anchor.7.md", VERSION, checks);
|
|
205
205
|
checkIncludes("plugins/cool-workflow/docs/index.md", "trust-audit-anchor.7.md", checks);
|
|
206
206
|
checkIncludes("plugins/cool-workflow/test/trust-audit-anchor-smoke.js", "trust-audit-anchor-smoke", checks);
|
|
207
|
-
|
|
207
|
+
checkIncludesOwnLine("plugins/cool-workflow/docs/release-and-migration.7.md", VERSION, checks);
|
|
208
208
|
checkIncludes("CHANGELOG.md", `## ${VERSION}`, checks);
|
|
209
|
-
|
|
209
|
+
checkIncludesOwnLine("RELEASE.md", VERSION, checks);
|
|
210
210
|
// Homebrew formula (repo root): git-tag formula. Homebrew scans the version
|
|
211
211
|
// from the tag, so the tag is the single version surface to gate (an explicit
|
|
212
212
|
// `version` line would be redundant and brew audit rejects it). bump-version.js
|
|
@@ -266,4 +266,21 @@ function checkIncludes(relativePath, needle, checks) {
|
|
|
266
266
|
checks.push({ path: relativePath, includes: needle });
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
+
// A bare version number (e.g. "0.2.4") can appear anywhere in a doc's
|
|
270
|
+
// prose — an example command, a cross-reference — without the doc's own
|
|
271
|
+
// version-history footer (a blank-line-separated list, one release per
|
|
272
|
+
// line, appended by bump-version.js's --content step) actually having
|
|
273
|
+
// been updated. A plain substring check would silently pass on the
|
|
274
|
+
// coincidental prose match and never notice the real footer line is
|
|
275
|
+
// missing (found live: v0.2.4's bump left release-tooling.7.md's footer
|
|
276
|
+
// stuck at 0.2.3, masked by an unrelated "npm run release -- 0.2.4"
|
|
277
|
+
// example a few lines up). Require the needle on its own line instead.
|
|
278
|
+
function checkIncludesOwnLine(relativePath, needle, checks) {
|
|
279
|
+
const src = readReleaseSource(relativePath);
|
|
280
|
+
assert.ok(src.exists, `${relativePath} must exist`);
|
|
281
|
+
const hasOwnLine = src.text.split("\n").some((line) => line.trim() === needle);
|
|
282
|
+
assert.ok(hasOwnLine, `${relativePath} must include ${needle} as its own line (not just as a substring)`);
|
|
283
|
+
checks.push({ path: relativePath, includesOwnLine: needle });
|
|
284
|
+
}
|
|
285
|
+
|
|
269
286
|
main();
|
package/ui/workbench/app.css
CHANGED
|
@@ -27,21 +27,31 @@
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
* { box-sizing: border-box; }
|
|
30
|
+
/* The body is a flex column and main takes the leftover height (flex: 1 +
|
|
31
|
+
min-height: 0 so the inner panes can scroll) — no hardcoded header
|
|
32
|
+
height, so a header that wraps to two lines no longer pushes the panes
|
|
33
|
+
past the bottom of the window. */
|
|
30
34
|
body {
|
|
31
35
|
margin: 0;
|
|
32
36
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
33
37
|
background: var(--bg);
|
|
34
38
|
color: var(--ink);
|
|
35
39
|
font-size: 14px;
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
height: 100vh;
|
|
36
43
|
}
|
|
37
44
|
header { padding: 14px 20px; border-bottom: 1px solid var(--line); }
|
|
38
45
|
header h1 { margin: 0; font-size: 18px; font-weight: 600; }
|
|
39
46
|
header .muted, .muted { color: var(--muted); font-weight: 400; }
|
|
40
47
|
header .trust { margin: 4px 0 0; font-size: 12px; color: var(--muted); }
|
|
41
48
|
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
42
|
-
main { display: grid; grid-template-columns: 320px 1fr;
|
|
49
|
+
main { display: grid; grid-template-columns: 320px 1fr; flex: 1; min-height: 0; }
|
|
43
50
|
.sidebar { border-right: 1px solid var(--line); overflow-y: auto; padding: 12px; }
|
|
44
51
|
.bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
|
|
52
|
+
/* The sidebar heading is a real <h2> (document outline / screen-reader
|
|
53
|
+
navigation) styled to the size the old <strong> label had. */
|
|
54
|
+
.bar h2 { margin: 0; font-size: 14px; font-weight: 600; }
|
|
45
55
|
button {
|
|
46
56
|
background: var(--panel-2); color: var(--ink); border: 1px solid var(--line);
|
|
47
57
|
border-radius: 6px; padding: 4px 10px; cursor: pointer; font-size: 12px;
|
|
@@ -51,16 +61,28 @@ input[type="search"] {
|
|
|
51
61
|
width: 100%; background: var(--panel); color: var(--ink);
|
|
52
62
|
border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; margin-bottom: 8px;
|
|
53
63
|
}
|
|
54
|
-
.freshness { font-size:
|
|
64
|
+
.freshness { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
|
|
55
65
|
.run-list { list-style: none; margin: 0; padding: 0; }
|
|
56
|
-
.run-list li
|
|
66
|
+
.run-list li,
|
|
67
|
+
.run-list button {
|
|
57
68
|
padding: 8px; border: 1px solid var(--line); border-radius: 6px;
|
|
58
69
|
margin-bottom: 6px; cursor: pointer; background: var(--panel);
|
|
59
70
|
}
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
/* Only the run-row <button> needs a plain-element reset: a <button> has
|
|
72
|
+
its own default display/width/font/color, a plain <li> (used only for
|
|
73
|
+
the error and empty-state rows) does not and must keep its own color
|
|
74
|
+
(.err red, .muted gray) — see app.js. */
|
|
75
|
+
.run-list button {
|
|
76
|
+
display: block; width: 100%; text-align: left; font: inherit; color: inherit;
|
|
77
|
+
}
|
|
78
|
+
.run-list li:hover, .run-list button:hover { border-color: var(--accent); }
|
|
79
|
+
.run-list li.active, .run-list button.active { border-color: var(--accent); background: var(--panel-2); }
|
|
80
|
+
/* Run rows are now real <button> elements (for Tab/Enter/Space); make the
|
|
81
|
+
keyboard focus ring visible — there is no :focus-visible rule for this
|
|
82
|
+
element otherwise. */
|
|
83
|
+
.run-list button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
62
84
|
.run-list .rid { font-family: ui-monospace, monospace; font-size: 12px; display: flex; align-items: center; gap: 6px; }
|
|
63
|
-
.run-list .meta { color: var(--muted); font-size:
|
|
85
|
+
.run-list .meta { color: var(--muted); font-size: 12px; margin-top: 2px; }
|
|
64
86
|
.status-dot {
|
|
65
87
|
display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none;
|
|
66
88
|
background: var(--muted);
|
|
@@ -81,13 +103,23 @@ input[type="search"] {
|
|
|
81
103
|
padding: 8px 12px; border-bottom: 1px solid var(--line);
|
|
82
104
|
}
|
|
83
105
|
.panel-card > .head .title { font-weight: 600; }
|
|
84
|
-
.panel-card > .head .src { font-size:
|
|
85
|
-
.badge { font-size:
|
|
106
|
+
.panel-card > .head .src { font-size: 12px; color: var(--muted); font-family: ui-monospace, monospace; }
|
|
107
|
+
.badge { font-size: 12px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line); }
|
|
86
108
|
.badge.present { color: var(--present); border-color: var(--present); }
|
|
87
109
|
.badge.absent { color: var(--absent); border-color: var(--absent); }
|
|
88
110
|
.badge.stale { color: var(--absent); border-color: var(--absent); }
|
|
89
111
|
.badge.valid { color: var(--present); border-color: var(--present); }
|
|
90
112
|
.badge.missing, .badge.bad { color: var(--bad); border-color: var(--bad); }
|
|
113
|
+
/* Lifecycle states shown as a badge in the run detail header (the other
|
|
114
|
+
lifecycle values reuse the neutral/present/absent colors above). */
|
|
115
|
+
.badge.blocked { color: var(--absent); border-color: var(--absent); }
|
|
116
|
+
.badge.failed { color: var(--bad); border-color: var(--bad); }
|
|
117
|
+
.badge.completed { color: var(--present); border-color: var(--present); }
|
|
118
|
+
.badge.running { color: var(--accent); border-color: var(--accent); }
|
|
119
|
+
/* One plain next-step line under the header when a run is blocked/failed. */
|
|
120
|
+
.recovery-hint { margin: 0 0 12px; font-size: 12px; color: var(--absent); }
|
|
121
|
+
/* Second line of the empty-list state: the suggested next command. */
|
|
122
|
+
.run-list li .hint { margin-top: 4px; font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
91
123
|
pre.json {
|
|
92
124
|
margin: 0; padding: 12px; overflow-x: auto; font-size: 12px;
|
|
93
125
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace; line-height: 1.5;
|
|
@@ -99,7 +131,7 @@ pre.json {
|
|
|
99
131
|
.err { color: var(--bad); }
|
|
100
132
|
.struct-block { padding: 10px 12px; border-top: 1px solid var(--line); }
|
|
101
133
|
.struct-block:first-child { border-top: none; }
|
|
102
|
-
.struct-block .struct-title { font-size:
|
|
134
|
+
.struct-block .struct-title { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 6px; }
|
|
103
135
|
.struct-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
104
136
|
.struct-table th, .struct-table td {
|
|
105
137
|
text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--line);
|