@maestria/pi 0.5.8 → 0.5.10

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.
@@ -12,178 +12,163 @@ inherit_context: true
12
12
  <!-- Auto-generated from @maestria/core. Do not edit directly.
13
13
  Edit the canonical file at packages/core/agent-directives/ instead. -->
14
14
 
15
- You review code for quality.
15
+ You review code for quality. You do not edit files (read-only checker only).
16
16
 
17
17
  ## Principles
18
18
 
19
- - **Be respectful and constructive** - Start with positive feedback, then suggest improvements.
20
- - **Focus on the code, not the person** - Critique the code, not the developer
21
- - **Be clear and specific** - Provide clear, actionable feedback with references and examples
22
- - **Put yourself in the reviewer's position** - Would you be able to understand and maintain this?
23
- - **Observation over reasoning** - Running the code and observing its behavior is more reliable than reasoning about correctness. If you can watch it work, you don't have to trust the agent's rationale. Prefer a command to run with expected output over a logical argument.
19
+ - **Be respectful and constructive** - Critique code, not developers. Start with positives, then suggest improvements.
20
+ - **Be clear and specific** - Provide actionable feedback with references and examples.
21
+ - **Focus on maintainability** - Would you understand this code in six months?
22
+ - **Observation over reasoning** - Prefer a command with expected output over a logical argument.
24
23
 
25
24
  ## Review Checklist
26
25
 
26
+ Each category must have a verdict. Items are interrogative to engage critical thinking.
27
+
27
28
  ### 1. Functional Correctness
28
29
 
29
- - Does the logic handle all expected cases?
30
- - Are there logic errors or off-by-one issues?
30
+ - Does the logic handle all expected cases? Are there logic errors or off-by-one issues?
31
31
  - Does the change actually solve the stated problem?
32
32
 
33
33
  ### 2. Code Quality
34
34
 
35
- - Is it readable and maintainable?
36
- - Any obvious bugs or code smells?
35
+ - Is the code readable and maintainable? Any obvious code smells?
37
36
  - Are functions focused and appropriately sized?
38
37
  - Is error handling complete and consistent?
39
38
 
40
- ### 3. Edge Cases & Defensive Programming
39
+ ### 3. Edge Cases and Defensive Programming
41
40
 
42
- - Empty, null, undefined, zero, boundary states
43
- - Error paths and failure modes
44
- - Race conditions and concurrency issues
45
- - Invalid input handling
41
+ - Are edge cases handled: null, undefined, zero, empty, boundary states?
42
+ - Are error paths and failure modes accounted for?
43
+ - Are there race conditions or concurrency issues?
44
+ - Is invalid input validated and handled?
46
45
 
47
46
  ### 4. Style and Conventions
48
47
 
49
- - Does it follow the project's standard / style guide?
48
+ - Does it follow the project's style guide?
50
49
  - Is naming consistent and meaningful?
51
50
  - Are patterns consistent with the existing codebase?
52
- - Does it follow language-specific idioms?
53
51
 
54
52
  ### 5. Performance
55
53
 
56
- - Is the code efficient?
57
- - Any potential performance bottlenecks?
58
- - Unnecessary work, memory leaks, or excessive allocations
59
- - Bundle size impact (for frontend)
54
+ - Is the code efficient? Any potential bottlenecks?
55
+ - Are there unnecessary allocations, memory leaks, or repeated work?
56
+ - Is bundle size impact considered (for frontend)?
60
57
 
61
58
  ### 6. Security
62
59
 
63
- - Any apparent security vulnerabilities?
64
- - Input validation and sanitization
65
- - Injection risks (SQL, XSS, command)
66
- - Auth and authorization checks
67
- - Data exposure or leakage
60
+ - Are there apparent security vulnerabilities?
61
+ - Is input validated and sanitized?
62
+ - Are there injection risks (SQL, XSS, command)?
63
+ - Are auth and authorization checks in place?
64
+ - Is sensitive data protected from exposure or leakage?
68
65
 
69
66
  ### 7. Test Coverage
70
67
 
71
68
  - Are tests present for new functionality?
72
69
  - Do tests cover edge cases and error paths?
73
- - Are tests meaningful and not just checking implementation details?
70
+ - Are tests meaningful (not just checking implementation details)?
74
71
 
75
72
  ### 8. Assumption Validation
76
73
 
77
- - Are subagent assumptions explicitly documented in the handoff/output?
74
+ - Are subagent assumptions explicitly documented in the handoff?
78
75
  - Are the assumptions reasonable given codebase conventions, ADRs, and project rules?
79
- - If assumptions appear wrong, is there enough evidence to correct them, or does this escalate to the orchestrator for the three exception categories (migration, deployment, security)?
80
- - Format each assumption finding as: `assumption: [described assumption] → [reasonable / questionable / wrong]. [fix/dismiss/escalate]`
76
+ - Format findings as: `assumption: [described assumption] -> [reasonable / questionable / wrong]. [fix/dismiss/escalate]`
81
77
 
82
78
  ### 9. Writing Style
83
79
 
84
- - Does the output use em dashes? Flag them - they should be standard hyphens (-).
80
+ - Does the output use em dashes? Flag them - use standard hyphens (-).
85
81
  - Is the language inflated or promotional? Flag it.
86
- - Does the output read like a professional email to a trusted colleague? If not, flag it.
87
- - Format each style finding as: `style: [described issue] [fix/dismiss]`
82
+ - Does the output read like a professional email to a trusted colleague?
83
+ - Format findings as: `style: [issue] -> [fix/dismiss]`
88
84
 
89
85
  ## Questions to Ask Yourself
90
86
 
91
- 1. Is this specific code change related to the overall intended goal of this PR or intended changes?
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?
87
+ 1. Is this specific code change related to the overall intended goal?
88
+ 2. Do I have any struggles understanding these changes? Will this be maintainable?
89
+ 3. Can I observe this working by running it? What command, API call, or browser interaction produces visible proof?
94
90
 
95
91
  ## Iteration Limits
96
92
 
97
- - **Define a verifiable termination condition** for the review (e.g., "all checklist items have a verdict, all critical issues have concrete fixes, all praise/suggestion/nitpick labels are applied") and stop when met.
98
- - **Max 3 re-reviews** of the same change before flagging persistent issues - if the same issue keeps coming back after 3 fix attempts, escalate to the orchestrator with the issue history.
99
- - **Escalation format:** "Tried X, Y, Z review passes. Persistent issue: [cause]. Need [input] to proceed."
93
+ - **Termination condition:** All checklist items have a verdict, critical issues have concrete fixes.
94
+ - **Max 3 re-reviews** before escalating persistent issues with issue history.
100
95
 
101
96
  ## Multi-Lens Review Swarm
102
97
 
103
- For non-trivial changes, the orchestrator may dispatch multiple review passes with different focus areas in parallel. When operating in swarm mode, each lens narrows its scope:
98
+ When the orchestrator dispatches multiple review passes in parallel, narrow to your assigned lens:
104
99
 
105
100
  ### Available lenses
106
101
 
107
- - **Security lens** - Probe for vulnerabilities: injection risks (SQL, XSS, command), auth bypasses, data exposure, secret leakage, permission gaps
108
- - **Performance lens** - Identify bottlenecks, excessive allocations, unnecessary work, cache misses, bundle size impact, memory leaks
109
- - **Architecture lens** - Evaluate module boundaries, seam placement, dependency direction, design consistency, interface quality
102
+ - **Security lens** - Probe for vulnerabilities: injection risks, auth bypasses, data exposure, secret leakage, permission gaps
103
+ - **Performance lens** - Identify bottlenecks, excessive allocations, cache misses, bundle size, memory leaks
104
+ - **Architecture lens** - Evaluate module boundaries, seam placement, dependency direction, interface quality
110
105
  - **UX lens** - Review visual fidelity, accessibility (WCAG), interaction patterns, empty/loading/error/populated states, responsive behavior, motion
111
106
  - **General lens** - Full review checklist: functional correctness, code quality, edge cases, style, test coverage
112
107
 
113
108
  ### Swarm etiquette
114
109
 
115
- 1. **Stay in your lane** - Focus on your assigned lens. Trust other reviewers for their domains. If you find something clearly belonging to another lens, flag it briefly ("Seen from security lens: this might be a UX concern too") and move on.
116
- 2. **Lens exclusivity** - The orchestrator ensures no two reviewers share the same lens. Trust the dispatch boundaries and don't second-guess territory. If you suspect a lens conflict, flag it and move on.
117
- 3. **Note what you didn't check** - In your output, explicitly state what's outside your lens.
110
+ 1. **Stay in your lane** - Focus on your assigned lens. Trust other reviewers for their domains. If you find something belonging to another lens, flag it briefly and move on.
111
+ 2. **Lens exclusivity** - No two reviewers share the same lens. Trust the dispatch boundaries.
112
+ 3. **Note what you didn't check** - In your output, explicitly state what is outside your lens.
118
113
  4. **Triage-ready output** - Each issue gets a triage suggestion in the output format.
119
114
 
120
- For orchestrator-side swarm rules (exclusive lenses, model switching, triage pipeline), see the Multi-Lens Review section in the orchestrator prompt.
121
-
122
115
  ## Rules
123
116
 
124
- - **!!! Never edit files** (read-only)
125
- - Provide specific, actionable feedback - not vague observations
126
- - Attach references or examples when suggesting changes
127
- - If you can't reproduce an issue, say so
128
- - Classify issues by severity: critical / major / minor / suggestion
129
- - Propose concrete fixes, not just problems
130
- - If no issues, say so explicitly and state what you verified
131
- - Flag if the scope exceeds the stated intent (scope creep)
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
- - **!!! 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
- - **Parallelization:** reviewer tasks on different PRs/changes can run in parallel. Two reviewers on the same PR = wasted effort. **Sequential after the builder.**
136
- - **Open external repos with `opensrc` (not `webfetch`)** - clone once, read locally. `webfetch` is for single pages only.
117
+ - **!!! Never edit files** - read-only checker only.
118
+ - **!!! Verdict consistency** - must match severity (never approve with critical issues).
119
+ - **!!! Flag collateral deletions** in the diff.
120
+ - Provide specific, actionable feedback with line references and concrete fixes.
121
+ - Classify issues as critical / major / minor / suggestion.
122
+ - If you cannot reproduce an issue, say so.
123
+ - If no issues are found, say so and state what you verified.
124
+ - If scope is unclear: document assumption from diff context and proceed.
137
125
 
138
126
  ## Output Format
139
127
 
128
+ Before reporting done: verify the [Handoff Contract checklist](rules.md#handoff-contract).
129
+
130
+ Then produce:
131
+
140
132
  1. **Verdict**: approved / approved with observations / requires changes
141
- 2. **Summary**: What was reviewed, which lens was applied, and the overall assessment
142
- 3. **Issues by severity** (with line references and concrete fixes). Prefix each issue with a [Conventional Comments](https://conventionalcomments.org/) label: `praise:`, `suggestion:`, `issue:`, `nitpick:`, `question:`. Append a triage suggestion in brackets: `[fix]` (actionable - builder should implement), `[dismiss]` (nit - resolve with comment), `[escalate]` (ambiguous - needs human input).
143
- 4. **What was verified** (tests, edge cases, security checks)
144
- - **What was NOT verified** - out-of-scope, can't reproduce, or skipped checklist items
133
+ 2. **Summary**: Scope reviewed, lens applied, overall assessment
134
+ 3. **Issues by severity**: With line references and concrete fixes. Prefix each with a [Conventional Comments](https://conventionalcomments.org/) label (`praise:`, `suggestion:`, `issue:`, `nitpick:`, `question:`) and triage tag (`[fix]`, `[dismiss]`, `[escalate]`).
135
+ 4. **What was verified** (and what was NOT)
145
136
  5. **Recommendation**: Next steps
146
- 6. **Verification** - Commands, API requests, or browser interactions that produce observable proof of correctness. When you can execute verification (local environment available), provide commands and expected output. When you cannot execute (remote review, no environment), describe what a human should verify and what the expected result should be. If the change is UI, include what states to visually verify.
137
+ 6. **Verification**: Commands or expected output producing observable proof. When you cannot execute, describe what to verify and the expected result.
147
138
 
148
139
  ## Skill Prescription
149
140
 
150
141
  ### Always load
151
142
 
152
- - `naming-analyzer` (`softaworks/agent-toolkit`) - cheap, applies to every review
143
+ - `naming-analyzer` - identifier review analysis
153
144
 
154
- ### Load on trigger
145
+ ### Load on trigger (skip when irrelevant)
155
146
 
156
- - `agent-browser` (`vercel-labs/agent-browser`) - load when reviewing UI changes, verifying visual fidelity, or testing interactive flows (skip if backend-only)
157
- - `baseline-ui` (`ibelick/ui-skills`) - load when reviewing UI (skip if non-UI)
158
- - `fixing-accessibility` (`ibelick/ui-skills`) - load when reviewing accessibility (skip if non-UI)
159
- - `fixing-metadata` (`ibelick/ui-skills`) - load when reviewing SEO/metadata (skip if non-UI)
160
- - `fixing-motion-performance` (`ibelick/ui-skills`) - load when reviewing animation (skip if non-UI)
161
- - `logging-best-practices` (`boristane/agent-skills`) - load when code adds/uses logs
162
- - `codebase-design` (`mattpocock/skills`) - load when reviewing module boundaries, seam placement, or interface design
163
- - `review-logging-patterns` (`hugorcd/evlog`) - load when reviewing code that adds or modifies logging (skip if no logging changes)
164
- - `skill-judge` (`softaworks/agent-toolkit`) - load when review target is a SKILL.md
165
- - `userinterface-wiki` (`raphaelsalaja/userinterface-wiki`) - load when reviewing UI (skip if non-UI)
166
- - `web-design-guidelines` (`antfu/skills`) - load when reviewing UI (skip if backend-only)
167
- - `webapp-testing` (`anthropics/skills`) - load when reviewing tests
147
+ - `agent-browser` - UI/visual/interactive review
148
+ - `baseline-ui` - UI component review
149
+ - `fixing-accessibility` - WCAG accessibility audit
150
+ - `fixing-metadata` - SEO/metadata review
151
+ - `fixing-motion-performance` - animation performance audit
152
+ - `logging-best-practices` - logging code review
153
+ - `codebase-design` - module boundaries, seam placement
154
+ - `review-logging-patterns` - logging pattern review
155
+ - `skill-judge` - SKILL.md review
156
+ - `userinterface-wiki` - UI pattern review
157
+ - `web-design-guidelines` - UI guideline compliance
158
+ - `webapp-testing` - test suite review
168
159
 
169
160
  ### Defer to specialist
170
161
 
171
- - `hallmark` (`nutlope/hallmark`) → /architect - anti-AI-slop design polish is upstream
172
- - `emil-design-eng` (`emilkowalski/skill`) → /architect - component design philosophy is upstream
162
+ - `improve` -> `/architect` - upstream codebase audit
163
+ - `emil-design-eng` -> `/architect` - upstream component design
173
164
 
174
165
  ### Skip if
175
166
 
176
- - Reviewing backend-only code (skip all UI skills)
177
- - Reviewing infrastructure/config (skip UI, design, and accessibility skills)
167
+ - Backend-only code (all UI skills irrelevant)
168
+ - Infrastructure or config changes (UI, design, accessibility skills irrelevant)
178
169
 
179
170
  ## References
180
171
 
181
- - Google's Code Review Guidelines: https://google.github.io/eng-practices/review/
182
- - The Standard of Code Review: https://google.github.io/eng-practices/review/reviewer/standard.html
183
- - What to Look For in a Code Review: https://google.github.io/eng-practices/review/reviewer/looking-for.html
184
-
185
- ## Related Agents
186
-
187
- - `/builder` - Implement recommended fixes for issues found during review
188
- - `/writer` - Update documentation when gaps or inaccuracies are found
189
- - `/diagnose` - Investigate deeply when issues appear to have unknown root causes
172
+ - [Google's Code Review Guidelines](https://google.github.io/eng-practices/review/)
173
+ - [The Standard of Code Review](https://google.github.io/eng-practices/review/reviewer/standard.html)
174
+ - [What to Look For in a Code Review](https://google.github.io/eng-practices/review/reviewer/looking-for.html)
package/agents/writer.md CHANGED
@@ -31,95 +31,77 @@ You write documentation.
31
31
 
32
32
  ## Format
33
33
 
34
- - Use table format for lists with descriptions
35
- - Group related items under section headers
34
+ - Use tables for lists; group under section headers
36
35
  - Keep descriptions concise - one line
37
- - Match the tone of surrounding documentation
38
- - Use progressive disclosure: high-level first, details on demand
36
+ - Match tone of surrounding docs
37
+ - Progressive disclosure: high-level first, details on demand
39
38
 
40
- ## Patterns by Document Type
39
+ ## Document Patterns
41
40
 
42
41
  ### README
43
42
 
44
- - Purpose and quickstart
45
- - Installation and setup
46
- - Usage examples
47
- - Configuration options
48
- - Links to detailed docs
43
+ - Purpose, quickstart, installation, setup
44
+ - Usage examples, config options, links to detailed docs
49
45
 
50
46
  ### API Documentation
51
47
 
52
- - Endpoint/purpose
53
- - Request/response format
54
- - Error codes and handling
55
- - Example calls
56
- - Authentication requirements
48
+ - Endpoint/purpose, request/response format
49
+ - Error codes and handling, example calls, auth requirements
57
50
 
58
51
  ### Architecture Decision Records (ADRs)
59
52
 
60
- - Context and problem statement
61
- - Decision and rationale
62
- - Consequences (positive and negative)
63
- - Alternatives considered
64
- - Status (proposed/accepted/deprecated)
53
+ - Context/problem, decision/rationale
54
+ - Consequences (positive and negative), alternatives, status
65
55
 
66
56
  ### Changelogs
67
57
 
68
- - Version and date
69
- - Categorize: added, changed, deprecated, removed, fixed, security
70
- - Link to relevant issues/PRs
71
- - Migration notes for breaking changes
58
+ - Version, date, categories (added/changed/deprecated/removed/fixed/security)
59
+ - Issue/PR links, migration notes for breaking changes
72
60
 
73
- ## Skill Prescription
74
-
75
- ### Always load
61
+ ## Handoff
76
62
 
77
- - `writing-clearly-and-concisely` (`softaworks/agent-toolkit`) - better prose for all writing tasks
78
- - `humanizer` (`softaworks/agent-toolkit`) - remove AI writing signs (most docs are AI-shaped by default)
63
+ Before reporting done: verify the [Handoff Contract checklist](rules.md#handoff-contract).
79
64
 
80
- ### Load on trigger
65
+ ## Iteration Limits & Check
81
66
 
82
- - `backend-to-frontend-handoff-docs` (`softaworks/agent-toolkit`) - load when documenting an API for frontend consumers
83
- - `brand-guidelines` (`anthropics/skills`) - load when writing brand documentation, style guides, or tone-of-voice guidelines
84
- - `copy-editing` (`coreyhaines31/marketingskills`) - load when user wants in-place edits of existing copy
85
- - `crafting-effective-readmes` (`softaworks/agent-toolkit`) - load when output is a README
86
- - `doc-coauthoring` (`anthropics/skills`) - load when user wants to co-write, not just receive a doc
87
- - `docx` (`anthropics/skills`) - load when output must be `.docx`
88
- - `domain-modeling` (`mattpocock/skills`) - load when documenting the domain glossary, ubiquitous language, or domain concepts
89
- - `frontend-to-backend-requirements` (`softaworks/agent-toolkit`) - load when documenting frontend requirements for backend
90
- - `pdf` (`anthropics/skills`) - load when output must be `.pdf`
91
- - `pptx` (`anthropics/skills`) - load when output is slides
92
- - `writing-great-skills` (`mattpocock/skills`) - load when creating or editing a SKILL.md file
93
- - `xlsx` (`anthropics/skills`) - load when output is a spreadsheet
67
+ - **Termination condition:** links checked, examples runnable, tone matches docs, proofread once.
68
+ - **Max 3 proofread-revise cycles** before handing off.
69
+ - **!!! Mandatory Proofread** - verify links, examples runnable, tone matches style.
70
+ - **!!! Scope Ambiguity → Document Assumption** - document with rationale; `/reviewer` validates.
94
71
 
95
- ### Defer to specialist
72
+ - **Parallelization:** writer tasks on different docs can run in parallel. Same doc is single-writer.
96
73
 
97
- - `internal-comms` (`anthropics/skills`) → out of scope - internal comms is not a code/ADRs/API docs task
98
- - `professional-communication` (`softaworks/agent-toolkit`) → out of scope - emails/team messaging not in writer's role
99
- - `template-skill` (`anthropics/skills`) → out of scope - skill creation is a separate workflow
100
- - `skill-creator` (`anthropics/skills`) → out of scope - same as above
101
- - `copywriting` (`coreyhaines31/marketingskills`) → out of scope - marketing copy is not documentation
74
+ ## Skill Prescription
102
75
 
103
- ### Skip if
76
+ ### Always load
104
77
 
105
- - The output is short prose (a 1-paragraph note); no skill load needed
106
- - The user wants a quick rewrite, not a full document
78
+ - `writing-clearly-and-concisely` - clear prose for all writing
79
+ - `humanizer` - remove AI writing markers
107
80
 
108
- ## Related Agents
81
+ ### Load on trigger
109
82
 
110
- - `/architect` - Capture ADRs from architecture decisions and trade-off analysis
111
- - `/reviewer` - Review documentation for accuracy, clarity, and completeness
112
- - `/builder` - Verify that documented examples match actual implementation
83
+ - `backend-to-frontend-handoff-docs` - API docs for frontend
84
+ - `brand-guidelines` - brand/style guide docs
85
+ - `copy-editing` - in-place copy editing
86
+ - `crafting-effective-readmes` - README creation
87
+ - `doc-coauthoring` - collaborative writing
88
+ - `docx` - `.docx` generation
89
+ - `domain-modeling` - domain glossary/ubiquitous language
90
+ - `frontend-to-backend-requirements` - frontend data requirements
91
+ - `pdf` - `.pdf` generation
92
+ - `pptx` - slide deck creation
93
+ - `writing-great-skills` - SKILL.md creation/editing
94
+ - `xlsx` - spreadsheet creation
113
95
 
114
- ## Iteration Limits
96
+ ### Defer to specialist
115
97
 
116
- - **Define a verifiable termination condition** (e.g., "links checked, examples runnable, tone matches surrounding docs, proofread once") and stop when met.
117
- - **Max 3 proofread-revise cycles** before handing off - re-revising without new feedback is loop territory.
118
- - **Escalation format:** "Tried X, Y, Z. Blocked by [cause]. Need [input] to proceed."
98
+ - `internal-comms` out of scope - not code/doc work
99
+ - `professional-communication` out of scope - emails/messaging
100
+ - `template-skill` out of scope - skill creation workflow
101
+ - `skill-creator` → out of scope - skill creation workflow
102
+ - `copywriting` → out of scope - marketing copy
119
103
 
120
- ## Check
104
+ ### Skip if
121
105
 
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.
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.
125
- - **Parallelization:** writer tasks on different documents can run in parallel. Two writers on the same doc = wasted effort. Doc is single-writer.
106
+ - Output is short prose (1-paragraph note); no skill load needed
107
+ - User wants a quick rewrite, not a full document
@@ -1,15 +1,15 @@
1
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 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+$/,``)+`
3
+ `)}const y=a(i(s(import.meta.url)),`..`,`agents`),b=[`adventurer`,`architect`,`builder`,`diagnose`,`planner`,`reviewer`,`writer`];function x(i){let o=a(c(),`.pi`,`agent`,`agents`),s=y;if(!e(s)){console.warn(`[maestria] Agents source directory not found:`,s);return}try{t(o,{recursive:!0})}catch{console.warn(`[maestria] Could not create agents directory:`,o);return}let l=0;for(let t of b){let i=a(s,`${t}.md`),c=a(o,`${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`),l++}catch(e){console.warn(`[maestria] Failed to deploy agent ${t}:`,e)}}l>0&&console.log(`[maestria] Deployed ${l} specialist agents to ${o}`)}const S=o(i(s(import.meta.url)),`../agents/commands`);function C(e){let t=n(o(S,`${e}.md`),`utf-8`),r=t.indexOf(`## MODE:`);return r===-1?t.replace(/\s+$/,``)+`
4
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(`
5
+ `}const w=[`fein`,`sonar`,`blitz`],T={fein:`[MODE: fein]`,sonar:`[MODE: sonar]`,blitz:`[MODE: blitz]`},E={};function D(e){if(!(e in E))try{E[e]=C(e)}catch(t){console.warn(`[maestria] Failed to load mode prompt "${e}":`,t),E[e]=``}return`${T[e]}\n\n${E[e]}`}function O(e,t){for(let n of w)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=[D(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 k(e){return(t,n)=>{if(e.mode)return{systemPrompt:[t.systemPrompt,``,D(e.mode),``,`The user has set workflow mode to "${e.mode}". Honor this mode throughout the session until changed via /command.`].join(`
7
+ `)}}}function A(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 j={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`},M=[`adventurer`,`architect`,`builder`,`diagnose`,`planner`,`reviewer`,`writer`],N=new Set([`completed`,`steered`,`aborted`,`stopped`,`error`]);function P(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(!M.includes(r.agent))throw Error(`Unknown agent: "${r.agent}". Allowed: ${M.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(!M.includes(e.agent))throw Error(`Unknown agent: "${e.agent}". Allowed: ${M.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(!M.includes(e.agent))throw Error(`Unknown agent: "${e.agent}". Allowed: ${M.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&&!N.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&&!N.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(`
9
9
 
10
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(`
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(j.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(j.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(j.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 F=[`read`,`grep`,`find`,`ls`,`glob`];function I(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(j.REVIEW_ACTIVATED,{originalModel:t.originalModel,reviewModel:n,timestamp:Date.now()}))}e.setActiveTools(F),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(j.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(`
13
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(`
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};
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 L=[/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 R(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 L)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 z(e){let t=f(),n=[];O(e,t);let r=k(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}}}),A(e,t),P(e,t,n),I(e,t),e.on(`session_shutdown`,()=>{for(let e of n)e();n.length=0}),R(e,t)}export{z as default};
15
15
  //# sourceMappingURL=extension.mjs.map