bmad-overlay 0.1.1

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 (73) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/PUBLISH.md +82 -0
  4. package/QUICKSTART.md +69 -0
  5. package/README.md +84 -0
  6. package/agents/orchestrator.md +94 -0
  7. package/config/agent-map.yaml +40 -0
  8. package/customizations/bmm-dev.customize.yaml +25 -0
  9. package/customizations/bmm-pm.customize.yaml +24 -0
  10. package/customizations/bmm-qa.customize.yaml +23 -0
  11. package/install/INSTALL.md +151 -0
  12. package/install/check-package.mjs +21 -0
  13. package/install/install-overlay.mjs +279 -0
  14. package/install/install-overlay.sh +14 -0
  15. package/install/merge-bmad-customizations.mjs +179 -0
  16. package/package.json +32 -0
  17. package/policies/routing-policy.md +60 -0
  18. package/runtime/README.md +112 -0
  19. package/runtime/STAGE_RUNNER.md +53 -0
  20. package/runtime/codex-orchestrator.js +922 -0
  21. package/runtime/codex-stage-runner.js +747 -0
  22. package/skills/README.md +38 -0
  23. package/skills/orchestrator-advance-stage/SKILL.md +55 -0
  24. package/skills/orchestrator-advance-stage/bmad-skill-manifest.yaml +1 -0
  25. package/skills/orchestrator-advance-stage/workflow.md +47 -0
  26. package/skills/orchestrator-block-stage/SKILL.md +44 -0
  27. package/skills/orchestrator-block-stage/bmad-skill-manifest.yaml +1 -0
  28. package/skills/orchestrator-block-stage/workflow.md +44 -0
  29. package/skills/orchestrator-close-run/SKILL.md +59 -0
  30. package/skills/orchestrator-close-run/bmad-skill-manifest.yaml +1 -0
  31. package/skills/orchestrator-close-run/workflow.md +47 -0
  32. package/skills/orchestrator-execute-active-stage/SKILL.md +50 -0
  33. package/skills/orchestrator-execute-active-stage/bmad-skill-manifest.yaml +1 -0
  34. package/skills/orchestrator-execute-active-stage/workflow.md +42 -0
  35. package/skills/orchestrator-launch-council/SKILL.md +53 -0
  36. package/skills/orchestrator-launch-council/bmad-skill-manifest.yaml +1 -0
  37. package/skills/orchestrator-launch-council/workflow.md +43 -0
  38. package/skills/orchestrator-resume-stage/SKILL.md +47 -0
  39. package/skills/orchestrator-resume-stage/bmad-skill-manifest.yaml +1 -0
  40. package/skills/orchestrator-resume-stage/workflow.md +45 -0
  41. package/skills/orchestrator-start-run/SKILL.md +62 -0
  42. package/skills/orchestrator-start-run/bmad-skill-manifest.yaml +1 -0
  43. package/skills/orchestrator-start-run/workflow.md +47 -0
  44. package/templates/CLAUDE.md +51 -0
  45. package/templates/analysis-synthesis.md +25 -0
  46. package/templates/analyst-seat-output.yaml +7 -0
  47. package/templates/architecture-handoff.yaml +8 -0
  48. package/templates/architecture-seat-output.yaml +7 -0
  49. package/templates/architecture-synthesis.md +23 -0
  50. package/templates/current-stage.yaml +26 -0
  51. package/templates/delivery-seat-output.yaml +7 -0
  52. package/templates/delivery-synthesis.md +27 -0
  53. package/templates/docs-index.md +19 -0
  54. package/templates/docs-studio-layout.md +88 -0
  55. package/templates/feature-index.md +21 -0
  56. package/templates/intake-request.yaml +12 -0
  57. package/templates/pm-handoff.yaml +11 -0
  58. package/templates/pm-seat-output.yaml +7 -0
  59. package/templates/pm-synthesis.md +25 -0
  60. package/templates/qa-review-findings.yaml +7 -0
  61. package/templates/qa-review-handoff.yaml +10 -0
  62. package/templates/qa-review-seat-output.yaml +7 -0
  63. package/templates/qa-review-summary.md +21 -0
  64. package/templates/run-manifest.md +46 -0
  65. package/templates/stage-handoff.yaml +8 -0
  66. package/workflows/councils/analyst-council.md +229 -0
  67. package/workflows/councils/architecture-council.md +240 -0
  68. package/workflows/councils/delivery-council.md +379 -0
  69. package/workflows/councils/orchestrator-governance.md +474 -0
  70. package/workflows/councils/pm-council.md +241 -0
  71. package/workflows/councils/qa-review-council.md +241 -0
  72. package/workflows/new-saas.md +51 -0
  73. package/workflows/orchestrated-saas-studio.md +155 -0
@@ -0,0 +1,279 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import process from "process";
6
+ import { execFileSync } from "child_process";
7
+
8
+ const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
9
+ const OVERLAY_ROOT = path.resolve(SCRIPT_DIR, "..");
10
+ const VALID_MODES = new Set(["codex", "claude-code", "bmad", "full"]);
11
+
12
+ main();
13
+
14
+ function main() {
15
+ const args = parseArgs(process.argv.slice(2));
16
+ const mode = args.mode || "full";
17
+ const target = args.target || process.cwd();
18
+ const mergeBmad = args["merge-bmad"] === true || args["merge-bmad"] === "true";
19
+
20
+ if (!VALID_MODES.has(mode)) {
21
+ fail(`Unknown mode '${mode}'. Valid modes: codex, claude-code, bmad, full`);
22
+ }
23
+ if (!fs.existsSync(target) || !fs.statSync(target).isDirectory()) {
24
+ fail(`Target project does not exist: ${target}`);
25
+ }
26
+
27
+ const targetOverlayDir = path.join(target, "overlay");
28
+ copyDir(OVERLAY_ROOT, targetOverlayDir, new Set([".DS_Store", "node_modules"]));
29
+
30
+ ensureDir(path.join(target, "docs"));
31
+ ensureDir(path.join(target, "docs", "features"));
32
+ ensureDir(path.join(target, "docs", "studio", "runs"));
33
+ ensureDir(path.join(target, ".overlay"));
34
+ ensureDir(path.join(target, "scripts"));
35
+
36
+ installDocs(target);
37
+ installRuntimeWrappers(target);
38
+ installMetadata(target, mode);
39
+
40
+ if (mode === "claude-code" || mode === "full") {
41
+ installClaudeFiles(target);
42
+ }
43
+
44
+ if (mode === "codex" || mode === "full") {
45
+ installCodexFiles(target);
46
+ }
47
+
48
+ if (mode === "bmad" || mode === "full") {
49
+ installBmadFiles(target);
50
+ if (mergeBmad) {
51
+ applyBmadMerge(target);
52
+ }
53
+ }
54
+
55
+ printSummary(target, mode, mergeBmad);
56
+ }
57
+
58
+ function parseArgs(argv) {
59
+ const args = {};
60
+ for (let i = 0; i < argv.length; i += 1) {
61
+ const token = argv[i];
62
+ if (!token.startsWith("--")) continue;
63
+ const key = token.slice(2);
64
+ const next = argv[i + 1];
65
+ if (!next || next.startsWith("--")) {
66
+ args[key] = true;
67
+ continue;
68
+ }
69
+ args[key] = next;
70
+ i += 1;
71
+ }
72
+ return args;
73
+ }
74
+
75
+ function installDocs(target) {
76
+ copyIfMissing(
77
+ path.join(OVERLAY_ROOT, "templates", "docs-index.md"),
78
+ path.join(target, "docs", "index.md")
79
+ );
80
+ copyIfMissing(
81
+ path.join(OVERLAY_ROOT, "templates", "feature-index.md"),
82
+ path.join(target, "docs", "features", "_template.index.md")
83
+ );
84
+ }
85
+
86
+ function installClaudeFiles(target) {
87
+ copyIfMissing(
88
+ path.join(OVERLAY_ROOT, "templates", "CLAUDE.md"),
89
+ path.join(target, "CLAUDE.md")
90
+ );
91
+ ensureDir(path.join(target, ".claude"));
92
+ writeText(
93
+ path.join(target, ".claude", "overlay-mode.md"),
94
+ [
95
+ "# Claude Code Overlay Mode",
96
+ "",
97
+ "This project has the BMAD overlay installed for Claude Code.",
98
+ "",
99
+ "Primary runtime entry points:",
100
+ "- `scripts/overlay-run-claude.sh`",
101
+ "- `scripts/overlay-execute-claude.sh`",
102
+ "",
103
+ "Primary state files:",
104
+ "- `docs/studio/current-stage.yaml`",
105
+ "- `docs/studio/run-manifest.md`",
106
+ ].join("\n")
107
+ );
108
+ }
109
+
110
+ function installCodexFiles(target) {
111
+ ensureDir(path.join(target, ".codex"));
112
+ writeText(
113
+ path.join(target, ".codex", "overlay-mode.md"),
114
+ [
115
+ "# Codex Overlay Mode",
116
+ "",
117
+ "This project has the BMAD overlay installed for Codex.",
118
+ "",
119
+ "Primary runtime entry points:",
120
+ "- `scripts/overlay-run-codex.sh`",
121
+ "- `scripts/overlay-execute-codex.sh`",
122
+ "",
123
+ "Primary state files:",
124
+ "- `docs/studio/current-stage.yaml`",
125
+ "- `docs/studio/run-manifest.md`",
126
+ ].join("\n")
127
+ );
128
+ }
129
+
130
+ function installBmadFiles(target) {
131
+ const appliedDir = path.join(target, "overlay-applied");
132
+ ensureDir(appliedDir);
133
+ ensureDir(path.join(appliedDir, "customizations"));
134
+ copyDir(path.join(OVERLAY_ROOT, "customizations"), path.join(appliedDir, "customizations"));
135
+ copyFile(
136
+ path.join(OVERLAY_ROOT, "config", "agent-map.yaml"),
137
+ path.join(appliedDir, "agent-map.yaml")
138
+ );
139
+ writeText(
140
+ path.join(appliedDir, "README.md"),
141
+ [
142
+ "# Overlay Applied",
143
+ "",
144
+ "This folder contains BMAD integration artifacts to merge into the target project.",
145
+ "",
146
+ "Files:",
147
+ "- `customizations/` for `_bmad/_config/agents/*.customize.yaml`",
148
+ "- `agent-map.yaml` for overlay council-to-BMAD role mapping",
149
+ "",
150
+ "Next step:",
151
+ "- merge the customization snippets into `_bmad/_config/agents/`",
152
+ "- rerun `npx bmad-method install` in the target project",
153
+ ].join("\n")
154
+ );
155
+ }
156
+
157
+ function applyBmadMerge(target) {
158
+ const mergeScript = path.join(OVERLAY_ROOT, "install", "merge-bmad-customizations.mjs");
159
+ execFileSync("node", [mergeScript, "--target", target], {
160
+ cwd: OVERLAY_ROOT,
161
+ stdio: "inherit",
162
+ });
163
+ }
164
+
165
+ function installRuntimeWrappers(target) {
166
+ const scripts = {
167
+ "overlay-run-codex.sh": `#!/usr/bin/env bash
168
+ set -euo pipefail
169
+ node overlay/runtime/codex-stage-runner.js run-to-close --studio-dir docs/studio --executor codex-cli --request "\${*:-Create a SaaS project}"`,
170
+ "overlay-run-claude.sh": `#!/usr/bin/env bash
171
+ set -euo pipefail
172
+ node overlay/runtime/codex-stage-runner.js run-to-close --studio-dir docs/studio --executor claude-code --request "\${*:-Create a SaaS project}"`,
173
+ "overlay-run-auto.sh": `#!/usr/bin/env bash
174
+ set -euo pipefail
175
+ node overlay/runtime/codex-stage-runner.js run-to-close --studio-dir docs/studio --executor heuristic --request "\${*:-Create a SaaS project}"`,
176
+ "overlay-execute-codex.sh": `#!/usr/bin/env bash
177
+ set -euo pipefail
178
+ node overlay/runtime/codex-stage-runner.js execute-stage --studio-dir docs/studio --advance --executor codex-cli`,
179
+ "overlay-execute-claude.sh": `#!/usr/bin/env bash
180
+ set -euo pipefail
181
+ node overlay/runtime/codex-stage-runner.js execute-stage --studio-dir docs/studio --advance --executor claude-code`,
182
+ "overlay-status.sh": `#!/usr/bin/env bash
183
+ set -euo pipefail
184
+ node overlay/runtime/codex-orchestrator.js status --studio-dir docs/studio`,
185
+ };
186
+
187
+ for (const [name, content] of Object.entries(scripts)) {
188
+ const scriptPath = path.join(target, "scripts", name);
189
+ writeText(scriptPath, content);
190
+ fs.chmodSync(scriptPath, 0o755);
191
+ }
192
+ }
193
+
194
+ function installMetadata(target, mode) {
195
+ const metadata = {
196
+ installed_at: new Date().toISOString(),
197
+ mode,
198
+ overlay_dir: "overlay",
199
+ runtime_entrypoints: {
200
+ run_codex: "scripts/overlay-run-codex.sh",
201
+ run_claude: "scripts/overlay-run-claude.sh",
202
+ run_auto: "scripts/overlay-run-auto.sh",
203
+ execute_codex: "scripts/overlay-execute-codex.sh",
204
+ execute_claude: "scripts/overlay-execute-claude.sh",
205
+ status: "scripts/overlay-status.sh",
206
+ },
207
+ docs_dir: "docs/studio",
208
+ };
209
+ writeText(path.join(target, ".overlay", "setup.json"), `${JSON.stringify(metadata, null, 2)}\n`);
210
+ }
211
+
212
+ function printSummary(target, mode, mergeBmad) {
213
+ const lines = [
214
+ `Overlay installed in: ${target}`,
215
+ `Mode: ${mode}`,
216
+ "Installed assets:",
217
+ "- overlay/",
218
+ "- docs/index.md and docs/features/_template.index.md when missing",
219
+ "- docs/studio/ runtime directories",
220
+ "- scripts/overlay-*.sh wrappers",
221
+ "- .overlay/setup.json",
222
+ ];
223
+
224
+ if (mode === "claude-code" || mode === "full") {
225
+ lines.push("- CLAUDE.md when missing");
226
+ lines.push("- .claude/overlay-mode.md");
227
+ }
228
+ if (mode === "codex" || mode === "full") {
229
+ lines.push("- .codex/overlay-mode.md");
230
+ }
231
+ if (mode === "bmad" || mode === "full") {
232
+ lines.push("- overlay-applied/customizations/");
233
+ lines.push("- overlay-applied/agent-map.yaml");
234
+ lines.push(mergeBmad
235
+ ? "- BMAD customizations merged into _bmad/_config/agents/"
236
+ : "Next BMAD step: merge snippets into _bmad/_config/agents/ and run `npx bmad-method install`.");
237
+ }
238
+
239
+ console.log(lines.join("\n"));
240
+ }
241
+
242
+ function copyIfMissing(source, target) {
243
+ if (!fs.existsSync(target)) {
244
+ copyFile(source, target);
245
+ }
246
+ }
247
+
248
+ function copyFile(source, target) {
249
+ ensureDir(path.dirname(target));
250
+ fs.copyFileSync(source, target);
251
+ }
252
+
253
+ function copyDir(source, target, exclude = new Set()) {
254
+ ensureDir(target);
255
+ for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
256
+ if (exclude.has(entry.name)) continue;
257
+ const sourcePath = path.join(source, entry.name);
258
+ const targetPath = path.join(target, entry.name);
259
+ if (entry.isDirectory()) {
260
+ copyDir(sourcePath, targetPath, exclude);
261
+ } else {
262
+ copyFile(sourcePath, targetPath);
263
+ }
264
+ }
265
+ }
266
+
267
+ function ensureDir(dir) {
268
+ fs.mkdirSync(dir, { recursive: true });
269
+ }
270
+
271
+ function writeText(file, content) {
272
+ ensureDir(path.dirname(file));
273
+ fs.writeFileSync(file, content, "utf8");
274
+ }
275
+
276
+ function fail(message) {
277
+ console.error(message);
278
+ process.exit(1);
279
+ }
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [ "${1:-}" = "" ]; then
5
+ echo "Usage: $0 /path/to/target-project [mode] [merge-bmad:true|false]"
6
+ exit 1
7
+ fi
8
+
9
+ SOURCE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
10
+ TARGET_DIR="$1"
11
+ MODE="${2:-full}"
12
+ MERGE_BMAD="${3:-false}"
13
+
14
+ node "$SOURCE_DIR/install/install-overlay.mjs" --target "$TARGET_DIR" --mode "$MODE" --merge-bmad "$MERGE_BMAD"
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import process from "process";
6
+
7
+ const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
8
+ const OVERLAY_ROOT = path.resolve(SCRIPT_DIR, "..");
9
+ const SECTION_NAMES = ["critical_actions", "memories", "menu", "prompts"];
10
+ const FILES = ["bmm-pm.customize.yaml", "bmm-dev.customize.yaml", "bmm-qa.customize.yaml"];
11
+
12
+ main();
13
+
14
+ function main() {
15
+ const args = parseArgs(process.argv.slice(2));
16
+ const target = args.target || process.cwd();
17
+ const targetAgentsDir = path.join(target, "_bmad", "_config", "agents");
18
+
19
+ if (!fs.existsSync(targetAgentsDir)) {
20
+ fail(`BMAD agent customization directory not found: ${targetAgentsDir}`);
21
+ }
22
+
23
+ for (const fileName of FILES) {
24
+ const sourcePath = path.join(OVERLAY_ROOT, "customizations", fileName);
25
+ const targetPath = path.join(targetAgentsDir, fileName);
26
+ if (!fs.existsSync(targetPath)) {
27
+ fail(`Target BMAD customization file not found: ${targetPath}`);
28
+ }
29
+
30
+ const sourceSections = parseSections(readText(sourcePath));
31
+ const merged = mergeIntoTarget(readText(targetPath), sourceSections);
32
+ fs.writeFileSync(targetPath, merged, "utf8");
33
+ }
34
+
35
+ console.log(`Merged overlay customizations into: ${targetAgentsDir}`);
36
+ }
37
+
38
+ function parseArgs(argv) {
39
+ const args = {};
40
+ for (let i = 0; i < argv.length; i += 1) {
41
+ const token = argv[i];
42
+ if (!token.startsWith("--")) continue;
43
+ const key = token.slice(2);
44
+ const next = argv[i + 1];
45
+ if (!next || next.startsWith("--")) {
46
+ args[key] = true;
47
+ continue;
48
+ }
49
+ args[key] = next;
50
+ i += 1;
51
+ }
52
+ return args;
53
+ }
54
+
55
+ function parseSections(text) {
56
+ const lines = text.split("\n");
57
+ const result = {};
58
+ let current = null;
59
+
60
+ for (let i = 0; i < lines.length; i += 1) {
61
+ const line = lines[i];
62
+ const sectionMatch = line.match(/^([a-z_]+):\s*(.*)$/);
63
+ if (sectionMatch && SECTION_NAMES.includes(sectionMatch[1])) {
64
+ current = sectionMatch[1];
65
+ result[current] = [];
66
+ continue;
67
+ }
68
+ if (!current) continue;
69
+ if (/^[A-Za-z_]+:/.test(line)) {
70
+ current = null;
71
+ continue;
72
+ }
73
+ if (!line.startsWith(" - ")) {
74
+ continue;
75
+ }
76
+
77
+ const itemLines = [line];
78
+ while (i + 1 < lines.length) {
79
+ const next = lines[i + 1];
80
+ if (/^[A-Za-z_]+:/.test(next) || next.startsWith(" - ")) break;
81
+ if (next.startsWith(" ") || next.trim() === "") {
82
+ itemLines.push(next);
83
+ i += 1;
84
+ continue;
85
+ }
86
+ break;
87
+ }
88
+ result[current].push(itemLines.join("\n").trimEnd());
89
+ }
90
+
91
+ return result;
92
+ }
93
+
94
+ function mergeIntoTarget(targetText, sourceSections) {
95
+ const lines = targetText.split("\n");
96
+ const sectionRanges = findSectionRanges(lines);
97
+
98
+ for (const sectionName of SECTION_NAMES) {
99
+ const additions = sourceSections[sectionName] || [];
100
+ if (additions.length === 0 || !sectionRanges[sectionName]) continue;
101
+
102
+ const { start, end } = sectionRanges[sectionName];
103
+ const blockLines = lines.slice(start, end);
104
+ const existingItems = parseItemsFromBlock(blockLines);
105
+ const seen = new Set(existingItems.map(normalizeItem));
106
+ const uniqueAdditions = additions.filter((item) => !seen.has(normalizeItem(item)));
107
+ if (uniqueAdditions.length === 0) continue;
108
+
109
+ const sectionHeader = lines[start];
110
+ const replacement = buildMergedSection(sectionHeader, existingItems, uniqueAdditions);
111
+ lines.splice(start, end - start, ...replacement);
112
+
113
+ const delta = replacement.length - (end - start);
114
+ for (const key of Object.keys(sectionRanges)) {
115
+ if (sectionRanges[key].start > start) {
116
+ sectionRanges[key].start += delta;
117
+ sectionRanges[key].end += delta;
118
+ } else if (sectionRanges[key].start === start) {
119
+ sectionRanges[key].end = sectionRanges[key].start + replacement.length;
120
+ }
121
+ }
122
+ }
123
+
124
+ return `${lines.join("\n").replace(/\n+$/, "\n")}`;
125
+ }
126
+
127
+ function findSectionRanges(lines) {
128
+ const ranges = {};
129
+ for (let i = 0; i < lines.length; i += 1) {
130
+ const match = lines[i].match(/^([a-z_]+):\s*(.*)$/);
131
+ if (!match || !SECTION_NAMES.includes(match[1])) continue;
132
+ const name = match[1];
133
+ let end = i + 1;
134
+ while (end < lines.length && !/^[A-Za-z_]+:/.test(lines[end])) {
135
+ end += 1;
136
+ }
137
+ ranges[name] = { start: i, end };
138
+ }
139
+ return ranges;
140
+ }
141
+
142
+ function parseItemsFromBlock(blockLines) {
143
+ if (blockLines.length === 0) return [];
144
+ const items = [];
145
+ for (let i = 1; i < blockLines.length; i += 1) {
146
+ const line = blockLines[i];
147
+ if (!line.startsWith(" - ")) continue;
148
+ const itemLines = [line];
149
+ while (i + 1 < blockLines.length) {
150
+ const next = blockLines[i + 1];
151
+ if (next.startsWith(" - ") || /^[A-Za-z_]+:/.test(next)) break;
152
+ itemLines.push(next);
153
+ i += 1;
154
+ }
155
+ items.push(itemLines.join("\n").trimEnd());
156
+ }
157
+ return items;
158
+ }
159
+
160
+ function buildMergedSection(header, existingItems, uniqueAdditions) {
161
+ const mergedItems = [...existingItems, ...uniqueAdditions];
162
+ if (mergedItems.length === 0) {
163
+ return [`${header.replace(/:\s*.*/, ": []")}`];
164
+ }
165
+ return [header.replace(/:\s*.*/, ":"), ...mergedItems];
166
+ }
167
+
168
+ function normalizeItem(item) {
169
+ return item.replace(/\s+$/gm, "").trim();
170
+ }
171
+
172
+ function readText(filePath) {
173
+ return fs.readFileSync(filePath, "utf8");
174
+ }
175
+
176
+ function fail(message) {
177
+ console.error(message);
178
+ process.exit(1);
179
+ }
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "bmad-overlay",
3
+ "version": "0.1.1",
4
+ "description": "Portable BMAD overlay kit for Codex, Claude Code, and BMAD projects",
5
+ "license": "MIT",
6
+ "files": [
7
+ "LICENSE",
8
+ "CHANGELOG.md",
9
+ "README.md",
10
+ "QUICKSTART.md",
11
+ "PUBLISH.md",
12
+ "agents/",
13
+ "config/",
14
+ "customizations/",
15
+ "install/",
16
+ "policies/",
17
+ "runtime/",
18
+ "skills/",
19
+ "templates/",
20
+ "workflows/"
21
+ ],
22
+ "bin": {
23
+ "bmad-overlay": "install/install-overlay.mjs",
24
+ "bmad-overlay-merge-bmad": "install/merge-bmad-customizations.mjs"
25
+ },
26
+ "scripts": {
27
+ "pack:check": "node install/check-package.mjs"
28
+ },
29
+ "engines": {
30
+ "node": ">=20.0.0"
31
+ }
32
+ }
@@ -0,0 +1,60 @@
1
+ # Routing Policy
2
+
3
+ ## Objectif
4
+
5
+ Orienter chaque demande vers le bon niveau de ceremonie.
6
+
7
+ ## Entree
8
+
9
+ La demande doit respecter le contrat:
10
+
11
+ - nom
12
+ - objectif
13
+ - domaine
14
+ - stack envisagee
15
+ - contraintes
16
+ - risques
17
+ - definition minimale de succes
18
+
19
+ ## Modes
20
+
21
+ ### `quick`
22
+
23
+ Choisir `quick` si:
24
+
25
+ - une seule capacite principale
26
+ - stack connue
27
+ - peu d'integration externe
28
+ - pas de contrainte forte de conformite
29
+ - pas de complexite multi-tenant ou billing avance
30
+
31
+ Pipeline:
32
+
33
+ `product-brief -> quick-spec -> quick-flow-solo-dev -> code-review`
34
+
35
+ ### `structured`
36
+
37
+ Choisir `structured` si au moins un point est vrai:
38
+
39
+ - auth complexe
40
+ - billing
41
+ - multi-tenant
42
+ - workflows metier multiples
43
+ - integrateurs externes nombreux
44
+ - exigences de fiabilite ou audit
45
+ - equipe multi-contributeurs
46
+
47
+ Pipeline:
48
+
49
+ `analyst -> pm/prd -> ux -> architect -> create-epics-and-stories -> dev -> qa`
50
+
51
+ ## Rule of escalation
52
+
53
+ Si une demande commence en `quick` mais expose ensuite:
54
+
55
+ - un second domaine produit
56
+ - une dette de cadrage
57
+ - plusieurs inconnues techniques
58
+ - des regressions repetitives
59
+
60
+ alors elle doit basculer en `structured`.
@@ -0,0 +1,112 @@
1
+ # Overlay Runtime
2
+
3
+ This folder contains the first Codex-first runtime controller for the overlay.
4
+
5
+ Companion runner:
6
+
7
+ - `codex-stage-runner.js` executes the active stage from generated task files
8
+ - supports `codex-cli`, `claude-code`, and `heuristic` executors
9
+
10
+ ## Current Scope
11
+
12
+ The runtime controls the file-backed orchestration loop:
13
+
14
+ - `start-run`
15
+ - `launch-council`
16
+ - `advance-stage`
17
+ - `block-stage`
18
+ - `resume-stage`
19
+ - `close-run`
20
+ - `status`
21
+
22
+ It manages:
23
+
24
+ - `current-stage.yaml`
25
+ - `run-manifest.md`
26
+ - run directories under `docs/studio/runs/`
27
+ - council seat output targets
28
+ - council seat and lead task files
29
+ - output templates for seats, synthesis, and handoff
30
+
31
+ It does not yet launch real LLM workers by itself.
32
+ It is the autonomous control plane for the overlay state machine.
33
+
34
+ The intended execution bridge is:
35
+
36
+ - runtime launches a stage
37
+ - runtime writes task files and templates
38
+ - Codex uses `orchestrator-execute-active-stage`
39
+ - runtime advances or blocks based on the produced artifacts
40
+
41
+ ## Command Examples
42
+
43
+ ```bash
44
+ node overlay/runtime/codex-orchestrator.js start-run --request "Create a SaaS website for appointment booking"
45
+ node overlay/runtime/codex-orchestrator.js launch-council
46
+ node overlay/runtime/codex-orchestrator.js status
47
+ node overlay/runtime/codex-orchestrator.js block-stage --reason "Missing synthesis" --missing docs/studio/runs/<run_id>/analysis-synthesis.md
48
+ node overlay/runtime/codex-orchestrator.js resume-stage
49
+ node overlay/runtime/codex-orchestrator.js close-run --reason "QA passed"
50
+ node overlay/runtime/codex-stage-runner.js execute-stage --studio-dir docs/studio-runtime-test --advance
51
+ node overlay/runtime/codex-stage-runner.js run-to-close --studio-dir docs/studio-runtime-test --request "Create a SaaS website"
52
+ ```
53
+
54
+ ## Safer Test Mode
55
+
56
+ To avoid touching the main studio state, use a dedicated studio dir:
57
+
58
+ ```bash
59
+ node overlay/runtime/codex-orchestrator.js start-run --studio-dir docs/studio-runtime-test --request "Create a SaaS website"
60
+ ```
61
+
62
+ ## Recommended Test Order
63
+
64
+ 1. `start-run`
65
+ 2. `launch-council`
66
+ 3. create seat outputs, synthesis, and handoff
67
+ 4. `advance-stage`
68
+ 5. `status`
69
+
70
+ ## Current Validation Status
71
+
72
+ Smoke-tested on `docs/studio-runtime-test/` for:
73
+
74
+ - `start-run`
75
+ - `launch-council`
76
+ - `advance-stage`
77
+ - `block-stage`
78
+ - `resume-stage`
79
+ - `close-run`
80
+
81
+ Multi-stage runtime proof also completed on `docs/studio-runtime-test-4/`:
82
+
83
+ - real `analysis` artifact production
84
+ - real `pm` artifact production
85
+ - runtime advancement up to `architecture`
86
+
87
+ End-to-end runtime proof completed on `docs/studio-runtime-test-5/`:
88
+
89
+ - `analysis`
90
+ - `pm`
91
+ - `architecture`
92
+ - `delivery`
93
+ - `qa-review`
94
+ - `closed`
95
+
96
+ Fully autonomous runner proof completed on `docs/studio-runtime-test-6/`:
97
+
98
+ - one `run-to-close` command
99
+ - full planning pipeline execution
100
+ - clean final `closed` state
101
+
102
+ Executor fallback proof completed on `docs/studio-runtime-test-9/`:
103
+
104
+ - `codex-cli` attempted first
105
+ - single failure disables further `codex-cli` attempts for the run
106
+ - heuristic fallback still closes the pipeline
107
+
108
+ Claude Code fallback proof completed on `docs/studio-runtime-test-10/`:
109
+
110
+ - `claude-code` attempted first
111
+ - single timeout disables further `claude-code` attempts for the run
112
+ - heuristic fallback still closes the pipeline