cool-workflow 0.1.78 → 0.1.80
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 +29 -3
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +64 -0
- package/apps/architecture-review-fast/workflow.js +153 -0
- 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 +71 -0
- package/dist/capability-registry.js +13 -8
- package/dist/cli.js +49 -1
- package/dist/drive.js +74 -1
- package/dist/evidence-reasoning.js +2 -2
- package/dist/execution-backend.js +6 -1
- package/dist/mcp-server.js +56 -13
- package/dist/orchestrator/lifecycle-operations.js +2 -1
- package/dist/orchestrator.js +1 -1
- package/dist/run-export.js +370 -25
- package/dist/run-registry.js +11 -4
- package/dist/state-explosion.js +100 -21
- package/dist/telemetry-demo.js +154 -0
- package/dist/version.js +1 -1
- package/docs/agent-delegation-drive.7.md +60 -0
- package/docs/canonical-workflow-apps.7.md +37 -0
- package/docs/cli-mcp-parity.7.md +14 -0
- package/docs/contract-migration-tooling.7.md +6 -0
- package/docs/control-plane-scheduling.7.md +6 -0
- package/docs/durable-state-and-locking.7.md +6 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +6 -0
- package/docs/execution-backends.7.md +6 -0
- package/docs/index.md +1 -0
- package/docs/launch/demo.tape +28 -0
- package/docs/launch/launch-kit.md +172 -0
- package/docs/launch/pre-launch-checklist.md +53 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +6 -0
- package/docs/multi-agent-eval-replay-harness.7.md +6 -0
- package/docs/multi-agent-operator-ux.7.md +6 -0
- package/docs/node-snapshot-diff-replay.7.md +6 -0
- package/docs/observability-cost-accounting.7.md +6 -0
- package/docs/project-index.md +16 -6
- package/docs/real-execution-backends.7.md +6 -0
- package/docs/release-and-migration.7.md +6 -0
- package/docs/release-tooling.7.md +6 -0
- package/docs/routines.md +23 -0
- package/docs/run-registry-control-plane.7.md +44 -1
- package/docs/run-retention-reclamation.7.md +6 -0
- package/docs/source-context-profiles.7.md +119 -0
- package/docs/state-explosion-management.7.md +13 -0
- package/docs/team-collaboration.7.md +6 -0
- package/docs/unix-principles.md +49 -1
- package/docs/web-desktop-workbench.7.md +6 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +142 -0
- package/package.json +2 -1
- package/scripts/agents/claude-p-agent.js +129 -43
- package/scripts/architecture-review-fast.js +362 -0
- package/scripts/bump-version.js +1 -0
- package/scripts/canonical-apps.js +21 -4
- package/scripts/coverage-gate.js +211 -0
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/source-context.js +291 -0
- package/scripts/version-sync-check.js +1 -0
- package/skills/ci-triage/SKILL.md +50 -0
- package/skills/ci-triage/agents/openai.yaml +4 -0
- package/skills/cool-workflow/SKILL.md +4 -1
- package/skills/deploy-check/SKILL.md +55 -0
- package/skills/deploy-check/agents/openai.yaml +4 -0
- package/skills/design-qa/SKILL.md +49 -0
- package/skills/design-qa/agents/openai.yaml +4 -0
- package/skills/pr-review/SKILL.md +45 -0
- package/skills/pr-review/agents/openai.yaml +4 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// source-context — opt-in JSONL source context exporter.
|
|
5
|
+
//
|
|
6
|
+
// Policy is data in manifest/source-context-profiles.json. This script is only
|
|
7
|
+
// mechanism: enumerate tracked files for a git ref, classify them through the
|
|
8
|
+
// selected profile, hash the committed bytes, and print JSONL to stdout.
|
|
9
|
+
|
|
10
|
+
const crypto = require("node:crypto");
|
|
11
|
+
const fs = require("node:fs");
|
|
12
|
+
const path = require("node:path");
|
|
13
|
+
const { spawnSync } = require("node:child_process");
|
|
14
|
+
|
|
15
|
+
const pluginRoot = path.resolve(__dirname, "..");
|
|
16
|
+
const defaultRepoRoot = path.resolve(pluginRoot, "..", "..");
|
|
17
|
+
let repoRoot = defaultRepoRoot;
|
|
18
|
+
const DEFAULT_PROFILE_FILE = path.join(pluginRoot, "manifest", "source-context-profiles.json");
|
|
19
|
+
|
|
20
|
+
const command = process.argv[2];
|
|
21
|
+
const args = process.argv.slice(3);
|
|
22
|
+
|
|
23
|
+
function main() {
|
|
24
|
+
if (!["export", "manifest", "profiles"].includes(command)) {
|
|
25
|
+
usage(1, `unknown command: ${command || "(missing)"}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const profileFile = valueArg("--profile-file") || DEFAULT_PROFILE_FILE;
|
|
30
|
+
repoRoot = path.resolve(valueArg("--repo-root") || defaultRepoRoot);
|
|
31
|
+
const profiles = readProfiles(profileFile);
|
|
32
|
+
|
|
33
|
+
if (command === "profiles") {
|
|
34
|
+
for (const [id, profile] of Object.entries(profiles.profiles)) {
|
|
35
|
+
writeJsonl({
|
|
36
|
+
schemaVersion: profiles.schemaVersion,
|
|
37
|
+
id,
|
|
38
|
+
description: profile.description || "",
|
|
39
|
+
maxLines: Number(profile.maxLines) || null,
|
|
40
|
+
include: profile.include || [],
|
|
41
|
+
exclude: profile.exclude || []
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const profileId = valueArg("--profile") || "core";
|
|
48
|
+
const profile = profiles.profiles[profileId];
|
|
49
|
+
if (!profile) die(`unknown profile: ${profileId}`);
|
|
50
|
+
|
|
51
|
+
const ref = resolveRef(valueArg("--ref") || "HEAD");
|
|
52
|
+
const changedFrom = valueArg("--changed-from") ? resolveRef(valueArg("--changed-from")) : "";
|
|
53
|
+
const changedPaths = changedFrom ? changedPathSet(changedFrom, ref) : null;
|
|
54
|
+
const cacheDir = command === "export" ? valueArg("--cache-dir") : "";
|
|
55
|
+
const cachePath = cacheDir ? sourceContextCachePath(cacheDir, profileId, ref, profile, changedFrom) : "";
|
|
56
|
+
if (cachePath && fs.existsSync(cachePath)) {
|
|
57
|
+
process.stdout.write(readValidCache(cachePath, profileId, ref, changedFrom));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const files = gitLines(["ls-tree", "-r", "--name-only", ref]).filter((file) => !changedPaths || changedPaths.has(file));
|
|
62
|
+
let exportedLines = 0;
|
|
63
|
+
const buffered = cachePath ? [] : null;
|
|
64
|
+
const emit = (value) => {
|
|
65
|
+
if (buffered) buffered.push(JSON.stringify(value));
|
|
66
|
+
else writeJsonl(value);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
for (const file of files) {
|
|
70
|
+
const classification = classify(file, profile);
|
|
71
|
+
const blob = gitBlob(ref, file);
|
|
72
|
+
const binary = isBinary(blob);
|
|
73
|
+
const record = {
|
|
74
|
+
schemaVersion: profiles.schemaVersion,
|
|
75
|
+
profile: profileId,
|
|
76
|
+
ref,
|
|
77
|
+
path: file,
|
|
78
|
+
bytes: blob.length,
|
|
79
|
+
lines: binary ? null : countLines(blob),
|
|
80
|
+
sha256: sha256(blob),
|
|
81
|
+
included: classification.included,
|
|
82
|
+
reason: classification.reason,
|
|
83
|
+
...(changedFrom ? { changedFrom } : {})
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
if (command === "manifest") {
|
|
87
|
+
emit(record);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!classification.included) continue;
|
|
92
|
+
if (binary) die(`included file is binary: ${file}`);
|
|
93
|
+
exportedLines += record.lines || 0;
|
|
94
|
+
emit({ ...record, content: blob.toString("utf8") });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const maxLines = Number(profile.maxLines) || 0;
|
|
98
|
+
if (command === "export" && maxLines > 0 && exportedLines > maxLines) {
|
|
99
|
+
die(`profile ${profileId} exported ${exportedLines} lines, above maxLines ${maxLines}`);
|
|
100
|
+
}
|
|
101
|
+
if (cachePath && buffered) {
|
|
102
|
+
const text = buffered.map((line) => `${line}\n`).join("");
|
|
103
|
+
writeCache(cachePath, text);
|
|
104
|
+
process.stdout.write(text);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function usage(code, message) {
|
|
109
|
+
if (message) process.stderr.write(`source-context: ${message}\n`);
|
|
110
|
+
process.stderr.write(
|
|
111
|
+
[
|
|
112
|
+
"usage:",
|
|
113
|
+
" node scripts/source-context.js profiles",
|
|
114
|
+
" node scripts/source-context.js manifest [--profile core] [--ref HEAD] [--changed-from REF] [--repo-root DIR]",
|
|
115
|
+
" node scripts/source-context.js export [--profile core] [--ref HEAD] [--changed-from REF] [--repo-root DIR] [--cache-dir DIR]"
|
|
116
|
+
].join("\n") + "\n"
|
|
117
|
+
);
|
|
118
|
+
process.exitCode = code;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function valueArg(name) {
|
|
122
|
+
const eq = args.find((arg) => arg.startsWith(`${name}=`));
|
|
123
|
+
if (eq) return eq.slice(name.length + 1);
|
|
124
|
+
const idx = args.indexOf(name);
|
|
125
|
+
return idx >= 0 ? args[idx + 1] : "";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function readProfiles(file) {
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
132
|
+
} catch (error) {
|
|
133
|
+
die(`cannot read profile file ${rel(file)}: ${error.message}`);
|
|
134
|
+
}
|
|
135
|
+
if (!parsed || parsed.schemaVersion !== 1 || !parsed.profiles || typeof parsed.profiles !== "object") {
|
|
136
|
+
die(`invalid source context profile file: ${rel(file)}`);
|
|
137
|
+
}
|
|
138
|
+
for (const [id, profile] of Object.entries(parsed.profiles)) {
|
|
139
|
+
if (!Array.isArray(profile.include) || !Array.isArray(profile.exclude)) {
|
|
140
|
+
die(`profile ${id} must define include and exclude arrays`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return parsed;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function resolveRef(ref) {
|
|
147
|
+
return git(["rev-parse", "--verify", `${ref}^{commit}`]).trim();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function gitLines(argv) {
|
|
151
|
+
return git(argv).split(/\r?\n/).filter(Boolean);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function changedPathSet(base, ref) {
|
|
155
|
+
return new Set(gitLines(["diff", "--name-only", "--diff-filter=ACMRT", `${base}..${ref}`]));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function git(argv) {
|
|
159
|
+
const result = spawnSync("git", argv, { cwd: repoRoot, encoding: "utf8" });
|
|
160
|
+
if (result.status !== 0) die((result.stderr || result.stdout || `git ${argv.join(" ")} failed`).trim());
|
|
161
|
+
return result.stdout;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function gitBlob(ref, file) {
|
|
165
|
+
const result = spawnSync("git", ["show", `${ref}:${file}`], { cwd: repoRoot, encoding: "buffer", maxBuffer: 1024 * 1024 * 64 });
|
|
166
|
+
if (result.status !== 0) die((result.stderr || result.stdout || `cannot read ${file} at ${ref}`).toString().trim());
|
|
167
|
+
return result.stdout;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function classify(file, profile) {
|
|
171
|
+
const excludedBy = (profile.exclude || []).find((pattern) => matches(pattern, file));
|
|
172
|
+
if (excludedBy) return { included: false, reason: `excluded:${excludedBy}` };
|
|
173
|
+
const includedBy = (profile.include || []).find((pattern) => matches(pattern, file));
|
|
174
|
+
if (includedBy) return { included: true, reason: `included:${includedBy}` };
|
|
175
|
+
return { included: false, reason: "not-included" };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function matches(pattern, file) {
|
|
179
|
+
if (pattern.endsWith("/**")) {
|
|
180
|
+
const dir = pattern.slice(0, -3);
|
|
181
|
+
return file === dir || file.startsWith(`${dir}/`);
|
|
182
|
+
}
|
|
183
|
+
if (!pattern.includes("*")) return file === pattern;
|
|
184
|
+
const escaped = pattern
|
|
185
|
+
.split("*")
|
|
186
|
+
.map((part) => part.replace(/[|\\{}()[\]^$+?.]/g, "\\$&"))
|
|
187
|
+
.join("[^/]*");
|
|
188
|
+
return new RegExp(`^${escaped}$`).test(file);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function countLines(buffer) {
|
|
192
|
+
if (buffer.length === 0) return 0;
|
|
193
|
+
let count = 0;
|
|
194
|
+
for (const byte of buffer) if (byte === 10) count++;
|
|
195
|
+
return buffer[buffer.length - 1] === 10 ? count : count + 1;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function isBinary(buffer) {
|
|
199
|
+
return buffer.includes(0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function sha256(buffer) {
|
|
203
|
+
return crypto.createHash("sha256").update(buffer).digest("hex");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function profileDigest(profileId, profile) {
|
|
207
|
+
return sha256(Buffer.from(stableStringify({ profileId, profile }), "utf8"));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function sourceContextCachePath(cacheDir, profileId, ref, profile, changedFrom) {
|
|
211
|
+
const safeProfile = String(profileId).replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
212
|
+
const diffPart = changedFrom ? `-changed-${changedFrom.slice(0, 12)}` : "";
|
|
213
|
+
const digest = sha256(Buffer.from(stableStringify({ profileId, profile, changedFrom: changedFrom || "" }), "utf8")).slice(0, 16);
|
|
214
|
+
return path.join(path.resolve(cacheDir), `${safeProfile}-${ref.slice(0, 12)}${diffPart}-${digest}.jsonl`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function readValidCache(file, profileId, ref, changedFrom) {
|
|
218
|
+
let text;
|
|
219
|
+
try {
|
|
220
|
+
text = fs.readFileSync(file, "utf8");
|
|
221
|
+
} catch (error) {
|
|
222
|
+
die(`cannot read source context cache ${rel(file)}: ${error.message}`);
|
|
223
|
+
}
|
|
224
|
+
if (text.length > 0 && !text.endsWith("\n")) {
|
|
225
|
+
die(`invalid source context cache ${rel(file)}: missing trailing newline`);
|
|
226
|
+
}
|
|
227
|
+
for (const line of text.split(/\n/)) {
|
|
228
|
+
if (!line) continue;
|
|
229
|
+
let record;
|
|
230
|
+
try {
|
|
231
|
+
record = JSON.parse(line);
|
|
232
|
+
} catch {
|
|
233
|
+
die(`invalid source context cache ${rel(file)}: non-JSONL record`);
|
|
234
|
+
}
|
|
235
|
+
if (
|
|
236
|
+
!record ||
|
|
237
|
+
record.profile !== profileId ||
|
|
238
|
+
record.ref !== ref ||
|
|
239
|
+
String(record.changedFrom || "") !== String(changedFrom || "") ||
|
|
240
|
+
record.included !== true ||
|
|
241
|
+
typeof record.path !== "string" ||
|
|
242
|
+
typeof record.content !== "string" ||
|
|
243
|
+
!/^[0-9a-f]{64}$/.test(String(record.sha256 || ""))
|
|
244
|
+
) {
|
|
245
|
+
die(`invalid source context cache ${rel(file)}: record does not match profile/ref`);
|
|
246
|
+
}
|
|
247
|
+
const contentBytes = Buffer.from(record.content, "utf8");
|
|
248
|
+
if (
|
|
249
|
+
record.sha256 !== sha256(contentBytes) ||
|
|
250
|
+
record.bytes !== contentBytes.length ||
|
|
251
|
+
record.lines !== countLines(contentBytes)
|
|
252
|
+
) {
|
|
253
|
+
die(`invalid source context cache ${rel(file)}: content digest mismatch`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return text;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function writeCache(file, text) {
|
|
260
|
+
try {
|
|
261
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
262
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
263
|
+
fs.writeFileSync(tmp, text, "utf8");
|
|
264
|
+
fs.renameSync(tmp, file);
|
|
265
|
+
} catch (error) {
|
|
266
|
+
die(`cannot write source context cache ${rel(file)}: ${error.message}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function stableStringify(value) {
|
|
271
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
272
|
+
if (value && typeof value === "object") {
|
|
273
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(",")}}`;
|
|
274
|
+
}
|
|
275
|
+
return JSON.stringify(value);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function writeJsonl(value) {
|
|
279
|
+
process.stdout.write(`${JSON.stringify(value)}\n`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function rel(file) {
|
|
283
|
+
return path.relative(repoRoot, path.resolve(file));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function die(message) {
|
|
287
|
+
process.stderr.write(`source-context: ${message}\n`);
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
main();
|
|
@@ -49,6 +49,7 @@ function readReleaseSource(relativePath) {
|
|
|
49
49
|
const VERSION = JSON.parse(readReleaseSource("plugins/cool-workflow/package.json").text).version;
|
|
50
50
|
const canonicalApps = [
|
|
51
51
|
"architecture-review",
|
|
52
|
+
"architecture-review-fast",
|
|
52
53
|
"end-to-end-golden-path",
|
|
53
54
|
"pr-review-fix-ci",
|
|
54
55
|
"release-cut",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-triage
|
|
3
|
+
description: >-
|
|
4
|
+
Diagnose failing CI, build, release-gate, or test runs for Cool Workflow. Use
|
|
5
|
+
when a GitHub Actions check, local npm test, npm run build, release gate,
|
|
6
|
+
smoke test, or generated-manifest check fails and Codex must identify the
|
|
7
|
+
first actionable failure with logs and verifier commands.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# CI Triage
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Triage the failure before editing. Keep stdout/log evidence separate from
|
|
15
|
+
diagnosis, identify the first failing command, and end with one verifier command
|
|
16
|
+
that proves the proposed fix.
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
1. Capture the failing command, exit code, and the earliest meaningful error.
|
|
21
|
+
2. Classify the failure as code, test expectation, generated artifact drift,
|
|
22
|
+
environment, timeout, or external service.
|
|
23
|
+
3. Inspect only the files needed to explain that first failure.
|
|
24
|
+
4. Propose or implement the smallest fix.
|
|
25
|
+
5. Run the narrow verifier first, then the full gate when the fix is plausible.
|
|
26
|
+
6. Write the lesson back to `PROJECT_MEMORY.md`, an eval case, or the matching
|
|
27
|
+
workflow skill when the failure pattern is likely to recur.
|
|
28
|
+
|
|
29
|
+
## Commands
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm run build
|
|
33
|
+
npm test
|
|
34
|
+
npm run gen:manifests -- --check
|
|
35
|
+
npm run index:check
|
|
36
|
+
git diff --check
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Use smoke tests directly for narrow verification:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
node test/<name>-smoke.js
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Output Rules
|
|
46
|
+
|
|
47
|
+
- Lead with the failing command and root cause.
|
|
48
|
+
- Quote only the shortest relevant log lines.
|
|
49
|
+
- Separate "confirmed" from "inference".
|
|
50
|
+
- Include the verifier commands actually run or still required.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cool-workflow
|
|
3
|
-
description:
|
|
3
|
+
description: >-
|
|
4
|
+
Use when the user asks for Cool Workflow, CW, agent workflow control-plane,
|
|
5
|
+
TypeScript workflow orchestration, phased multi-agent work, background
|
|
6
|
+
workflow tasks, reusable workflow apps, or auditable agent run state.
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Cool Workflow
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-check
|
|
3
|
+
description: >-
|
|
4
|
+
Verify Cool Workflow release, publish, deploy, or package readiness. Use when
|
|
5
|
+
Codex must check build/test gates, generated manifests, project index sync,
|
|
6
|
+
dist/source contract, changelog/release notes, npm package contents, or
|
|
7
|
+
pre-tag risk before shipping.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Deploy Check
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Deploy check is the verifier side of release work. It confirms the artifact a
|
|
15
|
+
user receives matches the source, docs, manifests, and stated capability.
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
1. Confirm the intended capability and release scope.
|
|
20
|
+
2. Inspect branch status and generated artifact drift.
|
|
21
|
+
3. Run the deterministic gates.
|
|
22
|
+
4. Check docs/man-page coverage for shipped behavior.
|
|
23
|
+
5. Check package contents and `dist/` policy.
|
|
24
|
+
6. Report risk before any tag or publish step.
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm run build
|
|
30
|
+
npm test
|
|
31
|
+
npm run gen:manifests -- --check
|
|
32
|
+
npm run index:check
|
|
33
|
+
npm run version:sync
|
|
34
|
+
npm run release:check
|
|
35
|
+
git diff --check
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For package inspection:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm pack --dry-run
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Red Lines
|
|
45
|
+
|
|
46
|
+
- Do not tag without test evidence.
|
|
47
|
+
- Do not write reviewer verdict files by hand.
|
|
48
|
+
- Do not silently skip `dist/` drift if the package still ships `dist/`.
|
|
49
|
+
- Do not publish undocumented behavior.
|
|
50
|
+
- Do not call a release ready if generated manifests or project index drift.
|
|
51
|
+
|
|
52
|
+
## Output Rules
|
|
53
|
+
|
|
54
|
+
Return a ship/no-ship verdict, gate results, artifact risks, and the next
|
|
55
|
+
operator action.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-qa
|
|
3
|
+
description: >-
|
|
4
|
+
Evaluate Cool Workflow architecture, product design, operator UX,
|
|
5
|
+
context-pack, workflow-app, MCP/CLI, or release-process proposals. Use when
|
|
6
|
+
Codex must decide whether a design respects FreeBSD/POLA,
|
|
7
|
+
mechanism-not-policy, stable JSON surfaces, evidence, and verifier boundaries
|
|
8
|
+
before implementation.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Design QA
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
Design QA checks whether a proposed capability belongs in the kernel,
|
|
16
|
+
userland, a manifest, a wrapper, a routine, or an eval before implementation.
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
1. State the user capability in one sentence.
|
|
21
|
+
2. Identify the contract surface: CLI, MCP, `.cw/` state, file layout, docs,
|
|
22
|
+
package contents, or external wrapper.
|
|
23
|
+
3. Separate mechanism from policy. Move policy into data, apps, wrappers, env,
|
|
24
|
+
or docs.
|
|
25
|
+
4. Check POLA: existing outputs, flags, exit codes, and file layouts stay
|
|
26
|
+
byte-identical unless a new opt-in surface is used.
|
|
27
|
+
5. Define verifier evidence: tests, manifests, screenshots for UI, replay, or
|
|
28
|
+
logs.
|
|
29
|
+
6. Decide whether the work needs a new eval case or skill update.
|
|
30
|
+
|
|
31
|
+
## Checks
|
|
32
|
+
|
|
33
|
+
- Does it preserve stdout-as-data?
|
|
34
|
+
- Does it fail closed instead of guessing?
|
|
35
|
+
- Does it avoid vendor-specific parsing in `src/`?
|
|
36
|
+
- Does it keep generated files verifiable?
|
|
37
|
+
- Does it have a man page or docs contract?
|
|
38
|
+
- Can maker and verifier run in separate worktrees?
|
|
39
|
+
|
|
40
|
+
## Output Rules
|
|
41
|
+
|
|
42
|
+
Return:
|
|
43
|
+
|
|
44
|
+
1. Verdict: acceptable, revise, or reject.
|
|
45
|
+
2. Required contract shape.
|
|
46
|
+
3. Verification plan.
|
|
47
|
+
4. Risks and non-goals.
|
|
48
|
+
|
|
49
|
+
Do not turn design QA into implementation unless the user asks to proceed.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review
|
|
3
|
+
description: >-
|
|
4
|
+
Review Cool Workflow pull requests or branch diffs. Use when Codex must
|
|
5
|
+
inspect code changes for bugs, regressions, FreeBSD/POLA violations, missing
|
|
6
|
+
tests, generated artifact drift, release-contract risk, or CI implications,
|
|
7
|
+
and return findings first with file/line citations.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PR Review
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Review for correctness and release risk before style. Findings lead; summaries
|
|
15
|
+
are secondary. Treat missing tests and POLA drift as real risks.
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
1. Read the diff and identify touched contracts: CLI, MCP, `.cw/` state, docs,
|
|
20
|
+
dist, manifests, tests, release flow, or public package files.
|
|
21
|
+
2. Inspect the surrounding code for behavioral expectations.
|
|
22
|
+
3. Check whether tests exercise the changed behavior and fail closed.
|
|
23
|
+
4. Look for stdout chatter, silent fallback, hidden policy in core, untracked
|
|
24
|
+
generated drift, and accidental public-output changes.
|
|
25
|
+
5. Report findings first, ordered by severity, with file and line references.
|
|
26
|
+
6. Include open questions only when they block confidence.
|
|
27
|
+
|
|
28
|
+
## Review Rules
|
|
29
|
+
|
|
30
|
+
- Do not request cosmetic rewrites unless they hide a bug.
|
|
31
|
+
- Do not approve undocumented shipped behavior.
|
|
32
|
+
- Do not accept type-only additions without runtime behavior.
|
|
33
|
+
- Do not accept `dist/` edits without matching `src/` changes.
|
|
34
|
+
- For UI work, require screenshots or browser verification.
|
|
35
|
+
|
|
36
|
+
## Output Shape
|
|
37
|
+
|
|
38
|
+
Use this order:
|
|
39
|
+
|
|
40
|
+
1. Findings
|
|
41
|
+
2. Open questions
|
|
42
|
+
3. Test gaps
|
|
43
|
+
4. Short summary
|
|
44
|
+
|
|
45
|
+
If there are no findings, say so clearly and name residual risk.
|