workflow-supervisor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +266 -0
  3. package/adapters/claude-code/adapter.json +7 -0
  4. package/adapters/codex/adapter.json +8 -0
  5. package/adapters/hermesagent/adapter.json +8 -0
  6. package/adapters/opencode/adapter.json +8 -0
  7. package/assets/workflow-supervisor-hero.png +0 -0
  8. package/bin/workflow-skills +2 -0
  9. package/bin/workflow-skills.mjs +452 -0
  10. package/docs/artifacts.md +40 -0
  11. package/docs/cli.md +119 -0
  12. package/docs/compatibility.md +85 -0
  13. package/docs/skill-reference.md +33 -0
  14. package/docs/troubleshooting.md +38 -0
  15. package/package.json +45 -0
  16. package/skills/acceptance-matrix/SKILL.md +77 -0
  17. package/skills/acceptance-matrix/agents/openai.yaml +7 -0
  18. package/skills/dossier-builder/SKILL.md +93 -0
  19. package/skills/dossier-builder/agents/openai.yaml +7 -0
  20. package/skills/loop-policy/SKILL.md +103 -0
  21. package/skills/loop-policy/agents/openai.yaml +7 -0
  22. package/skills/source-corpus/SKILL.md +92 -0
  23. package/skills/source-corpus/agents/openai.yaml +7 -0
  24. package/skills/work-unit/SKILL.md +72 -0
  25. package/skills/work-unit/agents/openai.yaml +7 -0
  26. package/skills/worker-roles/SKILL.md +115 -0
  27. package/skills/worker-roles/agents/openai.yaml +7 -0
  28. package/skills/workflow-docs/SKILL.md +88 -0
  29. package/skills/workflow-docs/agents/openai.yaml +7 -0
  30. package/skills/workflow-docs/references/documentation-production.md +230 -0
  31. package/skills/workflow-docs/references/goal-resume.md +62 -0
  32. package/skills/workflow-docs/references/templates.md +53 -0
  33. package/skills/workflow-docs/references/workflow-control.md +276 -0
  34. package/skills/workflow-supervisor/SKILL.md +254 -0
  35. package/skills/workflow-supervisor/agents/openai.yaml +7 -0
@@ -0,0 +1,452 @@
1
+ #!/usr/bin/env node
2
+ import crypto from "node:crypto";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const packageRoot = path.resolve(__dirname, "..");
10
+ const PACKAGE_NAME = "workflow-supervisor";
11
+ const PACKAGE_VERSION = "0.1.0";
12
+ const INSTALLABLE_AGENTS = ["codex", "claude-code", "opencode", "hermesagent"];
13
+ const AGENTS = new Set([...INSTALLABLE_AGENTS, "generic"]);
14
+
15
+ function usage() {
16
+ return `workflow-supervisor
17
+
18
+ Usage:
19
+ workflow-supervisor list [--root <path>]
20
+ workflow-supervisor validate [--root <path>]
21
+ workflow-supervisor doctor [--agent <agent|all>] [--scope user|project] [--project <path>] [--target <path>]
22
+ workflow-supervisor install --agent <agent|all> [--scope user|project] [--project <path>] [--target <path>] [--skills all|a,b] [--force] [--dry-run]
23
+ workflow-supervisor uninstall --agent <agent|all> [--scope user|project] [--project <path>] [--target <path>] [--skills all|a,b] [--dry-run]
24
+ workflow-supervisor emit-context --agent <agent> [--scope user|project] [--project <path>] [--target <path>] [--skills all|a,b] [--out <path>] [--root <path>]
25
+
26
+ Agents:
27
+ codex, claude-code, opencode, hermesagent, generic, all
28
+
29
+ Alias:
30
+ workflow-skills
31
+
32
+ Examples:
33
+ npx workflow-supervisor install --agent codex --scope user
34
+ npx workflow-supervisor install --agent all --scope project --project .
35
+ npx workflow-supervisor install --agent generic --target ./agent-skills
36
+ npx workflow-supervisor emit-context --agent opencode --skills workflow-supervisor,workflow-docs --out AGENTS.md
37
+ `;
38
+ }
39
+
40
+ function parseArgs(argv) {
41
+ const result = { _: [] };
42
+ const booleans = new Set(["force", "dry-run", "help"]);
43
+ for (let i = 0; i < argv.length; i += 1) {
44
+ const arg = argv[i];
45
+ if (!arg.startsWith("--")) {
46
+ result._.push(arg);
47
+ continue;
48
+ }
49
+ const key = arg.slice(2);
50
+ if (booleans.has(key)) {
51
+ result[key] = true;
52
+ continue;
53
+ }
54
+ const next = argv[i + 1];
55
+ if (!next || next.startsWith("--")) throw new Error(`Missing value for --${key}`);
56
+ result[key] = next;
57
+ i += 1;
58
+ }
59
+ return result;
60
+ }
61
+
62
+ function expandHome(input) {
63
+ if (!input) return input;
64
+ if (input === "~") return os.homedir();
65
+ if (input.startsWith("~/")) return path.join(os.homedir(), input.slice(2));
66
+ return input;
67
+ }
68
+
69
+ function skillsRoot(root = packageRoot) {
70
+ return path.join(root, "skills");
71
+ }
72
+
73
+ function listSkills(root = packageRoot) {
74
+ const rootDir = skillsRoot(root);
75
+ if (!fs.existsSync(rootDir)) throw new Error(`Missing skills directory: ${rootDir}`);
76
+ return fs
77
+ .readdirSync(rootDir, { withFileTypes: true })
78
+ .filter((entry) => entry.isDirectory())
79
+ .map((entry) => entry.name)
80
+ .sort();
81
+ }
82
+
83
+ function normalizeScope(scope = "user") {
84
+ if (scope !== "user" && scope !== "project") throw new Error("--scope must be user or project");
85
+ return scope;
86
+ }
87
+
88
+ function defaultTarget(agent, { scope = "user", project = process.cwd() } = {}) {
89
+ const home = os.homedir();
90
+ const resolvedScope = normalizeScope(scope);
91
+ const projectRoot = path.resolve(expandHome(project));
92
+ switch (agent) {
93
+ case "codex":
94
+ return resolvedScope === "project"
95
+ ? path.join(projectRoot, ".agents", "skills")
96
+ : path.join(home, ".agents", "skills");
97
+ case "claude-code":
98
+ return resolvedScope === "project"
99
+ ? path.join(projectRoot, ".claude", "skills")
100
+ : path.join(process.env.CLAUDE_HOME || path.join(home, ".claude"), "skills");
101
+ case "opencode":
102
+ return resolvedScope === "project"
103
+ ? path.join(projectRoot, ".opencode", "skills")
104
+ : path.join(process.env.OPENCODE_HOME || path.join(home, ".config", "opencode"), "skills");
105
+ case "hermesagent":
106
+ return resolvedScope === "project"
107
+ ? path.join(projectRoot, ".hermes", "skills")
108
+ : path.join(process.env.HERMESAGENT_HOME || process.env.HERMES_HOME || path.join(home, ".hermes"), "skills");
109
+ case "generic":
110
+ return null;
111
+ default:
112
+ throw new Error(`Unknown agent: ${agent}`);
113
+ }
114
+ }
115
+
116
+ function readText(file) {
117
+ return fs.readFileSync(file, "utf8");
118
+ }
119
+
120
+ function parseFrontmatter(text) {
121
+ if (!text.startsWith("---\n")) return null;
122
+ const end = text.indexOf("\n---\n", 4);
123
+ if (end === -1) return null;
124
+ const raw = text.slice(4, end).trim().split(/\r?\n/);
125
+ const parsed = {};
126
+ for (const line of raw) {
127
+ const idx = line.indexOf(":");
128
+ if (idx === -1) return null;
129
+ parsed[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
130
+ }
131
+ return parsed;
132
+ }
133
+
134
+ function validateSkill(root, name) {
135
+ const skillDir = path.join(skillsRoot(root), name);
136
+ const skillFile = path.join(skillDir, "SKILL.md");
137
+ const errors = [];
138
+ if (!fs.existsSync(skillFile)) return ["missing SKILL.md"];
139
+
140
+ const text = readText(skillFile);
141
+ const frontmatter = parseFrontmatter(text);
142
+ if (!frontmatter) {
143
+ errors.push("invalid frontmatter");
144
+ } else {
145
+ const keys = Object.keys(frontmatter).sort();
146
+ if (keys.join(",") !== "description,name") errors.push("frontmatter must contain only name and description");
147
+ if (frontmatter.name !== name) errors.push(`frontmatter name ${frontmatter.name || "<missing>"} does not match folder ${name}`);
148
+ if (!frontmatter.description || frontmatter.description.length < 80) errors.push("description is missing or too short");
149
+ }
150
+
151
+ if (/\[TODO|TODO:|Structuring This Skill|Not every skill requires/.test(text)) errors.push("contains scaffold/TODO text");
152
+
153
+ const agentFile = path.join(skillDir, "agents", "openai.yaml");
154
+ if (fs.existsSync(agentFile)) {
155
+ const agentYaml = readText(agentFile);
156
+ if (!agentYaml.includes(`Use $${name}`)) errors.push("agents/openai.yaml default prompt must mention skill name");
157
+ if (!agentYaml.includes("allow_implicit_invocation: false")) errors.push("skills must be opt-in by default");
158
+ }
159
+ return errors;
160
+ }
161
+
162
+ function validate(root = packageRoot) {
163
+ const names = listSkills(root);
164
+ const allErrors = [];
165
+ for (const name of names) {
166
+ for (const error of validateSkill(root, name)) allErrors.push(`${name}: ${error}`);
167
+ }
168
+ if (names.length === 0) allErrors.push("no skills found");
169
+ if (allErrors.length > 0) throw new Error(`Validation failed:\n${allErrors.map((e) => `- ${e}`).join("\n")}`);
170
+ return names;
171
+ }
172
+
173
+ function selectSkills(root, raw) {
174
+ const names = listSkills(root);
175
+ if (!raw || raw === "all") return names;
176
+ const requested = raw.split(",").map((item) => item.trim()).filter(Boolean);
177
+ for (const name of requested) {
178
+ if (!names.includes(name)) throw new Error(`Unknown skill ${name}. Available: ${names.join(", ")}`);
179
+ }
180
+ return requested;
181
+ }
182
+
183
+ function walkFiles(dir) {
184
+ if (!fs.existsSync(dir)) return [];
185
+ const files = [];
186
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
187
+ const full = path.join(dir, entry.name);
188
+ if (entry.isDirectory()) files.push(...walkFiles(full));
189
+ if (entry.isFile()) files.push(full);
190
+ }
191
+ return files.sort();
192
+ }
193
+
194
+ function hashDir(dir) {
195
+ const hash = crypto.createHash("sha256");
196
+ for (const file of walkFiles(dir)) {
197
+ hash.update(path.relative(dir, file));
198
+ hash.update("\0");
199
+ hash.update(fs.readFileSync(file));
200
+ hash.update("\0");
201
+ }
202
+ return hash.digest("hex");
203
+ }
204
+
205
+ const SKILL_SUMMARIES = {
206
+ "workflow-supervisor": "coordinate open-ended agent loops and bind Codex goals when appropriate",
207
+ "source-corpus": "rank and reconcile sources when source authority affects safe next action",
208
+ "work-unit": "decompose broad objectives into bounded units",
209
+ "dossier-builder": "create a handoff contract for one already-bounded work unit",
210
+ "worker-roles": "separate implementer, verifier, repair, documentation, reviewer, and solo-mode responsibilities",
211
+ "acceptance-matrix": "create formal evidence-mapped acceptance criteria",
212
+ "loop-policy": "define retries, parallel safety, approval gates, and goal binding policy",
213
+ "workflow-docs": "create durable workflow-state or documentation-production artifacts",
214
+ };
215
+
216
+ function skillSummary(name) {
217
+ return SKILL_SUMMARIES[name] || "use the bundled SKILL.md instructions";
218
+ }
219
+
220
+ function markdownResourceFiles(skillDir) {
221
+ const referencesDir = path.join(skillDir, "references");
222
+ return walkFiles(referencesDir).filter((file) => file.endsWith(".md"));
223
+ }
224
+
225
+ function copyDir(src, dest, { force = false, dryRun = false } = {}) {
226
+ if (fs.existsSync(dest)) {
227
+ if (!force) throw new Error(`Destination exists: ${dest}. Use --force to overwrite.`);
228
+ if (!dryRun) fs.rmSync(dest, { recursive: true, force: true });
229
+ }
230
+ if (dryRun) return;
231
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
232
+ fs.cpSync(src, dest, { recursive: true });
233
+ }
234
+
235
+ function resolveAgents(raw = "generic") {
236
+ if (raw === "all") return INSTALLABLE_AGENTS;
237
+ if (!AGENTS.has(raw)) throw new Error(`Unsupported agent: ${raw}`);
238
+ return [raw];
239
+ }
240
+
241
+ function resolveTarget(args, agent) {
242
+ const scope = normalizeScope(args.scope || "user");
243
+ if (args.target) return path.resolve(expandHome(args.target));
244
+ const target = defaultTarget(agent, { scope, project: args.project || process.cwd() });
245
+ if (!target) throw new Error(`--target is required for --agent ${agent} with --scope ${scope}`);
246
+ return target;
247
+ }
248
+
249
+ function contextFor(agent, target, names = listSkills(packageRoot)) {
250
+ const title = agent === "generic" ? "Workflow Skill Pack" : `Workflow Skill Pack for ${agent}`;
251
+ const skillLines = names.map((name) => `- \`$${name}\`: ${skillSummary(name)}.`);
252
+ return `# ${title}
253
+
254
+ Installed skills:
255
+
256
+ \`${target || "<custom skill directory>"}\`
257
+
258
+ Use these skills explicitly for supervised, long-running, or handoff-heavy workflows:
259
+
260
+ ${skillLines.join("\n")}
261
+
262
+ Do not use this pack for tiny direct tasks, ordinary README edits, one-off tests, or routine review unless a supervised workflow or durable handoff is explicitly needed.
263
+ `;
264
+ }
265
+
266
+ function portableContextFor(root, agent, target, names) {
267
+ const title = agent === "generic" ? "Workflow Skill Pack Portable Context" : `Workflow Skill Pack Portable Context for ${agent}`;
268
+ const sections = [
269
+ `# ${title}`,
270
+ "",
271
+ "This file embeds the selected Workflow Supervisor skills for agents that cannot discover `SKILL.md` folders directly.",
272
+ "",
273
+ "Use these skills explicitly for supervised, long-running, or handoff-heavy workflows. Loading or reading a skill does not by itself create a new thread, subagent, goal, commit, PR, publication, or other side effect; those actions require the governing environment tools and the gates described in the relevant skill.",
274
+ "",
275
+ `Expected skill directory: \`${target || "<custom skill directory>"}\``,
276
+ "",
277
+ "## Included Skills",
278
+ "",
279
+ ...names.map((name) => `- \`$${name}\`: ${skillSummary(name)}.`),
280
+ "",
281
+ "Do not use this pack for tiny direct tasks, ordinary README edits, one-off tests, or routine review unless a supervised workflow or durable handoff is explicitly needed.",
282
+ "",
283
+ ];
284
+
285
+ for (const name of names) {
286
+ const skillDir = path.join(skillsRoot(root), name);
287
+ const skillFile = path.join(skillDir, "SKILL.md");
288
+ sections.push(`## Skill: $${name}`, "");
289
+ sections.push(`Source: \`skills/${name}/SKILL.md\``, "");
290
+ sections.push(readText(skillFile).trim(), "");
291
+
292
+ for (const resourceFile of markdownResourceFiles(skillDir)) {
293
+ const relative = path.relative(skillDir, resourceFile);
294
+ sections.push(`### Bundled Reference: $${name}/${relative}`, "");
295
+ sections.push(readText(resourceFile).trim(), "");
296
+ }
297
+ }
298
+
299
+ return `${sections.join("\n")}\n`;
300
+ }
301
+
302
+ function writeManifest(target, data, dryRun) {
303
+ if (dryRun) return;
304
+ fs.mkdirSync(target, { recursive: true });
305
+ fs.writeFileSync(path.join(target, ".workflow-skills-install.json"), JSON.stringify(data, null, 2) + "\n");
306
+ }
307
+
308
+ function installOne(args, agent) {
309
+ const root = path.resolve(expandHome(args.root || packageRoot));
310
+ const scope = normalizeScope(args.scope || "user");
311
+ const target = resolveTarget(args, agent);
312
+ const names = selectSkills(root, args.skills || "all");
313
+ const dryRun = Boolean(args["dry-run"]);
314
+ const installed = [];
315
+
316
+ for (const name of names) {
317
+ const src = path.join(skillsRoot(root), name);
318
+ const dest = path.join(target, name);
319
+ copyDir(src, dest, { force: Boolean(args.force), dryRun });
320
+ installed.push({ name, checksum: hashDir(src) });
321
+ }
322
+
323
+ if (!dryRun) fs.writeFileSync(path.join(target, "WORKFLOW_SKILL_PACK.md"), contextFor(agent, target, names));
324
+ writeManifest(
325
+ target,
326
+ {
327
+ package: PACKAGE_NAME,
328
+ version: PACKAGE_VERSION,
329
+ agent,
330
+ scope,
331
+ project: scope === "project" ? path.resolve(expandHome(args.project || process.cwd())) : null,
332
+ target,
333
+ installedAt: new Date().toISOString(),
334
+ skills: installed,
335
+ },
336
+ dryRun
337
+ );
338
+
339
+ return { agent, target, skills: names, dryRun };
340
+ }
341
+
342
+ function install(args) {
343
+ validate(path.resolve(expandHome(args.root || packageRoot)));
344
+ return resolveAgents(args.agent || "generic").map((agent) => installOne(args, agent));
345
+ }
346
+
347
+ function uninstallOne(args, agent) {
348
+ const root = path.resolve(expandHome(args.root || packageRoot));
349
+ const target = resolveTarget(args, agent);
350
+ const names = selectSkills(root, args.skills || "all");
351
+ const dryRun = Boolean(args["dry-run"]);
352
+ for (const name of names) {
353
+ if (!dryRun) fs.rmSync(path.join(target, name), { recursive: true, force: true });
354
+ }
355
+ if (!dryRun) {
356
+ fs.rmSync(path.join(target, ".workflow-skills-install.json"), { force: true });
357
+ fs.rmSync(path.join(target, "WORKFLOW_SKILL_PACK.md"), { force: true });
358
+ }
359
+ return { agent, target, skills: names, dryRun };
360
+ }
361
+
362
+ function uninstall(args) {
363
+ return resolveAgents(args.agent || "generic").map((agent) => uninstallOne(args, agent));
364
+ }
365
+
366
+ function emitContext(args) {
367
+ const agent = args.agent || "generic";
368
+ if (!AGENTS.has(agent)) throw new Error(`Unsupported agent: ${agent}`);
369
+ const root = path.resolve(expandHome(args.root || packageRoot));
370
+ validate(root);
371
+ const names = selectSkills(root, args.skills || "all");
372
+ const target = args.target ? path.resolve(expandHome(args.target)) : defaultTarget(agent, { scope: args.scope || "user", project: args.project || process.cwd() });
373
+ const text = portableContextFor(root, agent, target, names);
374
+ if (args.out) {
375
+ const out = path.resolve(expandHome(args.out));
376
+ fs.mkdirSync(path.dirname(out), { recursive: true });
377
+ fs.writeFileSync(out, text);
378
+ return `Wrote ${out}`;
379
+ }
380
+ return text;
381
+ }
382
+
383
+ function doctorOne(args, agent) {
384
+ const target = args.target ? path.resolve(expandHome(args.target)) : defaultTarget(agent, { scope: args.scope || "user", project: args.project || process.cwd() });
385
+ return {
386
+ packageRoot,
387
+ agent,
388
+ scope: args.scope || "user",
389
+ defaultTarget: target,
390
+ skills: validate(packageRoot),
391
+ targetExists: target ? fs.existsSync(target) : false,
392
+ manifestExists: target ? fs.existsSync(path.join(target, ".workflow-skills-install.json")) : false,
393
+ note: target ? "Override with --target if your agent uses a different skill directory." : "Provide --target for installation.",
394
+ };
395
+ }
396
+
397
+ function doctor(args) {
398
+ const agent = args.agent || "generic";
399
+ if (agent === "all") return JSON.stringify(INSTALLABLE_AGENTS.map((item) => doctorOne(args, item)), null, 2);
400
+ if (!AGENTS.has(agent)) throw new Error(`Unsupported agent: ${agent}`);
401
+ return JSON.stringify(doctorOne(args, agent), null, 2);
402
+ }
403
+
404
+ function printInstallResults(results, verb) {
405
+ const pastTense = verb === "remove" ? "Removed" : "Installed";
406
+ for (const result of results) {
407
+ console.log(`${result.dryRun ? `Would ${verb}` : pastTense} ${result.skills.length} skills for ${result.agent} at ${result.target}`);
408
+ }
409
+ }
410
+
411
+ function main() {
412
+ const args = parseArgs(process.argv.slice(2));
413
+ const command = args._[0] || "help";
414
+ if (args.help || command === "help") {
415
+ console.log(usage());
416
+ return;
417
+ }
418
+ if (command === "list") {
419
+ console.log(listSkills(path.resolve(expandHome(args.root || packageRoot))).join("\n"));
420
+ return;
421
+ }
422
+ if (command === "validate") {
423
+ const root = path.resolve(expandHome(args.root || packageRoot));
424
+ const names = validate(root);
425
+ console.log(`Validated ${names.length} skills: ${names.join(", ")}`);
426
+ return;
427
+ }
428
+ if (command === "doctor") {
429
+ console.log(doctor(args));
430
+ return;
431
+ }
432
+ if (command === "install") {
433
+ printInstallResults(install(args), "install");
434
+ return;
435
+ }
436
+ if (command === "uninstall") {
437
+ printInstallResults(uninstall(args), "remove");
438
+ return;
439
+ }
440
+ if (command === "emit-context") {
441
+ console.log(emitContext(args));
442
+ return;
443
+ }
444
+ throw new Error(`Unknown command: ${command}\n\n${usage()}`);
445
+ }
446
+
447
+ try {
448
+ main();
449
+ } catch (error) {
450
+ console.error(error.message);
451
+ process.exit(1);
452
+ }
@@ -0,0 +1,40 @@
1
+ # Workflow And Documentation Artifacts
2
+
3
+ `$workflow-docs` creates only the smallest useful artifact set.
4
+
5
+ Default location: create Markdown workflow artifacts under `<workspace>/.workflow/`. Use another directory only when the user names one, the project already has a clearer workflow-state convention, or the artifact is a final deliverable that belongs elsewhere.
6
+
7
+ ## Workflow Control
8
+
9
+ - `.workflow/WORKFLOW.md`
10
+ - `.workflow/SOURCE-CORPUS.md`
11
+ - `.workflow/WORK-UNITS.md`
12
+ - `.workflow/DOSSIER.md`
13
+ - `.workflow/THREAD-MAP.md`
14
+ - `.workflow/ACCEPTANCE-MATRIX.md`
15
+ - `.workflow/VERIFICATION-REPORT.md`
16
+ - `.workflow/REPAIR-TICKETS.md`
17
+ - `.workflow/DECISIONS.md`
18
+ - `.workflow/HANDOFF.md`
19
+ - `.workflow/OUTCOME.md`
20
+ - `.workflow/GOAL-STATE.md`
21
+
22
+ ## Documentation Production
23
+
24
+ - `.workflow/DOCUMENTATION-BRIEF.md`
25
+ - `.workflow/CONTENT-INVENTORY.md`
26
+ - `.workflow/OUTLINE.md`
27
+ - `.workflow/CONTENT-DRAFT.md`
28
+ - `.workflow/CLAIMS-REGISTER.md`
29
+ - `.workflow/STYLE-GUIDE.md`
30
+ - `.workflow/GLOSSARY.md`
31
+ - `.workflow/ASSET-REGISTER.md`
32
+ - `.workflow/REVIEW-PLAN.md`
33
+ - `.workflow/REVISION-QUEUE.md`
34
+ - `.workflow/PUBLISHING-CHECKLIST.md`
35
+ - `.workflow/PUBLICATION-LOG.md`
36
+ - `.workflow/MAINTENANCE-PLAN.md`
37
+
38
+ ## State Medium
39
+
40
+ Markdown is the default, but state may also be an inline brief, spreadsheet tab, ticket set, design annotation, CRM note, runbook, decision log, slide appendix, whiteboard note, or chat handoff.
package/docs/cli.md ADDED
@@ -0,0 +1,119 @@
1
+ # CLI Reference
2
+
3
+ The package exposes two executables:
4
+
5
+ ```bash
6
+ workflow-supervisor
7
+ workflow-skills
8
+ ```
9
+
10
+ When using `npx`, run:
11
+
12
+ ```bash
13
+ npx workflow-supervisor <command>
14
+ ```
15
+
16
+ ## Commands
17
+
18
+ ### `list`
19
+
20
+ Print skills bundled with the package.
21
+
22
+ ```bash
23
+ workflow-supervisor list
24
+ ```
25
+
26
+ ### `validate`
27
+
28
+ Validate skill folder structure, `SKILL.md` frontmatter, required metadata, and opt-in policy.
29
+
30
+ ```bash
31
+ workflow-supervisor validate
32
+ ```
33
+
34
+ ### `doctor`
35
+
36
+ Print package, target, and skill discovery information.
37
+
38
+ ```bash
39
+ workflow-supervisor doctor --agent codex
40
+ workflow-supervisor doctor --agent generic --target ./agent-skills
41
+ ```
42
+
43
+ ### `install`
44
+
45
+ Install skills into an agent target.
46
+
47
+ ```bash
48
+ workflow-supervisor install --agent codex
49
+ workflow-supervisor install --agent claude-code --target ~/.claude/skills
50
+ workflow-supervisor install --agent opencode --target ~/.config/opencode/skills
51
+ workflow-supervisor install --agent hermesagent --target ~/.hermes/skills
52
+ workflow-supervisor install --agent generic --target ./agent-skills
53
+ workflow-supervisor install --agent all --scope project --project .
54
+ workflow-supervisor uninstall --agent codex --scope user
55
+ ```
56
+
57
+ Options:
58
+
59
+ ```text
60
+ --agent codex|claude-code|opencode|hermesagent|generic|all
61
+ --scope user|project Install to user-level or project-level location where supported.
62
+ --project <path> Project root for project-scope installs.
63
+ --target <path> Override install directory. Required for generic.
64
+ --skills all|a,b Install all skills or a comma-separated subset.
65
+ --force Replace existing installed skill folders.
66
+ --dry-run Validate and print intended action without writing.
67
+ --root <path> Use another package root.
68
+ ```
69
+
70
+ Default targets:
71
+
72
+ | Agent | Scope | Default |
73
+ |---|---|---|
74
+ | Codex | user | `~/.agents/skills` |
75
+ | Codex | project | `<project>/.agents/skills` |
76
+ | Claude Code | user | `${CLAUDE_HOME:-~/.claude}/skills` |
77
+ | Claude Code | project | `<project>/.claude/skills` |
78
+ | OpenCode | user | `${OPENCODE_HOME:-~/.config/opencode}/skills` |
79
+ | OpenCode | project | `<project>/.opencode/skills` |
80
+ | HermesAgent | user | `${HERMESAGENT_HOME:-${HERMES_HOME:-~/.hermes}}/skills` |
81
+ | HermesAgent | project | `<project>/.hermes/skills` |
82
+ | Generic | any | requires `--target` |
83
+
84
+ HermesAgent project scope is a package-local convention for portable installs. Use `--target` if your HermesAgent setup expects another directory.
85
+
86
+ ### `uninstall`
87
+
88
+ Remove installed skill folders and package context files.
89
+
90
+ ```bash
91
+ workflow-supervisor uninstall --agent codex --scope user
92
+ workflow-supervisor uninstall --agent generic --target ./agent-skills
93
+ ```
94
+
95
+ ### `emit-context`
96
+
97
+ Create a portable instruction file for agents that do not natively discover `SKILL.md` folders. The output embeds the selected `SKILL.md` files and bundled Markdown references, so the receiving agent can use the skills without separately reading the skill directory.
98
+
99
+ ```bash
100
+ workflow-supervisor emit-context --agent generic --target ./agent-skills --out AGENTS.md
101
+ workflow-supervisor emit-context --agent opencode --skills workflow-supervisor,workflow-docs --out AGENTS.md
102
+ ```
103
+
104
+ Options:
105
+
106
+ ```text
107
+ --agent codex|claude-code|opencode|hermesagent|generic
108
+ --scope user|project
109
+ --project <path>
110
+ --target <path>
111
+ --skills all|a,b Embed all skills or a comma-separated subset.
112
+ --out <path> Write to a file instead of stdout.
113
+ --root <path> Use another package root.
114
+ ```
115
+
116
+ ## Exit Codes
117
+
118
+ - `0`: command succeeded
119
+ - `1`: validation, install, argument, or filesystem error
@@ -0,0 +1,85 @@
1
+ # Agent Compatibility
2
+
3
+ The pack is built around portable `SKILL.md` folders. Codex consumes those folders directly. Other agents can use the same content as explicit prompt skills, context packs, or project-local instructions.
4
+
5
+ ## Skills, Threads, And Subagents
6
+
7
+ Loading a skill does not spawn a thread or subagent. A skill is instruction context for the current agent until the environment explicitly uses a separate execution tool.
8
+
9
+ `$workflow-supervisor` can plan worker threads or subagents, but they start only after complete intake, the workflow path gate, a concrete dossier, and target-environment delegation support are all satisfied. If those tools are unavailable or user-visible thread creation is not approved, use the generated handoff prompts or workflow docs as the fallback.
10
+
11
+ ## Codex
12
+
13
+ Codex support is native:
14
+
15
+ - each skill has `SKILL.md`
16
+ - each skill has `agents/openai.yaml`
17
+ - all skills opt out of implicit invocation by default
18
+ - `$workflow-supervisor`, `$loop-policy`, and `$workflow-docs` include Codex goal lifecycle rules
19
+
20
+ Install:
21
+
22
+ ```bash
23
+ npx workflow-supervisor install --agent codex --scope user
24
+ npx workflow-supervisor install --agent codex --scope project --project .
25
+ ```
26
+
27
+ Use:
28
+
29
+ ```text
30
+ Use $workflow-supervisor to supervise this migration. It should ask the complete intake before planning or work starts.
31
+ ```
32
+
33
+ ## Claude Code
34
+
35
+ Claude Code environments vary by local setup. Install to the skill or prompt directory your setup uses, or choose a project-local target.
36
+
37
+ ```bash
38
+ npx workflow-supervisor install --agent claude-code --target ~/.claude/skills
39
+ ```
40
+
41
+ If native discovery is unavailable, emit a context file:
42
+
43
+ ```bash
44
+ npx workflow-supervisor emit-context --agent claude-code --target ~/.claude/skills --skills workflow-supervisor,workflow-docs --out CLAUDE.md
45
+ ```
46
+
47
+ Codex goal APIs degrade to `.workflow/GOAL-STATE.md` and workflow docs.
48
+
49
+ ## OpenCode
50
+
51
+ Install to an OpenCode skill/prompt directory or project-local target:
52
+
53
+ ```bash
54
+ npx workflow-supervisor install --agent opencode --target ~/.config/opencode/skills
55
+ npx workflow-supervisor install --agent opencode --scope project --project .
56
+ ```
57
+
58
+ If OpenCode does not read `agents/openai.yaml`, ignore that file and invoke by explicit skill names from `SKILL.md`.
59
+
60
+ ## HermesAgent
61
+
62
+ Install to the HermesAgent skill/prompt directory configured by your environment:
63
+
64
+ ```bash
65
+ npx workflow-supervisor install --agent hermesagent --target ~/.hermes/skills
66
+ npx workflow-supervisor install --agent hermesagent --scope project --project .
67
+ ```
68
+
69
+ User scope follows HermesAgent's documented `~/.hermes/skills` location. Project scope uses the package-local fallback `<project>/.hermes/skills` so `--agent all --scope project` can create a complete portable skill bundle.
70
+
71
+ If native discovery is unavailable:
72
+
73
+ ```bash
74
+ npx workflow-supervisor emit-context --agent hermesagent --target ~/.hermes/skills --skills workflow-supervisor,workflow-docs --out HERMES.md
75
+ ```
76
+
77
+ ## Generic Agent
78
+
79
+ Use `generic` for any agent that can read a directory of Markdown instructions.
80
+
81
+ ```bash
82
+ npx workflow-supervisor install --agent generic --target ./agent-skills
83
+ ```
84
+
85
+ Then point the agent at `./agent-skills/WORKFLOW_SKILL_PACK.md` and the individual `SKILL.md` files.