@nathapp/nax 0.68.5 → 0.68.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nax.js +1070 -1204
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -18380,16 +18380,13 @@ function deepMergeConfig(base, override) {
|
|
|
18380
18380
|
for (const hookName of allHookNames) {
|
|
18381
18381
|
const baseHook = baseHookDefs[hookName];
|
|
18382
18382
|
const overrideHook = overrideHookDefs[hookName];
|
|
18383
|
-
|
|
18384
|
-
|
|
18385
|
-
|
|
18386
|
-
|
|
18387
|
-
} else {
|
|
18388
|
-
mergedHookDefs[hookName] = baseHook;
|
|
18389
|
-
}
|
|
18383
|
+
const baseItems = Array.isArray(baseHook) ? baseHook : baseHook ? [baseHook] : [];
|
|
18384
|
+
const overrideItems = Array.isArray(overrideHook) ? overrideHook : overrideHook ? [overrideHook] : [];
|
|
18385
|
+
const combined = [...baseItems, ...overrideItems];
|
|
18386
|
+
mergedHookDefs[hookName] = combined.length === 1 ? combined[0] : combined;
|
|
18390
18387
|
}
|
|
18391
18388
|
merged.hooks = mergedHookDefs;
|
|
18392
|
-
} else if (overrideHooks.hooks) {
|
|
18389
|
+
} else if (isPlainObject2(overrideHooks.hooks)) {
|
|
18393
18390
|
merged.hooks = overrideHooks.hooks;
|
|
18394
18391
|
}
|
|
18395
18392
|
for (const hookKey of Object.keys(overrideHooks)) {
|
|
@@ -28056,16 +28053,17 @@ function deriveTestPatterns(contextFiles, resolvedGlobs) {
|
|
|
28056
28053
|
async function detectTestDir(workdir, resolvedGlobs) {
|
|
28057
28054
|
const resolvedDirs = resolvedGlobs ? extractTestDirs(resolvedGlobs) : [];
|
|
28058
28055
|
const candidateDirs = resolvedDirs.length > 0 ? [...new Set([...resolvedDirs, ...DEFAULT_SCAN_TEST_DIRS])] : DEFAULT_SCAN_TEST_DIRS;
|
|
28059
|
-
|
|
28056
|
+
const checks3 = await Promise.all(candidateDirs.map(async (dir) => {
|
|
28060
28057
|
const fullPath = path.join(workdir, dir);
|
|
28061
28058
|
try {
|
|
28062
28059
|
const proc = Bun.spawn(["test", "-d", fullPath], { stdout: "pipe", stderr: "pipe" });
|
|
28063
28060
|
const exitCode = await proc.exited;
|
|
28064
|
-
|
|
28065
|
-
|
|
28066
|
-
|
|
28067
|
-
|
|
28068
|
-
|
|
28061
|
+
return exitCode === 0 ? dir : null;
|
|
28062
|
+
} catch {
|
|
28063
|
+
return null;
|
|
28064
|
+
}
|
|
28065
|
+
}));
|
|
28066
|
+
return checks3.find((dir) => dir !== null) ?? null;
|
|
28069
28067
|
}
|
|
28070
28068
|
function deriveScanGlob(resolvedTestGlobs, testDir) {
|
|
28071
28069
|
const prefix = `${testDir}/`;
|
|
@@ -29778,9 +29776,10 @@ Your task: make the failing tests pass by writing real source code.
|
|
|
29778
29776
|
Workflow:
|
|
29779
29777
|
1. Read every failing test in scope. The tests are the contract \u2014 understand what each one asserts before editing source.
|
|
29780
29778
|
2. Run the scoped test files once to establish the baseline (which fail, which pass, and why).
|
|
29781
|
-
3.
|
|
29782
|
-
4.
|
|
29783
|
-
5.
|
|
29779
|
+
3. Break the work into small steps before writing: for each step, note the source change and the failing test that verifies it (step -> verify). Resolve ambiguities now, not mid-edit.
|
|
29780
|
+
4. Implement source code in the package's source location (the project context names it).
|
|
29781
|
+
5. After each meaningful change, re-run only the scoped test files \u2014 never the full suite.
|
|
29782
|
+
6. When all scoped tests pass, stage and commit ALL changed files: \`git commit -m '${commitMsg}'\`.
|
|
29784
29783
|
|
|
29785
29784
|
Rules:
|
|
29786
29785
|
- Do NOT modify test files. Three narrow exceptions: (a) a lint-only fix to a test, (b) a contract drift where the test imports a removed/renamed symbol, (c) a sibling test file rename forced by your source change. Name which exception applies in the commit body before editing any test file.
|
|
@@ -29795,10 +29794,11 @@ Context: A test-writer session has already created tests and may have added mini
|
|
|
29795
29794
|
Workflow:
|
|
29796
29795
|
1. Run the existing scoped tests to see which fail and why (assertion failure vs import error).
|
|
29797
29796
|
2. Read each failing test. Note which ACs they cover and which they DON'T.
|
|
29798
|
-
3.
|
|
29799
|
-
4.
|
|
29800
|
-
5.
|
|
29801
|
-
6.
|
|
29797
|
+
3. Break the work into small steps before writing: for each stub, note the real implementation that replaces it and the test that verifies it (step -> verify); flag any AC still missing a test. Resolve ambiguities now, not mid-edit.
|
|
29798
|
+
4. Replace stubs with real implementations. A stub is one of: a type-only declaration, a function returning a placeholder/throwing "not implemented", or a const placeholder.
|
|
29799
|
+
5. If any AC has no test, add one before implementing \u2014 do not implement uncovered behavior.
|
|
29800
|
+
6. Re-run only the scoped test files after each meaningful change.
|
|
29801
|
+
7. When all scoped tests pass, stage and commit ALL changed files: \`git commit -m '${commitMsg}'\`.
|
|
29802
29802
|
|
|
29803
29803
|
Rules:
|
|
29804
29804
|
- Three test-modification exceptions apply (lint-only fix, contract drift, sibling rename). Name the exception in the commit body before editing any test the test-writer wrote.
|
|
@@ -29815,10 +29815,11 @@ Context: You are session 1 of a multi-session workflow. An implementer will foll
|
|
|
29815
29815
|
|
|
29816
29816
|
Workflow:
|
|
29817
29817
|
1. Re-read the acceptance criteria above.
|
|
29818
|
-
2.
|
|
29819
|
-
3. Create
|
|
29820
|
-
4.
|
|
29821
|
-
5.
|
|
29818
|
+
2. Break the work into small tasks before writing: treat each AC as one task and note the test name(s) you will add (success + boundary) and the minimal stub each test needs to compile. This per-AC list is your checklist.
|
|
29819
|
+
3. Create test files in the location the project uses for tests.
|
|
29820
|
+
4. Create stubs in the package's source location so the tests can import and compile. A stub is one of: a type/interface declaration, a function returning a placeholder/throwing "not implemented" (no more than 3 lines of body), or a const placeholder. If a stub body needs real logic, you have crossed into implementer territory \u2014 stop.
|
|
29821
|
+
5. For each AC: at least one success-path test and one boundary/failure-path test.
|
|
29822
|
+
6. Run the new test files. Confirm tests compile (stubs work) AND fail with ASSERTION failures \u2014 NOT import errors or compile errors. A test that errors before reaching its assertion does not prove the behavior is missing.
|
|
29822
29823
|
|
|
29823
29824
|
Rules:
|
|
29824
29825
|
- Stubs are NOT implementations. The implementer in the next session writes real logic.
|
|
@@ -29835,9 +29836,10 @@ Context: You are session 1 of a multi-session workflow.
|
|
|
29835
29836
|
|
|
29836
29837
|
Workflow:
|
|
29837
29838
|
1. Re-read the acceptance criteria above.
|
|
29838
|
-
2.
|
|
29839
|
-
3.
|
|
29840
|
-
4.
|
|
29839
|
+
2. Break the work into small tasks before writing: treat each AC as one task and note the test name(s) you will write (success + boundary) and which file they belong in. This per-AC list is your checklist.
|
|
29840
|
+
3. Create test files in the location the project uses for tests (project context names it).
|
|
29841
|
+
4. For each AC: write at least one test for the success path AND at least one for a boundary/failure path (zero, empty, negative, missing, throws). ACs worded as "throws X" require a test asserting the throw.
|
|
29842
|
+
5. Run the new test files. Confirm every test fails with an ASSERTION failure \u2014 NOT an import error, compile error, or runtime crash before assertion. A test that errors before reaching its assertion does not prove the behavior is missing.
|
|
29841
29843
|
|
|
29842
29844
|
Rules:
|
|
29843
29845
|
- Do NOT create or modify any source files. Read source for types/interfaces only.
|
|
@@ -41177,6 +41179,7 @@ ${errors3}
|
|
|
41177
41179
|
1. Read the relevant files to verify each finding is a real issue
|
|
41178
41180
|
2. Only fix findings that are actually valid problems
|
|
41179
41181
|
3. Do NOT add keys, functions, or imports that already exist \u2014 check first
|
|
41182
|
+
4. Break the fix into one small step per valid finding before touching code, each verified by re-running the relevant check
|
|
41180
41183
|
|
|
41181
41184
|
${testEditHeadline(story, `Do NOT change test files or test behavior \u2014 see the ${exceptionCountWord(story)} narrow exceptions appended below.`)}
|
|
41182
41185
|
Do NOT add new features \u2014 only fix valid issues.
|
|
@@ -41200,6 +41203,7 @@ ${errors3}
|
|
|
41200
41203
|
1. Read the relevant files to verify each finding is a real issue
|
|
41201
41204
|
2. Only fix findings that are actually valid problems
|
|
41202
41205
|
3. Do NOT add keys, functions, or imports that already exist \u2014 check first
|
|
41206
|
+
4. Break the fix into one small step per valid finding before touching code, each verified by re-running the relevant check
|
|
41203
41207
|
|
|
41204
41208
|
Do NOT add new features \u2014 only fix valid issues.
|
|
41205
41209
|
Commit your fixes when done.${scopeConstraint}${noTestIsolationBlock(story)}${escapeHatchFor(story)}`;
|
|
@@ -41226,6 +41230,7 @@ ${adversarialErrors}
|
|
|
41226
41230
|
1. Read the relevant files to verify each finding is a real issue
|
|
41227
41231
|
2. Only fix findings that are actually valid problems
|
|
41228
41232
|
3. Do NOT add keys, functions, or imports that already exist \u2014 check first
|
|
41233
|
+
4. Break the fix into one small step per valid finding before touching code, each verified by re-running the relevant check
|
|
41229
41234
|
|
|
41230
41235
|
Do NOT add new features \u2014 only fix valid issues.
|
|
41231
41236
|
Commit your fixes when done.${scopeConstraint}${noTestIsolationBlock(story)}${escapeHatchFor(story)}`;
|
|
@@ -41491,6 +41496,8 @@ ${findingLines}
|
|
|
41491
41496
|
|
|
41492
41497
|
**Task:** For each bug above, write a NEW failing test that asserts the spec-correct behavior described in the finding. The test should FAIL with the current (buggy) implementation and PASS once the implementer fixes the source.
|
|
41493
41498
|
|
|
41499
|
+
Break the work into one small task per bug before writing: for each, note the failing test's name and which spec-correct behavior it pins down.
|
|
41500
|
+
|
|
41494
41501
|
Rules:
|
|
41495
41502
|
1. Write the test against the SPECIFICATION, not the current behavior.
|
|
41496
41503
|
2. Do NOT fix the source files \u2014 only write test files.
|
|
@@ -41518,6 +41525,8 @@ ${fileList}
|
|
|
41518
41525
|
### Implementer handoff
|
|
41519
41526
|
${reason}
|
|
41520
41527
|
|
|
41528
|
+
Break the work into one small task per listed file before editing: for each, note how its mock setup and dispatch wiring must change to match the AC-mandated dispatch shape.
|
|
41529
|
+
|
|
41521
41530
|
Rules:
|
|
41522
41531
|
1. Modify ONLY the files listed above.
|
|
41523
41532
|
2. Do NOT modify any source file.
|
|
@@ -41556,7 +41565,8 @@ Before making any changes:
|
|
|
41556
41565
|
2. Do NOT loosen assertions to match current implementation behavior. If a test is failing because the source is wrong, the source is the suspect \u2014 not the test.
|
|
41557
41566
|
3. Do NOT delete a failing test because the implementation makes it hard to assert on. Refactor the test structure if needed; never silently drop coverage.
|
|
41558
41567
|
4. If the current behavior disagrees with the acceptance criteria, write the test against the spec and let the implementer fix the source.
|
|
41559
|
-
5. Do NOT modify source implementation files
|
|
41568
|
+
5. Do NOT modify source implementation files.
|
|
41569
|
+
6. Break the work into one small change per flagged test before editing, each verified by re-running that test.`;
|
|
41560
41570
|
return `${opener}
|
|
41561
41571
|
|
|
41562
41572
|
Story: ${story.title} (${story.id})
|
|
@@ -41746,7 +41756,7 @@ ${acList}
|
|
|
41746
41756
|
### Findings
|
|
41747
41757
|
${llmSection}
|
|
41748
41758
|
|
|
41749
|
-
**Important:** LLM reviewers may flag false positives. Before making changes for LLM review findings, read the relevant files to verify each finding is a real issue. Do NOT add keys, functions, or imports that already exist.
|
|
41759
|
+
**Important:** LLM reviewers may flag false positives. Before making changes for LLM review findings, read the relevant files to verify each finding is a real issue, then break the fix into one small step per valid finding before touching code, each verified by re-running the relevant check. Do NOT add keys, functions, or imports that already exist.
|
|
41750
41760
|
|
|
41751
41761
|
Do NOT add new features \u2014 only fix the identified issues.
|
|
41752
41762
|
Commit your fixes when done.${scopeConstraint}${escapeHatchFor(story)}`;
|
|
@@ -41904,7 +41914,7 @@ Tests are failing. Fix the source so all tests pass \u2014 not just the ones lis
|
|
|
41904
41914
|
${detail}`);
|
|
41905
41915
|
}
|
|
41906
41916
|
lines.push(`
|
|
41907
|
-
|
|
41917
|
+
Before editing, break the work into one small fix per finding above (fix -> re-run to verify). Then fix the implementation to resolve all verifier findings.`);
|
|
41908
41918
|
return lines.join(`
|
|
41909
41919
|
`);
|
|
41910
41920
|
}
|
|
@@ -48161,8 +48171,9 @@ ${request.summary}
|
|
|
48161
48171
|
if (!this.rl) {
|
|
48162
48172
|
throw new Error("CLI plugin not initialized");
|
|
48163
48173
|
}
|
|
48174
|
+
let timeoutId;
|
|
48164
48175
|
const timeoutPromise = new Promise((resolve13) => {
|
|
48165
|
-
setTimeout(() => {
|
|
48176
|
+
timeoutId = setTimeout(() => {
|
|
48166
48177
|
resolve13({
|
|
48167
48178
|
requestId: request.id,
|
|
48168
48179
|
action: "skip",
|
|
@@ -48172,8 +48183,12 @@ ${request.summary}
|
|
|
48172
48183
|
}, timeout);
|
|
48173
48184
|
});
|
|
48174
48185
|
const userPromise = this.getUserInput(request);
|
|
48175
|
-
|
|
48176
|
-
|
|
48186
|
+
try {
|
|
48187
|
+
return await Promise.race([userPromise, timeoutPromise]);
|
|
48188
|
+
} finally {
|
|
48189
|
+
if (timeoutId !== undefined)
|
|
48190
|
+
clearTimeout(timeoutId);
|
|
48191
|
+
}
|
|
48177
48192
|
}
|
|
48178
48193
|
async getUserInput(request) {
|
|
48179
48194
|
if (!this.rl) {
|
|
@@ -55483,7 +55498,16 @@ var init_routing2 = __esm(() => {
|
|
|
55483
55498
|
const TIER_RANK = { fast: 0, balanced: 1, powerful: 2 };
|
|
55484
55499
|
const derivedTier = decision.modelTier;
|
|
55485
55500
|
const previousTier = ctx.story.routing?.modelTier;
|
|
55486
|
-
const
|
|
55501
|
+
const previousRank = previousTier !== undefined ? TIER_RANK[previousTier] : undefined;
|
|
55502
|
+
const derivedRank = TIER_RANK[derivedTier];
|
|
55503
|
+
if (previousTier !== undefined && previousRank === undefined) {
|
|
55504
|
+
logger?.warn("routing", "Ignoring unknown previousTier \u2014 not escalating", {
|
|
55505
|
+
storyId: ctx.story.id,
|
|
55506
|
+
previousTier,
|
|
55507
|
+
derivedTier
|
|
55508
|
+
});
|
|
55509
|
+
}
|
|
55510
|
+
const isEscalated = previousTier !== undefined && previousRank !== undefined && derivedRank !== undefined && previousRank > derivedRank;
|
|
55487
55511
|
const modelTier = isEscalated ? previousTier : derivedTier;
|
|
55488
55512
|
const routing = { ...decision, modelTier, agent: ctx.story.routing?.agent };
|
|
55489
55513
|
ctx.story.routing = {
|
|
@@ -55590,6 +55614,7 @@ var init_pipeline = __esm(() => {
|
|
|
55590
55614
|
init_runner4();
|
|
55591
55615
|
init_events();
|
|
55592
55616
|
init_stages();
|
|
55617
|
+
init_event_bus();
|
|
55593
55618
|
});
|
|
55594
55619
|
|
|
55595
55620
|
// src/cli/prompts-shared.ts
|
|
@@ -58150,12 +58175,12 @@ var init_loader4 = __esm(() => {
|
|
|
58150
58175
|
});
|
|
58151
58176
|
|
|
58152
58177
|
// src/utils/paths.ts
|
|
58153
|
-
import { join as
|
|
58178
|
+
import { join as join63 } from "path";
|
|
58154
58179
|
function getRunsDir() {
|
|
58155
|
-
return process.env.NAX_RUNS_DIR ??
|
|
58180
|
+
return process.env.NAX_RUNS_DIR ?? join63(globalConfigDir(), "runs");
|
|
58156
58181
|
}
|
|
58157
58182
|
function getEventsRootDir() {
|
|
58158
|
-
return
|
|
58183
|
+
return join63(globalConfigDir(), "events");
|
|
58159
58184
|
}
|
|
58160
58185
|
var init_paths3 = __esm(() => {
|
|
58161
58186
|
init_paths();
|
|
@@ -58215,7 +58240,7 @@ var init_command_argv = __esm(() => {
|
|
|
58215
58240
|
});
|
|
58216
58241
|
|
|
58217
58242
|
// src/hooks/runner.ts
|
|
58218
|
-
import { join as
|
|
58243
|
+
import { join as join70 } from "path";
|
|
58219
58244
|
function createDrainDeadline2(deadlineMs) {
|
|
58220
58245
|
let timeoutId;
|
|
58221
58246
|
const promise2 = new Promise((resolve16) => {
|
|
@@ -58234,14 +58259,14 @@ async function loadHooksConfig(projectDir, globalDir) {
|
|
|
58234
58259
|
let globalHooks = { hooks: {} };
|
|
58235
58260
|
let projectHooks = { hooks: {} };
|
|
58236
58261
|
let skipGlobal = false;
|
|
58237
|
-
const projectPath =
|
|
58262
|
+
const projectPath = join70(projectDir, "hooks.json");
|
|
58238
58263
|
const projectData = await loadJsonFile(projectPath, "hooks");
|
|
58239
58264
|
if (projectData) {
|
|
58240
58265
|
projectHooks = projectData;
|
|
58241
58266
|
skipGlobal = projectData.skipGlobal ?? false;
|
|
58242
58267
|
}
|
|
58243
58268
|
if (!skipGlobal && globalDir) {
|
|
58244
|
-
const globalPath =
|
|
58269
|
+
const globalPath = join70(globalDir, "hooks.json");
|
|
58245
58270
|
const globalData = await loadJsonFile(globalPath, "hooks");
|
|
58246
58271
|
if (globalData) {
|
|
58247
58272
|
globalHooks = globalData;
|
|
@@ -58411,7 +58436,7 @@ var package_default;
|
|
|
58411
58436
|
var init_package = __esm(() => {
|
|
58412
58437
|
package_default = {
|
|
58413
58438
|
name: "@nathapp/nax",
|
|
58414
|
-
version: "0.68.
|
|
58439
|
+
version: "0.68.6",
|
|
58415
58440
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
58416
58441
|
type: "module",
|
|
58417
58442
|
bin: {
|
|
@@ -58506,8 +58531,8 @@ var init_version = __esm(() => {
|
|
|
58506
58531
|
NAX_VERSION = package_default.version;
|
|
58507
58532
|
NAX_COMMIT = (() => {
|
|
58508
58533
|
try {
|
|
58509
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
58510
|
-
return "
|
|
58534
|
+
if (/^[0-9a-f]{6,10}$/.test("acc1d4bd"))
|
|
58535
|
+
return "acc1d4bd";
|
|
58511
58536
|
} catch {}
|
|
58512
58537
|
try {
|
|
58513
58538
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -58528,9 +58553,9 @@ var init_version = __esm(() => {
|
|
|
58528
58553
|
// src/execution/crash-heartbeat.ts
|
|
58529
58554
|
import { appendFileSync as appendFileSync2 } from "fs";
|
|
58530
58555
|
async function heartbeatLoop(statusWriter, getTotalCost, getIterations, jsonlFilePath) {
|
|
58531
|
-
const logger = getSafeLogger();
|
|
58556
|
+
const logger = _heartbeatDeps.getSafeLogger();
|
|
58532
58557
|
while (heartbeatActive) {
|
|
58533
|
-
await
|
|
58558
|
+
await _heartbeatDeps.sleep(60000);
|
|
58534
58559
|
if (!heartbeatActive)
|
|
58535
58560
|
break;
|
|
58536
58561
|
try {
|
|
@@ -58559,10 +58584,14 @@ async function heartbeatLoop(statusWriter, getTotalCost, getIterations, jsonlFil
|
|
|
58559
58584
|
}
|
|
58560
58585
|
}
|
|
58561
58586
|
function startHeartbeat(statusWriter, getTotalCost, getIterations, jsonlFilePath) {
|
|
58562
|
-
const logger = getSafeLogger();
|
|
58587
|
+
const logger = _heartbeatDeps.getSafeLogger();
|
|
58563
58588
|
stopHeartbeat();
|
|
58564
58589
|
heartbeatActive = true;
|
|
58565
|
-
heartbeatLoop(statusWriter, getTotalCost, getIterations, jsonlFilePath).catch(() => {
|
|
58590
|
+
heartbeatLoop(statusWriter, getTotalCost, getIterations, jsonlFilePath).catch((err) => {
|
|
58591
|
+
_heartbeatDeps.getSafeLogger()?.warn("crash-recovery", "Heartbeat loop crashed; status updates stopped", {
|
|
58592
|
+
error: err instanceof Error ? err.message : String(err)
|
|
58593
|
+
});
|
|
58594
|
+
});
|
|
58566
58595
|
logger?.debug("crash-recovery", "Heartbeat started (60s interval)");
|
|
58567
58596
|
}
|
|
58568
58597
|
function stopHeartbeat() {
|
|
@@ -58571,9 +58600,13 @@ function stopHeartbeat() {
|
|
|
58571
58600
|
getSafeLogger()?.debug("crash-recovery", "Heartbeat stopped");
|
|
58572
58601
|
}
|
|
58573
58602
|
}
|
|
58574
|
-
var heartbeatActive = false;
|
|
58603
|
+
var _heartbeatDeps, heartbeatActive = false;
|
|
58575
58604
|
var init_crash_heartbeat = __esm(() => {
|
|
58576
58605
|
init_logger2();
|
|
58606
|
+
_heartbeatDeps = {
|
|
58607
|
+
sleep: async (ms) => Bun.sleep(ms),
|
|
58608
|
+
getSafeLogger
|
|
58609
|
+
};
|
|
58577
58610
|
});
|
|
58578
58611
|
|
|
58579
58612
|
// src/execution/crash-writer.ts
|
|
@@ -59376,15 +59409,15 @@ var init_acceptance_loop = __esm(() => {
|
|
|
59376
59409
|
|
|
59377
59410
|
// src/session/scratch-purge.ts
|
|
59378
59411
|
import { mkdir as mkdir13, rename, rm } from "fs/promises";
|
|
59379
|
-
import { dirname as dirname12, join as
|
|
59412
|
+
import { dirname as dirname12, join as join71 } from "path";
|
|
59380
59413
|
async function purgeStaleScratch(projectDir, featureName, retentionDays, archiveInsteadOfDelete = false) {
|
|
59381
|
-
const sessionsDir =
|
|
59414
|
+
const sessionsDir = join71(projectDir, ".nax", "features", featureName, "sessions");
|
|
59382
59415
|
const sessionIds = await _scratchPurgeDeps.listSessionDirs(sessionsDir);
|
|
59383
59416
|
const cutoffMs = _scratchPurgeDeps.now() - retentionDays * 86400000;
|
|
59384
59417
|
let purged = 0;
|
|
59385
59418
|
for (const sessionId of sessionIds) {
|
|
59386
|
-
const sessionDir =
|
|
59387
|
-
const descriptorPath =
|
|
59419
|
+
const sessionDir = join71(sessionsDir, sessionId);
|
|
59420
|
+
const descriptorPath = join71(sessionDir, "descriptor.json");
|
|
59388
59421
|
if (!await _scratchPurgeDeps.fileExists(descriptorPath))
|
|
59389
59422
|
continue;
|
|
59390
59423
|
let lastActivityAt;
|
|
@@ -59400,7 +59433,7 @@ async function purgeStaleScratch(projectDir, featureName, retentionDays, archive
|
|
|
59400
59433
|
if (new Date(lastActivityAt).getTime() >= cutoffMs)
|
|
59401
59434
|
continue;
|
|
59402
59435
|
if (archiveInsteadOfDelete) {
|
|
59403
|
-
const archiveDest =
|
|
59436
|
+
const archiveDest = join71(projectDir, ".nax", "features", featureName, "_archive", "sessions", sessionId);
|
|
59404
59437
|
await _scratchPurgeDeps.move(sessionDir, archiveDest);
|
|
59405
59438
|
} else {
|
|
59406
59439
|
await _scratchPurgeDeps.remove(sessionDir);
|
|
@@ -59623,6 +59656,13 @@ async function runDeferredRegression(options) {
|
|
|
59623
59656
|
storyOutcomes: {}
|
|
59624
59657
|
};
|
|
59625
59658
|
}
|
|
59659
|
+
for (const storyId of affectedStories) {
|
|
59660
|
+
pipelineEventBus.emit({
|
|
59661
|
+
type: "regression:detected",
|
|
59662
|
+
storyId,
|
|
59663
|
+
failedTests: testSummary.failed
|
|
59664
|
+
});
|
|
59665
|
+
}
|
|
59626
59666
|
let rectificationAttempts = 0;
|
|
59627
59667
|
let storiesRectified = 0;
|
|
59628
59668
|
let currentTestOutput = fullSuiteResult.output;
|
|
@@ -59736,6 +59776,7 @@ var init_run_regression = __esm(() => {
|
|
|
59736
59776
|
init_findings();
|
|
59737
59777
|
init_logger2();
|
|
59738
59778
|
init_operations();
|
|
59779
|
+
init_pipeline();
|
|
59739
59780
|
init_prd();
|
|
59740
59781
|
init_test_runners();
|
|
59741
59782
|
init_git();
|
|
@@ -60133,12 +60174,12 @@ var DEFAULT_MAX_BATCH_SIZE = 4;
|
|
|
60133
60174
|
|
|
60134
60175
|
// src/pipeline/subscribers/events-writer.ts
|
|
60135
60176
|
import { appendFile as appendFile4, mkdir as mkdir14 } from "fs/promises";
|
|
60136
|
-
import { basename as
|
|
60177
|
+
import { basename as basename13, join as join72 } from "path";
|
|
60137
60178
|
function wireEventsWriter(bus, feature, runId, workdir) {
|
|
60138
60179
|
const logger = getSafeLogger();
|
|
60139
|
-
const project =
|
|
60140
|
-
const eventsDir =
|
|
60141
|
-
const eventsFile =
|
|
60180
|
+
const project = basename13(workdir);
|
|
60181
|
+
const eventsDir = join72(getEventsRootDir(), project);
|
|
60182
|
+
const eventsFile = join72(eventsDir, "events.jsonl");
|
|
60142
60183
|
let dirReady = false;
|
|
60143
60184
|
const write = (line) => {
|
|
60144
60185
|
return (async () => {
|
|
@@ -60319,12 +60360,12 @@ var init_interaction2 = __esm(() => {
|
|
|
60319
60360
|
|
|
60320
60361
|
// src/pipeline/subscribers/registry.ts
|
|
60321
60362
|
import { mkdir as mkdir15, writeFile as writeFile2 } from "fs/promises";
|
|
60322
|
-
import { basename as
|
|
60363
|
+
import { basename as basename14, join as join73 } from "path";
|
|
60323
60364
|
function wireRegistry(bus, feature, runId, workdir, outputDir) {
|
|
60324
60365
|
const logger = getSafeLogger();
|
|
60325
|
-
const project =
|
|
60326
|
-
const runDir =
|
|
60327
|
-
const metaFile =
|
|
60366
|
+
const project = basename14(workdir);
|
|
60367
|
+
const runDir = join73(getRunsDir(), `${project}-${feature}-${runId}`);
|
|
60368
|
+
const metaFile = join73(runDir, "meta.json");
|
|
60328
60369
|
const unsub = bus.on("run:started", (_ev) => {
|
|
60329
60370
|
return (async () => {
|
|
60330
60371
|
try {
|
|
@@ -60334,8 +60375,8 @@ function wireRegistry(bus, feature, runId, workdir, outputDir) {
|
|
|
60334
60375
|
project,
|
|
60335
60376
|
feature,
|
|
60336
60377
|
workdir,
|
|
60337
|
-
statusPath:
|
|
60338
|
-
eventsDir:
|
|
60378
|
+
statusPath: join73(outputDir, "features", feature, "status.json"),
|
|
60379
|
+
eventsDir: join73(outputDir, "features", feature, "runs"),
|
|
60339
60380
|
registeredAt: new Date().toISOString()
|
|
60340
60381
|
};
|
|
60341
60382
|
await writeFile2(metaFile, JSON.stringify(meta3, null, 2));
|
|
@@ -60580,8 +60621,8 @@ var init_types9 = __esm(() => {
|
|
|
60580
60621
|
});
|
|
60581
60622
|
|
|
60582
60623
|
// src/worktree/dependencies.ts
|
|
60583
|
-
import { existsSync as
|
|
60584
|
-
import { join as
|
|
60624
|
+
import { existsSync as existsSync31 } from "fs";
|
|
60625
|
+
import { join as join74 } from "path";
|
|
60585
60626
|
async function prepareWorktreeDependencies(options) {
|
|
60586
60627
|
const mode = options.config.execution.worktreeDependencies.mode;
|
|
60587
60628
|
const resolvedCwd = resolveDependencyCwd(options);
|
|
@@ -60595,7 +60636,7 @@ async function prepareWorktreeDependencies(options) {
|
|
|
60595
60636
|
}
|
|
60596
60637
|
}
|
|
60597
60638
|
function resolveDependencyCwd(options) {
|
|
60598
|
-
return options.storyWorkdir ?
|
|
60639
|
+
return options.storyWorkdir ? join74(options.worktreeRoot, options.storyWorkdir) : options.worktreeRoot;
|
|
60599
60640
|
}
|
|
60600
60641
|
function resolveInheritedDependencies(options, resolvedCwd) {
|
|
60601
60642
|
if (hasDependencyManifests(options.worktreeRoot, resolvedCwd)) {
|
|
@@ -60605,7 +60646,7 @@ function resolveInheritedDependencies(options, resolvedCwd) {
|
|
|
60605
60646
|
}
|
|
60606
60647
|
function hasDependencyManifests(worktreeRoot, resolvedCwd) {
|
|
60607
60648
|
const directories = resolvedCwd === worktreeRoot ? [worktreeRoot] : [worktreeRoot, resolvedCwd];
|
|
60608
|
-
return directories.some((directory) => PHASE_ONE_INHERIT_UNSUPPORTED_FILES.some((filename) => _worktreeDependencyDeps.existsSync(
|
|
60649
|
+
return directories.some((directory) => PHASE_ONE_INHERIT_UNSUPPORTED_FILES.some((filename) => _worktreeDependencyDeps.existsSync(join74(directory, filename))));
|
|
60609
60650
|
}
|
|
60610
60651
|
async function provisionDependencies(config2, worktreeRoot, resolvedCwd) {
|
|
60611
60652
|
const setupCommand = config2.execution.worktreeDependencies.setupCommand;
|
|
@@ -60656,7 +60697,7 @@ var init_dependencies = __esm(() => {
|
|
|
60656
60697
|
"build.gradle.kts"
|
|
60657
60698
|
];
|
|
60658
60699
|
_worktreeDependencyDeps = {
|
|
60659
|
-
existsSync:
|
|
60700
|
+
existsSync: existsSync31,
|
|
60660
60701
|
spawn
|
|
60661
60702
|
};
|
|
60662
60703
|
});
|
|
@@ -60667,19 +60708,19 @@ __export(exports_manager, {
|
|
|
60667
60708
|
_managerDeps: () => _managerDeps,
|
|
60668
60709
|
WorktreeManager: () => WorktreeManager
|
|
60669
60710
|
});
|
|
60670
|
-
import { existsSync as
|
|
60711
|
+
import { existsSync as existsSync32, symlinkSync } from "fs";
|
|
60671
60712
|
import { mkdir as mkdir16 } from "fs/promises";
|
|
60672
|
-
import { join as
|
|
60713
|
+
import { join as join75 } from "path";
|
|
60673
60714
|
|
|
60674
60715
|
class WorktreeManager {
|
|
60675
60716
|
async ensureGitExcludes(projectRoot) {
|
|
60676
60717
|
const logger = getSafeLogger();
|
|
60677
|
-
const infoDir =
|
|
60678
|
-
const excludePath =
|
|
60718
|
+
const infoDir = join75(projectRoot, ".git", "info");
|
|
60719
|
+
const excludePath = join75(infoDir, "exclude");
|
|
60679
60720
|
try {
|
|
60680
60721
|
await mkdir16(infoDir, { recursive: true });
|
|
60681
60722
|
let existing = "";
|
|
60682
|
-
if (
|
|
60723
|
+
if (existsSync32(excludePath)) {
|
|
60683
60724
|
existing = await Bun.file(excludePath).text();
|
|
60684
60725
|
}
|
|
60685
60726
|
const missing = NAX_GITIGNORE_ENTRIES.filter((entry) => !existing.includes(entry));
|
|
@@ -60702,7 +60743,7 @@ ${missing.join(`
|
|
|
60702
60743
|
}
|
|
60703
60744
|
async create(projectRoot, storyId) {
|
|
60704
60745
|
validateStoryId(storyId);
|
|
60705
|
-
const worktreePath =
|
|
60746
|
+
const worktreePath = join75(projectRoot, ".nax-wt", storyId);
|
|
60706
60747
|
const branchName = `nax/${storyId}`;
|
|
60707
60748
|
try {
|
|
60708
60749
|
const pruneProc = _managerDeps.spawn(["git", "worktree", "prune"], {
|
|
@@ -60743,9 +60784,9 @@ ${missing.join(`
|
|
|
60743
60784
|
}
|
|
60744
60785
|
throw new Error(`Failed to create worktree: ${String(error48)}`);
|
|
60745
60786
|
}
|
|
60746
|
-
const envSource =
|
|
60747
|
-
if (
|
|
60748
|
-
const envTarget =
|
|
60787
|
+
const envSource = join75(projectRoot, ".env");
|
|
60788
|
+
if (existsSync32(envSource)) {
|
|
60789
|
+
const envTarget = join75(worktreePath, ".env");
|
|
60749
60790
|
try {
|
|
60750
60791
|
symlinkSync(envSource, envTarget, "file");
|
|
60751
60792
|
} catch (error48) {
|
|
@@ -60756,7 +60797,7 @@ ${missing.join(`
|
|
|
60756
60797
|
}
|
|
60757
60798
|
async remove(projectRoot, storyId) {
|
|
60758
60799
|
validateStoryId(storyId);
|
|
60759
|
-
const worktreePath =
|
|
60800
|
+
const worktreePath = join75(projectRoot, ".nax-wt", storyId);
|
|
60760
60801
|
const branchName = `nax/${storyId}`;
|
|
60761
60802
|
try {
|
|
60762
60803
|
const proc = _managerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
|
|
@@ -61434,6 +61475,12 @@ async function handleTierEscalation(ctx) {
|
|
|
61434
61475
|
runtime: ctx.runtime
|
|
61435
61476
|
});
|
|
61436
61477
|
}
|
|
61478
|
+
pipelineEventBus.emit({
|
|
61479
|
+
type: "story:escalated",
|
|
61480
|
+
storyId: ctx.story.id,
|
|
61481
|
+
fromTier: ctx.routing.modelTier,
|
|
61482
|
+
toTier: escalatedTier
|
|
61483
|
+
});
|
|
61437
61484
|
return {
|
|
61438
61485
|
outcome: "escalated",
|
|
61439
61486
|
prdDirty: true,
|
|
@@ -61444,6 +61491,7 @@ var _tierEscalationDeps;
|
|
|
61444
61491
|
var init_tier_escalation = __esm(() => {
|
|
61445
61492
|
init_hooks();
|
|
61446
61493
|
init_logger2();
|
|
61494
|
+
init_event_bus();
|
|
61447
61495
|
init_prd();
|
|
61448
61496
|
init_routing();
|
|
61449
61497
|
init_llm();
|
|
@@ -61559,10 +61607,10 @@ var init_merge_conflict_rectify = __esm(() => {
|
|
|
61559
61607
|
});
|
|
61560
61608
|
|
|
61561
61609
|
// src/execution/pipeline-result-handler.ts
|
|
61562
|
-
import { join as
|
|
61610
|
+
import { join as join76 } from "path";
|
|
61563
61611
|
async function removeWorktreeDirectory(projectRoot, storyId) {
|
|
61564
61612
|
const logger = getSafeLogger();
|
|
61565
|
-
const worktreePath =
|
|
61613
|
+
const worktreePath = join76(projectRoot, ".nax-wt", storyId);
|
|
61566
61614
|
try {
|
|
61567
61615
|
const proc = _resultHandlerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
|
|
61568
61616
|
cwd: projectRoot,
|
|
@@ -61692,6 +61740,11 @@ async function handlePipelineFailure(ctx, pipelineResult) {
|
|
|
61692
61740
|
break;
|
|
61693
61741
|
case "skip":
|
|
61694
61742
|
logger?.warn("pipeline", "Story skipped", { storyId: ctx.story.id, reason: pipelineResult.reason });
|
|
61743
|
+
pipelineEventBus.emit({
|
|
61744
|
+
type: "story:skipped",
|
|
61745
|
+
storyId: ctx.story.id,
|
|
61746
|
+
reason: pipelineResult.reason || "Story skipped"
|
|
61747
|
+
});
|
|
61695
61748
|
prdDirty = true;
|
|
61696
61749
|
break;
|
|
61697
61750
|
case "fail":
|
|
@@ -61772,8 +61825,8 @@ var init_pipeline_result_handler = __esm(() => {
|
|
|
61772
61825
|
});
|
|
61773
61826
|
|
|
61774
61827
|
// src/execution/iteration-runner.ts
|
|
61775
|
-
import { existsSync as
|
|
61776
|
-
import { join as
|
|
61828
|
+
import { existsSync as existsSync33 } from "fs";
|
|
61829
|
+
import { join as join77 } from "path";
|
|
61777
61830
|
async function runIteration(ctx, prd, selection, iterations, totalCost, allStoryMetrics) {
|
|
61778
61831
|
const { story, storiesToExecute, routing, isBatchExecution } = selection;
|
|
61779
61832
|
if (ctx.dryRun) {
|
|
@@ -61798,7 +61851,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
61798
61851
|
const storyStartTime = Date.now();
|
|
61799
61852
|
let effectiveWorkdir = ctx.workdir;
|
|
61800
61853
|
if (ctx.config.execution.storyIsolation === "worktree") {
|
|
61801
|
-
const worktreePath =
|
|
61854
|
+
const worktreePath = join77(ctx.workdir, ".nax-wt", story.id);
|
|
61802
61855
|
const worktreeExists = _iterationRunnerDeps.existsSync(worktreePath);
|
|
61803
61856
|
if (!worktreeExists) {
|
|
61804
61857
|
await _iterationRunnerDeps.worktreeManager.ensureGitExcludes(ctx.workdir);
|
|
@@ -61818,7 +61871,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
61818
61871
|
}
|
|
61819
61872
|
const accumulatedAttemptCost = (story.priorFailures || []).reduce((sum, f) => sum + (f.cost || 0), 0);
|
|
61820
61873
|
const profileOverride = ctx.config.profile && ctx.config.profile !== "default" ? { profile: ctx.config.profile } : undefined;
|
|
61821
|
-
const effectiveConfig = story.workdir ? await _iterationRunnerDeps.loadConfigForWorkdir(
|
|
61874
|
+
const effectiveConfig = story.workdir ? await _iterationRunnerDeps.loadConfigForWorkdir(join77(ctx.workdir, ".nax", "config.json"), story.workdir, profileOverride) : ctx.config;
|
|
61822
61875
|
let dependencyContext;
|
|
61823
61876
|
if (ctx.config.execution.storyIsolation === "worktree") {
|
|
61824
61877
|
try {
|
|
@@ -61845,7 +61898,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
61845
61898
|
};
|
|
61846
61899
|
}
|
|
61847
61900
|
}
|
|
61848
|
-
const resolvedWorkdir = dependencyContext?.cwd ? dependencyContext.cwd : ctx.config.execution.storyIsolation === "worktree" ? story.workdir ?
|
|
61901
|
+
const resolvedWorkdir = dependencyContext?.cwd ? dependencyContext.cwd : ctx.config.execution.storyIsolation === "worktree" ? story.workdir ? join77(effectiveWorkdir, story.workdir) : effectiveWorkdir : story.workdir ? join77(ctx.workdir, story.workdir) : ctx.workdir;
|
|
61849
61902
|
const pipelineContext = {
|
|
61850
61903
|
config: effectiveConfig,
|
|
61851
61904
|
rootConfig: ctx.config,
|
|
@@ -61977,7 +62030,7 @@ var init_iteration_runner = __esm(() => {
|
|
|
61977
62030
|
loadConfigForWorkdir,
|
|
61978
62031
|
prepareWorktreeDependencies,
|
|
61979
62032
|
runPipeline,
|
|
61980
|
-
existsSync:
|
|
62033
|
+
existsSync: existsSync33,
|
|
61981
62034
|
worktreeManager: new WorktreeManager
|
|
61982
62035
|
};
|
|
61983
62036
|
});
|
|
@@ -61988,7 +62041,7 @@ function selectNextStories(prd, config2, batchPlan, currentBatchIndex, lastStory
|
|
|
61988
62041
|
const batch = batchPlan[currentBatchIndex];
|
|
61989
62042
|
const storiesToExecute = batch.stories.filter((s) => !s.passes && s.status !== "passed" && s.status !== "skipped" && s.status !== "blocked" && s.status !== "failed" && s.status !== "paused" && s.status !== "decomposed");
|
|
61990
62043
|
if (storiesToExecute.length === 0) {
|
|
61991
|
-
return
|
|
62044
|
+
return null;
|
|
61992
62045
|
}
|
|
61993
62046
|
const story2 = storiesToExecute[0];
|
|
61994
62047
|
return {
|
|
@@ -62047,7 +62100,7 @@ __export(exports_parallel_worker, {
|
|
|
62047
62100
|
buildWorktreePipelineContext: () => buildWorktreePipelineContext,
|
|
62048
62101
|
_parallelWorkerDeps: () => _parallelWorkerDeps
|
|
62049
62102
|
});
|
|
62050
|
-
import { join as
|
|
62103
|
+
import { join as join78 } from "path";
|
|
62051
62104
|
function buildWorktreePipelineContext(base, _story) {
|
|
62052
62105
|
return { ...base, prd: structuredClone(base.prd) };
|
|
62053
62106
|
}
|
|
@@ -62070,7 +62123,7 @@ async function executeStoryInWorktree(story, worktreePath, dependencyContext, co
|
|
|
62070
62123
|
story,
|
|
62071
62124
|
stories: [story],
|
|
62072
62125
|
projectDir: context.projectDir,
|
|
62073
|
-
workdir: dependencyContext.cwd ?? (story.workdir ?
|
|
62126
|
+
workdir: dependencyContext.cwd ?? (story.workdir ? join78(worktreePath, story.workdir) : worktreePath),
|
|
62074
62127
|
worktreeDependencyContext: dependencyContext,
|
|
62075
62128
|
routing,
|
|
62076
62129
|
storyGitRef: storyGitRef ?? undefined
|
|
@@ -62195,10 +62248,27 @@ async function runParallelBatch(options) {
|
|
|
62195
62248
|
const rootConfigPath = path21.join(workdir, ".nax", "config.json");
|
|
62196
62249
|
const profileOverride = config2.profile && config2.profile !== "default" ? { profile: config2.profile } : undefined;
|
|
62197
62250
|
const storyEffectiveConfigs = new Map;
|
|
62198
|
-
await Promise.
|
|
62199
|
-
|
|
62200
|
-
|
|
62251
|
+
const configResults = await Promise.allSettled(stories.filter((story) => story.workdir).map(async (story) => {
|
|
62252
|
+
try {
|
|
62253
|
+
const effectiveConfig = await _parallelBatchDeps.loadConfigForWorkdir(rootConfigPath, story.workdir, profileOverride);
|
|
62254
|
+
return { storyId: story.id, effectiveConfig };
|
|
62255
|
+
} catch (err) {
|
|
62256
|
+
const enriched = new Error(err instanceof Error ? err.message : String(err));
|
|
62257
|
+
enriched.storyId = story.id;
|
|
62258
|
+
throw enriched;
|
|
62259
|
+
}
|
|
62201
62260
|
}));
|
|
62261
|
+
for (const result of configResults) {
|
|
62262
|
+
if (result.status === "fulfilled") {
|
|
62263
|
+
storyEffectiveConfigs.set(result.value.storyId, result.value.effectiveConfig);
|
|
62264
|
+
} else {
|
|
62265
|
+
const storyId = result.reason?.storyId ?? "(unknown)";
|
|
62266
|
+
logger?.warn("parallel-batch", "Failed to load per-story config; using root config", {
|
|
62267
|
+
storyId,
|
|
62268
|
+
reason: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
62269
|
+
});
|
|
62270
|
+
}
|
|
62271
|
+
}
|
|
62202
62272
|
const dependencyContexts = new Map;
|
|
62203
62273
|
const readyStories = [];
|
|
62204
62274
|
const preExecutionFailures = [];
|
|
@@ -62357,7 +62427,8 @@ var init_parallel_batch = __esm(() => {
|
|
|
62357
62427
|
const { rectifyConflictedStory: rectifyConflictedStory2 } = await Promise.resolve().then(() => (init_merge_conflict_rectify(), exports_merge_conflict_rectify));
|
|
62358
62428
|
return rectifyConflictedStory2(opts);
|
|
62359
62429
|
},
|
|
62360
|
-
prepareWorktreeDependencies
|
|
62430
|
+
prepareWorktreeDependencies,
|
|
62431
|
+
loadConfigForWorkdir
|
|
62361
62432
|
};
|
|
62362
62433
|
});
|
|
62363
62434
|
|
|
@@ -62725,6 +62796,8 @@ async function executeUnified(ctx, initialPrd) {
|
|
|
62725
62796
|
if (!selected)
|
|
62726
62797
|
return buildResult2("no-stories");
|
|
62727
62798
|
const { selection } = selected;
|
|
62799
|
+
if (!selection)
|
|
62800
|
+
return buildResult2("no-stories");
|
|
62728
62801
|
if (!ctx.useBatch)
|
|
62729
62802
|
lastStoryId = selection.story.id;
|
|
62730
62803
|
{
|
|
@@ -62931,7 +63004,7 @@ async function writeStatusFile(filePath, status) {
|
|
|
62931
63004
|
var init_status_file = () => {};
|
|
62932
63005
|
|
|
62933
63006
|
// src/execution/status-writer.ts
|
|
62934
|
-
import { join as
|
|
63007
|
+
import { join as join79 } from "path";
|
|
62935
63008
|
|
|
62936
63009
|
class StatusWriter {
|
|
62937
63010
|
statusFile;
|
|
@@ -63050,7 +63123,7 @@ class StatusWriter {
|
|
|
63050
63123
|
if (!this._prd)
|
|
63051
63124
|
return;
|
|
63052
63125
|
const safeLogger = getSafeLogger();
|
|
63053
|
-
const featureStatusPath =
|
|
63126
|
+
const featureStatusPath = join79(featureDir, "status.json");
|
|
63054
63127
|
const write = async () => {
|
|
63055
63128
|
try {
|
|
63056
63129
|
const base = this.getSnapshot(totalCost, iterations);
|
|
@@ -63081,11 +63154,11 @@ __export(exports_migrate, {
|
|
|
63081
63154
|
migrateCommand: () => migrateCommand,
|
|
63082
63155
|
detectGeneratedContent: () => detectGeneratedContent
|
|
63083
63156
|
});
|
|
63084
|
-
import { existsSync as
|
|
63157
|
+
import { existsSync as existsSync34 } from "fs";
|
|
63085
63158
|
import { mkdir as mkdir17, readdir as readdir6, rename as rename3 } from "fs/promises";
|
|
63086
63159
|
import path22 from "path";
|
|
63087
63160
|
async function detectGeneratedContent(naxDir) {
|
|
63088
|
-
if (!
|
|
63161
|
+
if (!existsSync34(naxDir))
|
|
63089
63162
|
return [];
|
|
63090
63163
|
const candidates = [];
|
|
63091
63164
|
let entries = [];
|
|
@@ -63100,7 +63173,7 @@ async function detectGeneratedContent(naxDir) {
|
|
|
63100
63173
|
}
|
|
63101
63174
|
}
|
|
63102
63175
|
const featuresDir = path22.join(naxDir, "features");
|
|
63103
|
-
if (
|
|
63176
|
+
if (existsSync34(featuresDir)) {
|
|
63104
63177
|
let featureDirs = [];
|
|
63105
63178
|
try {
|
|
63106
63179
|
featureDirs = await readdir6(featuresDir);
|
|
@@ -63162,7 +63235,7 @@ async function migrateCommand(options) {
|
|
|
63162
63235
|
});
|
|
63163
63236
|
}
|
|
63164
63237
|
const src = path22.join(globalConfigDir(), options.reclaim);
|
|
63165
|
-
if (!
|
|
63238
|
+
if (!existsSync34(src)) {
|
|
63166
63239
|
throw new NaxError(`Nothing to reclaim: ~/.nax/${options.reclaim} does not exist`, "MIGRATE_RECLAIM_NOT_FOUND", {
|
|
63167
63240
|
stage: "migrate",
|
|
63168
63241
|
name: options.reclaim
|
|
@@ -63208,7 +63281,7 @@ async function migrateCommand(options) {
|
|
|
63208
63281
|
}
|
|
63209
63282
|
const naxDir = path22.join(options.workdir, ".nax");
|
|
63210
63283
|
const configPath = path22.join(naxDir, "config.json");
|
|
63211
|
-
if (!
|
|
63284
|
+
if (!existsSync34(configPath)) {
|
|
63212
63285
|
throw new NaxError("No .nax/config.json found \u2014 run nax init first", "MIGRATE_NO_CONFIG", {
|
|
63213
63286
|
stage: "migrate",
|
|
63214
63287
|
workdir: options.workdir
|
|
@@ -63243,7 +63316,7 @@ async function migrateCommand(options) {
|
|
|
63243
63316
|
for (const candidate of candidates) {
|
|
63244
63317
|
const dest = path22.join(destBase, candidate.name);
|
|
63245
63318
|
await mkdir17(path22.dirname(dest), { recursive: true });
|
|
63246
|
-
if (
|
|
63319
|
+
if (existsSync34(dest)) {
|
|
63247
63320
|
throw new NaxError(`Migration conflict: destination already exists.
|
|
63248
63321
|
Source: ${candidate.srcPath}
|
|
63249
63322
|
Destination: ${dest}
|
|
@@ -63484,7 +63557,7 @@ __export(exports_run_initialization, {
|
|
|
63484
63557
|
initializeRun: () => initializeRun,
|
|
63485
63558
|
_reconcileDeps: () => _reconcileDeps
|
|
63486
63559
|
});
|
|
63487
|
-
import { join as
|
|
63560
|
+
import { join as join80 } from "path";
|
|
63488
63561
|
async function reconcileState(prd, prdPath, workdir, config2) {
|
|
63489
63562
|
const logger = getSafeLogger();
|
|
63490
63563
|
let reconciledCount = 0;
|
|
@@ -63501,7 +63574,7 @@ async function reconcileState(prd, prdPath, workdir, config2) {
|
|
|
63501
63574
|
});
|
|
63502
63575
|
continue;
|
|
63503
63576
|
}
|
|
63504
|
-
const effectiveWorkdir = story.workdir ?
|
|
63577
|
+
const effectiveWorkdir = story.workdir ? join80(workdir, story.workdir) : workdir;
|
|
63505
63578
|
try {
|
|
63506
63579
|
const reviewResult = await _reconcileDeps.runReview(config2.review, effectiveWorkdir, config2.execution);
|
|
63507
63580
|
if (!reviewResult.success) {
|
|
@@ -93059,6 +93132,229 @@ var require_stack_utils = __commonJS((exports, module) => {
|
|
|
93059
93132
|
module.exports = StackUtils;
|
|
93060
93133
|
});
|
|
93061
93134
|
|
|
93135
|
+
// node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
93136
|
+
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
93137
|
+
var React11 = __toESM(require_react());
|
|
93138
|
+
(function() {
|
|
93139
|
+
function getComponentNameFromType(type) {
|
|
93140
|
+
if (type == null)
|
|
93141
|
+
return null;
|
|
93142
|
+
if (typeof type === "function")
|
|
93143
|
+
return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
|
93144
|
+
if (typeof type === "string")
|
|
93145
|
+
return type;
|
|
93146
|
+
switch (type) {
|
|
93147
|
+
case REACT_FRAGMENT_TYPE:
|
|
93148
|
+
return "Fragment";
|
|
93149
|
+
case REACT_PROFILER_TYPE:
|
|
93150
|
+
return "Profiler";
|
|
93151
|
+
case REACT_STRICT_MODE_TYPE:
|
|
93152
|
+
return "StrictMode";
|
|
93153
|
+
case REACT_SUSPENSE_TYPE:
|
|
93154
|
+
return "Suspense";
|
|
93155
|
+
case REACT_SUSPENSE_LIST_TYPE:
|
|
93156
|
+
return "SuspenseList";
|
|
93157
|
+
case REACT_ACTIVITY_TYPE:
|
|
93158
|
+
return "Activity";
|
|
93159
|
+
}
|
|
93160
|
+
if (typeof type === "object")
|
|
93161
|
+
switch (typeof type.tag === "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
|
93162
|
+
case REACT_PORTAL_TYPE:
|
|
93163
|
+
return "Portal";
|
|
93164
|
+
case REACT_CONTEXT_TYPE:
|
|
93165
|
+
return type.displayName || "Context";
|
|
93166
|
+
case REACT_CONSUMER_TYPE:
|
|
93167
|
+
return (type._context.displayName || "Context") + ".Consumer";
|
|
93168
|
+
case REACT_FORWARD_REF_TYPE:
|
|
93169
|
+
var innerType = type.render;
|
|
93170
|
+
type = type.displayName;
|
|
93171
|
+
type || (type = innerType.displayName || innerType.name || "", type = type !== "" ? "ForwardRef(" + type + ")" : "ForwardRef");
|
|
93172
|
+
return type;
|
|
93173
|
+
case REACT_MEMO_TYPE:
|
|
93174
|
+
return innerType = type.displayName || null, innerType !== null ? innerType : getComponentNameFromType(type.type) || "Memo";
|
|
93175
|
+
case REACT_LAZY_TYPE:
|
|
93176
|
+
innerType = type._payload;
|
|
93177
|
+
type = type._init;
|
|
93178
|
+
try {
|
|
93179
|
+
return getComponentNameFromType(type(innerType));
|
|
93180
|
+
} catch (x) {}
|
|
93181
|
+
}
|
|
93182
|
+
return null;
|
|
93183
|
+
}
|
|
93184
|
+
function testStringCoercion(value) {
|
|
93185
|
+
return "" + value;
|
|
93186
|
+
}
|
|
93187
|
+
function checkKeyStringCoercion(value) {
|
|
93188
|
+
try {
|
|
93189
|
+
testStringCoercion(value);
|
|
93190
|
+
var JSCompiler_inline_result = false;
|
|
93191
|
+
} catch (e) {
|
|
93192
|
+
JSCompiler_inline_result = true;
|
|
93193
|
+
}
|
|
93194
|
+
if (JSCompiler_inline_result) {
|
|
93195
|
+
JSCompiler_inline_result = console;
|
|
93196
|
+
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
|
93197
|
+
var JSCompiler_inline_result$jscomp$0 = typeof Symbol === "function" && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
|
93198
|
+
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
|
93199
|
+
return testStringCoercion(value);
|
|
93200
|
+
}
|
|
93201
|
+
}
|
|
93202
|
+
function getTaskName(type) {
|
|
93203
|
+
if (type === REACT_FRAGMENT_TYPE)
|
|
93204
|
+
return "<>";
|
|
93205
|
+
if (typeof type === "object" && type !== null && type.$$typeof === REACT_LAZY_TYPE)
|
|
93206
|
+
return "<...>";
|
|
93207
|
+
try {
|
|
93208
|
+
var name = getComponentNameFromType(type);
|
|
93209
|
+
return name ? "<" + name + ">" : "<...>";
|
|
93210
|
+
} catch (x) {
|
|
93211
|
+
return "<...>";
|
|
93212
|
+
}
|
|
93213
|
+
}
|
|
93214
|
+
function getOwner() {
|
|
93215
|
+
var dispatcher = ReactSharedInternals.A;
|
|
93216
|
+
return dispatcher === null ? null : dispatcher.getOwner();
|
|
93217
|
+
}
|
|
93218
|
+
function UnknownOwner() {
|
|
93219
|
+
return Error("react-stack-top-frame");
|
|
93220
|
+
}
|
|
93221
|
+
function hasValidKey(config2) {
|
|
93222
|
+
if (hasOwnProperty.call(config2, "key")) {
|
|
93223
|
+
var getter = Object.getOwnPropertyDescriptor(config2, "key").get;
|
|
93224
|
+
if (getter && getter.isReactWarning)
|
|
93225
|
+
return false;
|
|
93226
|
+
}
|
|
93227
|
+
return config2.key !== undefined;
|
|
93228
|
+
}
|
|
93229
|
+
function defineKeyPropWarningGetter(props, displayName) {
|
|
93230
|
+
function warnAboutAccessingKey() {
|
|
93231
|
+
specialPropKeyWarningShown || (specialPropKeyWarningShown = true, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
|
93232
|
+
}
|
|
93233
|
+
warnAboutAccessingKey.isReactWarning = true;
|
|
93234
|
+
Object.defineProperty(props, "key", {
|
|
93235
|
+
get: warnAboutAccessingKey,
|
|
93236
|
+
configurable: true
|
|
93237
|
+
});
|
|
93238
|
+
}
|
|
93239
|
+
function elementRefGetterWithDeprecationWarning() {
|
|
93240
|
+
var componentName = getComponentNameFromType(this.type);
|
|
93241
|
+
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = true, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
|
93242
|
+
componentName = this.props.ref;
|
|
93243
|
+
return componentName !== undefined ? componentName : null;
|
|
93244
|
+
}
|
|
93245
|
+
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
|
93246
|
+
var refProp = props.ref;
|
|
93247
|
+
type = {
|
|
93248
|
+
$$typeof: REACT_ELEMENT_TYPE,
|
|
93249
|
+
type,
|
|
93250
|
+
key,
|
|
93251
|
+
props,
|
|
93252
|
+
_owner: owner
|
|
93253
|
+
};
|
|
93254
|
+
(refProp !== undefined ? refProp : null) !== null ? Object.defineProperty(type, "ref", {
|
|
93255
|
+
enumerable: false,
|
|
93256
|
+
get: elementRefGetterWithDeprecationWarning
|
|
93257
|
+
}) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
|
|
93258
|
+
type._store = {};
|
|
93259
|
+
Object.defineProperty(type._store, "validated", {
|
|
93260
|
+
configurable: false,
|
|
93261
|
+
enumerable: false,
|
|
93262
|
+
writable: true,
|
|
93263
|
+
value: 0
|
|
93264
|
+
});
|
|
93265
|
+
Object.defineProperty(type, "_debugInfo", {
|
|
93266
|
+
configurable: false,
|
|
93267
|
+
enumerable: false,
|
|
93268
|
+
writable: true,
|
|
93269
|
+
value: null
|
|
93270
|
+
});
|
|
93271
|
+
Object.defineProperty(type, "_debugStack", {
|
|
93272
|
+
configurable: false,
|
|
93273
|
+
enumerable: false,
|
|
93274
|
+
writable: true,
|
|
93275
|
+
value: debugStack
|
|
93276
|
+
});
|
|
93277
|
+
Object.defineProperty(type, "_debugTask", {
|
|
93278
|
+
configurable: false,
|
|
93279
|
+
enumerable: false,
|
|
93280
|
+
writable: true,
|
|
93281
|
+
value: debugTask
|
|
93282
|
+
});
|
|
93283
|
+
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
|
93284
|
+
return type;
|
|
93285
|
+
}
|
|
93286
|
+
function jsxDEVImpl(type, config2, maybeKey, isStaticChildren, debugStack, debugTask) {
|
|
93287
|
+
var children = config2.children;
|
|
93288
|
+
if (children !== undefined)
|
|
93289
|
+
if (isStaticChildren)
|
|
93290
|
+
if (isArrayImpl(children)) {
|
|
93291
|
+
for (isStaticChildren = 0;isStaticChildren < children.length; isStaticChildren++)
|
|
93292
|
+
validateChildKeys(children[isStaticChildren]);
|
|
93293
|
+
Object.freeze && Object.freeze(children);
|
|
93294
|
+
} else
|
|
93295
|
+
console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
|
93296
|
+
else
|
|
93297
|
+
validateChildKeys(children);
|
|
93298
|
+
if (hasOwnProperty.call(config2, "key")) {
|
|
93299
|
+
children = getComponentNameFromType(type);
|
|
93300
|
+
var keys2 = Object.keys(config2).filter(function(k) {
|
|
93301
|
+
return k !== "key";
|
|
93302
|
+
});
|
|
93303
|
+
isStaticChildren = 0 < keys2.length ? "{key: someKey, " + keys2.join(": ..., ") + ": ...}" : "{key: someKey}";
|
|
93304
|
+
didWarnAboutKeySpread[children + isStaticChildren] || (keys2 = 0 < keys2.length ? "{" + keys2.join(": ..., ") + ": ...}" : "{}", console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
93305
|
+
let props = %s;
|
|
93306
|
+
<%s {...props} />
|
|
93307
|
+
React keys must be passed directly to JSX without using spread:
|
|
93308
|
+
let props = %s;
|
|
93309
|
+
<%s key={someKey} {...props} />`, isStaticChildren, children, keys2, children), didWarnAboutKeySpread[children + isStaticChildren] = true);
|
|
93310
|
+
}
|
|
93311
|
+
children = null;
|
|
93312
|
+
maybeKey !== undefined && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
|
93313
|
+
hasValidKey(config2) && (checkKeyStringCoercion(config2.key), children = "" + config2.key);
|
|
93314
|
+
if ("key" in config2) {
|
|
93315
|
+
maybeKey = {};
|
|
93316
|
+
for (var propName in config2)
|
|
93317
|
+
propName !== "key" && (maybeKey[propName] = config2[propName]);
|
|
93318
|
+
} else
|
|
93319
|
+
maybeKey = config2;
|
|
93320
|
+
children && defineKeyPropWarningGetter(maybeKey, typeof type === "function" ? type.displayName || type.name || "Unknown" : type);
|
|
93321
|
+
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
|
93322
|
+
}
|
|
93323
|
+
function validateChildKeys(node) {
|
|
93324
|
+
isValidElement(node) ? node._store && (node._store.validated = 1) : typeof node === "object" && node !== null && node.$$typeof === REACT_LAZY_TYPE && (node._payload.status === "fulfilled" ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
|
93325
|
+
}
|
|
93326
|
+
function isValidElement(object2) {
|
|
93327
|
+
return typeof object2 === "object" && object2 !== null && object2.$$typeof === REACT_ELEMENT_TYPE;
|
|
93328
|
+
}
|
|
93329
|
+
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React11.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
93330
|
+
return null;
|
|
93331
|
+
};
|
|
93332
|
+
React11 = {
|
|
93333
|
+
react_stack_bottom_frame: function(callStackForError) {
|
|
93334
|
+
return callStackForError();
|
|
93335
|
+
}
|
|
93336
|
+
};
|
|
93337
|
+
var specialPropKeyWarningShown;
|
|
93338
|
+
var didWarnAboutElementRef = {};
|
|
93339
|
+
var unknownOwnerDebugStack = React11.react_stack_bottom_frame.bind(React11, UnknownOwner)();
|
|
93340
|
+
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
93341
|
+
var didWarnAboutKeySpread = {};
|
|
93342
|
+
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
93343
|
+
exports.jsxDEV = function(type, config2, maybeKey, isStaticChildren) {
|
|
93344
|
+
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
93345
|
+
return jsxDEVImpl(type, config2, maybeKey, isStaticChildren, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
93346
|
+
};
|
|
93347
|
+
})();
|
|
93348
|
+
});
|
|
93349
|
+
|
|
93350
|
+
// node_modules/react/jsx-dev-runtime.js
|
|
93351
|
+
var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
93352
|
+
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
|
|
93353
|
+
if (false) {} else {
|
|
93354
|
+
module.exports = react_jsx_dev_runtime_development;
|
|
93355
|
+
}
|
|
93356
|
+
});
|
|
93357
|
+
|
|
93062
93358
|
// node_modules/cli-spinners/spinners.json
|
|
93063
93359
|
var require_spinners = __commonJS((exports, module) => {
|
|
93064
93360
|
module.exports = {
|
|
@@ -94699,229 +94995,6 @@ var require_cli_spinners = __commonJS((exports, module) => {
|
|
|
94699
94995
|
module.exports = spinners;
|
|
94700
94996
|
});
|
|
94701
94997
|
|
|
94702
|
-
// node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
94703
|
-
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
94704
|
-
var React12 = __toESM(require_react());
|
|
94705
|
-
(function() {
|
|
94706
|
-
function getComponentNameFromType(type) {
|
|
94707
|
-
if (type == null)
|
|
94708
|
-
return null;
|
|
94709
|
-
if (typeof type === "function")
|
|
94710
|
-
return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
|
94711
|
-
if (typeof type === "string")
|
|
94712
|
-
return type;
|
|
94713
|
-
switch (type) {
|
|
94714
|
-
case REACT_FRAGMENT_TYPE:
|
|
94715
|
-
return "Fragment";
|
|
94716
|
-
case REACT_PROFILER_TYPE:
|
|
94717
|
-
return "Profiler";
|
|
94718
|
-
case REACT_STRICT_MODE_TYPE:
|
|
94719
|
-
return "StrictMode";
|
|
94720
|
-
case REACT_SUSPENSE_TYPE:
|
|
94721
|
-
return "Suspense";
|
|
94722
|
-
case REACT_SUSPENSE_LIST_TYPE:
|
|
94723
|
-
return "SuspenseList";
|
|
94724
|
-
case REACT_ACTIVITY_TYPE:
|
|
94725
|
-
return "Activity";
|
|
94726
|
-
}
|
|
94727
|
-
if (typeof type === "object")
|
|
94728
|
-
switch (typeof type.tag === "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
|
94729
|
-
case REACT_PORTAL_TYPE:
|
|
94730
|
-
return "Portal";
|
|
94731
|
-
case REACT_CONTEXT_TYPE:
|
|
94732
|
-
return type.displayName || "Context";
|
|
94733
|
-
case REACT_CONSUMER_TYPE:
|
|
94734
|
-
return (type._context.displayName || "Context") + ".Consumer";
|
|
94735
|
-
case REACT_FORWARD_REF_TYPE:
|
|
94736
|
-
var innerType = type.render;
|
|
94737
|
-
type = type.displayName;
|
|
94738
|
-
type || (type = innerType.displayName || innerType.name || "", type = type !== "" ? "ForwardRef(" + type + ")" : "ForwardRef");
|
|
94739
|
-
return type;
|
|
94740
|
-
case REACT_MEMO_TYPE:
|
|
94741
|
-
return innerType = type.displayName || null, innerType !== null ? innerType : getComponentNameFromType(type.type) || "Memo";
|
|
94742
|
-
case REACT_LAZY_TYPE:
|
|
94743
|
-
innerType = type._payload;
|
|
94744
|
-
type = type._init;
|
|
94745
|
-
try {
|
|
94746
|
-
return getComponentNameFromType(type(innerType));
|
|
94747
|
-
} catch (x) {}
|
|
94748
|
-
}
|
|
94749
|
-
return null;
|
|
94750
|
-
}
|
|
94751
|
-
function testStringCoercion(value) {
|
|
94752
|
-
return "" + value;
|
|
94753
|
-
}
|
|
94754
|
-
function checkKeyStringCoercion(value) {
|
|
94755
|
-
try {
|
|
94756
|
-
testStringCoercion(value);
|
|
94757
|
-
var JSCompiler_inline_result = false;
|
|
94758
|
-
} catch (e) {
|
|
94759
|
-
JSCompiler_inline_result = true;
|
|
94760
|
-
}
|
|
94761
|
-
if (JSCompiler_inline_result) {
|
|
94762
|
-
JSCompiler_inline_result = console;
|
|
94763
|
-
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
|
94764
|
-
var JSCompiler_inline_result$jscomp$0 = typeof Symbol === "function" && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
|
94765
|
-
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
|
94766
|
-
return testStringCoercion(value);
|
|
94767
|
-
}
|
|
94768
|
-
}
|
|
94769
|
-
function getTaskName(type) {
|
|
94770
|
-
if (type === REACT_FRAGMENT_TYPE)
|
|
94771
|
-
return "<>";
|
|
94772
|
-
if (typeof type === "object" && type !== null && type.$$typeof === REACT_LAZY_TYPE)
|
|
94773
|
-
return "<...>";
|
|
94774
|
-
try {
|
|
94775
|
-
var name = getComponentNameFromType(type);
|
|
94776
|
-
return name ? "<" + name + ">" : "<...>";
|
|
94777
|
-
} catch (x) {
|
|
94778
|
-
return "<...>";
|
|
94779
|
-
}
|
|
94780
|
-
}
|
|
94781
|
-
function getOwner() {
|
|
94782
|
-
var dispatcher = ReactSharedInternals.A;
|
|
94783
|
-
return dispatcher === null ? null : dispatcher.getOwner();
|
|
94784
|
-
}
|
|
94785
|
-
function UnknownOwner() {
|
|
94786
|
-
return Error("react-stack-top-frame");
|
|
94787
|
-
}
|
|
94788
|
-
function hasValidKey(config2) {
|
|
94789
|
-
if (hasOwnProperty.call(config2, "key")) {
|
|
94790
|
-
var getter = Object.getOwnPropertyDescriptor(config2, "key").get;
|
|
94791
|
-
if (getter && getter.isReactWarning)
|
|
94792
|
-
return false;
|
|
94793
|
-
}
|
|
94794
|
-
return config2.key !== undefined;
|
|
94795
|
-
}
|
|
94796
|
-
function defineKeyPropWarningGetter(props, displayName) {
|
|
94797
|
-
function warnAboutAccessingKey() {
|
|
94798
|
-
specialPropKeyWarningShown || (specialPropKeyWarningShown = true, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
|
94799
|
-
}
|
|
94800
|
-
warnAboutAccessingKey.isReactWarning = true;
|
|
94801
|
-
Object.defineProperty(props, "key", {
|
|
94802
|
-
get: warnAboutAccessingKey,
|
|
94803
|
-
configurable: true
|
|
94804
|
-
});
|
|
94805
|
-
}
|
|
94806
|
-
function elementRefGetterWithDeprecationWarning() {
|
|
94807
|
-
var componentName = getComponentNameFromType(this.type);
|
|
94808
|
-
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = true, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
|
94809
|
-
componentName = this.props.ref;
|
|
94810
|
-
return componentName !== undefined ? componentName : null;
|
|
94811
|
-
}
|
|
94812
|
-
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
|
94813
|
-
var refProp = props.ref;
|
|
94814
|
-
type = {
|
|
94815
|
-
$$typeof: REACT_ELEMENT_TYPE,
|
|
94816
|
-
type,
|
|
94817
|
-
key,
|
|
94818
|
-
props,
|
|
94819
|
-
_owner: owner
|
|
94820
|
-
};
|
|
94821
|
-
(refProp !== undefined ? refProp : null) !== null ? Object.defineProperty(type, "ref", {
|
|
94822
|
-
enumerable: false,
|
|
94823
|
-
get: elementRefGetterWithDeprecationWarning
|
|
94824
|
-
}) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
|
|
94825
|
-
type._store = {};
|
|
94826
|
-
Object.defineProperty(type._store, "validated", {
|
|
94827
|
-
configurable: false,
|
|
94828
|
-
enumerable: false,
|
|
94829
|
-
writable: true,
|
|
94830
|
-
value: 0
|
|
94831
|
-
});
|
|
94832
|
-
Object.defineProperty(type, "_debugInfo", {
|
|
94833
|
-
configurable: false,
|
|
94834
|
-
enumerable: false,
|
|
94835
|
-
writable: true,
|
|
94836
|
-
value: null
|
|
94837
|
-
});
|
|
94838
|
-
Object.defineProperty(type, "_debugStack", {
|
|
94839
|
-
configurable: false,
|
|
94840
|
-
enumerable: false,
|
|
94841
|
-
writable: true,
|
|
94842
|
-
value: debugStack
|
|
94843
|
-
});
|
|
94844
|
-
Object.defineProperty(type, "_debugTask", {
|
|
94845
|
-
configurable: false,
|
|
94846
|
-
enumerable: false,
|
|
94847
|
-
writable: true,
|
|
94848
|
-
value: debugTask
|
|
94849
|
-
});
|
|
94850
|
-
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
|
94851
|
-
return type;
|
|
94852
|
-
}
|
|
94853
|
-
function jsxDEVImpl(type, config2, maybeKey, isStaticChildren, debugStack, debugTask) {
|
|
94854
|
-
var children = config2.children;
|
|
94855
|
-
if (children !== undefined)
|
|
94856
|
-
if (isStaticChildren)
|
|
94857
|
-
if (isArrayImpl(children)) {
|
|
94858
|
-
for (isStaticChildren = 0;isStaticChildren < children.length; isStaticChildren++)
|
|
94859
|
-
validateChildKeys(children[isStaticChildren]);
|
|
94860
|
-
Object.freeze && Object.freeze(children);
|
|
94861
|
-
} else
|
|
94862
|
-
console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
|
94863
|
-
else
|
|
94864
|
-
validateChildKeys(children);
|
|
94865
|
-
if (hasOwnProperty.call(config2, "key")) {
|
|
94866
|
-
children = getComponentNameFromType(type);
|
|
94867
|
-
var keys2 = Object.keys(config2).filter(function(k) {
|
|
94868
|
-
return k !== "key";
|
|
94869
|
-
});
|
|
94870
|
-
isStaticChildren = 0 < keys2.length ? "{key: someKey, " + keys2.join(": ..., ") + ": ...}" : "{key: someKey}";
|
|
94871
|
-
didWarnAboutKeySpread[children + isStaticChildren] || (keys2 = 0 < keys2.length ? "{" + keys2.join(": ..., ") + ": ...}" : "{}", console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
94872
|
-
let props = %s;
|
|
94873
|
-
<%s {...props} />
|
|
94874
|
-
React keys must be passed directly to JSX without using spread:
|
|
94875
|
-
let props = %s;
|
|
94876
|
-
<%s key={someKey} {...props} />`, isStaticChildren, children, keys2, children), didWarnAboutKeySpread[children + isStaticChildren] = true);
|
|
94877
|
-
}
|
|
94878
|
-
children = null;
|
|
94879
|
-
maybeKey !== undefined && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
|
94880
|
-
hasValidKey(config2) && (checkKeyStringCoercion(config2.key), children = "" + config2.key);
|
|
94881
|
-
if ("key" in config2) {
|
|
94882
|
-
maybeKey = {};
|
|
94883
|
-
for (var propName in config2)
|
|
94884
|
-
propName !== "key" && (maybeKey[propName] = config2[propName]);
|
|
94885
|
-
} else
|
|
94886
|
-
maybeKey = config2;
|
|
94887
|
-
children && defineKeyPropWarningGetter(maybeKey, typeof type === "function" ? type.displayName || type.name || "Unknown" : type);
|
|
94888
|
-
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
|
94889
|
-
}
|
|
94890
|
-
function validateChildKeys(node) {
|
|
94891
|
-
isValidElement(node) ? node._store && (node._store.validated = 1) : typeof node === "object" && node !== null && node.$$typeof === REACT_LAZY_TYPE && (node._payload.status === "fulfilled" ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
|
94892
|
-
}
|
|
94893
|
-
function isValidElement(object2) {
|
|
94894
|
-
return typeof object2 === "object" && object2 !== null && object2.$$typeof === REACT_ELEMENT_TYPE;
|
|
94895
|
-
}
|
|
94896
|
-
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React12.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
94897
|
-
return null;
|
|
94898
|
-
};
|
|
94899
|
-
React12 = {
|
|
94900
|
-
react_stack_bottom_frame: function(callStackForError) {
|
|
94901
|
-
return callStackForError();
|
|
94902
|
-
}
|
|
94903
|
-
};
|
|
94904
|
-
var specialPropKeyWarningShown;
|
|
94905
|
-
var didWarnAboutElementRef = {};
|
|
94906
|
-
var unknownOwnerDebugStack = React12.react_stack_bottom_frame.bind(React12, UnknownOwner)();
|
|
94907
|
-
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
94908
|
-
var didWarnAboutKeySpread = {};
|
|
94909
|
-
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
94910
|
-
exports.jsxDEV = function(type, config2, maybeKey, isStaticChildren) {
|
|
94911
|
-
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
94912
|
-
return jsxDEVImpl(type, config2, maybeKey, isStaticChildren, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
94913
|
-
};
|
|
94914
|
-
})();
|
|
94915
|
-
});
|
|
94916
|
-
|
|
94917
|
-
// node_modules/react/jsx-dev-runtime.js
|
|
94918
|
-
var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
94919
|
-
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
|
|
94920
|
-
if (false) {} else {
|
|
94921
|
-
module.exports = react_jsx_dev_runtime_development;
|
|
94922
|
-
}
|
|
94923
|
-
});
|
|
94924
|
-
|
|
94925
94998
|
// src/commands/curator.ts
|
|
94926
94999
|
var exports_curator = {};
|
|
94927
95000
|
__export(exports_curator, {
|
|
@@ -94931,15 +95004,15 @@ __export(exports_curator, {
|
|
|
94931
95004
|
curatorCommit: () => curatorCommit,
|
|
94932
95005
|
_curatorCmdDeps: () => _curatorCmdDeps
|
|
94933
95006
|
});
|
|
94934
|
-
import { readdirSync as
|
|
95007
|
+
import { readdirSync as readdirSync8 } from "fs";
|
|
94935
95008
|
import { unlink as unlink4 } from "fs/promises";
|
|
94936
|
-
import { basename as
|
|
95009
|
+
import { basename as basename15, join as join82 } from "path";
|
|
94937
95010
|
function getProjectKey(config2, projectDir) {
|
|
94938
|
-
return config2.name?.trim() ||
|
|
95011
|
+
return config2.name?.trim() || basename15(projectDir);
|
|
94939
95012
|
}
|
|
94940
95013
|
function listRunIds(runsDir) {
|
|
94941
95014
|
try {
|
|
94942
|
-
return
|
|
95015
|
+
return readdirSync8(runsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
94943
95016
|
} catch {
|
|
94944
95017
|
return [];
|
|
94945
95018
|
}
|
|
@@ -95016,7 +95089,7 @@ async function curatorStatus(options) {
|
|
|
95016
95089
|
const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
|
|
95017
95090
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95018
95091
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95019
|
-
const runsDir =
|
|
95092
|
+
const runsDir = join82(outputDir, "runs");
|
|
95020
95093
|
const runIds = listRunIds(runsDir);
|
|
95021
95094
|
let runId;
|
|
95022
95095
|
if (options.run) {
|
|
@@ -95033,8 +95106,8 @@ async function curatorStatus(options) {
|
|
|
95033
95106
|
runId = runIds[runIds.length - 1];
|
|
95034
95107
|
}
|
|
95035
95108
|
console.log(`Run: ${runId}`);
|
|
95036
|
-
const runDir =
|
|
95037
|
-
const observationsPath =
|
|
95109
|
+
const runDir = join82(runsDir, runId);
|
|
95110
|
+
const observationsPath = join82(runDir, "observations.jsonl");
|
|
95038
95111
|
const observations = await parseObservations(observationsPath);
|
|
95039
95112
|
const counts = new Map;
|
|
95040
95113
|
for (const obs of observations) {
|
|
@@ -95044,7 +95117,7 @@ async function curatorStatus(options) {
|
|
|
95044
95117
|
for (const [kind, count] of counts.entries()) {
|
|
95045
95118
|
console.log(` ${kind}: ${count}`);
|
|
95046
95119
|
}
|
|
95047
|
-
const proposalsPath =
|
|
95120
|
+
const proposalsPath = join82(runDir, "curator-proposals.md");
|
|
95048
95121
|
const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
|
|
95049
95122
|
if (proposalText !== null) {
|
|
95050
95123
|
console.log("");
|
|
@@ -95058,8 +95131,8 @@ async function curatorCommit(options) {
|
|
|
95058
95131
|
const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
|
|
95059
95132
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95060
95133
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95061
|
-
const runDir =
|
|
95062
|
-
const proposalsPath =
|
|
95134
|
+
const runDir = join82(outputDir, "runs", options.runId);
|
|
95135
|
+
const proposalsPath = join82(runDir, "curator-proposals.md");
|
|
95063
95136
|
const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
|
|
95064
95137
|
if (proposalText === null) {
|
|
95065
95138
|
console.log(`curator-proposals.md not found for run ${options.runId}.`);
|
|
@@ -95075,7 +95148,7 @@ async function curatorCommit(options) {
|
|
|
95075
95148
|
const dropFileState = new Map;
|
|
95076
95149
|
const skippedDrops = new Set;
|
|
95077
95150
|
for (const drop2 of drops) {
|
|
95078
|
-
const targetPath =
|
|
95151
|
+
const targetPath = join82(resolved.projectDir, drop2.canonicalFile);
|
|
95079
95152
|
if (!dropFileState.has(targetPath)) {
|
|
95080
95153
|
const fileExists2 = await Bun.file(targetPath).exists();
|
|
95081
95154
|
const existing = fileExists2 ? await _curatorCmdDeps.readFile(targetPath).catch(() => "") : "";
|
|
@@ -95109,7 +95182,7 @@ async function curatorCommit(options) {
|
|
|
95109
95182
|
if (skippedDrops.has(drop2)) {
|
|
95110
95183
|
continue;
|
|
95111
95184
|
}
|
|
95112
|
-
const targetPath =
|
|
95185
|
+
const targetPath = join82(resolved.projectDir, drop2.canonicalFile);
|
|
95113
95186
|
const existing = await _curatorCmdDeps.readFile(targetPath).catch(() => "");
|
|
95114
95187
|
const filtered = filterDropContent(existing, drop2.description);
|
|
95115
95188
|
await _curatorCmdDeps.writeFile(targetPath, filtered);
|
|
@@ -95118,7 +95191,7 @@ async function curatorCommit(options) {
|
|
|
95118
95191
|
}
|
|
95119
95192
|
const adds = proposals.filter((p) => p.action === "add" || p.action === "advisory");
|
|
95120
95193
|
for (const add2 of adds) {
|
|
95121
|
-
const targetPath =
|
|
95194
|
+
const targetPath = join82(resolved.projectDir, add2.canonicalFile);
|
|
95122
95195
|
const content = buildAddContent(add2);
|
|
95123
95196
|
await _curatorCmdDeps.appendFile(targetPath, content);
|
|
95124
95197
|
modifiedFiles.add(targetPath);
|
|
@@ -95155,7 +95228,7 @@ async function curatorDryrun(options) {
|
|
|
95155
95228
|
const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
|
|
95156
95229
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95157
95230
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95158
|
-
const runsDir =
|
|
95231
|
+
const runsDir = join82(outputDir, "runs");
|
|
95159
95232
|
const runIds = listRunIds(runsDir);
|
|
95160
95233
|
if (runIds.length === 0) {
|
|
95161
95234
|
console.log("No runs found.");
|
|
@@ -95166,7 +95239,7 @@ async function curatorDryrun(options) {
|
|
|
95166
95239
|
console.log(`Run ${options.run} not found in ${runsDir}.`);
|
|
95167
95240
|
return;
|
|
95168
95241
|
}
|
|
95169
|
-
const observationsPath =
|
|
95242
|
+
const observationsPath = join82(runsDir, runId, "observations.jsonl");
|
|
95170
95243
|
const observations = await parseObservations(observationsPath);
|
|
95171
95244
|
const thresholds = getThresholds(config2);
|
|
95172
95245
|
const proposals = runHeuristics(observations, thresholds);
|
|
@@ -95207,12 +95280,12 @@ async function curatorGc(options) {
|
|
|
95207
95280
|
await _curatorCmdDeps.writeFile(rollupPath, newContent);
|
|
95208
95281
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95209
95282
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95210
|
-
const perRunsDir =
|
|
95283
|
+
const perRunsDir = join82(outputDir, "runs");
|
|
95211
95284
|
for (const runId of uniqueRunIds) {
|
|
95212
95285
|
if (!keepSet.has(runId)) {
|
|
95213
|
-
const runDir =
|
|
95214
|
-
await _curatorCmdDeps.removeFile(
|
|
95215
|
-
await _curatorCmdDeps.removeFile(
|
|
95286
|
+
const runDir = join82(perRunsDir, runId);
|
|
95287
|
+
await _curatorCmdDeps.removeFile(join82(runDir, "observations.jsonl"));
|
|
95288
|
+
await _curatorCmdDeps.removeFile(join82(runDir, "curator-proposals.md"));
|
|
95216
95289
|
}
|
|
95217
95290
|
}
|
|
95218
95291
|
console.log(`[gc] Pruned rollup to ${keep} most recent runs (was ${uniqueRunIds.length}).`);
|
|
@@ -95255,9 +95328,9 @@ var init_curator2 = __esm(() => {
|
|
|
95255
95328
|
|
|
95256
95329
|
// bin/nax.ts
|
|
95257
95330
|
init_source();
|
|
95258
|
-
import { existsSync as
|
|
95331
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync7 } from "fs";
|
|
95259
95332
|
import { homedir as homedir3 } from "os";
|
|
95260
|
-
import { basename as
|
|
95333
|
+
import { basename as basename16, join as join83 } from "path";
|
|
95261
95334
|
|
|
95262
95335
|
// node_modules/commander/esm.mjs
|
|
95263
95336
|
var import__ = __toESM(require_commander(), 1);
|
|
@@ -96413,324 +96486,6 @@ function formatSource(type, sourcePath) {
|
|
|
96413
96486
|
function pad(str, width) {
|
|
96414
96487
|
return str.padEnd(width);
|
|
96415
96488
|
}
|
|
96416
|
-
// src/cli/diagnose.ts
|
|
96417
|
-
init_config();
|
|
96418
|
-
init_logger2();
|
|
96419
|
-
init_prd();
|
|
96420
|
-
init_runtime();
|
|
96421
|
-
import { existsSync as existsSync25, readdirSync as readdirSync5 } from "fs";
|
|
96422
|
-
import { basename as basename12, join as join57 } from "path";
|
|
96423
|
-
|
|
96424
|
-
// src/cli/diagnose-analysis.ts
|
|
96425
|
-
function detectFailurePattern(story, _prd, status) {
|
|
96426
|
-
if (story.status === "passed" && story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))) {
|
|
96427
|
-
return "AUTO_RECOVERED";
|
|
96428
|
-
}
|
|
96429
|
-
if (story.status !== "failed" && story.status !== "blocked" && story.status !== "paused") {
|
|
96430
|
-
return "UNKNOWN";
|
|
96431
|
-
}
|
|
96432
|
-
if (story.failureCategory === "greenfield-no-tests" || story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))) {
|
|
96433
|
-
return "GREENFIELD_TDD";
|
|
96434
|
-
}
|
|
96435
|
-
const testFailingCount = story.priorErrors?.filter((err) => err.toLowerCase().includes("tests-failing")).length || 0;
|
|
96436
|
-
if (testFailingCount >= 2)
|
|
96437
|
-
return "TEST_MISMATCH";
|
|
96438
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("precheck-failed")) || (status?.progress.blocked ?? 0) > 0) {
|
|
96439
|
-
return "ENVIRONMENTAL";
|
|
96440
|
-
}
|
|
96441
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("ratelimited")))
|
|
96442
|
-
return "RATE_LIMITED";
|
|
96443
|
-
if (story.failureCategory === "isolation-violation")
|
|
96444
|
-
return "ISOLATION_VIOLATION";
|
|
96445
|
-
if (status?.run.status === "stalled")
|
|
96446
|
-
return "STALLED";
|
|
96447
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("session-failure")))
|
|
96448
|
-
return "SESSION_CRASH";
|
|
96449
|
-
if (story.attempts > 3)
|
|
96450
|
-
return "MAX_TIERS_EXHAUSTED";
|
|
96451
|
-
return "UNKNOWN";
|
|
96452
|
-
}
|
|
96453
|
-
function getPatternSymptom(pattern) {
|
|
96454
|
-
const symptoms = {
|
|
96455
|
-
GREENFIELD_TDD: "Story attempted in greenfield project with no existing tests",
|
|
96456
|
-
TEST_MISMATCH: "Multiple test failures across attempts",
|
|
96457
|
-
ENVIRONMENTAL: "Environment prechecks failed or blockers detected",
|
|
96458
|
-
RATE_LIMITED: "API rate limit exceeded",
|
|
96459
|
-
ISOLATION_VIOLATION: "Story modified files outside its scope",
|
|
96460
|
-
MAX_TIERS_EXHAUSTED: "Story attempted at all configured model tiers without success",
|
|
96461
|
-
SESSION_CRASH: "Agent session crashed without producing commits",
|
|
96462
|
-
STALLED: "All stories blocked or paused -- no forward progress possible",
|
|
96463
|
-
LOCK_STALE: "Lock file present but process is dead",
|
|
96464
|
-
AUTO_RECOVERED: "Greenfield issue detected but S5 auto-recovery succeeded",
|
|
96465
|
-
UNKNOWN: "Unknown failure pattern"
|
|
96466
|
-
};
|
|
96467
|
-
return symptoms[pattern] ?? "Unknown failure pattern";
|
|
96468
|
-
}
|
|
96469
|
-
function getPatternFixSuggestion(pattern, _story) {
|
|
96470
|
-
const fixes = {
|
|
96471
|
-
GREENFIELD_TDD: "Add --greenfield flag or bootstrap with scaffolding tests first",
|
|
96472
|
-
TEST_MISMATCH: "Review acceptance criteria; tests may be too strict or story underspecified",
|
|
96473
|
-
ENVIRONMENTAL: "Fix precheck issues (deps, env, build) before re-running",
|
|
96474
|
-
RATE_LIMITED: "Wait for rate limit to reset or increase tier limits",
|
|
96475
|
-
ISOLATION_VIOLATION: "Narrow story scope or adjust expectedFiles to allow cross-file changes",
|
|
96476
|
-
MAX_TIERS_EXHAUSTED: "Simplify story or split into smaller sub-stories",
|
|
96477
|
-
SESSION_CRASH: "Check agent logs for crash details; may need manual intervention",
|
|
96478
|
-
STALLED: "Resolve blocked stories or skip them to unblock dependencies",
|
|
96479
|
-
LOCK_STALE: "Run: rm nax.lock",
|
|
96480
|
-
AUTO_RECOVERED: "No action needed -- S5 successfully handled greenfield scenario",
|
|
96481
|
-
UNKNOWN: "Review logs and prior errors for clues"
|
|
96482
|
-
};
|
|
96483
|
-
return fixes[pattern] ?? "Review logs and prior errors for clues";
|
|
96484
|
-
}
|
|
96485
|
-
function generateRecommendations(report) {
|
|
96486
|
-
const recommendations = [];
|
|
96487
|
-
if (report.lockCheck.lockPresent && report.lockCheck.pidAlive === false) {
|
|
96488
|
-
recommendations.push(`Remove stale lock: ${report.lockCheck.fixCommand}`);
|
|
96489
|
-
}
|
|
96490
|
-
const criticalPatterns = report.failureAnalysis.filter((f) => ["ENVIRONMENTAL", "STALLED", "SESSION_CRASH"].includes(f.pattern));
|
|
96491
|
-
if (criticalPatterns.length > 0) {
|
|
96492
|
-
recommendations.push(`Fix ${criticalPatterns.length} critical blocker(s): ${criticalPatterns.map((f) => f.storyId).join(", ")}`);
|
|
96493
|
-
}
|
|
96494
|
-
if (report.failureAnalysis.some((f) => f.pattern === "RATE_LIMITED")) {
|
|
96495
|
-
recommendations.push("Wait for rate limits to reset before re-running");
|
|
96496
|
-
}
|
|
96497
|
-
if (report.failureAnalysis.some((f) => f.pattern === "GREENFIELD_TDD")) {
|
|
96498
|
-
recommendations.push("Consider adding --greenfield flag or bootstrap tests for greenfield stories");
|
|
96499
|
-
}
|
|
96500
|
-
if (report.runSummary.storiesFailed > 0 && recommendations.length === 0) {
|
|
96501
|
-
recommendations.push(`Re-run with: nax run -f ${report.runSummary.feature}`);
|
|
96502
|
-
}
|
|
96503
|
-
if (report.runSummary.storiesFailed === 0 && report.runSummary.storiesPending === 0) {
|
|
96504
|
-
recommendations.push("All stories passed -- feature is complete!");
|
|
96505
|
-
}
|
|
96506
|
-
return recommendations;
|
|
96507
|
-
}
|
|
96508
|
-
function diagnoseStories(prd, status) {
|
|
96509
|
-
const storyBreakdown = [];
|
|
96510
|
-
const failureAnalysis = [];
|
|
96511
|
-
for (const story of prd.userStories) {
|
|
96512
|
-
const pattern = detectFailurePattern(story, prd, status);
|
|
96513
|
-
const diagnosis = {
|
|
96514
|
-
storyId: story.id,
|
|
96515
|
-
title: story.title,
|
|
96516
|
-
status: story.status,
|
|
96517
|
-
attempts: story.attempts,
|
|
96518
|
-
tier: story.routing?.modelTier,
|
|
96519
|
-
strategy: story.routing?.testStrategy,
|
|
96520
|
-
pattern
|
|
96521
|
-
};
|
|
96522
|
-
storyBreakdown.push(diagnosis);
|
|
96523
|
-
if (story.status === "failed" || story.status === "blocked" || story.status === "paused" || pattern === "AUTO_RECOVERED") {
|
|
96524
|
-
diagnosis.symptom = getPatternSymptom(pattern);
|
|
96525
|
-
diagnosis.fixSuggestion = getPatternFixSuggestion(pattern, story);
|
|
96526
|
-
failureAnalysis.push(diagnosis);
|
|
96527
|
-
}
|
|
96528
|
-
}
|
|
96529
|
-
return { storyBreakdown, failureAnalysis };
|
|
96530
|
-
}
|
|
96531
|
-
|
|
96532
|
-
// src/cli/diagnose-formatter.ts
|
|
96533
|
-
init_source();
|
|
96534
|
-
function formatReport(report, verbose) {
|
|
96535
|
-
const lines = [];
|
|
96536
|
-
lines.push(source_default.bold(`
|
|
96537
|
-
Diagnosis Report: ${report.runSummary.feature}
|
|
96538
|
-
`));
|
|
96539
|
-
if (!report.dataSources.eventsFound) {
|
|
96540
|
-
lines.push(source_default.yellow(`[WARN] events.jsonl not found -- diagnosis limited to PRD + git log
|
|
96541
|
-
`));
|
|
96542
|
-
}
|
|
96543
|
-
lines.push(source_default.bold(`Run Summary
|
|
96544
|
-
`));
|
|
96545
|
-
if (report.runSummary.lastRunTime) {
|
|
96546
|
-
lines.push(source_default.dim(` Last Run: ${report.runSummary.lastRunTime}`));
|
|
96547
|
-
}
|
|
96548
|
-
lines.push(source_default.dim(` Status: ${report.runSummary.status}`));
|
|
96549
|
-
lines.push(source_default.green(` Passed: ${report.runSummary.storiesPassed}`));
|
|
96550
|
-
lines.push(source_default.red(` Failed: ${report.runSummary.storiesFailed}`));
|
|
96551
|
-
lines.push(source_default.dim(` Pending: ${report.runSummary.storiesPending}`));
|
|
96552
|
-
if (report.runSummary.cost !== undefined) {
|
|
96553
|
-
lines.push(source_default.dim(` Cost: $${report.runSummary.cost.toFixed(4)}`));
|
|
96554
|
-
}
|
|
96555
|
-
lines.push(source_default.dim(` Commits: ${report.runSummary.commitsProduced}`));
|
|
96556
|
-
lines.push("");
|
|
96557
|
-
if (verbose && report.storyBreakdown.length > 0) {
|
|
96558
|
-
lines.push(source_default.bold(`Story Breakdown
|
|
96559
|
-
`));
|
|
96560
|
-
for (const story of report.storyBreakdown) {
|
|
96561
|
-
const icon = story.status === "passed" ? "[OK]" : story.status === "failed" ? "[FAIL]" : "[ ]";
|
|
96562
|
-
const pattern = story.pattern !== "UNKNOWN" ? source_default.yellow(` [${story.pattern}]`) : "";
|
|
96563
|
-
lines.push(` ${icon} ${story.storyId}: ${story.title}${pattern}`);
|
|
96564
|
-
if (verbose && story.tier) {
|
|
96565
|
-
lines.push(source_default.dim(` Tier: ${story.tier}, Strategy: ${story.strategy}, Attempts: ${story.attempts}`));
|
|
96566
|
-
}
|
|
96567
|
-
}
|
|
96568
|
-
lines.push("");
|
|
96569
|
-
}
|
|
96570
|
-
if (report.failureAnalysis.length > 0) {
|
|
96571
|
-
lines.push(source_default.bold(`Failure Analysis
|
|
96572
|
-
`));
|
|
96573
|
-
for (const failure of report.failureAnalysis) {
|
|
96574
|
-
const level = failure.pattern === "AUTO_RECOVERED" ? source_default.green("INFO") : source_default.red("ERROR");
|
|
96575
|
-
lines.push(` ${level} ${failure.storyId}: ${failure.title}`);
|
|
96576
|
-
lines.push(source_default.dim(` Pattern: ${failure.pattern}`));
|
|
96577
|
-
if (failure.symptom) {
|
|
96578
|
-
lines.push(source_default.dim(` Symptom: ${failure.symptom}`));
|
|
96579
|
-
}
|
|
96580
|
-
if (failure.fixSuggestion) {
|
|
96581
|
-
lines.push(source_default.yellow(` Fix: ${failure.fixSuggestion}`));
|
|
96582
|
-
}
|
|
96583
|
-
lines.push("");
|
|
96584
|
-
}
|
|
96585
|
-
}
|
|
96586
|
-
lines.push(source_default.bold(`Lock Check
|
|
96587
|
-
`));
|
|
96588
|
-
if (!report.lockCheck.lockPresent) {
|
|
96589
|
-
lines.push(source_default.dim(` No lock file present
|
|
96590
|
-
`));
|
|
96591
|
-
} else if (report.lockCheck.pidAlive === false) {
|
|
96592
|
-
lines.push(source_default.red(` [FAIL] Stale lock detected (PID ${report.lockCheck.pid} is dead)`));
|
|
96593
|
-
lines.push(source_default.yellow(` Fix: ${report.lockCheck.fixCommand}
|
|
96594
|
-
`));
|
|
96595
|
-
} else {
|
|
96596
|
-
lines.push(source_default.green(` [OK] Active lock (PID ${report.lockCheck.pid})
|
|
96597
|
-
`));
|
|
96598
|
-
}
|
|
96599
|
-
if (report.recommendations.length > 0) {
|
|
96600
|
-
lines.push(source_default.bold(`Recommendations
|
|
96601
|
-
`));
|
|
96602
|
-
for (let i = 0;i < report.recommendations.length; i++) {
|
|
96603
|
-
lines.push(` ${i + 1}. ${report.recommendations[i]}`);
|
|
96604
|
-
}
|
|
96605
|
-
lines.push("");
|
|
96606
|
-
}
|
|
96607
|
-
return lines.join(`
|
|
96608
|
-
`);
|
|
96609
|
-
}
|
|
96610
|
-
|
|
96611
|
-
// src/cli/diagnose.ts
|
|
96612
|
-
var _diagnoseDeps = {
|
|
96613
|
-
projectOutputDir,
|
|
96614
|
-
loadConfig
|
|
96615
|
-
};
|
|
96616
|
-
function isProcessAlive2(pid) {
|
|
96617
|
-
try {
|
|
96618
|
-
const result = Bun.spawnSync(["ps", "-p", String(pid)], { stdout: "ignore", stderr: "ignore" });
|
|
96619
|
-
return result.exitCode === 0;
|
|
96620
|
-
} catch {
|
|
96621
|
-
return false;
|
|
96622
|
-
}
|
|
96623
|
-
}
|
|
96624
|
-
async function loadStatusFile2(outputDir) {
|
|
96625
|
-
const statusPath = join57(outputDir, "status.json");
|
|
96626
|
-
if (!existsSync25(statusPath))
|
|
96627
|
-
return null;
|
|
96628
|
-
try {
|
|
96629
|
-
return await Bun.file(statusPath).json();
|
|
96630
|
-
} catch {
|
|
96631
|
-
return null;
|
|
96632
|
-
}
|
|
96633
|
-
}
|
|
96634
|
-
async function countCommitsSince(workdir, since) {
|
|
96635
|
-
if (!since)
|
|
96636
|
-
return 0;
|
|
96637
|
-
try {
|
|
96638
|
-
const result = Bun.spawnSync(["git", "log", "--oneline", `--since=${since}`, "--all"], {
|
|
96639
|
-
cwd: workdir,
|
|
96640
|
-
stdout: "pipe",
|
|
96641
|
-
stderr: "ignore"
|
|
96642
|
-
});
|
|
96643
|
-
if (result.exitCode !== 0)
|
|
96644
|
-
return 0;
|
|
96645
|
-
const output = new TextDecoder().decode(result.stdout);
|
|
96646
|
-
return output.trim().split(`
|
|
96647
|
-
`).filter((line) => line.length > 0).length;
|
|
96648
|
-
} catch {
|
|
96649
|
-
return 0;
|
|
96650
|
-
}
|
|
96651
|
-
}
|
|
96652
|
-
async function checkLock(workdir) {
|
|
96653
|
-
const lockFile = Bun.file(join57(workdir, "nax.lock"));
|
|
96654
|
-
if (!await lockFile.exists())
|
|
96655
|
-
return { lockPresent: false };
|
|
96656
|
-
try {
|
|
96657
|
-
const lockData = JSON.parse(await lockFile.text());
|
|
96658
|
-
const pid = lockData.pid;
|
|
96659
|
-
const pidAlive = isProcessAlive2(pid);
|
|
96660
|
-
if (!pidAlive)
|
|
96661
|
-
return { lockPresent: true, pidAlive: false, pid, fixCommand: "rm nax.lock" };
|
|
96662
|
-
return { lockPresent: true, pidAlive: true, pid };
|
|
96663
|
-
} catch {
|
|
96664
|
-
return { lockPresent: true };
|
|
96665
|
-
}
|
|
96666
|
-
}
|
|
96667
|
-
async function diagnoseCommand(options = {}) {
|
|
96668
|
-
const logger = getLogger();
|
|
96669
|
-
const workdir = options.workdir ?? process.cwd();
|
|
96670
|
-
const naxSubdir = findProjectDir(workdir);
|
|
96671
|
-
let projectDir = naxSubdir ? join57(naxSubdir, "..") : null;
|
|
96672
|
-
if (!projectDir && existsSync25(join57(workdir, ".nax"))) {
|
|
96673
|
-
projectDir = workdir;
|
|
96674
|
-
}
|
|
96675
|
-
if (!projectDir)
|
|
96676
|
-
throw new Error("Not in a nax project directory");
|
|
96677
|
-
const config2 = await _diagnoseDeps.loadConfig(projectDir).catch(() => null);
|
|
96678
|
-
const projectKey = config2?.name?.trim() || basename12(projectDir);
|
|
96679
|
-
const outputDir = _diagnoseDeps.projectOutputDir(projectKey, config2?.outputDir);
|
|
96680
|
-
let feature = options.feature;
|
|
96681
|
-
if (!feature) {
|
|
96682
|
-
const status2 = await loadStatusFile2(outputDir);
|
|
96683
|
-
if (status2) {
|
|
96684
|
-
feature = status2.run.feature;
|
|
96685
|
-
} else {
|
|
96686
|
-
const featuresDir = join57(outputDir, "features");
|
|
96687
|
-
if (!existsSync25(featuresDir))
|
|
96688
|
-
throw new Error("No features found in project");
|
|
96689
|
-
const features = readdirSync5(featuresDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
96690
|
-
if (features.length === 0)
|
|
96691
|
-
throw new Error("No features found");
|
|
96692
|
-
feature = features[0];
|
|
96693
|
-
logger.info("diagnose", "No feature specified, using first found", { feature });
|
|
96694
|
-
}
|
|
96695
|
-
}
|
|
96696
|
-
const featureDir = join57(outputDir, "features", feature);
|
|
96697
|
-
const prdPath = join57(featureDir, "prd.json");
|
|
96698
|
-
if (!existsSync25(prdPath))
|
|
96699
|
-
throw new Error(`Feature not found: ${feature}`);
|
|
96700
|
-
const prd = await loadPRD(prdPath);
|
|
96701
|
-
const status = await loadStatusFile2(outputDir);
|
|
96702
|
-
const lockCheck = await checkLock(projectDir);
|
|
96703
|
-
const commitCount = await countCommitsSince(projectDir, status?.run.startedAt);
|
|
96704
|
-
const { storyBreakdown, failureAnalysis } = diagnoseStories(prd, status);
|
|
96705
|
-
const report = {
|
|
96706
|
-
runSummary: {
|
|
96707
|
-
feature,
|
|
96708
|
-
lastRunTime: status?.run.startedAt,
|
|
96709
|
-
status: status?.run.status ?? "unknown",
|
|
96710
|
-
storiesPassed: prd.userStories.filter((s) => s.status === "passed").length,
|
|
96711
|
-
storiesFailed: prd.userStories.filter((s) => s.status === "failed").length,
|
|
96712
|
-
storiesPending: prd.userStories.filter((s) => s.status !== "passed" && s.status !== "failed" && s.status !== "skipped").length,
|
|
96713
|
-
cost: status?.cost.spent,
|
|
96714
|
-
commitsProduced: commitCount
|
|
96715
|
-
},
|
|
96716
|
-
storyBreakdown,
|
|
96717
|
-
failureAnalysis,
|
|
96718
|
-
lockCheck,
|
|
96719
|
-
recommendations: [],
|
|
96720
|
-
dataSources: {
|
|
96721
|
-
prdFound: true,
|
|
96722
|
-
statusFound: status !== null,
|
|
96723
|
-
eventsFound: false,
|
|
96724
|
-
gitLogFound: commitCount > 0
|
|
96725
|
-
}
|
|
96726
|
-
};
|
|
96727
|
-
report.recommendations = generateRecommendations(report);
|
|
96728
|
-
if (options.json) {
|
|
96729
|
-
console.log(JSON.stringify(report, null, 2));
|
|
96730
|
-
} else {
|
|
96731
|
-
console.log(formatReport(report, options.verbose ?? false));
|
|
96732
|
-
}
|
|
96733
|
-
}
|
|
96734
96489
|
// src/cli/interact.ts
|
|
96735
96490
|
init_common();
|
|
96736
96491
|
init_interaction();
|
|
@@ -96738,8 +96493,8 @@ init_interaction();
|
|
|
96738
96493
|
init_source();
|
|
96739
96494
|
init_loader();
|
|
96740
96495
|
init_generator2();
|
|
96741
|
-
import { existsSync as
|
|
96742
|
-
import { join as
|
|
96496
|
+
import { existsSync as existsSync25 } from "fs";
|
|
96497
|
+
import { join as join57 } from "path";
|
|
96743
96498
|
var VALID_AGENTS = ["claude", "codex", "opencode", "cursor", "windsurf", "aider", "gemini"];
|
|
96744
96499
|
async function generateCommand(options) {
|
|
96745
96500
|
const workdir = options.dir ?? process.cwd();
|
|
@@ -96782,7 +96537,7 @@ async function generateCommand(options) {
|
|
|
96782
96537
|
return;
|
|
96783
96538
|
}
|
|
96784
96539
|
if (options.package) {
|
|
96785
|
-
const packageDir =
|
|
96540
|
+
const packageDir = join57(workdir, options.package);
|
|
96786
96541
|
if (dryRun) {
|
|
96787
96542
|
console.log(source_default.yellow("\u26A0 Dry run \u2014 no files will be written"));
|
|
96788
96543
|
}
|
|
@@ -96802,10 +96557,10 @@ async function generateCommand(options) {
|
|
|
96802
96557
|
process.exit(1);
|
|
96803
96558
|
return;
|
|
96804
96559
|
}
|
|
96805
|
-
const contextPath = options.context ?
|
|
96806
|
-
const outputDir = options.output ?
|
|
96560
|
+
const contextPath = options.context ? join57(workdir, options.context) : join57(workdir, ".nax/context.md");
|
|
96561
|
+
const outputDir = options.output ? join57(workdir, options.output) : workdir;
|
|
96807
96562
|
const autoInject = !options.noAutoInject;
|
|
96808
|
-
if (!
|
|
96563
|
+
if (!existsSync25(contextPath)) {
|
|
96809
96564
|
console.error(source_default.red(`\u2717 Context file not found: ${contextPath}`));
|
|
96810
96565
|
console.error(source_default.yellow(" Create .nax/context.md first, or run `nax init` to scaffold it."));
|
|
96811
96566
|
process.exit(1);
|
|
@@ -96908,8 +96663,8 @@ async function generateCommand(options) {
|
|
|
96908
96663
|
}
|
|
96909
96664
|
// src/cli/config-display.ts
|
|
96910
96665
|
init_loader();
|
|
96911
|
-
import { existsSync as
|
|
96912
|
-
import { join as
|
|
96666
|
+
import { existsSync as existsSync27 } from "fs";
|
|
96667
|
+
import { join as join59 } from "path";
|
|
96913
96668
|
|
|
96914
96669
|
// src/cli/config-descriptions.ts
|
|
96915
96670
|
var FIELD_DESCRIPTIONS = {
|
|
@@ -97160,10 +96915,10 @@ function deepEqual(a, b) {
|
|
|
97160
96915
|
// src/cli/config-get.ts
|
|
97161
96916
|
init_defaults();
|
|
97162
96917
|
init_loader();
|
|
97163
|
-
import { existsSync as
|
|
97164
|
-
import { join as
|
|
96918
|
+
import { existsSync as existsSync26 } from "fs";
|
|
96919
|
+
import { join as join58 } from "path";
|
|
97165
96920
|
async function loadConfigFile(path18) {
|
|
97166
|
-
if (!
|
|
96921
|
+
if (!existsSync26(path18))
|
|
97167
96922
|
return null;
|
|
97168
96923
|
try {
|
|
97169
96924
|
return await Bun.file(path18).json();
|
|
@@ -97183,7 +96938,7 @@ async function loadProjectConfig() {
|
|
|
97183
96938
|
const projectDir = findProjectDir();
|
|
97184
96939
|
if (!projectDir)
|
|
97185
96940
|
return null;
|
|
97186
|
-
const projectPath =
|
|
96941
|
+
const projectPath = join58(projectDir, "config.json");
|
|
97187
96942
|
return await loadConfigFile(projectPath);
|
|
97188
96943
|
}
|
|
97189
96944
|
|
|
@@ -97243,14 +96998,14 @@ async function configCommand(config2, options = {}) {
|
|
|
97243
96998
|
function determineConfigSources() {
|
|
97244
96999
|
const globalPath = globalConfigPath();
|
|
97245
97000
|
const projectDir = findProjectDir();
|
|
97246
|
-
const projectPath = projectDir ?
|
|
97001
|
+
const projectPath = projectDir ? join59(projectDir, "config.json") : null;
|
|
97247
97002
|
return {
|
|
97248
97003
|
global: fileExists(globalPath) ? globalPath : null,
|
|
97249
97004
|
project: projectPath && fileExists(projectPath) ? projectPath : null
|
|
97250
97005
|
};
|
|
97251
97006
|
}
|
|
97252
97007
|
function fileExists(path18) {
|
|
97253
|
-
return
|
|
97008
|
+
return existsSync27(path18);
|
|
97254
97009
|
}
|
|
97255
97010
|
function displayConfigWithDescriptions(obj, path18, sources, indent = 0) {
|
|
97256
97011
|
const indentStr = " ".repeat(indent);
|
|
@@ -97391,16 +97146,16 @@ function formatValueForTable(value) {
|
|
|
97391
97146
|
init_paths();
|
|
97392
97147
|
init_profile();
|
|
97393
97148
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
97394
|
-
import { readdirSync as
|
|
97395
|
-
import { join as
|
|
97149
|
+
import { readdirSync as readdirSync5 } from "fs";
|
|
97150
|
+
import { join as join60 } from "path";
|
|
97396
97151
|
var _profileCLIDeps = {
|
|
97397
97152
|
env: process.env
|
|
97398
97153
|
};
|
|
97399
97154
|
var SENSITIVE_KEY_PATTERN = /key|token|secret|password|credential/i;
|
|
97400
97155
|
var VAR_PATTERN = /\$[A-Za-z_][A-Za-z0-9_]*/;
|
|
97401
97156
|
async function profileListCommand(startDir) {
|
|
97402
|
-
const globalProfilesDir =
|
|
97403
|
-
const projectProfilesDir =
|
|
97157
|
+
const globalProfilesDir = join60(globalConfigDir(), "profiles");
|
|
97158
|
+
const projectProfilesDir = join60(projectConfigDir(startDir), "profiles");
|
|
97404
97159
|
const globalProfiles = scanProfileDir(globalProfilesDir);
|
|
97405
97160
|
const projectProfiles = scanProfileDir(projectProfilesDir);
|
|
97406
97161
|
const activeProfile = await resolveProfileName({}, _profileCLIDeps.env, startDir);
|
|
@@ -97426,7 +97181,7 @@ async function profileListCommand(startDir) {
|
|
|
97426
97181
|
}
|
|
97427
97182
|
function scanProfileDir(dir) {
|
|
97428
97183
|
try {
|
|
97429
|
-
return
|
|
97184
|
+
return readdirSync5(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, ""));
|
|
97430
97185
|
} catch {
|
|
97431
97186
|
return [];
|
|
97432
97187
|
}
|
|
@@ -97459,7 +97214,7 @@ function maskProfileValues(obj) {
|
|
|
97459
97214
|
return result;
|
|
97460
97215
|
}
|
|
97461
97216
|
async function profileUseCommand(profileName, startDir) {
|
|
97462
|
-
const configPath =
|
|
97217
|
+
const configPath = join60(projectConfigDir(startDir), "config.json");
|
|
97463
97218
|
const configFile = Bun.file(configPath);
|
|
97464
97219
|
let existing = {};
|
|
97465
97220
|
if (await configFile.exists()) {
|
|
@@ -97478,8 +97233,8 @@ async function profileCurrentCommand(startDir) {
|
|
|
97478
97233
|
return resolveProfileName({}, _profileCLIDeps.env, startDir);
|
|
97479
97234
|
}
|
|
97480
97235
|
async function profileCreateCommand(profileName, startDir) {
|
|
97481
|
-
const profilesDir =
|
|
97482
|
-
const profilePath =
|
|
97236
|
+
const profilesDir = join60(projectConfigDir(startDir), "profiles");
|
|
97237
|
+
const profilePath = join60(profilesDir, `${profileName}.json`);
|
|
97483
97238
|
const profileFile = Bun.file(profilePath);
|
|
97484
97239
|
if (await profileFile.exists()) {
|
|
97485
97240
|
throw new Error(`Profile "${profileName}" already exists at ${profilePath}`);
|
|
@@ -97601,7 +97356,7 @@ async function contextInspectCommand(options) {
|
|
|
97601
97356
|
init_canonical_loader();
|
|
97602
97357
|
init_errors();
|
|
97603
97358
|
import { mkdir as mkdir12 } from "fs/promises";
|
|
97604
|
-
import { basename as
|
|
97359
|
+
import { basename as basename12, join as join61 } from "path";
|
|
97605
97360
|
var _rulesCLIDeps = {
|
|
97606
97361
|
readFile: async (path18) => Bun.file(path18).text(),
|
|
97607
97362
|
writeFile: async (path18, content) => {
|
|
@@ -97610,7 +97365,7 @@ var _rulesCLIDeps = {
|
|
|
97610
97365
|
fileExists: async (path18) => Bun.file(path18).exists(),
|
|
97611
97366
|
globInDir: (dir) => {
|
|
97612
97367
|
try {
|
|
97613
|
-
return [...new Bun.Glob("*.md").scanSync({ cwd: dir })].sort().map((f) =>
|
|
97368
|
+
return [...new Bun.Glob("*.md").scanSync({ cwd: dir })].sort().map((f) => join61(dir, f));
|
|
97614
97369
|
} catch {
|
|
97615
97370
|
return [];
|
|
97616
97371
|
}
|
|
@@ -97659,7 +97414,7 @@ ${r.content}`).join(`
|
|
|
97659
97414
|
`);
|
|
97660
97415
|
const shimContent = `${header + body}
|
|
97661
97416
|
`;
|
|
97662
|
-
const shimPath =
|
|
97417
|
+
const shimPath = join61(workdir, shimFileName);
|
|
97663
97418
|
if (options.dryRun) {
|
|
97664
97419
|
console.log(`[dry-run] Would write ${shimPath} (${shimContent.length} bytes)`);
|
|
97665
97420
|
return;
|
|
@@ -97688,20 +97443,20 @@ function neutralizeContent(content) {
|
|
|
97688
97443
|
}
|
|
97689
97444
|
async function collectMigrationSources(workdir) {
|
|
97690
97445
|
const sources = [];
|
|
97691
|
-
const claudeMdPath =
|
|
97446
|
+
const claudeMdPath = join61(workdir, "CLAUDE.md");
|
|
97692
97447
|
if (await _rulesCLIDeps.fileExists(claudeMdPath)) {
|
|
97693
97448
|
const content = await _rulesCLIDeps.readFile(claudeMdPath);
|
|
97694
97449
|
if (content.trim()) {
|
|
97695
97450
|
sources.push({ sourcePath: claudeMdPath, targetFileName: "project-conventions.md", content });
|
|
97696
97451
|
}
|
|
97697
97452
|
}
|
|
97698
|
-
const rulesDir =
|
|
97453
|
+
const rulesDir = join61(workdir, ".claude", "rules");
|
|
97699
97454
|
const ruleFiles = _rulesCLIDeps.globInDir(rulesDir);
|
|
97700
97455
|
for (const filePath of ruleFiles) {
|
|
97701
97456
|
try {
|
|
97702
97457
|
const content = await _rulesCLIDeps.readFile(filePath);
|
|
97703
97458
|
if (content.trim()) {
|
|
97704
|
-
sources.push({ sourcePath: filePath, targetFileName:
|
|
97459
|
+
sources.push({ sourcePath: filePath, targetFileName: basename12(filePath), content });
|
|
97705
97460
|
}
|
|
97706
97461
|
} catch {}
|
|
97707
97462
|
}
|
|
@@ -97715,7 +97470,7 @@ async function rulesMigrateCommand(options) {
|
|
|
97715
97470
|
console.log("[WARN] No source files found (checked CLAUDE.md and .claude/rules/*.md). Nothing to migrate.");
|
|
97716
97471
|
return;
|
|
97717
97472
|
}
|
|
97718
|
-
const targetDir =
|
|
97473
|
+
const targetDir = join61(workdir, CANONICAL_RULES_DIR);
|
|
97719
97474
|
if (!options.dryRun) {
|
|
97720
97475
|
try {
|
|
97721
97476
|
await _rulesCLIDeps.mkdir(targetDir);
|
|
@@ -97726,7 +97481,7 @@ async function rulesMigrateCommand(options) {
|
|
|
97726
97481
|
let written = 0;
|
|
97727
97482
|
let skipped = 0;
|
|
97728
97483
|
for (const { sourcePath, targetFileName, content } of sources) {
|
|
97729
|
-
const targetPath =
|
|
97484
|
+
const targetPath = join61(targetDir, targetFileName);
|
|
97730
97485
|
if (!force && !options.dryRun && await _rulesCLIDeps.fileExists(targetPath)) {
|
|
97731
97486
|
console.log(`[skip] ${targetFileName} already exists (use --force to overwrite)`);
|
|
97732
97487
|
skipped++;
|
|
@@ -97765,7 +97520,7 @@ function collectCanonicalRuleRoots(workdir) {
|
|
|
97765
97520
|
const packageRel = normalized.slice(0, idx);
|
|
97766
97521
|
if (!packageRel)
|
|
97767
97522
|
continue;
|
|
97768
|
-
roots.add(
|
|
97523
|
+
roots.add(join61(workdir, packageRel));
|
|
97769
97524
|
}
|
|
97770
97525
|
return [...roots].sort();
|
|
97771
97526
|
}
|
|
@@ -97787,7 +97542,7 @@ init_logger2();
|
|
|
97787
97542
|
init_detect2();
|
|
97788
97543
|
init_workspace();
|
|
97789
97544
|
init_common();
|
|
97790
|
-
import { join as
|
|
97545
|
+
import { join as join62 } from "path";
|
|
97791
97546
|
function resolveEffective(detected, configPatterns) {
|
|
97792
97547
|
if (configPatterns !== undefined)
|
|
97793
97548
|
return "config";
|
|
@@ -97872,7 +97627,7 @@ async function detectCommand(options) {
|
|
|
97872
97627
|
const rootDetected = detectionMap[""] ?? { patterns: [], confidence: "empty", sources: [] };
|
|
97873
97628
|
const pkgEntries = await Promise.all(packageDirs.map(async (dir) => {
|
|
97874
97629
|
const det = detectionMap[dir] ?? { patterns: [], confidence: "empty", sources: [] };
|
|
97875
|
-
const pkgConfigPath =
|
|
97630
|
+
const pkgConfigPath = join62(workdir, ".nax", "mono", dir, "config.json");
|
|
97876
97631
|
const pkgRaw = await loadRawConfig(pkgConfigPath);
|
|
97877
97632
|
const pkgPatterns = deepGet(pkgRaw, TEST_PATTERNS_KEY);
|
|
97878
97633
|
const effective = Array.isArray(pkgPatterns) ? pkgPatterns : undefined;
|
|
@@ -97926,13 +97681,13 @@ async function detectCommand(options) {
|
|
|
97926
97681
|
if (rootDetected.confidence === "empty") {
|
|
97927
97682
|
console.log(source_default.yellow(" root: skipped (empty detection)"));
|
|
97928
97683
|
} else {
|
|
97929
|
-
const rootConfigPath =
|
|
97684
|
+
const rootConfigPath = join62(workdir, ".nax", "config.json");
|
|
97930
97685
|
try {
|
|
97931
97686
|
const status = await applyToConfig(rootConfigPath, rootDetected.patterns, options.force ?? false);
|
|
97932
97687
|
if (status === "skipped") {
|
|
97933
97688
|
console.log(source_default.dim(" root: skipped (testFilePatterns already set; use --force to overwrite)"));
|
|
97934
97689
|
} else {
|
|
97935
|
-
console.log(source_default.green(` root: ${status} \u2192 ${
|
|
97690
|
+
console.log(source_default.green(` root: ${status} \u2192 ${join62(".nax", "config.json")}`));
|
|
97936
97691
|
}
|
|
97937
97692
|
} catch (err) {
|
|
97938
97693
|
console.error(source_default.red(` root: write failed \u2014 ${err.message}`));
|
|
@@ -97945,13 +97700,13 @@ async function detectCommand(options) {
|
|
|
97945
97700
|
console.log(source_default.dim(` ${dir}: skipped (empty detection)`));
|
|
97946
97701
|
continue;
|
|
97947
97702
|
}
|
|
97948
|
-
const pkgConfigPath =
|
|
97703
|
+
const pkgConfigPath = join62(workdir, ".nax", "mono", dir, "config.json");
|
|
97949
97704
|
try {
|
|
97950
97705
|
const status = await applyToConfig(pkgConfigPath, det.patterns, options.force ?? false);
|
|
97951
97706
|
if (status === "skipped") {
|
|
97952
97707
|
console.log(source_default.dim(` ${dir}: skipped (already set)`));
|
|
97953
97708
|
} else {
|
|
97954
|
-
console.log(source_default.green(` ${dir}: ${status} \u2192 ${
|
|
97709
|
+
console.log(source_default.green(` ${dir}: ${status} \u2192 ${join62(".nax", "mono", dir, "config.json")}`));
|
|
97955
97710
|
}
|
|
97956
97711
|
} catch (err) {
|
|
97957
97712
|
console.error(source_default.red(` ${dir}: write failed \u2014 ${err.message}`));
|
|
@@ -97966,27 +97721,22 @@ async function detectCommand(options) {
|
|
|
97966
97721
|
process.exitCode = allEmpty ? 1 : 0;
|
|
97967
97722
|
}
|
|
97968
97723
|
|
|
97969
|
-
// src/commands/diagnose.ts
|
|
97970
|
-
async function diagnose(options) {
|
|
97971
|
-
await diagnoseCommand(options);
|
|
97972
|
-
}
|
|
97973
|
-
|
|
97974
97724
|
// src/commands/logs.ts
|
|
97975
97725
|
init_common();
|
|
97976
|
-
import { existsSync as
|
|
97977
|
-
import { join as
|
|
97726
|
+
import { existsSync as existsSync29 } from "fs";
|
|
97727
|
+
import { join as join66 } from "path";
|
|
97978
97728
|
|
|
97979
97729
|
// src/commands/logs-formatter.ts
|
|
97980
97730
|
init_source();
|
|
97981
97731
|
init_formatter();
|
|
97982
|
-
import { readdirSync as
|
|
97983
|
-
import { join as
|
|
97732
|
+
import { readdirSync as readdirSync7 } from "fs";
|
|
97733
|
+
import { join as join65 } from "path";
|
|
97984
97734
|
|
|
97985
97735
|
// src/commands/logs-reader.ts
|
|
97986
97736
|
init_paths3();
|
|
97987
|
-
import { existsSync as
|
|
97737
|
+
import { existsSync as existsSync28, readdirSync as readdirSync6 } from "fs";
|
|
97988
97738
|
import { readdir as readdir4 } from "fs/promises";
|
|
97989
|
-
import { join as
|
|
97739
|
+
import { join as join64 } from "path";
|
|
97990
97740
|
var _logsReaderDeps = {
|
|
97991
97741
|
getRunsDir
|
|
97992
97742
|
};
|
|
@@ -98000,7 +97750,7 @@ async function resolveRunFileFromRegistry(runId) {
|
|
|
98000
97750
|
}
|
|
98001
97751
|
let matched = null;
|
|
98002
97752
|
for (const entry of entries) {
|
|
98003
|
-
const metaPath =
|
|
97753
|
+
const metaPath = join64(runsDir, entry, "meta.json");
|
|
98004
97754
|
try {
|
|
98005
97755
|
const meta3 = await Bun.file(metaPath).json();
|
|
98006
97756
|
if (meta3.runId === runId || meta3.runId.startsWith(runId)) {
|
|
@@ -98012,24 +97762,24 @@ async function resolveRunFileFromRegistry(runId) {
|
|
|
98012
97762
|
if (!matched) {
|
|
98013
97763
|
throw new Error(`Run not found in registry: ${runId}`);
|
|
98014
97764
|
}
|
|
98015
|
-
if (!
|
|
97765
|
+
if (!existsSync28(matched.eventsDir)) {
|
|
98016
97766
|
console.log(`Log directory unavailable for run: ${runId}`);
|
|
98017
97767
|
return null;
|
|
98018
97768
|
}
|
|
98019
|
-
const files =
|
|
97769
|
+
const files = readdirSync6(matched.eventsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
|
|
98020
97770
|
if (files.length === 0) {
|
|
98021
97771
|
console.log(`No log files found for run: ${runId}`);
|
|
98022
97772
|
return null;
|
|
98023
97773
|
}
|
|
98024
97774
|
const specificFile = files.find((f) => f === `${matched.runId}.jsonl`);
|
|
98025
|
-
return
|
|
97775
|
+
return join64(matched.eventsDir, specificFile ?? files[0]);
|
|
98026
97776
|
}
|
|
98027
97777
|
async function selectRunFile(runsDir) {
|
|
98028
|
-
const files =
|
|
97778
|
+
const files = readdirSync6(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
|
|
98029
97779
|
if (files.length === 0) {
|
|
98030
97780
|
return null;
|
|
98031
97781
|
}
|
|
98032
|
-
return
|
|
97782
|
+
return join64(runsDir, files[0]);
|
|
98033
97783
|
}
|
|
98034
97784
|
async function extractRunSummary(filePath) {
|
|
98035
97785
|
const file3 = Bun.file(filePath);
|
|
@@ -98104,7 +97854,7 @@ var LOG_LEVEL_PRIORITY2 = {
|
|
|
98104
97854
|
error: 3
|
|
98105
97855
|
};
|
|
98106
97856
|
async function displayRunsList(runsDir) {
|
|
98107
|
-
const files =
|
|
97857
|
+
const files = readdirSync7(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
|
|
98108
97858
|
if (files.length === 0) {
|
|
98109
97859
|
console.log(source_default.dim("No runs found"));
|
|
98110
97860
|
return;
|
|
@@ -98115,7 +97865,7 @@ Runs:
|
|
|
98115
97865
|
console.log(source_default.gray(" Timestamp Stories Duration Cost Status"));
|
|
98116
97866
|
console.log(source_default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
98117
97867
|
for (const file3 of files) {
|
|
98118
|
-
const filePath =
|
|
97868
|
+
const filePath = join65(runsDir, file3);
|
|
98119
97869
|
const summary = await extractRunSummary(filePath);
|
|
98120
97870
|
const timestamp = file3.replace(".jsonl", "");
|
|
98121
97871
|
const stories = summary ? `${summary.passed}/${summary.total}` : "?/?";
|
|
@@ -98229,7 +97979,7 @@ async function logsCommand(options) {
|
|
|
98229
97979
|
return;
|
|
98230
97980
|
}
|
|
98231
97981
|
const resolved = resolveProject({ dir: options.dir });
|
|
98232
|
-
const naxDir =
|
|
97982
|
+
const naxDir = join66(resolved.projectDir, ".nax");
|
|
98233
97983
|
const configPath = resolved.configPath;
|
|
98234
97984
|
const configFile = Bun.file(configPath);
|
|
98235
97985
|
const config2 = await configFile.json();
|
|
@@ -98237,9 +97987,9 @@ async function logsCommand(options) {
|
|
|
98237
97987
|
if (!featureName) {
|
|
98238
97988
|
throw new Error("No feature specified in config.json");
|
|
98239
97989
|
}
|
|
98240
|
-
const featureDir =
|
|
98241
|
-
const runsDir =
|
|
98242
|
-
if (!
|
|
97990
|
+
const featureDir = join66(naxDir, "features", featureName);
|
|
97991
|
+
const runsDir = join66(featureDir, "runs");
|
|
97992
|
+
if (!existsSync29(runsDir)) {
|
|
98243
97993
|
throw new Error(`No runs directory found for feature: ${featureName}`);
|
|
98244
97994
|
}
|
|
98245
97995
|
if (options.list) {
|
|
@@ -98263,8 +98013,8 @@ init_config();
|
|
|
98263
98013
|
init_prd();
|
|
98264
98014
|
init_precheck();
|
|
98265
98015
|
init_common();
|
|
98266
|
-
import { existsSync as
|
|
98267
|
-
import { join as
|
|
98016
|
+
import { existsSync as existsSync30 } from "fs";
|
|
98017
|
+
import { join as join67 } from "path";
|
|
98268
98018
|
async function precheckCommand(options) {
|
|
98269
98019
|
const resolved = resolveProject({
|
|
98270
98020
|
dir: options.dir,
|
|
@@ -98286,14 +98036,14 @@ async function precheckCommand(options) {
|
|
|
98286
98036
|
process.exit(1);
|
|
98287
98037
|
}
|
|
98288
98038
|
}
|
|
98289
|
-
const naxDir =
|
|
98290
|
-
const featureDir =
|
|
98291
|
-
const prdPath =
|
|
98292
|
-
if (!
|
|
98039
|
+
const naxDir = join67(resolved.projectDir, ".nax");
|
|
98040
|
+
const featureDir = join67(naxDir, "features", featureName);
|
|
98041
|
+
const prdPath = join67(featureDir, "prd.json");
|
|
98042
|
+
if (!existsSync30(featureDir)) {
|
|
98293
98043
|
console.error(source_default.red(`Feature not found: ${featureName}`));
|
|
98294
98044
|
process.exit(1);
|
|
98295
98045
|
}
|
|
98296
|
-
if (!
|
|
98046
|
+
if (!existsSync30(prdPath)) {
|
|
98297
98047
|
console.error(source_default.red(`Missing prd.json for feature: ${featureName}`));
|
|
98298
98048
|
console.error(source_default.dim(`Run: nax plan -f ${featureName} --from spec.md --auto`));
|
|
98299
98049
|
process.exit(EXIT_CODES.INVALID_PRD);
|
|
@@ -98311,7 +98061,7 @@ async function precheckCommand(options) {
|
|
|
98311
98061
|
init_source();
|
|
98312
98062
|
init_paths3();
|
|
98313
98063
|
import { readdir as readdir5 } from "fs/promises";
|
|
98314
|
-
import { join as
|
|
98064
|
+
import { join as join68 } from "path";
|
|
98315
98065
|
var DEFAULT_LIMIT = 20;
|
|
98316
98066
|
var _runsCmdDeps = {
|
|
98317
98067
|
getRunsDir
|
|
@@ -98366,7 +98116,7 @@ async function runsCommand(options = {}) {
|
|
|
98366
98116
|
}
|
|
98367
98117
|
const rows = [];
|
|
98368
98118
|
for (const entry of entries) {
|
|
98369
|
-
const metaPath =
|
|
98119
|
+
const metaPath = join68(runsDir, entry, "meta.json");
|
|
98370
98120
|
let meta3;
|
|
98371
98121
|
try {
|
|
98372
98122
|
meta3 = await Bun.file(metaPath).json();
|
|
@@ -98443,8 +98193,8 @@ async function runsCommand(options = {}) {
|
|
|
98443
98193
|
|
|
98444
98194
|
// src/commands/unlock.ts
|
|
98445
98195
|
init_source();
|
|
98446
|
-
import { join as
|
|
98447
|
-
function
|
|
98196
|
+
import { join as join69 } from "path";
|
|
98197
|
+
function isProcessAlive2(pid) {
|
|
98448
98198
|
try {
|
|
98449
98199
|
process.kill(pid, 0);
|
|
98450
98200
|
return true;
|
|
@@ -98458,7 +98208,7 @@ function formatLockAge(ageMs) {
|
|
|
98458
98208
|
}
|
|
98459
98209
|
async function unlockCommand(options) {
|
|
98460
98210
|
const workdir = options.dir ?? process.cwd();
|
|
98461
|
-
const lockPath =
|
|
98211
|
+
const lockPath = join69(workdir, "nax.lock");
|
|
98462
98212
|
const lockFile = Bun.file(lockPath);
|
|
98463
98213
|
const exists = await lockFile.exists();
|
|
98464
98214
|
if (!exists) {
|
|
@@ -98476,7 +98226,7 @@ async function unlockCommand(options) {
|
|
|
98476
98226
|
const { pid, timestamp } = lockData;
|
|
98477
98227
|
const ageMs = Date.now() - timestamp;
|
|
98478
98228
|
if (!options.force) {
|
|
98479
|
-
if (
|
|
98229
|
+
if (isProcessAlive2(pid)) {
|
|
98480
98230
|
console.error(source_default.red(`nax is still running (PID ${pid}). Use --force to override.`));
|
|
98481
98231
|
process.exit(1);
|
|
98482
98232
|
}
|
|
@@ -105156,7 +104906,7 @@ var import_react27 = __toESM(require_react(), 1);
|
|
|
105156
104906
|
// node_modules/ink/build/hooks/use-cursor.js
|
|
105157
104907
|
var import_react28 = __toESM(require_react(), 1);
|
|
105158
104908
|
// src/tui/App.tsx
|
|
105159
|
-
var
|
|
104909
|
+
var import_react36 = __toESM(require_react(), 1);
|
|
105160
104910
|
|
|
105161
104911
|
// src/utils/queue-writer.ts
|
|
105162
104912
|
async function writeQueueCommand(queueFilePath, command) {
|
|
@@ -105185,151 +104935,8 @@ ${commandLine2}
|
|
|
105185
104935
|
await Bun.write(queueFilePath, newContent);
|
|
105186
104936
|
}
|
|
105187
104937
|
|
|
105188
|
-
// node_modules/ink-spinner/build/index.js
|
|
105189
|
-
var import_react29 = __toESM(require_react(), 1);
|
|
105190
|
-
var import_cli_spinners = __toESM(require_cli_spinners(), 1);
|
|
105191
|
-
function Spinner({ type = "dots" }) {
|
|
105192
|
-
const [frame, setFrame] = import_react29.useState(0);
|
|
105193
|
-
const spinner = import_cli_spinners.default[type];
|
|
105194
|
-
import_react29.useEffect(() => {
|
|
105195
|
-
const timer = setInterval(() => {
|
|
105196
|
-
setFrame((previousFrame) => {
|
|
105197
|
-
const isLastFrame = previousFrame === spinner.frames.length - 1;
|
|
105198
|
-
return isLastFrame ? 0 : previousFrame + 1;
|
|
105199
|
-
});
|
|
105200
|
-
}, spinner.interval);
|
|
105201
|
-
return () => {
|
|
105202
|
-
clearInterval(timer);
|
|
105203
|
-
};
|
|
105204
|
-
}, [spinner]);
|
|
105205
|
-
return import_react29.default.createElement(Text, null, spinner.frames[frame]);
|
|
105206
|
-
}
|
|
105207
|
-
var build_default = Spinner;
|
|
105208
|
-
|
|
105209
|
-
// src/tui/components/AgentPanel.tsx
|
|
105210
|
-
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
105211
|
-
var MAX_OUTPUT_LINES = 500;
|
|
105212
|
-
function AgentPanel({ focused = false, outputLines = [], activeCalls }) {
|
|
105213
|
-
const borderColor = focused ? "cyan" : "gray";
|
|
105214
|
-
const bufferedLines = outputLines.length > MAX_OUTPUT_LINES ? outputLines.slice(-MAX_OUTPUT_LINES) : outputLines;
|
|
105215
|
-
const activeCallList = activeCalls ? Array.from(activeCalls.values()) : [];
|
|
105216
|
-
const hasActiveCalls = activeCallList.length > 0;
|
|
105217
|
-
const hasOutput = bufferedLines.length > 0;
|
|
105218
|
-
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105219
|
-
flexDirection: "column",
|
|
105220
|
-
flexGrow: 1,
|
|
105221
|
-
borderStyle: "single",
|
|
105222
|
-
borderColor,
|
|
105223
|
-
children: [
|
|
105224
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105225
|
-
paddingX: 1,
|
|
105226
|
-
borderStyle: "single",
|
|
105227
|
-
borderBottom: true,
|
|
105228
|
-
borderColor,
|
|
105229
|
-
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105230
|
-
bold: true,
|
|
105231
|
-
color: focused ? "cyan" : undefined,
|
|
105232
|
-
children: [
|
|
105233
|
-
"Agent ",
|
|
105234
|
-
focused && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105235
|
-
dimColor: true,
|
|
105236
|
-
children: "(focused)"
|
|
105237
|
-
}, undefined, false, undefined, this)
|
|
105238
|
-
]
|
|
105239
|
-
}, undefined, true, undefined, this)
|
|
105240
|
-
}, undefined, false, undefined, this),
|
|
105241
|
-
hasActiveCalls && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105242
|
-
flexDirection: "column",
|
|
105243
|
-
paddingX: 1,
|
|
105244
|
-
paddingY: 1,
|
|
105245
|
-
children: activeCallList.map((call) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(AgentCallRow, {
|
|
105246
|
-
call
|
|
105247
|
-
}, call.callId, false, undefined, this))
|
|
105248
|
-
}, undefined, false, undefined, this),
|
|
105249
|
-
!hasActiveCalls && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105250
|
-
flexDirection: "column",
|
|
105251
|
-
paddingX: 1,
|
|
105252
|
-
paddingY: 1,
|
|
105253
|
-
children: hasOutput ? bufferedLines.map((line, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105254
|
-
children: line
|
|
105255
|
-
}, `line-${i}-${line.slice(0, 20)}`, false, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105256
|
-
dimColor: true,
|
|
105257
|
-
children: [
|
|
105258
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
|
|
105259
|
-
type: "dots"
|
|
105260
|
-
}, undefined, false, undefined, this),
|
|
105261
|
-
" Waiting for agent..."
|
|
105262
|
-
]
|
|
105263
|
-
}, undefined, true, undefined, this)
|
|
105264
|
-
}, undefined, false, undefined, this)
|
|
105265
|
-
]
|
|
105266
|
-
}, undefined, true, undefined, this);
|
|
105267
|
-
}
|
|
105268
|
-
function formatMs(ms) {
|
|
105269
|
-
if (ms < 1000)
|
|
105270
|
-
return `${ms}ms`;
|
|
105271
|
-
return `${Math.floor(ms / 1000)}s`;
|
|
105272
|
-
}
|
|
105273
|
-
function AgentCallRow({ call }) {
|
|
105274
|
-
const now3 = Date.now();
|
|
105275
|
-
const elapsedMs = now3 - call.startedAt;
|
|
105276
|
-
const idleMs = now3 - call.lastActivityAt;
|
|
105277
|
-
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105278
|
-
flexDirection: "row",
|
|
105279
|
-
gap: 1,
|
|
105280
|
-
children: [
|
|
105281
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105282
|
-
color: "cyan",
|
|
105283
|
-
children: call.agentName
|
|
105284
|
-
}, undefined, false, undefined, this),
|
|
105285
|
-
call.storyId && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105286
|
-
dimColor: true,
|
|
105287
|
-
children: call.storyId
|
|
105288
|
-
}, undefined, false, undefined, this),
|
|
105289
|
-
call.stage && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105290
|
-
dimColor: true,
|
|
105291
|
-
children: [
|
|
105292
|
-
"[",
|
|
105293
|
-
call.stage,
|
|
105294
|
-
"]"
|
|
105295
|
-
]
|
|
105296
|
-
}, undefined, true, undefined, this),
|
|
105297
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105298
|
-
children: [
|
|
105299
|
-
" elapsed:",
|
|
105300
|
-
formatMs(elapsedMs)
|
|
105301
|
-
]
|
|
105302
|
-
}, undefined, true, undefined, this),
|
|
105303
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105304
|
-
children: [
|
|
105305
|
-
" idle:",
|
|
105306
|
-
formatMs(idleMs)
|
|
105307
|
-
]
|
|
105308
|
-
}, undefined, true, undefined, this),
|
|
105309
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105310
|
-
children: [
|
|
105311
|
-
" msg:",
|
|
105312
|
-
call.messageUpdates
|
|
105313
|
-
]
|
|
105314
|
-
}, undefined, true, undefined, this),
|
|
105315
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105316
|
-
children: [
|
|
105317
|
-
" think:",
|
|
105318
|
-
call.thinkingUpdates
|
|
105319
|
-
]
|
|
105320
|
-
}, undefined, true, undefined, this),
|
|
105321
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105322
|
-
children: [
|
|
105323
|
-
" usage:",
|
|
105324
|
-
call.usageUpdates
|
|
105325
|
-
]
|
|
105326
|
-
}, undefined, true, undefined, this)
|
|
105327
|
-
]
|
|
105328
|
-
}, undefined, true, undefined, this);
|
|
105329
|
-
}
|
|
105330
|
-
|
|
105331
104938
|
// src/tui/components/CostOverlay.tsx
|
|
105332
|
-
var
|
|
104939
|
+
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
105333
104940
|
function formatCost2(cost) {
|
|
105334
104941
|
return `$${cost.toFixed(4)}`;
|
|
105335
104942
|
}
|
|
@@ -105338,7 +104945,7 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105338
104945
|
return null;
|
|
105339
104946
|
}
|
|
105340
104947
|
const executedStories = stories.filter((s) => s.cost && s.cost > 0 || s.status !== "pending");
|
|
105341
|
-
return /* @__PURE__ */
|
|
104948
|
+
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105342
104949
|
flexDirection: "column",
|
|
105343
104950
|
borderStyle: "double",
|
|
105344
104951
|
borderColor: "cyan",
|
|
@@ -105346,87 +104953,87 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105346
104953
|
paddingY: 1,
|
|
105347
104954
|
minWidth: 60,
|
|
105348
104955
|
children: [
|
|
105349
|
-
/* @__PURE__ */
|
|
104956
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105350
104957
|
paddingBottom: 1,
|
|
105351
|
-
children: /* @__PURE__ */
|
|
104958
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105352
104959
|
bold: true,
|
|
105353
104960
|
color: "cyan",
|
|
105354
104961
|
children: "Cost Breakdown"
|
|
105355
104962
|
}, undefined, false, undefined, this)
|
|
105356
104963
|
}, undefined, false, undefined, this),
|
|
105357
|
-
/* @__PURE__ */
|
|
104964
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105358
104965
|
paddingBottom: 1,
|
|
105359
104966
|
borderBottom: true,
|
|
105360
104967
|
borderColor: "gray",
|
|
105361
104968
|
children: [
|
|
105362
|
-
/* @__PURE__ */
|
|
104969
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105363
104970
|
width: 12,
|
|
105364
|
-
children: /* @__PURE__ */
|
|
104971
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105365
104972
|
bold: true,
|
|
105366
104973
|
children: "Story ID"
|
|
105367
104974
|
}, undefined, false, undefined, this)
|
|
105368
104975
|
}, undefined, false, undefined, this),
|
|
105369
|
-
/* @__PURE__ */
|
|
104976
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105370
104977
|
width: 12,
|
|
105371
|
-
children: /* @__PURE__ */
|
|
104978
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105372
104979
|
bold: true,
|
|
105373
104980
|
children: "Status"
|
|
105374
104981
|
}, undefined, false, undefined, this)
|
|
105375
104982
|
}, undefined, false, undefined, this),
|
|
105376
|
-
/* @__PURE__ */
|
|
104983
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105377
104984
|
width: 12,
|
|
105378
|
-
children: /* @__PURE__ */
|
|
104985
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105379
104986
|
bold: true,
|
|
105380
104987
|
children: "Cost"
|
|
105381
104988
|
}, undefined, false, undefined, this)
|
|
105382
104989
|
}, undefined, false, undefined, this)
|
|
105383
104990
|
]
|
|
105384
104991
|
}, undefined, true, undefined, this),
|
|
105385
|
-
/* @__PURE__ */
|
|
104992
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105386
104993
|
flexDirection: "column",
|
|
105387
104994
|
paddingY: 1,
|
|
105388
|
-
children: executedStories.length > 0 ? executedStories.map((story) => /* @__PURE__ */
|
|
104995
|
+
children: executedStories.length > 0 ? executedStories.map((story) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105389
104996
|
children: [
|
|
105390
|
-
/* @__PURE__ */
|
|
104997
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105391
104998
|
width: 12,
|
|
105392
|
-
children: /* @__PURE__ */
|
|
104999
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105393
105000
|
children: story.story.id
|
|
105394
105001
|
}, undefined, false, undefined, this)
|
|
105395
105002
|
}, undefined, false, undefined, this),
|
|
105396
|
-
/* @__PURE__ */
|
|
105003
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105397
105004
|
width: 12,
|
|
105398
|
-
children: /* @__PURE__ */
|
|
105005
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105399
105006
|
color: story.status === "passed" ? "green" : story.status === "failed" ? "red" : undefined,
|
|
105400
105007
|
children: story.status
|
|
105401
105008
|
}, undefined, false, undefined, this)
|
|
105402
105009
|
}, undefined, false, undefined, this),
|
|
105403
|
-
/* @__PURE__ */
|
|
105010
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105404
105011
|
width: 12,
|
|
105405
|
-
children: /* @__PURE__ */
|
|
105012
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105406
105013
|
children: formatCost2(story.cost || 0)
|
|
105407
105014
|
}, undefined, false, undefined, this)
|
|
105408
105015
|
}, undefined, false, undefined, this)
|
|
105409
105016
|
]
|
|
105410
|
-
}, story.story.id, true, undefined, this)) : /* @__PURE__ */
|
|
105017
|
+
}, story.story.id, true, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105411
105018
|
dimColor: true,
|
|
105412
105019
|
children: "No stories executed yet"
|
|
105413
105020
|
}, undefined, false, undefined, this)
|
|
105414
105021
|
}, undefined, false, undefined, this),
|
|
105415
|
-
/* @__PURE__ */
|
|
105022
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105416
105023
|
paddingTop: 1,
|
|
105417
105024
|
borderTop: true,
|
|
105418
105025
|
borderColor: "gray",
|
|
105419
105026
|
children: [
|
|
105420
|
-
/* @__PURE__ */
|
|
105027
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105421
105028
|
width: 24,
|
|
105422
|
-
children: /* @__PURE__ */
|
|
105029
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105423
105030
|
bold: true,
|
|
105424
105031
|
children: "Total Cost:"
|
|
105425
105032
|
}, undefined, false, undefined, this)
|
|
105426
105033
|
}, undefined, false, undefined, this),
|
|
105427
|
-
/* @__PURE__ */
|
|
105034
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105428
105035
|
width: 12,
|
|
105429
|
-
children: /* @__PURE__ */
|
|
105036
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105430
105037
|
bold: true,
|
|
105431
105038
|
color: "cyan",
|
|
105432
105039
|
children: formatCost2(totalCost)
|
|
@@ -105434,16 +105041,16 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105434
105041
|
}, undefined, false, undefined, this)
|
|
105435
105042
|
]
|
|
105436
105043
|
}, undefined, true, undefined, this),
|
|
105437
|
-
/* @__PURE__ */
|
|
105044
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105438
105045
|
justifyContent: "center",
|
|
105439
105046
|
paddingTop: 1,
|
|
105440
105047
|
borderTop: true,
|
|
105441
105048
|
borderColor: "gray",
|
|
105442
|
-
children: /* @__PURE__ */
|
|
105049
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105443
105050
|
dimColor: true,
|
|
105444
105051
|
children: [
|
|
105445
105052
|
"Press ",
|
|
105446
|
-
/* @__PURE__ */
|
|
105053
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105447
105054
|
color: "yellow",
|
|
105448
105055
|
children: "Esc"
|
|
105449
105056
|
}, undefined, false, undefined, this),
|
|
@@ -105456,118 +105063,118 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105456
105063
|
}
|
|
105457
105064
|
|
|
105458
105065
|
// src/tui/components/HelpOverlay.tsx
|
|
105459
|
-
var
|
|
105066
|
+
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
105460
105067
|
function HelpOverlay({ visible = false }) {
|
|
105461
105068
|
if (!visible) {
|
|
105462
105069
|
return null;
|
|
105463
105070
|
}
|
|
105464
|
-
return /* @__PURE__ */
|
|
105071
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105465
105072
|
flexDirection: "column",
|
|
105466
105073
|
borderStyle: "double",
|
|
105467
105074
|
borderColor: "cyan",
|
|
105468
105075
|
paddingX: 2,
|
|
105469
105076
|
paddingY: 1,
|
|
105470
105077
|
children: [
|
|
105471
|
-
/* @__PURE__ */
|
|
105078
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105472
105079
|
paddingBottom: 1,
|
|
105473
|
-
children: /* @__PURE__ */
|
|
105080
|
+
children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105474
105081
|
bold: true,
|
|
105475
105082
|
color: "cyan",
|
|
105476
105083
|
children: "Keyboard Shortcuts"
|
|
105477
105084
|
}, undefined, false, undefined, this)
|
|
105478
105085
|
}, undefined, false, undefined, this),
|
|
105479
|
-
/* @__PURE__ */
|
|
105086
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105480
105087
|
flexDirection: "column",
|
|
105481
105088
|
paddingBottom: 1,
|
|
105482
105089
|
children: [
|
|
105483
|
-
/* @__PURE__ */
|
|
105090
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105484
105091
|
dimColor: true,
|
|
105485
105092
|
children: "Stories Panel (default):"
|
|
105486
105093
|
}, undefined, false, undefined, this),
|
|
105487
|
-
/* @__PURE__ */
|
|
105094
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105488
105095
|
children: [
|
|
105489
105096
|
" ",
|
|
105490
|
-
/* @__PURE__ */
|
|
105097
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105491
105098
|
color: "yellow",
|
|
105492
105099
|
children: "p"
|
|
105493
105100
|
}, undefined, false, undefined, this),
|
|
105494
105101
|
" \u2014 Pause after current story"
|
|
105495
105102
|
]
|
|
105496
105103
|
}, undefined, true, undefined, this),
|
|
105497
|
-
/* @__PURE__ */
|
|
105104
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105498
105105
|
children: [
|
|
105499
105106
|
" ",
|
|
105500
|
-
/* @__PURE__ */
|
|
105107
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105501
105108
|
color: "yellow",
|
|
105502
105109
|
children: "a"
|
|
105503
105110
|
}, undefined, false, undefined, this),
|
|
105504
105111
|
" \u2014 Abort run"
|
|
105505
105112
|
]
|
|
105506
105113
|
}, undefined, true, undefined, this),
|
|
105507
|
-
/* @__PURE__ */
|
|
105114
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105508
105115
|
children: [
|
|
105509
105116
|
" ",
|
|
105510
|
-
/* @__PURE__ */
|
|
105117
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105511
105118
|
color: "yellow",
|
|
105512
105119
|
children: "s"
|
|
105513
105120
|
}, undefined, false, undefined, this),
|
|
105514
105121
|
" \u2014 Skip current story"
|
|
105515
105122
|
]
|
|
105516
105123
|
}, undefined, true, undefined, this),
|
|
105517
|
-
/* @__PURE__ */
|
|
105124
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105518
105125
|
children: [
|
|
105519
105126
|
" ",
|
|
105520
|
-
/* @__PURE__ */
|
|
105127
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105521
105128
|
color: "yellow",
|
|
105522
105129
|
children: "Tab"
|
|
105523
105130
|
}, undefined, false, undefined, this),
|
|
105524
105131
|
" \u2014 Toggle focus to Agent panel"
|
|
105525
105132
|
]
|
|
105526
105133
|
}, undefined, true, undefined, this),
|
|
105527
|
-
/* @__PURE__ */
|
|
105134
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105528
105135
|
children: [
|
|
105529
105136
|
" ",
|
|
105530
|
-
/* @__PURE__ */
|
|
105137
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105531
105138
|
color: "yellow",
|
|
105532
105139
|
children: "q"
|
|
105533
105140
|
}, undefined, false, undefined, this),
|
|
105534
105141
|
" \u2014 Quit TUI"
|
|
105535
105142
|
]
|
|
105536
105143
|
}, undefined, true, undefined, this),
|
|
105537
|
-
/* @__PURE__ */
|
|
105144
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105538
105145
|
children: [
|
|
105539
105146
|
" ",
|
|
105540
|
-
/* @__PURE__ */
|
|
105147
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105541
105148
|
color: "yellow",
|
|
105542
105149
|
children: "?"
|
|
105543
105150
|
}, undefined, false, undefined, this),
|
|
105544
105151
|
" \u2014 Show this help"
|
|
105545
105152
|
]
|
|
105546
105153
|
}, undefined, true, undefined, this),
|
|
105547
|
-
/* @__PURE__ */
|
|
105154
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105548
105155
|
children: [
|
|
105549
105156
|
" ",
|
|
105550
|
-
/* @__PURE__ */
|
|
105157
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105551
105158
|
color: "yellow",
|
|
105552
105159
|
children: "c"
|
|
105553
105160
|
}, undefined, false, undefined, this),
|
|
105554
105161
|
" \u2014 Show cost breakdown"
|
|
105555
105162
|
]
|
|
105556
105163
|
}, undefined, true, undefined, this),
|
|
105557
|
-
/* @__PURE__ */
|
|
105164
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105558
105165
|
children: [
|
|
105559
105166
|
" ",
|
|
105560
|
-
/* @__PURE__ */
|
|
105167
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105561
105168
|
color: "yellow",
|
|
105562
105169
|
children: "r"
|
|
105563
105170
|
}, undefined, false, undefined, this),
|
|
105564
105171
|
" \u2014 Retry last failed story"
|
|
105565
105172
|
]
|
|
105566
105173
|
}, undefined, true, undefined, this),
|
|
105567
|
-
/* @__PURE__ */
|
|
105174
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105568
105175
|
children: [
|
|
105569
105176
|
" ",
|
|
105570
|
-
/* @__PURE__ */
|
|
105177
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105571
105178
|
color: "yellow",
|
|
105572
105179
|
children: "Esc"
|
|
105573
105180
|
}, undefined, false, undefined, this),
|
|
@@ -105576,28 +105183,28 @@ function HelpOverlay({ visible = false }) {
|
|
|
105576
105183
|
}, undefined, true, undefined, this)
|
|
105577
105184
|
]
|
|
105578
105185
|
}, undefined, true, undefined, this),
|
|
105579
|
-
/* @__PURE__ */
|
|
105186
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105580
105187
|
flexDirection: "column",
|
|
105581
105188
|
paddingBottom: 1,
|
|
105582
105189
|
children: [
|
|
105583
|
-
/* @__PURE__ */
|
|
105190
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105584
105191
|
dimColor: true,
|
|
105585
105192
|
children: "Agent Panel (when focused):"
|
|
105586
105193
|
}, undefined, false, undefined, this),
|
|
105587
|
-
/* @__PURE__ */
|
|
105194
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105588
105195
|
children: [
|
|
105589
105196
|
" ",
|
|
105590
|
-
/* @__PURE__ */
|
|
105197
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105591
105198
|
color: "yellow",
|
|
105592
105199
|
children: "Ctrl+]"
|
|
105593
105200
|
}, undefined, false, undefined, this),
|
|
105594
105201
|
" \u2014 Escape back to Stories panel"
|
|
105595
105202
|
]
|
|
105596
105203
|
}, undefined, true, undefined, this),
|
|
105597
|
-
/* @__PURE__ */
|
|
105204
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105598
105205
|
children: [
|
|
105599
105206
|
" ",
|
|
105600
|
-
/* @__PURE__ */
|
|
105207
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105601
105208
|
dimColor: true,
|
|
105602
105209
|
children: "All other keys"
|
|
105603
105210
|
}, undefined, false, undefined, this),
|
|
@@ -105606,16 +105213,16 @@ function HelpOverlay({ visible = false }) {
|
|
|
105606
105213
|
}, undefined, true, undefined, this)
|
|
105607
105214
|
]
|
|
105608
105215
|
}, undefined, true, undefined, this),
|
|
105609
|
-
/* @__PURE__ */
|
|
105216
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105610
105217
|
justifyContent: "center",
|
|
105611
105218
|
paddingTop: 1,
|
|
105612
105219
|
borderTop: true,
|
|
105613
105220
|
borderColor: "gray",
|
|
105614
|
-
children: /* @__PURE__ */
|
|
105221
|
+
children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105615
105222
|
dimColor: true,
|
|
105616
105223
|
children: [
|
|
105617
105224
|
"Press ",
|
|
105618
|
-
/* @__PURE__ */
|
|
105225
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105619
105226
|
color: "yellow",
|
|
105620
105227
|
children: "Esc"
|
|
105621
105228
|
}, undefined, false, undefined, this),
|
|
@@ -105627,46 +105234,289 @@ function HelpOverlay({ visible = false }) {
|
|
|
105627
105234
|
}, undefined, true, undefined, this);
|
|
105628
105235
|
}
|
|
105629
105236
|
|
|
105630
|
-
//
|
|
105631
|
-
var
|
|
105632
|
-
|
|
105633
|
-
|
|
105634
|
-
|
|
105635
|
-
|
|
105636
|
-
|
|
105637
|
-
|
|
105638
|
-
|
|
105639
|
-
|
|
105640
|
-
|
|
105641
|
-
}
|
|
105642
|
-
},
|
|
105643
|
-
|
|
105644
|
-
|
|
105645
|
-
|
|
105646
|
-
|
|
105647
|
-
|
|
105648
|
-
|
|
105649
|
-
|
|
105237
|
+
// node_modules/ink-spinner/build/index.js
|
|
105238
|
+
var import_react29 = __toESM(require_react(), 1);
|
|
105239
|
+
var import_cli_spinners = __toESM(require_cli_spinners(), 1);
|
|
105240
|
+
function Spinner({ type = "dots" }) {
|
|
105241
|
+
const [frame, setFrame] = import_react29.useState(0);
|
|
105242
|
+
const spinner = import_cli_spinners.default[type];
|
|
105243
|
+
import_react29.useEffect(() => {
|
|
105244
|
+
const timer = setInterval(() => {
|
|
105245
|
+
setFrame((previousFrame) => {
|
|
105246
|
+
const isLastFrame = previousFrame === spinner.frames.length - 1;
|
|
105247
|
+
return isLastFrame ? 0 : previousFrame + 1;
|
|
105248
|
+
});
|
|
105249
|
+
}, spinner.interval);
|
|
105250
|
+
return () => {
|
|
105251
|
+
clearInterval(timer);
|
|
105252
|
+
};
|
|
105253
|
+
}, [spinner]);
|
|
105254
|
+
return import_react29.default.createElement(Text, null, spinner.frames[frame]);
|
|
105255
|
+
}
|
|
105256
|
+
var build_default = Spinner;
|
|
105257
|
+
|
|
105258
|
+
// src/tui/components/LiveActivityPanel.tsx
|
|
105259
|
+
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
105260
|
+
var MAX_ESCALATION_DISPLAY = 5;
|
|
105261
|
+
function LiveActivityPanel({
|
|
105262
|
+
focused = false,
|
|
105263
|
+
activeCalls,
|
|
105264
|
+
runSummary,
|
|
105265
|
+
runErrored,
|
|
105266
|
+
escalationLog = []
|
|
105267
|
+
}) {
|
|
105268
|
+
const borderColor = focused ? "cyan" : "gray";
|
|
105269
|
+
const activeCallList = activeCalls ? Array.from(activeCalls.values()) : [];
|
|
105270
|
+
const hasActiveCalls = activeCallList.length > 0;
|
|
105271
|
+
const hasSummary = runSummary !== undefined;
|
|
105272
|
+
const hasError = runErrored !== undefined;
|
|
105273
|
+
const recentEscalations = escalationLog.slice(-MAX_ESCALATION_DISPLAY);
|
|
105274
|
+
const hasEscalations = recentEscalations.length > 0;
|
|
105275
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105276
|
+
flexDirection: "column",
|
|
105277
|
+
flexGrow: 1,
|
|
105650
105278
|
borderStyle: "single",
|
|
105651
|
-
borderColor
|
|
105652
|
-
children:
|
|
105279
|
+
borderColor,
|
|
105280
|
+
children: [
|
|
105281
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105282
|
+
paddingX: 1,
|
|
105283
|
+
borderStyle: "single",
|
|
105284
|
+
borderBottom: true,
|
|
105285
|
+
borderColor,
|
|
105286
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105287
|
+
bold: true,
|
|
105288
|
+
color: focused ? "cyan" : undefined,
|
|
105289
|
+
children: [
|
|
105290
|
+
"Live Activity ",
|
|
105291
|
+
focused && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105292
|
+
dimColor: true,
|
|
105293
|
+
children: "(focused)"
|
|
105294
|
+
}, undefined, false, undefined, this)
|
|
105295
|
+
]
|
|
105296
|
+
}, undefined, true, undefined, this)
|
|
105297
|
+
}, undefined, false, undefined, this),
|
|
105298
|
+
hasError && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105299
|
+
paddingX: 1,
|
|
105300
|
+
paddingY: 1,
|
|
105301
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105302
|
+
color: "red",
|
|
105303
|
+
children: [
|
|
105304
|
+
"[FAIL] ",
|
|
105305
|
+
runErrored
|
|
105306
|
+
]
|
|
105307
|
+
}, undefined, true, undefined, this)
|
|
105308
|
+
}, undefined, false, undefined, this),
|
|
105309
|
+
hasSummary && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105310
|
+
flexDirection: "column",
|
|
105311
|
+
paddingX: 1,
|
|
105312
|
+
paddingY: 1,
|
|
105313
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(RunSummaryRow, {
|
|
105314
|
+
summary: runSummary
|
|
105315
|
+
}, undefined, false, undefined, this)
|
|
105316
|
+
}, undefined, false, undefined, this),
|
|
105317
|
+
hasActiveCalls && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105318
|
+
flexDirection: "column",
|
|
105319
|
+
paddingX: 1,
|
|
105320
|
+
paddingY: 1,
|
|
105321
|
+
children: activeCallList.map((call) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(ActiveCallRow, {
|
|
105322
|
+
call
|
|
105323
|
+
}, call.callId, false, undefined, this))
|
|
105324
|
+
}, undefined, false, undefined, this),
|
|
105325
|
+
hasEscalations && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105326
|
+
flexDirection: "column",
|
|
105327
|
+
paddingX: 1,
|
|
105328
|
+
children: [
|
|
105329
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105330
|
+
dimColor: true,
|
|
105331
|
+
children: "Escalations:"
|
|
105332
|
+
}, undefined, false, undefined, this),
|
|
105333
|
+
recentEscalations.map((entry) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(EscalationRow, {
|
|
105334
|
+
entry
|
|
105335
|
+
}, `${entry.storyId}-${entry.at}`, false, undefined, this))
|
|
105336
|
+
]
|
|
105337
|
+
}, undefined, true, undefined, this),
|
|
105338
|
+
!hasActiveCalls && !hasSummary && !hasError && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105339
|
+
paddingX: 1,
|
|
105340
|
+
paddingY: 1,
|
|
105341
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105342
|
+
dimColor: true,
|
|
105343
|
+
children: [
|
|
105344
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(build_default, {
|
|
105345
|
+
type: "dots"
|
|
105346
|
+
}, undefined, false, undefined, this),
|
|
105347
|
+
" Waiting for agent..."
|
|
105348
|
+
]
|
|
105349
|
+
}, undefined, true, undefined, this)
|
|
105350
|
+
}, undefined, false, undefined, this)
|
|
105351
|
+
]
|
|
105352
|
+
}, undefined, true, undefined, this);
|
|
105353
|
+
}
|
|
105354
|
+
function ActiveCallRow({ call }) {
|
|
105355
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105356
|
+
flexDirection: "column",
|
|
105357
|
+
marginBottom: 1,
|
|
105358
|
+
children: [
|
|
105359
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105360
|
+
flexDirection: "row",
|
|
105361
|
+
gap: 1,
|
|
105362
|
+
children: [
|
|
105363
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105364
|
+
color: "cyan",
|
|
105365
|
+
children: call.agentName
|
|
105366
|
+
}, undefined, false, undefined, this),
|
|
105367
|
+
call.storyId && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105368
|
+
children: call.storyId
|
|
105369
|
+
}, undefined, false, undefined, this),
|
|
105370
|
+
call.stage && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105371
|
+
dimColor: true,
|
|
105372
|
+
children: [
|
|
105373
|
+
"[",
|
|
105374
|
+
call.stage,
|
|
105375
|
+
"]"
|
|
105376
|
+
]
|
|
105377
|
+
}, undefined, true, undefined, this)
|
|
105378
|
+
]
|
|
105379
|
+
}, undefined, true, undefined, this),
|
|
105380
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105381
|
+
flexDirection: "row",
|
|
105382
|
+
gap: 1,
|
|
105383
|
+
children: [
|
|
105384
|
+
call.model && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105385
|
+
dimColor: true,
|
|
105386
|
+
children: [
|
|
105387
|
+
"model:",
|
|
105388
|
+
call.model
|
|
105389
|
+
]
|
|
105390
|
+
}, undefined, true, undefined, this),
|
|
105391
|
+
call.lastToolName && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105392
|
+
dimColor: true,
|
|
105393
|
+
children: [
|
|
105394
|
+
"tool:",
|
|
105395
|
+
call.lastToolName
|
|
105396
|
+
]
|
|
105397
|
+
}, undefined, true, undefined, this),
|
|
105398
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105399
|
+
dimColor: true,
|
|
105400
|
+
children: [
|
|
105401
|
+
"tools:",
|
|
105402
|
+
call.toolCallUpdates,
|
|
105403
|
+
" msg:",
|
|
105404
|
+
call.messageUpdates
|
|
105405
|
+
]
|
|
105406
|
+
}, undefined, true, undefined, this)
|
|
105407
|
+
]
|
|
105408
|
+
}, undefined, true, undefined, this)
|
|
105409
|
+
]
|
|
105410
|
+
}, undefined, true, undefined, this);
|
|
105411
|
+
}
|
|
105412
|
+
function RunSummaryRow({ summary }) {
|
|
105413
|
+
const cost = summary.totalCost !== undefined ? `$${summary.totalCost.toFixed(4)}` : null;
|
|
105414
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105415
|
+
flexDirection: "column",
|
|
105416
|
+
children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105417
|
+
flexDirection: "row",
|
|
105418
|
+
gap: 1,
|
|
105653
105419
|
children: [
|
|
105654
|
-
/* @__PURE__ */
|
|
105420
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105655
105421
|
bold: true,
|
|
105656
|
-
children:
|
|
105422
|
+
children: "Run complete"
|
|
105657
105423
|
}, undefined, false, undefined, this),
|
|
105658
|
-
/* @__PURE__ */
|
|
105424
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105425
|
+
color: "green",
|
|
105426
|
+
children: [
|
|
105427
|
+
summary.passedStories,
|
|
105428
|
+
" passed"
|
|
105429
|
+
]
|
|
105430
|
+
}, undefined, true, undefined, this),
|
|
105431
|
+
summary.failedStories > 0 && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105432
|
+
color: "red",
|
|
105433
|
+
children: [
|
|
105434
|
+
summary.failedStories,
|
|
105435
|
+
" failed"
|
|
105436
|
+
]
|
|
105437
|
+
}, undefined, true, undefined, this),
|
|
105438
|
+
summary.skippedStories > 0 && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105659
105439
|
dimColor: true,
|
|
105660
105440
|
children: [
|
|
105661
|
-
|
|
105662
|
-
|
|
105663
|
-
strategyInfo
|
|
105441
|
+
summary.skippedStories,
|
|
105442
|
+
" skipped"
|
|
105664
105443
|
]
|
|
105665
|
-
}, undefined, true, undefined, this)
|
|
105444
|
+
}, undefined, true, undefined, this),
|
|
105445
|
+
cost && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105446
|
+
dimColor: true,
|
|
105447
|
+
children: cost
|
|
105448
|
+
}, undefined, false, undefined, this)
|
|
105666
105449
|
]
|
|
105667
105450
|
}, undefined, true, undefined, this)
|
|
105668
105451
|
}, undefined, false, undefined, this);
|
|
105669
105452
|
}
|
|
105453
|
+
function EscalationRow({ entry }) {
|
|
105454
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
105455
|
+
flexDirection: "row",
|
|
105456
|
+
gap: 1,
|
|
105457
|
+
children: [
|
|
105458
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105459
|
+
dimColor: true,
|
|
105460
|
+
children: entry.storyId
|
|
105461
|
+
}, undefined, false, undefined, this),
|
|
105462
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105463
|
+
color: "yellow",
|
|
105464
|
+
children: entry.fromTier
|
|
105465
|
+
}, undefined, false, undefined, this),
|
|
105466
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105467
|
+
dimColor: true,
|
|
105468
|
+
children: "->"
|
|
105469
|
+
}, undefined, false, undefined, this),
|
|
105470
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105471
|
+
color: "cyan",
|
|
105472
|
+
children: entry.toTier
|
|
105473
|
+
}, undefined, false, undefined, this)
|
|
105474
|
+
]
|
|
105475
|
+
}, undefined, true, undefined, this);
|
|
105476
|
+
}
|
|
105477
|
+
|
|
105478
|
+
// src/tui/components/StatusBar.tsx
|
|
105479
|
+
var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
|
|
105480
|
+
function StatusBar({
|
|
105481
|
+
currentStage,
|
|
105482
|
+
currentStoryId,
|
|
105483
|
+
modelTier,
|
|
105484
|
+
runPaused,
|
|
105485
|
+
runComplete,
|
|
105486
|
+
isParallel,
|
|
105487
|
+
activeCount = 0
|
|
105488
|
+
}) {
|
|
105489
|
+
const hints = runComplete ? "q quit c cost ? help" : "p pause a abort s skip c cost ? help";
|
|
105490
|
+
let context;
|
|
105491
|
+
if (runComplete) {
|
|
105492
|
+
context = "done";
|
|
105493
|
+
} else if (runPaused) {
|
|
105494
|
+
context = "run paused";
|
|
105495
|
+
} else if (isParallel && activeCount > 0) {
|
|
105496
|
+
context = `parallel \xB7 ${activeCount} active`;
|
|
105497
|
+
} else if (currentStoryId) {
|
|
105498
|
+
const parts = [currentStoryId, currentStage, modelTier].filter(Boolean);
|
|
105499
|
+
context = parts.join(" \xB7 ");
|
|
105500
|
+
} else {
|
|
105501
|
+
context = "idle";
|
|
105502
|
+
}
|
|
105503
|
+
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
105504
|
+
paddingX: 1,
|
|
105505
|
+
borderStyle: "single",
|
|
105506
|
+
borderColor: "gray",
|
|
105507
|
+
justifyContent: "space-between",
|
|
105508
|
+
children: [
|
|
105509
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
105510
|
+
dimColor: true,
|
|
105511
|
+
children: hints
|
|
105512
|
+
}, undefined, false, undefined, this),
|
|
105513
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
105514
|
+
dimColor: true,
|
|
105515
|
+
children: context
|
|
105516
|
+
}, undefined, false, undefined, this)
|
|
105517
|
+
]
|
|
105518
|
+
}, undefined, true, undefined, this);
|
|
105519
|
+
}
|
|
105670
105520
|
|
|
105671
105521
|
// src/tui/components/StoriesPanel.tsx
|
|
105672
105522
|
var import_react31 = __toESM(require_react(), 1);
|
|
@@ -105731,13 +105581,7 @@ function getStatusIcon(status) {
|
|
|
105731
105581
|
return "\u23F8\uFE0F";
|
|
105732
105582
|
}
|
|
105733
105583
|
}
|
|
105734
|
-
function
|
|
105735
|
-
const totalSeconds = Math.floor(ms / 1000);
|
|
105736
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
105737
|
-
const seconds = totalSeconds % 60;
|
|
105738
|
-
return `${minutes}m ${seconds}s`;
|
|
105739
|
-
}
|
|
105740
|
-
function StoriesPanel({ stories, totalCost, elapsedMs, width, compact: compact2 = false, maxHeight }) {
|
|
105584
|
+
function StoriesPanel({ stories, width, compact: compact2 = false, maxHeight }) {
|
|
105741
105585
|
const maxVisible = compact2 ? COMPACT_MAX_VISIBLE_STORIES : MAX_VISIBLE_STORIES;
|
|
105742
105586
|
const needsScrolling = stories.length > maxVisible;
|
|
105743
105587
|
const [scrollOffset, setScrollOffset] = import_react31.useState(0);
|
|
@@ -105810,20 +105654,37 @@ function StoriesPanel({ stories, totalCost, elapsedMs, width, compact: compact2
|
|
|
105810
105654
|
}, undefined, true, undefined, this)
|
|
105811
105655
|
}, s.story.id, false, undefined, this);
|
|
105812
105656
|
}
|
|
105813
|
-
const routing = s.routing ? ` ${s.routing.complexity.slice(0, 3)}
|
|
105657
|
+
const routing = s.routing ? ` ${s.routing.complexity.slice(0, 3)}` : "";
|
|
105658
|
+
const shortTier = s.modelTier?.slice(0, 3);
|
|
105659
|
+
const tierSuffix = s.status === "retrying" && shortTier ? `\u2192${shortTier}` : s.status === "running" && shortTier ? shortTier : "";
|
|
105660
|
+
const showFailureLine = (s.status === "failed" || s.status === "paused") && s.failureReason;
|
|
105814
105661
|
return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
105815
|
-
|
|
105816
|
-
|
|
105817
|
-
|
|
105818
|
-
|
|
105819
|
-
|
|
105820
|
-
|
|
105821
|
-
|
|
105822
|
-
|
|
105823
|
-
|
|
105824
|
-
|
|
105825
|
-
|
|
105826
|
-
|
|
105662
|
+
flexDirection: "column",
|
|
105663
|
+
children: [
|
|
105664
|
+
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105665
|
+
children: [
|
|
105666
|
+
icon,
|
|
105667
|
+
" ",
|
|
105668
|
+
s.story.id,
|
|
105669
|
+
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105670
|
+
dimColor: true,
|
|
105671
|
+
children: routing
|
|
105672
|
+
}, undefined, false, undefined, this),
|
|
105673
|
+
tierSuffix ? /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105674
|
+
dimColor: true,
|
|
105675
|
+
children: [
|
|
105676
|
+
" ",
|
|
105677
|
+
tierSuffix
|
|
105678
|
+
]
|
|
105679
|
+
}, undefined, true, undefined, this) : null
|
|
105680
|
+
]
|
|
105681
|
+
}, undefined, true, undefined, this),
|
|
105682
|
+
showFailureLine && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105683
|
+
dimColor: true,
|
|
105684
|
+
children: ` \u2514 ${s.failureReason.slice(0, 25)}`
|
|
105685
|
+
}, undefined, false, undefined, this)
|
|
105686
|
+
]
|
|
105687
|
+
}, s.story.id, true, undefined, this);
|
|
105827
105688
|
})
|
|
105828
105689
|
}, undefined, false, undefined, this),
|
|
105829
105690
|
needsScrolling && canScrollDown && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
@@ -105836,50 +105697,7 @@ function StoriesPanel({ stories, totalCost, elapsedMs, width, compact: compact2
|
|
|
105836
105697
|
" more below"
|
|
105837
105698
|
]
|
|
105838
105699
|
}, undefined, true, undefined, this)
|
|
105839
|
-
}, undefined, false, undefined, this)
|
|
105840
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
105841
|
-
flexDirection: "column",
|
|
105842
|
-
paddingX: 1,
|
|
105843
|
-
paddingY: 1,
|
|
105844
|
-
borderStyle: "single",
|
|
105845
|
-
borderTop: true,
|
|
105846
|
-
borderColor: "gray",
|
|
105847
|
-
children: [
|
|
105848
|
-
!compact2 && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(jsx_dev_runtime5.Fragment, {
|
|
105849
|
-
children: [
|
|
105850
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105851
|
-
children: [
|
|
105852
|
-
"Cost: ",
|
|
105853
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105854
|
-
color: "green",
|
|
105855
|
-
children: [
|
|
105856
|
-
"$",
|
|
105857
|
-
totalCost.toFixed(4)
|
|
105858
|
-
]
|
|
105859
|
-
}, undefined, true, undefined, this)
|
|
105860
|
-
]
|
|
105861
|
-
}, undefined, true, undefined, this),
|
|
105862
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105863
|
-
children: [
|
|
105864
|
-
"Time: ",
|
|
105865
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105866
|
-
color: "cyan",
|
|
105867
|
-
children: formatElapsedTime(elapsedMs)
|
|
105868
|
-
}, undefined, false, undefined, this)
|
|
105869
|
-
]
|
|
105870
|
-
}, undefined, true, undefined, this)
|
|
105871
|
-
]
|
|
105872
|
-
}, undefined, true, undefined, this),
|
|
105873
|
-
compact2 && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105874
|
-
children: [
|
|
105875
|
-
"$",
|
|
105876
|
-
totalCost.toFixed(2),
|
|
105877
|
-
" \xB7 ",
|
|
105878
|
-
formatElapsedTime(elapsedMs)
|
|
105879
|
-
]
|
|
105880
|
-
}, undefined, true, undefined, this)
|
|
105881
|
-
]
|
|
105882
|
-
}, undefined, true, undefined, this)
|
|
105700
|
+
}, undefined, false, undefined, this)
|
|
105883
105701
|
]
|
|
105884
105702
|
}, undefined, true, undefined, this);
|
|
105885
105703
|
}
|
|
@@ -105908,7 +105726,8 @@ function useAgentStreamEvents(bus) {
|
|
|
105908
105726
|
thinkingUpdates: 0,
|
|
105909
105727
|
usageUpdates: 0,
|
|
105910
105728
|
toolCallUpdates: 0,
|
|
105911
|
-
status: "active"
|
|
105729
|
+
status: "active",
|
|
105730
|
+
model: event.model
|
|
105912
105731
|
});
|
|
105913
105732
|
break;
|
|
105914
105733
|
}
|
|
@@ -105951,7 +105770,8 @@ function useAgentStreamEvents(bus) {
|
|
|
105951
105770
|
next.set(event.callId, {
|
|
105952
105771
|
...state,
|
|
105953
105772
|
toolCallUpdates: state.toolCallUpdates + 1,
|
|
105954
|
-
lastActivityAt: event.timestamp
|
|
105773
|
+
lastActivityAt: event.timestamp,
|
|
105774
|
+
lastToolName: event.toolName
|
|
105955
105775
|
});
|
|
105956
105776
|
}
|
|
105957
105777
|
break;
|
|
@@ -106025,128 +105845,159 @@ function useKeyboard({ focus, currentStory, onAction, disabled = false }) {
|
|
|
106025
105845
|
});
|
|
106026
105846
|
}
|
|
106027
105847
|
|
|
106028
|
-
// src/tui/hooks/
|
|
105848
|
+
// src/tui/hooks/usePipelineBusEvents.ts
|
|
105849
|
+
init_pipeline();
|
|
106029
105850
|
var import_react33 = __toESM(require_react(), 1);
|
|
106030
|
-
function
|
|
105851
|
+
function usePipelineBusEvents(initialStories) {
|
|
106031
105852
|
const [state, setState] = import_react33.useState(() => ({
|
|
106032
|
-
stories: initialStories
|
|
106033
|
-
story,
|
|
106034
|
-
status: story.passes ? "passed" : "pending",
|
|
106035
|
-
routing: story.routing,
|
|
106036
|
-
cost: 0
|
|
106037
|
-
})),
|
|
105853
|
+
stories: initialStories,
|
|
106038
105854
|
totalCost: 0,
|
|
106039
|
-
elapsedMs: 0
|
|
105855
|
+
elapsedMs: 0,
|
|
105856
|
+
runPaused: false,
|
|
105857
|
+
runErrored: false,
|
|
105858
|
+
escalationLog: []
|
|
106040
105859
|
}));
|
|
106041
105860
|
const startTimeRef = import_react33.useRef(Date.now());
|
|
106042
105861
|
import_react33.useEffect(() => {
|
|
106043
105862
|
const startTime = startTimeRef.current;
|
|
106044
|
-
|
|
106045
|
-
const startTimer = () => {
|
|
106046
|
-
if (!timer) {
|
|
106047
|
-
timer = setInterval(() => {
|
|
106048
|
-
setState((prev) => ({
|
|
106049
|
-
...prev,
|
|
106050
|
-
elapsedMs: Date.now() - startTime
|
|
106051
|
-
}));
|
|
106052
|
-
}, 1000);
|
|
106053
|
-
}
|
|
106054
|
-
};
|
|
106055
|
-
const stopTimer = () => {
|
|
106056
|
-
if (timer) {
|
|
106057
|
-
clearInterval(timer);
|
|
106058
|
-
timer = null;
|
|
106059
|
-
}
|
|
106060
|
-
};
|
|
106061
|
-
const onStoryStart = (story) => {
|
|
106062
|
-
startTimer();
|
|
105863
|
+
const timer = setInterval(() => {
|
|
106063
105864
|
setState((prev) => ({
|
|
106064
105865
|
...prev,
|
|
106065
|
-
|
|
106066
|
-
stories: prev.stories.map((s) => s.story.id === story.id ? { ...s, status: "running" } : s)
|
|
105866
|
+
elapsedMs: Date.now() - startTime
|
|
106067
105867
|
}));
|
|
106068
|
-
};
|
|
106069
|
-
const
|
|
106070
|
-
|
|
105868
|
+
}, 1000);
|
|
105869
|
+
const unsubStarted = pipelineEventBus.on("story:started", (event) => {
|
|
105870
|
+
setState((prev) => ({
|
|
105871
|
+
...prev,
|
|
105872
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? {
|
|
105873
|
+
...s,
|
|
105874
|
+
status: "running",
|
|
105875
|
+
modelTier: event.modelTier,
|
|
105876
|
+
iteration: event.iteration
|
|
105877
|
+
} : s)
|
|
105878
|
+
}));
|
|
105879
|
+
});
|
|
105880
|
+
const unsubCompleted = pipelineEventBus.on("story:completed", (event) => {
|
|
106071
105881
|
setState((prev) => {
|
|
106072
105882
|
const newStories = prev.stories.map((s) => {
|
|
106073
|
-
if (s.story.id ===
|
|
106074
|
-
|
|
106075
|
-
|
|
106076
|
-
status = "passed";
|
|
106077
|
-
} else if (result2.action === "fail") {
|
|
106078
|
-
status = "failed";
|
|
106079
|
-
} else if (result2.action === "skip") {
|
|
106080
|
-
status = "skipped";
|
|
106081
|
-
} else if (result2.action === "pause") {
|
|
106082
|
-
status = "paused";
|
|
106083
|
-
}
|
|
106084
|
-
const storyCost = (s.cost || 0) + (result2.cost || 0);
|
|
105883
|
+
if (s.story.id === event.storyId) {
|
|
105884
|
+
const status = event.passed ? "passed" : "failed";
|
|
105885
|
+
const storyCost = event.cost ?? s.cost;
|
|
106085
105886
|
return { ...s, status, cost: storyCost };
|
|
106086
105887
|
}
|
|
106087
105888
|
return s;
|
|
106088
105889
|
});
|
|
106089
|
-
const totalCost = newStories.reduce((sum2, s) => sum2 + (s.cost
|
|
106090
|
-
return {
|
|
106091
|
-
...prev,
|
|
106092
|
-
stories: newStories,
|
|
106093
|
-
currentStory: undefined,
|
|
106094
|
-
totalCost
|
|
106095
|
-
};
|
|
105890
|
+
const totalCost = newStories.reduce((sum2, s) => sum2 + (s.cost ?? 0), 0);
|
|
105891
|
+
return { ...prev, stories: newStories, totalCost };
|
|
106096
105892
|
});
|
|
106097
|
-
};
|
|
106098
|
-
const
|
|
105893
|
+
});
|
|
105894
|
+
const unsubFailed = pipelineEventBus.on("story:failed", (event) => {
|
|
106099
105895
|
setState((prev) => ({
|
|
106100
105896
|
...prev,
|
|
106101
|
-
stories: prev.stories.map((s) => s.story.id ===
|
|
105897
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? {
|
|
105898
|
+
...s,
|
|
105899
|
+
status: "failed",
|
|
105900
|
+
failureReason: event.reason
|
|
105901
|
+
} : s)
|
|
106102
105902
|
}));
|
|
106103
|
-
};
|
|
106104
|
-
const
|
|
105903
|
+
});
|
|
105904
|
+
const unsubSkipped = pipelineEventBus.on("story:skipped", (event) => {
|
|
106105
105905
|
setState((prev) => ({
|
|
106106
105906
|
...prev,
|
|
106107
|
-
|
|
105907
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? { ...s, status: "skipped" } : s)
|
|
106108
105908
|
}));
|
|
106109
|
-
};
|
|
106110
|
-
const
|
|
105909
|
+
});
|
|
105910
|
+
const unsubEscalated = pipelineEventBus.on("story:escalated", (event) => {
|
|
105911
|
+
const entry = {
|
|
105912
|
+
storyId: event.storyId,
|
|
105913
|
+
fromTier: event.fromTier,
|
|
105914
|
+
toTier: event.toTier,
|
|
105915
|
+
at: Date.now()
|
|
105916
|
+
};
|
|
106111
105917
|
setState((prev) => ({
|
|
106112
105918
|
...prev,
|
|
106113
|
-
|
|
106114
|
-
|
|
105919
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? { ...s, status: "retrying" } : s),
|
|
105920
|
+
escalationLog: [...prev.escalationLog, entry]
|
|
106115
105921
|
}));
|
|
106116
|
-
};
|
|
106117
|
-
|
|
106118
|
-
|
|
106119
|
-
|
|
106120
|
-
|
|
106121
|
-
|
|
105922
|
+
});
|
|
105923
|
+
const unsubStoryPaused = pipelineEventBus.on("story:paused", (event) => {
|
|
105924
|
+
setState((prev) => ({
|
|
105925
|
+
...prev,
|
|
105926
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? { ...s, status: "paused", failureReason: event.reason } : s)
|
|
105927
|
+
}));
|
|
105928
|
+
});
|
|
105929
|
+
const unsubPaused = pipelineEventBus.on("run:paused", (_event) => {
|
|
105930
|
+
setState((prev) => ({ ...prev, runPaused: true }));
|
|
105931
|
+
});
|
|
105932
|
+
const unsubResumed = pipelineEventBus.on("run:resumed", (_event) => {
|
|
105933
|
+
setState((prev) => ({ ...prev, runPaused: false }));
|
|
105934
|
+
});
|
|
105935
|
+
const unsubCompleted2 = pipelineEventBus.on("run:completed", (event) => {
|
|
105936
|
+
clearInterval(timer);
|
|
105937
|
+
const summary = {
|
|
105938
|
+
totalStories: event.totalStories,
|
|
105939
|
+
passedStories: event.passedStories,
|
|
105940
|
+
failedStories: event.failedStories,
|
|
105941
|
+
skippedStories: event.skippedStories,
|
|
105942
|
+
pausedStories: event.pausedStories,
|
|
105943
|
+
durationMs: event.durationMs,
|
|
105944
|
+
totalCost: event.totalCost
|
|
105945
|
+
};
|
|
105946
|
+
setState((prev) => ({
|
|
105947
|
+
...prev,
|
|
105948
|
+
elapsedMs: event.durationMs,
|
|
105949
|
+
runSummary: summary,
|
|
105950
|
+
totalCost: event.totalCost ?? prev.totalCost
|
|
105951
|
+
}));
|
|
105952
|
+
});
|
|
105953
|
+
const unsubErrored = pipelineEventBus.on("run:errored", (_event) => {
|
|
105954
|
+
setState((prev) => ({ ...prev, runErrored: true }));
|
|
105955
|
+
});
|
|
106122
105956
|
return () => {
|
|
106123
|
-
|
|
106124
|
-
|
|
106125
|
-
|
|
106126
|
-
|
|
106127
|
-
|
|
106128
|
-
|
|
105957
|
+
clearInterval(timer);
|
|
105958
|
+
unsubStarted();
|
|
105959
|
+
unsubCompleted();
|
|
105960
|
+
unsubFailed();
|
|
105961
|
+
unsubSkipped();
|
|
105962
|
+
unsubEscalated();
|
|
105963
|
+
unsubStoryPaused();
|
|
105964
|
+
unsubPaused();
|
|
105965
|
+
unsubResumed();
|
|
105966
|
+
unsubCompleted2();
|
|
105967
|
+
unsubErrored();
|
|
106129
105968
|
};
|
|
106130
|
-
}, [
|
|
105969
|
+
}, []);
|
|
106131
105970
|
return state;
|
|
106132
105971
|
}
|
|
106133
105972
|
|
|
106134
|
-
// src/tui/hooks/
|
|
105973
|
+
// src/tui/hooks/usePipelineEvents.ts
|
|
106135
105974
|
var import_react34 = __toESM(require_react(), 1);
|
|
105975
|
+
function usePipelineEvents(events) {
|
|
105976
|
+
const [currentStage, setCurrentStage] = import_react34.useState(undefined);
|
|
105977
|
+
import_react34.useEffect(() => {
|
|
105978
|
+
const onStageEnter = (stage) => setCurrentStage(stage);
|
|
105979
|
+
events.on("stage:enter", onStageEnter);
|
|
105980
|
+
return () => events.off("stage:enter", onStageEnter);
|
|
105981
|
+
}, [events]);
|
|
105982
|
+
return { currentStage };
|
|
105983
|
+
}
|
|
105984
|
+
|
|
105985
|
+
// src/tui/hooks/usePty.ts
|
|
105986
|
+
var import_react35 = __toESM(require_react(), 1);
|
|
106136
105987
|
var MAX_PTY_BUFFER_LINES = 500;
|
|
106137
105988
|
var MAX_LINE_LENGTH = 1e4;
|
|
106138
105989
|
var PTY_FLUSH_INTERVAL_MS = 100;
|
|
106139
105990
|
function usePty(options) {
|
|
106140
|
-
const [state, setState] =
|
|
105991
|
+
const [state, setState] = import_react35.useState(() => ({
|
|
106141
105992
|
outputLines: [],
|
|
106142
105993
|
isRunning: false
|
|
106143
105994
|
}));
|
|
106144
|
-
const [handle, setHandle] =
|
|
105995
|
+
const [handle, setHandle] = import_react35.useState(null);
|
|
106145
105996
|
const command = options?.command;
|
|
106146
105997
|
const argsJson = JSON.stringify(options?.args);
|
|
106147
105998
|
const cwd2 = options?.cwd;
|
|
106148
105999
|
const envJson = JSON.stringify(options?.env);
|
|
106149
|
-
|
|
106000
|
+
import_react35.useEffect(() => {
|
|
106150
106001
|
if (!command) {
|
|
106151
106002
|
return;
|
|
106152
106003
|
}
|
|
@@ -106215,8 +106066,8 @@ function usePty(options) {
|
|
|
106215
106066
|
proc.kill();
|
|
106216
106067
|
};
|
|
106217
106068
|
}, [command, argsJson, cwd2, envJson]);
|
|
106218
|
-
const handleResize =
|
|
106219
|
-
|
|
106069
|
+
const handleResize = import_react35.useCallback((_cols, _rows) => {}, []);
|
|
106070
|
+
import_react35.useEffect(() => {
|
|
106220
106071
|
const onResize = () => {
|
|
106221
106072
|
const cols = process.stdout.columns ?? 80;
|
|
106222
106073
|
const rows = process.stdout.rows ?? 24;
|
|
@@ -106232,6 +106083,14 @@ function usePty(options) {
|
|
|
106232
106083
|
|
|
106233
106084
|
// src/tui/App.tsx
|
|
106234
106085
|
var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
|
|
106086
|
+
function formatElapsed(ms) {
|
|
106087
|
+
const mins = Math.floor(ms / 60000);
|
|
106088
|
+
const secs = Math.floor(ms % 60000 / 1000);
|
|
106089
|
+
return `${mins}m ${secs}s`;
|
|
106090
|
+
}
|
|
106091
|
+
function formatCost3(cost) {
|
|
106092
|
+
return `$${cost.toFixed(4)}`;
|
|
106093
|
+
}
|
|
106235
106094
|
function App2({
|
|
106236
106095
|
feature,
|
|
106237
106096
|
stories: initialStories,
|
|
@@ -106241,15 +106100,21 @@ function App2({
|
|
|
106241
106100
|
agentStreamEvents
|
|
106242
106101
|
}) {
|
|
106243
106102
|
const layout = useLayout();
|
|
106244
|
-
const
|
|
106103
|
+
const busState = usePipelineBusEvents(initialStories);
|
|
106104
|
+
const { currentStage } = usePipelineEvents(events);
|
|
106245
106105
|
const { exit } = use_app_default();
|
|
106246
|
-
const [focus, setFocus] =
|
|
106247
|
-
const [showHelp, setShowHelp] =
|
|
106248
|
-
const [showCost, setShowCost] =
|
|
106249
|
-
const [showQuitConfirm, setShowQuitConfirm] =
|
|
106250
|
-
const [showAbortConfirm, setShowAbortConfirm] =
|
|
106251
|
-
const {
|
|
106106
|
+
const [focus, setFocus] = import_react36.useState("stories" /* Stories */);
|
|
106107
|
+
const [showHelp, setShowHelp] = import_react36.useState(false);
|
|
106108
|
+
const [showCost, setShowCost] = import_react36.useState(false);
|
|
106109
|
+
const [showQuitConfirm, setShowQuitConfirm] = import_react36.useState(false);
|
|
106110
|
+
const [showAbortConfirm, setShowAbortConfirm] = import_react36.useState(false);
|
|
106111
|
+
const { handle: ptyHandle } = usePty(ptyOptions ?? null);
|
|
106252
106112
|
const { activeCalls } = useAgentStreamEvents(agentStreamEvents);
|
|
106113
|
+
const isRunComplete = !!busState.runSummary;
|
|
106114
|
+
const runningStories = busState.stories.filter((s) => s.status === "running");
|
|
106115
|
+
const isParallel = runningStories.length > 1;
|
|
106116
|
+
const currentRunningStory = runningStories[0];
|
|
106117
|
+
const runErroredForPanel = busState.runErrored ? "Run encountered an error" : undefined;
|
|
106253
106118
|
const handleKeyboardAction = async (action) => {
|
|
106254
106119
|
switch (action.type) {
|
|
106255
106120
|
case "TOGGLE_FOCUS":
|
|
@@ -106271,7 +106136,7 @@ function App2({
|
|
|
106271
106136
|
setShowAbortConfirm(false);
|
|
106272
106137
|
break;
|
|
106273
106138
|
case "QUIT":
|
|
106274
|
-
if (
|
|
106139
|
+
if (currentRunningStory) {
|
|
106275
106140
|
setShowQuitConfirm(true);
|
|
106276
106141
|
} else {
|
|
106277
106142
|
exit();
|
|
@@ -106283,7 +106148,7 @@ function App2({
|
|
|
106283
106148
|
}
|
|
106284
106149
|
break;
|
|
106285
106150
|
case "ABORT":
|
|
106286
|
-
if (
|
|
106151
|
+
if (currentRunningStory) {
|
|
106287
106152
|
setShowAbortConfirm(true);
|
|
106288
106153
|
} else if (queueFilePath) {
|
|
106289
106154
|
await writeQueueCommand(queueFilePath, { type: "ABORT" });
|
|
@@ -106325,12 +106190,18 @@ function App2({
|
|
|
106325
106190
|
});
|
|
106326
106191
|
useKeyboard({
|
|
106327
106192
|
focus,
|
|
106328
|
-
currentStory:
|
|
106193
|
+
currentStory: currentRunningStory?.story,
|
|
106329
106194
|
onAction: handleKeyboardAction,
|
|
106330
106195
|
disabled: showQuitConfirm || showAbortConfirm
|
|
106331
106196
|
});
|
|
106332
|
-
const currentRouting = state.currentStory?.routing;
|
|
106333
106197
|
const isTooSmall = layout.width < MIN_TERMINAL_WIDTH;
|
|
106198
|
+
const activeCount = runningStories.length;
|
|
106199
|
+
const headerRight = [
|
|
106200
|
+
activeCount > 0 ? `${activeCount} running` : null,
|
|
106201
|
+
formatCost3(busState.totalCost),
|
|
106202
|
+
formatElapsed(busState.elapsedMs)
|
|
106203
|
+
].filter(Boolean).join(" \xB7 ");
|
|
106204
|
+
const maxHeight = layout.mode === "single" ? COMPACT_MAX_VISIBLE_STORIES : MAX_VISIBLE_STORIES;
|
|
106334
106205
|
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106335
106206
|
flexDirection: "column",
|
|
106336
106207
|
height: "100%",
|
|
@@ -106340,22 +106211,29 @@ function App2({
|
|
|
106340
106211
|
borderStyle: "single",
|
|
106341
106212
|
borderBottom: true,
|
|
106342
106213
|
borderColor: "cyan",
|
|
106343
|
-
|
|
106344
|
-
|
|
106345
|
-
|
|
106346
|
-
|
|
106347
|
-
|
|
106348
|
-
|
|
106349
|
-
|
|
106350
|
-
|
|
106351
|
-
|
|
106214
|
+
justifyContent: "space-between",
|
|
106215
|
+
children: [
|
|
106216
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106217
|
+
bold: true,
|
|
106218
|
+
color: "cyan",
|
|
106219
|
+
children: [
|
|
106220
|
+
"nax run \u2014 ",
|
|
106221
|
+
feature
|
|
106222
|
+
]
|
|
106223
|
+
}, undefined, true, undefined, this),
|
|
106224
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106225
|
+
dimColor: true,
|
|
106226
|
+
children: headerRight
|
|
106227
|
+
}, undefined, false, undefined, this)
|
|
106228
|
+
]
|
|
106229
|
+
}, undefined, true, undefined, this),
|
|
106352
106230
|
isTooSmall && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106353
106231
|
paddingX: 1,
|
|
106354
106232
|
backgroundColor: "yellow",
|
|
106355
106233
|
children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106356
106234
|
color: "black",
|
|
106357
106235
|
children: [
|
|
106358
|
-
"
|
|
106236
|
+
"Terminal too narrow (",
|
|
106359
106237
|
layout.width,
|
|
106360
106238
|
" cols). Minimum ",
|
|
106361
106239
|
MIN_TERMINAL_WIDTH,
|
|
@@ -106368,33 +106246,36 @@ function App2({
|
|
|
106368
106246
|
flexGrow: 1,
|
|
106369
106247
|
children: [
|
|
106370
106248
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(StoriesPanel, {
|
|
106371
|
-
stories:
|
|
106372
|
-
totalCost: state.totalCost,
|
|
106373
|
-
elapsedMs: state.elapsedMs,
|
|
106249
|
+
stories: busState.stories,
|
|
106374
106250
|
width: layout.mode === "single" ? layout.width : layout.storiesPanelWidth,
|
|
106375
106251
|
compact: layout.mode === "single",
|
|
106376
|
-
maxHeight
|
|
106252
|
+
maxHeight
|
|
106377
106253
|
}, undefined, false, undefined, this),
|
|
106378
|
-
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(
|
|
106254
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(LiveActivityPanel, {
|
|
106379
106255
|
focused: focus === "agent" /* Agent */,
|
|
106380
|
-
|
|
106381
|
-
|
|
106256
|
+
activeCalls,
|
|
106257
|
+
runSummary: busState.runSummary,
|
|
106258
|
+
runErrored: runErroredForPanel,
|
|
106259
|
+
escalationLog: busState.escalationLog
|
|
106382
106260
|
}, undefined, false, undefined, this)
|
|
106383
106261
|
]
|
|
106384
106262
|
}, undefined, true, undefined, this),
|
|
106385
106263
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(StatusBar, {
|
|
106386
|
-
|
|
106387
|
-
|
|
106388
|
-
modelTier:
|
|
106389
|
-
|
|
106264
|
+
currentStage,
|
|
106265
|
+
currentStoryId: currentRunningStory?.story.id,
|
|
106266
|
+
modelTier: currentRunningStory?.modelTier,
|
|
106267
|
+
runPaused: busState.runPaused,
|
|
106268
|
+
runComplete: isRunComplete,
|
|
106269
|
+
isParallel,
|
|
106270
|
+
activeCount
|
|
106390
106271
|
}, undefined, false, undefined, this),
|
|
106391
106272
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(HelpOverlay, {
|
|
106392
106273
|
visible: showHelp
|
|
106393
106274
|
}, undefined, false, undefined, this),
|
|
106394
106275
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(CostOverlay, {
|
|
106395
106276
|
visible: showCost,
|
|
106396
|
-
stories:
|
|
106397
|
-
totalCost:
|
|
106277
|
+
stories: busState.stories,
|
|
106278
|
+
totalCost: busState.totalCost
|
|
106398
106279
|
}, undefined, false, undefined, this),
|
|
106399
106280
|
showQuitConfirm && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106400
106281
|
position: "absolute",
|
|
@@ -106412,7 +106293,7 @@ function App2({
|
|
|
106412
106293
|
children: [
|
|
106413
106294
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106414
106295
|
color: "yellow",
|
|
106415
|
-
children: "
|
|
106296
|
+
children: "Story is running. Quit anyway?"
|
|
106416
106297
|
}, undefined, false, undefined, this),
|
|
106417
106298
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106418
106299
|
paddingTop: 1,
|
|
@@ -106452,7 +106333,7 @@ function App2({
|
|
|
106452
106333
|
children: [
|
|
106453
106334
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106454
106335
|
color: "red",
|
|
106455
|
-
children: "
|
|
106336
|
+
children: "Story is running. Abort anyway?"
|
|
106456
106337
|
}, undefined, false, undefined, this),
|
|
106457
106338
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106458
106339
|
paddingTop: 1,
|
|
@@ -106541,8 +106422,8 @@ Next: nax generate --package ${options.package}`));
|
|
|
106541
106422
|
}
|
|
106542
106423
|
return;
|
|
106543
106424
|
}
|
|
106544
|
-
const naxDir =
|
|
106545
|
-
if (
|
|
106425
|
+
const naxDir = join83(workdir, ".nax");
|
|
106426
|
+
if (existsSync36(naxDir) && !options.force) {
|
|
106546
106427
|
console.log(source_default.yellow("nax already initialized. Use --force to overwrite."));
|
|
106547
106428
|
return;
|
|
106548
106429
|
}
|
|
@@ -106570,11 +106451,11 @@ Next: nax generate --package ${options.package}`));
|
|
|
106570
106451
|
}
|
|
106571
106452
|
}
|
|
106572
106453
|
}
|
|
106573
|
-
mkdirSync7(
|
|
106574
|
-
mkdirSync7(
|
|
106454
|
+
mkdirSync7(join83(naxDir, "features"), { recursive: true });
|
|
106455
|
+
mkdirSync7(join83(naxDir, "hooks"), { recursive: true });
|
|
106575
106456
|
const initConfig = options.name ? { ...DEFAULT_CONFIG, name: options.name } : DEFAULT_CONFIG;
|
|
106576
|
-
await Bun.write(
|
|
106577
|
-
await Bun.write(
|
|
106457
|
+
await Bun.write(join83(naxDir, "config.json"), JSON.stringify(initConfig, null, 2));
|
|
106458
|
+
await Bun.write(join83(naxDir, "hooks.json"), JSON.stringify({
|
|
106578
106459
|
hooks: {
|
|
106579
106460
|
"on-start": { command: 'echo "nax started: $NAX_FEATURE"', enabled: false },
|
|
106580
106461
|
"on-complete": { command: 'echo "nax complete: $NAX_FEATURE"', enabled: false },
|
|
@@ -106582,12 +106463,12 @@ Next: nax generate --package ${options.package}`));
|
|
|
106582
106463
|
"on-error": { command: 'echo "nax error: $NAX_REASON"', enabled: false }
|
|
106583
106464
|
}
|
|
106584
106465
|
}, null, 2));
|
|
106585
|
-
await Bun.write(
|
|
106466
|
+
await Bun.write(join83(naxDir, ".gitignore"), `# nax temp files
|
|
106586
106467
|
*.tmp
|
|
106587
106468
|
.paused.json
|
|
106588
106469
|
.nax-verifier-verdict.json
|
|
106589
106470
|
`);
|
|
106590
|
-
await Bun.write(
|
|
106471
|
+
await Bun.write(join83(naxDir, "context.md"), `# Project Context
|
|
106591
106472
|
|
|
106592
106473
|
This document defines coding standards, architectural decisions, and forbidden patterns for this project.
|
|
106593
106474
|
Run \`nax generate\` to regenerate agent config files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) from this file.
|
|
@@ -106684,7 +106565,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106684
106565
|
console.error(source_default.red("Error: --plan requires --from <spec-path>"));
|
|
106685
106566
|
process.exit(1);
|
|
106686
106567
|
}
|
|
106687
|
-
if (options.from && !
|
|
106568
|
+
if (options.from && !existsSync36(options.from)) {
|
|
106688
106569
|
console.error(source_default.red(`Error: File not found: ${options.from} (required with --plan)`));
|
|
106689
106570
|
process.exit(1);
|
|
106690
106571
|
}
|
|
@@ -106717,10 +106598,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106717
106598
|
console.error(source_default.red("nax not initialized. Run: nax init"));
|
|
106718
106599
|
process.exit(1);
|
|
106719
106600
|
}
|
|
106720
|
-
const featureDir =
|
|
106721
|
-
const prdPath =
|
|
106601
|
+
const featureDir = join83(naxDir, "features", options.feature);
|
|
106602
|
+
const prdPath = join83(featureDir, "prd.json");
|
|
106722
106603
|
if (options.plan && options.from) {
|
|
106723
|
-
if (
|
|
106604
|
+
if (existsSync36(prdPath) && !options.force) {
|
|
106724
106605
|
console.error(source_default.red(`Error: prd.json already exists for feature "${options.feature}".`));
|
|
106725
106606
|
console.error(source_default.dim(" Use --force to overwrite, or run without --plan to use the existing PRD."));
|
|
106726
106607
|
process.exit(1);
|
|
@@ -106740,10 +106621,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106740
106621
|
}
|
|
106741
106622
|
}
|
|
106742
106623
|
try {
|
|
106743
|
-
const planLogDir =
|
|
106624
|
+
const planLogDir = join83(featureDir, "plan");
|
|
106744
106625
|
mkdirSync7(planLogDir, { recursive: true });
|
|
106745
106626
|
const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
|
|
106746
|
-
const planLogPath =
|
|
106627
|
+
const planLogPath = join83(planLogDir, `${planLogId}.jsonl`);
|
|
106747
106628
|
initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
|
|
106748
106629
|
console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
|
|
106749
106630
|
console.log(source_default.dim(" [Planning phase: generating PRD from spec]"));
|
|
@@ -106782,17 +106663,17 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106782
106663
|
process.exit(1);
|
|
106783
106664
|
}
|
|
106784
106665
|
}
|
|
106785
|
-
if (!
|
|
106666
|
+
if (!existsSync36(prdPath)) {
|
|
106786
106667
|
console.error(source_default.red(`Feature "${options.feature}" not found or missing prd.json`));
|
|
106787
106668
|
process.exit(1);
|
|
106788
106669
|
}
|
|
106789
106670
|
resetLogger();
|
|
106790
|
-
const projectKey = config2.name?.trim() ||
|
|
106671
|
+
const projectKey = config2.name?.trim() || basename16(workdir);
|
|
106791
106672
|
const outputDir = projectOutputDir(projectKey, config2.outputDir);
|
|
106792
|
-
const runsDir =
|
|
106673
|
+
const runsDir = join83(outputDir, "features", options.feature, "runs");
|
|
106793
106674
|
mkdirSync7(runsDir, { recursive: true });
|
|
106794
106675
|
const runId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
|
|
106795
|
-
const logFilePath =
|
|
106676
|
+
const logFilePath = join83(runsDir, `${runId}.jsonl`);
|
|
106796
106677
|
const isTTY = process.stdout.isTTY ?? false;
|
|
106797
106678
|
const headlessFlag = options.headless ?? false;
|
|
106798
106679
|
const headlessEnv = process.env.NAX_HEADLESS === "1";
|
|
@@ -106809,7 +106690,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106809
106690
|
config2.agent.default = options.agent;
|
|
106810
106691
|
}
|
|
106811
106692
|
config2.execution.maxIterations = Number.parseInt(options.maxIterations, 10);
|
|
106812
|
-
const globalNaxDir =
|
|
106693
|
+
const globalNaxDir = join83(homedir3(), ".nax");
|
|
106813
106694
|
const hooks = await loadHooksConfig(naxDir, globalNaxDir);
|
|
106814
106695
|
const eventEmitter = new PipelineEventEmitter;
|
|
106815
106696
|
let tuiInstance;
|
|
@@ -106824,15 +106705,13 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106824
106705
|
tuiInstance = renderTui({
|
|
106825
106706
|
feature: options.feature,
|
|
106826
106707
|
stories: initialStories,
|
|
106827
|
-
totalCost: 0,
|
|
106828
|
-
elapsedMs: 0,
|
|
106829
106708
|
events: eventEmitter,
|
|
106830
106709
|
ptyOptions: null
|
|
106831
106710
|
});
|
|
106832
106711
|
} else {
|
|
106833
106712
|
console.log(source_default.dim(" [Headless mode \u2014 pipe output]"));
|
|
106834
106713
|
}
|
|
106835
|
-
const statusFilePath =
|
|
106714
|
+
const statusFilePath = join83(outputDir, "status.json");
|
|
106836
106715
|
let parallel;
|
|
106837
106716
|
if (options.parallel !== undefined) {
|
|
106838
106717
|
parallel = Number.parseInt(options.parallel, 10);
|
|
@@ -106858,9 +106737,9 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106858
106737
|
headless: useHeadless,
|
|
106859
106738
|
skipPrecheck: options.skipPrecheck ?? false
|
|
106860
106739
|
});
|
|
106861
|
-
const latestSymlink =
|
|
106740
|
+
const latestSymlink = join83(runsDir, "latest.jsonl");
|
|
106862
106741
|
try {
|
|
106863
|
-
if (
|
|
106742
|
+
if (existsSync36(latestSymlink)) {
|
|
106864
106743
|
Bun.spawnSync(["rm", latestSymlink]);
|
|
106865
106744
|
}
|
|
106866
106745
|
Bun.spawnSync(["ln", "-s", `${runId}.jsonl`, latestSymlink], {
|
|
@@ -106919,9 +106798,9 @@ features.command("create <name>").description("Create a new feature").option("-d
|
|
|
106919
106798
|
console.error(source_default.red("nax not initialized. Run: nax init"));
|
|
106920
106799
|
process.exit(1);
|
|
106921
106800
|
}
|
|
106922
|
-
const featureDir =
|
|
106801
|
+
const featureDir = join83(naxDir, "features", name);
|
|
106923
106802
|
mkdirSync7(featureDir, { recursive: true });
|
|
106924
|
-
await Bun.write(
|
|
106803
|
+
await Bun.write(join83(featureDir, "spec.md"), `# Feature: ${name}
|
|
106925
106804
|
|
|
106926
106805
|
## Overview
|
|
106927
106806
|
|
|
@@ -106954,7 +106833,7 @@ features.command("create <name>").description("Create a new feature").option("-d
|
|
|
106954
106833
|
|
|
106955
106834
|
<!-- What this feature explicitly does NOT cover. -->
|
|
106956
106835
|
`);
|
|
106957
|
-
await Bun.write(
|
|
106836
|
+
await Bun.write(join83(featureDir, "progress.txt"), `# Progress: ${name}
|
|
106958
106837
|
|
|
106959
106838
|
Created: ${new Date().toISOString()}
|
|
106960
106839
|
|
|
@@ -106980,13 +106859,13 @@ features.command("list").description("List all features").option("-d, --dir <pat
|
|
|
106980
106859
|
console.error(source_default.red("nax not initialized."));
|
|
106981
106860
|
process.exit(1);
|
|
106982
106861
|
}
|
|
106983
|
-
const featuresDir =
|
|
106984
|
-
if (!
|
|
106862
|
+
const featuresDir = join83(naxDir, "features");
|
|
106863
|
+
if (!existsSync36(featuresDir)) {
|
|
106985
106864
|
console.log(source_default.dim("No features yet."));
|
|
106986
106865
|
return;
|
|
106987
106866
|
}
|
|
106988
|
-
const { readdirSync:
|
|
106989
|
-
const entries =
|
|
106867
|
+
const { readdirSync: readdirSync9 } = await import("fs");
|
|
106868
|
+
const entries = readdirSync9(featuresDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
106990
106869
|
if (entries.length === 0) {
|
|
106991
106870
|
console.log(source_default.dim("No features yet."));
|
|
106992
106871
|
return;
|
|
@@ -106995,8 +106874,8 @@ features.command("list").description("List all features").option("-d, --dir <pat
|
|
|
106995
106874
|
Features:
|
|
106996
106875
|
`));
|
|
106997
106876
|
for (const name of entries) {
|
|
106998
|
-
const prdPath =
|
|
106999
|
-
if (
|
|
106877
|
+
const prdPath = join83(featuresDir, name, "prd.json");
|
|
106878
|
+
if (existsSync36(prdPath)) {
|
|
107000
106879
|
const prd = await loadPRD(prdPath);
|
|
107001
106880
|
const c = countStories(prd);
|
|
107002
106881
|
console.log(` ${name} \u2014 ${c.passed}/${c.total} stories done`);
|
|
@@ -107030,10 +106909,10 @@ Use: nax plan -f <feature> --from <spec>`));
|
|
|
107030
106909
|
cliOverrides.profile = options.profile;
|
|
107031
106910
|
}
|
|
107032
106911
|
const config2 = await loadConfig(workdir, cliOverrides);
|
|
107033
|
-
const featureLogDir =
|
|
106912
|
+
const featureLogDir = join83(naxDir, "features", options.feature, "plan");
|
|
107034
106913
|
mkdirSync7(featureLogDir, { recursive: true });
|
|
107035
106914
|
const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
|
|
107036
|
-
const planLogPath =
|
|
106915
|
+
const planLogPath = join83(featureLogDir, `${planLogId}.jsonl`);
|
|
107037
106916
|
initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
|
|
107038
106917
|
console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
|
|
107039
106918
|
try {
|
|
@@ -107198,19 +107077,6 @@ program2.command("logs").description("Display run logs with filtering and follow
|
|
|
107198
107077
|
process.exit(1);
|
|
107199
107078
|
}
|
|
107200
107079
|
});
|
|
107201
|
-
program2.command("diagnose").description("Diagnose run failures and generate recommendations").option("-f, --feature <name>", "Feature name (defaults to current feature)").option("-d, --dir <path>", "Working directory", process.cwd()).option("--json", "Output machine-readable JSON", false).option("--verbose", "Verbose output with story breakdown", false).action(async (options) => {
|
|
107202
|
-
try {
|
|
107203
|
-
await diagnose({
|
|
107204
|
-
feature: options.feature,
|
|
107205
|
-
workdir: options.dir,
|
|
107206
|
-
json: options.json,
|
|
107207
|
-
verbose: options.verbose
|
|
107208
|
-
});
|
|
107209
|
-
} catch (err) {
|
|
107210
|
-
console.error(source_default.red(`Error: ${err.message}`));
|
|
107211
|
-
process.exit(1);
|
|
107212
|
-
}
|
|
107213
|
-
});
|
|
107214
107080
|
program2.command("precheck").description("Validate feature readiness before execution").option("-f, --feature <name>", "Feature name").option("-d, --dir <path>", "Project directory", process.cwd()).option("--json", "Output machine-readable JSON", false).option("--light", "Environment-only check \u2014 skips PRD validation (use before nax plan)", false).action(async (options) => {
|
|
107215
107081
|
try {
|
|
107216
107082
|
await precheckCommand({
|