@njeybe/nativ 2.4.0 → 2.5.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.
Files changed (140) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +26 -0
  3. package/dist/commands/db/db-formatter.d.ts +5 -0
  4. package/dist/commands/db/db-formatter.js +116 -0
  5. package/dist/commands/db/db-introspect.d.ts +11 -0
  6. package/dist/commands/db/db-introspect.js +84 -0
  7. package/dist/commands/db.js +4 -206
  8. package/dist/commands/profile.d.ts +3 -0
  9. package/dist/commands/profile.js +39 -0
  10. package/dist/commands/task/task-add.d.ts +11 -0
  11. package/dist/commands/task/task-add.js +169 -0
  12. package/dist/commands/task/task-common.d.ts +57 -0
  13. package/dist/commands/task/task-common.js +45 -0
  14. package/dist/commands/task/task-escalate.d.ts +7 -0
  15. package/dist/commands/task/task-escalate.js +119 -0
  16. package/dist/commands/task/task-lifecycle.d.ts +5 -0
  17. package/dist/commands/task/task-lifecycle.js +252 -0
  18. package/dist/commands/task/task-query.d.ts +10 -0
  19. package/dist/commands/task/task-query.js +269 -0
  20. package/dist/commands/task.d.ts +9 -87
  21. package/dist/commands/task.js +8 -850
  22. package/dist/commands/triage/triage-store.d.ts +56 -0
  23. package/dist/commands/triage/triage-store.js +108 -0
  24. package/dist/commands/triage/triage-ui.d.ts +14 -0
  25. package/dist/commands/triage/triage-ui.js +104 -0
  26. package/dist/commands/triage.d.ts +3 -52
  27. package/dist/commands/triage.js +8 -216
  28. package/dist/core/enforcement.d.ts +1 -0
  29. package/dist/core/enforcement.js +19 -0
  30. package/dist/core/human-gate.d.ts +2 -1
  31. package/dist/core/human-gate.js +9 -2
  32. package/dist/core/profiles.d.ts +14 -0
  33. package/dist/core/profiles.js +82 -0
  34. package/dist/core/setup/config-merger.d.ts +59 -0
  35. package/dist/core/setup/config-merger.js +107 -0
  36. package/dist/core/setup/session-context.d.ts +4 -0
  37. package/dist/core/setup/session-context.js +65 -0
  38. package/dist/core/setup/setup-planner.d.ts +14 -0
  39. package/dist/core/setup/setup-planner.js +180 -0
  40. package/dist/core/setup/template-planner.d.ts +8 -0
  41. package/dist/core/setup/template-planner.js +32 -0
  42. package/dist/core/setup/types.d.ts +65 -0
  43. package/dist/core/setup/types.js +55 -0
  44. package/dist/core/setup-assets.d.ts +8 -119
  45. package/dist/core/setup-assets.js +7 -437
  46. package/dist/core/spec-slices.js +119 -7
  47. package/dist/core/tier1-liaison.d.ts +2 -0
  48. package/dist/core/tier1-liaison.js +64 -3
  49. package/dist/core/verifier/executor.d.ts +5 -0
  50. package/dist/core/verifier/executor.js +62 -0
  51. package/dist/core/verifier/phases.d.ts +5 -0
  52. package/dist/core/verifier/phases.js +71 -0
  53. package/dist/core/verifier/task-verifier.d.ts +37 -0
  54. package/dist/core/verifier/task-verifier.js +233 -0
  55. package/dist/core/verifier/types.d.ts +51 -0
  56. package/dist/core/verifier/types.js +1 -0
  57. package/dist/core/verifier.d.ts +5 -93
  58. package/dist/core/verifier.js +5 -359
  59. package/dist/db/introspector.js +59 -59
  60. package/dist/governor/evaluator.d.ts +4 -64
  61. package/dist/governor/evaluator.js +21 -686
  62. package/dist/governor/patch-applier.d.ts +8 -0
  63. package/dist/governor/patch-applier.js +121 -0
  64. package/dist/governor/self-healing.d.ts +24 -0
  65. package/dist/governor/self-healing.js +351 -0
  66. package/dist/governor/test-integrity.d.ts +41 -0
  67. package/dist/governor/test-integrity.js +237 -0
  68. package/dist/index.js +8 -0
  69. package/dist/mcp/capture.d.ts +4 -0
  70. package/dist/mcp/capture.js +33 -0
  71. package/dist/mcp/resources.d.ts +39 -0
  72. package/dist/mcp/resources.js +44 -0
  73. package/dist/mcp/server.d.ts +11 -0
  74. package/dist/mcp/server.js +14 -89
  75. package/dist/mcp/tools.d.ts +1 -0
  76. package/dist/mcp/tools.js +1 -0
  77. package/dist/runner/agent-supervisor.d.ts +8 -302
  78. package/dist/runner/agent-supervisor.js +41 -1030
  79. package/dist/runner/cli-config.d.ts +84 -0
  80. package/dist/runner/cli-config.js +215 -0
  81. package/dist/runner/native-driver.d.ts +18 -0
  82. package/dist/runner/native-driver.js +208 -0
  83. package/dist/runner/native-engine.d.ts +27 -0
  84. package/dist/runner/native-engine.js +184 -0
  85. package/dist/runner/native-tools.d.ts +31 -0
  86. package/dist/runner/native-tools.js +241 -0
  87. package/dist/runner/process-utils.d.ts +12 -0
  88. package/dist/runner/process-utils.js +96 -0
  89. package/dist/runner/run-lifecycle.d.ts +6 -0
  90. package/dist/runner/run-lifecycle.js +42 -0
  91. package/dist/runner/types.d.ts +215 -0
  92. package/dist/runner/types.js +41 -0
  93. package/dist/scanner/detector.js +42 -663
  94. package/dist/scanner/detectors/ecosystem-detector.d.ts +16 -0
  95. package/dist/scanner/detectors/ecosystem-detector.js +354 -0
  96. package/dist/scanner/detectors/orm-detector.d.ts +5 -0
  97. package/dist/scanner/detectors/orm-detector.js +59 -0
  98. package/dist/scanner/detectors/workspace-detector.d.ts +19 -0
  99. package/dist/scanner/detectors/workspace-detector.js +266 -0
  100. package/dist/server/cli-runner.d.ts +15 -0
  101. package/dist/server/cli-runner.js +43 -0
  102. package/dist/server/event-hub.d.ts +42 -0
  103. package/dist/server/event-hub.js +169 -0
  104. package/dist/server/http-utils.d.ts +15 -0
  105. package/dist/server/http-utils.js +56 -0
  106. package/dist/server/plan-utils.d.ts +9 -0
  107. package/dist/server/plan-utils.js +31 -0
  108. package/dist/server/routes/db-routes.d.ts +57 -0
  109. package/dist/server/routes/db-routes.js +484 -0
  110. package/dist/server/routes/task-routes.d.ts +266 -0
  111. package/dist/server/routes/task-routes.js +285 -0
  112. package/dist/server/routes/telemetry-routes.d.ts +128 -0
  113. package/dist/server/routes/telemetry-routes.js +179 -0
  114. package/dist/server/routes/triage-routes.d.ts +81 -0
  115. package/dist/server/routes/triage-routes.js +244 -0
  116. package/dist/server/routes/worktree-routes.d.ts +31 -0
  117. package/dist/server/routes/worktree-routes.js +144 -0
  118. package/dist/server/studio-server.d.ts +4 -11
  119. package/dist/server/studio-server.js +34 -1578
  120. package/dist/server/studio-ui/shell/pipeline-state.js +2 -0
  121. package/dist/server/studio-ui/shell/triage.js +10 -0
  122. package/package.json +2 -2
  123. package/plugin/.claude-plugin/plugin.json +1 -1
  124. package/plugin/agents/architect.md +4 -2
  125. package/plugin/agents/verifier.md +1 -1
  126. package/plugin/agents/worker.md +7 -4
  127. package/plugin/skills/nativ/SKILL.md +1 -0
  128. package/templates/.claudeignore +62 -45
  129. package/templates/AGENTS.md +1 -0
  130. package/templates/CLAUDE.md +13 -0
  131. package/templates/claude-agents/architect.md +4 -2
  132. package/templates/claude-agents/verifier.md +1 -1
  133. package/templates/claude-agents/worker.md +7 -4
  134. package/templates/dot-ai/api_contracts.json +66 -66
  135. package/templates/dot-ai/context.md +38 -38
  136. package/templates/dot-ai/db_schema.json +39 -39
  137. package/dist/commands/session.d.ts +0 -22
  138. package/dist/commands/session.js +0 -106
  139. package/dist/core/session-memory.d.ts +0 -42
  140. package/dist/core/session-memory.js +0 -121
@@ -0,0 +1,51 @@
1
+ import type { CodeShapeReport } from '../code-shape.js';
2
+ export interface VerificationResult {
3
+ success: boolean;
4
+ exitCode: number;
5
+ command: string;
6
+ stdout: string;
7
+ stderr: string;
8
+ durationMs: number;
9
+ error?: string;
10
+ skipped?: boolean;
11
+ codeShape?: CodeShapeReport;
12
+ /** Results of the configured `verifyPhases`, when any ran. */
13
+ phases?: PhaseResult[];
14
+ }
15
+ export interface PhaseResult {
16
+ name: string;
17
+ command: string;
18
+ success: boolean;
19
+ durationMs: number;
20
+ }
21
+ export interface TaskVerificationResult {
22
+ taskId: string;
23
+ title: string;
24
+ milestoneId: string;
25
+ milestoneName: string;
26
+ status: string;
27
+ result: VerificationResult;
28
+ }
29
+ export interface BatchVerificationResult {
30
+ projectName: string;
31
+ total: number;
32
+ passed: number;
33
+ failed: number;
34
+ skipped: number;
35
+ durationMs: number;
36
+ tasks: TaskVerificationResult[];
37
+ }
38
+ export interface VerifyPhase {
39
+ name: string;
40
+ run: string;
41
+ }
42
+ /** Configured phases, or an error when the config exists but cannot be trusted to say what they are. */
43
+ export interface VerifyPhasesConfig {
44
+ phases: VerifyPhase[];
45
+ error?: string;
46
+ }
47
+ /** Outcome of running the configured phases once; shared by every task in a batch. */
48
+ export interface PhasesOutcome {
49
+ reports: PhaseResult[];
50
+ failure?: VerificationResult;
51
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,95 +1,7 @@
1
- import { MasterPlan, MasterPlanTask } from '../scanner/types.js';
2
- import { type CodeShapeReport } from './code-shape.js';
3
- export interface VerificationResult {
4
- success: boolean;
5
- exitCode: number;
6
- command: string;
7
- stdout: string;
8
- stderr: string;
9
- durationMs: number;
10
- error?: string;
11
- skipped?: boolean;
12
- codeShape?: CodeShapeReport;
13
- /** Results of the configured `verifyPhases`, when any ran. */
14
- phases?: PhaseResult[];
15
- }
16
- export interface PhaseResult {
17
- name: string;
18
- command: string;
19
- success: boolean;
20
- durationMs: number;
21
- }
22
- export interface TaskVerificationResult {
23
- taskId: string;
24
- title: string;
25
- milestoneId: string;
26
- milestoneName: string;
27
- status: string;
28
- result: VerificationResult;
29
- }
30
- export interface BatchVerificationResult {
31
- projectName: string;
32
- total: number;
33
- passed: number;
34
- failed: number;
35
- skipped: number;
36
- durationMs: number;
37
- tasks: TaskVerificationResult[];
38
- }
39
- export declare function loadMasterPlan(targetDir: string): {
40
- planPath: string;
41
- plan: MasterPlan | null;
42
- error?: string;
43
- };
44
1
  /**
45
- * Execute a verification command in the workspace directory with timeout and output capture.
2
+ * Re-exports the modular verifier engine components.
46
3
  */
47
- export declare function executeVerification(command: string, cwd: string, timeoutMs?: number): Promise<VerificationResult>;
48
- /**
49
- * Run the code-shape check on a task's target files and print a short summary to stderr.
50
- * In 'warn' mode (default) the result is untouched; in 'block' mode issues fail it with a reason.
51
- */
52
- export declare function applyCodeShape(result: VerificationResult, targetDir: string, task: MasterPlanTask): VerificationResult;
53
- export interface VerifyPhase {
54
- name: string;
55
- run: string;
56
- }
57
- /** Configured phases, or an error when the config exists but cannot be trusted to say what they are. */
58
- export interface VerifyPhasesConfig {
59
- phases: VerifyPhase[];
60
- error?: string;
61
- }
62
- /** `verifyPhases` from the main checkout's `.nativ/config.json`, never from a worktree's own copy. */
63
- export declare function loadVerifyPhases(configDir: string): VerifyPhasesConfig;
64
- /** Outcome of running the configured phases once; shared by every task in a batch. */
65
- export interface PhasesOutcome {
66
- reports: PhaseResult[];
67
- failure?: VerificationResult;
68
- }
69
- /** Runs the configured phases in order and stops at the first failure. */
70
- export declare function runVerifyPhases(cwd: string, configDir: string, timeout?: number): Promise<PhasesOutcome>;
71
- /**
72
- * The one verification every path shares: the configured phases in order, stopping at the
73
- * first failure, then the task's own command, then the code-shape check.
74
- */
75
- export declare function runTaskVerification(task: MasterPlanTask, options: {
76
- cwd: string;
77
- configDir?: string;
78
- timeout?: number;
79
- phases?: PhasesOutcome;
80
- }): Promise<VerificationResult>;
81
- /**
82
- * Run verification for a single specific task in the plan.
83
- */
84
- export declare function verifyTask(taskId: string, targetDirArg?: string, options?: {
85
- timeout?: number;
86
- }): Promise<TaskVerificationResult>;
87
- /**
88
- * Verify a batch of tasks (by milestone, all completed tasks, or the active in-progress task).
89
- */
90
- export declare function verifyBatch(targetDirArg?: string, options?: {
91
- taskId?: string;
92
- milestoneId?: string;
93
- all?: boolean;
94
- timeout?: number;
95
- }): Promise<BatchVerificationResult>;
4
+ export * from './verifier/types.js';
5
+ export { executeVerification } from './verifier/executor.js';
6
+ export { loadVerifyPhases, runVerifyPhases } from './verifier/phases.js';
7
+ export { loadMasterPlan, applyCodeShape, runTaskVerification, verifyTask, verifyBatch, } from './verifier/task-verifier.js';
@@ -1,361 +1,7 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { exec } from 'node:child_process';
4
- import { checkCodeShape, formatCodeShapeReport } from './code-shape.js';
5
- import { parseJsonLoose } from './enforcement.js';
6
- import { resolveMainRoot } from './root-resolver.js';
7
- export function loadMasterPlan(targetDir) {
8
- const planPath = path.join(targetDir, '.ai', 'master_plan.json');
9
- if (!fs.existsSync(planPath)) {
10
- return { planPath, plan: null, error: `No .ai/master_plan.json found at: ${planPath}` };
11
- }
12
- try {
13
- const raw = fs.readFileSync(planPath, 'utf8');
14
- const plan = JSON.parse(raw);
15
- return { planPath, plan };
16
- }
17
- catch (err) {
18
- return { planPath, plan: null, error: `Failed to parse .ai/master_plan.json: ${err.message}` };
19
- }
20
- }
21
1
  /**
22
- * Execute a verification command in the workspace directory with timeout and output capture.
2
+ * Re-exports the modular verifier engine components.
23
3
  */
24
- export async function executeVerification(command, cwd, timeoutMs = 120_000) {
25
- const trimmed = (command || '').trim();
26
- // Treat empty, 'none', or 'skip' as an informational pass
27
- if (!trimmed || trimmed.toLowerCase() === 'none' || trimmed.toLowerCase() === 'skip') {
28
- return {
29
- success: true,
30
- exitCode: 0,
31
- command: trimmed || 'none',
32
- stdout: '',
33
- stderr: '',
34
- durationMs: 0,
35
- skipped: true,
36
- };
37
- }
38
- // Cross-platform compatibility for common test commands on Windows cmd.exe
39
- let finalCommand = trimmed;
40
- if (process.platform === 'win32') {
41
- if (trimmed === 'true')
42
- finalCommand = 'exit 0';
43
- else if (trimmed === 'false')
44
- finalCommand = 'exit 1';
45
- }
46
- const start = Date.now();
47
- return new Promise((resolve) => {
48
- exec(finalCommand, {
49
- cwd,
50
- timeout: timeoutMs,
51
- maxBuffer: 10 * 1024 * 1024,
52
- env: process.env,
53
- }, (err, stdout, stderr) => {
54
- const durationMs = Date.now() - start;
55
- const out = (stdout || '').toString();
56
- const errOut = (stderr || '').toString();
57
- if (err) {
58
- const exitCode = typeof err.code === 'number' ? err.code : 1;
59
- resolve({
60
- success: false,
61
- exitCode,
62
- command: trimmed,
63
- stdout: out,
64
- stderr: errOut || err.message,
65
- durationMs,
66
- error: err.killed ? `Command timed out after ${timeoutMs}ms` : err.message,
67
- });
68
- }
69
- else {
70
- resolve({
71
- success: true,
72
- exitCode: 0,
73
- command: trimmed,
74
- stdout: out,
75
- stderr: errOut,
76
- durationMs,
77
- });
78
- }
79
- });
80
- });
81
- }
82
- /**
83
- * Run the code-shape check on a task's target files and print a short summary to stderr.
84
- * In 'warn' mode (default) the result is untouched; in 'block' mode issues fail it with a reason.
85
- */
86
- export function applyCodeShape(result, targetDir, task) {
87
- if (result.skipped || !result.success)
88
- return result;
89
- const report = checkCodeShape(targetDir, task.targetFiles || []);
90
- if (report.mode === 'off')
91
- return result;
92
- result.codeShape = report;
93
- const summary = formatCodeShapeReport(report);
94
- if (summary)
95
- console.error(summary);
96
- if (report.mode === 'block' && report.issues.length > 0) {
97
- result.success = false;
98
- result.exitCode = 1;
99
- result.error = `Code shape check failed: ${report.issues.length} issue(s) (codeStyle.mode is "block")`;
100
- }
101
- return result;
102
- }
103
- /** Reads the file, retrying once: antivirus or an editor saving can briefly lock it on Windows. */
104
- function readConfigText(file) {
105
- for (let attempt = 0;; attempt++) {
106
- try {
107
- return fs.readFileSync(file, 'utf8');
108
- }
109
- catch (err) {
110
- if (err?.code === 'ENOENT')
111
- return null;
112
- if (attempt >= 1)
113
- throw err;
114
- }
115
- }
116
- }
117
- /** `verifyPhases` from the main checkout's `.nativ/config.json`, never from a worktree's own copy. */
118
- export function loadVerifyPhases(configDir) {
119
- let raw;
120
- try {
121
- raw = readConfigText(path.join(resolveMainRoot(configDir), '.nativ', 'config.json'));
122
- }
123
- catch (err) {
124
- return { phases: [], error: `.nativ/config.json cannot be read (${err?.message})` };
125
- }
126
- if (raw === null)
127
- return { phases: [] };
128
- if (!raw.trim())
129
- return { phases: [], error: '.nativ/config.json is empty' };
130
- let phases;
131
- try {
132
- phases = parseJsonLoose(raw)?.verifyPhases;
133
- }
134
- catch (err) {
135
- return { phases: [], error: `.nativ/config.json is not valid JSON (${err?.message})` };
136
- }
137
- if (phases === undefined || phases === null)
138
- return { phases: [] };
139
- // An empty or null "run" switches a phase off; a missing or mistyped field is a mistake.
140
- const isEntry = (p) => typeof p?.name === 'string' && p.name.trim()
141
- && (p.run === null || typeof p.run === 'string');
142
- if (!Array.isArray(phases) || !phases.every(isEntry)) {
143
- return { phases: [], error: 'verifyPhases must be a list of { "name": "...", "run": "..." } entries' };
144
- }
145
- const active = phases.filter((p) => p.run && p.run.trim());
146
- return { phases: active.map((p) => ({ name: p.name.trim(), run: p.run.trim() })) };
147
- }
148
- function configFailure(message) {
149
- const error = `${message}, so the configured checks could not run. Fix it and verify again.`;
150
- const command = '.nativ/config.json';
151
- return { success: false, exitCode: 1, command, stdout: '', stderr: error, durationMs: 0, error };
152
- }
153
- /** Runs the configured phases in order and stops at the first failure. */
154
- export async function runVerifyPhases(cwd, configDir, timeout) {
155
- const config = loadVerifyPhases(configDir);
156
- if (config.error)
157
- return { reports: [], failure: configFailure(config.error) };
158
- const reports = [];
159
- for (const phase of config.phases) {
160
- const res = await executeVerification(phase.run, cwd, timeout);
161
- reports.push({ name: phase.name, command: res.command, success: res.success, durationMs: res.durationMs });
162
- if (!res.success) {
163
- const cause = res.error ? `: ${res.error.trim()}` : '';
164
- return { reports, failure: { ...res, phases: reports, error: `Phase "${phase.name}" failed${cause}` } };
165
- }
166
- }
167
- return { reports };
168
- }
169
- /**
170
- * The one verification every path shares: the configured phases in order, stopping at the
171
- * first failure, then the task's own command, then the code-shape check.
172
- */
173
- export async function runTaskVerification(task, options) {
174
- const configDir = options.configDir ?? options.cwd;
175
- const outcome = options.phases ?? (await runVerifyPhases(options.cwd, configDir, options.timeout));
176
- // In a batch the shared phase time is counted once, by the batch, not again for every task.
177
- if (outcome.failure) {
178
- return { ...outcome.failure, phases: outcome.reports, ...(options.phases ? { durationMs: 0 } : {}) };
179
- }
180
- const raw = await executeVerification(task.verificationCommand, options.cwd, options.timeout);
181
- if (outcome.reports.length) {
182
- raw.phases = outcome.reports;
183
- raw.durationMs += options.phases ? 0 : outcome.reports.reduce((sum, r) => sum + r.durationMs, 0);
184
- raw.skipped = false;
185
- }
186
- return applyCodeShape(raw, options.cwd, task);
187
- }
188
- /**
189
- * Run verification for a single specific task in the plan.
190
- */
191
- export async function verifyTask(taskId, targetDirArg, options = {}) {
192
- const targetDir = path.resolve(targetDirArg || process.cwd());
193
- const { plan, error } = loadMasterPlan(targetDir);
194
- if (!plan) {
195
- return {
196
- taskId,
197
- title: 'Unknown',
198
- milestoneId: 'unknown',
199
- milestoneName: 'Unknown',
200
- status: 'unknown',
201
- result: {
202
- success: false,
203
- exitCode: 1,
204
- command: '',
205
- stdout: '',
206
- stderr: error || 'Failed to load master plan',
207
- durationMs: 0,
208
- error: error || 'Failed to load master plan',
209
- },
210
- };
211
- }
212
- let foundTask = null;
213
- let foundMilestone = null;
214
- for (const m of plan.milestones) {
215
- const t = m.tasks.find((item) => item.id === taskId);
216
- if (t) {
217
- foundTask = t;
218
- foundMilestone = m;
219
- break;
220
- }
221
- }
222
- if (!foundTask || !foundMilestone) {
223
- return {
224
- taskId,
225
- title: 'Not Found',
226
- milestoneId: 'unknown',
227
- milestoneName: 'Unknown',
228
- status: 'unknown',
229
- result: {
230
- success: false,
231
- exitCode: 1,
232
- command: '',
233
- stdout: '',
234
- stderr: `Task [${taskId}] not found in .ai/master_plan.json`,
235
- durationMs: 0,
236
- error: `Task [${taskId}] not found`,
237
- },
238
- };
239
- }
240
- const result = await runTaskVerification(foundTask, { cwd: targetDir, timeout: options.timeout });
241
- return {
242
- taskId: foundTask.id,
243
- title: foundTask.title,
244
- milestoneId: foundMilestone.id,
245
- milestoneName: foundMilestone.name,
246
- status: foundTask.status,
247
- result,
248
- };
249
- }
250
- /**
251
- * Verify a batch of tasks (by milestone, all completed tasks, or the active in-progress task).
252
- */
253
- export async function verifyBatch(targetDirArg, options = {}) {
254
- const targetDir = path.resolve(targetDirArg || process.cwd());
255
- const { plan, error } = loadMasterPlan(targetDir);
256
- if (!plan) {
257
- return {
258
- projectName: 'unknown',
259
- total: 0,
260
- passed: 0,
261
- failed: 1,
262
- skipped: 0,
263
- durationMs: 0,
264
- tasks: [
265
- {
266
- taskId: 'init',
267
- title: 'Plan Loader',
268
- milestoneId: 'unknown',
269
- milestoneName: 'Unknown',
270
- status: 'unknown',
271
- result: {
272
- success: false,
273
- exitCode: 1,
274
- command: '',
275
- stdout: '',
276
- stderr: error || 'Plan not found',
277
- durationMs: 0,
278
- error: error || 'Plan not found',
279
- },
280
- },
281
- ],
282
- };
283
- }
284
- // Filter tasks to run
285
- const candidates = [];
286
- for (const m of plan.milestones) {
287
- for (const t of m.tasks) {
288
- if (options.taskId && t.id === options.taskId) {
289
- candidates.push({ task: t, milestone: m });
290
- }
291
- else if (options.milestoneId && (m.id === options.milestoneId || m.name.toLowerCase() === options.milestoneId.toLowerCase())) {
292
- candidates.push({ task: t, milestone: m });
293
- }
294
- else if (options.all) {
295
- // All tasks with verification commands (prefer completed or in_progress, but include all)
296
- candidates.push({ task: t, milestone: m });
297
- }
298
- }
299
- }
300
- // If no filters specified, find the current in_progress task, or next ready task
301
- if (!options.taskId && !options.milestoneId && !options.all) {
302
- let activeTask = null;
303
- for (const m of plan.milestones) {
304
- const inProgress = m.tasks.find((t) => t.status === 'in_progress');
305
- if (inProgress) {
306
- activeTask = { task: inProgress, milestone: m };
307
- break;
308
- }
309
- }
310
- if (!activeTask) {
311
- for (const m of plan.milestones) {
312
- const pending = m.tasks.find((t) => t.status === 'pending');
313
- if (pending) {
314
- activeTask = { task: pending, milestone: m };
315
- break;
316
- }
317
- }
318
- }
319
- if (activeTask) {
320
- candidates.push(activeTask);
321
- }
322
- }
323
- const results = [];
324
- let passed = 0;
325
- let failed = 0;
326
- let skipped = 0;
327
- let totalDuration = 0;
328
- // The phases check the whole project, so one run serves every task in the batch.
329
- const phases = candidates.length ? await runVerifyPhases(targetDir, targetDir, options.timeout) : { reports: [] };
330
- totalDuration += phases.reports.reduce((sum, r) => sum + r.durationMs, 0);
331
- for (const { task, milestone } of candidates) {
332
- const vResult = await runTaskVerification(task, { cwd: targetDir, timeout: options.timeout, phases });
333
- totalDuration += vResult.durationMs;
334
- if (vResult.skipped) {
335
- skipped++;
336
- }
337
- else if (vResult.success) {
338
- passed++;
339
- }
340
- else {
341
- failed++;
342
- }
343
- results.push({
344
- taskId: task.id,
345
- title: task.title,
346
- milestoneId: milestone.id,
347
- milestoneName: milestone.name,
348
- status: task.status,
349
- result: vResult,
350
- });
351
- }
352
- return {
353
- projectName: plan.projectName,
354
- total: candidates.length,
355
- passed,
356
- failed,
357
- skipped,
358
- durationMs: totalDuration,
359
- tasks: results,
360
- };
361
- }
4
+ export * from './verifier/types.js';
5
+ export { executeVerification } from './verifier/executor.js';
6
+ export { loadVerifyPhases, runVerifyPhases } from './verifier/phases.js';
7
+ export { loadMasterPlan, applyCodeShape, runTaskVerification, verifyTask, verifyBatch, } from './verifier/task-verifier.js';