@maestrofrontier/frontier 1.4.0 → 1.4.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.
package/.cursorrules ADDED
@@ -0,0 +1,194 @@
1
+ # Maestro -- Orchestration Kernel (Cursor)
2
+
3
+ Discipline layer for AI coding agents. Self-contained copy of the
4
+ Maestro kernel (Cursor does not support file imports); the full
5
+ multi-agent protocol lives in docs/orchestration.md and is read on
6
+ demand. Section numbers S0-S10 are stable identifiers.
7
+
8
+ ---
9
+
10
+ ## 0. Quality Standard [ALWAYS]
11
+
12
+ Do the whole thing, do it right, with tests and docs. Search before
13
+ building; test before shipping. Bar: genuinely done. Applies within
14
+ requested scope.
15
+
16
+ ---
17
+
18
+ ## 1. Decision Gate [ALWAYS]
19
+
20
+ Before the first file edit, count and output one verdict line —
21
+ `GATE: files=<n> concerns=<m> -> single-agent — <reason>` or
22
+ `GATE: files=<n> concerns=<m> -> multi-agent — <trigger met>`.
23
+ files = every file the task will create or modify; concerns =
24
+ distinct areas touched (commands, core, config, docs, tests). No
25
+ edits before the verdict.
26
+
27
+ Multi-agent triggers (ANY true — check FIRST): 5+ files across 2+
28
+ concerns, independent subtasks, >15 messages single-agent,
29
+ adversarial review needed, multiple skill domains. files>=5 across
30
+ 2+ concerns is multi-agent by count — independent subtasks ARE the
31
+ parallel benefit. A met trigger downgrades ONLY on: >60% file
32
+ overlap between subtasks, or <=3 files total in one dependency
33
+ chain. Nothing else.
34
+
35
+ A multi-agent verdict is executed, not noted: immediately engage the
36
+ Planner workflow below — before any specialist work or file edit.
37
+ Read docs/orchestration.md first when it is available; the compact
38
+ protocol below suffices when it is not.
39
+
40
+ Single-agent fallback (no trigger met: <=3 tightly coupled files,
41
+ sequential, no parallel benefit): execute via S7, skip S2-S6.
42
+ Constraints: max 4 specialists per group; review and debate panels
43
+ of 3 (odd, no ties); user override ("single agent" / "parallelize")
44
+ wins regardless; default single-agent when in doubt.
45
+ Frontier-class orchestrators with large context bias single-agent
46
+ harder — only parallelism, context isolation, or adversarial review
47
+ justify multi-agent.
48
+
49
+ ---
50
+
51
+ ## 2-6. Multi-Agent Protocol [MULTI-AGENT]
52
+
53
+ Compact protocol — enough to act on a multi-agent verdict. Full
54
+ version: docs/orchestration.md.
55
+
56
+ - Planner first, as a real subagent where the runtime supports one,
57
+ never simulated inline: subtasks with boundaries, file scopes,
58
+ dependency map, parallel groups (max 4), acceptance criteria.
59
+ Planner recommends single-agent: switch.
60
+ - Specialist manifests: ROLE (procedural workflow, never a bare job
61
+ title), TASK, FILES, OUTPUT, ACCEPT, scoped TOOLS. No conversation
62
+ history or unrelated context — isolation is the advantage. Out of
63
+ scope: report and stop.
64
+ - After each group, cross-talk check: did A modify B's files, change
65
+ B's interfaces, invalidate B's assumptions, or produce B's inputs?
66
+ Route the minimum context.
67
+ - Staff Engineer last: reviews integrated diffs against requirements,
68
+ returns PASS or FAIL (issues + owner + fix). Max 2 cycles, then
69
+ deliver with issues listed.
70
+ - The orchestrator spawns, sequences, routes, and delivers. It never
71
+ plans, codes, or reviews specialist work itself.
72
+
73
+ ---
74
+
75
+ ## 7. Universal Rules [ALWAYS]
76
+
77
+ Both modes. In multi-agent, inject into every specialist.
78
+
79
+ ### 7.0 Before code
80
+
81
+ State load-bearing assumptions when the task is ambiguous; list
82
+ competing interpretations rather than picking one silently; propose
83
+ the simpler alternative when you spot one. Confusion: stop, name
84
+ what is unclear, ask. No sycophancy — push back when warranted.
85
+
86
+ ### 7.1 Phase scope
87
+
88
+ Max 5 files per phase; complete and verify before the next.
89
+ Planning produces plans, not code — flag problems, don't improvise.
90
+
91
+ ### 7.2 Context integrity
92
+
93
+ This doctrine is loaded via .cursorrules at session start: do not
94
+ re-read it from disk. Orient from the files the task names; expand
95
+ only when a dependency forces it — no blanket repo audit before
96
+ editing. Re-read a file before editing if 10+ messages have passed
97
+ since you last read it; after 3 edits to the same file, do a full
98
+ re-read. Files >500 LOC: read in chunks; truncated results: narrow
99
+ scope and retry.
100
+
101
+ ### 7.3 Verification
102
+
103
+ FORBIDDEN from reporting complete until: type-checker pass
104
+ (`npx tsc --noEmit`), linter pass (`npx eslint . --quiet`), tests
105
+ pass if configured, ALL errors fixed. No checker: state explicitly.
106
+ Bug fix or new behavior: write the failing test first; success
107
+ criteria are the exit condition, not a post-hoc check. After 2
108
+ failed attempts: stop, re-read from scratch, change approach.
109
+
110
+ Every completion report carries exactly one status token:
111
+ VERIFIED (relevant checks passed) | PENDING_REVIEW (protected
112
+ surfaces touched — instructions, tests, evals, CI — needs human
113
+ review) | UNVERIFIED (check could not run; name the exact gap) |
114
+ FAIL (checks failed; fix the defect, never weaken the oracle).
115
+ No checker ran -> the token is UNVERIFIED, never VERIFIED — grep or
116
+ read evidence does not upgrade it.
117
+ The final message BEGINS with the status token; no separate wrap-up
118
+ turn after the work is done.
119
+
120
+ ### 7.4 Edit safety
121
+
122
+ Surgical scope: every changed line traces to the request. Match
123
+ existing style even if you'd write it differently. No drive-by
124
+ refactor, formatting, type-hint, or docstring drift; unrelated dead
125
+ code is mentioned, not deleted. Renames: search direct calls, type
126
+ refs, string literals, dynamic imports, re-exports/barrels, and
127
+ tests/mocks/fixtures separately — assume a single search missed
128
+ something. One source of truth. Never delete unverified. Never push
129
+ unless told.
130
+
131
+ ### 7.5 Code quality
132
+
133
+ Senior dev standard: structural fixes within request scope, never
134
+ workarounds. Simple and correct > elaborate. Output >2x the simplest
135
+ solution that meets requirements: rewrite.
136
+
137
+ ### 7.7 Communication
138
+
139
+ Study the code the user points to (working code > English spec).
140
+ "yes" / "do it" / "go": execute immediately, no recap. Terse output;
141
+ structured artifacts over transcript prose.
142
+
143
+ ---
144
+
145
+ ## 8. Compression [ALWAYS]
146
+
147
+ NEVER alter: code, commands, paths, URLs, identifiers, schemas,
148
+ versions, dates, requirements, type signatures, API contracts,
149
+ errors. Cache layout: static doctrine contiguous and first; dynamic
150
+ session state appended after it — never interspersed. Persistent
151
+ files are token cost: structured > prose; audit anything >500 lines.
152
+
153
+ ---
154
+
155
+ ## 9. Model Routing [ALWAYS]
156
+
157
+ Pick the cheapest model that handles the task; when unsure, the
158
+ mid-tier default. Small tier: no edits, single source, low
159
+ reasoning. Mid tier (default): 1-3 file edits, known scope. Large
160
+ tier: 4+ files, novel design, high reversal cost. Frontier tier:
161
+ orchestration, very large audits, long-horizon autonomy. Cap
162
+ subagent response length in every prompt; research agents report in
163
+ under 200-500 words. Cap subagent actions too: a tool-call budget
164
+ in every prompt (~20 calls routine; read-first-write-once; one
165
+ diagnostic read per failure, then the two-attempt rule). Full
166
+ routing table: docs/orchestration.md.
167
+
168
+ ---
169
+
170
+ ## 10. Long-Horizon Operation [ALWAYS]
171
+
172
+ Work spanning sessions, iterations, or scheduled runs:
173
+
174
+ - One durable checkpoint artifact (gitignored) holding phase status,
175
+ findings with sources, decisions with rationale. Read it FIRST on
176
+ every resume; never redo completed phases. The context window is
177
+ not durable — checkpoint + version-control history are the memory.
178
+ - Re-ground every iteration: re-read checkpoint and live files
179
+ before editing; re-state the terminal objective verbatim at every
180
+ resume and pre-compaction checkpoint write.
181
+ - Dual termination declared at checkpoint creation: success
182
+ condition AND max-iteration/time cap. The end condition set at
183
+ start wins over anything encountered mid-run. On completion:
184
+ final report, then stop — no zombie loops.
185
+ - Autonomous runs never block on the user: decide, record why in the
186
+ checkpoint, surface it in the final report.
187
+ - Loops never spawn loops: one orchestrator loop, bounded specialist
188
+ groups inside. Write the pre-compaction checkpoint BEFORE the
189
+ context limit; record per-step completion markers before each
190
+ irreversible action.
191
+ - Harness mutations (instructions, hooks, evals, scorers, runners,
192
+ CI): name the component, targeted failure mode, predicted
193
+ improvement, falsifying check, and rollback path. Report
194
+ PENDING_REVIEW — never count a harness change as green evidence.
package/GEMINI.md ADDED
@@ -0,0 +1,42 @@
1
+ # GEMINI.md — Maestro for Gemini
2
+
3
+ @./AGENTS.md
4
+
5
+ ---
6
+
7
+ ## Gemini Runtime Notes
8
+
9
+ ### Precedence
10
+
11
+ This file takes precedence over `AGENTS.md` when both are present.
12
+ Portable orchestration doctrine is imported above — only
13
+ Gemini-specific behavior belongs here.
14
+
15
+ ### Execution Mapping
16
+
17
+ - **Single-agent mode** — standard Gemini execution, no overhead.
18
+ - **Multi-agent mode** — use Gemini sub-agents for independent parallel
19
+ work when the Decision Gate (Section 1) qualifies the task.
20
+ - Do not assume Claude Code features (hooks, agent teams, per-subagent
21
+ tool restriction) are available. Use only verified Gemini capabilities.
22
+
23
+ ### Instruction Organization
24
+
25
+ - Use `@./path/to/file.md` imports to share instructions without
26
+ duplication.
27
+ - Keep runtime-specific rules in this file; portable rules in
28
+ `AGENTS.md`.
29
+
30
+ ### Verification
31
+
32
+ When Section 7.3 requires type-checking or linting, use the project's
33
+ configured tooling. Do not assume specific CLI tools — check project
34
+ configuration first.
35
+
36
+ ### Long-Horizon Operation (S10 mapping)
37
+
38
+ Gemini CLI has no native scheduler — recurring runs come from external
39
+ schedulers or Gemini Enterprise scheduled agents. Section 10 applies
40
+ unchanged: checkpoint artifact read first on every run, explicit end
41
+ condition, final report on completion. Verify scheduling capabilities
42
+ before assuming them.
package/README.md CHANGED
@@ -25,41 +25,30 @@
25
25
  <sub>13 fixture tasks &middot; 123 valid A/B runs &middot; 11 voids excluded &amp; re-run &middot; 6 hooks, all tested &middot; ~8 KB always-on kernel &middot; 2-line plugin install</sub>
26
26
  </p>
27
27
 
28
- > **⚡ Universal install** paste this to your coding agent (Claude Code, Gemini, Codex / Codex Desktop, Cursor, Cline, Windsurf, …) and it installs the full Maestro your runtime can run orchestration doctrine, the Frontier engine, and on Claude Code the whole plugin:
28
+ > **⚡ Installrun the one line for your tool, inside that tool.** Each installs only that tool's setup (the portable `AGENTS.md` doctrine, that tool's adapter, `docs/orchestration.md`, the Frontier engine, and that tool's `/frontier` command) **append-only; it never overwrites or deletes your files.**
29
+
30
+ **Claude Code / Desktop** — native plugin (enforcement hooks, `/maestro:*` commands, skills, status line, Frontier auto-run):
29
31
 
30
32
  ```text
31
- Install Maestro into this repository — the orchestration doctrine, the Frontier fusion engine,
32
- and, on Claude Code, the full plugin machinery. Source of truth: the repo at
33
- https://github.com/mbanderas/maestro (raw base https://raw.githubusercontent.com/mbanderas/maestro/main/).
34
-
35
- 1. Doctrine — every runtime. Put AGENTS.md in the project root; if one already exists, append
36
- Maestro's content below what is there and never overwrite or delete it. Add my runtime adapter —
37
- CLAUDE.md (Claude Code), GEMINI.md (Gemini), or .cursorrules (Cursor); Codex needs only AGENTS.md.
38
- Merge the adapter into any existing file the same append-only way, and make the adapter — not
39
- AGENTS.md — import @AGENTS.md at the top (Cursor has no imports, so paste the kernel in). Also
40
- fetch docs/orchestration.md into docs/ — the doctrine loads the full S2-S6 multi-agent protocol
41
- from it on demand.
42
-
43
- 2. Machinery.
44
- - Claude Code: run `/plugin marketplace add mbanderas/maestro` then `/plugin install maestro@maestro`.
45
- Those two lines wire the enforcement hooks, /maestro:* commands, skills, status line, and the
46
- Frontier engine with auto-run. That is the entire install — you are done.
47
- - Any other CLI (Codex, Cursor, Gemini, Cline, Windsurf, …): run
48
- `npx github:mbanderas/maestro install --target auto --project .` from the project root — it
49
- fetches the engine, copies the integration files, and verifies the install in one step. Zero
50
- dependencies; works today from GitHub before any npm publish. Once Maestro is published to
51
- npm, `npx @maestrofrontier/frontier install --target auto` is the equivalent shorthand. Confirm with
52
- `maestro frontier status` (or `node bin/maestro.cjs frontier status` if maestro is not yet on
53
- PATH). For a /frontier slash command, the install copies integrations/cursor/commands/frontier.md
54
- to .cursor/commands/ (Cursor) or integrations/codex/prompts/frontier.md to ~/.codex/prompts/
55
- (Codex). The plugin's enforcement hooks, /maestro:* commands, and skills can't load outside Claude
56
- Code, so the doctrine from step 1 is what governs the agent there. Per non-Claude tool add
57
- --scope <tool> (e.g. --scope codex, --scope cursor) so armed state stays per-CLI-global.
58
-
59
- Leave Frontier off (its default) until I arm it — /maestro:frontier on Claude Code, or
60
- `maestro frontier mode fusion --preset opus-gpt` elsewhere.
33
+ /plugin marketplace add mbanderas/maestro
34
+ /plugin install maestro@maestro
61
35
  ```
62
36
 
37
+ **Every other CLI / Desktop app** — run its line in that tool's terminal, or just ask its agent to run it. It auto-targets that tool and installs nothing for the others:
38
+
39
+ | Tool | Install (run inside the tool) |
40
+ |------|-------------------------------|
41
+ | Codex (CLI / Desktop) | `npx github:mbanderas/maestro install --target codex` |
42
+ | Cursor | `npx github:mbanderas/maestro install --target cursor` |
43
+ | Gemini CLI | `npx github:mbanderas/maestro install --target gemini` |
44
+ | Cline | `npx github:mbanderas/maestro install --target cline` |
45
+ | Windsurf / Devin | `npx github:mbanderas/maestro install --target windsurf` |
46
+ | Not sure / auto-detect | `npx github:mbanderas/maestro install --target auto` |
47
+
48
+ Per tool it lays down `AGENTS.md` + that tool's adapter (`CLAUDE.md` / `GEMINI.md` / `.cursorrules`; Codex, Cline, and Windsurf read `AGENTS.md` directly), `docs/orchestration.md`, the zero-dependency Frontier engine, and that tool's `/frontier` command. Confirm with `maestro frontier status` (or `node bin/maestro.cjs frontier status` if `maestro` is not on PATH). Once published, swap `github:mbanderas/maestro` for `@maestrofrontier/frontier`.
49
+
50
+ Frontier stays **off** until you arm it: `/maestro:frontier fusion opus-gpt` (Claude Code) or `maestro frontier mode fusion --preset opus-gpt --scope <tool>` elsewhere (armed state stays per-CLI-global; `--scope codex`/`cursor`/`gemini`/`cline`/`windsurf`).
51
+
63
52
  ---
64
53
 
65
54
  > **Agents:** start with [`docs/agent-map.md`](docs/agent-map.md) for
package/docs/codex.md ADDED
@@ -0,0 +1,88 @@
1
+ # Maestro on Codex
2
+
3
+ Codex reads `AGENTS.md` natively, no adapter file needed. This page
4
+ maps Maestro's concepts onto Codex specifics. All behavior below was
5
+ verified against the official Codex docs
6
+ ([AGENTS.md guide](https://developers.openai.com/codex/guides/agents-md),
7
+ [Automations](https://developers.openai.com/codex/app/automations.md),
8
+ [Subagents](https://developers.openai.com/codex/subagents.md))
9
+ on 2026-06-12.
10
+
11
+ ## AGENTS.md semantics
12
+
13
+ Codex discovers instruction files in this order:
14
+
15
+ 1. **Global:** `~/.codex/AGENTS.override.md` if present, else
16
+ `~/.codex/AGENTS.md`.
17
+ 2. **Project:** walking from the Git root down to the current working
18
+ directory, checking each level for `AGENTS.override.md`, then
19
+ `AGENTS.md`.
20
+
21
+ Files are concatenated root-down with blank lines between them; files
22
+ closer to your current directory appear later in the combined prompt
23
+ and therefore override earlier guidance. Codex skips empty files,
24
+ discovers once per run, and stops adding files once the combined set
25
+ hits `project_doc_max_bytes` (32 KiB by default).
26
+
27
+ Practical consequences for Maestro:
28
+
29
+ - **Placement:** put Maestro's `AGENTS.md` at the repository root. If
30
+ you already have a project `AGENTS.md`, append Maestro's content to
31
+ it (Codex concatenates by directory level, not by file).
32
+ - **Budget:** Maestro's always-on kernel is ~8 KB, a quarter of the
33
+ default 32 KiB cap, leaving room for your project instructions
34
+ (the full S2-S6 protocol lives in `docs/orchestration.md`, read on
35
+ demand). If you layer nested `AGENTS.md` files, watch the cap:
36
+ Codex silently stops adding files beyond it.
37
+ - **Global install:** putting Maestro in `~/.codex/AGENTS.md` applies
38
+ the doctrine to every project; per-repo files then layer on top and
39
+ win where they conflict.
40
+
41
+ ## Multi-agent routing (S2-S6 mapping)
42
+
43
+ Codex supports subagent workflows in the CLI and app, but current Codex
44
+ docs specify that subagents spawn only when the user explicitly asks for
45
+ them. Practical mapping for Maestro:
46
+
47
+ - If the user did **not** explicitly ask for subagents, parallel
48
+ agents, or delegation, emit the counted S1 verdict and continue
49
+ single-agent even when the portable gate would otherwise route to
50
+ S2-S6.
51
+ - If the user explicitly asked for subagents/parallel work and the S1
52
+ gate returns multi-agent, map Maestro's Planner, Specialists, and
53
+ Staff Engineer to Codex subagents. Keep specialist prompts scoped and
54
+ cap parallel groups at 4 as usual.
55
+ - Claude Code agent teams do not transfer to Codex. Codex subagents are
56
+ the only Codex-native mapping for Maestro specialists.
57
+
58
+ ## Long-horizon operation (S10 mapping)
59
+
60
+ Claude Code maps S10 to `/loop`, `/schedule`, and `ScheduleWakeup`.
61
+ The Codex analog is **Automations** (Codex app, automations pane):
62
+ recurring prompts that run in the background on minute-based, daily,
63
+ weekly, or cron schedules.
64
+
65
+ | Maestro S10 concept | Codex mechanism |
66
+ |---|---|
67
+ | Self-paced session loop | **Thread automations**, heartbeat-style recurring wake-up calls attached to the current thread, preserving conversation context |
68
+ | Durable scheduled routine | **Standalone/project automations**, independent runs; findings land in the Triage inbox (auto-archived when there is nothing to report) |
69
+ | Checkpoint artifact | Same convention: one `_<task>.md` in the repo root (gitignore `_*`), read first on every run, holding phase status, findings with sources, decisions with rationale |
70
+ | Scripted/CI iteration | `codex exec "<prompt>"` non-interactive runs |
71
+
72
+ S10 rules apply unchanged: hard caps on iterations, completion criteria
73
+ declared up front, externalized state (the thread is not durable
74
+ memory), and an explicit final report instead of a zombie loop. For
75
+ project-scoped automations note the Codex requirement that the local
76
+ app is running and the project is on disk.
77
+
78
+ ## What does not transfer
79
+
80
+ Codex has no user-hook system equivalent to Claude Code's, so Maestro's
81
+ structural enforcement pack (subagent guard, loop guard, phase-scope
82
+ guard, gate telemetry) does not run on Codex. The prose doctrine in
83
+ `AGENTS.md` is the enforcement surface; S7.3's verification gate relies
84
+ on the model honoring it rather than on a hook.
85
+
86
+ The Maestro context bar also does not apply: Codex CLI ships a native
87
+ context-usage indicator (`/statusline` picker, or `context` in
88
+ `[tui].status_line` in `~/.codex/config.toml`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maestrofrontier/frontier",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Achieve Frontier AI performance in your CLI by fusing the model CLIs you already run. Maestro Frontier is an opt-in, zero-dependency local multi-CLI fusion engine for AI coding agents: fan a prompt across a panel of any 1 to 8 local model CLIs you pick, have a judge model and a synthesizer you choose read the answers into a structured analysis and write one grounded synthesis (default Opus 4.8, override either with --judge/--synth). On a 100-task benchmark every fusion panel outscored its individual member models. Three adapters ship today: Opus 4.8, GPT-5.5, Gemini 3.1 Pro, with Kimi, DeepSeek, GLM, and Qwen to follow. Off, single, and fusion modes switch via /maestro:frontier. Built on Maestro orchestration discipline: decision-gated routing, verified done-claims, surgical scope, and structural enforcement hooks.",
5
5
  "keywords": ["multi-cli-fusion", "fusion-engine", "frontier", "multi-agent", "orchestration", "claude-code", "gemini", "codex", "agents", "hooks", "doctrine"],
6
6
  "license": "MIT",
@@ -27,7 +27,10 @@
27
27
  "scripts/install.cjs",
28
28
  "AGENTS.md",
29
29
  "CLAUDE.md",
30
+ "GEMINI.md",
31
+ ".cursorrules",
30
32
  "docs/orchestration.md",
33
+ "docs/codex.md",
31
34
  "commands/",
32
35
  "integrations/",
33
36
  "hooks/frontier-autorun.cjs",
@@ -49,6 +49,15 @@ const WRAPPER_MAP = {
49
49
  },
50
50
  };
51
51
 
52
+ // Runtime adapter per target. The adapter imports @AGENTS.md (Cursor has no
53
+ // imports, so .cursorrules embeds the kernel). codex/cline/windsurf read
54
+ // AGENTS.md directly and need no adapter.
55
+ const ADAPTER_MAP = {
56
+ claude: 'CLAUDE.md',
57
+ gemini: 'GEMINI.md',
58
+ cursor: '.cursorrules',
59
+ };
60
+
52
61
  // Marker dirs used for auto-detection (scanned inside project root)
53
62
  const AUTO_MARKERS = [
54
63
  { dir: '.cursor', target: 'cursor' },
@@ -177,48 +186,53 @@ function detectTarget(projectRoot) {
177
186
  // ---- install actions ----
178
187
 
179
188
  /**
180
- * Install doctrine (AGENTS.md) into project root. Append-only, idempotent.
181
- * @param {string} projectRoot
182
- * @param {boolean} dryRun
189
+ * Read a file from the package root. Returns string, or null (logs) on error.
190
+ * @param {string} rel
183
191
  * @param {(msg: string) => void} log
184
- * @returns {boolean} true = success (or no-op), false = error
192
+ * @returns {string|null}
185
193
  */
186
- function installDoctrine(projectRoot, dryRun, log) {
187
- const dest = path.join(projectRoot, 'AGENTS.md');
188
- const srcPath = path.join(PKG_ROOT, 'AGENTS.md');
189
-
190
- let srcContent;
194
+ function readPkgFile(rel, log) {
191
195
  try {
192
- srcContent = fs.readFileSync(srcPath, 'utf8');
196
+ return fs.readFileSync(path.join(PKG_ROOT, rel), 'utf8');
193
197
  } catch (err) {
194
- log(`ERROR: cannot read package AGENTS.md: ${err.message}`);
195
- return false;
198
+ log(`ERROR: cannot read package ${rel}: ${err.message}`);
199
+ return null;
196
200
  }
201
+ }
197
202
 
203
+ /**
204
+ * Install a doctrine/adapter markdown file. Append-only, idempotent, never
205
+ * clobbers user content above the maestro block; refuses symlinks.
206
+ * @param {string} dest absolute destination path
207
+ * @param {string} srcContent content to install
208
+ * @param {string} label short name for logs (e.g. "AGENTS.md")
209
+ * @param {boolean} dryRun
210
+ * @param {(msg: string) => void} log
211
+ * @returns {boolean} true = success (or no-op), false = error
212
+ */
213
+ function appendOnlyDoctrine(dest, srcContent, label, dryRun, log) {
198
214
  const block = `\n${SENTINEL}\n${srcContent}\n${SENTINEL_END}\n`;
199
215
 
200
- // Check if dest exists
201
216
  let existsStat;
202
217
  try { existsStat = fs.lstatSync(dest); } catch { existsStat = null; }
203
218
 
204
219
  if (existsStat) {
205
220
  if (existsStat.isSymbolicLink()) {
206
- log(`ERROR: AGENTS.md is a symlink — refusing to write through it: ${dest}`);
221
+ log(`ERROR: ${label} is a symlink — refusing to write through it: ${dest}`);
207
222
  return false;
208
223
  }
209
224
 
210
225
  let existing;
211
226
  try { existing = fs.readFileSync(dest, 'utf8'); } catch (err) {
212
- log(`ERROR: cannot read existing AGENTS.md: ${err.message}`);
227
+ log(`ERROR: cannot read existing ${label}: ${err.message}`);
213
228
  return false;
214
229
  }
215
230
 
216
231
  if (existing.includes(SENTINEL)) {
217
- log(`[doctrine] AGENTS.md already contains sentinel — skipping`);
232
+ log(`[doctrine] ${label} already contains sentinel — skipping`);
218
233
  return true;
219
234
  }
220
235
 
221
- // Append block
222
236
  if (dryRun) {
223
237
  log(`[dry-run] would append maestro doctrine to existing ${dest}`);
224
238
  return true;
@@ -226,14 +240,14 @@ function installDoctrine(projectRoot, dryRun, log) {
226
240
 
227
241
  const res = safeWrite(dest, existing + block);
228
242
  if (!res.ok) {
229
- log(`ERROR: failed to append to AGENTS.md: ${res.reason}`);
243
+ log(`ERROR: failed to append to ${label}: ${res.reason}`);
230
244
  return false;
231
245
  }
232
- log(`[doctrine] appended maestro block to existing AGENTS.md`);
246
+ log(`[doctrine] appended maestro block to existing ${label}`);
233
247
  return true;
234
248
  }
235
249
 
236
- // Absent — write fresh. Wrap in sentinel block so subsequent runs detect it.
250
+ // Absent — write fresh, wrapped in the sentinel so re-runs detect it.
237
251
  if (dryRun) {
238
252
  log(`[dry-run] would create ${dest}`);
239
253
  return true;
@@ -247,13 +261,43 @@ function installDoctrine(projectRoot, dryRun, log) {
247
261
  const freshContent = SENTINEL + '\n' + srcContent + '\n' + SENTINEL_END + '\n';
248
262
  const res = safeWrite(dest, freshContent);
249
263
  if (!res.ok) {
250
- log(`ERROR: failed to write AGENTS.md: ${res.reason}`);
264
+ log(`ERROR: failed to write ${label}: ${res.reason}`);
251
265
  return false;
252
266
  }
253
- log(`[doctrine] wrote AGENTS.md`);
267
+ log(`[doctrine] wrote ${label}`);
254
268
  return true;
255
269
  }
256
270
 
271
+ /**
272
+ * Install the portable doctrine core (AGENTS.md) into the project root.
273
+ * @param {string} projectRoot
274
+ * @param {boolean} dryRun
275
+ * @param {(msg: string) => void} log
276
+ * @returns {boolean}
277
+ */
278
+ function installDoctrine(projectRoot, dryRun, log) {
279
+ const src = readPkgFile('AGENTS.md', log);
280
+ if (src === null) return false;
281
+ return appendOnlyDoctrine(path.join(projectRoot, 'AGENTS.md'), src, 'AGENTS.md', dryRun, log);
282
+ }
283
+
284
+ /**
285
+ * Install the runtime adapter for a target (CLAUDE.md / GEMINI.md /
286
+ * .cursorrules). codex/cline/windsurf read AGENTS.md directly -> no-op.
287
+ * @param {string} target
288
+ * @param {string} projectRoot
289
+ * @param {boolean} dryRun
290
+ * @param {(msg: string) => void} log
291
+ * @returns {boolean}
292
+ */
293
+ function installAdapter(target, projectRoot, dryRun, log) {
294
+ const rel = ADAPTER_MAP[target];
295
+ if (!rel) return true; // no adapter for this target
296
+ const src = readPkgFile(rel, log);
297
+ if (src === null) return false;
298
+ return appendOnlyDoctrine(path.join(projectRoot, rel), src, rel, dryRun, log);
299
+ }
300
+
257
301
  /**
258
302
  * Recursively copy srcDir -> destDir, skipping *.test.cjs files.
259
303
  * @param {string} srcDir
@@ -345,6 +389,26 @@ function installEngine(projectRoot, dryRun, log) {
345
389
  }
346
390
  }
347
391
 
392
+ // docs/orchestration.md — the on-demand S2-S6 multi-agent protocol the
393
+ // kernel references. Maestro-owned reference file; copy (refuse symlinks).
394
+ const srcDocs = path.join(PKG_ROOT, 'docs', 'orchestration.md');
395
+ const destDocs = path.join(projectRoot, 'docs', 'orchestration.md');
396
+ if (dryRun) {
397
+ log(`[dry-run] would write ${destDocs}`);
398
+ } else if (isSymlink(destDocs)) {
399
+ log(`ERROR: docs/orchestration.md is a symlink — refusing: ${destDocs}`);
400
+ ok = false;
401
+ } else {
402
+ try {
403
+ fs.mkdirSync(path.dirname(destDocs), { recursive: true });
404
+ fs.writeFileSync(destDocs, fs.readFileSync(srcDocs));
405
+ log(`[doctrine] copied ${destDocs}`);
406
+ } catch (err) {
407
+ log(`ERROR: failed to copy docs/orchestration.md: ${err.message}`);
408
+ ok = false;
409
+ }
410
+ }
411
+
348
412
  return ok;
349
413
  }
350
414
 
@@ -461,13 +525,14 @@ function run(argv) {
461
525
 
462
526
  let anyError = false;
463
527
 
464
- // 1. Doctrine
528
+ // 1. Doctrine — portable AGENTS.md kernel + this target's runtime adapter.
465
529
  if (!installDoctrine(project, dryRun, log)) anyError = true;
530
+ if (!installAdapter(target, project, dryRun, log)) anyError = true;
466
531
 
467
- // 2. Engine
532
+ // 2. Engine — frontier/ + bin/maestro.cjs + docs/orchestration.md.
468
533
  if (!installEngine(project, dryRun, log)) anyError = true;
469
534
 
470
- // 3. Wrapper (skip if no specific target detected)
535
+ // 3. Wrapper — this target's /frontier command (skip if no target detected).
471
536
  if (target !== 'none') {
472
537
  if (!installWrapper(target, project, userGlobal, dryRun, log)) anyError = true;
473
538
  }