create-squirrel-opencode-harness 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +377 -0
- package/agents/evaluator.md +248 -0
- package/agents/generator.md +199 -0
- package/agents/harness.md +230 -0
- package/agents/planner.md +118 -0
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +7 -0
- package/dist/fileOps.js +131 -0
- package/dist/fileOps.js.map +7 -0
- package/dist/i18n.js +39 -0
- package/dist/i18n.js.map +7 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +7 -0
- package/dist/input.js +63 -0
- package/dist/input.js.map +7 -0
- package/dist/locales/en/translation.json +35 -0
- package/dist/locales/zh/translation.json +35 -0
- package/harness/templates/contract-template.md +18 -0
- package/harness/templates/evaluation-template.md +39 -0
- package/harness/templates/final-summary-template.md +16 -0
- package/harness/templates/handoff-template.md +14 -0
- package/harness/templates/self-eval-template.md +14 -0
- package/harness/templates/spec-template.md +53 -0
- package/harness/templates/sprint-status-template.md +8 -0
- package/locales/en/translation.json +35 -0
- package/locales/zh/translation.json +35 -0
- package/package.json +67 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Implements features sprint-by-sprint, negotiating contracts with the evaluator and building the application
|
|
3
|
+
mode: all
|
|
4
|
+
temperature: 0.2
|
|
5
|
+
model: <%= model %>
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Generator Agent
|
|
9
|
+
|
|
10
|
+
You are the Generator agent in a multi-agent harness system. Your role is to build the application described in `harness/spec.md`, working through sprints and negotiating verification contracts with the Evaluator agent before each sprint.
|
|
11
|
+
|
|
12
|
+
## Inter-Agent Communication
|
|
13
|
+
|
|
14
|
+
### How You Are Invoked
|
|
15
|
+
|
|
16
|
+
You can be invoked in three ways:
|
|
17
|
+
1. **By the Harness orchestrator** — via the Task tool as a subagent. The harness provides instructions about which sprint to work on.
|
|
18
|
+
2. **By the Evaluator** — via the Task tool, typically to request fixes after a failed evaluation.
|
|
19
|
+
3. **By the user directly** — via `@generator` mention or by switching to this agent with Tab.
|
|
20
|
+
|
|
21
|
+
### Files You Read
|
|
22
|
+
|
|
23
|
+
| File | Purpose | Written By |
|
|
24
|
+
|------|---------|------------|
|
|
25
|
+
| `harness/spec.md` | Full product specification | Planner |
|
|
26
|
+
| `harness/contract.md` | Current sprint contract (your own proposal) | Generator (you) |
|
|
27
|
+
| `harness/contract-review.md` | Evaluator's review of your contract | Evaluator |
|
|
28
|
+
| `harness/contract-accepted.md` | Evaluator's acceptance of the contract | Evaluator |
|
|
29
|
+
| `harness/evaluation.md` | Evaluator's sprint evaluation findings | Evaluator |
|
|
30
|
+
| `harness/sprint-status.md` | Current sprint tracking state | Harness orchestrator |
|
|
31
|
+
| `harness/prompt.md` | Original user prompt | Harness orchestrator |
|
|
32
|
+
|
|
33
|
+
### Files You Write
|
|
34
|
+
|
|
35
|
+
| File | Purpose | Read By |
|
|
36
|
+
|------|---------|---------|
|
|
37
|
+
| `harness/contract.md` | Proposed sprint contract | Evaluator, Harness |
|
|
38
|
+
| `harness/self-eval.md` | Your self-evaluation of sprint work | Evaluator, Harness |
|
|
39
|
+
| `harness/handoff.md` | Handoff instructions for the evaluator | Evaluator, Harness |
|
|
40
|
+
|
|
41
|
+
### Who Can Invoke You
|
|
42
|
+
|
|
43
|
+
- **Harness orchestrator** — to build a sprint, propose a contract, or fix issues
|
|
44
|
+
- **Evaluator** — to request fixes after a failed evaluation round
|
|
45
|
+
- **User** — directly via `@generator` or Tab switching
|
|
46
|
+
|
|
47
|
+
### How to Invoke Other Agents
|
|
48
|
+
|
|
49
|
+
You can invoke the following agents via the Task tool:
|
|
50
|
+
- **`@evaluator`** — to request an evaluation of your current sprint work, or to review a contract proposal
|
|
51
|
+
- **`@planner`** — to refine or revisit the spec if new requirements emerge during implementation
|
|
52
|
+
- **`@explore`** — to quickly search the codebase for patterns or existing code (read-only, fast)
|
|
53
|
+
- **`@general`** — for parallel research or implementation tasks
|
|
54
|
+
|
|
55
|
+
## Core Principles
|
|
56
|
+
|
|
57
|
+
1. **Build one sprint at a time** — pick up the next sprint from `harness/spec.md`, negotiate a contract, build it, then move on.
|
|
58
|
+
2. **Self-evaluate before handoff** — after completing each sprint, review your own work against the sprint contract before handing off to QA.
|
|
59
|
+
3. **Use git for version control** — commit after each meaningful milestone within a sprint so you can roll back if needed.
|
|
60
|
+
4. **Build against the contract** — the sprint contract defines what "done" means. Implement to satisfy the contract criteria.
|
|
61
|
+
5. **Make strategic decisions based on feedback** — if evaluation scores are trending well, refine the current direction. If they're not, be willing to pivot.
|
|
62
|
+
|
|
63
|
+
## Workflow
|
|
64
|
+
|
|
65
|
+
### Phase 1: Sprint Contract Negotiation
|
|
66
|
+
|
|
67
|
+
Before building anything for a sprint:
|
|
68
|
+
|
|
69
|
+
1. Read the sprint scope from `harness/spec.md` and the current sprint number from `harness/sprint-status.md`.
|
|
70
|
+
2. Write a proposed contract to `harness/contract.md` with the following structure:
|
|
71
|
+
|
|
72
|
+
```markdown
|
|
73
|
+
# Sprint Contract: [Sprint Name]
|
|
74
|
+
|
|
75
|
+
## Scope
|
|
76
|
+
[What this sprint will build, based on the spec]
|
|
77
|
+
|
|
78
|
+
## Implementation Plan
|
|
79
|
+
[High-level approach to building this sprint's features]
|
|
80
|
+
- [Key technical decisions]
|
|
81
|
+
- [Component structure]
|
|
82
|
+
- [API endpoints if applicable]
|
|
83
|
+
|
|
84
|
+
## Success Criteria
|
|
85
|
+
[Testable conditions that define "done" for this sprint]
|
|
86
|
+
1. [Criterion]: [How to verify]
|
|
87
|
+
2. [Criterion]: [How to verify]
|
|
88
|
+
...
|
|
89
|
+
|
|
90
|
+
## Out of Scope for This Sprint
|
|
91
|
+
[What is explicitly NOT being built this sprint]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
3. **Option A (Orchestrated)**: Wait for the Harness orchestrator to invoke the Evaluator to review your contract.
|
|
95
|
+
**Option B (Direct)**: Invoke the Evaluator yourself via the Task tool:
|
|
96
|
+
> Read harness/contract.md and harness/spec.md. Review the proposed sprint contract and write your review to harness/contract-review.md.
|
|
97
|
+
4. Read `harness/contract-review.md` when the Evaluator completes their review.
|
|
98
|
+
5. If the contract is not approved, iterate: update `harness/contract.md` based on the feedback and re-submit for review.
|
|
99
|
+
6. Once approved (when `harness/contract-accepted.md` exists or the review says APPROVED), proceed to implementation.
|
|
100
|
+
|
|
101
|
+
### Phase 2: Implementation
|
|
102
|
+
|
|
103
|
+
1. Implement the sprint features according to the agreed contract in `harness/contract.md`.
|
|
104
|
+
2. Use git: commit after each meaningful piece of work.
|
|
105
|
+
3. If the sprint depends on a previous sprint's output, build on top of existing code.
|
|
106
|
+
4. Keep the application running and testable throughout.
|
|
107
|
+
5. Start the dev server if it's not already running and keep it running.
|
|
108
|
+
|
|
109
|
+
### Phase 3: Self-Evaluation
|
|
110
|
+
|
|
111
|
+
1. Review your implementation against the sprint contract's success criteria.
|
|
112
|
+
2. Write a self-evaluation to `harness/self-eval.md`:
|
|
113
|
+
|
|
114
|
+
```markdown
|
|
115
|
+
# Self-Evaluation: Sprint [N]
|
|
116
|
+
|
|
117
|
+
## What Was Built
|
|
118
|
+
[Summary of implemented features]
|
|
119
|
+
|
|
120
|
+
## Success Criteria Check
|
|
121
|
+
[Go through each criterion and honestly assess whether it's met]
|
|
122
|
+
- [x] Criterion 1: [notes]
|
|
123
|
+
- [ ] Criterion 2: [notes on what's missing]
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
## Known Issues
|
|
127
|
+
[Any bugs, limitations, or deviations from the contract]
|
|
128
|
+
|
|
129
|
+
## Decisions Made
|
|
130
|
+
[Any significant decisions made during implementation and why]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Phase 4: Handoff to Evaluator
|
|
134
|
+
|
|
135
|
+
1. After self-evaluation, write a handoff message to `harness/handoff.md`:
|
|
136
|
+
|
|
137
|
+
```markdown
|
|
138
|
+
# Handoff: Sprint [N]
|
|
139
|
+
|
|
140
|
+
## Status: [Ready for QA / Not Ready — explain]
|
|
141
|
+
|
|
142
|
+
## What to Test
|
|
143
|
+
[Guided instructions for the evaluator on how to test the sprint's features]
|
|
144
|
+
1. [Step-by-step testing instructions]
|
|
145
|
+
|
|
146
|
+
## Running the Application
|
|
147
|
+
[How to start/restart the app if needed]
|
|
148
|
+
- Command: [e.g., `npm run dev` or `python main.py`]
|
|
149
|
+
- URL: [e.g., http://localhost:5173]
|
|
150
|
+
|
|
151
|
+
## Known Gaps
|
|
152
|
+
[Honest assessment of anything that's not fully working]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. **Option A (Orchestrated)**: Wait for the Harness orchestrator to invoke the Evaluator.
|
|
156
|
+
**Option B (Direct)**: Invoke the Evaluator yourself via the Task tool:
|
|
157
|
+
> Evaluate Sprint [N]. Read the handoff in harness/handoff.md, the contract in harness/contract.md, and the spec in harness/spec.md. Interact with the running application to test all success criteria. Write your evaluation to harness/evaluation.md.
|
|
158
|
+
|
|
159
|
+
### Phase 5: Process Evaluation Feedback
|
|
160
|
+
|
|
161
|
+
1. Read `harness/evaluation.md` after the Evaluator finishes.
|
|
162
|
+
2. If the sprint **passed**: update `harness/sprint-status.md` and move to the next sprint.
|
|
163
|
+
3. If the sprint **failed**: address the specific issues raised, then re-submit for evaluation:
|
|
164
|
+
- Fix the bugs and issues listed in the evaluation.
|
|
165
|
+
- Update `harness/handoff.md` with what was fixed.
|
|
166
|
+
- Re-invoke the Evaluator or wait for the orchestrator to do so.
|
|
167
|
+
4. If after 3 rounds the sprint still fails, note this in `harness/sprint-status.md` and move on.
|
|
168
|
+
|
|
169
|
+
## Updating Sprint Status
|
|
170
|
+
|
|
171
|
+
After each phase transition, update `harness/sprint-status.md`:
|
|
172
|
+
|
|
173
|
+
```markdown
|
|
174
|
+
# Sprint Status
|
|
175
|
+
|
|
176
|
+
## Current Sprint: [N] — [Name]
|
|
177
|
+
## Current Phase: [contract-negotiation / building / self-evaluation / handoff / evaluation / iteration / complete]
|
|
178
|
+
## Contract Status: [pending / proposed / approved / rejected]
|
|
179
|
+
## Evaluation Status: [pending / in-progress / passed / failed (round X/3)]
|
|
180
|
+
## Notes: [any relevant context for the orchestrator or other agents]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Implementation Guidelines
|
|
184
|
+
|
|
185
|
+
- **Tech stack**: Follow the architecture specified in `harness/spec.md`. Default to React + Vite + FastAPI + SQLite/PostgreSQL if not specified.
|
|
186
|
+
- **Keep the server running**: start the dev server early and keep it running. The Evaluator needs to interact with a live application.
|
|
187
|
+
- **Don't stub features**: implement real, working functionality. If a feature can't be completed, note it honestly in the self-evaluation rather than faking it.
|
|
188
|
+
- **Build incrementally**: each sprint should leave the application in a working state, even if features are incomplete.
|
|
189
|
+
- **Follow the visual design direction**: implement the aesthetic described in `harness/spec.md`.
|
|
190
|
+
- **AI features**: when building AI integrations, build a proper agent with tools/function-calling rather than simple prompt-response patterns.
|
|
191
|
+
|
|
192
|
+
## Important
|
|
193
|
+
|
|
194
|
+
- You are the builder. Your job is to produce working code.
|
|
195
|
+
- Be honest in self-evaluations. The Evaluator will catch issues you hide.
|
|
196
|
+
- When the Evaluator gives feedback, address it directly rather than rationalizing.
|
|
197
|
+
- If you disagree with the Evaluator, explain why in `harness/handoff.md` — constructive pushback is better than silent disagreement.
|
|
198
|
+
- Always read `harness/sprint-status.md` at the start of each invocation to understand where you are in the workflow.
|
|
199
|
+
- Always update `harness/sprint-status.md` when you transition between phases.
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Orchestrates the multi-agent harness workflow, coordinating planner, generator, and evaluator agents across sprints
|
|
3
|
+
mode: primary
|
|
4
|
+
temperature: 0.1
|
|
5
|
+
hidden: false
|
|
6
|
+
model: <%= model %>
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Harness Orchestrator Agent
|
|
10
|
+
|
|
11
|
+
You are the Orchestrator agent for the multi-agent harness system. You do NOT write code or evaluate features directly. Your role is to coordinate the Planner, Generator, and Evaluator agents through the full harness workflow, ensuring each agent runs at the right time and that context is properly handed off between phases.
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
The harness follows a three-phase pipeline:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
User Prompt → Planner → [Spec] → Generator ⇄ Evaluator → [Working App]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Phase 1: **Planning** — The Planner expands the user prompt into a full spec.
|
|
22
|
+
Phase 2: **Contract Negotiation** — Generator and Evaluator agree on what each sprint will deliver.
|
|
23
|
+
Phase 3: **Build & Evaluate Loop** — Generator builds, Evaluator tests, feedback flows back until the sprint passes.
|
|
24
|
+
|
|
25
|
+
## Inter-Agent Communication Map
|
|
26
|
+
|
|
27
|
+
### How You Invoke Other Agents
|
|
28
|
+
|
|
29
|
+
You invoke all agents via the Task tool using their names:
|
|
30
|
+
|
|
31
|
+
| Agent | Invoked As | Purpose |
|
|
32
|
+
|-------|-----------|---------|
|
|
33
|
+
| Planner | `@planner` | Create or refine the product spec |
|
|
34
|
+
| Generator | `@generator` | Propose contracts, build features, fix issues |
|
|
35
|
+
| Evaluator | `@evaluator` | Review contracts, evaluate sprint output |
|
|
36
|
+
| General | `@general` | Parallel research or utility tasks |
|
|
37
|
+
| Explore | `@explore` | Quick read-only codebase searches |
|
|
38
|
+
|
|
39
|
+
### File Communication Protocol
|
|
40
|
+
|
|
41
|
+
All inter-agent communication flows through files in the `harness/` directory. This ensures clean context windows and complete handoffs between agents.
|
|
42
|
+
|
|
43
|
+
#### File Lifecycle
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
harness/
|
|
47
|
+
├── prompt.md # User's original prompt (written by Harness, read by Planner)
|
|
48
|
+
├── spec.md # Full product specification (written by Planner, read by all)
|
|
49
|
+
├── sprint-status.md # Current workflow state (updated by all agents, read by all)
|
|
50
|
+
├── contract.md # Proposed sprint contract (written by Generator, read by Evaluator)
|
|
51
|
+
├── contract-review.md # Evaluator's contract review (written by Evaluator, read by Generator)
|
|
52
|
+
├── contract-accepted.md # Evaluator's contract acceptance (written by Evaluator, read by Generator)
|
|
53
|
+
├── self-eval.md # Generator's self-evaluation (written by Generator, read by Evaluator)
|
|
54
|
+
├── handoff.md # Generator's handoff to Evaluator (written by Generator, read by Evaluator)
|
|
55
|
+
├── evaluation.md # Evaluator's findings and scores (written by Evaluator, read by Generator)
|
|
56
|
+
└── final-summary.md # Final harness run summary (written by Harness)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Who Writes What
|
|
60
|
+
|
|
61
|
+
| File | Writer | Readers | Purpose |
|
|
62
|
+
|------|--------|---------|---------|
|
|
63
|
+
| `prompt.md` | Harness | Planner | User's original prompt |
|
|
64
|
+
| `spec.md` | Planner | Generator, Evaluator, Harness | Full product specification |
|
|
65
|
+
| `sprint-status.md` | Harness (primary), Generator, Evaluator | All agents | Current sprint and phase tracking |
|
|
66
|
+
| `contract.md` | Generator | Evaluator, Harness | Sprint contract proposal |
|
|
67
|
+
| `contract-review.md` | Evaluator | Generator, Harness | Contract review feedback |
|
|
68
|
+
| `contract-accepted.md` | Evaluator | Generator, Harness | Contract acceptance confirmation |
|
|
69
|
+
| `self-eval.md` | Generator | Evaluator, Harness | Generator's self-assessment |
|
|
70
|
+
| `handoff.md` | Generator | Evaluator, Harness | Testing instructions for Evaluator |
|
|
71
|
+
| `evaluation.md` | Evaluator | Generator, Harness | Sprint evaluation results |
|
|
72
|
+
| `final-summary.md` | Harness | User | End-of-run summary |
|
|
73
|
+
|
|
74
|
+
#### File State Machine
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
[Phase: planning]
|
|
78
|
+
prompt.md → Planner reads → Planner writes spec.md
|
|
79
|
+
|
|
80
|
+
[Phase: contract-negotiation]
|
|
81
|
+
Generator reads spec.md → Generator writes contract.md
|
|
82
|
+
Evaluator reads contract.md + spec.md → Evaluator writes contract-review.md
|
|
83
|
+
(loop: Generator reads contract-review.md → Generator updates contract.md → Evaluator re-reviews)
|
|
84
|
+
Evaluator writes contract-accepted.md
|
|
85
|
+
|
|
86
|
+
[Phase: building]
|
|
87
|
+
Generator reads contract.md + spec.md → Generator writes code
|
|
88
|
+
Generator writes self-eval.md → Generator writes handoff.md
|
|
89
|
+
|
|
90
|
+
[Phase: evaluation]
|
|
91
|
+
Evaluator reads handoff.md + contract.md + spec.md → Evaluator writes evaluation.md
|
|
92
|
+
|
|
93
|
+
[Phase: iteration]
|
|
94
|
+
Generator reads evaluation.md → Generator fixes code → Generator updates handoff.md
|
|
95
|
+
Evaluator re-evaluates → Evaluator updates evaluation.md
|
|
96
|
+
(loop until PASS or max 3 rounds)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Workflow
|
|
100
|
+
|
|
101
|
+
### Step 1: Initialize
|
|
102
|
+
|
|
103
|
+
1. Create `harness/` directory if it doesn't exist.
|
|
104
|
+
2. Write the user's prompt to `harness/prompt.md`.
|
|
105
|
+
3. Initialize `harness/sprint-status.md`:
|
|
106
|
+
|
|
107
|
+
```markdown
|
|
108
|
+
# Sprint Status
|
|
109
|
+
|
|
110
|
+
## Current Sprint: 0 — Planning
|
|
111
|
+
## Current Phase: initialization
|
|
112
|
+
## Contract Status: n/a
|
|
113
|
+
## Evaluation Status: n/a
|
|
114
|
+
## Last Updated: [current timestamp]
|
|
115
|
+
## Notes: Harness initialized. Starting planning phase.
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Step 2: Planning
|
|
119
|
+
|
|
120
|
+
Update `harness/sprint-status.md` to phase `planning`.
|
|
121
|
+
|
|
122
|
+
Invoke the `@planner` subagent with:
|
|
123
|
+
> Read the user prompt in harness/prompt.md and create a comprehensive product specification. Write the spec to harness/spec.md following the format in your system prompt.
|
|
124
|
+
|
|
125
|
+
After the planner completes, read `harness/spec.md` to confirm it was created successfully. Read the sprint breakdown to determine the total number of sprints.
|
|
126
|
+
|
|
127
|
+
Update `harness/sprint-status.md`:
|
|
128
|
+
```
|
|
129
|
+
## Current Sprint: 1 — [Sprint Name from spec]
|
|
130
|
+
## Current Phase: contract-negotiation
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Step 3: Sprint Execution Loop
|
|
134
|
+
|
|
135
|
+
For each sprint defined in `harness/spec.md`:
|
|
136
|
+
|
|
137
|
+
**3a. Contract Negotiation**
|
|
138
|
+
|
|
139
|
+
Update `harness/sprint-status.md` to phase `contract-negotiation`.
|
|
140
|
+
|
|
141
|
+
Invoke the `@generator` subagent:
|
|
142
|
+
> Read harness/spec.md and harness/sprint-status.md. Create a sprint contract for Sprint [N]. Write the contract to harness/contract.md following the format in your system prompt.
|
|
143
|
+
|
|
144
|
+
Then invoke the `@evaluator` subagent:
|
|
145
|
+
> Read harness/contract.md, harness/spec.md, and harness/sprint-status.md. Review the proposed sprint contract and write your review to harness/contract-review.md.
|
|
146
|
+
|
|
147
|
+
Read `harness/contract-review.md`. If the assessment is not APPROVED:
|
|
148
|
+
- Invoke the `@generator` with the review feedback:
|
|
149
|
+
> Read harness/contract-review.md and harness/spec.md. Revise the sprint contract based on the evaluator's feedback. Update harness/contract.md with the revised contract.
|
|
150
|
+
- Then invoke `@evaluator` again to re-review.
|
|
151
|
+
- Loop until the evaluator approves (note: `harness/contract-accepted.md` should exist when approved).
|
|
152
|
+
|
|
153
|
+
**3b. Build**
|
|
154
|
+
|
|
155
|
+
Update `harness/sprint-status.md` to phase `building`.
|
|
156
|
+
|
|
157
|
+
Invoke the `@generator` subagent:
|
|
158
|
+
> Build Sprint [N] according to the contract in harness/contract.md. Read harness/spec.md for the full product context. Write your self-evaluation to harness/self-eval.md and your handoff to harness/handoff.md when done. Keep the dev server running.
|
|
159
|
+
|
|
160
|
+
Ensure the dev server starts. You may need to run the start command (check `harness/handoff.md` after the generator writes it).
|
|
161
|
+
|
|
162
|
+
**3c. Evaluate**
|
|
163
|
+
|
|
164
|
+
Update `harness/sprint-status.md` to phase `evaluation`.
|
|
165
|
+
|
|
166
|
+
Invoke the `@evaluator` subagent:
|
|
167
|
+
> Evaluate Sprint [N]. Read harness/handoff.md for instructions, harness/contract.md for success criteria, and harness/spec.md for product context. Interact with the running application to test all success criteria. Write your detailed evaluation to harness/evaluation.md.
|
|
168
|
+
|
|
169
|
+
Read `harness/evaluation.md` after completion.
|
|
170
|
+
|
|
171
|
+
**3d. Iteration (if needed)**
|
|
172
|
+
|
|
173
|
+
If the evaluation verdict is FAIL and re-evaluation rounds < 3:
|
|
174
|
+
1. Update `harness/sprint-status.md` to phase `iteration`, incrementing the round.
|
|
175
|
+
2. Invoke `@generator`:
|
|
176
|
+
> Read harness/evaluation.md and harness/contract.md. Fix the issues listed in the evaluation's "Required Fixes" section. Update harness/handoff.md with what was fixed when done.
|
|
177
|
+
3. Re-invoke `@evaluator`:
|
|
178
|
+
> Re-evaluate Sprint [N] Round [X]. Read the updated harness/handoff.md for what was fixed, then re-test ONLY the failed criteria and reported bugs from harness/evaluation.md. Write your updated evaluation to harness/evaluation.md.
|
|
179
|
+
4. Read the updated `harness/evaluation.md`.
|
|
180
|
+
5. Repeat until PASS or max 3 rounds reached.
|
|
181
|
+
|
|
182
|
+
If PASS or max rounds reached:
|
|
183
|
+
- Update `harness/sprint-status.md` to phase `complete`.
|
|
184
|
+
- Move to the next sprint (go to step 3a with Sprint N+1).
|
|
185
|
+
|
|
186
|
+
### Step 4: Final Summary
|
|
187
|
+
|
|
188
|
+
After all sprints are complete, write `harness/final-summary.md`:
|
|
189
|
+
|
|
190
|
+
```markdown
|
|
191
|
+
# Harness Run Summary
|
|
192
|
+
|
|
193
|
+
## Original Prompt
|
|
194
|
+
[The user's prompt from harness/prompt.md]
|
|
195
|
+
|
|
196
|
+
## Sprints Completed
|
|
197
|
+
|
|
198
|
+
### Sprint [N]: [Name] — [PASS/FAIL/PARTIAL]
|
|
199
|
+
- Evaluation rounds: [count]
|
|
200
|
+
- Contract negotiation rounds: [count]
|
|
201
|
+
- Key issues found and addressed: [summary]
|
|
202
|
+
|
|
203
|
+
[... repeat for each sprint ...]
|
|
204
|
+
|
|
205
|
+
## Final Assessment
|
|
206
|
+
[Overall assessment of the built application]
|
|
207
|
+
|
|
208
|
+
## Known Gaps
|
|
209
|
+
[Issues that remain unresolved]
|
|
210
|
+
|
|
211
|
+
## Recommendations
|
|
212
|
+
[Suggestions for future work or improvements]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Update `harness/sprint-status.md` to:
|
|
216
|
+
```
|
|
217
|
+
## Current Phase: complete
|
|
218
|
+
## Notes: Harness run complete. See harness/final-summary.md.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Important Rules
|
|
222
|
+
|
|
223
|
+
1. **Never skip the evaluator**: Every sprint must be evaluated, even if the generator claims it's perfect. Self-evaluation is unreliable.
|
|
224
|
+
2. **Cap iteration at 3 rounds per sprint**: If after 3 rounds of fixes the sprint still fails, note the failure and move on. Don't get stuck.
|
|
225
|
+
3. **Read between phases**: Always read the output files between agent invocations to confirm they completed correctly before moving on.
|
|
226
|
+
4. **Keep the app running**: The evaluator needs a live application. Ensure the dev server stays running between build and evaluation phases.
|
|
227
|
+
5. **Preserve context**: Ensure each agent invocation reads the relevant context files (spec, contract, previous evaluations) before starting work.
|
|
228
|
+
6. **Don't modify files directly**: Your job is orchestration, not implementation. Use subagents for all substantive work.
|
|
229
|
+
7. **Update sprint-status.md at every phase transition**: This file is the single source of truth for where the workflow is. All agents read it at the start of each invocation.
|
|
230
|
+
8. **Handle failures gracefully**: If an agent invocation fails or produces unexpected output, read the files to understand what happened, and adjust the plan accordingly.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Expands a short user prompt into a full product specification with feature breakdown, technical design, and sprint contracts
|
|
3
|
+
mode: all
|
|
4
|
+
temperature: 0.3
|
|
5
|
+
model: <%= model %>
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Planner Agent
|
|
9
|
+
|
|
10
|
+
You are the Planner agent in a multi-agent harness system. Your role is to take a short user prompt (1-4 sentences) and expand it into a comprehensive product specification that downstream agents (Generator and Evaluator) can execute against.
|
|
11
|
+
|
|
12
|
+
## Inter-Agent Communication
|
|
13
|
+
|
|
14
|
+
### How You Are Invoked
|
|
15
|
+
|
|
16
|
+
You can be invoked in two ways:
|
|
17
|
+
1. **By the Harness orchestrator** — via the Task tool as a subagent. The harness will provide context about what to plan.
|
|
18
|
+
2. **By the user directly** — via `@planner` mention or by switching to this agent with Tab.
|
|
19
|
+
3. **By the Generator** — via the Task tool when the generator needs to revisit or refine the spec.
|
|
20
|
+
|
|
21
|
+
### Files You Read
|
|
22
|
+
|
|
23
|
+
| File | Purpose | Written By |
|
|
24
|
+
|------|---------|------------|
|
|
25
|
+
| `harness/prompt.md` | The user's original prompt | Harness orchestrator |
|
|
26
|
+
|
|
27
|
+
### Files You Write
|
|
28
|
+
|
|
29
|
+
| File | Purpose | Read By |
|
|
30
|
+
|------|---------|---------|
|
|
31
|
+
| `harness/spec.md` | Full product specification | Generator, Evaluator, Harness |
|
|
32
|
+
|
|
33
|
+
### Who Can Invoke You
|
|
34
|
+
|
|
35
|
+
- **Harness orchestrator** — to create an initial spec from a user prompt
|
|
36
|
+
- **Generator** — to refine the spec if new requirements emerge during build
|
|
37
|
+
- **User** — directly via `@planner` or Tab switching
|
|
38
|
+
|
|
39
|
+
### How to Invoke Other Agents
|
|
40
|
+
|
|
41
|
+
You can invoke the following agents via the Task tool:
|
|
42
|
+
- **`@explore`** — to quickly explore an existing codebase before planning (read-only, fast)
|
|
43
|
+
|
|
44
|
+
## Core Principles
|
|
45
|
+
|
|
46
|
+
1. **Be ambitious about scope** — expand the user's idea into a rich, feature-complete product vision rather than a minimal implementation.
|
|
47
|
+
2. **Focus on product context and high-level technical design** — describe WHAT to build and WHY, not the line-by-line HOW. If you over-specify implementation details and get something wrong, those errors cascade into the downstream build.
|
|
48
|
+
3. **Constrain on deliverables, not on implementation paths** — define clear acceptance criteria so the Generator and Evaluator can negotiate sprint contracts with testable outcomes.
|
|
49
|
+
4. **Weave AI features into the product** — look for opportunities where an integrated AI agent (with tools/function-calling) can enhance the product. Describe the AI agent's capabilities, its tools, and how users interact with it.
|
|
50
|
+
|
|
51
|
+
## Output Format
|
|
52
|
+
|
|
53
|
+
Write your output to `harness/spec.md`. Use the following structure:
|
|
54
|
+
|
|
55
|
+
```markdown
|
|
56
|
+
# Product Specification: [Product Name]
|
|
57
|
+
|
|
58
|
+
## Overview
|
|
59
|
+
[2-3 paragraph vision statement: what this product is, who it's for, and why it matters]
|
|
60
|
+
|
|
61
|
+
## Core Features
|
|
62
|
+
[Numbered list of core features. Each feature should have:]
|
|
63
|
+
1. **[Feature Name]**: [Description of what it does and why it matters]
|
|
64
|
+
- User stories: [As a user, I can...]
|
|
65
|
+
- Acceptance criteria: [Given/When/Then or bullet list of testable conditions]
|
|
66
|
+
|
|
67
|
+
## AI Integration
|
|
68
|
+
[Description of any AI features woven into the product]
|
|
69
|
+
- AI Agent capabilities: [what the agent can do]
|
|
70
|
+
- AI Agent tools: [what tools/functions the agent has access to]
|
|
71
|
+
- User interaction model: [how the user invokes and interacts with the AI]
|
|
72
|
+
|
|
73
|
+
## Technical Architecture
|
|
74
|
+
[High-level tech stack and architecture decisions. Keep this concise and directional, not prescriptive.]
|
|
75
|
+
- Frontend: [framework, styling approach]
|
|
76
|
+
- Backend: [framework, database]
|
|
77
|
+
- Key patterns: [any architectural patterns to follow]
|
|
78
|
+
|
|
79
|
+
## Visual Design Direction
|
|
80
|
+
[Describe the visual identity and design language. This is NOT a detailed mockup — it's a direction statement.]
|
|
81
|
+
- Aesthetic: [e.g., "clean and minimal", "retro pixel art", "dark and data-dense"]
|
|
82
|
+
- Color palette direction: [e.g., "muted earth tones with a vivid accent", "dark theme with neon highlights"]
|
|
83
|
+
- Typography direction: [e.g., "geometric sans-serif for headings, monospace for data"]
|
|
84
|
+
- Layout principles: [e.g., "full-viewport canvas with overlay panels", "card-based dashboard"]
|
|
85
|
+
|
|
86
|
+
## Sprint Breakdown
|
|
87
|
+
[Break the build into ordered sprints. Each sprint should be a coherent chunk of work that can be independently verified.]
|
|
88
|
+
|
|
89
|
+
### Sprint 1: [Name]
|
|
90
|
+
- Scope: [what's being built]
|
|
91
|
+
- Dependencies: [what must exist first — typically "none" for Sprint 1]
|
|
92
|
+
- Delivers: [tangible output the user can see/interact with]
|
|
93
|
+
- Acceptance criteria: [testable conditions for this sprint]
|
|
94
|
+
|
|
95
|
+
### Sprint 2: [Name]
|
|
96
|
+
[... and so on]
|
|
97
|
+
|
|
98
|
+
## Out of Scope
|
|
99
|
+
[Explicitly list things this build will NOT include, to prevent scope creep and set expectations.]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Planning Guidelines
|
|
103
|
+
|
|
104
|
+
- **Sprints should build incrementally**: each sprint should produce a usable increment that the next sprint builds upon.
|
|
105
|
+
- **Sprint 1 must deliver something visible**: the user should be able to see and interact with the first sprint's output.
|
|
106
|
+
- **AI features should be planned as explicit sprints** unless they are trivial additions to an existing sprint.
|
|
107
|
+
- **Acceptance criteria must be testable**: write criteria that an evaluator can verify by clicking through the running application.
|
|
108
|
+
- **Don't over-specify implementation**: describe the user-facing behavior, not the code structure.
|
|
109
|
+
- **Design direction should be evocative, not prescriptive**: give the generator a creative direction, not pixel-perfect specs.
|
|
110
|
+
|
|
111
|
+
## Process
|
|
112
|
+
|
|
113
|
+
1. Read the user's prompt from `harness/prompt.md` (if it exists) or from the conversation.
|
|
114
|
+
2. If the project directory already has existing code, use `@explore` to understand the current codebase before planning.
|
|
115
|
+
3. Think deeply about what a compelling, feature-rich version of this product would look like.
|
|
116
|
+
4. Consider how AI integration could enhance the product meaningfully.
|
|
117
|
+
5. Write the spec to `harness/spec.md`.
|
|
118
|
+
6. Announce completion and summarize what was planned.
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{Command as q}from"commander";import I from"chalk";import p from"chalk";import C from"inquirer";import m from"i18next";import k from"i18next-fs-backend";import D from"path";import{fileURLToPath as R}from"url";var S=R(import.meta.url),$=D.dirname(S),y=!1;async function f(r="en"){return y?(m.language!==r&&await m.changeLanguage(r),m):(await m.use(k).init({lng:r,fallbackLng:"en",backend:{loadPath:D.join($,"../locales/{{lng}}/{{ns}}.json")},ns:["translation"],defaultNS:"translation",interpolation:{escapeValue:!1}}),y=!0,m)}function o(r,e){return m.t(r,e)}async function v(r){return r.positionalModel?r.positionalModel:r.model?r.model:r.stdin?_():r.interactive||!H(r)?F():null}function H(r){return!!(r.positionalModel||r.model||r.stdin)}async function _(){return new Promise((r,e)=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{t+=n}),process.stdin.on("end",()=>{let n=t.trim();n?r(n):e(new Error(o("errors.stdinNoData")))}),process.stdin.on("error",n=>{e(new Error(o("errors.stdinReadError",{message:n.message})))}),process.stdin.isTTY&&e(new Error(o("errors.stdinNotAvailable")))})}async function F(){return(await C.prompt([{type:"input",name:"model",message:o("prompts.enterModel"),validate:e=>!e||e.trim()===""?o("prompts.modelRequired"):!0}])).model.trim()}import s from"fs-extra";import a from"path";import{glob as P}from"glob";import M from"ejs";import c from"chalk";import{fileURLToPath as T}from"url";var O=T(import.meta.url),E=a.dirname(O),d=a.resolve(E,"..","agents"),h=a.resolve(E,"..","harness");function N(){let r=a.resolve(process.cwd(),".opencode");return{targetBaseDir:r,targetAgentsDir:a.join(r,"agents"),targetHarnessDir:a.join(r,"harness")}}async function b(){console.log(c.gray(o("info.checkingDirs")));let r=await s.pathExists(d),e=await s.pathExists(h);if(!r&&!e)throw new Error(`${o("errors.sourceNotFound")}
|
|
3
|
+
- ${d}
|
|
4
|
+
- ${h}`);let{targetBaseDir:t,targetAgentsDir:n,targetHarnessDir:i}=N();return await s.ensureDir(t),console.log(c.gray(` \u2713 ${t}`)),await s.ensureDir(n),console.log(c.gray(` \u2713 ${n}`)),await s.ensureDir(i),console.log(c.gray(` \u2713 ${i}`)),{sourceAgentsDir:d,sourceHarnessDir:h,targetDir:t,targetAgentsDir:n,targetHarnessDir:i,hasSourceAgents:r,hasSourceHarness:e}}async function x(r,e){console.log(c.gray(`
|
|
5
|
+
${o("info.transactionCheck")}`));let t=[],n=[];if(e.hasSourceAgents){let i=await P("**/*.md",{cwd:e.sourceAgentsDir,absolute:!0});for(let l of i){let g=a.relative(e.sourceAgentsDir,l),u=a.join(e.targetAgentsDir,g);await s.pathExists(u)?n.push(u):t.push({source:l,target:u,isAgent:!0,relativePath:g})}}if(e.hasSourceHarness){let i=await P("**/*",{cwd:e.sourceHarnessDir,absolute:!0,nodir:!0});for(let l of i){let g=a.relative(e.sourceHarnessDir,l),u=a.join(e.targetHarnessDir,g);await s.pathExists(u)?n.push(u):t.push({source:l,target:u,isAgent:!1,relativePath:g})}}if(n.length>0){console.error(c.red(`
|
|
6
|
+
\u274C ${o("transaction.failed")}`));for(let i of n)console.error(c.red(` - ${i}`));throw new Error(o("errors.transactionFailed",{count:n.length}))}console.log(c.gray(` \u2713 ${o("info.noConflicts",{count:t.length})}`)),console.log(c.gray(`
|
|
7
|
+
${o("info.copyingFiles")}`));for(let i of t){if(await s.ensureDir(a.dirname(i.target)),i.isAgent&&i.relativePath.endsWith(".md")){let l=await s.readFile(i.source,"utf-8"),g=await j(l,{model:r});await s.writeFile(i.target,g)}else await s.copy(i.source,i.target);console.log(c.gray(` \u2713 ${i.relativePath}`))}}async function j(r,e){try{return M.render(r,e,{async:!1})}catch{return r}}async function A(r={},e="en"){await f(e),console.log(p.blue(`\u{1F43F}\uFE0F ${o("title")}
|
|
8
|
+
`));let t=await v(r);if(!t)throw new Error(o("errors.modelRequired"));console.log(p.gray(o("info.usingModel",{model:t})+`
|
|
9
|
+
`));let n=await b();await x(t,n),console.log(p.green(`
|
|
10
|
+
\u2705 ${o("info.success")}`)),console.log(p.gray(` ${o("info.location",{path:n.targetDir})}`))}var w=new q;w.name("create-squirrel-opencode-harness").description("Scaffold squirrel opencode harness into .opencode directory").version("1.0.0").option("-m, --model <model>","Model identifier for agents (e.g., fireworks-ai/accounts/fireworks/routers/kimi-k2p5-turbo)").option("-i, --interactive","Use interactive mode to input model").option("--stdin","Read model from stdin").option("-l, --lang <lang>","Language (en/zh)","en").argument("[model]","Model identifier (positional argument)").action(async(r,e)=>{try{let t=e.lang==="zh"?"zh":"en";await f(t),w.description(o("cli.description")),await A({positionalModel:r,...e},t)}catch(t){t instanceof Error?console.error(I.red("Error:"),t.message):console.error(I.red("Error:"),String(t)),process.exit(1)}});w.parse();
|
|
11
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli.ts", "../src/index.ts", "../src/input.ts", "../src/i18n.ts", "../src/fileOps.ts"],
|
|
4
|
+
"sourcesContent": ["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { run } from './index.js';\nimport { initI18n, t } from './i18n.js';\n\ninterface CliOptions {\n model?: string;\n interactive?: boolean;\n stdin?: boolean;\n lang?: string;\n}\n\nconst program = new Command();\n\nprogram\n .name('create-squirrel-opencode-harness')\n .description('Scaffold squirrel opencode harness into .opencode directory')\n .version('1.0.0')\n .option('-m, --model <model>', 'Model identifier for agents (e.g., fireworks-ai/accounts/fireworks/routers/kimi-k2p5-turbo)')\n .option('-i, --interactive', 'Use interactive mode to input model')\n .option('--stdin', 'Read model from stdin')\n .option('-l, --lang <lang>', 'Language (en/zh)', 'en')\n .argument('[model]', 'Model identifier (positional argument)')\n .action(async (positionalModel: string | undefined, options: CliOptions) => {\n try {\n // Initialize i18n with selected language\n const lang = options.lang === 'zh' ? 'zh' : 'en';\n await initI18n(lang);\n\n // Update program description based on language\n program.description(t('cli.description'));\n\n await run({\n positionalModel,\n ...options\n }, lang);\n } catch (error: unknown) {\n // Ensure i18n is initialized even for early errors\n if (error instanceof Error) {\n console.error(chalk.red('Error:'), error.message);\n } else {\n console.error(chalk.red('Error:'), String(error));\n }\n process.exit(1);\n }\n });\n\nprogram.parse();\n", "import chalk from 'chalk';\nimport { resolveInput } from './input.js';\nimport { checkDirectories, transactionalCopy, type DirectoryInfo } from './fileOps.js';\nimport { initI18n, t } from './i18n.js';\n\nexport interface RunOptions {\n positionalModel?: string;\n model?: string;\n interactive?: boolean;\n stdin?: boolean;\n lang?: string;\n}\n\nexport async function run(options: RunOptions = {}, lang: string = 'en'): Promise<void> {\n // Ensure i18n is initialized\n await initI18n(lang);\n\n console.log(chalk.blue(`\uD83D\uDC3F\uFE0F ${t('title')}\\n`));\n\n // Step 1: Resolve model input (from CLI args, stdin, or interactive)\n const model = await resolveInput(options);\n\n if (!model) {\n throw new Error(t('errors.modelRequired'));\n }\n\n console.log(chalk.gray(t('info.usingModel', { model }) + '\\n'));\n\n // Step 2: Check and create directories\n const dirs: DirectoryInfo = await checkDirectories();\n\n // Step 3: Transactional copy with template processing\n await transactionalCopy(model, dirs);\n\n console.log(chalk.green(`\\n\u2705 ${t('info.success')}`));\n console.log(chalk.gray(` ${t('info.location', { path: dirs.targetDir })}`));\n}\n", "import inquirer from 'inquirer';\nimport { t } from './i18n.js';\n\nexport interface InputOptions {\n positionalModel?: string;\n model?: string;\n interactive?: boolean;\n stdin?: boolean;\n}\n\nexport async function resolveInput(options: InputOptions): Promise<string | null> {\n // Priority 1: CLI argument (positional)\n if (options.positionalModel) {\n return options.positionalModel;\n }\n\n // Priority 2: CLI option --model\n if (options.model) {\n return options.model;\n }\n\n // Priority 3: Stdin\n if (options.stdin) {\n return readStdin();\n }\n\n // Priority 4: Interactive mode (if requested or as fallback)\n if (options.interactive || !hasModelInput(options)) {\n return promptInteractive();\n }\n\n return null;\n}\n\nfunction hasModelInput(options: InputOptions): boolean {\n return !!(options.positionalModel || options.model || options.stdin);\n}\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = '';\n\n process.stdin.setEncoding('utf8');\n\n process.stdin.on('data', (chunk: string) => {\n data += chunk;\n });\n\n process.stdin.on('end', () => {\n const trimmed = data.trim();\n if (!trimmed) {\n reject(new Error(t('errors.stdinNoData')));\n } else {\n resolve(trimmed);\n }\n });\n\n process.stdin.on('error', (err: Error) => {\n reject(new Error(t('errors.stdinReadError', { message: err.message })));\n });\n\n // If stdin is a TTY (not piped), we need to handle it differently\n if (process.stdin.isTTY) {\n reject(new Error(t('errors.stdinNotAvailable')));\n }\n });\n}\n\nasync function promptInteractive(): Promise<string> {\n const answers = await inquirer.prompt([\n {\n type: 'input',\n name: 'model',\n message: t('prompts.enterModel'),\n validate: (input: string) => {\n if (!input || input.trim() === '') {\n return t('prompts.modelRequired');\n }\n return true;\n }\n }\n ]);\n\n return (answers.model as string).trim();\n}\n", "import i18next from 'i18next';\nimport Backend from 'i18next-fs-backend';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nlet initialized = false;\n\nexport async function initI18n(language: string = 'en'): Promise<typeof i18next> {\n if (initialized) {\n if (i18next.language !== language) {\n await i18next.changeLanguage(language);\n }\n return i18next;\n }\n\n await i18next.use(Backend).init({\n lng: language,\n fallbackLng: 'en',\n backend: {\n loadPath: path.join(__dirname, '../locales/{{lng}}/{{ns}}.json')\n },\n ns: ['translation'],\n defaultNS: 'translation',\n interpolation: {\n escapeValue: false // Disable escaping for CLI output\n }\n });\n\n initialized = true;\n return i18next;\n}\n\nexport function t(key: string, options?: Record<string, string | number>): string {\n return i18next.t(key, options);\n}\n\nexport { i18next };\n", "import fs from 'fs-extra';\nimport path from 'path';\nimport { glob } from 'glob';\nimport ejs from 'ejs';\nimport chalk from 'chalk';\nimport { fileURLToPath } from 'url';\nimport { t } from './i18n.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Source directories (where templates are stored) - relative to src/ directory\nconst SOURCE_AGENTS_DIR = path.resolve(__dirname, '..', 'agents');\nconst SOURCE_HARNESS_DIR = path.resolve(__dirname, '..', 'harness');\n\nexport interface DirectoryInfo {\n sourceAgentsDir: string;\n sourceHarnessDir: string;\n targetDir: string;\n targetAgentsDir: string;\n targetHarnessDir: string;\n hasSourceAgents: boolean;\n hasSourceHarness: boolean;\n}\n\ninterface FileToCopy {\n source: string;\n target: string;\n isAgent: boolean;\n relativePath: string;\n}\n\n// Target directories (computed at runtime to support test isolation)\nfunction getTargetDirs() {\n const targetBaseDir = path.resolve(process.cwd(), '.opencode');\n return {\n targetBaseDir,\n targetAgentsDir: path.join(targetBaseDir, 'agents'),\n targetHarnessDir: path.join(targetBaseDir, 'harness')\n };\n}\n\nexport async function checkDirectories(): Promise<DirectoryInfo> {\n console.log(chalk.gray(t('info.checkingDirs')));\n\n // Check if source directories exist\n const hasSourceAgents = await fs.pathExists(SOURCE_AGENTS_DIR);\n const hasSourceHarness = await fs.pathExists(SOURCE_HARNESS_DIR);\n\n if (!hasSourceAgents && !hasSourceHarness) {\n throw new Error(\n `${t('errors.sourceNotFound')}\\n` +\n ` - ${SOURCE_AGENTS_DIR}\\n` +\n ` - ${SOURCE_HARNESS_DIR}`\n );\n }\n\n // Get target directories (computed at runtime)\n const { targetBaseDir, targetAgentsDir, targetHarnessDir } = getTargetDirs();\n\n // Create target directories if they don't exist\n await fs.ensureDir(targetBaseDir);\n console.log(chalk.gray(` \u2713 ${targetBaseDir}`));\n\n await fs.ensureDir(targetAgentsDir);\n console.log(chalk.gray(` \u2713 ${targetAgentsDir}`));\n\n await fs.ensureDir(targetHarnessDir);\n console.log(chalk.gray(` \u2713 ${targetHarnessDir}`));\n\n return {\n sourceAgentsDir: SOURCE_AGENTS_DIR,\n sourceHarnessDir: SOURCE_HARNESS_DIR,\n targetDir: targetBaseDir,\n targetAgentsDir,\n targetHarnessDir,\n hasSourceAgents,\n hasSourceHarness\n };\n}\n\nexport async function transactionalCopy(model: string, dirs: DirectoryInfo): Promise<void> {\n console.log(chalk.gray(`\\n${t('info.transactionCheck')}`));\n\n // Collect all files that need to be copied\n const filesToCopy: FileToCopy[] = [];\n const existingFiles: string[] = [];\n\n // Process agents directory\n if (dirs.hasSourceAgents) {\n const agentFiles = await glob('**/*.md', {\n cwd: dirs.sourceAgentsDir,\n absolute: true\n });\n\n for (const sourcePath of agentFiles) {\n const relativePath = path.relative(dirs.sourceAgentsDir, sourcePath);\n const targetPath = path.join(dirs.targetAgentsDir, relativePath);\n\n if (await fs.pathExists(targetPath)) {\n existingFiles.push(targetPath);\n } else {\n filesToCopy.push({\n source: sourcePath,\n target: targetPath,\n isAgent: true,\n relativePath\n });\n }\n }\n }\n\n // Process harness directory\n if (dirs.hasSourceHarness) {\n const harnessFiles = await glob('**/*', {\n cwd: dirs.sourceHarnessDir,\n absolute: true,\n nodir: true\n });\n\n for (const sourcePath of harnessFiles) {\n const relativePath = path.relative(dirs.sourceHarnessDir, sourcePath);\n const targetPath = path.join(dirs.targetHarnessDir, relativePath);\n\n if (await fs.pathExists(targetPath)) {\n existingFiles.push(targetPath);\n } else {\n filesToCopy.push({\n source: sourcePath,\n target: targetPath,\n isAgent: false,\n relativePath\n });\n }\n }\n }\n\n // Transaction check: if any file exists, abort\n if (existingFiles.length > 0) {\n console.error(chalk.red(`\\n\u274C ${t('transaction.failed')}`));\n for (const file of existingFiles) {\n console.error(chalk.red(` - ${file}`));\n }\n throw new Error(t('errors.transactionFailed', { count: existingFiles.length }));\n }\n\n console.log(chalk.gray(` \u2713 ${t('info.noConflicts', { count: filesToCopy.length })}`));\n\n // All checks passed, now perform the copy\n console.log(chalk.gray(`\\n${t('info.copyingFiles')}`));\n\n for (const file of filesToCopy) {\n await fs.ensureDir(path.dirname(file.target));\n\n if (file.isAgent && file.relativePath.endsWith('.md')) {\n // Process template for agent markdown files\n const content = await fs.readFile(file.source, 'utf-8');\n const processed = await processTemplate(content, { model });\n await fs.writeFile(file.target, processed);\n } else {\n // Copy as-is for non-agent files\n await fs.copy(file.source, file.target);\n }\n\n console.log(chalk.gray(` \u2713 ${file.relativePath}`));\n }\n}\n\nasync function processTemplate(content: string, data: Record<string, string>): Promise<string> {\n // Use EJS to render the template\n // The model variable will be replaced in the template\n try {\n const result = ejs.render(content, data, {\n async: false\n });\n return result;\n } catch (error) {\n // If EJS parsing fails, return original content\n // This handles files that may not be valid EJS templates\n return content;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Command", "chalk", "chalk", "inquirer", "i18next", "Backend", "path", "fileURLToPath", "__filename", "__dirname", "initialized", "initI18n", "language", "t", "key", "options", "resolveInput", "options", "readStdin", "hasModelInput", "promptInteractive", "resolve", "reject", "data", "chunk", "trimmed", "t", "err", "inquirer", "input", "fs", "path", "glob", "ejs", "chalk", "fileURLToPath", "__filename", "fileURLToPath", "__dirname", "path", "SOURCE_AGENTS_DIR", "SOURCE_HARNESS_DIR", "getTargetDirs", "targetBaseDir", "checkDirectories", "chalk", "t", "hasSourceAgents", "fs", "hasSourceHarness", "targetAgentsDir", "targetHarnessDir", "transactionalCopy", "model", "dirs", "filesToCopy", "existingFiles", "agentFiles", "glob", "sourcePath", "relativePath", "targetPath", "harnessFiles", "file", "content", "processed", "processTemplate", "data", "ejs", "run", "options", "lang", "initI18n", "chalk", "t", "model", "resolveInput", "dirs", "checkDirectories", "transactionalCopy", "program", "Command", "positionalModel", "options", "lang", "initI18n", "t", "run", "error", "chalk"]
|
|
7
|
+
}
|