cool-workflow 0.1.92 → 0.1.94
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 +104 -129
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/architecture-review-fast/workflow.js +15 -2
- 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/capability-core.js +47 -0
- package/dist/capability-registry.js +2 -0
- package/dist/cli/command-surface.js +165 -1352
- package/dist/cli/format.js +56 -0
- package/dist/cli/handlers/audit.js +82 -0
- package/dist/cli/handlers/blackboard.js +81 -0
- package/dist/cli/handlers/candidate.js +40 -0
- package/dist/cli/handlers/clones.js +34 -0
- package/dist/cli/handlers/collaboration.js +61 -0
- package/dist/cli/handlers/eval.js +40 -0
- package/dist/cli/handlers/maintenance.js +107 -0
- package/dist/cli/handlers/multi-agent.js +165 -0
- package/dist/cli/handlers/node.js +41 -0
- package/dist/cli/handlers/operational.js +155 -0
- package/dist/cli/handlers/operator.js +146 -0
- package/dist/cli/handlers/registry.js +68 -0
- package/dist/cli/handlers/run.js +153 -0
- package/dist/cli/handlers/scheduling.js +126 -0
- package/dist/cli/handlers/workbench.js +41 -0
- package/dist/cli/handlers/worker.js +45 -0
- package/dist/cli/io.js +27 -0
- package/dist/cli/run-summary.js +45 -0
- package/dist/commit.js +0 -5
- package/dist/execution-backend.js +0 -11
- package/dist/mcp/tool-call.js +2 -0
- package/dist/mcp/tool-definitions.js +8 -0
- package/dist/orchestrator/app-operations.js +205 -0
- package/dist/orchestrator.js +41 -153
- package/dist/state-explosion.js +0 -7
- package/dist/term.js +0 -18
- package/dist/validation.js +0 -21
- package/dist/version.js +1 -1
- package/docs/agent-delegation-drive.7.md +13 -7
- package/docs/cli-mcp-parity.7.md +19 -2
- package/docs/contract-migration-tooling.7.md +3 -1
- package/docs/control-plane-scheduling.7.md +3 -1
- package/docs/durable-state-and-locking.7.md +3 -1
- package/docs/evidence-adoption-reasoning-chain.7.md +3 -1
- package/docs/execution-backends.7.md +3 -1
- package/docs/mcp-app-surface.7.md +12 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +3 -1
- package/docs/multi-agent-eval-replay-harness.7.md +3 -1
- package/docs/multi-agent-operator-ux.7.md +3 -1
- package/docs/node-snapshot-diff-replay.7.md +3 -1
- package/docs/observability-cost-accounting.7.md +3 -1
- package/docs/project-index.md +16 -3
- package/docs/real-execution-backends.7.md +3 -1
- package/docs/release-and-migration.7.md +3 -1
- package/docs/release-tooling.7.md +3 -1
- package/docs/run-registry-control-plane.7.md +27 -3
- package/docs/run-retention-reclamation.7.md +3 -1
- package/docs/state-explosion-management.7.md +3 -1
- package/docs/team-collaboration.7.md +3 -1
- package/docs/web-desktop-workbench.7.md +3 -1
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/agents/builtin-templates.json +3 -2
- package/scripts/agents/claude-p-agent.js +6 -6
- package/scripts/agents/codex-agent.js +17 -3
- package/scripts/agents/deepseek-agent.js +23 -0
- package/scripts/agents/gemini-opencode-agent.js +25 -0
- package/scripts/agents/opencode-agent.js +57 -8
- package/scripts/architecture-review-fast.js +19 -5
- package/scripts/bump-version.js +16 -0
- package/scripts/canonical-apps.js +4 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/parity-check.js +9 -1
- package/scripts/release-flow.js +35 -0
- package/scripts/vendor-preflight.js +127 -0
- package/scripts/version-sync-check.js +5 -0
|
@@ -83,7 +83,7 @@ const canonicalApps = [
|
|
|
83
83
|
"--source",
|
|
84
84
|
"plugins/cool-workflow/docs/workflow-app-framework.7.md",
|
|
85
85
|
"--scope",
|
|
86
|
-
"Cool Workflow v0.1.
|
|
86
|
+
"Cool Workflow v0.1.94",
|
|
87
87
|
"--freshness",
|
|
88
88
|
"as of release preparation"
|
|
89
89
|
]
|
|
@@ -117,14 +117,14 @@ function main() {
|
|
|
117
117
|
assert.ok(summary, `${app.id} must appear in app list`);
|
|
118
118
|
assert.equal(summary.sourceKind, "app-directory");
|
|
119
119
|
assert.equal(summary.legacy, false);
|
|
120
|
-
assert.equal(summary.version, "0.1.
|
|
120
|
+
assert.equal(summary.version, "0.1.94");
|
|
121
121
|
|
|
122
122
|
const validation = runJson(["app", "validate", manifestPath]);
|
|
123
123
|
assert.equal(validation.valid, true, `${app.id} manifest must validate`);
|
|
124
124
|
|
|
125
125
|
const shown = runJson(["app", "show", app.id]);
|
|
126
126
|
assert.equal(shown.app.id, app.id);
|
|
127
|
-
assert.equal(shown.app.version, "0.1.
|
|
127
|
+
assert.equal(shown.app.version, "0.1.94");
|
|
128
128
|
assert.ok(shown.app.metadata.canonical, `${app.id} must be marked canonical`);
|
|
129
129
|
assert.ok(shown.app.sandboxProfiles.length > 0, `${app.id} must declare sandbox profiles`);
|
|
130
130
|
assertTaskIdsUnique(shown);
|
|
@@ -135,7 +135,7 @@ function main() {
|
|
|
135
135
|
const plan = runJson(["plan", app.id, ...app.args(workspace)]);
|
|
136
136
|
const state = JSON.parse(fs.readFileSync(plan.statePath, "utf8"));
|
|
137
137
|
assert.equal(state.workflow.app.id, app.id);
|
|
138
|
-
assert.equal(state.workflow.app.version, "0.1.
|
|
138
|
+
assert.equal(state.workflow.app.version, "0.1.94");
|
|
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/orchestrator.js");
|
|
8
8
|
|
|
9
|
-
const TARGET_VERSION = "0.1.
|
|
9
|
+
const TARGET_VERSION = "0.1.94";
|
|
10
10
|
const PREVIOUS_VERSION = "0.1.31";
|
|
11
11
|
const pluginRoot = path.resolve(__dirname, "..");
|
|
12
12
|
const repoRoot = path.resolve(pluginRoot, "..", "..");
|
package/scripts/golden-path.js
CHANGED
|
@@ -33,7 +33,7 @@ function main() {
|
|
|
33
33
|
const appValidation = runJson(["app", "validate", "end-to-end-golden-path"], pluginRoot);
|
|
34
34
|
assert.equal(appValidation.valid, true);
|
|
35
35
|
assert.equal(appValidation.summary.id, "end-to-end-golden-path");
|
|
36
|
-
assert.equal(appValidation.summary.version, "0.1.
|
|
36
|
+
assert.equal(appValidation.summary.version, "0.1.94");
|
|
37
37
|
|
|
38
38
|
const plan = runJson(
|
|
39
39
|
[
|
|
@@ -42,7 +42,7 @@ function main() {
|
|
|
42
42
|
"--repo",
|
|
43
43
|
tmp,
|
|
44
44
|
"--question",
|
|
45
|
-
"Prove the deterministic v0.1.
|
|
45
|
+
"Prove the deterministic v0.1.94 end-to-end golden path."
|
|
46
46
|
],
|
|
47
47
|
pluginRoot
|
|
48
48
|
);
|
|
@@ -52,7 +52,7 @@ function main() {
|
|
|
52
52
|
|
|
53
53
|
let state = readJson(plan.statePath);
|
|
54
54
|
assert.equal(state.workflow.app.id, "end-to-end-golden-path");
|
|
55
|
-
assert.equal(state.workflow.app.version, "0.1.
|
|
55
|
+
assert.equal(state.workflow.app.version, "0.1.94");
|
|
56
56
|
assert.equal(state.loopStage, "interpret");
|
|
57
57
|
|
|
58
58
|
const dispatch = runJson(["dispatch", plan.runId, "--limit", "1", "--sandbox", "readonly"], tmp);
|
|
@@ -195,7 +195,7 @@ function main() {
|
|
|
195
195
|
assert.equal(reportPath, plan.reportPath);
|
|
196
196
|
assert.ok(fs.existsSync(reportPath));
|
|
197
197
|
const report = fs.readFileSync(reportPath, "utf8");
|
|
198
|
-
assert.match(report, /Workflow App: end-to-end-golden-path@0\.1\.
|
|
198
|
+
assert.match(report, /Workflow App: end-to-end-golden-path@0\.1\.94/);
|
|
199
199
|
assert.match(report, /## Candidates/);
|
|
200
200
|
assert.match(report, /## Trust Audit/);
|
|
201
201
|
assert.match(report, /## Acceptance Rationale/);
|
package/scripts/parity-check.js
CHANGED
|
@@ -69,7 +69,15 @@ function cliDispatchTokens() {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function cliDispatchSources() {
|
|
72
|
-
|
|
72
|
+
// The dispatcher + every per-command handler module carved out of it (the
|
|
73
|
+
// command-surface god-object decomposition). A verb's subcommand `case`s may
|
|
74
|
+
// live in dist/cli/handlers/<group>.js, so scan those too or their tokens read
|
|
75
|
+
// as "missing from dist/cli.js".
|
|
76
|
+
const handlersDir = path.join(pluginRoot, "dist", "cli", "handlers");
|
|
77
|
+
const handlerFiles = fs.existsSync(handlersDir)
|
|
78
|
+
? fs.readdirSync(handlersDir).filter((name) => name.endsWith(".js")).map((name) => path.join(handlersDir, name))
|
|
79
|
+
: [];
|
|
80
|
+
return [cli, path.join(pluginRoot, "dist", "cli", "command-surface.js"), ...handlerFiles].filter((file) => fs.existsSync(file));
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
function cliHelpTokens() {
|
package/scripts/release-flow.js
CHANGED
|
@@ -119,6 +119,40 @@ function runGate() {
|
|
|
119
119
|
if (r.status !== 0) die("deterministic gate FAILED — fix findings in normal cycles, do not retry the release here.");
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
// ---- 1b. vendor liveness preflight (cut only) ------------------------------
|
|
123
|
+
// CW promises claude/codex/gemini/deepseek all work; this proves it before a cut.
|
|
124
|
+
// LIVE: spends real tokens on each vendor, so it runs on --cut (release machine
|
|
125
|
+
// has the keys), not on --check. HARD-BLOCK: any vendor not green stops the cut.
|
|
126
|
+
// Escape hatch CW_SKIP_VENDOR_PREFLIGHT=1 (emergencies/offline). Test seam
|
|
127
|
+
// CW_RELEASE_FLOW_PREFLIGHT_CMD overrides the command (smoke stubs it).
|
|
128
|
+
function runVendorPreflight() {
|
|
129
|
+
if (!MODE_CUT) {
|
|
130
|
+
say("[1b/3] vendor preflight — skipped (check mode; live vendor calls run on --cut)");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (process.env.CW_SKIP_VENDOR_PREFLIGHT === "1") {
|
|
134
|
+
say("[1b/3] vendor preflight — SKIPPED via CW_SKIP_VENDOR_PREFLIGHT=1 (operator override)");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const vendors = (process.env.CW_PREFLIGHT_VENDORS || "claude,codex,gemini,deepseek").trim();
|
|
138
|
+
const override = (process.env.CW_RELEASE_FLOW_PREFLIGHT_CMD || "").trim();
|
|
139
|
+
say(`[1b/3] vendor preflight — live liveness check: ${vendors}`);
|
|
140
|
+
let r;
|
|
141
|
+
if (override) {
|
|
142
|
+
// Test/override seam — shell:true, smoke/operator only, never the delegated agent.
|
|
143
|
+
r = spawnSync(override, { cwd: repoRoot, encoding: "utf8", shell: true, stdio: "inherit" });
|
|
144
|
+
} else {
|
|
145
|
+
r = spawnSync(process.execPath, [path.join(scriptsDir, "vendor-preflight.js"), "--vendors", vendors], {
|
|
146
|
+
cwd: repoRoot,
|
|
147
|
+
encoding: "utf8",
|
|
148
|
+
stdio: "inherit"
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (r.status !== 0) {
|
|
152
|
+
die("vendor preflight FAILED — a promised vendor is not live (missing CLI/key or broken). Users must not be limited to one vendor; fix before cutting, or set CW_SKIP_VENDOR_PREFLIGHT=1 to override.");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
122
156
|
// ---- 2. independent reviewer, delegated to the configured agent -------------
|
|
123
157
|
function reviewerPromptBody() {
|
|
124
158
|
// Reuse the committed reviewer spec as the prompt; strip YAML frontmatter.
|
|
@@ -476,6 +510,7 @@ function main() {
|
|
|
476
510
|
const inputPath = path.join(markerDir, `review-input-${HEAD}.md`);
|
|
477
511
|
|
|
478
512
|
runGate();
|
|
513
|
+
runVendorPreflight();
|
|
479
514
|
fs.writeFileSync(inputPath, buildReviewerInput(resultPath));
|
|
480
515
|
delegateReview(resultPath, inputPath);
|
|
481
516
|
const capability = verifyVerdict(resultPath);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// vendor-preflight.js — pre-release liveness gate for ALL agent vendors.
|
|
5
|
+
//
|
|
6
|
+
// CW promises that claude, codex, gemini, and deepseek all work. This gate
|
|
7
|
+
// proves it before a release: it runs EACH builtin wrapper against a tiny
|
|
8
|
+
// throwaway git repo with a trivial question and checks the wrapper returns a
|
|
9
|
+
// real, non-empty result. It is the enforcement behind that promise.
|
|
10
|
+
//
|
|
11
|
+
// HARD-BLOCK policy (operator chose this): a vendor that does not return a valid
|
|
12
|
+
// result — missing CLI, auth error, empty/garbage output — counts as FAIL and
|
|
13
|
+
// the gate exits nonzero. There is no "skip"; an unconfigured vendor blocks.
|
|
14
|
+
//
|
|
15
|
+
// This is a LIVE gate: it spends real tokens on each configured vendor. It is
|
|
16
|
+
// meant for the release machine (where all keys/logins exist), NOT the offline
|
|
17
|
+
// CI test suite. The offline smoke (test/vendor-preflight-smoke.js) exercises
|
|
18
|
+
// this script's LOGIC with PATH shims, no keys.
|
|
19
|
+
//
|
|
20
|
+
// Zero runtime dependency: node + git only. stdout is data (the matrix), stderr
|
|
21
|
+
// is diagnostics — same discipline as the rest of CW.
|
|
22
|
+
//
|
|
23
|
+
// Usage:
|
|
24
|
+
// node vendor-preflight.js [--vendors claude,codex,deepseek] [--question "..."]
|
|
25
|
+
// [--timeout-ms 180000] [--json] [--keep]
|
|
26
|
+
//
|
|
27
|
+
// Test seam (smoke/operator only):
|
|
28
|
+
// CW_PREFLIGHT_AGENTS_DIR override where wrapper scripts + builtin-templates.json
|
|
29
|
+
// are read from (the smoke points this at a shim dir).
|
|
30
|
+
|
|
31
|
+
const fs = require("node:fs");
|
|
32
|
+
const os = require("node:os");
|
|
33
|
+
const path = require("node:path");
|
|
34
|
+
const { spawnSync } = require("node:child_process");
|
|
35
|
+
|
|
36
|
+
function argValue(flag, fallback) {
|
|
37
|
+
const i = process.argv.indexOf(flag);
|
|
38
|
+
return i >= 0 && i + 1 < process.argv.length ? process.argv[i + 1] : fallback;
|
|
39
|
+
}
|
|
40
|
+
const hasFlag = (flag) => process.argv.includes(flag);
|
|
41
|
+
|
|
42
|
+
const agentsDir = process.env.CW_PREFLIGHT_AGENTS_DIR || path.join(__dirname, "agents");
|
|
43
|
+
const manifestPath = path.join(agentsDir, "builtin-templates.json");
|
|
44
|
+
const question = argValue("--question", "In one sentence, what does this repo do? Keep it short.");
|
|
45
|
+
const timeoutMs = Number(argValue("--timeout-ms", "180000")) || 180000;
|
|
46
|
+
const asJson = hasFlag("--json");
|
|
47
|
+
const keep = hasFlag("--keep");
|
|
48
|
+
|
|
49
|
+
function die(msg) {
|
|
50
|
+
process.stderr.write(msg + "\n");
|
|
51
|
+
process.exit(2);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let templates;
|
|
55
|
+
try {
|
|
56
|
+
templates = JSON.parse(fs.readFileSync(manifestPath, "utf8")).templates || {};
|
|
57
|
+
} catch (e) {
|
|
58
|
+
die(`vendor-preflight: cannot read ${manifestPath}: ${e.message}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const onlyRaw = argValue("--vendors", "");
|
|
62
|
+
const only = onlyRaw ? onlyRaw.split(",").map((s) => s.trim()).filter(Boolean) : null;
|
|
63
|
+
const vendors = Object.keys(templates).filter((v) => !only || only.includes(v));
|
|
64
|
+
if (only) {
|
|
65
|
+
for (const v of only) if (!templates[v]) die(`vendor-preflight: unknown vendor "${v}" — known: ${Object.keys(templates).join(", ")}`);
|
|
66
|
+
}
|
|
67
|
+
if (!vendors.length) die("vendor-preflight: no vendors to check");
|
|
68
|
+
|
|
69
|
+
// One throwaway git repo + worker input, reused read-only across vendors.
|
|
70
|
+
const work = fs.mkdtempSync(path.join(os.tmpdir(), "cw-preflight-"));
|
|
71
|
+
const repo = path.join(work, "repo");
|
|
72
|
+
fs.mkdirSync(repo, { recursive: true });
|
|
73
|
+
spawnSync("git", ["init", "-q"], { cwd: repo });
|
|
74
|
+
fs.writeFileSync(path.join(repo, "README.md"), "# Tiny App\n\nA one-file demo. main.js reads input and prints it.\n");
|
|
75
|
+
const inputPath = path.join(repo, "input.md");
|
|
76
|
+
fs.writeFileSync(inputPath, `# Worker preflight\n\n- Result: ${path.join(repo, "result.md")}\n\n## Task\n\n${question}\n`);
|
|
77
|
+
|
|
78
|
+
function checkVendor(name) {
|
|
79
|
+
const script = templates[name];
|
|
80
|
+
const wrapper = path.join(agentsDir, script);
|
|
81
|
+
const resultPath = path.join(repo, `result-${name}.md`);
|
|
82
|
+
try { fs.rmSync(resultPath, { force: true }); } catch { /* ignore */ }
|
|
83
|
+
const started = process.hrtime.bigint();
|
|
84
|
+
const r = spawnSync(process.execPath, [wrapper, inputPath, resultPath], {
|
|
85
|
+
cwd: repo,
|
|
86
|
+
encoding: "utf8",
|
|
87
|
+
timeout: timeoutMs,
|
|
88
|
+
env: { ...process.env, CW_AGENT_STREAM: "0" }
|
|
89
|
+
});
|
|
90
|
+
const ms = Number((process.hrtime.bigint() - started) / 1000000n);
|
|
91
|
+
const result = (() => { try { return fs.readFileSync(resultPath, "utf8"); } catch { return ""; } })();
|
|
92
|
+
let model;
|
|
93
|
+
try { model = JSON.parse(r.stdout || "{}").model; } catch { /* provenance optional */ }
|
|
94
|
+
|
|
95
|
+
let status = "PASS";
|
|
96
|
+
let reason = "";
|
|
97
|
+
if (r.error && r.error.code === "ETIMEDOUT") {
|
|
98
|
+
status = "FAIL"; reason = `timed out after ${timeoutMs}ms`;
|
|
99
|
+
} else if (r.status !== 0) {
|
|
100
|
+
status = "FAIL"; reason = (r.stderr || "").trim().split("\n").pop() || `exit ${r.status}`;
|
|
101
|
+
} else if (!result.trim()) {
|
|
102
|
+
status = "FAIL"; reason = "exit 0 but empty result";
|
|
103
|
+
}
|
|
104
|
+
return { vendor: name, status, reason, ms, model, hasContract: /```cw:result/.test(result) };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const rows = vendors.map(checkVendor);
|
|
108
|
+
if (!keep) { try { fs.rmSync(work, { recursive: true, force: true }); } catch { /* ignore */ } }
|
|
109
|
+
|
|
110
|
+
const failed = rows.filter((r) => r.status !== "PASS");
|
|
111
|
+
|
|
112
|
+
if (asJson) {
|
|
113
|
+
process.stdout.write(JSON.stringify({ ok: failed.length === 0, vendors: rows }, null, 2) + "\n");
|
|
114
|
+
} else {
|
|
115
|
+
for (const r of rows) {
|
|
116
|
+
const mark = r.status === "PASS" ? "✓" : "✗";
|
|
117
|
+
const extra = r.status === "PASS"
|
|
118
|
+
? `${r.ms}ms${r.model ? `, ${r.model}` : ""}${r.hasContract ? "" : ", no cw:result block"}`
|
|
119
|
+
: r.reason;
|
|
120
|
+
process.stdout.write(` ${mark} ${r.vendor.padEnd(10)} ${r.status} (${extra})\n`);
|
|
121
|
+
}
|
|
122
|
+
process.stdout.write(failed.length === 0
|
|
123
|
+
? `vendor-preflight: ok — ${rows.length}/${rows.length} vendors live\n`
|
|
124
|
+
: `vendor-preflight: BLOCKED — ${failed.length}/${rows.length} vendor(s) not live: ${failed.map((r) => r.vendor).join(", ")}\n`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
process.exit(failed.length === 0 ? 0 : 1);
|
|
@@ -196,6 +196,11 @@ function main() {
|
|
|
196
196
|
checkIncludes("plugins/cool-workflow/docs/release-and-migration.7.md", VERSION, checks);
|
|
197
197
|
checkIncludes("CHANGELOG.md", `## ${VERSION}`, checks);
|
|
198
198
|
checkIncludes("RELEASE.md", VERSION, checks);
|
|
199
|
+
// Homebrew formula (repo root): git-tag formula. Homebrew scans the version
|
|
200
|
+
// from the tag, so the tag is the single version surface to gate (an explicit
|
|
201
|
+
// `version` line would be redundant and brew audit rejects it). bump-version.js
|
|
202
|
+
// moves this tag.
|
|
203
|
+
checkIncludes("Formula/cool-workflow.rb", `tag: "v${VERSION}"`, checks);
|
|
199
204
|
checkIncludes("plugins/cool-workflow/skills/cool-workflow/SKILL.md", "release:check", checks);
|
|
200
205
|
|
|
201
206
|
process.stdout.write(
|