@maestria/pi 0.5.4 → 0.5.6

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/README.md CHANGED
@@ -51,7 +51,6 @@ pi uninstall @gotgenes/pi-subagents
51
51
  | `/fein <goal>` | Set workflow mode to full pipeline (recon → design → impl → review) |
52
52
  | `/sonar <goal>` | Set workflow mode to research only (recon → design → stop) |
53
53
  | `/blitz <goal>` | Set workflow mode to fast implementation (builder directly) |
54
- | `/orchestrate <goal>` | Start a full pipeline by delegating to the orchestrator |
55
54
  | `/review <target>` | Enter review mode - blocks destructive tools, sets read-only toolset |
56
55
  | `/restore-model` | Restore the original model and tools active before review mode |
57
56
  | `/handoff <goal>` | Generate a structured handoff prompt for a new task context |
@@ -93,17 +93,13 @@ Specific guidance for the downstream specialist.
93
93
  - **!!! Never edit files** - you are read-only reconnaissance
94
94
  - **!!! Never implement solutions** - that's `/builder`'s job
95
95
  - **!!! Never make design decisions** - that's `/architect`'s job
96
- - **Use `opensrc` for investigating external dependencies** - when you need to understand how a library works internally, use the `opensrc` skill to clone and read its source instead of making API calls or web requests
97
- - **External repos: `opensrc` for big repos, `webfetch` for single pages** - For GitHub/GitLab/BitBucket URLs, scoped queries (single file, single page) → `webfetch` is fine. Whole repos or "how is X implemented in library Y" → `opensrc path <owner/repo>` (clones to global cache, gives you a path for `read`/`glob`/`grep`). Don't webfetch a multi-file repo one file at a time - clone once, read locally.
96
+ - **Open external repos with `opensrc` (not `webfetch`)** - clone once with `opensrc path <owner/repo>`, read locally. `webfetch` is for single pages only.
98
97
  - **One role per session** - don't mix exploration with building
99
98
  - If you can't find something after reasonable effort, report what you tried
100
- - Prefer `lsp` tool for code intelligence over grep when possible
101
99
  - Document negative findings too ("no middleware layer found")
102
100
  - Include specific file paths and line numbers in findings
103
101
  - For large codebases, use grep-first strategy to avoid token waste
104
- - **!!! Maker/checker split** - your work is reviewed by `/reviewer` before it lands. The model that wrote the recon is too nice grading its own homework. Produce the report, do not QA it.
105
- - **!!! Validate before handoff** - never present a report that hasn't been cross-checked against the source. Read your own report for completeness before reporting back.
106
- - **!!! If anything is unclear or ambiguous during reconnaissance, document the ambiguity as an explicit `[inferred]` assumption in your report with the evidence that led to your interpretation** - downstream specialists (builder, architect) need to know where your report relies on inference vs. direct observation.
102
+ - **!!! Document ambiguity as explicit `[inferred]` assumptions in your report, with the evidence behind each interpretation** - downstream specialists (builder, architect) need to know where your report relies on inference vs. direct observation.
107
103
  - **Parallelization:** adventurer tasks on different modules/areas can run in parallel. Two adventurers mapping the same module produce overlapping reports. Read-only is safe; duplication is wasteful.
108
104
 
109
105
  ## Handoff
@@ -115,7 +115,6 @@ After the ADR is written, your handoff should cover:
115
115
 
116
116
  - `api-design-principles` (`wshobson/agents`) - load when designing APIs, choosing REST vs GraphQL, or defining endpoint structures
117
117
  - `architecture-decision-framework` (`agustinusnathaniel/skills`) - load when using decision matrices, weighted scoring, or comparing implementation approaches
118
- - `architecture-decision-records` (`wshobson/agents`) - load when documenting an architecture decision as an ADR
119
118
  - `c4-architecture` (`softaworks/agent-toolkit`) - load when output requires a container/component diagram
120
119
  - `codebase-design` (`mattpocock/skills`) - load when designing module boundaries, deciding where seams go, or improving codebase structure
121
120
  - `domain-modeling` (`mattpocock/skills`) - load when building or sharpening the project's domain model and ubiquitous language
@@ -143,12 +142,9 @@ After the ADR is written, your handoff should cover:
143
142
  ## Constraints
144
143
 
145
144
  - **!!! Read the docs first** - before making recommendations, verify API behavior and library capabilities against official documentation. Don't guess at how a tool works.
146
- - Don't assume - verify against official docs and references
147
145
  - Don't oversimplify - acknowledge trade-offs honestly
148
146
  - For irreversible decisions, recommend more conservative options
149
147
  - Tag every assumption in the ADR as `[verified]` or `[inferred]`
150
- - **If the requirements are ambiguous, exhaust available data first, then document your assumption with supporting rationale and proceed** - the ADR should not contain open questions. Every unclear item becomes an explicit assumption with evidence.
151
- - **!!! Maker/checker split** - your work is reviewed by `/reviewer` before it lands. The model that wrote the ADR is too nice grading its own homework. Produce the recommendation, do not QA it.
152
- - **!!! Validate before handoff** - never present an ADR that hasn't been cross-checked against the constraints (reversibility, MVP vs production, expertise match) listed above. Re-read the ADR before reporting back.
148
+ - **The ADR should not contain open questions** - every unclear item becomes an explicit assumption with evidence.
153
149
  - **Parallelization:** architect tasks on different decisions can run in parallel. Two architects on the same decision = wasted effort. ADR is single-writer.
154
- - **External repos: `opensrc` for big repos, `webfetch` for single pages** - For GitHub/GitLab/BitBucket URLs, scoped queries (single file, single page) → `webfetch` is fine. Whole repos or "how is X implemented in library Y" → `opensrc path <owner/repo>` (clones to global cache, gives you a path for `read`/`glob`/`grep`). Don't webfetch a multi-file repo one file at a time - clone once, read locally.
150
+ - **Open external repos with `opensrc` (not `webfetch`)** - clone once, read locally. `webfetch` is for single pages only.
package/agents/builder.md CHANGED
@@ -109,20 +109,18 @@ This reveals what actually requires heavy tools vs. what's simple.
109
109
 
110
110
  ## Rules
111
111
 
112
- - **!!! Touch only files relevant to the task** - no collateral changes
112
+ - **!!! Read the docs first** - consult official documentation before writing code that touches unfamiliar APIs or migration paths. Don't guess at API changes.
113
+ - **!!! Validate before handoff** - never present a change you haven't tested. Run the existing test suite, confirm the diff is focused.
114
+ - **!!! Touch only files relevant to the task** - no collateral changes; if existing code seems unnecessary, flag it in your handoff with your reasoning rather than deleting it
113
115
  - Prefer `edit` over `write` - preserve existing code
114
- - **!!! Run tests before claiming done**
116
+ - **!!! Run tests before claiming done** - run the existing test suite (`npm test*` / `pnpm test*` / `npx tsc*` per the bash allow-list) and confirm the diff is focused
115
117
  - **!!! Never implement without reading the target files first**
116
- - **!!! Read the docs first** - before writing code that uses unfamiliar APIs, tools, or migration paths, consult official documentation. Don't guess at API changes.
117
118
  - If a change grows beyond the original task scope, flag it in your handoff
118
119
  - Keep the change focused - one concern per invocation
119
- - **External repos: `opensrc` for big repos, `webfetch` for single pages** - For GitHub/GitLab/BitBucket URLs, scoped queries (single file, single page) → `webfetch` is fine. Whole repos or "how is X implemented in library Y" → `opensrc path <owner/repo>` (clones to global cache, gives you a path for `read`/`glob`/`grep`). Don't webfetch a multi-file repo one file at a time - clone once, read locally.
120
- - **!!! Maker/checker split** - your work is reviewed by `/reviewer` before it lands. The model that wrote the code is too nice grading its own homework. Apply the fix, do not QA it.
121
- - **!!! Never delete what you didn't create** - adapt, don't remove. If something exists and it seems unnecessary, flag it in your handoff with your reasoning rather than deleting it. Collateral deletions are a trust killer.
122
- - **!!! Validate before handoff** - never present a change you haven't tested. Run `npm test*` / `pnpm test*` / `npx tsc*` per the bash allow-list. Run the existing test suite, confirm the diff is focused.
123
- - **!!! When implementation is ambiguous, don't ask - exhaust data first.** Read the codebase for existing patterns, follow conventions already established, check ADRs for prior decisions, check `.maestria/rules.md` for project constraints. If still ambiguous: make the best decision based on codebase patterns, document the assumption in your handoff, and proceed. The reviewer will validate the assumption.
124
120
  - **Parallelization:** builder tasks on different files can run in parallel. Two builders on the same file = merge conflict. **Never parallelize builder tasks that touch overlapping files.**
125
121
  - **!!! Report at the signature level, not the body level** - when listing changes, mention function signatures and interface fields, not internal implementation. The orchestrator uses this to build a user-facing summary.
122
+ - **Open external repos with `opensrc` (not `webfetch`)** - clone once, read locally. `webfetch` is for single pages only.
123
+ - **!!! When implementation is ambiguous - exhaust data first.** Check codebase patterns, ADRs, `.maestria/rules.md`. If still ambiguous: make the best decision based on conventions, document the assumption, and proceed.
126
124
 
127
125
  ## Iteration Limits
128
126
 
@@ -0,0 +1,8 @@
1
+ <!-- Auto-generated from @maestria/core. Do not edit directly.
2
+ Edit the canonical file at packages/core/agent-directives/ instead. -->
3
+
4
+ [MODE: blitz]
5
+
6
+ ## MODE: blitz (Fast Implementation)
7
+
8
+ Speed mode: skip reconnaissance and design gates. Go directly to /builder for implementation. Only use /adventurer if the codebase context is genuinely unknown (not as a default step). Skip /reviewer unless the user explicitly requests review.
@@ -0,0 +1,8 @@
1
+ <!-- Auto-generated from @maestria/core. Do not edit directly.
2
+ Edit the canonical file at packages/core/agent-directives/ instead. -->
3
+
4
+ [MODE: fein]
5
+
6
+ ## MODE: fein (Full Pipeline)
7
+
8
+ Default role-based pipeline: thinker (recon/design/plan) -> worker (implementation) -> verifier (review). Verifier acceptance terminates the pipeline for that unit of work. Roles and order may adapt to task needs - this is the default, not a fixed requirement. Do NOT skip any phase unless the user explicitly overrides in the same turn.
@@ -0,0 +1,8 @@
1
+ <!-- Auto-generated from @maestria/core. Do not edit directly.
2
+ Edit the canonical file at packages/core/agent-directives/ instead. -->
3
+
4
+ [MODE: sonar]
5
+
6
+ ## MODE: sonar (Research Only)
7
+
8
+ Research mode: reconnaissance and design only. Delegate to /adventurer (recon) followed by /architect or /planner (analysis/design). STOP after delivering findings and design. Do NOT implement, write code, or create any production files.
@@ -82,8 +82,6 @@ Confirm it works:
82
82
  - Check for unintended side effects
83
83
  - Prepare rollback plan
84
84
 
85
- **!!! Always verify before handoff** - Never present broken code.
86
-
87
85
  ## Skill Prescription
88
86
 
89
87
  ### Always load
@@ -95,7 +93,6 @@ Confirm it works:
95
93
  - `agent-browser` (`vercel-labs/agent-browser`) - load when bug involves UI behavior, network requests, performance profiling, or needs visual reproduction (skip if backend-only)
96
94
  - `dependency-updater` (`softaworks/agent-toolkit`) - load when investigating dependency-related bugs, lockfile issues, or version conflicts
97
95
  - `resolving-merge-conflicts` (`mattpocock/skills`) - load when debugging regressions introduced by a merge or rebase
98
- - `diagnosing-bugs` (`mattpocock/skills`) - load when using the diagnose methodology for systematic debugging
99
96
  - `karpathy-guidelines` (`multica-ai/andrej-karpathy-skills`) - load when investigating pattern-level bugs
100
97
  - `logging-best-practices` (`boristane/agent-skills`) - load when bug surfaces in logs or you need to add logging
101
98
  - `opensrc` (`vercel-labs/opensrc`) - load when root cause is in an external library
@@ -126,8 +123,6 @@ Document findings at each step:
126
123
  - Prevention measures
127
124
  - **Assumptions documented** - what was unclear and what you assumed, with the evidence that led to each assumption
128
125
 
129
- **!!! Save your findings as persistent knowledge artifacts** - don't let diagnostic work disappear after the session ends. Create a markdown file or use `/writer` to store the investigation record for future reference.
130
-
131
126
  ## Iteration Limits
132
127
 
133
128
  - **Max 3 fix attempts** (Step 4) before escalating with the audit table.
@@ -138,11 +133,7 @@ Document findings at each step:
138
133
 
139
134
  - **!!! Document your diagnostic work as persistent knowledge artifacts** - save what you investigated, ruled out, root cause, and fix applied. Don't let findings disappear when the session ends. Use `/writer` or a markdown file if no knowledge base exists yet.
140
135
  - **!!! Edit and bash permissions are `ask`** - explain why before any change
141
- - **!!! Always verify before handoff** - Never present broken code
142
- - **!!! Maker/checker split** - your work is reviewed by `/reviewer` before it lands. The model that wrote the fix is too nice grading its own homework. Apply the fix, do not QA it.
143
- - **!!! Validate before handoff** - never present a fix you haven't reproduced-and-verified works. Run the existing test suite, reproduce the original error, confirm it's gone.
144
- - **!!! If anything is unclear or ambiguous, exhaust environment data (lockfile, env vars, version mismatch, CWD), document your assumption with supporting evidence, and proceed** - wrong assumptions waste more time than asking questions. Document assumptions, not questions.
136
+ - **!!! Never present a fix you haven't reproduced-and-verified** - run the existing test suite, reproduce the original error, confirm it's gone.
137
+ - **!!! Exhaust environment data before concluding** - lockfile, env vars, version mismatches, CWD. If the error description or reproduction is vague, attempt reproduction with available information and document what you assumed about environment or inputs.
145
138
  - **Parallelization:** diagnose tasks on different bugs can run in parallel. Two diagnoses on the same bug = wasted; same root-cause cluster = consolidate first.
146
- - **External repos: `opensrc` for big repos, `webfetch` for single pages** - For GitHub/GitLab/BitBucket URLs, scoped queries (single file, single page) → `webfetch` is fine. Whole repos or "how is X implemented in library Y" → `opensrc path <owner/repo>` (clones to global cache, gives you a path for `read`/`glob`/`grep`). Don't webfetch a multi-file repo one file at a time - clone once, read locally.
147
-
148
- **If the error description is vague or the reproduction is unclear, attempt to reproduce with available information, document what you assumed about the environment or inputs, and proceed.** The reviewer will validate whether the assumptions were reasonable.
139
+ - **Open external repos with `opensrc` (not `webfetch`)** - clone once, read locally. `webfetch` is for single pages only.
package/agents/planner.md CHANGED
@@ -35,14 +35,11 @@ After the plan is written, your handoff should cover:
35
35
  ## Rules
36
36
 
37
37
  - One plan per complex feature - never bundle unrelated work
38
- - **!!! Each phase must have verifiable completion criteria**
38
+ - **!!! Each phase must have verifiable completion criteria** - success criteria and rollback points are the termination condition for every phase
39
39
  - Mark dependencies between phases explicitly
40
40
  - Include rollback points between phases
41
- - Verify plan completeness before claiming done
42
41
  - Define guard rails: what to do and what not to do
43
- - **!!! Maker/checker split** - your work is reviewed by `/reviewer` before it lands. The model that wrote the plan is too nice grading its own homework. Produce the plan, do not QA it.
44
- - **!!! Validate before handoff** - never present a plan where each phase lacks success criteria or rollback points. Re-read the plan structure before reporting back.
45
- - **!!! If anything is unclear or ambiguous, document your assumption explicitly in the plan with supporting rationale and proceed** - the plan should not contain open questions. Every open question is a blocked phase; convert it to an assumption with the evidence that led to it.
42
+ - **!!! The plan should not contain open questions** - every open question is a blocked phase; convert it to an assumption with the evidence that led to it.
46
43
  - **Parallelization:** planner tasks on different features can run in parallel. Two planners on the same feature = wasted effort. Plan is single-writer.
47
44
 
48
45
  ## Iteration Limits
@@ -97,4 +94,3 @@ After the plan is written, your handoff should cover:
97
94
  - Don't add new dependencies without approval
98
95
  - Don't refactor existing code while adding features
99
96
  - Don't skip verification steps
100
- - **If requirements are ambiguous, exhaust available data, document your assumption, and proceed** - the plan should not contain open questions. Convert ambiguity to documented assumptions.
@@ -90,7 +90,7 @@ You review code for quality.
90
90
 
91
91
  1. Is this specific code change related to the overall intended goal of this PR or intended changes?
92
92
  2. Do I have any struggles understanding these changes? Will this code be maintainable in the future?
93
- 3. Can I observe this working by running it? What command, API request, or browser interaction produces visible proof of correctness? (Observation is more reliable than reasoning - if you can watch it work, you don't need to trust the rationale.)
93
+ 3. Can I observe this working by running it? What command, API request, or browser interaction produces visible proof of correctness?
94
94
 
95
95
  ## Iteration Limits
96
96
 
@@ -130,10 +130,10 @@ For orchestrator-side swarm rules (exclusive lenses, model switching, triage pip
130
130
  - If no issues, say so explicitly and state what you verified
131
131
  - Flag if the scope exceeds the stated intent (scope creep)
132
132
  - **!!! If the review scope or criteria are unclear, document your scope assumption (based on diff context and reviewer mandate) and proceed. Do not refuse to review.**
133
- - **!!! Validate before handoff** - never present a review where the verdict doesn't match the issues (e.g., "approved" with critical issues). Re-read your own verdict before reporting back.
134
- - **!!! Don't delete what you didn't create** - flag deletions of unrelated code in the diff. Builder is supposed to make focused changes; collateral deletions are a trust killer.
133
+ - **!!! Verdict consistency** - never present a review where the verdict doesn't match the issues (e.g., "approved" with critical issues). Re-read your own verdict before reporting back.
134
+ - **!!! Flag deletions of unrelated code in the diff** - builder is supposed to make focused changes; collateral deletions are a trust killer.
135
135
  - **Parallelization:** reviewer tasks on different PRs/changes can run in parallel. Two reviewers on the same PR = wasted effort. **Sequential after the builder.**
136
- - **External repos: `opensrc` for big repos, `webfetch` for single pages** - For GitHub/GitLab/BitBucket URLs, scoped queries (single file, single page) → `webfetch` is fine. Whole repos or "how is X implemented in library Y" → `opensrc path <owner/repo>` (clones to global cache, gives you a path for `read`/`glob`/`grep`). Don't webfetch a multi-file repo one file at a time - clone once, read locally.
136
+ - **Open external repos with `opensrc` (not `webfetch`)** - clone once, read locally. `webfetch` is for single pages only.
137
137
 
138
138
  ## Output Format
139
139
 
package/agents/writer.md CHANGED
@@ -119,13 +119,7 @@ You write documentation.
119
119
 
120
120
  ## Check
121
121
 
122
- - **!!! Proofread before finishing**
123
- - Verify links work
124
- - Check that examples are accurate
125
- - Ensure examples are runnable (not pseudocode)
126
- - Test code examples if possible
122
+ - **!!! Proofread before finishing** - verify links work, examples are accurate and runnable (not pseudocode), tone matches the surrounding style. Test code examples if possible.
123
+ - **Keep documentation changes focused** - flag deletions of unrelated sections in your own diff.
127
124
  - **!!! If the documentation purpose or audience is unclear, flag it in your output and ask before proceeding** - wrong assumptions waste more time than asking questions.
128
- - **!!! Maker/checker split** - your work is reviewed by `/reviewer` before it lands. The model that wrote the doc is too nice grading its own homework. Produce the doc, do not QA it.
129
- - **!!! Validate before handoff** - never present a doc you haven't proofread. Verify links work, examples are runnable (not pseudocode), tone matches the surrounding style. Re-read the doc before reporting back.
130
- - **!!! Don't delete what you didn't create** - flag deletions of unrelated sections in your own diff. Documentation changes should be focused; collateral deletions are a trust killer.
131
125
  - **Parallelization:** writer tasks on different documents can run in parallel. Two writers on the same doc = wasted effort. Doc is single-writer.
@@ -1,17 +1,15 @@
1
- import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import{dirname as i,join as a}from"node:path";import{fileURLToPath as o}from"node:url";import{homedir as s}from"node:os";import{Type as c}from"typebox";import{SUBAGENT_EVENTS as l}from"@gotgenes/pi-subagents";import{isToolCallEventType as u}from"@earendil-works/pi-coding-agent";function d(){return{mode:null,activeTask:``,completionPromise:``,specialistsDelegated:[],blockers:[],filesModified:[],filesRead:[],handoffHistory:[],reviewMode:!1,originalModel:null,originalTools:null,subagentStatus:{},reviewModel:null}}function f(e,t,n,r){let i=[{from:t,to:n,task:r,timestamp:Date.now()},...e.handoffHistory].slice(0,5);return{...e,handoffHistory:i}}function p(e){return{state:{...e,reviewMode:!1,originalModel:null,originalTools:null},originalModel:e.originalModel,originalTools:e.originalTools}}async function m(e,t,n){let{state:r,originalModel:i,originalTools:a}=p(n);if(a&&a.length>0&&e.setActiveTools(a),i)try{let n=t.modelRegistry.getAll().find(e=>e.id===i);n&&await e.setModel(n)}catch{}Object.assign(n,r)}function h(e,t){e.appendEntry(`maestria_state`,{...t})}async function g(e,t,n){let r=n.reviewModel;if(!r)return null;try{let n=t.modelRegistry.getAll().find(e=>e.id===r);return n?(await e.setModel(n),r):(t.ui.notify(`Review model "${r}" not found in registry, staying on current.`),null)}catch{return t.ui.notify(`Could not switch to review model "${r}", staying on current.`),null}}function _(e){let t=[];if(e.mode&&t.push(`**Mode:** ${e.mode.toUpperCase()}`),e.reviewModel&&t.push(`**Review Model:** ${e.reviewModel}`),e.activeTask&&t.push(`**Goal:** ${e.activeTask}`),e.completionPromise&&t.push(`**Completion Promise:** ${e.completionPromise}`),e.specialistsDelegated.length>0&&t.push(`**Specialists Delegated:** ${e.specialistsDelegated.join(`, `)}`),e.blockers.length>0){t.push(`**Blockers:**`);for(let n of e.blockers)t.push(`- ${n}`)}let n=[];if(e.filesModified.length>0&&n.push(`**Modified:** ${e.filesModified.join(`, `)}`),e.filesRead.length>0&&n.push(`**Read:** ${e.filesRead.join(`, `)}`),n.length>0&&t.push(`**Files:** ${n.join(`; `)}`),e.handoffHistory.length>0){t.push(`**Recent Handoffs:**`);for(let n of e.handoffHistory)t.push(`- ${n.from} → ${n.to}: ${n.task}`)}return t.join(`
1
+ import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import{dirname as i,join as a,resolve as o}from"node:path";import{fileURLToPath as s}from"node:url";import{homedir as c}from"node:os";import{Type as l}from"typebox";import{SUBAGENT_EVENTS as u}from"@gotgenes/pi-subagents";import{isToolCallEventType as d}from"@earendil-works/pi-coding-agent";function f(){return{mode:null,activeTask:``,completionPromise:``,specialistsDelegated:[],blockers:[],filesModified:[],filesRead:[],handoffHistory:[],reviewMode:!1,originalModel:null,originalTools:null,subagentStatus:{},reviewModel:null}}function p(e,t,n,r){let i=[{from:t,to:n,task:r,timestamp:Date.now()},...e.handoffHistory].slice(0,5);return{...e,handoffHistory:i}}function m(e){return{state:{...e,reviewMode:!1,originalModel:null,originalTools:null},originalModel:e.originalModel,originalTools:e.originalTools}}async function h(e,t,n){let{state:r,originalModel:i,originalTools:a}=m(n);if(a&&a.length>0&&e.setActiveTools(a),i)try{let n=t.modelRegistry.getAll().find(e=>e.id===i);n&&await e.setModel(n)}catch{}Object.assign(n,r)}function g(e,t){e.appendEntry(`maestria_state`,{...t})}async function _(e,t,n){let r=n.reviewModel;if(!r)return null;try{let n=t.modelRegistry.getAll().find(e=>e.id===r);return n?(await e.setModel(n),r):(t.ui.notify(`Review model "${r}" not found in registry, staying on current.`),null)}catch{return t.ui.notify(`Could not switch to review model "${r}", staying on current.`),null}}function v(e){let t=[];if(e.mode&&t.push(`**Mode:** ${e.mode.toUpperCase()}`),e.reviewModel&&t.push(`**Review Model:** ${e.reviewModel}`),e.activeTask&&t.push(`**Goal:** ${e.activeTask}`),e.completionPromise&&t.push(`**Completion Promise:** ${e.completionPromise}`),e.specialistsDelegated.length>0&&t.push(`**Specialists Delegated:** ${e.specialistsDelegated.join(`, `)}`),e.blockers.length>0){t.push(`**Blockers:**`);for(let n of e.blockers)t.push(`- ${n}`)}let n=[];if(e.filesModified.length>0&&n.push(`**Modified:** ${e.filesModified.join(`, `)}`),e.filesRead.length>0&&n.push(`**Read:** ${e.filesRead.join(`, `)}`),n.length>0&&t.push(`**Files:** ${n.join(`; `)}`),e.handoffHistory.length>0){t.push(`**Recent Handoffs:**`);for(let n of e.handoffHistory)t.push(`- ${n.from} → ${n.to}: ${n.task}`)}return t.join(`
2
2
 
3
- `)}const v=a(i(o(import.meta.url)),`..`,`agents`),y=a(s(),`.pi`,`agent`,`agents`),b=[`adventurer`,`architect`,`builder`,`diagnose`,`planner`,`reviewer`,`writer`];function x(i){let o=v;if(!e(o)){console.warn(`[maestria] Agents source directory not found:`,o);return}try{t(y,{recursive:!0})}catch{console.warn(`[maestria] Could not create agents directory:`,y);return}let s=0;for(let t of b){let i=a(o,`${t}.md`),c=a(y,`${t}.md`);if(!e(i)){console.warn(`[maestria] Agent source not found: ${t}.md`);continue}if(!e(c))try{r(c,n(i,`utf-8`),`utf-8`),s++}catch(e){console.warn(`[maestria] Failed to deploy agent ${t}:`,e)}}s>0&&console.log(`[maestria] Deployed ${s} specialist agents to ${y}`)}const S=[`fein`,`sonar`,`blitz`],C={fein:[`## MODE: fein (Full Pipeline)`,``,`Execute the complete fein pipeline: mandatory reconnaissance`,`(/adventurer) → design/plan (/architect or /planner) →`,`implementation (/builder) → review (/reviewer).`,`Do NOT skip any phase unless the user explicitly overrides`,`in the same turn.`].join(`
4
- `),sonar:[`## MODE: sonar (Research Only)`,``,`Execute research only: /adventurer (recon) →`,`/architect or /planner (design/plan) → STOP.`,`Do NOT implement anything. Return findings.`].join(`
5
- `),blitz:[`## MODE: blitz (Fast Implementation)`,``,`Execute fast implementation via /builder directly.`,`Skip reconnaissance and design unless the codebase`,`is genuinely unknown. Skip review unless the result`,`needs validation.`].join(`
6
- `)},w={fein:`[MODE: fein]`,sonar:`[MODE: sonar]`,blitz:`[MODE: blitz]`};function T(e){return`${w[e]}\n\n${C[e]}`}function E(e,t){for(let n of S)e.registerCommand(n,{description:`Set workflow mode to ${n}`,handler:async(r,i)=>{if(t.reviewMode&&await m(e,i,t),t.mode=n,h(e,t),r.trim()){let t=[T(n),``,`Run the maestria default pipeline on: ${r}`].join(`
7
- `);e.sendUserMessage(t,{deliverAs:`steer`})}else i.ui.notify(`Mode set to ${n}. Describe what you'd like to work on.`)}})}function D(e){return(t,n)=>{if(e.mode)return{systemPrompt:[t.systemPrompt,``,T(e.mode),``,`The user has set workflow mode to "${e.mode}". Honor this mode throughout the session until changed via /command.`].join(`
8
- `)}}}function O(e,t){e.on(`session_before_compact`,e=>({compaction:{summary:_(t),details:{...t},firstKeptEntryId:e.preparation.firstKeptEntryId,tokensBefore:e.preparation.tokensBefore}})),e.on(`session_before_tree`,e=>{if(e.preparation.userWantsSummary)return{summary:{summary:_(t)}}})}const k={REVIEW_ACTIVATED:`maestria:review:activated`,REVIEW_DEACTIVATED:`maestria:review:deactivated`,SUBAGENT_STARTED:`maestria:subagent:started`,SUBAGENT_COMPLETED:`maestria:subagent:completed`,SUBAGENT_FAILED:`maestria:subagent:failed`},A=[`adventurer`,`architect`,`builder`,`diagnose`,`planner`,`reviewer`,`writer`],j=new Set([`completed`,`steered`,`aborted`,`stopped`,`error`]);function M(e,t,n){if(e.registerTool({name:`maestria_subagent`,label:`Maestria Subagent`,description:`Dispatch a task to a @maestria specialist subagent`,promptSnippet:`Delegate tasks to @maestria specialist subagents (adventurer, architect, builder, planner, diagnose, reviewer, writer)`,promptGuidelines:[`Use maestria_subagent when a task MUST be delegated to a specialist subagent rather than handled directly. Each specialist has focused capabilities: adventurer (recon), architect (design), builder (impl), planner (planning), diagnose (bugs), reviewer (QA), writer (docs).`],prepareArguments(e){return e},parameters:c.Object({agent:c.Optional(c.String({description:`Specialist agent name`})),task:c.Optional(c.String({description:`Task description for the subagent`})),tasks:c.Optional(c.Array(c.Object({agent:c.String(),task:c.String()}),{description:`Array of task objects for parallel or chain dispatch`})),mode:c.Optional(c.Union([c.Literal(`parallel`),c.Literal(`chain`),c.Literal(`single`)]))}),async execute(n,r,i,a,o){if(t.reviewMode)return{content:[{type:`text`,text:`Subagent dispatch is not available during review mode. Use /restore-model to exit review mode first.`}]};let s=r.mode??`single`;if(s===`single`){if(!A.includes(r.agent))throw Error(`Unknown agent: "${r.agent}". Allowed: ${A.join(`, `)}`);if(!r.task||!r.task.trim())throw Error(`Task description is required`)}else if(s===`parallel`){if(!r.tasks||r.tasks.length<2)throw Error(`For parallel mode, tasks array is required with at least 2 items`);if(r.tasks.length>8)throw Error(`For parallel mode, tasks array may have at most 8 items (got ${r.tasks.length})`);for(let e of r.tasks){if(!A.includes(e.agent))throw Error(`Unknown agent: "${e.agent}". Allowed: ${A.join(`, `)}`);if(!e.task||!e.task.trim())throw Error(`Task description is required for all tasks`)}}else if(s===`chain`){if(!r.tasks||r.tasks.length<2)throw Error(`For chain mode, tasks array is required with at least 2 items`);for(let e of r.tasks){if(!A.includes(e.agent))throw Error(`Unknown agent: "${e.agent}". Allowed: ${A.join(`, `)}`);if(!e.task||!e.task.trim())throw Error(`Task description is required for all tasks`)}}let{getSubagentsService:c}=await import(`@gotgenes/pi-subagents`),l=c();if(!l||typeof l.spawn!=`function`)return{content:[{type:`text`,text:[`## Subagent Dispatch Unavailable`,``,"The `@gotgenes/pi-subagents` extension is required for subagent dispatch but has not been loaded.",``,`Install it as a Pi extension:`,``,"```",`pi install npm:@gotgenes/pi-subagents`,"```",``,`Then restart your Pi session.`].join(`
9
- `)}]};try{async function n(e,t,n){let r=0,o=l.getRecord(e);for(;o&&!j.has(o.status)&&r<120;){if(i?.aborted)throw Error(`Maestria subagent call aborted`);await new Promise(e=>setTimeout(e,500)),o=l.getRecord(e),r++,n&&a?.({content:[{type:`text`,text:`${t} running... (${Math.round(r*500/1e3)}s)`}]})}if(o&&!j.has(o.status))throw Error(`Subagent ${e} timed out after 60000ms`);if(!o)throw Error(`Subagent ${e} was cleaned up before completion`);return o}if(s===`single`){let i=r.agent,a=r.task,o=l.spawn(i,a,{description:a.slice(0,80),foreground:!0,inheritContext:!0}),s=f(t,`orchestrator`,i,a);Object.assign(t,s),e.appendEntry(`maestria_state`,t);let c=await n(o,`Subagent ${i}`,!0);return{content:[{type:`text`,text:c.result??c.error??`No output.`}],details:{subagentId:o}}}if(s===`parallel`){let i=r.tasks;a?.({content:[{type:`text`,text:`Spawning ${i.length} parallel subagents...`}]});let o=[];for(let e of i){let n=l.spawn(e.agent,e.task,{description:e.task.slice(0,80),foreground:!0,inheritContext:!0});o.push(n);let r=f(t,`orchestrator`,e.agent,e.task);Object.assign(t,r)}e.appendEntry(`maestria_state`,t);let s=await Promise.all(o.map((e,t)=>n(e,`${i[t].agent} (${t+1}/${i.length})`,!1)));a?.({content:[{type:`text`,text:`All ${i.length} parallel subagents completed.`}]});let c=[`## Parallel Results (${i.length} tasks)\n`];for(let e=0;e<i.length;e++){let t=i[e],n=s[e],r=n.result??n.error??`No output.`;c.push(`### ${e+1}: ${t.agent}`),c.push(r)}return{content:[{type:`text`,text:c.join(`
3
+ `)}const y=a(i(s(import.meta.url)),`..`,`agents`),b=a(c(),`.pi`,`agent`,`agents`),x=[`adventurer`,`architect`,`builder`,`diagnose`,`planner`,`reviewer`,`writer`];function S(i){let o=y;if(!e(o)){console.warn(`[maestria] Agents source directory not found:`,o);return}try{t(b,{recursive:!0})}catch{console.warn(`[maestria] Could not create agents directory:`,b);return}let s=0;for(let t of x){let i=a(o,`${t}.md`),c=a(b,`${t}.md`);if(!e(i)){console.warn(`[maestria] Agent source not found: ${t}.md`);continue}if(!e(c))try{r(c,n(i,`utf-8`),`utf-8`),s++}catch(e){console.warn(`[maestria] Failed to deploy agent ${t}:`,e)}}s>0&&console.log(`[maestria] Deployed ${s} specialist agents to ${b}`)}const C=o(i(s(import.meta.url)),`../agents/commands`);function w(e){let t=n(o(C,`${e}.md`),`utf-8`),r=t.indexOf(`## MODE:`);return r===-1?t.replace(/\s+$/,``)+`
4
+ `:t.slice(r).replace(/\s+$/,``)+`
5
+ `}const T=[`fein`,`sonar`,`blitz`],E={fein:w(`fein`),sonar:w(`sonar`),blitz:w(`blitz`)},D={fein:`[MODE: fein]`,sonar:`[MODE: sonar]`,blitz:`[MODE: blitz]`};function O(e){return`${D[e]}\n\n${E[e]}`}function k(e,t){for(let n of T)e.registerCommand(n,{description:`Set workflow mode to ${n}`,handler:async(r,i)=>{if(t.reviewMode&&await h(e,i,t),t.mode=n,g(e,t),r.trim()){let t=[O(n),``,`Run the maestria default pipeline on: ${r}`].join(`
6
+ `);e.sendUserMessage(t,{deliverAs:`steer`})}else i.ui.notify(`Mode set to ${n}. Describe what you'd like to work on.`)}})}function A(e){return(t,n)=>{if(e.mode)return{systemPrompt:[t.systemPrompt,``,O(e.mode),``,`The user has set workflow mode to "${e.mode}". Honor this mode throughout the session until changed via /command.`].join(`
7
+ `)}}}function j(e,t){e.on(`session_before_compact`,e=>({compaction:{summary:v(t),details:{...t},firstKeptEntryId:e.preparation.firstKeptEntryId,tokensBefore:e.preparation.tokensBefore}})),e.on(`session_before_tree`,e=>{if(e.preparation.userWantsSummary)return{summary:{summary:v(t)}}})}const M={REVIEW_ACTIVATED:`maestria:review:activated`,REVIEW_DEACTIVATED:`maestria:review:deactivated`,SUBAGENT_STARTED:`maestria:subagent:started`,SUBAGENT_COMPLETED:`maestria:subagent:completed`,SUBAGENT_FAILED:`maestria:subagent:failed`},N=[`adventurer`,`architect`,`builder`,`diagnose`,`planner`,`reviewer`,`writer`],P=new Set([`completed`,`steered`,`aborted`,`stopped`,`error`]);function F(e,t,n){if(e.registerTool({name:`maestria_subagent`,label:`Maestria Subagent`,description:`Dispatch a task to a @maestria specialist subagent`,promptSnippet:`Delegate tasks to @maestria specialist subagents (adventurer, architect, builder, planner, diagnose, reviewer, writer)`,promptGuidelines:[`Use maestria_subagent when a task MUST be delegated to a specialist subagent rather than handled directly. Each specialist has focused capabilities: adventurer (recon), architect (design), builder (impl), planner (planning), diagnose (bugs), reviewer (QA), writer (docs).`],prepareArguments(e){return e},parameters:l.Object({agent:l.Optional(l.String({description:`Specialist agent name`})),task:l.Optional(l.String({description:`Task description for the subagent`})),tasks:l.Optional(l.Array(l.Object({agent:l.String(),task:l.String()}),{description:`Array of task objects for parallel or chain dispatch`})),mode:l.Optional(l.Union([l.Literal(`parallel`),l.Literal(`chain`),l.Literal(`single`)]))}),async execute(n,r,i,a,o){if(t.reviewMode)return{content:[{type:`text`,text:`Subagent dispatch is not available during review mode. Use /restore-model to exit review mode first.`}]};let s=r.mode??`single`;if(s===`single`){if(!N.includes(r.agent))throw Error(`Unknown agent: "${r.agent}". Allowed: ${N.join(`, `)}`);if(!r.task||!r.task.trim())throw Error(`Task description is required`)}else if(s===`parallel`){if(!r.tasks||r.tasks.length<2)throw Error(`For parallel mode, tasks array is required with at least 2 items`);if(r.tasks.length>8)throw Error(`For parallel mode, tasks array may have at most 8 items (got ${r.tasks.length})`);for(let e of r.tasks){if(!N.includes(e.agent))throw Error(`Unknown agent: "${e.agent}". Allowed: ${N.join(`, `)}`);if(!e.task||!e.task.trim())throw Error(`Task description is required for all tasks`)}}else if(s===`chain`){if(!r.tasks||r.tasks.length<2)throw Error(`For chain mode, tasks array is required with at least 2 items`);for(let e of r.tasks){if(!N.includes(e.agent))throw Error(`Unknown agent: "${e.agent}". Allowed: ${N.join(`, `)}`);if(!e.task||!e.task.trim())throw Error(`Task description is required for all tasks`)}}let{getSubagentsService:c}=await import(`@gotgenes/pi-subagents`),l=c();if(!l||typeof l.spawn!=`function`)return{content:[{type:`text`,text:[`## Subagent Dispatch Unavailable`,``,"The `@gotgenes/pi-subagents` extension is required for subagent dispatch but has not been loaded.",``,`Install it as a Pi extension:`,``,"```",`pi install npm:@gotgenes/pi-subagents`,"```",``,`Then restart your Pi session.`].join(`
8
+ `)}]};try{async function n(e,t,n){let r=0,o=l.getRecord(e);for(;o&&!P.has(o.status)&&r<120;){if(i?.aborted)throw Error(`Maestria subagent call aborted`);await new Promise(e=>setTimeout(e,500)),o=l.getRecord(e),r++,n&&a?.({content:[{type:`text`,text:`${t} running... (${Math.round(r*500/1e3)}s)`}]})}if(o&&!P.has(o.status))throw Error(`Subagent ${e} timed out after 60000ms`);if(!o)throw Error(`Subagent ${e} was cleaned up before completion`);return o}if(s===`single`){let i=r.agent,a=r.task,o=l.spawn(i,a,{description:a.slice(0,80),foreground:!0,inheritContext:!0}),s=p(t,`orchestrator`,i,a);Object.assign(t,s),e.appendEntry(`maestria_state`,t);let c=await n(o,`Subagent ${i}`,!0);return{content:[{type:`text`,text:c.result??c.error??`No output.`}],details:{subagentId:o}}}if(s===`parallel`){let i=r.tasks;a?.({content:[{type:`text`,text:`Spawning ${i.length} parallel subagents...`}]});let o=[];for(let e of i){let n=l.spawn(e.agent,e.task,{description:e.task.slice(0,80),foreground:!0,inheritContext:!0});o.push(n);let r=p(t,`orchestrator`,e.agent,e.task);Object.assign(t,r)}e.appendEntry(`maestria_state`,t);let s=await Promise.all(o.map((e,t)=>n(e,`${i[t].agent} (${t+1}/${i.length})`,!1)));a?.({content:[{type:`text`,text:`All ${i.length} parallel subagents completed.`}]});let c=[`## Parallel Results (${i.length} tasks)\n`];for(let e=0;e<i.length;e++){let t=i[e],n=s[e],r=n.result??n.error??`No output.`;c.push(`### ${e+1}: ${t.agent}`),c.push(r)}return{content:[{type:`text`,text:c.join(`
10
9
 
11
- `)}],details:{subagentIds:o}}}if(s===`chain`){let i=r.tasks,o=``;for(let r=0;r<i.length;r++){let s=i[r],c=s.task;r>0&&c.includes(`{previous}`)&&(c=c.replace(/\{previous\}/g,o));let u=l.spawn(s.agent,c,{description:c.slice(0,80),foreground:!0,inheritContext:!0}),d=f(t,`orchestrator`,s.agent,c);Object.assign(t,d),e.appendEntry(`maestria_state`,t),a?.({content:[{type:`text`,text:`Chain step ${r+1}/${i.length}: ${s.agent} running...`}]});let p=await n(u,`Chain step ${r+1}: ${s.agent}`,!0);o=p.result??p.error??`No output.`,r<i.length-1&&a?.({content:[{type:`text`,text:`Chain step ${r+1}/${i.length}: ${s.agent} completed. Moving to next step.`}]})}return{content:[{type:`text`,text:o}],details:{subagentId:`chain-completed`}}}throw Error(`Unknown dispatch mode`)}catch(e){console.warn(`[maestria] Subagent dispatch failed:`,e);let t=r.agent??r.tasks?.[0]?.agent??`unknown`,n=r.task??r.tasks?.map(e=>e.task).join(`; `)??`unknown`;return{content:[{type:`text`,text:[`## Subagent Handoff Required`,``,`**From:** orchestrator`,`**To:** ${t}`,`**Task:** ${n}`,``,`Subagent dispatch failed. Please delegate this work manually.`].join(`
12
- `)}]}}}}),e.events){let r=e.events.on(l.STARTED,n=>{let{id:r,type:i}=n;t.subagentStatus[r]={type:i,status:`running`,startedAt:Date.now()},h(e,t),e.events?.emit(k.SUBAGENT_STARTED,{id:r,type:i,timestamp:Date.now()})}),i=e.events.on(l.COMPLETED,n=>{let{id:r}=n,i=t.subagentStatus[r];i&&(i.status=`completed`,i.completedAt=Date.now()),h(e,t),e.events?.emit(k.SUBAGENT_COMPLETED,{id:r,type:i?.type,timestamp:Date.now()})}),a=e.events.on(l.FAILED,n=>{let{id:r,status:i}=n,a=t.subagentStatus[r];a&&(a.status=i??`error`,a.completedAt=Date.now()),h(e,t),e.events?.emit(k.SUBAGENT_FAILED,{id:r,type:a?.type,timestamp:Date.now()})}),o=e.events.on(l.STEERED,n=>{let{id:r}=n;t.subagentStatus[r]||(t.subagentStatus[r]={type:`unknown`,status:`running`,startedAt:Date.now()}),h(e,t)});n&&n.push(r,i,a,o)}}const N=[`read`,`grep`,`find`,`ls`,`glob`];function P(e,t){e.registerCommand(`orchestrate`,{description:`Start a full pipeline by delegating to the orchestrator`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /orchestrate <goal> - describe what to accomplish`);return}if(t.reviewMode){let n=t.originalModel;await m(e,r,t),h(e,t),e.events?.emit(k.REVIEW_DEACTIVATED,{originalModel:n,source:`orchestrate`,timestamp:Date.now()})}e.sendUserMessage([`[ORCHESTRATE: ${n}]`,``,`Orchestrate the full maestria pipeline to: ${n}`,`Use the orchestrator prompt template for subagent delegation.`].join(`
13
- `),{deliverAs:`steer`})}}),e.registerCommand(`maestria-status`,{description:`Show current maestria session state including handoff history`,handler:async(e,n)=>{let r=_(t);if(!r){n.ui.notify(`No active maestria state to report.`);return}n.ui.setEditorText(r)}}),e.registerCommand(`review`,{description:`Enter review mode. Blocks destructive tools, sets read-only toolset.`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /review <target> - describe what to review`);return}let i=r.model?.id??null,a=e.getActiveTools(),o={...t,reviewMode:!0,originalModel:i,originalTools:a};if(Object.assign(t,o),h(e,t),t.reviewModel){let n=await g(e,r,t);n&&(r.ui.notify(`Review mode: switched to ${n}`),e.events?.emit(k.REVIEW_ACTIVATED,{originalModel:t.originalModel,reviewModel:n,timestamp:Date.now()}))}e.setActiveTools(N),e.sendUserMessage([`[REVIEW: ${n}]`,``,`Review: ${n}. Use the reviewer prompt template.`,`Read only, no edits, report findings.`].join(`
14
- `),{deliverAs:`steer`})}}),e.registerCommand(`restore-model`,{description:`Restore the original model and tools that were active before review mode was entered.`,handler:async(n,r)=>{if(!t.reviewMode){r.ui.notify(`Not in review mode. Nothing to restore.`);return}let i=t.originalModel;await m(e,r,t),h(e,t),r.ui.notify(`Restored original model and tools.`),e.events?.emit(k.REVIEW_DEACTIVATED,{originalModel:i,timestamp:Date.now()})}}),e.registerCommand(`handoff`,{description:`Generate a structured handoff prompt for a new task context`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /handoff <goal> - describe the task context for handoff`);return}let i=n.trim(),a=[`**Goal:** `+i,``,`**Context:**`,`- Mode: `+(t.mode??`none`),`- Active task: `+(t.activeTask||`none`),`- Specialists delegated: `+((t.specialistsDelegated?.length??0)>0?t.specialistsDelegated.join(`, `):`none`),`- Recent handoffs: `+(t.handoffHistory?.length??0)+` entries`,`- Files modified: `+((t.filesModified?.length??0)>0?t.filesModified.join(`, `):`none`),``,`**Requirements:**`,`(fill in specific requirements)`,``,`**Known problems:**`,(t.blockers?.length??0)>0?t.blockers.map(e=>`- `+e).join(`
10
+ `)}],details:{subagentIds:o}}}if(s===`chain`){let i=r.tasks,o=``;for(let r=0;r<i.length;r++){let s=i[r],c=s.task;r>0&&c.includes(`{previous}`)&&(c=c.replace(/\{previous\}/g,o));let u=l.spawn(s.agent,c,{description:c.slice(0,80),foreground:!0,inheritContext:!0}),d=p(t,`orchestrator`,s.agent,c);Object.assign(t,d),e.appendEntry(`maestria_state`,t),a?.({content:[{type:`text`,text:`Chain step ${r+1}/${i.length}: ${s.agent} running...`}]});let f=await n(u,`Chain step ${r+1}: ${s.agent}`,!0);o=f.result??f.error??`No output.`,r<i.length-1&&a?.({content:[{type:`text`,text:`Chain step ${r+1}/${i.length}: ${s.agent} completed. Moving to next step.`}]})}return{content:[{type:`text`,text:o}],details:{subagentId:`chain-completed`}}}throw Error(`Unknown dispatch mode`)}catch(e){console.warn(`[maestria] Subagent dispatch failed:`,e);let t=r.agent??r.tasks?.[0]?.agent??`unknown`,n=r.task??r.tasks?.map(e=>e.task).join(`; `)??`unknown`;return{content:[{type:`text`,text:[`## Subagent Handoff Required`,``,`**From:** orchestrator`,`**To:** ${t}`,`**Task:** ${n}`,``,`Subagent dispatch failed. Please delegate this work manually.`].join(`
11
+ `)}]}}}}),e.events){let r=e.events.on(u.STARTED,n=>{let{id:r,type:i}=n;t.subagentStatus[r]={type:i,status:`running`,startedAt:Date.now()},g(e,t),e.events?.emit(M.SUBAGENT_STARTED,{id:r,type:i,timestamp:Date.now()})}),i=e.events.on(u.COMPLETED,n=>{let{id:r}=n,i=t.subagentStatus[r];i&&(i.status=`completed`,i.completedAt=Date.now()),g(e,t),e.events?.emit(M.SUBAGENT_COMPLETED,{id:r,type:i?.type,timestamp:Date.now()})}),a=e.events.on(u.FAILED,n=>{let{id:r,status:i}=n,a=t.subagentStatus[r];a&&(a.status=i??`error`,a.completedAt=Date.now()),g(e,t),e.events?.emit(M.SUBAGENT_FAILED,{id:r,type:a?.type,timestamp:Date.now()})}),o=e.events.on(u.STEERED,n=>{let{id:r}=n;t.subagentStatus[r]||(t.subagentStatus[r]={type:`unknown`,status:`running`,startedAt:Date.now()}),g(e,t)});n&&n.push(r,i,a,o)}}const I=[`read`,`grep`,`find`,`ls`,`glob`];function L(e,t){e.registerCommand(`maestria-status`,{description:`Show current maestria session state including handoff history`,handler:async(e,n)=>{let r=v(t);if(!r){n.ui.notify(`No active maestria state to report.`);return}n.ui.setEditorText(r)}}),e.registerCommand(`review`,{description:`Enter review mode. Blocks destructive tools, sets read-only toolset.`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /review <target> - describe what to review`);return}let i=r.model?.id??null,a=e.getActiveTools(),o={...t,reviewMode:!0,originalModel:i,originalTools:a};if(Object.assign(t,o),g(e,t),t.reviewModel){let n=await _(e,r,t);n&&(r.ui.notify(`Review mode: switched to ${n}`),e.events?.emit(M.REVIEW_ACTIVATED,{originalModel:t.originalModel,reviewModel:n,timestamp:Date.now()}))}e.setActiveTools(I),e.sendUserMessage([`[REVIEW: ${n}]`,``,`Review: ${n}. Use the reviewer prompt template.`,`Read only, no edits, report findings.`].join(`
12
+ `),{deliverAs:`steer`})}}),e.registerCommand(`restore-model`,{description:`Restore the original model and tools that were active before review mode was entered.`,handler:async(n,r)=>{if(!t.reviewMode){r.ui.notify(`Not in review mode. Nothing to restore.`);return}let i=t.originalModel;await h(e,r,t),g(e,t),r.ui.notify(`Restored original model and tools.`),e.events?.emit(M.REVIEW_DEACTIVATED,{originalModel:i,timestamp:Date.now()})}}),e.registerCommand(`handoff`,{description:`Generate a structured handoff prompt for a new task context`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /handoff <goal> - describe the task context for handoff`);return}let i=n.trim(),a=[`**Goal:** `+i,``,`**Context:**`,`- Mode: `+(t.mode??`none`),`- Active task: `+(t.activeTask||`none`),`- Specialists delegated: `+((t.specialistsDelegated?.length??0)>0?t.specialistsDelegated.join(`, `):`none`),`- Recent handoffs: `+(t.handoffHistory?.length??0)+` entries`,`- Files modified: `+((t.filesModified?.length??0)>0?t.filesModified.join(`, `):`none`),``,`**Requirements:**`,`(fill in specific requirements)`,``,`**Known problems:**`,(t.blockers?.length??0)>0?t.blockers.map(e=>`- `+e).join(`
15
13
  `):`(no known problems documented)`,``,`**Success criteria:**`,`(fill in how to verify completion)`,``,`**Next step:**`,`(fill in what happens after this task)`,``,`---`,`Complete the fields above before sending.`].join(`
16
- `);t.handoffHistory=[{from:`current`,to:`next`,task:i,timestamp:Date.now()},...t.handoffHistory??[]].slice(0,5),h(e,t),e.sendUserMessage(a,{deliverAs:`steer`})}}),e.registerCommand(`review-model`,{description:`Set which model to use when entering review mode`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /review-model <model-id>`);return}let i=n.trim(),a=r.modelRegistry.getAll();if(!a.find(e=>e.id===i)){r.ui.notify(`Unknown model: "${i}". Available: ${a.map(e=>e.id).join(`, `)}`);return}t.reviewModel=i,h(e,t),r.ui.notify(`Review model set to: ${i}`)}})}const F=[/rm\s+-rf\s+\//,/dd\s+if=/,/>\s*\/dev\/sd/,/chmod\s+-R\s+777\s+\//,/mkfs\.\w+/,/:(){ :\|:& };:/,/>\s*\/etc\/(passwd|shadow|sudoers)/,/\beval\b/,/wget\s+-O\s*-\s*\|\s*(bash|sh)/,/curl\s+.*\|\s*(bash|sh)/,/crontab\s+-r/];function I(e,t){e.on(`tool_call`,async(e,n)=>{if(!(!e||!e.toolName)){if(t.reviewMode&&(u(`edit`,e)||u(`write`,e)||u(`bash`,e)))return{block:!0,reason:`Review mode is active. Report findings, do not edit.`};if(u(`bash`,e)){if(!e.input||typeof e.input!=`object`)return;let t=e.input.command;if(t){for(let e of F)if(e.test(t))return n.hasUI&&await n.ui.confirm(`Dangerous Pattern Detected`,`This command matches a dangerous pattern:\n${t}\nProceed?`)?void 0:{block:!0,reason:`Command matches dangerous pattern: ${e}`}}}}})}function L(e){let t=d(),n=[];E(e,t);let r=D(t);e.on(`before_agent_start`,(e,t)=>r(e,t)),e.on(`session_start`,(e,n)=>{if(x(n),!n.sessionManager?.getEntries)return;let r=n.sessionManager.getEntries();for(let e=r.length-1;e>=0;e--){let n=r[e];if(n.type===`custom`&&n.customType===`maestria_state`){let e=n.data;e&&typeof e==`object`&&Object.assign(t,e);break}}}),O(e,t),M(e,t,n),P(e,t),e.on(`session_shutdown`,()=>{for(let e of n)e();n.length=0}),I(e,t)}export{L as default};
14
+ `);t.handoffHistory=[{from:`current`,to:`next`,task:i,timestamp:Date.now()},...t.handoffHistory??[]].slice(0,5),g(e,t),e.sendUserMessage(a,{deliverAs:`steer`})}}),e.registerCommand(`review-model`,{description:`Set which model to use when entering review mode`,handler:async(n,r)=>{if(!n.trim()){r.ui.notify(`Usage: /review-model <model-id>`);return}let i=n.trim(),a=r.modelRegistry.getAll();if(!a.find(e=>e.id===i)){r.ui.notify(`Unknown model: "${i}". Available: ${a.map(e=>e.id).join(`, `)}`);return}t.reviewModel=i,g(e,t),r.ui.notify(`Review model set to: ${i}`)}})}const R=[/rm\s+-rf\s+\//,/dd\s+if=/,/>\s*\/dev\/sd/,/chmod\s+-R\s+777\s+\//,/mkfs\.\w+/,/:(){ :\|:& };:/,/>\s*\/etc\/(passwd|shadow|sudoers)/,/\beval\b/,/wget\s+-O\s*-\s*\|\s*(bash|sh)/,/curl\s+.*\|\s*(bash|sh)/,/crontab\s+-r/];function z(e,t){e.on(`tool_call`,async(e,n)=>{if(!(!e||!e.toolName)){if(t.reviewMode&&(d(`edit`,e)||d(`write`,e)||d(`bash`,e)))return{block:!0,reason:`Review mode is active. Report findings, do not edit.`};if(d(`bash`,e)){if(!e.input||typeof e.input!=`object`)return;let t=e.input.command;if(t){for(let e of R)if(e.test(t))return n.hasUI&&await n.ui.confirm(`Dangerous Pattern Detected`,`This command matches a dangerous pattern:\n${t}\nProceed?`)?void 0:{block:!0,reason:`Command matches dangerous pattern: ${e}`}}}}})}function B(e){let t=f(),n=[];k(e,t);let r=A(t);e.on(`before_agent_start`,(e,t)=>r(e,t)),e.on(`session_start`,(e,n)=>{if(S(n),!n.sessionManager?.getEntries)return;let r=n.sessionManager.getEntries();for(let e=r.length-1;e>=0;e--){let n=r[e];if(n.type===`custom`&&n.customType===`maestria_state`){let e=n.data;e&&typeof e==`object`&&Object.assign(t,e);break}}}),j(e,t),F(e,t,n),L(e,t),e.on(`session_shutdown`,()=>{for(let e of n)e();n.length=0}),z(e,t)}export{B as default};
17
15
  //# sourceMappingURL=extension.mjs.map