@nova286/nova-workflow 0.2.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 +246 -0
- package/dist/cli/commands/archive.d.ts +1 -0
- package/dist/cli/commands/archive.js +120 -0
- package/dist/cli/commands/archive.js.map +1 -0
- package/dist/cli/commands/context.d.ts +1 -0
- package/dist/cli/commands/context.js +23 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/guard.d.ts +1 -0
- package/dist/cli/commands/guard.js +21 -0
- package/dist/cli/commands/guard.js.map +1 -0
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.js +22 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/status.d.ts +1 -0
- package/dist/cli/commands/status.js +72 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/error-handler.d.ts +1 -0
- package/dist/cli/error-handler.js +18 -0
- package/dist/cli/error-handler.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui.d.ts +10 -0
- package/dist/cli/ui.js +21 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/cli-core/__tests__/context-generator.test.d.ts +1 -0
- package/dist/cli-core/__tests__/context-generator.test.js +97 -0
- package/dist/cli-core/__tests__/context-generator.test.js.map +1 -0
- package/dist/cli-core/__tests__/dispatcher.test.d.ts +1 -0
- package/dist/cli-core/__tests__/dispatcher.test.js +99 -0
- package/dist/cli-core/__tests__/dispatcher.test.js.map +1 -0
- package/dist/cli-core/__tests__/guard.test.d.ts +1 -0
- package/dist/cli-core/__tests__/guard.test.js +136 -0
- package/dist/cli-core/__tests__/guard.test.js.map +1 -0
- package/dist/cli-core/__tests__/init-manager.test.d.ts +1 -0
- package/dist/cli-core/__tests__/init-manager.test.js +150 -0
- package/dist/cli-core/__tests__/init-manager.test.js.map +1 -0
- package/dist/cli-core/__tests__/pipeline.test.d.ts +1 -0
- package/dist/cli-core/__tests__/pipeline.test.js +119 -0
- package/dist/cli-core/__tests__/pipeline.test.js.map +1 -0
- package/dist/cli-core/__tests__/project-detect.test.d.ts +1 -0
- package/dist/cli-core/__tests__/project-detect.test.js +92 -0
- package/dist/cli-core/__tests__/project-detect.test.js.map +1 -0
- package/dist/cli-core/__tests__/state-manager.test.d.ts +1 -0
- package/dist/cli-core/__tests__/state-manager.test.js +120 -0
- package/dist/cli-core/__tests__/state-manager.test.js.map +1 -0
- package/dist/cli-core/adapters/claude-code.d.ts +6 -0
- package/dist/cli-core/adapters/claude-code.js +311 -0
- package/dist/cli-core/adapters/claude-code.js.map +1 -0
- package/dist/cli-core/context-generator.d.ts +4 -0
- package/dist/cli-core/context-generator.js +81 -0
- package/dist/cli-core/context-generator.js.map +1 -0
- package/dist/cli-core/dispatcher.d.ts +11 -0
- package/dist/cli-core/dispatcher.js +169 -0
- package/dist/cli-core/dispatcher.js.map +1 -0
- package/dist/cli-core/guard.d.ts +1 -0
- package/dist/cli-core/guard.js +57 -0
- package/dist/cli-core/guard.js.map +1 -0
- package/dist/cli-core/init-manager.d.ts +25 -0
- package/dist/cli-core/init-manager.js +182 -0
- package/dist/cli-core/init-manager.js.map +1 -0
- package/dist/cli-core/pipeline.d.ts +7 -0
- package/dist/cli-core/pipeline.js +79 -0
- package/dist/cli-core/pipeline.js.map +1 -0
- package/dist/cli-core/platform-client.d.ts +19 -0
- package/dist/cli-core/platform-client.js +119 -0
- package/dist/cli-core/platform-client.js.map +1 -0
- package/dist/cli-core/project-detect.d.ts +1 -0
- package/dist/cli-core/project-detect.js +64 -0
- package/dist/cli-core/project-detect.js.map +1 -0
- package/dist/cli-core/state.d.ts +11 -0
- package/dist/cli-core/state.js +106 -0
- package/dist/cli-core/state.js.map +1 -0
- package/dist/cli-core/types.d.ts +141 -0
- package/dist/cli-core/types.js +13 -0
- package/dist/cli-core/types.js.map +1 -0
- package/package.json +33 -0
- package/templates/docs/design.md +41 -0
- package/templates/docs/proposal.md +25 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ClaudeCodeAdapter = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const SKILL_TEMPLATES = {
|
|
40
|
+
'nova.md': `---
|
|
41
|
+
description: Nova — unified entry point. Shows progress and suggests next action.
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
# Nova
|
|
45
|
+
|
|
46
|
+
Read \`.nova.yaml\` and present a compact overview with a clear next action.
|
|
47
|
+
|
|
48
|
+
## Step 1: Read State
|
|
49
|
+
Parse \`.nova.yaml\`. For each phase, determine status (pending / in-progress / done).
|
|
50
|
+
If \`.nova.yaml\` does not exist, say: "Nova not initialized. Run \`nova init\` first."
|
|
51
|
+
|
|
52
|
+
## Step 2: Show Overview
|
|
53
|
+
\`\`\`
|
|
54
|
+
Nova · <project-name>
|
|
55
|
+
────────────────────────────────────────
|
|
56
|
+
propose [done] docs/proposals/proposal.md
|
|
57
|
+
design [done] docs/designs/design.md · 6 tasks
|
|
58
|
+
implement [in-progress] 3/6 tasks done
|
|
59
|
+
verify [pending]
|
|
60
|
+
archive [pending]
|
|
61
|
+
────────────────────────────────────────
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
## Step 3: Suggest Next Action
|
|
65
|
+
Based on the first phase that is NOT done:
|
|
66
|
+
- propose: pending → "/nova-propose — Start with a proposal"
|
|
67
|
+
- design: pending → "/nova-design — Create technical design"
|
|
68
|
+
- implement: pending → "/nova-implement — Start implementing"
|
|
69
|
+
- verify: pending → "/nova-verify — Run review pipeline"
|
|
70
|
+
- all done → "nova archive — Finalize project"
|
|
71
|
+
|
|
72
|
+
Show: "Next: <suggestion>"
|
|
73
|
+
Also list: /nova-propose /nova-design /nova-implement /nova-verify /nova-iterate /nova-status
|
|
74
|
+
|
|
75
|
+
## Step 4: Act
|
|
76
|
+
Ask: "Run the suggested action, pick another, or do something else?"
|
|
77
|
+
|
|
78
|
+
## Constraints
|
|
79
|
+
Read-only unless the user explicitly confirms an action.
|
|
80
|
+
`,
|
|
81
|
+
'nova-propose.md': `---
|
|
82
|
+
description: Nova propose phase — generate a feature proposal from interactive Q&A
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
# Nova Propose Phase
|
|
86
|
+
|
|
87
|
+
You are executing the **propose phase** of a Nova workflow. Your role is to
|
|
88
|
+
orchestrate requirements exploration and produce a structured proposal document.
|
|
89
|
+
|
|
90
|
+
## Step 1: Verify State
|
|
91
|
+
Read \`.nova.yaml\`. Check \`phases.open.status\`. If pending, update to
|
|
92
|
+
\`in-progress\` and set \`startedAt\`.
|
|
93
|
+
|
|
94
|
+
## Step 2: Gather Context
|
|
95
|
+
Read \`AGENTS.md\`, \`CLAUDE.md\`, \`README.md\`, \`package.json\`, \`src/\` to
|
|
96
|
+
understand the project.
|
|
97
|
+
|
|
98
|
+
## Step 3: Explore Requirements
|
|
99
|
+
Use the **brainstorming skill** to explore the problem space: clarify the problem,
|
|
100
|
+
explore alternatives, identify risks, define success criteria. Summarize for the
|
|
101
|
+
user and ask them to confirm before proceeding.
|
|
102
|
+
|
|
103
|
+
## Step 4: Generate Proposal
|
|
104
|
+
Write \`docs/proposals/proposal.md\` with: Problem Statement, Proposed Solution,
|
|
105
|
+
User Stories (prioritized), Scope & Deliverables (in/out), Success Criteria
|
|
106
|
+
(measurable), Risks & Constraints.
|
|
107
|
+
|
|
108
|
+
## Step 5: Update State
|
|
109
|
+
Set \`phases.open.status = 'in-progress'\`,
|
|
110
|
+
\`phases.open.proposal = 'docs/proposals/proposal.md'\`.
|
|
111
|
+
|
|
112
|
+
## Constraints
|
|
113
|
+
- Read any file for context. Write only to \`docs/proposals/\` and \`.nova.yaml\`.
|
|
114
|
+
- Do not modify source code — the implement phase handles that.
|
|
115
|
+
`,
|
|
116
|
+
'nova-design.md': `---
|
|
117
|
+
description: Nova design phase — generate technical design from approved proposal
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
# Nova Design Phase
|
|
121
|
+
|
|
122
|
+
You are executing the **design phase** of a Nova workflow. Your role is to
|
|
123
|
+
orchestrate architecture exploration and produce a design document with an
|
|
124
|
+
actionable task list.
|
|
125
|
+
|
|
126
|
+
## Step 1: Verify State
|
|
127
|
+
Read \`.nova.yaml\`. Require \`phases.open.status: done\` with a non-empty proposal.
|
|
128
|
+
Update \`phases.design.status\` to \`in-progress\` and set \`startedAt\`.
|
|
129
|
+
|
|
130
|
+
## Step 2: Load Context
|
|
131
|
+
Read the proposal (\`phases.open.proposal\`), \`AGENTS.md\`, \`package.json\`, \`src/\`.
|
|
132
|
+
|
|
133
|
+
## Step 3: Explore Architecture Options
|
|
134
|
+
Use the **brainstorming skill** to explore at least 2 architectural approaches.
|
|
135
|
+
For each: architecture pattern, tech stack rationale, component structure, data
|
|
136
|
+
flow, key trade-offs. Present alternatives to the user for selection.
|
|
137
|
+
|
|
138
|
+
## Step 4: Generate Design Document
|
|
139
|
+
Based on the user-selected approach, use the **writing-plans skill** to produce
|
|
140
|
+
\`docs/designs/design.md\` with: Architecture Overview, Tech Stack, Component
|
|
141
|
+
Breakdown, Data Flow, Implementation Plan (YAML task list), Risks & Mitigations.
|
|
142
|
+
|
|
143
|
+
## Step 5: Validate Tasks
|
|
144
|
+
Verify each task has all required fields (id, title, type, description, files,
|
|
145
|
+
acceptance, priority, estimatedComplexity).
|
|
146
|
+
|
|
147
|
+
## Step 6: Update State
|
|
148
|
+
Set \`phases.design.status = 'done'\`, \`designDoc\`, \`tasks\` from parsed YAML.
|
|
149
|
+
|
|
150
|
+
## Constraints
|
|
151
|
+
- Design and plan only — no implementation code.
|
|
152
|
+
- Tasks must be concrete: specific file paths, verifiable acceptance criteria.
|
|
153
|
+
`,
|
|
154
|
+
'nova-implement.md': `---
|
|
155
|
+
description: Nova implement phase — execute design tasks with retry and tracing
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
# Nova Implement Phase
|
|
159
|
+
|
|
160
|
+
You are executing the **implement phase** of a Nova workflow. Your role is to
|
|
161
|
+
execute each task from the design phase, routing by task type.
|
|
162
|
+
|
|
163
|
+
## Step 1: Verify State
|
|
164
|
+
Read \`.nova.yaml\`. Require \`phases.design.status: done\` with non-empty tasks.
|
|
165
|
+
Update \`phases.build.status\` to \`in-progress\` and set \`startedAt\`.
|
|
166
|
+
|
|
167
|
+
## Step 2: Load Task List
|
|
168
|
+
Show task summary (id, title, type, priority). Ask user to confirm before
|
|
169
|
+
proceeding.
|
|
170
|
+
|
|
171
|
+
## Step 3: Execute Each Task
|
|
172
|
+
For each task in priority order:
|
|
173
|
+
|
|
174
|
+
### Route by Task Type
|
|
175
|
+
- **implementation** — write production code following project conventions
|
|
176
|
+
- **testing** — use the **test-driven-development skill**
|
|
177
|
+
- **design** — update design documents (noted for user review)
|
|
178
|
+
|
|
179
|
+
### Verify After Each Task
|
|
180
|
+
1. Run type check (\`npx tsc --noEmit\`)
|
|
181
|
+
2. Run tests (\`npx jest --no-coverage\`)
|
|
182
|
+
3. Fix before marking complete
|
|
183
|
+
|
|
184
|
+
### Record Result
|
|
185
|
+
Update \`.nova.yaml\` with task status (done/failed) and timestamp.
|
|
186
|
+
On failure, ask user: abort, skip, or retry.
|
|
187
|
+
|
|
188
|
+
## Step 4: Final Verification
|
|
189
|
+
Run full test suite and type check. Report summary.
|
|
190
|
+
|
|
191
|
+
## Step 5: Update State
|
|
192
|
+
Set \`phases.build.status = 'done'\`.
|
|
193
|
+
|
|
194
|
+
## Constraints
|
|
195
|
+
- Follow existing project conventions. Never leave TODOs or stubs.
|
|
196
|
+
- Run checks after EACH task, not just at the end.
|
|
197
|
+
`,
|
|
198
|
+
'nova-verify.md': `---
|
|
199
|
+
description: Nova verify phase — run code review and security review pipeline
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
# Nova Verify Phase
|
|
203
|
+
|
|
204
|
+
You are executing the **verify phase** of a Nova workflow. Your role is to
|
|
205
|
+
orchestrate a verification pipeline using ECC review skills.
|
|
206
|
+
|
|
207
|
+
## Step 1: Verify State
|
|
208
|
+
Read \`.nova.yaml\`. Require \`phases.build.status: done\`.
|
|
209
|
+
Update \`phases.verify.status\` to \`in-progress\` and set \`startedAt\`.
|
|
210
|
+
|
|
211
|
+
## Step 2: Gather Context
|
|
212
|
+
Load completed tasks from \`phases.design.tasks\`. Read changed files and the
|
|
213
|
+
design document.
|
|
214
|
+
|
|
215
|
+
## Step 3: Run Code Review
|
|
216
|
+
Use the **ecc:code-reviewer** skill to review each task's changed files:
|
|
217
|
+
correctness, conventions, error handling, test coverage, type safety.
|
|
218
|
+
Verdict: PASS / CHANGES_REQUESTED / COMMENT.
|
|
219
|
+
|
|
220
|
+
## Step 4: Run Security Review
|
|
221
|
+
Use the **ecc:security-reviewer** skill to audit each task's changed files:
|
|
222
|
+
injection risks, secret exposure, insecure dependencies, input validation.
|
|
223
|
+
Verdict: PASS / VULNERABILITY_FOUND. Include severity and remediation.
|
|
224
|
+
|
|
225
|
+
## Step 5: Generate Report
|
|
226
|
+
Write \`docs/designs/verification-report.md\` with summary, per-task results,
|
|
227
|
+
overall assessment (PASS / NEEDS_FIXES / BLOCKED), and recommendations.
|
|
228
|
+
|
|
229
|
+
## Step 6: Update State
|
|
230
|
+
Set \`phases.verify.status = 'done'\`, \`pipelineResult\` with stage results.
|
|
231
|
+
|
|
232
|
+
## Constraints
|
|
233
|
+
- Be specific — reference file paths and line numbers.
|
|
234
|
+
- Security findings must include severity and remediation.
|
|
235
|
+
`,
|
|
236
|
+
'nova-iterate.md': `---
|
|
237
|
+
description: Nova iterate — roll back to a previous phase for iteration
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
# Nova Iterate Phase
|
|
241
|
+
|
|
242
|
+
You are handling a **phase iteration** in a Nova workflow. Software development
|
|
243
|
+
is iterative — implementation reveals design gaps, verification reveals spec issues.
|
|
244
|
+
|
|
245
|
+
## Step 1: Detect Current Phase
|
|
246
|
+
Read \`.nova.yaml\`. Determine which phase is active and which earlier phases are
|
|
247
|
+
valid rollback targets.
|
|
248
|
+
|
|
249
|
+
## Step 2: Present Options
|
|
250
|
+
Show valid rollback targets. For each, explain what will be reset.
|
|
251
|
+
Ask user: which phase, why (recorded in history), keep or discard work?
|
|
252
|
+
|
|
253
|
+
## Step 3: Execute Rollback
|
|
254
|
+
- **Keep work**: Reset state only — preserve all files. Set target phase and all
|
|
255
|
+
subsequent phases to \`pending\`, clear task results and timestamps.
|
|
256
|
+
- **Discard work**: Additionally revert changed files via \`git checkout\`.
|
|
257
|
+
|
|
258
|
+
## Step 4: Record Iteration
|
|
259
|
+
Add to \`.nova.yaml\` metadata.history:
|
|
260
|
+
\`"Iterated <from> to <target>: <user's reason>"\`
|
|
261
|
+
|
|
262
|
+
## Step 5: Report Next Steps
|
|
263
|
+
Summarize what changed and which command to run next.
|
|
264
|
+
|
|
265
|
+
## Constraints
|
|
266
|
+
- Never delete code files without explicit user confirmation.
|
|
267
|
+
- Always record the iteration reason.
|
|
268
|
+
`,
|
|
269
|
+
'nova-status.md': `---
|
|
270
|
+
description: Nova status — display phase progress, task completion, and stuck detection
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
# Nova Status
|
|
274
|
+
|
|
275
|
+
Display current project status from \`.nova.yaml\`.
|
|
276
|
+
|
|
277
|
+
## Step 1: Load State
|
|
278
|
+
Read \`.nova.yaml\`. Parse all phase statuses and task results.
|
|
279
|
+
|
|
280
|
+
## Step 2: Display Summary
|
|
281
|
+
Show each phase with status icon (pending/in-progress/done), timestamps, and
|
|
282
|
+
key artifacts. For the build phase, show per-task completion.
|
|
283
|
+
|
|
284
|
+
## Step 3: Detect Issues
|
|
285
|
+
Flag: phases stuck in-progress, failed tasks, skipped guard conditions,
|
|
286
|
+
missing artifacts.
|
|
287
|
+
`,
|
|
288
|
+
};
|
|
289
|
+
class ClaudeCodeAdapter {
|
|
290
|
+
constructor() {
|
|
291
|
+
this.name = 'claude-code';
|
|
292
|
+
}
|
|
293
|
+
async setup(cwd) {
|
|
294
|
+
const dir = path.join(cwd, '.claude', 'commands');
|
|
295
|
+
await fs.mkdir(dir, { recursive: true });
|
|
296
|
+
for (const [filename, content] of Object.entries(SKILL_TEMPLATES)) {
|
|
297
|
+
await this.writeCommand(dir, filename, content);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async writeCommand(dir, file, content) {
|
|
301
|
+
const filePath = path.join(dir, file);
|
|
302
|
+
try {
|
|
303
|
+
await fs.access(filePath);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
catch { }
|
|
307
|
+
await fs.writeFile(filePath, content);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
exports.ClaudeCodeAdapter = ClaudeCodeAdapter;
|
|
311
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/cli-core/adapters/claude-code.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAkC;AAClC,2CAA6B;AAG7B,MAAM,eAAe,GAA2B;IAC9C,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCZ;IAEC,iBAAiB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCpB;IAEC,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCnB;IAEC,mBAAmB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CtB;IAEC,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCnB;IAEC,iBAAiB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCpB;IAEC,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;CAkBnB;CACA,CAAC;AAEF,MAAa,iBAAiB;IAA9B;QACE,SAAI,GAAG,aAAa,CAAC;IAavB,CAAC;IAZC,KAAK,CAAC,KAAK,CAAC,GAAW;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAClD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACO,KAAK,CAAC,YAAY,CAAC,GAAW,EAAE,IAAY,EAAE,OAAe;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YAAC,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACnD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;CACF;AAdD,8CAcC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContextGenerator = void 0;
|
|
4
|
+
const state_1 = require("./state");
|
|
5
|
+
const PROJECT_TYPE_ENV = {
|
|
6
|
+
node: { language: 'TypeScript', framework: 'Express.js', buildTool: 'npm', testFramework: 'jest' },
|
|
7
|
+
python: { language: 'Python', framework: '', buildTool: 'pip', testFramework: 'pytest' },
|
|
8
|
+
go: { language: 'Go', framework: '', buildTool: 'go', testFramework: 'testing' },
|
|
9
|
+
java: { language: 'Java', framework: 'Spring Boot', buildTool: 'maven', testFramework: 'junit' },
|
|
10
|
+
rust: { language: 'Rust', framework: '', buildTool: 'cargo', testFramework: 'cargo test' },
|
|
11
|
+
ruby: { language: 'Ruby', framework: 'Rails', buildTool: 'bundler', testFramework: 'rspec' },
|
|
12
|
+
php: { language: 'PHP', framework: 'Laravel', buildTool: 'composer', testFramework: 'phpunit' },
|
|
13
|
+
cpp: { language: 'C++', framework: '', buildTool: 'cmake', testFramework: 'gtest' },
|
|
14
|
+
csharp: { language: 'C#', framework: '.NET', buildTool: 'dotnet', testFramework: 'xunit' },
|
|
15
|
+
swift: { language: 'Swift', framework: 'SwiftUI', buildTool: 'swift', testFramework: 'XCTest' },
|
|
16
|
+
kotlin: { language: 'Kotlin', framework: 'Spring Boot', buildTool: 'gradle', testFramework: 'junit' },
|
|
17
|
+
};
|
|
18
|
+
const TYPE_MAP = {
|
|
19
|
+
implementation: 'implementation',
|
|
20
|
+
design: 'design',
|
|
21
|
+
review: 'review',
|
|
22
|
+
test: 'testing',
|
|
23
|
+
testing: 'testing',
|
|
24
|
+
security: 'security',
|
|
25
|
+
};
|
|
26
|
+
class ContextGenerator {
|
|
27
|
+
static async generateFromTask(task) {
|
|
28
|
+
const state = await state_1.StateManager.load();
|
|
29
|
+
const projectType = state.projectType || '';
|
|
30
|
+
const env = PROJECT_TYPE_ENV[projectType] || {
|
|
31
|
+
language: '',
|
|
32
|
+
framework: '',
|
|
33
|
+
buildTool: '',
|
|
34
|
+
testFramework: '',
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
taskId: task.id,
|
|
38
|
+
parentTaskId: task.parentId,
|
|
39
|
+
title: task.title,
|
|
40
|
+
description: task.description,
|
|
41
|
+
taskType: TYPE_MAP[task.type] || 'other',
|
|
42
|
+
designContext: {
|
|
43
|
+
designDocRef: state.phases.design?.designDoc || '',
|
|
44
|
+
relevantSpecs: [],
|
|
45
|
+
architectureNotes: '',
|
|
46
|
+
},
|
|
47
|
+
input: {
|
|
48
|
+
files: (task.files || []).map((f) => ({
|
|
49
|
+
path: f.path,
|
|
50
|
+
content: '',
|
|
51
|
+
action: f.action,
|
|
52
|
+
})),
|
|
53
|
+
dependencies: task.dependencies || [],
|
|
54
|
+
environment: env,
|
|
55
|
+
},
|
|
56
|
+
output: {
|
|
57
|
+
expectedArtifacts: (task.expectedArtifacts || []).map((a) => ({
|
|
58
|
+
type: a.type,
|
|
59
|
+
description: a.description,
|
|
60
|
+
pathHint: a.pathHint,
|
|
61
|
+
validation: a.validation,
|
|
62
|
+
})),
|
|
63
|
+
constraints: task.constraints || { mustPassTests: true },
|
|
64
|
+
},
|
|
65
|
+
acceptanceCriteria: task.acceptance || [],
|
|
66
|
+
guardConditions: {
|
|
67
|
+
requireReview: true,
|
|
68
|
+
requireTests: true,
|
|
69
|
+
blocking: task.blocking !== false,
|
|
70
|
+
},
|
|
71
|
+
metadata: {
|
|
72
|
+
createdBy: 'nova-build',
|
|
73
|
+
createdAt: new Date().toISOString(),
|
|
74
|
+
priority: task.priority || 'medium',
|
|
75
|
+
estimatedComplexity: task.estimatedComplexity || 5,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.ContextGenerator = ContextGenerator;
|
|
81
|
+
//# sourceMappingURL=context-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-generator.js","sourceRoot":"","sources":["../../src/cli-core/context-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PlatformClient } from './platform-client';
|
|
2
|
+
import { DispatchRequest, DispatchResult } from './types';
|
|
3
|
+
export declare class Dispatcher {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: PlatformClient);
|
|
6
|
+
static create(cwd?: string): Promise<Dispatcher>;
|
|
7
|
+
execute(request: DispatchRequest): Promise<DispatchResult>;
|
|
8
|
+
private parseOutput;
|
|
9
|
+
private validateOutput;
|
|
10
|
+
private sleep;
|
|
11
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Dispatcher = void 0;
|
|
4
|
+
const platform_client_1 = require("./platform-client");
|
|
5
|
+
function generateTraceId() {
|
|
6
|
+
const ts = Date.now().toString(36);
|
|
7
|
+
const rand = Math.random().toString(36).slice(2, 9);
|
|
8
|
+
return `nova-${ts}-${rand}`;
|
|
9
|
+
}
|
|
10
|
+
function buildPrompt(agent, context) {
|
|
11
|
+
const lines = [];
|
|
12
|
+
// 1. 指令(最核心)
|
|
13
|
+
if (context.description) {
|
|
14
|
+
lines.push(context.description);
|
|
15
|
+
lines.push('');
|
|
16
|
+
}
|
|
17
|
+
// 2. 输入文件(如有)
|
|
18
|
+
if (context.input.files.length > 0) {
|
|
19
|
+
lines.push('## Relevant Files');
|
|
20
|
+
for (const f of context.input.files) {
|
|
21
|
+
lines.push(`- ${f.path} (${f.action})${f.content ? `\n content: ${f.content}` : ''}`);
|
|
22
|
+
}
|
|
23
|
+
lines.push('');
|
|
24
|
+
}
|
|
25
|
+
// 3. 验收标准(仅当 description 未包含时追加)
|
|
26
|
+
if (context.acceptanceCriteria.length > 0 && !context.description.includes('Acceptance Criteria')) {
|
|
27
|
+
lines.push('## Acceptance Criteria');
|
|
28
|
+
for (const c of context.acceptanceCriteria) {
|
|
29
|
+
lines.push(`- ${c}`);
|
|
30
|
+
}
|
|
31
|
+
lines.push('');
|
|
32
|
+
}
|
|
33
|
+
return lines.join('\n');
|
|
34
|
+
}
|
|
35
|
+
class Dispatcher {
|
|
36
|
+
constructor(client) {
|
|
37
|
+
this.client = client;
|
|
38
|
+
}
|
|
39
|
+
static async create(cwd) {
|
|
40
|
+
const client = await (0, platform_client_1.resolvePlatformClient)(cwd);
|
|
41
|
+
return new Dispatcher(client);
|
|
42
|
+
}
|
|
43
|
+
async execute(request) {
|
|
44
|
+
const traceId = generateTraceId();
|
|
45
|
+
const startTime = new Date();
|
|
46
|
+
const maxAttempts = request.retry?.maxAttempts ?? 1;
|
|
47
|
+
const backoff = request.retry?.backoff ?? 'fixed';
|
|
48
|
+
const errors = [];
|
|
49
|
+
let lastRawOutput;
|
|
50
|
+
const prompt = buildPrompt(request.agent, request.context);
|
|
51
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
52
|
+
try {
|
|
53
|
+
const response = await this.client.sendPrompt(prompt, {
|
|
54
|
+
timeout: request.timeout,
|
|
55
|
+
model: request.model || 'sonnet',
|
|
56
|
+
effort: request.effort || 'low',
|
|
57
|
+
});
|
|
58
|
+
const output = this.parseOutput(response.content);
|
|
59
|
+
if (request.outputSchema) {
|
|
60
|
+
const valid = this.validateOutput(output, request.outputSchema);
|
|
61
|
+
if (!valid) {
|
|
62
|
+
return {
|
|
63
|
+
traceId,
|
|
64
|
+
agent: request.agent,
|
|
65
|
+
status: 'validation_error',
|
|
66
|
+
output,
|
|
67
|
+
rawOutput: response.content,
|
|
68
|
+
metadata: {
|
|
69
|
+
startTime,
|
|
70
|
+
endTime: new Date(),
|
|
71
|
+
attempts: attempt,
|
|
72
|
+
tokenUsage: response.tokenUsage,
|
|
73
|
+
},
|
|
74
|
+
errors: [{ message: `Output failed schema validation: ${request.outputSchema}` }],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
traceId,
|
|
80
|
+
agent: request.agent,
|
|
81
|
+
status: 'success',
|
|
82
|
+
output,
|
|
83
|
+
rawOutput: response.content,
|
|
84
|
+
metadata: {
|
|
85
|
+
startTime,
|
|
86
|
+
endTime: new Date(),
|
|
87
|
+
attempts: attempt,
|
|
88
|
+
tokenUsage: response.tokenUsage,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
errors.push({ message: err.message, code: err.code });
|
|
94
|
+
if (attempt < maxAttempts) {
|
|
95
|
+
await this.sleep(attempt, backoff);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
traceId,
|
|
101
|
+
agent: request.agent,
|
|
102
|
+
status: 'failed',
|
|
103
|
+
rawOutput: lastRawOutput,
|
|
104
|
+
metadata: {
|
|
105
|
+
startTime,
|
|
106
|
+
endTime: new Date(),
|
|
107
|
+
attempts: maxAttempts,
|
|
108
|
+
},
|
|
109
|
+
errors,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
parseOutput(content) {
|
|
113
|
+
try {
|
|
114
|
+
return JSON.parse(content);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return { result: content };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
validateOutput(output, schema) {
|
|
121
|
+
if (output == null)
|
|
122
|
+
return false;
|
|
123
|
+
switch (schema) {
|
|
124
|
+
case 'task-result': {
|
|
125
|
+
return typeof output === 'object' && 'result' in output;
|
|
126
|
+
}
|
|
127
|
+
case 'proposal': {
|
|
128
|
+
if (typeof output === 'string')
|
|
129
|
+
return output.length > 50;
|
|
130
|
+
if (typeof output === 'object') {
|
|
131
|
+
const o = output;
|
|
132
|
+
return typeof o.result === 'string' && o.result.length > 50;
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
case 'design': {
|
|
137
|
+
if (typeof output === 'string')
|
|
138
|
+
return output.length > 100;
|
|
139
|
+
if (typeof output === 'object') {
|
|
140
|
+
const o = output;
|
|
141
|
+
return typeof o.result === 'string' && o.result.length > 100;
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
case 'review': {
|
|
146
|
+
return typeof output === 'object' && 'verdict' in output;
|
|
147
|
+
}
|
|
148
|
+
default: {
|
|
149
|
+
// 逗号分隔字段名: 检查对象是否包含所有字段
|
|
150
|
+
if (typeof output === 'object') {
|
|
151
|
+
const required = schema.split(',').map(s => s.trim()).filter(Boolean);
|
|
152
|
+
if (required.length > 0) {
|
|
153
|
+
const o = output;
|
|
154
|
+
return required.every(field => field in o);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return typeof output === 'object' || (typeof output === 'string' && output.length > 0);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
sleep(attempt, backoff) {
|
|
162
|
+
const ms = backoff === 'exponential'
|
|
163
|
+
? Math.min(1000 * Math.pow(2, attempt - 1), 30000)
|
|
164
|
+
: 1000;
|
|
165
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.Dispatcher = Dispatcher;
|
|
169
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/cli-core/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function guardPhaseTransition(from: string, to: string): Promise<boolean>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.guardPhaseTransition = guardPhaseTransition;
|
|
4
|
+
const state_1 = require("./state");
|
|
5
|
+
const TRANSITION_RULES = {
|
|
6
|
+
'open:design': [
|
|
7
|
+
{ label: 'Proposal phase is done', check: (s) => s.phases.open?.status === 'done' },
|
|
8
|
+
{ label: 'Proposal document exists', check: (s) => !!s.phases.open?.proposal },
|
|
9
|
+
],
|
|
10
|
+
'design:build': [
|
|
11
|
+
{ label: 'Design phase is done', check: (s) => s.phases.design?.status === 'done' },
|
|
12
|
+
{ label: 'Design document exists', check: (s) => !!s.phases.design?.designDoc },
|
|
13
|
+
{
|
|
14
|
+
label: 'Task list is non-empty',
|
|
15
|
+
check: (s) => Array.isArray(s.phases.design?.tasks) && s.phases.design.tasks.length > 0,
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
'build:verify': [
|
|
19
|
+
{ label: 'Build phase is done', check: (s) => s.phases.build?.status === 'done' },
|
|
20
|
+
{
|
|
21
|
+
label: 'All tasks completed or ECC review passed',
|
|
22
|
+
check: (s) => {
|
|
23
|
+
if (s.phases.build?.eccReviewPassed)
|
|
24
|
+
return true;
|
|
25
|
+
const tasks = s.phases.build?.tasks || {};
|
|
26
|
+
const entries = Object.values(tasks);
|
|
27
|
+
return entries.length > 0 && entries.every((t) => t.status === 'done');
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
'verify:archive': [
|
|
32
|
+
{ label: 'Verify phase is done', check: (s) => s.phases.verify?.status === 'done' },
|
|
33
|
+
],
|
|
34
|
+
// Rollback transitions — always allowed (iteration is expected)
|
|
35
|
+
'build:design': [
|
|
36
|
+
{ label: 'Build phase has started (rollback)', check: (s) => s.phases.build?.status !== 'pending' },
|
|
37
|
+
],
|
|
38
|
+
'verify:build': [
|
|
39
|
+
{ label: 'Verify phase has started (rollback)', check: (s) => s.phases.verify?.status !== 'pending' },
|
|
40
|
+
],
|
|
41
|
+
'verify:design': [
|
|
42
|
+
{ label: 'Verify phase has started (rollback to design)', check: (s) => s.phases.verify?.status !== 'pending' },
|
|
43
|
+
],
|
|
44
|
+
'design:open': [
|
|
45
|
+
{ label: 'Design phase has started (rollback)', check: (s) => s.phases.design?.status !== 'pending' },
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
async function guardPhaseTransition(from, to) {
|
|
49
|
+
const state = await state_1.StateManager.load();
|
|
50
|
+
const key = `${from}:${to}`;
|
|
51
|
+
const rules = TRANSITION_RULES[key];
|
|
52
|
+
if (!rules) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return rules.every((rule) => rule.check(state));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/cli-core/guard.ts"],"names":[],"mappings":"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"}
|