@nathapp/nax 0.68.4 → 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 +1142 -1247
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -16837,6 +16837,7 @@ var init_schemas_execution = __esm(() => {
|
|
|
16837
16837
|
fullSuiteTimeoutSeconds: exports_external.number().int().min(10).max(600).default(120),
|
|
16838
16838
|
maxFailureSummaryChars: exports_external.number().int().min(500).max(1e4).default(2000),
|
|
16839
16839
|
abortOnIncreasingFailures: exports_external.boolean().default(true),
|
|
16840
|
+
consecutiveIncreasesToBail: exports_external.number().int().min(1).max(10).default(2),
|
|
16840
16841
|
escalateOnExhaustion: exports_external.boolean().optional().default(true),
|
|
16841
16842
|
rethinkAtAttempt: exports_external.number().int().min(1).default(2),
|
|
16842
16843
|
urgencyAtAttempt: exports_external.number().int().min(1).default(3)
|
|
@@ -17321,6 +17322,7 @@ var init_schemas3 = __esm(() => {
|
|
|
17321
17322
|
fullSuiteTimeoutSeconds: 300,
|
|
17322
17323
|
maxFailureSummaryChars: 2000,
|
|
17323
17324
|
abortOnIncreasingFailures: true,
|
|
17325
|
+
consecutiveIncreasesToBail: 2,
|
|
17324
17326
|
escalateOnExhaustion: true,
|
|
17325
17327
|
rethinkAtAttempt: 2,
|
|
17326
17328
|
urgencyAtAttempt: 3
|
|
@@ -18378,16 +18380,13 @@ function deepMergeConfig(base, override) {
|
|
|
18378
18380
|
for (const hookName of allHookNames) {
|
|
18379
18381
|
const baseHook = baseHookDefs[hookName];
|
|
18380
18382
|
const overrideHook = overrideHookDefs[hookName];
|
|
18381
|
-
|
|
18382
|
-
|
|
18383
|
-
|
|
18384
|
-
|
|
18385
|
-
} else {
|
|
18386
|
-
mergedHookDefs[hookName] = baseHook;
|
|
18387
|
-
}
|
|
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;
|
|
18388
18387
|
}
|
|
18389
18388
|
merged.hooks = mergedHookDefs;
|
|
18390
|
-
} else if (overrideHooks.hooks) {
|
|
18389
|
+
} else if (isPlainObject2(overrideHooks.hooks)) {
|
|
18391
18390
|
merged.hooks = overrideHooks.hooks;
|
|
18392
18391
|
}
|
|
18393
18392
|
for (const hookKey of Object.keys(overrideHooks)) {
|
|
@@ -19086,6 +19085,12 @@ function resolveTestStrategy(raw) {
|
|
|
19086
19085
|
return "three-session-tdd-lite";
|
|
19087
19086
|
return "test-after";
|
|
19088
19087
|
}
|
|
19088
|
+
function isThreeSessionStrategy(strategy) {
|
|
19089
|
+
return strategy !== undefined && THREE_SESSION_STRATEGIES.has(strategy);
|
|
19090
|
+
}
|
|
19091
|
+
function isSingleSessionTestOwningStrategy(strategy) {
|
|
19092
|
+
return strategy !== undefined && SINGLE_SESSION_TEST_OWNING_STRATEGIES.has(strategy);
|
|
19093
|
+
}
|
|
19089
19094
|
function getAcQualityRules(profile) {
|
|
19090
19095
|
const langSection = profile?.language ? LANGUAGE_PATTERNS[profile.language] : undefined;
|
|
19091
19096
|
const typeSection = profile?.type ? TYPE_PATTERNS[profile.type] : undefined;
|
|
@@ -19098,7 +19103,7 @@ function getAcQualityRules(profile) {
|
|
|
19098
19103
|
|
|
19099
19104
|
${extras}`;
|
|
19100
19105
|
}
|
|
19101
|
-
var VALID_TEST_STRATEGIES, COMPLEXITY_GUIDE = `## Complexity Classification Guide
|
|
19106
|
+
var VALID_TEST_STRATEGIES, THREE_SESSION_STRATEGIES, SINGLE_SESSION_TEST_OWNING_STRATEGIES, COMPLEXITY_GUIDE = `## Complexity Classification Guide
|
|
19102
19107
|
|
|
19103
19108
|
Classify each story's complexity based on scope and risk \u2014 NOT acceptance criteria count.
|
|
19104
19109
|
A story with 10 simple "add field" ACs is simpler than one with 3 ACs involving concurrent
|
|
@@ -19239,6 +19244,11 @@ var init_test_strategy = __esm(() => {
|
|
|
19239
19244
|
"three-session-tdd",
|
|
19240
19245
|
"three-session-tdd-lite"
|
|
19241
19246
|
];
|
|
19247
|
+
THREE_SESSION_STRATEGIES = new Set([
|
|
19248
|
+
"three-session-tdd",
|
|
19249
|
+
"three-session-tdd-lite"
|
|
19250
|
+
]);
|
|
19251
|
+
SINGLE_SESSION_TEST_OWNING_STRATEGIES = new Set(["tdd-simple", "test-after"]);
|
|
19242
19252
|
LANGUAGE_PATTERNS = {
|
|
19243
19253
|
go: `### Go-Specific AC Patterns
|
|
19244
19254
|
|
|
@@ -28043,16 +28053,17 @@ function deriveTestPatterns(contextFiles, resolvedGlobs) {
|
|
|
28043
28053
|
async function detectTestDir(workdir, resolvedGlobs) {
|
|
28044
28054
|
const resolvedDirs = resolvedGlobs ? extractTestDirs(resolvedGlobs) : [];
|
|
28045
28055
|
const candidateDirs = resolvedDirs.length > 0 ? [...new Set([...resolvedDirs, ...DEFAULT_SCAN_TEST_DIRS])] : DEFAULT_SCAN_TEST_DIRS;
|
|
28046
|
-
|
|
28056
|
+
const checks3 = await Promise.all(candidateDirs.map(async (dir) => {
|
|
28047
28057
|
const fullPath = path.join(workdir, dir);
|
|
28048
28058
|
try {
|
|
28049
28059
|
const proc = Bun.spawn(["test", "-d", fullPath], { stdout: "pipe", stderr: "pipe" });
|
|
28050
28060
|
const exitCode = await proc.exited;
|
|
28051
|
-
|
|
28052
|
-
|
|
28053
|
-
|
|
28054
|
-
|
|
28055
|
-
|
|
28061
|
+
return exitCode === 0 ? dir : null;
|
|
28062
|
+
} catch {
|
|
28063
|
+
return null;
|
|
28064
|
+
}
|
|
28065
|
+
}));
|
|
28066
|
+
return checks3.find((dir) => dir !== null) ?? null;
|
|
28056
28067
|
}
|
|
28057
28068
|
function deriveScanGlob(resolvedTestGlobs, testDir) {
|
|
28058
28069
|
const prefix = `${testDir}/`;
|
|
@@ -29765,9 +29776,10 @@ Your task: make the failing tests pass by writing real source code.
|
|
|
29765
29776
|
Workflow:
|
|
29766
29777
|
1. Read every failing test in scope. The tests are the contract \u2014 understand what each one asserts before editing source.
|
|
29767
29778
|
2. Run the scoped test files once to establish the baseline (which fail, which pass, and why).
|
|
29768
|
-
3.
|
|
29769
|
-
4.
|
|
29770
|
-
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}'\`.
|
|
29771
29783
|
|
|
29772
29784
|
Rules:
|
|
29773
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.
|
|
@@ -29782,10 +29794,11 @@ Context: A test-writer session has already created tests and may have added mini
|
|
|
29782
29794
|
Workflow:
|
|
29783
29795
|
1. Run the existing scoped tests to see which fail and why (assertion failure vs import error).
|
|
29784
29796
|
2. Read each failing test. Note which ACs they cover and which they DON'T.
|
|
29785
|
-
3.
|
|
29786
|
-
4.
|
|
29787
|
-
5.
|
|
29788
|
-
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}'\`.
|
|
29789
29802
|
|
|
29790
29803
|
Rules:
|
|
29791
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.
|
|
@@ -29802,10 +29815,11 @@ Context: You are session 1 of a multi-session workflow. An implementer will foll
|
|
|
29802
29815
|
|
|
29803
29816
|
Workflow:
|
|
29804
29817
|
1. Re-read the acceptance criteria above.
|
|
29805
|
-
2.
|
|
29806
|
-
3. Create
|
|
29807
|
-
4.
|
|
29808
|
-
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.
|
|
29809
29823
|
|
|
29810
29824
|
Rules:
|
|
29811
29825
|
- Stubs are NOT implementations. The implementer in the next session writes real logic.
|
|
@@ -29822,9 +29836,10 @@ Context: You are session 1 of a multi-session workflow.
|
|
|
29822
29836
|
|
|
29823
29837
|
Workflow:
|
|
29824
29838
|
1. Re-read the acceptance criteria above.
|
|
29825
|
-
2.
|
|
29826
|
-
3.
|
|
29827
|
-
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.
|
|
29828
29843
|
|
|
29829
29844
|
Rules:
|
|
29830
29845
|
- Do NOT create or modify any source files. Read source for types/interfaces only.
|
|
@@ -36046,7 +36061,7 @@ var init_autofix_test_writer = __esm(() => {
|
|
|
36046
36061
|
kind: "run",
|
|
36047
36062
|
name: "autofix-test-writer",
|
|
36048
36063
|
stage: "rectification",
|
|
36049
|
-
session: { role: "test-writer", lifetime: "
|
|
36064
|
+
session: { role: "test-writer", lifetime: "warm" },
|
|
36050
36065
|
config: autofixConfigSelector,
|
|
36051
36066
|
build(input, _ctx) {
|
|
36052
36067
|
const prompt = RectifierPromptBuilder.testWriterRectification(input.failedChecks, input.story, {
|
|
@@ -36838,18 +36853,36 @@ var init__session_output = __esm(() => {
|
|
|
36838
36853
|
EMPTY = { success: false, filesChanged: [], output: "", parsed: false };
|
|
36839
36854
|
});
|
|
36840
36855
|
|
|
36856
|
+
// src/operations/execution-gates.ts
|
|
36857
|
+
function shouldRunReview(config2) {
|
|
36858
|
+
return config2.review?.enabled === true;
|
|
36859
|
+
}
|
|
36860
|
+
function shouldRunRectification(config2) {
|
|
36861
|
+
return config2.execution?.rectification?.enabled === true;
|
|
36862
|
+
}
|
|
36863
|
+
function shouldKeepSessionOpen(config2, role) {
|
|
36864
|
+
return SESSION_CONTINUITY_ROLES.has(role) && (shouldRunReview(config2) || shouldRunRectification(config2));
|
|
36865
|
+
}
|
|
36866
|
+
var SESSION_CONTINUITY_ROLES;
|
|
36867
|
+
var init_execution_gates = __esm(() => {
|
|
36868
|
+
init_config();
|
|
36869
|
+
SESSION_CONTINUITY_ROLES = new Set(["implementer", "test-writer"]);
|
|
36870
|
+
});
|
|
36871
|
+
|
|
36841
36872
|
// src/operations/write-test.ts
|
|
36842
36873
|
var testWriterOp;
|
|
36843
36874
|
var init_write_test = __esm(() => {
|
|
36844
36875
|
init_config();
|
|
36845
36876
|
init_isolation();
|
|
36846
36877
|
init__session_output();
|
|
36878
|
+
init_execution_gates();
|
|
36847
36879
|
testWriterOp = {
|
|
36848
36880
|
kind: "run",
|
|
36849
36881
|
name: "test-writer",
|
|
36850
36882
|
stage: "run",
|
|
36851
|
-
session: { role: "test-writer", lifetime: "
|
|
36883
|
+
session: { role: "test-writer", lifetime: "warm" },
|
|
36852
36884
|
config: tddConfigSelector,
|
|
36885
|
+
keepOpen: (_input, ctx) => shouldKeepSessionOpen(ctx.config, "test-writer"),
|
|
36853
36886
|
build(input, _ctx) {
|
|
36854
36887
|
if (input.promptMarkdown?.trim()) {
|
|
36855
36888
|
return {
|
|
@@ -36896,20 +36929,6 @@ var init_write_test = __esm(() => {
|
|
|
36896
36929
|
};
|
|
36897
36930
|
});
|
|
36898
36931
|
|
|
36899
|
-
// src/operations/execution-gates.ts
|
|
36900
|
-
function shouldRunReview(config2) {
|
|
36901
|
-
return config2.review?.enabled === true;
|
|
36902
|
-
}
|
|
36903
|
-
function shouldRunRectification(config2) {
|
|
36904
|
-
return config2.execution?.rectification?.enabled === true;
|
|
36905
|
-
}
|
|
36906
|
-
function shouldKeepSessionOpen(config2, role) {
|
|
36907
|
-
return role === "implementer" && (shouldRunReview(config2) || shouldRunRectification(config2));
|
|
36908
|
-
}
|
|
36909
|
-
var init_execution_gates = __esm(() => {
|
|
36910
|
-
init_config();
|
|
36911
|
-
});
|
|
36912
|
-
|
|
36913
36932
|
// src/operations/implement.ts
|
|
36914
36933
|
var implementerOp;
|
|
36915
36934
|
var init_implement = __esm(() => {
|
|
@@ -38416,10 +38435,11 @@ var init__finding_to_check = __esm(() => {
|
|
|
38416
38435
|
});
|
|
38417
38436
|
|
|
38418
38437
|
// src/operations/autofix-implementer-strategy.ts
|
|
38419
|
-
function makeAutofixImplementerStrategy(story, config2, sink) {
|
|
38438
|
+
function makeAutofixImplementerStrategy(story, config2, sink, opts = {}) {
|
|
38439
|
+
const claimsAdversarial = opts.includeAdversarialReview === true;
|
|
38420
38440
|
return {
|
|
38421
38441
|
name: "autofix-implementer",
|
|
38422
|
-
appliesTo: (f) => f.fixTarget === "source" && IMPLEMENTER_SOURCES.has(f.source),
|
|
38442
|
+
appliesTo: (f) => f.fixTarget === "source" && IMPLEMENTER_SOURCES.has(f.source) || claimsAdversarial && f.source === "adversarial-review",
|
|
38423
38443
|
fixOp: implementerRectifyOp,
|
|
38424
38444
|
buildInput: (findings, _prior, _cycleCtx) => ({
|
|
38425
38445
|
failedChecks: findingsToFailedChecks(findings),
|
|
@@ -41078,18 +41098,18 @@ ${exceptions.join(`
|
|
|
41078
41098
|
`)}`;
|
|
41079
41099
|
}
|
|
41080
41100
|
function implementerOwnsTests(story) {
|
|
41081
|
-
return
|
|
41101
|
+
return isSingleSessionTestOwningStrategy(story.routing?.testStrategy);
|
|
41082
41102
|
}
|
|
41083
41103
|
function testEditHeadline(story, prohibition) {
|
|
41084
41104
|
return implementerOwnsTests(story) ? SINGLE_SESSION_PERMIT_HEADLINE : prohibition;
|
|
41085
41105
|
}
|
|
41086
41106
|
function exceptionCountWord(story) {
|
|
41087
|
-
return
|
|
41107
|
+
return isThreeSessionStrategy(story.routing?.testStrategy) ? "four" : "three";
|
|
41088
41108
|
}
|
|
41089
41109
|
function escapeHatchFor(story) {
|
|
41090
41110
|
if (implementerOwnsTests(story))
|
|
41091
41111
|
return SINGLE_SESSION_TEST_EDIT_POLICY;
|
|
41092
|
-
const isTdd =
|
|
41112
|
+
const isTdd = isThreeSessionStrategy(story.routing?.testStrategy);
|
|
41093
41113
|
return buildEscapeHatch({ includeMockHandoff: isTdd });
|
|
41094
41114
|
}
|
|
41095
41115
|
function noTestIsolationBlock(story) {
|
|
@@ -41159,6 +41179,7 @@ ${errors3}
|
|
|
41159
41179
|
1. Read the relevant files to verify each finding is a real issue
|
|
41160
41180
|
2. Only fix findings that are actually valid problems
|
|
41161
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
|
|
41162
41183
|
|
|
41163
41184
|
${testEditHeadline(story, `Do NOT change test files or test behavior \u2014 see the ${exceptionCountWord(story)} narrow exceptions appended below.`)}
|
|
41164
41185
|
Do NOT add new features \u2014 only fix valid issues.
|
|
@@ -41182,6 +41203,7 @@ ${errors3}
|
|
|
41182
41203
|
1. Read the relevant files to verify each finding is a real issue
|
|
41183
41204
|
2. Only fix findings that are actually valid problems
|
|
41184
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
|
|
41185
41207
|
|
|
41186
41208
|
Do NOT add new features \u2014 only fix valid issues.
|
|
41187
41209
|
Commit your fixes when done.${scopeConstraint}${noTestIsolationBlock(story)}${escapeHatchFor(story)}`;
|
|
@@ -41208,6 +41230,7 @@ ${adversarialErrors}
|
|
|
41208
41230
|
1. Read the relevant files to verify each finding is a real issue
|
|
41209
41231
|
2. Only fix findings that are actually valid problems
|
|
41210
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
|
|
41211
41234
|
|
|
41212
41235
|
Do NOT add new features \u2014 only fix valid issues.
|
|
41213
41236
|
Commit your fixes when done.${scopeConstraint}${noTestIsolationBlock(story)}${escapeHatchFor(story)}`;
|
|
@@ -41294,7 +41317,7 @@ REASON: <one paragraph: which mock is wrong vs which dispatch the new code uses,
|
|
|
41294
41317
|
Rules:
|
|
41295
41318
|
- Do NOT make any edits yourself; the test-writer will fulfill.
|
|
41296
41319
|
- Do NOT also emit \`UNRESOLVED:\` in the same turn \u2014 this declaration IS the handoff.
|
|
41297
|
-
- FILES must list real test files. Each path must exist and be a test file.`,
|
|
41320
|
+
- FILES must list real test files. Each path must exist and be a test file.`, SINGLE_SESSION_PERMIT_HEADLINE = "You authored these tests in the same session as the implementation, so you MAY edit test files \u2014 but ONLY to resolve a genuine contradiction between a test and this story's acceptance criteria (or between two acceptance criteria). NEVER weaken, delete, loosen, or skip a test merely to make it pass. See the test-edit guidance appended below.", SINGLE_SESSION_TEST_EDIT_POLICY = `
|
|
41298
41321
|
|
|
41299
41322
|
## Test-edit guidance (single-session implementer)
|
|
41300
41323
|
|
|
@@ -41313,10 +41336,9 @@ If two findings or two acceptance criteria contradict each other and you cannot
|
|
|
41313
41336
|
both even after adjusting tests, do not guess. Emit:
|
|
41314
41337
|
UNRESOLVED: <which findings/ACs conflicted and why they cannot both be satisfied>`, CONTRADICTION_ESCAPE_HATCH, MAX_STRUCTURED_FINDINGS = 10, RAW_WITH_FINDINGS_LIMIT = 1000, RAW_FALLBACK_LIMIT = 4000;
|
|
41315
41338
|
var init_rectifier_builder_helpers = __esm(() => {
|
|
41339
|
+
init_config();
|
|
41316
41340
|
init_review();
|
|
41317
41341
|
init_sections2();
|
|
41318
|
-
THREE_SESSION_STRATEGIES = new Set(["three-session-tdd", "three-session-tdd-lite"]);
|
|
41319
|
-
SINGLE_SESSION_TEST_OWNING_STRATEGIES = new Set(["tdd-simple", "test-after"]);
|
|
41320
41342
|
CONTRADICTION_ESCAPE_HATCH = buildEscapeHatch({ includeMockHandoff: false });
|
|
41321
41343
|
});
|
|
41322
41344
|
|
|
@@ -41474,6 +41496,8 @@ ${findingLines}
|
|
|
41474
41496
|
|
|
41475
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.
|
|
41476
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
|
+
|
|
41477
41501
|
Rules:
|
|
41478
41502
|
1. Write the test against the SPECIFICATION, not the current behavior.
|
|
41479
41503
|
2. Do NOT fix the source files \u2014 only write test files.
|
|
@@ -41501,6 +41525,8 @@ ${fileList}
|
|
|
41501
41525
|
### Implementer handoff
|
|
41502
41526
|
${reason}
|
|
41503
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
|
+
|
|
41504
41530
|
Rules:
|
|
41505
41531
|
1. Modify ONLY the files listed above.
|
|
41506
41532
|
2. Do NOT modify any source file.
|
|
@@ -41539,7 +41565,8 @@ Before making any changes:
|
|
|
41539
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.
|
|
41540
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.
|
|
41541
41567
|
4. If the current behavior disagrees with the acceptance criteria, write the test against the spec and let the implementer fix the source.
|
|
41542
|
-
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.`;
|
|
41543
41570
|
return `${opener}
|
|
41544
41571
|
|
|
41545
41572
|
Story: ${story.title} (${story.id})
|
|
@@ -41729,7 +41756,7 @@ ${acList}
|
|
|
41729
41756
|
### Findings
|
|
41730
41757
|
${llmSection}
|
|
41731
41758
|
|
|
41732
|
-
**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.
|
|
41733
41760
|
|
|
41734
41761
|
Do NOT add new features \u2014 only fix the identified issues.
|
|
41735
41762
|
Commit your fixes when done.${scopeConstraint}${escapeHatchFor(story)}`;
|
|
@@ -41887,7 +41914,7 @@ Tests are failing. Fix the source so all tests pass \u2014 not just the ones lis
|
|
|
41887
41914
|
${detail}`);
|
|
41888
41915
|
}
|
|
41889
41916
|
lines.push(`
|
|
41890
|
-
|
|
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.`);
|
|
41891
41918
|
return lines.join(`
|
|
41892
41919
|
`);
|
|
41893
41920
|
}
|
|
@@ -48144,8 +48171,9 @@ ${request.summary}
|
|
|
48144
48171
|
if (!this.rl) {
|
|
48145
48172
|
throw new Error("CLI plugin not initialized");
|
|
48146
48173
|
}
|
|
48174
|
+
let timeoutId;
|
|
48147
48175
|
const timeoutPromise = new Promise((resolve13) => {
|
|
48148
|
-
setTimeout(() => {
|
|
48176
|
+
timeoutId = setTimeout(() => {
|
|
48149
48177
|
resolve13({
|
|
48150
48178
|
requestId: request.id,
|
|
48151
48179
|
action: "skip",
|
|
@@ -48155,8 +48183,12 @@ ${request.summary}
|
|
|
48155
48183
|
}, timeout);
|
|
48156
48184
|
});
|
|
48157
48185
|
const userPromise = this.getUserInput(request);
|
|
48158
|
-
|
|
48159
|
-
|
|
48186
|
+
try {
|
|
48187
|
+
return await Promise.race([userPromise, timeoutPromise]);
|
|
48188
|
+
} finally {
|
|
48189
|
+
if (timeoutId !== undefined)
|
|
48190
|
+
clearTimeout(timeoutId);
|
|
48191
|
+
}
|
|
48160
48192
|
}
|
|
48161
48193
|
async getUserInput(request) {
|
|
48162
48194
|
if (!this.rl) {
|
|
@@ -53430,6 +53462,11 @@ function phasesToRevalidate(strategiesRun, allPhases) {
|
|
|
53430
53462
|
}
|
|
53431
53463
|
return allPhases.filter((p) => needed.has(p.kind));
|
|
53432
53464
|
}
|
|
53465
|
+
function orderGateLast(phases) {
|
|
53466
|
+
const rest = phases.filter((p) => p.kind !== "full-suite-gate");
|
|
53467
|
+
const gates = phases.filter((p) => p.kind === "full-suite-gate");
|
|
53468
|
+
return [...rest, ...gates];
|
|
53469
|
+
}
|
|
53433
53470
|
function toReviewDecisionPayload(opName, output) {
|
|
53434
53471
|
if (output === null || output === undefined || typeof output !== "object")
|
|
53435
53472
|
return null;
|
|
@@ -53644,18 +53681,24 @@ async function runPhase(ctx, slot, phaseCosts, phaseOutputs, isThreeSession = fa
|
|
|
53644
53681
|
scope.close();
|
|
53645
53682
|
}
|
|
53646
53683
|
}
|
|
53647
|
-
function withIncreasingFailuresBail(strategies, enabled) {
|
|
53684
|
+
function withIncreasingFailuresBail(strategies, enabled, consecutiveIncreases) {
|
|
53648
53685
|
if (!enabled)
|
|
53649
53686
|
return strategies;
|
|
53687
|
+
const threshold = Math.max(1, consecutiveIncreases);
|
|
53650
53688
|
return strategies.map((strategy) => ({
|
|
53651
53689
|
...strategy,
|
|
53652
53690
|
bailWhen: (iterations) => {
|
|
53653
53691
|
const userReason = strategy.bailWhen?.(iterations) ?? null;
|
|
53654
53692
|
if (userReason !== null)
|
|
53655
53693
|
return userReason;
|
|
53656
|
-
|
|
53657
|
-
|
|
53658
|
-
|
|
53694
|
+
if (iterations.length < threshold)
|
|
53695
|
+
return null;
|
|
53696
|
+
const trailing = iterations.slice(-threshold);
|
|
53697
|
+
const allRegressed = trailing.every((it) => it.findingsAfter.length > it.findingsBefore.length);
|
|
53698
|
+
if (allRegressed) {
|
|
53699
|
+
const first = trailing[0];
|
|
53700
|
+
const last = trailing[trailing.length - 1];
|
|
53701
|
+
return `failure count increased for ${threshold} consecutive iteration(s): ${first.findingsBefore.length} -> ${last.findingsAfter.length}`;
|
|
53659
53702
|
}
|
|
53660
53703
|
return null;
|
|
53661
53704
|
}
|
|
@@ -53685,13 +53728,14 @@ async function runRectification(ctx, state, phaseCosts, phaseOutputs) {
|
|
|
53685
53728
|
const cycle = {
|
|
53686
53729
|
findings: [...initialFindings],
|
|
53687
53730
|
iterations: [],
|
|
53688
|
-
strategies: withIncreasingFailuresBail(rectification.strategies, rectification.abortOnIncreasingFailures),
|
|
53731
|
+
strategies: withIncreasingFailuresBail(rectification.strategies, rectification.abortOnIncreasingFailures, rectification.consecutiveIncreasesToBail ?? 1),
|
|
53689
53732
|
config: { maxAttemptsTotal: rectification.maxAttempts, validatorRetries: 1 },
|
|
53690
53733
|
validate: async (_validateCtx, opts) => {
|
|
53691
53734
|
if (ctx.runtime.signal?.aborted)
|
|
53692
53735
|
return { findings: [], shortCircuited: false };
|
|
53693
53736
|
const lite = (opts?.mode ?? "full") === "lite";
|
|
53694
|
-
const
|
|
53737
|
+
const selected = phasesToRevalidate(opts?.strategiesRun, validationPhases);
|
|
53738
|
+
const phases = lite ? orderGateLast(selected) : selected;
|
|
53695
53739
|
getSafeLogger()?.debug("story-orchestrator", "rectification validate scope", {
|
|
53696
53740
|
storyId: ctx.storyId,
|
|
53697
53741
|
mode: opts?.mode ?? "full",
|
|
@@ -53701,9 +53745,6 @@ async function runRectification(ctx, state, phaseCosts, phaseOutputs) {
|
|
|
53701
53745
|
const findings = [];
|
|
53702
53746
|
let shortCircuited = false;
|
|
53703
53747
|
for (const phase of phases) {
|
|
53704
|
-
if (lite && phase.kind === "full-suite-gate") {
|
|
53705
|
-
continue;
|
|
53706
|
-
}
|
|
53707
53748
|
await runPhase(ctx, phase.slot, phaseCosts, phaseOutputs);
|
|
53708
53749
|
if (shouldSkipPhaseForRectification(phase, state, phaseOutputs))
|
|
53709
53750
|
continue;
|
|
@@ -54019,9 +54060,6 @@ var init_story_orchestrator = __esm(() => {
|
|
|
54019
54060
|
|
|
54020
54061
|
// src/execution/build-plan-for-strategy.ts
|
|
54021
54062
|
import { join as join46 } from "path";
|
|
54022
|
-
function isThreeSessionStrategy(strategy) {
|
|
54023
|
-
return THREE_SESSION_STRATEGIES2.has(strategy);
|
|
54024
|
-
}
|
|
54025
54063
|
function requiresInitialRefCapture(strategy) {
|
|
54026
54064
|
return isThreeSessionStrategy(strategy);
|
|
54027
54065
|
}
|
|
@@ -54080,8 +54118,12 @@ async function buildPlanForStrategy(ctx, story, config2, testStrategy, inputs) {
|
|
|
54080
54118
|
strategies.push(makeFullSuiteRectifyStrategy(story, config2));
|
|
54081
54119
|
}
|
|
54082
54120
|
if (config2.quality.autofix?.enabled !== false) {
|
|
54083
|
-
strategies.push(makeAutofixImplementerStrategy(story, config2, sink
|
|
54084
|
-
|
|
54121
|
+
strategies.push(makeAutofixImplementerStrategy(story, config2, sink, {
|
|
54122
|
+
includeAdversarialReview: !isThreeSession
|
|
54123
|
+
}));
|
|
54124
|
+
if (isThreeSession) {
|
|
54125
|
+
strategies.push(makeAutofixTestWriterStrategy(story, config2, sink));
|
|
54126
|
+
}
|
|
54085
54127
|
}
|
|
54086
54128
|
const postValidate = async (findings, _validateCtx) => {
|
|
54087
54129
|
if (sink.testEdits.length === 0 && sink.mockHandoffs.length === 0)
|
|
@@ -54107,14 +54149,13 @@ async function buildPlanForStrategy(ctx, story, config2, testStrategy, inputs) {
|
|
|
54107
54149
|
}
|
|
54108
54150
|
return builder.build(ctx, { isThreeSession });
|
|
54109
54151
|
}
|
|
54110
|
-
var THREE_SESSION_STRATEGIES2;
|
|
54111
54152
|
var init_build_plan_for_strategy = __esm(() => {
|
|
54153
|
+
init_config();
|
|
54112
54154
|
init_operations();
|
|
54113
54155
|
init_execution_gates();
|
|
54114
54156
|
init_full_suite_rectify();
|
|
54115
54157
|
init_test_runners();
|
|
54116
54158
|
init_story_orchestrator();
|
|
54117
|
-
THREE_SESSION_STRATEGIES2 = new Set(["three-session-tdd", "three-session-tdd-lite"]);
|
|
54118
54159
|
});
|
|
54119
54160
|
|
|
54120
54161
|
// src/execution/plan-inputs.ts
|
|
@@ -54314,7 +54355,8 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
54314
54355
|
const rectificationInput = ctx.config.execution?.rectification?.enabled === true ? {
|
|
54315
54356
|
maxAttempts: ctx.config.execution.rectification.maxAttemptsTotal,
|
|
54316
54357
|
strategies: [],
|
|
54317
|
-
abortOnIncreasingFailures: ctx.config.execution.rectification.abortOnIncreasingFailures
|
|
54358
|
+
abortOnIncreasingFailures: ctx.config.execution.rectification.abortOnIncreasingFailures,
|
|
54359
|
+
consecutiveIncreasesToBail: ctx.config.execution.rectification.consecutiveIncreasesToBail
|
|
54318
54360
|
} : undefined;
|
|
54319
54361
|
return {
|
|
54320
54362
|
story,
|
|
@@ -54333,12 +54375,12 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
54333
54375
|
};
|
|
54334
54376
|
}
|
|
54335
54377
|
var init_plan_inputs = __esm(() => {
|
|
54378
|
+
init_config();
|
|
54336
54379
|
init_context();
|
|
54337
54380
|
init_errors();
|
|
54338
54381
|
init_prompts();
|
|
54339
54382
|
init_review();
|
|
54340
54383
|
init_resolver();
|
|
54341
|
-
init_build_plan_for_strategy();
|
|
54342
54384
|
});
|
|
54343
54385
|
|
|
54344
54386
|
// src/pipeline/stages/execution-helpers.ts
|
|
@@ -54865,6 +54907,7 @@ var init_post_run = __esm(() => {
|
|
|
54865
54907
|
// src/pipeline/stages/execution.ts
|
|
54866
54908
|
var RUNTIME_CRASH_CODES, executionStage, _executionDeps;
|
|
54867
54909
|
var init_execution = __esm(() => {
|
|
54910
|
+
init_config();
|
|
54868
54911
|
init_agents();
|
|
54869
54912
|
init_errors();
|
|
54870
54913
|
init_build_plan_for_strategy();
|
|
@@ -55455,7 +55498,16 @@ var init_routing2 = __esm(() => {
|
|
|
55455
55498
|
const TIER_RANK = { fast: 0, balanced: 1, powerful: 2 };
|
|
55456
55499
|
const derivedTier = decision.modelTier;
|
|
55457
55500
|
const previousTier = ctx.story.routing?.modelTier;
|
|
55458
|
-
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;
|
|
55459
55511
|
const modelTier = isEscalated ? previousTier : derivedTier;
|
|
55460
55512
|
const routing = { ...decision, modelTier, agent: ctx.story.routing?.agent };
|
|
55461
55513
|
ctx.story.routing = {
|
|
@@ -55562,6 +55614,7 @@ var init_pipeline = __esm(() => {
|
|
|
55562
55614
|
init_runner4();
|
|
55563
55615
|
init_events();
|
|
55564
55616
|
init_stages();
|
|
55617
|
+
init_event_bus();
|
|
55565
55618
|
});
|
|
55566
55619
|
|
|
55567
55620
|
// src/cli/prompts-shared.ts
|
|
@@ -58122,12 +58175,12 @@ var init_loader4 = __esm(() => {
|
|
|
58122
58175
|
});
|
|
58123
58176
|
|
|
58124
58177
|
// src/utils/paths.ts
|
|
58125
|
-
import { join as
|
|
58178
|
+
import { join as join63 } from "path";
|
|
58126
58179
|
function getRunsDir() {
|
|
58127
|
-
return process.env.NAX_RUNS_DIR ??
|
|
58180
|
+
return process.env.NAX_RUNS_DIR ?? join63(globalConfigDir(), "runs");
|
|
58128
58181
|
}
|
|
58129
58182
|
function getEventsRootDir() {
|
|
58130
|
-
return
|
|
58183
|
+
return join63(globalConfigDir(), "events");
|
|
58131
58184
|
}
|
|
58132
58185
|
var init_paths3 = __esm(() => {
|
|
58133
58186
|
init_paths();
|
|
@@ -58187,7 +58240,7 @@ var init_command_argv = __esm(() => {
|
|
|
58187
58240
|
});
|
|
58188
58241
|
|
|
58189
58242
|
// src/hooks/runner.ts
|
|
58190
|
-
import { join as
|
|
58243
|
+
import { join as join70 } from "path";
|
|
58191
58244
|
function createDrainDeadline2(deadlineMs) {
|
|
58192
58245
|
let timeoutId;
|
|
58193
58246
|
const promise2 = new Promise((resolve16) => {
|
|
@@ -58206,14 +58259,14 @@ async function loadHooksConfig(projectDir, globalDir) {
|
|
|
58206
58259
|
let globalHooks = { hooks: {} };
|
|
58207
58260
|
let projectHooks = { hooks: {} };
|
|
58208
58261
|
let skipGlobal = false;
|
|
58209
|
-
const projectPath =
|
|
58262
|
+
const projectPath = join70(projectDir, "hooks.json");
|
|
58210
58263
|
const projectData = await loadJsonFile(projectPath, "hooks");
|
|
58211
58264
|
if (projectData) {
|
|
58212
58265
|
projectHooks = projectData;
|
|
58213
58266
|
skipGlobal = projectData.skipGlobal ?? false;
|
|
58214
58267
|
}
|
|
58215
58268
|
if (!skipGlobal && globalDir) {
|
|
58216
|
-
const globalPath =
|
|
58269
|
+
const globalPath = join70(globalDir, "hooks.json");
|
|
58217
58270
|
const globalData = await loadJsonFile(globalPath, "hooks");
|
|
58218
58271
|
if (globalData) {
|
|
58219
58272
|
globalHooks = globalData;
|
|
@@ -58383,7 +58436,7 @@ var package_default;
|
|
|
58383
58436
|
var init_package = __esm(() => {
|
|
58384
58437
|
package_default = {
|
|
58385
58438
|
name: "@nathapp/nax",
|
|
58386
|
-
version: "0.68.
|
|
58439
|
+
version: "0.68.6",
|
|
58387
58440
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
58388
58441
|
type: "module",
|
|
58389
58442
|
bin: {
|
|
@@ -58478,8 +58531,8 @@ var init_version = __esm(() => {
|
|
|
58478
58531
|
NAX_VERSION = package_default.version;
|
|
58479
58532
|
NAX_COMMIT = (() => {
|
|
58480
58533
|
try {
|
|
58481
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
58482
|
-
return "
|
|
58534
|
+
if (/^[0-9a-f]{6,10}$/.test("acc1d4bd"))
|
|
58535
|
+
return "acc1d4bd";
|
|
58483
58536
|
} catch {}
|
|
58484
58537
|
try {
|
|
58485
58538
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -58500,9 +58553,9 @@ var init_version = __esm(() => {
|
|
|
58500
58553
|
// src/execution/crash-heartbeat.ts
|
|
58501
58554
|
import { appendFileSync as appendFileSync2 } from "fs";
|
|
58502
58555
|
async function heartbeatLoop(statusWriter, getTotalCost, getIterations, jsonlFilePath) {
|
|
58503
|
-
const logger = getSafeLogger();
|
|
58556
|
+
const logger = _heartbeatDeps.getSafeLogger();
|
|
58504
58557
|
while (heartbeatActive) {
|
|
58505
|
-
await
|
|
58558
|
+
await _heartbeatDeps.sleep(60000);
|
|
58506
58559
|
if (!heartbeatActive)
|
|
58507
58560
|
break;
|
|
58508
58561
|
try {
|
|
@@ -58531,10 +58584,14 @@ async function heartbeatLoop(statusWriter, getTotalCost, getIterations, jsonlFil
|
|
|
58531
58584
|
}
|
|
58532
58585
|
}
|
|
58533
58586
|
function startHeartbeat(statusWriter, getTotalCost, getIterations, jsonlFilePath) {
|
|
58534
|
-
const logger = getSafeLogger();
|
|
58587
|
+
const logger = _heartbeatDeps.getSafeLogger();
|
|
58535
58588
|
stopHeartbeat();
|
|
58536
58589
|
heartbeatActive = true;
|
|
58537
|
-
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
|
+
});
|
|
58538
58595
|
logger?.debug("crash-recovery", "Heartbeat started (60s interval)");
|
|
58539
58596
|
}
|
|
58540
58597
|
function stopHeartbeat() {
|
|
@@ -58543,9 +58600,13 @@ function stopHeartbeat() {
|
|
|
58543
58600
|
getSafeLogger()?.debug("crash-recovery", "Heartbeat stopped");
|
|
58544
58601
|
}
|
|
58545
58602
|
}
|
|
58546
|
-
var heartbeatActive = false;
|
|
58603
|
+
var _heartbeatDeps, heartbeatActive = false;
|
|
58547
58604
|
var init_crash_heartbeat = __esm(() => {
|
|
58548
58605
|
init_logger2();
|
|
58606
|
+
_heartbeatDeps = {
|
|
58607
|
+
sleep: async (ms) => Bun.sleep(ms),
|
|
58608
|
+
getSafeLogger
|
|
58609
|
+
};
|
|
58549
58610
|
});
|
|
58550
58611
|
|
|
58551
58612
|
// src/execution/crash-writer.ts
|
|
@@ -59348,15 +59409,15 @@ var init_acceptance_loop = __esm(() => {
|
|
|
59348
59409
|
|
|
59349
59410
|
// src/session/scratch-purge.ts
|
|
59350
59411
|
import { mkdir as mkdir13, rename, rm } from "fs/promises";
|
|
59351
|
-
import { dirname as dirname12, join as
|
|
59412
|
+
import { dirname as dirname12, join as join71 } from "path";
|
|
59352
59413
|
async function purgeStaleScratch(projectDir, featureName, retentionDays, archiveInsteadOfDelete = false) {
|
|
59353
|
-
const sessionsDir =
|
|
59414
|
+
const sessionsDir = join71(projectDir, ".nax", "features", featureName, "sessions");
|
|
59354
59415
|
const sessionIds = await _scratchPurgeDeps.listSessionDirs(sessionsDir);
|
|
59355
59416
|
const cutoffMs = _scratchPurgeDeps.now() - retentionDays * 86400000;
|
|
59356
59417
|
let purged = 0;
|
|
59357
59418
|
for (const sessionId of sessionIds) {
|
|
59358
|
-
const sessionDir =
|
|
59359
|
-
const descriptorPath =
|
|
59419
|
+
const sessionDir = join71(sessionsDir, sessionId);
|
|
59420
|
+
const descriptorPath = join71(sessionDir, "descriptor.json");
|
|
59360
59421
|
if (!await _scratchPurgeDeps.fileExists(descriptorPath))
|
|
59361
59422
|
continue;
|
|
59362
59423
|
let lastActivityAt;
|
|
@@ -59372,7 +59433,7 @@ async function purgeStaleScratch(projectDir, featureName, retentionDays, archive
|
|
|
59372
59433
|
if (new Date(lastActivityAt).getTime() >= cutoffMs)
|
|
59373
59434
|
continue;
|
|
59374
59435
|
if (archiveInsteadOfDelete) {
|
|
59375
|
-
const archiveDest =
|
|
59436
|
+
const archiveDest = join71(projectDir, ".nax", "features", featureName, "_archive", "sessions", sessionId);
|
|
59376
59437
|
await _scratchPurgeDeps.move(sessionDir, archiveDest);
|
|
59377
59438
|
} else {
|
|
59378
59439
|
await _scratchPurgeDeps.remove(sessionDir);
|
|
@@ -59595,6 +59656,13 @@ async function runDeferredRegression(options) {
|
|
|
59595
59656
|
storyOutcomes: {}
|
|
59596
59657
|
};
|
|
59597
59658
|
}
|
|
59659
|
+
for (const storyId of affectedStories) {
|
|
59660
|
+
pipelineEventBus.emit({
|
|
59661
|
+
type: "regression:detected",
|
|
59662
|
+
storyId,
|
|
59663
|
+
failedTests: testSummary.failed
|
|
59664
|
+
});
|
|
59665
|
+
}
|
|
59598
59666
|
let rectificationAttempts = 0;
|
|
59599
59667
|
let storiesRectified = 0;
|
|
59600
59668
|
let currentTestOutput = fullSuiteResult.output;
|
|
@@ -59708,6 +59776,7 @@ var init_run_regression = __esm(() => {
|
|
|
59708
59776
|
init_findings();
|
|
59709
59777
|
init_logger2();
|
|
59710
59778
|
init_operations();
|
|
59779
|
+
init_pipeline();
|
|
59711
59780
|
init_prd();
|
|
59712
59781
|
init_test_runners();
|
|
59713
59782
|
init_git();
|
|
@@ -60105,12 +60174,12 @@ var DEFAULT_MAX_BATCH_SIZE = 4;
|
|
|
60105
60174
|
|
|
60106
60175
|
// src/pipeline/subscribers/events-writer.ts
|
|
60107
60176
|
import { appendFile as appendFile4, mkdir as mkdir14 } from "fs/promises";
|
|
60108
|
-
import { basename as
|
|
60177
|
+
import { basename as basename13, join as join72 } from "path";
|
|
60109
60178
|
function wireEventsWriter(bus, feature, runId, workdir) {
|
|
60110
60179
|
const logger = getSafeLogger();
|
|
60111
|
-
const project =
|
|
60112
|
-
const eventsDir =
|
|
60113
|
-
const eventsFile =
|
|
60180
|
+
const project = basename13(workdir);
|
|
60181
|
+
const eventsDir = join72(getEventsRootDir(), project);
|
|
60182
|
+
const eventsFile = join72(eventsDir, "events.jsonl");
|
|
60114
60183
|
let dirReady = false;
|
|
60115
60184
|
const write = (line) => {
|
|
60116
60185
|
return (async () => {
|
|
@@ -60291,12 +60360,12 @@ var init_interaction2 = __esm(() => {
|
|
|
60291
60360
|
|
|
60292
60361
|
// src/pipeline/subscribers/registry.ts
|
|
60293
60362
|
import { mkdir as mkdir15, writeFile as writeFile2 } from "fs/promises";
|
|
60294
|
-
import { basename as
|
|
60363
|
+
import { basename as basename14, join as join73 } from "path";
|
|
60295
60364
|
function wireRegistry(bus, feature, runId, workdir, outputDir) {
|
|
60296
60365
|
const logger = getSafeLogger();
|
|
60297
|
-
const project =
|
|
60298
|
-
const runDir =
|
|
60299
|
-
const metaFile =
|
|
60366
|
+
const project = basename14(workdir);
|
|
60367
|
+
const runDir = join73(getRunsDir(), `${project}-${feature}-${runId}`);
|
|
60368
|
+
const metaFile = join73(runDir, "meta.json");
|
|
60300
60369
|
const unsub = bus.on("run:started", (_ev) => {
|
|
60301
60370
|
return (async () => {
|
|
60302
60371
|
try {
|
|
@@ -60306,8 +60375,8 @@ function wireRegistry(bus, feature, runId, workdir, outputDir) {
|
|
|
60306
60375
|
project,
|
|
60307
60376
|
feature,
|
|
60308
60377
|
workdir,
|
|
60309
|
-
statusPath:
|
|
60310
|
-
eventsDir:
|
|
60378
|
+
statusPath: join73(outputDir, "features", feature, "status.json"),
|
|
60379
|
+
eventsDir: join73(outputDir, "features", feature, "runs"),
|
|
60311
60380
|
registeredAt: new Date().toISOString()
|
|
60312
60381
|
};
|
|
60313
60382
|
await writeFile2(metaFile, JSON.stringify(meta3, null, 2));
|
|
@@ -60552,8 +60621,8 @@ var init_types9 = __esm(() => {
|
|
|
60552
60621
|
});
|
|
60553
60622
|
|
|
60554
60623
|
// src/worktree/dependencies.ts
|
|
60555
|
-
import { existsSync as
|
|
60556
|
-
import { join as
|
|
60624
|
+
import { existsSync as existsSync31 } from "fs";
|
|
60625
|
+
import { join as join74 } from "path";
|
|
60557
60626
|
async function prepareWorktreeDependencies(options) {
|
|
60558
60627
|
const mode = options.config.execution.worktreeDependencies.mode;
|
|
60559
60628
|
const resolvedCwd = resolveDependencyCwd(options);
|
|
@@ -60567,7 +60636,7 @@ async function prepareWorktreeDependencies(options) {
|
|
|
60567
60636
|
}
|
|
60568
60637
|
}
|
|
60569
60638
|
function resolveDependencyCwd(options) {
|
|
60570
|
-
return options.storyWorkdir ?
|
|
60639
|
+
return options.storyWorkdir ? join74(options.worktreeRoot, options.storyWorkdir) : options.worktreeRoot;
|
|
60571
60640
|
}
|
|
60572
60641
|
function resolveInheritedDependencies(options, resolvedCwd) {
|
|
60573
60642
|
if (hasDependencyManifests(options.worktreeRoot, resolvedCwd)) {
|
|
@@ -60577,7 +60646,7 @@ function resolveInheritedDependencies(options, resolvedCwd) {
|
|
|
60577
60646
|
}
|
|
60578
60647
|
function hasDependencyManifests(worktreeRoot, resolvedCwd) {
|
|
60579
60648
|
const directories = resolvedCwd === worktreeRoot ? [worktreeRoot] : [worktreeRoot, resolvedCwd];
|
|
60580
|
-
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))));
|
|
60581
60650
|
}
|
|
60582
60651
|
async function provisionDependencies(config2, worktreeRoot, resolvedCwd) {
|
|
60583
60652
|
const setupCommand = config2.execution.worktreeDependencies.setupCommand;
|
|
@@ -60628,7 +60697,7 @@ var init_dependencies = __esm(() => {
|
|
|
60628
60697
|
"build.gradle.kts"
|
|
60629
60698
|
];
|
|
60630
60699
|
_worktreeDependencyDeps = {
|
|
60631
|
-
existsSync:
|
|
60700
|
+
existsSync: existsSync31,
|
|
60632
60701
|
spawn
|
|
60633
60702
|
};
|
|
60634
60703
|
});
|
|
@@ -60639,19 +60708,19 @@ __export(exports_manager, {
|
|
|
60639
60708
|
_managerDeps: () => _managerDeps,
|
|
60640
60709
|
WorktreeManager: () => WorktreeManager
|
|
60641
60710
|
});
|
|
60642
|
-
import { existsSync as
|
|
60711
|
+
import { existsSync as existsSync32, symlinkSync } from "fs";
|
|
60643
60712
|
import { mkdir as mkdir16 } from "fs/promises";
|
|
60644
|
-
import { join as
|
|
60713
|
+
import { join as join75 } from "path";
|
|
60645
60714
|
|
|
60646
60715
|
class WorktreeManager {
|
|
60647
60716
|
async ensureGitExcludes(projectRoot) {
|
|
60648
60717
|
const logger = getSafeLogger();
|
|
60649
|
-
const infoDir =
|
|
60650
|
-
const excludePath =
|
|
60718
|
+
const infoDir = join75(projectRoot, ".git", "info");
|
|
60719
|
+
const excludePath = join75(infoDir, "exclude");
|
|
60651
60720
|
try {
|
|
60652
60721
|
await mkdir16(infoDir, { recursive: true });
|
|
60653
60722
|
let existing = "";
|
|
60654
|
-
if (
|
|
60723
|
+
if (existsSync32(excludePath)) {
|
|
60655
60724
|
existing = await Bun.file(excludePath).text();
|
|
60656
60725
|
}
|
|
60657
60726
|
const missing = NAX_GITIGNORE_ENTRIES.filter((entry) => !existing.includes(entry));
|
|
@@ -60674,7 +60743,7 @@ ${missing.join(`
|
|
|
60674
60743
|
}
|
|
60675
60744
|
async create(projectRoot, storyId) {
|
|
60676
60745
|
validateStoryId(storyId);
|
|
60677
|
-
const worktreePath =
|
|
60746
|
+
const worktreePath = join75(projectRoot, ".nax-wt", storyId);
|
|
60678
60747
|
const branchName = `nax/${storyId}`;
|
|
60679
60748
|
try {
|
|
60680
60749
|
const pruneProc = _managerDeps.spawn(["git", "worktree", "prune"], {
|
|
@@ -60715,9 +60784,9 @@ ${missing.join(`
|
|
|
60715
60784
|
}
|
|
60716
60785
|
throw new Error(`Failed to create worktree: ${String(error48)}`);
|
|
60717
60786
|
}
|
|
60718
|
-
const envSource =
|
|
60719
|
-
if (
|
|
60720
|
-
const envTarget =
|
|
60787
|
+
const envSource = join75(projectRoot, ".env");
|
|
60788
|
+
if (existsSync32(envSource)) {
|
|
60789
|
+
const envTarget = join75(worktreePath, ".env");
|
|
60721
60790
|
try {
|
|
60722
60791
|
symlinkSync(envSource, envTarget, "file");
|
|
60723
60792
|
} catch (error48) {
|
|
@@ -60728,7 +60797,7 @@ ${missing.join(`
|
|
|
60728
60797
|
}
|
|
60729
60798
|
async remove(projectRoot, storyId) {
|
|
60730
60799
|
validateStoryId(storyId);
|
|
60731
|
-
const worktreePath =
|
|
60800
|
+
const worktreePath = join75(projectRoot, ".nax-wt", storyId);
|
|
60732
60801
|
const branchName = `nax/${storyId}`;
|
|
60733
60802
|
try {
|
|
60734
60803
|
const proc = _managerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
|
|
@@ -61406,6 +61475,12 @@ async function handleTierEscalation(ctx) {
|
|
|
61406
61475
|
runtime: ctx.runtime
|
|
61407
61476
|
});
|
|
61408
61477
|
}
|
|
61478
|
+
pipelineEventBus.emit({
|
|
61479
|
+
type: "story:escalated",
|
|
61480
|
+
storyId: ctx.story.id,
|
|
61481
|
+
fromTier: ctx.routing.modelTier,
|
|
61482
|
+
toTier: escalatedTier
|
|
61483
|
+
});
|
|
61409
61484
|
return {
|
|
61410
61485
|
outcome: "escalated",
|
|
61411
61486
|
prdDirty: true,
|
|
@@ -61416,6 +61491,7 @@ var _tierEscalationDeps;
|
|
|
61416
61491
|
var init_tier_escalation = __esm(() => {
|
|
61417
61492
|
init_hooks();
|
|
61418
61493
|
init_logger2();
|
|
61494
|
+
init_event_bus();
|
|
61419
61495
|
init_prd();
|
|
61420
61496
|
init_routing();
|
|
61421
61497
|
init_llm();
|
|
@@ -61531,10 +61607,10 @@ var init_merge_conflict_rectify = __esm(() => {
|
|
|
61531
61607
|
});
|
|
61532
61608
|
|
|
61533
61609
|
// src/execution/pipeline-result-handler.ts
|
|
61534
|
-
import { join as
|
|
61610
|
+
import { join as join76 } from "path";
|
|
61535
61611
|
async function removeWorktreeDirectory(projectRoot, storyId) {
|
|
61536
61612
|
const logger = getSafeLogger();
|
|
61537
|
-
const worktreePath =
|
|
61613
|
+
const worktreePath = join76(projectRoot, ".nax-wt", storyId);
|
|
61538
61614
|
try {
|
|
61539
61615
|
const proc = _resultHandlerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
|
|
61540
61616
|
cwd: projectRoot,
|
|
@@ -61664,6 +61740,11 @@ async function handlePipelineFailure(ctx, pipelineResult) {
|
|
|
61664
61740
|
break;
|
|
61665
61741
|
case "skip":
|
|
61666
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
|
+
});
|
|
61667
61748
|
prdDirty = true;
|
|
61668
61749
|
break;
|
|
61669
61750
|
case "fail":
|
|
@@ -61744,8 +61825,8 @@ var init_pipeline_result_handler = __esm(() => {
|
|
|
61744
61825
|
});
|
|
61745
61826
|
|
|
61746
61827
|
// src/execution/iteration-runner.ts
|
|
61747
|
-
import { existsSync as
|
|
61748
|
-
import { join as
|
|
61828
|
+
import { existsSync as existsSync33 } from "fs";
|
|
61829
|
+
import { join as join77 } from "path";
|
|
61749
61830
|
async function runIteration(ctx, prd, selection, iterations, totalCost, allStoryMetrics) {
|
|
61750
61831
|
const { story, storiesToExecute, routing, isBatchExecution } = selection;
|
|
61751
61832
|
if (ctx.dryRun) {
|
|
@@ -61770,7 +61851,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
61770
61851
|
const storyStartTime = Date.now();
|
|
61771
61852
|
let effectiveWorkdir = ctx.workdir;
|
|
61772
61853
|
if (ctx.config.execution.storyIsolation === "worktree") {
|
|
61773
|
-
const worktreePath =
|
|
61854
|
+
const worktreePath = join77(ctx.workdir, ".nax-wt", story.id);
|
|
61774
61855
|
const worktreeExists = _iterationRunnerDeps.existsSync(worktreePath);
|
|
61775
61856
|
if (!worktreeExists) {
|
|
61776
61857
|
await _iterationRunnerDeps.worktreeManager.ensureGitExcludes(ctx.workdir);
|
|
@@ -61790,7 +61871,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
61790
61871
|
}
|
|
61791
61872
|
const accumulatedAttemptCost = (story.priorFailures || []).reduce((sum, f) => sum + (f.cost || 0), 0);
|
|
61792
61873
|
const profileOverride = ctx.config.profile && ctx.config.profile !== "default" ? { profile: ctx.config.profile } : undefined;
|
|
61793
|
-
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;
|
|
61794
61875
|
let dependencyContext;
|
|
61795
61876
|
if (ctx.config.execution.storyIsolation === "worktree") {
|
|
61796
61877
|
try {
|
|
@@ -61817,7 +61898,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
61817
61898
|
};
|
|
61818
61899
|
}
|
|
61819
61900
|
}
|
|
61820
|
-
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;
|
|
61821
61902
|
const pipelineContext = {
|
|
61822
61903
|
config: effectiveConfig,
|
|
61823
61904
|
rootConfig: ctx.config,
|
|
@@ -61949,7 +62030,7 @@ var init_iteration_runner = __esm(() => {
|
|
|
61949
62030
|
loadConfigForWorkdir,
|
|
61950
62031
|
prepareWorktreeDependencies,
|
|
61951
62032
|
runPipeline,
|
|
61952
|
-
existsSync:
|
|
62033
|
+
existsSync: existsSync33,
|
|
61953
62034
|
worktreeManager: new WorktreeManager
|
|
61954
62035
|
};
|
|
61955
62036
|
});
|
|
@@ -61960,7 +62041,7 @@ function selectNextStories(prd, config2, batchPlan, currentBatchIndex, lastStory
|
|
|
61960
62041
|
const batch = batchPlan[currentBatchIndex];
|
|
61961
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");
|
|
61962
62043
|
if (storiesToExecute.length === 0) {
|
|
61963
|
-
return
|
|
62044
|
+
return null;
|
|
61964
62045
|
}
|
|
61965
62046
|
const story2 = storiesToExecute[0];
|
|
61966
62047
|
return {
|
|
@@ -62019,7 +62100,7 @@ __export(exports_parallel_worker, {
|
|
|
62019
62100
|
buildWorktreePipelineContext: () => buildWorktreePipelineContext,
|
|
62020
62101
|
_parallelWorkerDeps: () => _parallelWorkerDeps
|
|
62021
62102
|
});
|
|
62022
|
-
import { join as
|
|
62103
|
+
import { join as join78 } from "path";
|
|
62023
62104
|
function buildWorktreePipelineContext(base, _story) {
|
|
62024
62105
|
return { ...base, prd: structuredClone(base.prd) };
|
|
62025
62106
|
}
|
|
@@ -62042,7 +62123,7 @@ async function executeStoryInWorktree(story, worktreePath, dependencyContext, co
|
|
|
62042
62123
|
story,
|
|
62043
62124
|
stories: [story],
|
|
62044
62125
|
projectDir: context.projectDir,
|
|
62045
|
-
workdir: dependencyContext.cwd ?? (story.workdir ?
|
|
62126
|
+
workdir: dependencyContext.cwd ?? (story.workdir ? join78(worktreePath, story.workdir) : worktreePath),
|
|
62046
62127
|
worktreeDependencyContext: dependencyContext,
|
|
62047
62128
|
routing,
|
|
62048
62129
|
storyGitRef: storyGitRef ?? undefined
|
|
@@ -62167,10 +62248,27 @@ async function runParallelBatch(options) {
|
|
|
62167
62248
|
const rootConfigPath = path21.join(workdir, ".nax", "config.json");
|
|
62168
62249
|
const profileOverride = config2.profile && config2.profile !== "default" ? { profile: config2.profile } : undefined;
|
|
62169
62250
|
const storyEffectiveConfigs = new Map;
|
|
62170
|
-
await Promise.
|
|
62171
|
-
|
|
62172
|
-
|
|
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
|
+
}
|
|
62173
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
|
+
}
|
|
62174
62272
|
const dependencyContexts = new Map;
|
|
62175
62273
|
const readyStories = [];
|
|
62176
62274
|
const preExecutionFailures = [];
|
|
@@ -62329,7 +62427,8 @@ var init_parallel_batch = __esm(() => {
|
|
|
62329
62427
|
const { rectifyConflictedStory: rectifyConflictedStory2 } = await Promise.resolve().then(() => (init_merge_conflict_rectify(), exports_merge_conflict_rectify));
|
|
62330
62428
|
return rectifyConflictedStory2(opts);
|
|
62331
62429
|
},
|
|
62332
|
-
prepareWorktreeDependencies
|
|
62430
|
+
prepareWorktreeDependencies,
|
|
62431
|
+
loadConfigForWorkdir
|
|
62333
62432
|
};
|
|
62334
62433
|
});
|
|
62335
62434
|
|
|
@@ -62697,6 +62796,8 @@ async function executeUnified(ctx, initialPrd) {
|
|
|
62697
62796
|
if (!selected)
|
|
62698
62797
|
return buildResult2("no-stories");
|
|
62699
62798
|
const { selection } = selected;
|
|
62799
|
+
if (!selection)
|
|
62800
|
+
return buildResult2("no-stories");
|
|
62700
62801
|
if (!ctx.useBatch)
|
|
62701
62802
|
lastStoryId = selection.story.id;
|
|
62702
62803
|
{
|
|
@@ -62903,7 +63004,7 @@ async function writeStatusFile(filePath, status) {
|
|
|
62903
63004
|
var init_status_file = () => {};
|
|
62904
63005
|
|
|
62905
63006
|
// src/execution/status-writer.ts
|
|
62906
|
-
import { join as
|
|
63007
|
+
import { join as join79 } from "path";
|
|
62907
63008
|
|
|
62908
63009
|
class StatusWriter {
|
|
62909
63010
|
statusFile;
|
|
@@ -63022,7 +63123,7 @@ class StatusWriter {
|
|
|
63022
63123
|
if (!this._prd)
|
|
63023
63124
|
return;
|
|
63024
63125
|
const safeLogger = getSafeLogger();
|
|
63025
|
-
const featureStatusPath =
|
|
63126
|
+
const featureStatusPath = join79(featureDir, "status.json");
|
|
63026
63127
|
const write = async () => {
|
|
63027
63128
|
try {
|
|
63028
63129
|
const base = this.getSnapshot(totalCost, iterations);
|
|
@@ -63053,11 +63154,11 @@ __export(exports_migrate, {
|
|
|
63053
63154
|
migrateCommand: () => migrateCommand,
|
|
63054
63155
|
detectGeneratedContent: () => detectGeneratedContent
|
|
63055
63156
|
});
|
|
63056
|
-
import { existsSync as
|
|
63157
|
+
import { existsSync as existsSync34 } from "fs";
|
|
63057
63158
|
import { mkdir as mkdir17, readdir as readdir6, rename as rename3 } from "fs/promises";
|
|
63058
63159
|
import path22 from "path";
|
|
63059
63160
|
async function detectGeneratedContent(naxDir) {
|
|
63060
|
-
if (!
|
|
63161
|
+
if (!existsSync34(naxDir))
|
|
63061
63162
|
return [];
|
|
63062
63163
|
const candidates = [];
|
|
63063
63164
|
let entries = [];
|
|
@@ -63072,7 +63173,7 @@ async function detectGeneratedContent(naxDir) {
|
|
|
63072
63173
|
}
|
|
63073
63174
|
}
|
|
63074
63175
|
const featuresDir = path22.join(naxDir, "features");
|
|
63075
|
-
if (
|
|
63176
|
+
if (existsSync34(featuresDir)) {
|
|
63076
63177
|
let featureDirs = [];
|
|
63077
63178
|
try {
|
|
63078
63179
|
featureDirs = await readdir6(featuresDir);
|
|
@@ -63134,7 +63235,7 @@ async function migrateCommand(options) {
|
|
|
63134
63235
|
});
|
|
63135
63236
|
}
|
|
63136
63237
|
const src = path22.join(globalConfigDir(), options.reclaim);
|
|
63137
|
-
if (!
|
|
63238
|
+
if (!existsSync34(src)) {
|
|
63138
63239
|
throw new NaxError(`Nothing to reclaim: ~/.nax/${options.reclaim} does not exist`, "MIGRATE_RECLAIM_NOT_FOUND", {
|
|
63139
63240
|
stage: "migrate",
|
|
63140
63241
|
name: options.reclaim
|
|
@@ -63180,7 +63281,7 @@ async function migrateCommand(options) {
|
|
|
63180
63281
|
}
|
|
63181
63282
|
const naxDir = path22.join(options.workdir, ".nax");
|
|
63182
63283
|
const configPath = path22.join(naxDir, "config.json");
|
|
63183
|
-
if (!
|
|
63284
|
+
if (!existsSync34(configPath)) {
|
|
63184
63285
|
throw new NaxError("No .nax/config.json found \u2014 run nax init first", "MIGRATE_NO_CONFIG", {
|
|
63185
63286
|
stage: "migrate",
|
|
63186
63287
|
workdir: options.workdir
|
|
@@ -63215,7 +63316,7 @@ async function migrateCommand(options) {
|
|
|
63215
63316
|
for (const candidate of candidates) {
|
|
63216
63317
|
const dest = path22.join(destBase, candidate.name);
|
|
63217
63318
|
await mkdir17(path22.dirname(dest), { recursive: true });
|
|
63218
|
-
if (
|
|
63319
|
+
if (existsSync34(dest)) {
|
|
63219
63320
|
throw new NaxError(`Migration conflict: destination already exists.
|
|
63220
63321
|
Source: ${candidate.srcPath}
|
|
63221
63322
|
Destination: ${dest}
|
|
@@ -63456,7 +63557,7 @@ __export(exports_run_initialization, {
|
|
|
63456
63557
|
initializeRun: () => initializeRun,
|
|
63457
63558
|
_reconcileDeps: () => _reconcileDeps
|
|
63458
63559
|
});
|
|
63459
|
-
import { join as
|
|
63560
|
+
import { join as join80 } from "path";
|
|
63460
63561
|
async function reconcileState(prd, prdPath, workdir, config2) {
|
|
63461
63562
|
const logger = getSafeLogger();
|
|
63462
63563
|
let reconciledCount = 0;
|
|
@@ -63473,7 +63574,7 @@ async function reconcileState(prd, prdPath, workdir, config2) {
|
|
|
63473
63574
|
});
|
|
63474
63575
|
continue;
|
|
63475
63576
|
}
|
|
63476
|
-
const effectiveWorkdir = story.workdir ?
|
|
63577
|
+
const effectiveWorkdir = story.workdir ? join80(workdir, story.workdir) : workdir;
|
|
63477
63578
|
try {
|
|
63478
63579
|
const reviewResult = await _reconcileDeps.runReview(config2.review, effectiveWorkdir, config2.execution);
|
|
63479
63580
|
if (!reviewResult.success) {
|
|
@@ -93031,6 +93132,229 @@ var require_stack_utils = __commonJS((exports, module) => {
|
|
|
93031
93132
|
module.exports = StackUtils;
|
|
93032
93133
|
});
|
|
93033
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
|
+
|
|
93034
93358
|
// node_modules/cli-spinners/spinners.json
|
|
93035
93359
|
var require_spinners = __commonJS((exports, module) => {
|
|
93036
93360
|
module.exports = {
|
|
@@ -94671,229 +94995,6 @@ var require_cli_spinners = __commonJS((exports, module) => {
|
|
|
94671
94995
|
module.exports = spinners;
|
|
94672
94996
|
});
|
|
94673
94997
|
|
|
94674
|
-
// node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
94675
|
-
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
94676
|
-
var React12 = __toESM(require_react());
|
|
94677
|
-
(function() {
|
|
94678
|
-
function getComponentNameFromType(type) {
|
|
94679
|
-
if (type == null)
|
|
94680
|
-
return null;
|
|
94681
|
-
if (typeof type === "function")
|
|
94682
|
-
return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
|
94683
|
-
if (typeof type === "string")
|
|
94684
|
-
return type;
|
|
94685
|
-
switch (type) {
|
|
94686
|
-
case REACT_FRAGMENT_TYPE:
|
|
94687
|
-
return "Fragment";
|
|
94688
|
-
case REACT_PROFILER_TYPE:
|
|
94689
|
-
return "Profiler";
|
|
94690
|
-
case REACT_STRICT_MODE_TYPE:
|
|
94691
|
-
return "StrictMode";
|
|
94692
|
-
case REACT_SUSPENSE_TYPE:
|
|
94693
|
-
return "Suspense";
|
|
94694
|
-
case REACT_SUSPENSE_LIST_TYPE:
|
|
94695
|
-
return "SuspenseList";
|
|
94696
|
-
case REACT_ACTIVITY_TYPE:
|
|
94697
|
-
return "Activity";
|
|
94698
|
-
}
|
|
94699
|
-
if (typeof type === "object")
|
|
94700
|
-
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) {
|
|
94701
|
-
case REACT_PORTAL_TYPE:
|
|
94702
|
-
return "Portal";
|
|
94703
|
-
case REACT_CONTEXT_TYPE:
|
|
94704
|
-
return type.displayName || "Context";
|
|
94705
|
-
case REACT_CONSUMER_TYPE:
|
|
94706
|
-
return (type._context.displayName || "Context") + ".Consumer";
|
|
94707
|
-
case REACT_FORWARD_REF_TYPE:
|
|
94708
|
-
var innerType = type.render;
|
|
94709
|
-
type = type.displayName;
|
|
94710
|
-
type || (type = innerType.displayName || innerType.name || "", type = type !== "" ? "ForwardRef(" + type + ")" : "ForwardRef");
|
|
94711
|
-
return type;
|
|
94712
|
-
case REACT_MEMO_TYPE:
|
|
94713
|
-
return innerType = type.displayName || null, innerType !== null ? innerType : getComponentNameFromType(type.type) || "Memo";
|
|
94714
|
-
case REACT_LAZY_TYPE:
|
|
94715
|
-
innerType = type._payload;
|
|
94716
|
-
type = type._init;
|
|
94717
|
-
try {
|
|
94718
|
-
return getComponentNameFromType(type(innerType));
|
|
94719
|
-
} catch (x) {}
|
|
94720
|
-
}
|
|
94721
|
-
return null;
|
|
94722
|
-
}
|
|
94723
|
-
function testStringCoercion(value) {
|
|
94724
|
-
return "" + value;
|
|
94725
|
-
}
|
|
94726
|
-
function checkKeyStringCoercion(value) {
|
|
94727
|
-
try {
|
|
94728
|
-
testStringCoercion(value);
|
|
94729
|
-
var JSCompiler_inline_result = false;
|
|
94730
|
-
} catch (e) {
|
|
94731
|
-
JSCompiler_inline_result = true;
|
|
94732
|
-
}
|
|
94733
|
-
if (JSCompiler_inline_result) {
|
|
94734
|
-
JSCompiler_inline_result = console;
|
|
94735
|
-
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
|
94736
|
-
var JSCompiler_inline_result$jscomp$0 = typeof Symbol === "function" && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
|
94737
|
-
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);
|
|
94738
|
-
return testStringCoercion(value);
|
|
94739
|
-
}
|
|
94740
|
-
}
|
|
94741
|
-
function getTaskName(type) {
|
|
94742
|
-
if (type === REACT_FRAGMENT_TYPE)
|
|
94743
|
-
return "<>";
|
|
94744
|
-
if (typeof type === "object" && type !== null && type.$$typeof === REACT_LAZY_TYPE)
|
|
94745
|
-
return "<...>";
|
|
94746
|
-
try {
|
|
94747
|
-
var name = getComponentNameFromType(type);
|
|
94748
|
-
return name ? "<" + name + ">" : "<...>";
|
|
94749
|
-
} catch (x) {
|
|
94750
|
-
return "<...>";
|
|
94751
|
-
}
|
|
94752
|
-
}
|
|
94753
|
-
function getOwner() {
|
|
94754
|
-
var dispatcher = ReactSharedInternals.A;
|
|
94755
|
-
return dispatcher === null ? null : dispatcher.getOwner();
|
|
94756
|
-
}
|
|
94757
|
-
function UnknownOwner() {
|
|
94758
|
-
return Error("react-stack-top-frame");
|
|
94759
|
-
}
|
|
94760
|
-
function hasValidKey(config2) {
|
|
94761
|
-
if (hasOwnProperty.call(config2, "key")) {
|
|
94762
|
-
var getter = Object.getOwnPropertyDescriptor(config2, "key").get;
|
|
94763
|
-
if (getter && getter.isReactWarning)
|
|
94764
|
-
return false;
|
|
94765
|
-
}
|
|
94766
|
-
return config2.key !== undefined;
|
|
94767
|
-
}
|
|
94768
|
-
function defineKeyPropWarningGetter(props, displayName) {
|
|
94769
|
-
function warnAboutAccessingKey() {
|
|
94770
|
-
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));
|
|
94771
|
-
}
|
|
94772
|
-
warnAboutAccessingKey.isReactWarning = true;
|
|
94773
|
-
Object.defineProperty(props, "key", {
|
|
94774
|
-
get: warnAboutAccessingKey,
|
|
94775
|
-
configurable: true
|
|
94776
|
-
});
|
|
94777
|
-
}
|
|
94778
|
-
function elementRefGetterWithDeprecationWarning() {
|
|
94779
|
-
var componentName = getComponentNameFromType(this.type);
|
|
94780
|
-
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."));
|
|
94781
|
-
componentName = this.props.ref;
|
|
94782
|
-
return componentName !== undefined ? componentName : null;
|
|
94783
|
-
}
|
|
94784
|
-
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
|
94785
|
-
var refProp = props.ref;
|
|
94786
|
-
type = {
|
|
94787
|
-
$$typeof: REACT_ELEMENT_TYPE,
|
|
94788
|
-
type,
|
|
94789
|
-
key,
|
|
94790
|
-
props,
|
|
94791
|
-
_owner: owner
|
|
94792
|
-
};
|
|
94793
|
-
(refProp !== undefined ? refProp : null) !== null ? Object.defineProperty(type, "ref", {
|
|
94794
|
-
enumerable: false,
|
|
94795
|
-
get: elementRefGetterWithDeprecationWarning
|
|
94796
|
-
}) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
|
|
94797
|
-
type._store = {};
|
|
94798
|
-
Object.defineProperty(type._store, "validated", {
|
|
94799
|
-
configurable: false,
|
|
94800
|
-
enumerable: false,
|
|
94801
|
-
writable: true,
|
|
94802
|
-
value: 0
|
|
94803
|
-
});
|
|
94804
|
-
Object.defineProperty(type, "_debugInfo", {
|
|
94805
|
-
configurable: false,
|
|
94806
|
-
enumerable: false,
|
|
94807
|
-
writable: true,
|
|
94808
|
-
value: null
|
|
94809
|
-
});
|
|
94810
|
-
Object.defineProperty(type, "_debugStack", {
|
|
94811
|
-
configurable: false,
|
|
94812
|
-
enumerable: false,
|
|
94813
|
-
writable: true,
|
|
94814
|
-
value: debugStack
|
|
94815
|
-
});
|
|
94816
|
-
Object.defineProperty(type, "_debugTask", {
|
|
94817
|
-
configurable: false,
|
|
94818
|
-
enumerable: false,
|
|
94819
|
-
writable: true,
|
|
94820
|
-
value: debugTask
|
|
94821
|
-
});
|
|
94822
|
-
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
|
94823
|
-
return type;
|
|
94824
|
-
}
|
|
94825
|
-
function jsxDEVImpl(type, config2, maybeKey, isStaticChildren, debugStack, debugTask) {
|
|
94826
|
-
var children = config2.children;
|
|
94827
|
-
if (children !== undefined)
|
|
94828
|
-
if (isStaticChildren)
|
|
94829
|
-
if (isArrayImpl(children)) {
|
|
94830
|
-
for (isStaticChildren = 0;isStaticChildren < children.length; isStaticChildren++)
|
|
94831
|
-
validateChildKeys(children[isStaticChildren]);
|
|
94832
|
-
Object.freeze && Object.freeze(children);
|
|
94833
|
-
} else
|
|
94834
|
-
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.");
|
|
94835
|
-
else
|
|
94836
|
-
validateChildKeys(children);
|
|
94837
|
-
if (hasOwnProperty.call(config2, "key")) {
|
|
94838
|
-
children = getComponentNameFromType(type);
|
|
94839
|
-
var keys2 = Object.keys(config2).filter(function(k) {
|
|
94840
|
-
return k !== "key";
|
|
94841
|
-
});
|
|
94842
|
-
isStaticChildren = 0 < keys2.length ? "{key: someKey, " + keys2.join(": ..., ") + ": ...}" : "{key: someKey}";
|
|
94843
|
-
didWarnAboutKeySpread[children + isStaticChildren] || (keys2 = 0 < keys2.length ? "{" + keys2.join(": ..., ") + ": ...}" : "{}", console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
94844
|
-
let props = %s;
|
|
94845
|
-
<%s {...props} />
|
|
94846
|
-
React keys must be passed directly to JSX without using spread:
|
|
94847
|
-
let props = %s;
|
|
94848
|
-
<%s key={someKey} {...props} />`, isStaticChildren, children, keys2, children), didWarnAboutKeySpread[children + isStaticChildren] = true);
|
|
94849
|
-
}
|
|
94850
|
-
children = null;
|
|
94851
|
-
maybeKey !== undefined && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
|
94852
|
-
hasValidKey(config2) && (checkKeyStringCoercion(config2.key), children = "" + config2.key);
|
|
94853
|
-
if ("key" in config2) {
|
|
94854
|
-
maybeKey = {};
|
|
94855
|
-
for (var propName in config2)
|
|
94856
|
-
propName !== "key" && (maybeKey[propName] = config2[propName]);
|
|
94857
|
-
} else
|
|
94858
|
-
maybeKey = config2;
|
|
94859
|
-
children && defineKeyPropWarningGetter(maybeKey, typeof type === "function" ? type.displayName || type.name || "Unknown" : type);
|
|
94860
|
-
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
|
94861
|
-
}
|
|
94862
|
-
function validateChildKeys(node) {
|
|
94863
|
-
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));
|
|
94864
|
-
}
|
|
94865
|
-
function isValidElement(object2) {
|
|
94866
|
-
return typeof object2 === "object" && object2 !== null && object2.$$typeof === REACT_ELEMENT_TYPE;
|
|
94867
|
-
}
|
|
94868
|
-
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() {
|
|
94869
|
-
return null;
|
|
94870
|
-
};
|
|
94871
|
-
React12 = {
|
|
94872
|
-
react_stack_bottom_frame: function(callStackForError) {
|
|
94873
|
-
return callStackForError();
|
|
94874
|
-
}
|
|
94875
|
-
};
|
|
94876
|
-
var specialPropKeyWarningShown;
|
|
94877
|
-
var didWarnAboutElementRef = {};
|
|
94878
|
-
var unknownOwnerDebugStack = React12.react_stack_bottom_frame.bind(React12, UnknownOwner)();
|
|
94879
|
-
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
94880
|
-
var didWarnAboutKeySpread = {};
|
|
94881
|
-
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
94882
|
-
exports.jsxDEV = function(type, config2, maybeKey, isStaticChildren) {
|
|
94883
|
-
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
94884
|
-
return jsxDEVImpl(type, config2, maybeKey, isStaticChildren, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
94885
|
-
};
|
|
94886
|
-
})();
|
|
94887
|
-
});
|
|
94888
|
-
|
|
94889
|
-
// node_modules/react/jsx-dev-runtime.js
|
|
94890
|
-
var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
94891
|
-
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
|
|
94892
|
-
if (false) {} else {
|
|
94893
|
-
module.exports = react_jsx_dev_runtime_development;
|
|
94894
|
-
}
|
|
94895
|
-
});
|
|
94896
|
-
|
|
94897
94998
|
// src/commands/curator.ts
|
|
94898
94999
|
var exports_curator = {};
|
|
94899
95000
|
__export(exports_curator, {
|
|
@@ -94903,15 +95004,15 @@ __export(exports_curator, {
|
|
|
94903
95004
|
curatorCommit: () => curatorCommit,
|
|
94904
95005
|
_curatorCmdDeps: () => _curatorCmdDeps
|
|
94905
95006
|
});
|
|
94906
|
-
import { readdirSync as
|
|
95007
|
+
import { readdirSync as readdirSync8 } from "fs";
|
|
94907
95008
|
import { unlink as unlink4 } from "fs/promises";
|
|
94908
|
-
import { basename as
|
|
95009
|
+
import { basename as basename15, join as join82 } from "path";
|
|
94909
95010
|
function getProjectKey(config2, projectDir) {
|
|
94910
|
-
return config2.name?.trim() ||
|
|
95011
|
+
return config2.name?.trim() || basename15(projectDir);
|
|
94911
95012
|
}
|
|
94912
95013
|
function listRunIds(runsDir) {
|
|
94913
95014
|
try {
|
|
94914
|
-
return
|
|
95015
|
+
return readdirSync8(runsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
94915
95016
|
} catch {
|
|
94916
95017
|
return [];
|
|
94917
95018
|
}
|
|
@@ -94988,7 +95089,7 @@ async function curatorStatus(options) {
|
|
|
94988
95089
|
const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
|
|
94989
95090
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
94990
95091
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
94991
|
-
const runsDir =
|
|
95092
|
+
const runsDir = join82(outputDir, "runs");
|
|
94992
95093
|
const runIds = listRunIds(runsDir);
|
|
94993
95094
|
let runId;
|
|
94994
95095
|
if (options.run) {
|
|
@@ -95005,8 +95106,8 @@ async function curatorStatus(options) {
|
|
|
95005
95106
|
runId = runIds[runIds.length - 1];
|
|
95006
95107
|
}
|
|
95007
95108
|
console.log(`Run: ${runId}`);
|
|
95008
|
-
const runDir =
|
|
95009
|
-
const observationsPath =
|
|
95109
|
+
const runDir = join82(runsDir, runId);
|
|
95110
|
+
const observationsPath = join82(runDir, "observations.jsonl");
|
|
95010
95111
|
const observations = await parseObservations(observationsPath);
|
|
95011
95112
|
const counts = new Map;
|
|
95012
95113
|
for (const obs of observations) {
|
|
@@ -95016,7 +95117,7 @@ async function curatorStatus(options) {
|
|
|
95016
95117
|
for (const [kind, count] of counts.entries()) {
|
|
95017
95118
|
console.log(` ${kind}: ${count}`);
|
|
95018
95119
|
}
|
|
95019
|
-
const proposalsPath =
|
|
95120
|
+
const proposalsPath = join82(runDir, "curator-proposals.md");
|
|
95020
95121
|
const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
|
|
95021
95122
|
if (proposalText !== null) {
|
|
95022
95123
|
console.log("");
|
|
@@ -95030,8 +95131,8 @@ async function curatorCommit(options) {
|
|
|
95030
95131
|
const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
|
|
95031
95132
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95032
95133
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95033
|
-
const runDir =
|
|
95034
|
-
const proposalsPath =
|
|
95134
|
+
const runDir = join82(outputDir, "runs", options.runId);
|
|
95135
|
+
const proposalsPath = join82(runDir, "curator-proposals.md");
|
|
95035
95136
|
const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
|
|
95036
95137
|
if (proposalText === null) {
|
|
95037
95138
|
console.log(`curator-proposals.md not found for run ${options.runId}.`);
|
|
@@ -95047,7 +95148,7 @@ async function curatorCommit(options) {
|
|
|
95047
95148
|
const dropFileState = new Map;
|
|
95048
95149
|
const skippedDrops = new Set;
|
|
95049
95150
|
for (const drop2 of drops) {
|
|
95050
|
-
const targetPath =
|
|
95151
|
+
const targetPath = join82(resolved.projectDir, drop2.canonicalFile);
|
|
95051
95152
|
if (!dropFileState.has(targetPath)) {
|
|
95052
95153
|
const fileExists2 = await Bun.file(targetPath).exists();
|
|
95053
95154
|
const existing = fileExists2 ? await _curatorCmdDeps.readFile(targetPath).catch(() => "") : "";
|
|
@@ -95081,7 +95182,7 @@ async function curatorCommit(options) {
|
|
|
95081
95182
|
if (skippedDrops.has(drop2)) {
|
|
95082
95183
|
continue;
|
|
95083
95184
|
}
|
|
95084
|
-
const targetPath =
|
|
95185
|
+
const targetPath = join82(resolved.projectDir, drop2.canonicalFile);
|
|
95085
95186
|
const existing = await _curatorCmdDeps.readFile(targetPath).catch(() => "");
|
|
95086
95187
|
const filtered = filterDropContent(existing, drop2.description);
|
|
95087
95188
|
await _curatorCmdDeps.writeFile(targetPath, filtered);
|
|
@@ -95090,7 +95191,7 @@ async function curatorCommit(options) {
|
|
|
95090
95191
|
}
|
|
95091
95192
|
const adds = proposals.filter((p) => p.action === "add" || p.action === "advisory");
|
|
95092
95193
|
for (const add2 of adds) {
|
|
95093
|
-
const targetPath =
|
|
95194
|
+
const targetPath = join82(resolved.projectDir, add2.canonicalFile);
|
|
95094
95195
|
const content = buildAddContent(add2);
|
|
95095
95196
|
await _curatorCmdDeps.appendFile(targetPath, content);
|
|
95096
95197
|
modifiedFiles.add(targetPath);
|
|
@@ -95127,7 +95228,7 @@ async function curatorDryrun(options) {
|
|
|
95127
95228
|
const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
|
|
95128
95229
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95129
95230
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95130
|
-
const runsDir =
|
|
95231
|
+
const runsDir = join82(outputDir, "runs");
|
|
95131
95232
|
const runIds = listRunIds(runsDir);
|
|
95132
95233
|
if (runIds.length === 0) {
|
|
95133
95234
|
console.log("No runs found.");
|
|
@@ -95138,7 +95239,7 @@ async function curatorDryrun(options) {
|
|
|
95138
95239
|
console.log(`Run ${options.run} not found in ${runsDir}.`);
|
|
95139
95240
|
return;
|
|
95140
95241
|
}
|
|
95141
|
-
const observationsPath =
|
|
95242
|
+
const observationsPath = join82(runsDir, runId, "observations.jsonl");
|
|
95142
95243
|
const observations = await parseObservations(observationsPath);
|
|
95143
95244
|
const thresholds = getThresholds(config2);
|
|
95144
95245
|
const proposals = runHeuristics(observations, thresholds);
|
|
@@ -95179,12 +95280,12 @@ async function curatorGc(options) {
|
|
|
95179
95280
|
await _curatorCmdDeps.writeFile(rollupPath, newContent);
|
|
95180
95281
|
const projectKey = getProjectKey(config2, resolved.projectDir);
|
|
95181
95282
|
const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
|
|
95182
|
-
const perRunsDir =
|
|
95283
|
+
const perRunsDir = join82(outputDir, "runs");
|
|
95183
95284
|
for (const runId of uniqueRunIds) {
|
|
95184
95285
|
if (!keepSet.has(runId)) {
|
|
95185
|
-
const runDir =
|
|
95186
|
-
await _curatorCmdDeps.removeFile(
|
|
95187
|
-
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"));
|
|
95188
95289
|
}
|
|
95189
95290
|
}
|
|
95190
95291
|
console.log(`[gc] Pruned rollup to ${keep} most recent runs (was ${uniqueRunIds.length}).`);
|
|
@@ -95227,9 +95328,9 @@ var init_curator2 = __esm(() => {
|
|
|
95227
95328
|
|
|
95228
95329
|
// bin/nax.ts
|
|
95229
95330
|
init_source();
|
|
95230
|
-
import { existsSync as
|
|
95331
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync7 } from "fs";
|
|
95231
95332
|
import { homedir as homedir3 } from "os";
|
|
95232
|
-
import { basename as
|
|
95333
|
+
import { basename as basename16, join as join83 } from "path";
|
|
95233
95334
|
|
|
95234
95335
|
// node_modules/commander/esm.mjs
|
|
95235
95336
|
var import__ = __toESM(require_commander(), 1);
|
|
@@ -96385,324 +96486,6 @@ function formatSource(type, sourcePath) {
|
|
|
96385
96486
|
function pad(str, width) {
|
|
96386
96487
|
return str.padEnd(width);
|
|
96387
96488
|
}
|
|
96388
|
-
// src/cli/diagnose.ts
|
|
96389
|
-
init_config();
|
|
96390
|
-
init_logger2();
|
|
96391
|
-
init_prd();
|
|
96392
|
-
init_runtime();
|
|
96393
|
-
import { existsSync as existsSync25, readdirSync as readdirSync5 } from "fs";
|
|
96394
|
-
import { basename as basename12, join as join57 } from "path";
|
|
96395
|
-
|
|
96396
|
-
// src/cli/diagnose-analysis.ts
|
|
96397
|
-
function detectFailurePattern(story, _prd, status) {
|
|
96398
|
-
if (story.status === "passed" && story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))) {
|
|
96399
|
-
return "AUTO_RECOVERED";
|
|
96400
|
-
}
|
|
96401
|
-
if (story.status !== "failed" && story.status !== "blocked" && story.status !== "paused") {
|
|
96402
|
-
return "UNKNOWN";
|
|
96403
|
-
}
|
|
96404
|
-
if (story.failureCategory === "greenfield-no-tests" || story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))) {
|
|
96405
|
-
return "GREENFIELD_TDD";
|
|
96406
|
-
}
|
|
96407
|
-
const testFailingCount = story.priorErrors?.filter((err) => err.toLowerCase().includes("tests-failing")).length || 0;
|
|
96408
|
-
if (testFailingCount >= 2)
|
|
96409
|
-
return "TEST_MISMATCH";
|
|
96410
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("precheck-failed")) || (status?.progress.blocked ?? 0) > 0) {
|
|
96411
|
-
return "ENVIRONMENTAL";
|
|
96412
|
-
}
|
|
96413
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("ratelimited")))
|
|
96414
|
-
return "RATE_LIMITED";
|
|
96415
|
-
if (story.failureCategory === "isolation-violation")
|
|
96416
|
-
return "ISOLATION_VIOLATION";
|
|
96417
|
-
if (status?.run.status === "stalled")
|
|
96418
|
-
return "STALLED";
|
|
96419
|
-
if (story.priorErrors?.some((err) => err.toLowerCase().includes("session-failure")))
|
|
96420
|
-
return "SESSION_CRASH";
|
|
96421
|
-
if (story.attempts > 3)
|
|
96422
|
-
return "MAX_TIERS_EXHAUSTED";
|
|
96423
|
-
return "UNKNOWN";
|
|
96424
|
-
}
|
|
96425
|
-
function getPatternSymptom(pattern) {
|
|
96426
|
-
const symptoms = {
|
|
96427
|
-
GREENFIELD_TDD: "Story attempted in greenfield project with no existing tests",
|
|
96428
|
-
TEST_MISMATCH: "Multiple test failures across attempts",
|
|
96429
|
-
ENVIRONMENTAL: "Environment prechecks failed or blockers detected",
|
|
96430
|
-
RATE_LIMITED: "API rate limit exceeded",
|
|
96431
|
-
ISOLATION_VIOLATION: "Story modified files outside its scope",
|
|
96432
|
-
MAX_TIERS_EXHAUSTED: "Story attempted at all configured model tiers without success",
|
|
96433
|
-
SESSION_CRASH: "Agent session crashed without producing commits",
|
|
96434
|
-
STALLED: "All stories blocked or paused -- no forward progress possible",
|
|
96435
|
-
LOCK_STALE: "Lock file present but process is dead",
|
|
96436
|
-
AUTO_RECOVERED: "Greenfield issue detected but S5 auto-recovery succeeded",
|
|
96437
|
-
UNKNOWN: "Unknown failure pattern"
|
|
96438
|
-
};
|
|
96439
|
-
return symptoms[pattern] ?? "Unknown failure pattern";
|
|
96440
|
-
}
|
|
96441
|
-
function getPatternFixSuggestion(pattern, _story) {
|
|
96442
|
-
const fixes = {
|
|
96443
|
-
GREENFIELD_TDD: "Add --greenfield flag or bootstrap with scaffolding tests first",
|
|
96444
|
-
TEST_MISMATCH: "Review acceptance criteria; tests may be too strict or story underspecified",
|
|
96445
|
-
ENVIRONMENTAL: "Fix precheck issues (deps, env, build) before re-running",
|
|
96446
|
-
RATE_LIMITED: "Wait for rate limit to reset or increase tier limits",
|
|
96447
|
-
ISOLATION_VIOLATION: "Narrow story scope or adjust expectedFiles to allow cross-file changes",
|
|
96448
|
-
MAX_TIERS_EXHAUSTED: "Simplify story or split into smaller sub-stories",
|
|
96449
|
-
SESSION_CRASH: "Check agent logs for crash details; may need manual intervention",
|
|
96450
|
-
STALLED: "Resolve blocked stories or skip them to unblock dependencies",
|
|
96451
|
-
LOCK_STALE: "Run: rm nax.lock",
|
|
96452
|
-
AUTO_RECOVERED: "No action needed -- S5 successfully handled greenfield scenario",
|
|
96453
|
-
UNKNOWN: "Review logs and prior errors for clues"
|
|
96454
|
-
};
|
|
96455
|
-
return fixes[pattern] ?? "Review logs and prior errors for clues";
|
|
96456
|
-
}
|
|
96457
|
-
function generateRecommendations(report) {
|
|
96458
|
-
const recommendations = [];
|
|
96459
|
-
if (report.lockCheck.lockPresent && report.lockCheck.pidAlive === false) {
|
|
96460
|
-
recommendations.push(`Remove stale lock: ${report.lockCheck.fixCommand}`);
|
|
96461
|
-
}
|
|
96462
|
-
const criticalPatterns = report.failureAnalysis.filter((f) => ["ENVIRONMENTAL", "STALLED", "SESSION_CRASH"].includes(f.pattern));
|
|
96463
|
-
if (criticalPatterns.length > 0) {
|
|
96464
|
-
recommendations.push(`Fix ${criticalPatterns.length} critical blocker(s): ${criticalPatterns.map((f) => f.storyId).join(", ")}`);
|
|
96465
|
-
}
|
|
96466
|
-
if (report.failureAnalysis.some((f) => f.pattern === "RATE_LIMITED")) {
|
|
96467
|
-
recommendations.push("Wait for rate limits to reset before re-running");
|
|
96468
|
-
}
|
|
96469
|
-
if (report.failureAnalysis.some((f) => f.pattern === "GREENFIELD_TDD")) {
|
|
96470
|
-
recommendations.push("Consider adding --greenfield flag or bootstrap tests for greenfield stories");
|
|
96471
|
-
}
|
|
96472
|
-
if (report.runSummary.storiesFailed > 0 && recommendations.length === 0) {
|
|
96473
|
-
recommendations.push(`Re-run with: nax run -f ${report.runSummary.feature}`);
|
|
96474
|
-
}
|
|
96475
|
-
if (report.runSummary.storiesFailed === 0 && report.runSummary.storiesPending === 0) {
|
|
96476
|
-
recommendations.push("All stories passed -- feature is complete!");
|
|
96477
|
-
}
|
|
96478
|
-
return recommendations;
|
|
96479
|
-
}
|
|
96480
|
-
function diagnoseStories(prd, status) {
|
|
96481
|
-
const storyBreakdown = [];
|
|
96482
|
-
const failureAnalysis = [];
|
|
96483
|
-
for (const story of prd.userStories) {
|
|
96484
|
-
const pattern = detectFailurePattern(story, prd, status);
|
|
96485
|
-
const diagnosis = {
|
|
96486
|
-
storyId: story.id,
|
|
96487
|
-
title: story.title,
|
|
96488
|
-
status: story.status,
|
|
96489
|
-
attempts: story.attempts,
|
|
96490
|
-
tier: story.routing?.modelTier,
|
|
96491
|
-
strategy: story.routing?.testStrategy,
|
|
96492
|
-
pattern
|
|
96493
|
-
};
|
|
96494
|
-
storyBreakdown.push(diagnosis);
|
|
96495
|
-
if (story.status === "failed" || story.status === "blocked" || story.status === "paused" || pattern === "AUTO_RECOVERED") {
|
|
96496
|
-
diagnosis.symptom = getPatternSymptom(pattern);
|
|
96497
|
-
diagnosis.fixSuggestion = getPatternFixSuggestion(pattern, story);
|
|
96498
|
-
failureAnalysis.push(diagnosis);
|
|
96499
|
-
}
|
|
96500
|
-
}
|
|
96501
|
-
return { storyBreakdown, failureAnalysis };
|
|
96502
|
-
}
|
|
96503
|
-
|
|
96504
|
-
// src/cli/diagnose-formatter.ts
|
|
96505
|
-
init_source();
|
|
96506
|
-
function formatReport(report, verbose) {
|
|
96507
|
-
const lines = [];
|
|
96508
|
-
lines.push(source_default.bold(`
|
|
96509
|
-
Diagnosis Report: ${report.runSummary.feature}
|
|
96510
|
-
`));
|
|
96511
|
-
if (!report.dataSources.eventsFound) {
|
|
96512
|
-
lines.push(source_default.yellow(`[WARN] events.jsonl not found -- diagnosis limited to PRD + git log
|
|
96513
|
-
`));
|
|
96514
|
-
}
|
|
96515
|
-
lines.push(source_default.bold(`Run Summary
|
|
96516
|
-
`));
|
|
96517
|
-
if (report.runSummary.lastRunTime) {
|
|
96518
|
-
lines.push(source_default.dim(` Last Run: ${report.runSummary.lastRunTime}`));
|
|
96519
|
-
}
|
|
96520
|
-
lines.push(source_default.dim(` Status: ${report.runSummary.status}`));
|
|
96521
|
-
lines.push(source_default.green(` Passed: ${report.runSummary.storiesPassed}`));
|
|
96522
|
-
lines.push(source_default.red(` Failed: ${report.runSummary.storiesFailed}`));
|
|
96523
|
-
lines.push(source_default.dim(` Pending: ${report.runSummary.storiesPending}`));
|
|
96524
|
-
if (report.runSummary.cost !== undefined) {
|
|
96525
|
-
lines.push(source_default.dim(` Cost: $${report.runSummary.cost.toFixed(4)}`));
|
|
96526
|
-
}
|
|
96527
|
-
lines.push(source_default.dim(` Commits: ${report.runSummary.commitsProduced}`));
|
|
96528
|
-
lines.push("");
|
|
96529
|
-
if (verbose && report.storyBreakdown.length > 0) {
|
|
96530
|
-
lines.push(source_default.bold(`Story Breakdown
|
|
96531
|
-
`));
|
|
96532
|
-
for (const story of report.storyBreakdown) {
|
|
96533
|
-
const icon = story.status === "passed" ? "[OK]" : story.status === "failed" ? "[FAIL]" : "[ ]";
|
|
96534
|
-
const pattern = story.pattern !== "UNKNOWN" ? source_default.yellow(` [${story.pattern}]`) : "";
|
|
96535
|
-
lines.push(` ${icon} ${story.storyId}: ${story.title}${pattern}`);
|
|
96536
|
-
if (verbose && story.tier) {
|
|
96537
|
-
lines.push(source_default.dim(` Tier: ${story.tier}, Strategy: ${story.strategy}, Attempts: ${story.attempts}`));
|
|
96538
|
-
}
|
|
96539
|
-
}
|
|
96540
|
-
lines.push("");
|
|
96541
|
-
}
|
|
96542
|
-
if (report.failureAnalysis.length > 0) {
|
|
96543
|
-
lines.push(source_default.bold(`Failure Analysis
|
|
96544
|
-
`));
|
|
96545
|
-
for (const failure of report.failureAnalysis) {
|
|
96546
|
-
const level = failure.pattern === "AUTO_RECOVERED" ? source_default.green("INFO") : source_default.red("ERROR");
|
|
96547
|
-
lines.push(` ${level} ${failure.storyId}: ${failure.title}`);
|
|
96548
|
-
lines.push(source_default.dim(` Pattern: ${failure.pattern}`));
|
|
96549
|
-
if (failure.symptom) {
|
|
96550
|
-
lines.push(source_default.dim(` Symptom: ${failure.symptom}`));
|
|
96551
|
-
}
|
|
96552
|
-
if (failure.fixSuggestion) {
|
|
96553
|
-
lines.push(source_default.yellow(` Fix: ${failure.fixSuggestion}`));
|
|
96554
|
-
}
|
|
96555
|
-
lines.push("");
|
|
96556
|
-
}
|
|
96557
|
-
}
|
|
96558
|
-
lines.push(source_default.bold(`Lock Check
|
|
96559
|
-
`));
|
|
96560
|
-
if (!report.lockCheck.lockPresent) {
|
|
96561
|
-
lines.push(source_default.dim(` No lock file present
|
|
96562
|
-
`));
|
|
96563
|
-
} else if (report.lockCheck.pidAlive === false) {
|
|
96564
|
-
lines.push(source_default.red(` [FAIL] Stale lock detected (PID ${report.lockCheck.pid} is dead)`));
|
|
96565
|
-
lines.push(source_default.yellow(` Fix: ${report.lockCheck.fixCommand}
|
|
96566
|
-
`));
|
|
96567
|
-
} else {
|
|
96568
|
-
lines.push(source_default.green(` [OK] Active lock (PID ${report.lockCheck.pid})
|
|
96569
|
-
`));
|
|
96570
|
-
}
|
|
96571
|
-
if (report.recommendations.length > 0) {
|
|
96572
|
-
lines.push(source_default.bold(`Recommendations
|
|
96573
|
-
`));
|
|
96574
|
-
for (let i = 0;i < report.recommendations.length; i++) {
|
|
96575
|
-
lines.push(` ${i + 1}. ${report.recommendations[i]}`);
|
|
96576
|
-
}
|
|
96577
|
-
lines.push("");
|
|
96578
|
-
}
|
|
96579
|
-
return lines.join(`
|
|
96580
|
-
`);
|
|
96581
|
-
}
|
|
96582
|
-
|
|
96583
|
-
// src/cli/diagnose.ts
|
|
96584
|
-
var _diagnoseDeps = {
|
|
96585
|
-
projectOutputDir,
|
|
96586
|
-
loadConfig
|
|
96587
|
-
};
|
|
96588
|
-
function isProcessAlive2(pid) {
|
|
96589
|
-
try {
|
|
96590
|
-
const result = Bun.spawnSync(["ps", "-p", String(pid)], { stdout: "ignore", stderr: "ignore" });
|
|
96591
|
-
return result.exitCode === 0;
|
|
96592
|
-
} catch {
|
|
96593
|
-
return false;
|
|
96594
|
-
}
|
|
96595
|
-
}
|
|
96596
|
-
async function loadStatusFile2(outputDir) {
|
|
96597
|
-
const statusPath = join57(outputDir, "status.json");
|
|
96598
|
-
if (!existsSync25(statusPath))
|
|
96599
|
-
return null;
|
|
96600
|
-
try {
|
|
96601
|
-
return await Bun.file(statusPath).json();
|
|
96602
|
-
} catch {
|
|
96603
|
-
return null;
|
|
96604
|
-
}
|
|
96605
|
-
}
|
|
96606
|
-
async function countCommitsSince(workdir, since) {
|
|
96607
|
-
if (!since)
|
|
96608
|
-
return 0;
|
|
96609
|
-
try {
|
|
96610
|
-
const result = Bun.spawnSync(["git", "log", "--oneline", `--since=${since}`, "--all"], {
|
|
96611
|
-
cwd: workdir,
|
|
96612
|
-
stdout: "pipe",
|
|
96613
|
-
stderr: "ignore"
|
|
96614
|
-
});
|
|
96615
|
-
if (result.exitCode !== 0)
|
|
96616
|
-
return 0;
|
|
96617
|
-
const output = new TextDecoder().decode(result.stdout);
|
|
96618
|
-
return output.trim().split(`
|
|
96619
|
-
`).filter((line) => line.length > 0).length;
|
|
96620
|
-
} catch {
|
|
96621
|
-
return 0;
|
|
96622
|
-
}
|
|
96623
|
-
}
|
|
96624
|
-
async function checkLock(workdir) {
|
|
96625
|
-
const lockFile = Bun.file(join57(workdir, "nax.lock"));
|
|
96626
|
-
if (!await lockFile.exists())
|
|
96627
|
-
return { lockPresent: false };
|
|
96628
|
-
try {
|
|
96629
|
-
const lockData = JSON.parse(await lockFile.text());
|
|
96630
|
-
const pid = lockData.pid;
|
|
96631
|
-
const pidAlive = isProcessAlive2(pid);
|
|
96632
|
-
if (!pidAlive)
|
|
96633
|
-
return { lockPresent: true, pidAlive: false, pid, fixCommand: "rm nax.lock" };
|
|
96634
|
-
return { lockPresent: true, pidAlive: true, pid };
|
|
96635
|
-
} catch {
|
|
96636
|
-
return { lockPresent: true };
|
|
96637
|
-
}
|
|
96638
|
-
}
|
|
96639
|
-
async function diagnoseCommand(options = {}) {
|
|
96640
|
-
const logger = getLogger();
|
|
96641
|
-
const workdir = options.workdir ?? process.cwd();
|
|
96642
|
-
const naxSubdir = findProjectDir(workdir);
|
|
96643
|
-
let projectDir = naxSubdir ? join57(naxSubdir, "..") : null;
|
|
96644
|
-
if (!projectDir && existsSync25(join57(workdir, ".nax"))) {
|
|
96645
|
-
projectDir = workdir;
|
|
96646
|
-
}
|
|
96647
|
-
if (!projectDir)
|
|
96648
|
-
throw new Error("Not in a nax project directory");
|
|
96649
|
-
const config2 = await _diagnoseDeps.loadConfig(projectDir).catch(() => null);
|
|
96650
|
-
const projectKey = config2?.name?.trim() || basename12(projectDir);
|
|
96651
|
-
const outputDir = _diagnoseDeps.projectOutputDir(projectKey, config2?.outputDir);
|
|
96652
|
-
let feature = options.feature;
|
|
96653
|
-
if (!feature) {
|
|
96654
|
-
const status2 = await loadStatusFile2(outputDir);
|
|
96655
|
-
if (status2) {
|
|
96656
|
-
feature = status2.run.feature;
|
|
96657
|
-
} else {
|
|
96658
|
-
const featuresDir = join57(outputDir, "features");
|
|
96659
|
-
if (!existsSync25(featuresDir))
|
|
96660
|
-
throw new Error("No features found in project");
|
|
96661
|
-
const features = readdirSync5(featuresDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
96662
|
-
if (features.length === 0)
|
|
96663
|
-
throw new Error("No features found");
|
|
96664
|
-
feature = features[0];
|
|
96665
|
-
logger.info("diagnose", "No feature specified, using first found", { feature });
|
|
96666
|
-
}
|
|
96667
|
-
}
|
|
96668
|
-
const featureDir = join57(outputDir, "features", feature);
|
|
96669
|
-
const prdPath = join57(featureDir, "prd.json");
|
|
96670
|
-
if (!existsSync25(prdPath))
|
|
96671
|
-
throw new Error(`Feature not found: ${feature}`);
|
|
96672
|
-
const prd = await loadPRD(prdPath);
|
|
96673
|
-
const status = await loadStatusFile2(outputDir);
|
|
96674
|
-
const lockCheck = await checkLock(projectDir);
|
|
96675
|
-
const commitCount = await countCommitsSince(projectDir, status?.run.startedAt);
|
|
96676
|
-
const { storyBreakdown, failureAnalysis } = diagnoseStories(prd, status);
|
|
96677
|
-
const report = {
|
|
96678
|
-
runSummary: {
|
|
96679
|
-
feature,
|
|
96680
|
-
lastRunTime: status?.run.startedAt,
|
|
96681
|
-
status: status?.run.status ?? "unknown",
|
|
96682
|
-
storiesPassed: prd.userStories.filter((s) => s.status === "passed").length,
|
|
96683
|
-
storiesFailed: prd.userStories.filter((s) => s.status === "failed").length,
|
|
96684
|
-
storiesPending: prd.userStories.filter((s) => s.status !== "passed" && s.status !== "failed" && s.status !== "skipped").length,
|
|
96685
|
-
cost: status?.cost.spent,
|
|
96686
|
-
commitsProduced: commitCount
|
|
96687
|
-
},
|
|
96688
|
-
storyBreakdown,
|
|
96689
|
-
failureAnalysis,
|
|
96690
|
-
lockCheck,
|
|
96691
|
-
recommendations: [],
|
|
96692
|
-
dataSources: {
|
|
96693
|
-
prdFound: true,
|
|
96694
|
-
statusFound: status !== null,
|
|
96695
|
-
eventsFound: false,
|
|
96696
|
-
gitLogFound: commitCount > 0
|
|
96697
|
-
}
|
|
96698
|
-
};
|
|
96699
|
-
report.recommendations = generateRecommendations(report);
|
|
96700
|
-
if (options.json) {
|
|
96701
|
-
console.log(JSON.stringify(report, null, 2));
|
|
96702
|
-
} else {
|
|
96703
|
-
console.log(formatReport(report, options.verbose ?? false));
|
|
96704
|
-
}
|
|
96705
|
-
}
|
|
96706
96489
|
// src/cli/interact.ts
|
|
96707
96490
|
init_common();
|
|
96708
96491
|
init_interaction();
|
|
@@ -96710,8 +96493,8 @@ init_interaction();
|
|
|
96710
96493
|
init_source();
|
|
96711
96494
|
init_loader();
|
|
96712
96495
|
init_generator2();
|
|
96713
|
-
import { existsSync as
|
|
96714
|
-
import { join as
|
|
96496
|
+
import { existsSync as existsSync25 } from "fs";
|
|
96497
|
+
import { join as join57 } from "path";
|
|
96715
96498
|
var VALID_AGENTS = ["claude", "codex", "opencode", "cursor", "windsurf", "aider", "gemini"];
|
|
96716
96499
|
async function generateCommand(options) {
|
|
96717
96500
|
const workdir = options.dir ?? process.cwd();
|
|
@@ -96754,7 +96537,7 @@ async function generateCommand(options) {
|
|
|
96754
96537
|
return;
|
|
96755
96538
|
}
|
|
96756
96539
|
if (options.package) {
|
|
96757
|
-
const packageDir =
|
|
96540
|
+
const packageDir = join57(workdir, options.package);
|
|
96758
96541
|
if (dryRun) {
|
|
96759
96542
|
console.log(source_default.yellow("\u26A0 Dry run \u2014 no files will be written"));
|
|
96760
96543
|
}
|
|
@@ -96774,10 +96557,10 @@ async function generateCommand(options) {
|
|
|
96774
96557
|
process.exit(1);
|
|
96775
96558
|
return;
|
|
96776
96559
|
}
|
|
96777
|
-
const contextPath = options.context ?
|
|
96778
|
-
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;
|
|
96779
96562
|
const autoInject = !options.noAutoInject;
|
|
96780
|
-
if (!
|
|
96563
|
+
if (!existsSync25(contextPath)) {
|
|
96781
96564
|
console.error(source_default.red(`\u2717 Context file not found: ${contextPath}`));
|
|
96782
96565
|
console.error(source_default.yellow(" Create .nax/context.md first, or run `nax init` to scaffold it."));
|
|
96783
96566
|
process.exit(1);
|
|
@@ -96880,8 +96663,8 @@ async function generateCommand(options) {
|
|
|
96880
96663
|
}
|
|
96881
96664
|
// src/cli/config-display.ts
|
|
96882
96665
|
init_loader();
|
|
96883
|
-
import { existsSync as
|
|
96884
|
-
import { join as
|
|
96666
|
+
import { existsSync as existsSync27 } from "fs";
|
|
96667
|
+
import { join as join59 } from "path";
|
|
96885
96668
|
|
|
96886
96669
|
// src/cli/config-descriptions.ts
|
|
96887
96670
|
var FIELD_DESCRIPTIONS = {
|
|
@@ -96937,6 +96720,7 @@ var FIELD_DESCRIPTIONS = {
|
|
|
96937
96720
|
"execution.rectification.fullSuiteTimeoutSeconds": "Timeout for full test suite run in seconds",
|
|
96938
96721
|
"execution.rectification.maxFailureSummaryChars": "Max characters in failure summary",
|
|
96939
96722
|
"execution.rectification.abortOnIncreasingFailures": "Abort if failure count increases",
|
|
96723
|
+
"execution.rectification.consecutiveIncreasesToBail": "Consecutive regressing iterations required before abortOnIncreasingFailures bails (default: 2; 1 = legacy behaviour)",
|
|
96940
96724
|
"execution.rectification.escalateOnExhaustion": "Enable model tier escalation when attempts are exhausted with remaining failures",
|
|
96941
96725
|
"execution.rectification.rethinkAtAttempt": "Attempt number at which 'rethink your approach' language is injected into the prompt (default: 2)",
|
|
96942
96726
|
"execution.rectification.urgencyAtAttempt": "Attempt number at which 'final chance before escalation' urgency is added (default: 3)",
|
|
@@ -97131,10 +96915,10 @@ function deepEqual(a, b) {
|
|
|
97131
96915
|
// src/cli/config-get.ts
|
|
97132
96916
|
init_defaults();
|
|
97133
96917
|
init_loader();
|
|
97134
|
-
import { existsSync as
|
|
97135
|
-
import { join as
|
|
96918
|
+
import { existsSync as existsSync26 } from "fs";
|
|
96919
|
+
import { join as join58 } from "path";
|
|
97136
96920
|
async function loadConfigFile(path18) {
|
|
97137
|
-
if (!
|
|
96921
|
+
if (!existsSync26(path18))
|
|
97138
96922
|
return null;
|
|
97139
96923
|
try {
|
|
97140
96924
|
return await Bun.file(path18).json();
|
|
@@ -97154,7 +96938,7 @@ async function loadProjectConfig() {
|
|
|
97154
96938
|
const projectDir = findProjectDir();
|
|
97155
96939
|
if (!projectDir)
|
|
97156
96940
|
return null;
|
|
97157
|
-
const projectPath =
|
|
96941
|
+
const projectPath = join58(projectDir, "config.json");
|
|
97158
96942
|
return await loadConfigFile(projectPath);
|
|
97159
96943
|
}
|
|
97160
96944
|
|
|
@@ -97214,14 +96998,14 @@ async function configCommand(config2, options = {}) {
|
|
|
97214
96998
|
function determineConfigSources() {
|
|
97215
96999
|
const globalPath = globalConfigPath();
|
|
97216
97000
|
const projectDir = findProjectDir();
|
|
97217
|
-
const projectPath = projectDir ?
|
|
97001
|
+
const projectPath = projectDir ? join59(projectDir, "config.json") : null;
|
|
97218
97002
|
return {
|
|
97219
97003
|
global: fileExists(globalPath) ? globalPath : null,
|
|
97220
97004
|
project: projectPath && fileExists(projectPath) ? projectPath : null
|
|
97221
97005
|
};
|
|
97222
97006
|
}
|
|
97223
97007
|
function fileExists(path18) {
|
|
97224
|
-
return
|
|
97008
|
+
return existsSync27(path18);
|
|
97225
97009
|
}
|
|
97226
97010
|
function displayConfigWithDescriptions(obj, path18, sources, indent = 0) {
|
|
97227
97011
|
const indentStr = " ".repeat(indent);
|
|
@@ -97362,16 +97146,16 @@ function formatValueForTable(value) {
|
|
|
97362
97146
|
init_paths();
|
|
97363
97147
|
init_profile();
|
|
97364
97148
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
97365
|
-
import { readdirSync as
|
|
97366
|
-
import { join as
|
|
97149
|
+
import { readdirSync as readdirSync5 } from "fs";
|
|
97150
|
+
import { join as join60 } from "path";
|
|
97367
97151
|
var _profileCLIDeps = {
|
|
97368
97152
|
env: process.env
|
|
97369
97153
|
};
|
|
97370
97154
|
var SENSITIVE_KEY_PATTERN = /key|token|secret|password|credential/i;
|
|
97371
97155
|
var VAR_PATTERN = /\$[A-Za-z_][A-Za-z0-9_]*/;
|
|
97372
97156
|
async function profileListCommand(startDir) {
|
|
97373
|
-
const globalProfilesDir =
|
|
97374
|
-
const projectProfilesDir =
|
|
97157
|
+
const globalProfilesDir = join60(globalConfigDir(), "profiles");
|
|
97158
|
+
const projectProfilesDir = join60(projectConfigDir(startDir), "profiles");
|
|
97375
97159
|
const globalProfiles = scanProfileDir(globalProfilesDir);
|
|
97376
97160
|
const projectProfiles = scanProfileDir(projectProfilesDir);
|
|
97377
97161
|
const activeProfile = await resolveProfileName({}, _profileCLIDeps.env, startDir);
|
|
@@ -97397,7 +97181,7 @@ async function profileListCommand(startDir) {
|
|
|
97397
97181
|
}
|
|
97398
97182
|
function scanProfileDir(dir) {
|
|
97399
97183
|
try {
|
|
97400
|
-
return
|
|
97184
|
+
return readdirSync5(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, ""));
|
|
97401
97185
|
} catch {
|
|
97402
97186
|
return [];
|
|
97403
97187
|
}
|
|
@@ -97430,7 +97214,7 @@ function maskProfileValues(obj) {
|
|
|
97430
97214
|
return result;
|
|
97431
97215
|
}
|
|
97432
97216
|
async function profileUseCommand(profileName, startDir) {
|
|
97433
|
-
const configPath =
|
|
97217
|
+
const configPath = join60(projectConfigDir(startDir), "config.json");
|
|
97434
97218
|
const configFile = Bun.file(configPath);
|
|
97435
97219
|
let existing = {};
|
|
97436
97220
|
if (await configFile.exists()) {
|
|
@@ -97449,8 +97233,8 @@ async function profileCurrentCommand(startDir) {
|
|
|
97449
97233
|
return resolveProfileName({}, _profileCLIDeps.env, startDir);
|
|
97450
97234
|
}
|
|
97451
97235
|
async function profileCreateCommand(profileName, startDir) {
|
|
97452
|
-
const profilesDir =
|
|
97453
|
-
const profilePath =
|
|
97236
|
+
const profilesDir = join60(projectConfigDir(startDir), "profiles");
|
|
97237
|
+
const profilePath = join60(profilesDir, `${profileName}.json`);
|
|
97454
97238
|
const profileFile = Bun.file(profilePath);
|
|
97455
97239
|
if (await profileFile.exists()) {
|
|
97456
97240
|
throw new Error(`Profile "${profileName}" already exists at ${profilePath}`);
|
|
@@ -97572,7 +97356,7 @@ async function contextInspectCommand(options) {
|
|
|
97572
97356
|
init_canonical_loader();
|
|
97573
97357
|
init_errors();
|
|
97574
97358
|
import { mkdir as mkdir12 } from "fs/promises";
|
|
97575
|
-
import { basename as
|
|
97359
|
+
import { basename as basename12, join as join61 } from "path";
|
|
97576
97360
|
var _rulesCLIDeps = {
|
|
97577
97361
|
readFile: async (path18) => Bun.file(path18).text(),
|
|
97578
97362
|
writeFile: async (path18, content) => {
|
|
@@ -97581,7 +97365,7 @@ var _rulesCLIDeps = {
|
|
|
97581
97365
|
fileExists: async (path18) => Bun.file(path18).exists(),
|
|
97582
97366
|
globInDir: (dir) => {
|
|
97583
97367
|
try {
|
|
97584
|
-
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));
|
|
97585
97369
|
} catch {
|
|
97586
97370
|
return [];
|
|
97587
97371
|
}
|
|
@@ -97630,7 +97414,7 @@ ${r.content}`).join(`
|
|
|
97630
97414
|
`);
|
|
97631
97415
|
const shimContent = `${header + body}
|
|
97632
97416
|
`;
|
|
97633
|
-
const shimPath =
|
|
97417
|
+
const shimPath = join61(workdir, shimFileName);
|
|
97634
97418
|
if (options.dryRun) {
|
|
97635
97419
|
console.log(`[dry-run] Would write ${shimPath} (${shimContent.length} bytes)`);
|
|
97636
97420
|
return;
|
|
@@ -97659,20 +97443,20 @@ function neutralizeContent(content) {
|
|
|
97659
97443
|
}
|
|
97660
97444
|
async function collectMigrationSources(workdir) {
|
|
97661
97445
|
const sources = [];
|
|
97662
|
-
const claudeMdPath =
|
|
97446
|
+
const claudeMdPath = join61(workdir, "CLAUDE.md");
|
|
97663
97447
|
if (await _rulesCLIDeps.fileExists(claudeMdPath)) {
|
|
97664
97448
|
const content = await _rulesCLIDeps.readFile(claudeMdPath);
|
|
97665
97449
|
if (content.trim()) {
|
|
97666
97450
|
sources.push({ sourcePath: claudeMdPath, targetFileName: "project-conventions.md", content });
|
|
97667
97451
|
}
|
|
97668
97452
|
}
|
|
97669
|
-
const rulesDir =
|
|
97453
|
+
const rulesDir = join61(workdir, ".claude", "rules");
|
|
97670
97454
|
const ruleFiles = _rulesCLIDeps.globInDir(rulesDir);
|
|
97671
97455
|
for (const filePath of ruleFiles) {
|
|
97672
97456
|
try {
|
|
97673
97457
|
const content = await _rulesCLIDeps.readFile(filePath);
|
|
97674
97458
|
if (content.trim()) {
|
|
97675
|
-
sources.push({ sourcePath: filePath, targetFileName:
|
|
97459
|
+
sources.push({ sourcePath: filePath, targetFileName: basename12(filePath), content });
|
|
97676
97460
|
}
|
|
97677
97461
|
} catch {}
|
|
97678
97462
|
}
|
|
@@ -97686,7 +97470,7 @@ async function rulesMigrateCommand(options) {
|
|
|
97686
97470
|
console.log("[WARN] No source files found (checked CLAUDE.md and .claude/rules/*.md). Nothing to migrate.");
|
|
97687
97471
|
return;
|
|
97688
97472
|
}
|
|
97689
|
-
const targetDir =
|
|
97473
|
+
const targetDir = join61(workdir, CANONICAL_RULES_DIR);
|
|
97690
97474
|
if (!options.dryRun) {
|
|
97691
97475
|
try {
|
|
97692
97476
|
await _rulesCLIDeps.mkdir(targetDir);
|
|
@@ -97697,7 +97481,7 @@ async function rulesMigrateCommand(options) {
|
|
|
97697
97481
|
let written = 0;
|
|
97698
97482
|
let skipped = 0;
|
|
97699
97483
|
for (const { sourcePath, targetFileName, content } of sources) {
|
|
97700
|
-
const targetPath =
|
|
97484
|
+
const targetPath = join61(targetDir, targetFileName);
|
|
97701
97485
|
if (!force && !options.dryRun && await _rulesCLIDeps.fileExists(targetPath)) {
|
|
97702
97486
|
console.log(`[skip] ${targetFileName} already exists (use --force to overwrite)`);
|
|
97703
97487
|
skipped++;
|
|
@@ -97736,7 +97520,7 @@ function collectCanonicalRuleRoots(workdir) {
|
|
|
97736
97520
|
const packageRel = normalized.slice(0, idx);
|
|
97737
97521
|
if (!packageRel)
|
|
97738
97522
|
continue;
|
|
97739
|
-
roots.add(
|
|
97523
|
+
roots.add(join61(workdir, packageRel));
|
|
97740
97524
|
}
|
|
97741
97525
|
return [...roots].sort();
|
|
97742
97526
|
}
|
|
@@ -97758,7 +97542,7 @@ init_logger2();
|
|
|
97758
97542
|
init_detect2();
|
|
97759
97543
|
init_workspace();
|
|
97760
97544
|
init_common();
|
|
97761
|
-
import { join as
|
|
97545
|
+
import { join as join62 } from "path";
|
|
97762
97546
|
function resolveEffective(detected, configPatterns) {
|
|
97763
97547
|
if (configPatterns !== undefined)
|
|
97764
97548
|
return "config";
|
|
@@ -97843,7 +97627,7 @@ async function detectCommand(options) {
|
|
|
97843
97627
|
const rootDetected = detectionMap[""] ?? { patterns: [], confidence: "empty", sources: [] };
|
|
97844
97628
|
const pkgEntries = await Promise.all(packageDirs.map(async (dir) => {
|
|
97845
97629
|
const det = detectionMap[dir] ?? { patterns: [], confidence: "empty", sources: [] };
|
|
97846
|
-
const pkgConfigPath =
|
|
97630
|
+
const pkgConfigPath = join62(workdir, ".nax", "mono", dir, "config.json");
|
|
97847
97631
|
const pkgRaw = await loadRawConfig(pkgConfigPath);
|
|
97848
97632
|
const pkgPatterns = deepGet(pkgRaw, TEST_PATTERNS_KEY);
|
|
97849
97633
|
const effective = Array.isArray(pkgPatterns) ? pkgPatterns : undefined;
|
|
@@ -97897,13 +97681,13 @@ async function detectCommand(options) {
|
|
|
97897
97681
|
if (rootDetected.confidence === "empty") {
|
|
97898
97682
|
console.log(source_default.yellow(" root: skipped (empty detection)"));
|
|
97899
97683
|
} else {
|
|
97900
|
-
const rootConfigPath =
|
|
97684
|
+
const rootConfigPath = join62(workdir, ".nax", "config.json");
|
|
97901
97685
|
try {
|
|
97902
97686
|
const status = await applyToConfig(rootConfigPath, rootDetected.patterns, options.force ?? false);
|
|
97903
97687
|
if (status === "skipped") {
|
|
97904
97688
|
console.log(source_default.dim(" root: skipped (testFilePatterns already set; use --force to overwrite)"));
|
|
97905
97689
|
} else {
|
|
97906
|
-
console.log(source_default.green(` root: ${status} \u2192 ${
|
|
97690
|
+
console.log(source_default.green(` root: ${status} \u2192 ${join62(".nax", "config.json")}`));
|
|
97907
97691
|
}
|
|
97908
97692
|
} catch (err) {
|
|
97909
97693
|
console.error(source_default.red(` root: write failed \u2014 ${err.message}`));
|
|
@@ -97916,13 +97700,13 @@ async function detectCommand(options) {
|
|
|
97916
97700
|
console.log(source_default.dim(` ${dir}: skipped (empty detection)`));
|
|
97917
97701
|
continue;
|
|
97918
97702
|
}
|
|
97919
|
-
const pkgConfigPath =
|
|
97703
|
+
const pkgConfigPath = join62(workdir, ".nax", "mono", dir, "config.json");
|
|
97920
97704
|
try {
|
|
97921
97705
|
const status = await applyToConfig(pkgConfigPath, det.patterns, options.force ?? false);
|
|
97922
97706
|
if (status === "skipped") {
|
|
97923
97707
|
console.log(source_default.dim(` ${dir}: skipped (already set)`));
|
|
97924
97708
|
} else {
|
|
97925
|
-
console.log(source_default.green(` ${dir}: ${status} \u2192 ${
|
|
97709
|
+
console.log(source_default.green(` ${dir}: ${status} \u2192 ${join62(".nax", "mono", dir, "config.json")}`));
|
|
97926
97710
|
}
|
|
97927
97711
|
} catch (err) {
|
|
97928
97712
|
console.error(source_default.red(` ${dir}: write failed \u2014 ${err.message}`));
|
|
@@ -97937,27 +97721,22 @@ async function detectCommand(options) {
|
|
|
97937
97721
|
process.exitCode = allEmpty ? 1 : 0;
|
|
97938
97722
|
}
|
|
97939
97723
|
|
|
97940
|
-
// src/commands/diagnose.ts
|
|
97941
|
-
async function diagnose(options) {
|
|
97942
|
-
await diagnoseCommand(options);
|
|
97943
|
-
}
|
|
97944
|
-
|
|
97945
97724
|
// src/commands/logs.ts
|
|
97946
97725
|
init_common();
|
|
97947
|
-
import { existsSync as
|
|
97948
|
-
import { join as
|
|
97726
|
+
import { existsSync as existsSync29 } from "fs";
|
|
97727
|
+
import { join as join66 } from "path";
|
|
97949
97728
|
|
|
97950
97729
|
// src/commands/logs-formatter.ts
|
|
97951
97730
|
init_source();
|
|
97952
97731
|
init_formatter();
|
|
97953
|
-
import { readdirSync as
|
|
97954
|
-
import { join as
|
|
97732
|
+
import { readdirSync as readdirSync7 } from "fs";
|
|
97733
|
+
import { join as join65 } from "path";
|
|
97955
97734
|
|
|
97956
97735
|
// src/commands/logs-reader.ts
|
|
97957
97736
|
init_paths3();
|
|
97958
|
-
import { existsSync as
|
|
97737
|
+
import { existsSync as existsSync28, readdirSync as readdirSync6 } from "fs";
|
|
97959
97738
|
import { readdir as readdir4 } from "fs/promises";
|
|
97960
|
-
import { join as
|
|
97739
|
+
import { join as join64 } from "path";
|
|
97961
97740
|
var _logsReaderDeps = {
|
|
97962
97741
|
getRunsDir
|
|
97963
97742
|
};
|
|
@@ -97971,7 +97750,7 @@ async function resolveRunFileFromRegistry(runId) {
|
|
|
97971
97750
|
}
|
|
97972
97751
|
let matched = null;
|
|
97973
97752
|
for (const entry of entries) {
|
|
97974
|
-
const metaPath =
|
|
97753
|
+
const metaPath = join64(runsDir, entry, "meta.json");
|
|
97975
97754
|
try {
|
|
97976
97755
|
const meta3 = await Bun.file(metaPath).json();
|
|
97977
97756
|
if (meta3.runId === runId || meta3.runId.startsWith(runId)) {
|
|
@@ -97983,24 +97762,24 @@ async function resolveRunFileFromRegistry(runId) {
|
|
|
97983
97762
|
if (!matched) {
|
|
97984
97763
|
throw new Error(`Run not found in registry: ${runId}`);
|
|
97985
97764
|
}
|
|
97986
|
-
if (!
|
|
97765
|
+
if (!existsSync28(matched.eventsDir)) {
|
|
97987
97766
|
console.log(`Log directory unavailable for run: ${runId}`);
|
|
97988
97767
|
return null;
|
|
97989
97768
|
}
|
|
97990
|
-
const files =
|
|
97769
|
+
const files = readdirSync6(matched.eventsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
|
|
97991
97770
|
if (files.length === 0) {
|
|
97992
97771
|
console.log(`No log files found for run: ${runId}`);
|
|
97993
97772
|
return null;
|
|
97994
97773
|
}
|
|
97995
97774
|
const specificFile = files.find((f) => f === `${matched.runId}.jsonl`);
|
|
97996
|
-
return
|
|
97775
|
+
return join64(matched.eventsDir, specificFile ?? files[0]);
|
|
97997
97776
|
}
|
|
97998
97777
|
async function selectRunFile(runsDir) {
|
|
97999
|
-
const files =
|
|
97778
|
+
const files = readdirSync6(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
|
|
98000
97779
|
if (files.length === 0) {
|
|
98001
97780
|
return null;
|
|
98002
97781
|
}
|
|
98003
|
-
return
|
|
97782
|
+
return join64(runsDir, files[0]);
|
|
98004
97783
|
}
|
|
98005
97784
|
async function extractRunSummary(filePath) {
|
|
98006
97785
|
const file3 = Bun.file(filePath);
|
|
@@ -98075,7 +97854,7 @@ var LOG_LEVEL_PRIORITY2 = {
|
|
|
98075
97854
|
error: 3
|
|
98076
97855
|
};
|
|
98077
97856
|
async function displayRunsList(runsDir) {
|
|
98078
|
-
const files =
|
|
97857
|
+
const files = readdirSync7(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
|
|
98079
97858
|
if (files.length === 0) {
|
|
98080
97859
|
console.log(source_default.dim("No runs found"));
|
|
98081
97860
|
return;
|
|
@@ -98086,7 +97865,7 @@ Runs:
|
|
|
98086
97865
|
console.log(source_default.gray(" Timestamp Stories Duration Cost Status"));
|
|
98087
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"));
|
|
98088
97867
|
for (const file3 of files) {
|
|
98089
|
-
const filePath =
|
|
97868
|
+
const filePath = join65(runsDir, file3);
|
|
98090
97869
|
const summary = await extractRunSummary(filePath);
|
|
98091
97870
|
const timestamp = file3.replace(".jsonl", "");
|
|
98092
97871
|
const stories = summary ? `${summary.passed}/${summary.total}` : "?/?";
|
|
@@ -98200,7 +97979,7 @@ async function logsCommand(options) {
|
|
|
98200
97979
|
return;
|
|
98201
97980
|
}
|
|
98202
97981
|
const resolved = resolveProject({ dir: options.dir });
|
|
98203
|
-
const naxDir =
|
|
97982
|
+
const naxDir = join66(resolved.projectDir, ".nax");
|
|
98204
97983
|
const configPath = resolved.configPath;
|
|
98205
97984
|
const configFile = Bun.file(configPath);
|
|
98206
97985
|
const config2 = await configFile.json();
|
|
@@ -98208,9 +97987,9 @@ async function logsCommand(options) {
|
|
|
98208
97987
|
if (!featureName) {
|
|
98209
97988
|
throw new Error("No feature specified in config.json");
|
|
98210
97989
|
}
|
|
98211
|
-
const featureDir =
|
|
98212
|
-
const runsDir =
|
|
98213
|
-
if (!
|
|
97990
|
+
const featureDir = join66(naxDir, "features", featureName);
|
|
97991
|
+
const runsDir = join66(featureDir, "runs");
|
|
97992
|
+
if (!existsSync29(runsDir)) {
|
|
98214
97993
|
throw new Error(`No runs directory found for feature: ${featureName}`);
|
|
98215
97994
|
}
|
|
98216
97995
|
if (options.list) {
|
|
@@ -98234,8 +98013,8 @@ init_config();
|
|
|
98234
98013
|
init_prd();
|
|
98235
98014
|
init_precheck();
|
|
98236
98015
|
init_common();
|
|
98237
|
-
import { existsSync as
|
|
98238
|
-
import { join as
|
|
98016
|
+
import { existsSync as existsSync30 } from "fs";
|
|
98017
|
+
import { join as join67 } from "path";
|
|
98239
98018
|
async function precheckCommand(options) {
|
|
98240
98019
|
const resolved = resolveProject({
|
|
98241
98020
|
dir: options.dir,
|
|
@@ -98257,14 +98036,14 @@ async function precheckCommand(options) {
|
|
|
98257
98036
|
process.exit(1);
|
|
98258
98037
|
}
|
|
98259
98038
|
}
|
|
98260
|
-
const naxDir =
|
|
98261
|
-
const featureDir =
|
|
98262
|
-
const prdPath =
|
|
98263
|
-
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)) {
|
|
98264
98043
|
console.error(source_default.red(`Feature not found: ${featureName}`));
|
|
98265
98044
|
process.exit(1);
|
|
98266
98045
|
}
|
|
98267
|
-
if (!
|
|
98046
|
+
if (!existsSync30(prdPath)) {
|
|
98268
98047
|
console.error(source_default.red(`Missing prd.json for feature: ${featureName}`));
|
|
98269
98048
|
console.error(source_default.dim(`Run: nax plan -f ${featureName} --from spec.md --auto`));
|
|
98270
98049
|
process.exit(EXIT_CODES.INVALID_PRD);
|
|
@@ -98282,7 +98061,7 @@ async function precheckCommand(options) {
|
|
|
98282
98061
|
init_source();
|
|
98283
98062
|
init_paths3();
|
|
98284
98063
|
import { readdir as readdir5 } from "fs/promises";
|
|
98285
|
-
import { join as
|
|
98064
|
+
import { join as join68 } from "path";
|
|
98286
98065
|
var DEFAULT_LIMIT = 20;
|
|
98287
98066
|
var _runsCmdDeps = {
|
|
98288
98067
|
getRunsDir
|
|
@@ -98337,7 +98116,7 @@ async function runsCommand(options = {}) {
|
|
|
98337
98116
|
}
|
|
98338
98117
|
const rows = [];
|
|
98339
98118
|
for (const entry of entries) {
|
|
98340
|
-
const metaPath =
|
|
98119
|
+
const metaPath = join68(runsDir, entry, "meta.json");
|
|
98341
98120
|
let meta3;
|
|
98342
98121
|
try {
|
|
98343
98122
|
meta3 = await Bun.file(metaPath).json();
|
|
@@ -98414,8 +98193,8 @@ async function runsCommand(options = {}) {
|
|
|
98414
98193
|
|
|
98415
98194
|
// src/commands/unlock.ts
|
|
98416
98195
|
init_source();
|
|
98417
|
-
import { join as
|
|
98418
|
-
function
|
|
98196
|
+
import { join as join69 } from "path";
|
|
98197
|
+
function isProcessAlive2(pid) {
|
|
98419
98198
|
try {
|
|
98420
98199
|
process.kill(pid, 0);
|
|
98421
98200
|
return true;
|
|
@@ -98429,7 +98208,7 @@ function formatLockAge(ageMs) {
|
|
|
98429
98208
|
}
|
|
98430
98209
|
async function unlockCommand(options) {
|
|
98431
98210
|
const workdir = options.dir ?? process.cwd();
|
|
98432
|
-
const lockPath =
|
|
98211
|
+
const lockPath = join69(workdir, "nax.lock");
|
|
98433
98212
|
const lockFile = Bun.file(lockPath);
|
|
98434
98213
|
const exists = await lockFile.exists();
|
|
98435
98214
|
if (!exists) {
|
|
@@ -98447,7 +98226,7 @@ async function unlockCommand(options) {
|
|
|
98447
98226
|
const { pid, timestamp } = lockData;
|
|
98448
98227
|
const ageMs = Date.now() - timestamp;
|
|
98449
98228
|
if (!options.force) {
|
|
98450
|
-
if (
|
|
98229
|
+
if (isProcessAlive2(pid)) {
|
|
98451
98230
|
console.error(source_default.red(`nax is still running (PID ${pid}). Use --force to override.`));
|
|
98452
98231
|
process.exit(1);
|
|
98453
98232
|
}
|
|
@@ -105127,7 +104906,7 @@ var import_react27 = __toESM(require_react(), 1);
|
|
|
105127
104906
|
// node_modules/ink/build/hooks/use-cursor.js
|
|
105128
104907
|
var import_react28 = __toESM(require_react(), 1);
|
|
105129
104908
|
// src/tui/App.tsx
|
|
105130
|
-
var
|
|
104909
|
+
var import_react36 = __toESM(require_react(), 1);
|
|
105131
104910
|
|
|
105132
104911
|
// src/utils/queue-writer.ts
|
|
105133
104912
|
async function writeQueueCommand(queueFilePath, command) {
|
|
@@ -105156,151 +104935,8 @@ ${commandLine2}
|
|
|
105156
104935
|
await Bun.write(queueFilePath, newContent);
|
|
105157
104936
|
}
|
|
105158
104937
|
|
|
105159
|
-
// node_modules/ink-spinner/build/index.js
|
|
105160
|
-
var import_react29 = __toESM(require_react(), 1);
|
|
105161
|
-
var import_cli_spinners = __toESM(require_cli_spinners(), 1);
|
|
105162
|
-
function Spinner({ type = "dots" }) {
|
|
105163
|
-
const [frame, setFrame] = import_react29.useState(0);
|
|
105164
|
-
const spinner = import_cli_spinners.default[type];
|
|
105165
|
-
import_react29.useEffect(() => {
|
|
105166
|
-
const timer = setInterval(() => {
|
|
105167
|
-
setFrame((previousFrame) => {
|
|
105168
|
-
const isLastFrame = previousFrame === spinner.frames.length - 1;
|
|
105169
|
-
return isLastFrame ? 0 : previousFrame + 1;
|
|
105170
|
-
});
|
|
105171
|
-
}, spinner.interval);
|
|
105172
|
-
return () => {
|
|
105173
|
-
clearInterval(timer);
|
|
105174
|
-
};
|
|
105175
|
-
}, [spinner]);
|
|
105176
|
-
return import_react29.default.createElement(Text, null, spinner.frames[frame]);
|
|
105177
|
-
}
|
|
105178
|
-
var build_default = Spinner;
|
|
105179
|
-
|
|
105180
|
-
// src/tui/components/AgentPanel.tsx
|
|
105181
|
-
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
105182
|
-
var MAX_OUTPUT_LINES = 500;
|
|
105183
|
-
function AgentPanel({ focused = false, outputLines = [], activeCalls }) {
|
|
105184
|
-
const borderColor = focused ? "cyan" : "gray";
|
|
105185
|
-
const bufferedLines = outputLines.length > MAX_OUTPUT_LINES ? outputLines.slice(-MAX_OUTPUT_LINES) : outputLines;
|
|
105186
|
-
const activeCallList = activeCalls ? Array.from(activeCalls.values()) : [];
|
|
105187
|
-
const hasActiveCalls = activeCallList.length > 0;
|
|
105188
|
-
const hasOutput = bufferedLines.length > 0;
|
|
105189
|
-
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105190
|
-
flexDirection: "column",
|
|
105191
|
-
flexGrow: 1,
|
|
105192
|
-
borderStyle: "single",
|
|
105193
|
-
borderColor,
|
|
105194
|
-
children: [
|
|
105195
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105196
|
-
paddingX: 1,
|
|
105197
|
-
borderStyle: "single",
|
|
105198
|
-
borderBottom: true,
|
|
105199
|
-
borderColor,
|
|
105200
|
-
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105201
|
-
bold: true,
|
|
105202
|
-
color: focused ? "cyan" : undefined,
|
|
105203
|
-
children: [
|
|
105204
|
-
"Agent ",
|
|
105205
|
-
focused && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105206
|
-
dimColor: true,
|
|
105207
|
-
children: "(focused)"
|
|
105208
|
-
}, undefined, false, undefined, this)
|
|
105209
|
-
]
|
|
105210
|
-
}, undefined, true, undefined, this)
|
|
105211
|
-
}, undefined, false, undefined, this),
|
|
105212
|
-
hasActiveCalls && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105213
|
-
flexDirection: "column",
|
|
105214
|
-
paddingX: 1,
|
|
105215
|
-
paddingY: 1,
|
|
105216
|
-
children: activeCallList.map((call) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(AgentCallRow, {
|
|
105217
|
-
call
|
|
105218
|
-
}, call.callId, false, undefined, this))
|
|
105219
|
-
}, undefined, false, undefined, this),
|
|
105220
|
-
!hasActiveCalls && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105221
|
-
flexDirection: "column",
|
|
105222
|
-
paddingX: 1,
|
|
105223
|
-
paddingY: 1,
|
|
105224
|
-
children: hasOutput ? bufferedLines.map((line, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105225
|
-
children: line
|
|
105226
|
-
}, `line-${i}-${line.slice(0, 20)}`, false, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105227
|
-
dimColor: true,
|
|
105228
|
-
children: [
|
|
105229
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
|
|
105230
|
-
type: "dots"
|
|
105231
|
-
}, undefined, false, undefined, this),
|
|
105232
|
-
" Waiting for agent..."
|
|
105233
|
-
]
|
|
105234
|
-
}, undefined, true, undefined, this)
|
|
105235
|
-
}, undefined, false, undefined, this)
|
|
105236
|
-
]
|
|
105237
|
-
}, undefined, true, undefined, this);
|
|
105238
|
-
}
|
|
105239
|
-
function formatMs(ms) {
|
|
105240
|
-
if (ms < 1000)
|
|
105241
|
-
return `${ms}ms`;
|
|
105242
|
-
return `${Math.floor(ms / 1000)}s`;
|
|
105243
|
-
}
|
|
105244
|
-
function AgentCallRow({ call }) {
|
|
105245
|
-
const now3 = Date.now();
|
|
105246
|
-
const elapsedMs = now3 - call.startedAt;
|
|
105247
|
-
const idleMs = now3 - call.lastActivityAt;
|
|
105248
|
-
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105249
|
-
flexDirection: "row",
|
|
105250
|
-
gap: 1,
|
|
105251
|
-
children: [
|
|
105252
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105253
|
-
color: "cyan",
|
|
105254
|
-
children: call.agentName
|
|
105255
|
-
}, undefined, false, undefined, this),
|
|
105256
|
-
call.storyId && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105257
|
-
dimColor: true,
|
|
105258
|
-
children: call.storyId
|
|
105259
|
-
}, undefined, false, undefined, this),
|
|
105260
|
-
call.stage && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105261
|
-
dimColor: true,
|
|
105262
|
-
children: [
|
|
105263
|
-
"[",
|
|
105264
|
-
call.stage,
|
|
105265
|
-
"]"
|
|
105266
|
-
]
|
|
105267
|
-
}, undefined, true, undefined, this),
|
|
105268
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105269
|
-
children: [
|
|
105270
|
-
" elapsed:",
|
|
105271
|
-
formatMs(elapsedMs)
|
|
105272
|
-
]
|
|
105273
|
-
}, undefined, true, undefined, this),
|
|
105274
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105275
|
-
children: [
|
|
105276
|
-
" idle:",
|
|
105277
|
-
formatMs(idleMs)
|
|
105278
|
-
]
|
|
105279
|
-
}, undefined, true, undefined, this),
|
|
105280
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105281
|
-
children: [
|
|
105282
|
-
" msg:",
|
|
105283
|
-
call.messageUpdates
|
|
105284
|
-
]
|
|
105285
|
-
}, undefined, true, undefined, this),
|
|
105286
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105287
|
-
children: [
|
|
105288
|
-
" think:",
|
|
105289
|
-
call.thinkingUpdates
|
|
105290
|
-
]
|
|
105291
|
-
}, undefined, true, undefined, this),
|
|
105292
|
-
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105293
|
-
children: [
|
|
105294
|
-
" usage:",
|
|
105295
|
-
call.usageUpdates
|
|
105296
|
-
]
|
|
105297
|
-
}, undefined, true, undefined, this)
|
|
105298
|
-
]
|
|
105299
|
-
}, undefined, true, undefined, this);
|
|
105300
|
-
}
|
|
105301
|
-
|
|
105302
104938
|
// src/tui/components/CostOverlay.tsx
|
|
105303
|
-
var
|
|
104939
|
+
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
105304
104940
|
function formatCost2(cost) {
|
|
105305
104941
|
return `$${cost.toFixed(4)}`;
|
|
105306
104942
|
}
|
|
@@ -105309,7 +104945,7 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105309
104945
|
return null;
|
|
105310
104946
|
}
|
|
105311
104947
|
const executedStories = stories.filter((s) => s.cost && s.cost > 0 || s.status !== "pending");
|
|
105312
|
-
return /* @__PURE__ */
|
|
104948
|
+
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105313
104949
|
flexDirection: "column",
|
|
105314
104950
|
borderStyle: "double",
|
|
105315
104951
|
borderColor: "cyan",
|
|
@@ -105317,87 +104953,87 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105317
104953
|
paddingY: 1,
|
|
105318
104954
|
minWidth: 60,
|
|
105319
104955
|
children: [
|
|
105320
|
-
/* @__PURE__ */
|
|
104956
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105321
104957
|
paddingBottom: 1,
|
|
105322
|
-
children: /* @__PURE__ */
|
|
104958
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105323
104959
|
bold: true,
|
|
105324
104960
|
color: "cyan",
|
|
105325
104961
|
children: "Cost Breakdown"
|
|
105326
104962
|
}, undefined, false, undefined, this)
|
|
105327
104963
|
}, undefined, false, undefined, this),
|
|
105328
|
-
/* @__PURE__ */
|
|
104964
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105329
104965
|
paddingBottom: 1,
|
|
105330
104966
|
borderBottom: true,
|
|
105331
104967
|
borderColor: "gray",
|
|
105332
104968
|
children: [
|
|
105333
|
-
/* @__PURE__ */
|
|
104969
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105334
104970
|
width: 12,
|
|
105335
|
-
children: /* @__PURE__ */
|
|
104971
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105336
104972
|
bold: true,
|
|
105337
104973
|
children: "Story ID"
|
|
105338
104974
|
}, undefined, false, undefined, this)
|
|
105339
104975
|
}, undefined, false, undefined, this),
|
|
105340
|
-
/* @__PURE__ */
|
|
104976
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105341
104977
|
width: 12,
|
|
105342
|
-
children: /* @__PURE__ */
|
|
104978
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105343
104979
|
bold: true,
|
|
105344
104980
|
children: "Status"
|
|
105345
104981
|
}, undefined, false, undefined, this)
|
|
105346
104982
|
}, undefined, false, undefined, this),
|
|
105347
|
-
/* @__PURE__ */
|
|
104983
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105348
104984
|
width: 12,
|
|
105349
|
-
children: /* @__PURE__ */
|
|
104985
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105350
104986
|
bold: true,
|
|
105351
104987
|
children: "Cost"
|
|
105352
104988
|
}, undefined, false, undefined, this)
|
|
105353
104989
|
}, undefined, false, undefined, this)
|
|
105354
104990
|
]
|
|
105355
104991
|
}, undefined, true, undefined, this),
|
|
105356
|
-
/* @__PURE__ */
|
|
104992
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105357
104993
|
flexDirection: "column",
|
|
105358
104994
|
paddingY: 1,
|
|
105359
|
-
children: executedStories.length > 0 ? executedStories.map((story) => /* @__PURE__ */
|
|
104995
|
+
children: executedStories.length > 0 ? executedStories.map((story) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105360
104996
|
children: [
|
|
105361
|
-
/* @__PURE__ */
|
|
104997
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105362
104998
|
width: 12,
|
|
105363
|
-
children: /* @__PURE__ */
|
|
104999
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105364
105000
|
children: story.story.id
|
|
105365
105001
|
}, undefined, false, undefined, this)
|
|
105366
105002
|
}, undefined, false, undefined, this),
|
|
105367
|
-
/* @__PURE__ */
|
|
105003
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105368
105004
|
width: 12,
|
|
105369
|
-
children: /* @__PURE__ */
|
|
105005
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105370
105006
|
color: story.status === "passed" ? "green" : story.status === "failed" ? "red" : undefined,
|
|
105371
105007
|
children: story.status
|
|
105372
105008
|
}, undefined, false, undefined, this)
|
|
105373
105009
|
}, undefined, false, undefined, this),
|
|
105374
|
-
/* @__PURE__ */
|
|
105010
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105375
105011
|
width: 12,
|
|
105376
|
-
children: /* @__PURE__ */
|
|
105012
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105377
105013
|
children: formatCost2(story.cost || 0)
|
|
105378
105014
|
}, undefined, false, undefined, this)
|
|
105379
105015
|
}, undefined, false, undefined, this)
|
|
105380
105016
|
]
|
|
105381
|
-
}, story.story.id, true, undefined, this)) : /* @__PURE__ */
|
|
105017
|
+
}, story.story.id, true, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105382
105018
|
dimColor: true,
|
|
105383
105019
|
children: "No stories executed yet"
|
|
105384
105020
|
}, undefined, false, undefined, this)
|
|
105385
105021
|
}, undefined, false, undefined, this),
|
|
105386
|
-
/* @__PURE__ */
|
|
105022
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105387
105023
|
paddingTop: 1,
|
|
105388
105024
|
borderTop: true,
|
|
105389
105025
|
borderColor: "gray",
|
|
105390
105026
|
children: [
|
|
105391
|
-
/* @__PURE__ */
|
|
105027
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105392
105028
|
width: 24,
|
|
105393
|
-
children: /* @__PURE__ */
|
|
105029
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105394
105030
|
bold: true,
|
|
105395
105031
|
children: "Total Cost:"
|
|
105396
105032
|
}, undefined, false, undefined, this)
|
|
105397
105033
|
}, undefined, false, undefined, this),
|
|
105398
|
-
/* @__PURE__ */
|
|
105034
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105399
105035
|
width: 12,
|
|
105400
|
-
children: /* @__PURE__ */
|
|
105036
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105401
105037
|
bold: true,
|
|
105402
105038
|
color: "cyan",
|
|
105403
105039
|
children: formatCost2(totalCost)
|
|
@@ -105405,16 +105041,16 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105405
105041
|
}, undefined, false, undefined, this)
|
|
105406
105042
|
]
|
|
105407
105043
|
}, undefined, true, undefined, this),
|
|
105408
|
-
/* @__PURE__ */
|
|
105044
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
105409
105045
|
justifyContent: "center",
|
|
105410
105046
|
paddingTop: 1,
|
|
105411
105047
|
borderTop: true,
|
|
105412
105048
|
borderColor: "gray",
|
|
105413
|
-
children: /* @__PURE__ */
|
|
105049
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105414
105050
|
dimColor: true,
|
|
105415
105051
|
children: [
|
|
105416
105052
|
"Press ",
|
|
105417
|
-
/* @__PURE__ */
|
|
105053
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
105418
105054
|
color: "yellow",
|
|
105419
105055
|
children: "Esc"
|
|
105420
105056
|
}, undefined, false, undefined, this),
|
|
@@ -105427,118 +105063,118 @@ function CostOverlay({ visible = false, stories = [], totalCost = 0 }) {
|
|
|
105427
105063
|
}
|
|
105428
105064
|
|
|
105429
105065
|
// src/tui/components/HelpOverlay.tsx
|
|
105430
|
-
var
|
|
105066
|
+
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
105431
105067
|
function HelpOverlay({ visible = false }) {
|
|
105432
105068
|
if (!visible) {
|
|
105433
105069
|
return null;
|
|
105434
105070
|
}
|
|
105435
|
-
return /* @__PURE__ */
|
|
105071
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105436
105072
|
flexDirection: "column",
|
|
105437
105073
|
borderStyle: "double",
|
|
105438
105074
|
borderColor: "cyan",
|
|
105439
105075
|
paddingX: 2,
|
|
105440
105076
|
paddingY: 1,
|
|
105441
105077
|
children: [
|
|
105442
|
-
/* @__PURE__ */
|
|
105078
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105443
105079
|
paddingBottom: 1,
|
|
105444
|
-
children: /* @__PURE__ */
|
|
105080
|
+
children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105445
105081
|
bold: true,
|
|
105446
105082
|
color: "cyan",
|
|
105447
105083
|
children: "Keyboard Shortcuts"
|
|
105448
105084
|
}, undefined, false, undefined, this)
|
|
105449
105085
|
}, undefined, false, undefined, this),
|
|
105450
|
-
/* @__PURE__ */
|
|
105086
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105451
105087
|
flexDirection: "column",
|
|
105452
105088
|
paddingBottom: 1,
|
|
105453
105089
|
children: [
|
|
105454
|
-
/* @__PURE__ */
|
|
105090
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105455
105091
|
dimColor: true,
|
|
105456
105092
|
children: "Stories Panel (default):"
|
|
105457
105093
|
}, undefined, false, undefined, this),
|
|
105458
|
-
/* @__PURE__ */
|
|
105094
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105459
105095
|
children: [
|
|
105460
105096
|
" ",
|
|
105461
|
-
/* @__PURE__ */
|
|
105097
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105462
105098
|
color: "yellow",
|
|
105463
105099
|
children: "p"
|
|
105464
105100
|
}, undefined, false, undefined, this),
|
|
105465
105101
|
" \u2014 Pause after current story"
|
|
105466
105102
|
]
|
|
105467
105103
|
}, undefined, true, undefined, this),
|
|
105468
|
-
/* @__PURE__ */
|
|
105104
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105469
105105
|
children: [
|
|
105470
105106
|
" ",
|
|
105471
|
-
/* @__PURE__ */
|
|
105107
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105472
105108
|
color: "yellow",
|
|
105473
105109
|
children: "a"
|
|
105474
105110
|
}, undefined, false, undefined, this),
|
|
105475
105111
|
" \u2014 Abort run"
|
|
105476
105112
|
]
|
|
105477
105113
|
}, undefined, true, undefined, this),
|
|
105478
|
-
/* @__PURE__ */
|
|
105114
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105479
105115
|
children: [
|
|
105480
105116
|
" ",
|
|
105481
|
-
/* @__PURE__ */
|
|
105117
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105482
105118
|
color: "yellow",
|
|
105483
105119
|
children: "s"
|
|
105484
105120
|
}, undefined, false, undefined, this),
|
|
105485
105121
|
" \u2014 Skip current story"
|
|
105486
105122
|
]
|
|
105487
105123
|
}, undefined, true, undefined, this),
|
|
105488
|
-
/* @__PURE__ */
|
|
105124
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105489
105125
|
children: [
|
|
105490
105126
|
" ",
|
|
105491
|
-
/* @__PURE__ */
|
|
105127
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105492
105128
|
color: "yellow",
|
|
105493
105129
|
children: "Tab"
|
|
105494
105130
|
}, undefined, false, undefined, this),
|
|
105495
105131
|
" \u2014 Toggle focus to Agent panel"
|
|
105496
105132
|
]
|
|
105497
105133
|
}, undefined, true, undefined, this),
|
|
105498
|
-
/* @__PURE__ */
|
|
105134
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105499
105135
|
children: [
|
|
105500
105136
|
" ",
|
|
105501
|
-
/* @__PURE__ */
|
|
105137
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105502
105138
|
color: "yellow",
|
|
105503
105139
|
children: "q"
|
|
105504
105140
|
}, undefined, false, undefined, this),
|
|
105505
105141
|
" \u2014 Quit TUI"
|
|
105506
105142
|
]
|
|
105507
105143
|
}, undefined, true, undefined, this),
|
|
105508
|
-
/* @__PURE__ */
|
|
105144
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105509
105145
|
children: [
|
|
105510
105146
|
" ",
|
|
105511
|
-
/* @__PURE__ */
|
|
105147
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105512
105148
|
color: "yellow",
|
|
105513
105149
|
children: "?"
|
|
105514
105150
|
}, undefined, false, undefined, this),
|
|
105515
105151
|
" \u2014 Show this help"
|
|
105516
105152
|
]
|
|
105517
105153
|
}, undefined, true, undefined, this),
|
|
105518
|
-
/* @__PURE__ */
|
|
105154
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105519
105155
|
children: [
|
|
105520
105156
|
" ",
|
|
105521
|
-
/* @__PURE__ */
|
|
105157
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105522
105158
|
color: "yellow",
|
|
105523
105159
|
children: "c"
|
|
105524
105160
|
}, undefined, false, undefined, this),
|
|
105525
105161
|
" \u2014 Show cost breakdown"
|
|
105526
105162
|
]
|
|
105527
105163
|
}, undefined, true, undefined, this),
|
|
105528
|
-
/* @__PURE__ */
|
|
105164
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105529
105165
|
children: [
|
|
105530
105166
|
" ",
|
|
105531
|
-
/* @__PURE__ */
|
|
105167
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105532
105168
|
color: "yellow",
|
|
105533
105169
|
children: "r"
|
|
105534
105170
|
}, undefined, false, undefined, this),
|
|
105535
105171
|
" \u2014 Retry last failed story"
|
|
105536
105172
|
]
|
|
105537
105173
|
}, undefined, true, undefined, this),
|
|
105538
|
-
/* @__PURE__ */
|
|
105174
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105539
105175
|
children: [
|
|
105540
105176
|
" ",
|
|
105541
|
-
/* @__PURE__ */
|
|
105177
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105542
105178
|
color: "yellow",
|
|
105543
105179
|
children: "Esc"
|
|
105544
105180
|
}, undefined, false, undefined, this),
|
|
@@ -105547,28 +105183,28 @@ function HelpOverlay({ visible = false }) {
|
|
|
105547
105183
|
}, undefined, true, undefined, this)
|
|
105548
105184
|
]
|
|
105549
105185
|
}, undefined, true, undefined, this),
|
|
105550
|
-
/* @__PURE__ */
|
|
105186
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105551
105187
|
flexDirection: "column",
|
|
105552
105188
|
paddingBottom: 1,
|
|
105553
105189
|
children: [
|
|
105554
|
-
/* @__PURE__ */
|
|
105190
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105555
105191
|
dimColor: true,
|
|
105556
105192
|
children: "Agent Panel (when focused):"
|
|
105557
105193
|
}, undefined, false, undefined, this),
|
|
105558
|
-
/* @__PURE__ */
|
|
105194
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105559
105195
|
children: [
|
|
105560
105196
|
" ",
|
|
105561
|
-
/* @__PURE__ */
|
|
105197
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105562
105198
|
color: "yellow",
|
|
105563
105199
|
children: "Ctrl+]"
|
|
105564
105200
|
}, undefined, false, undefined, this),
|
|
105565
105201
|
" \u2014 Escape back to Stories panel"
|
|
105566
105202
|
]
|
|
105567
105203
|
}, undefined, true, undefined, this),
|
|
105568
|
-
/* @__PURE__ */
|
|
105204
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105569
105205
|
children: [
|
|
105570
105206
|
" ",
|
|
105571
|
-
/* @__PURE__ */
|
|
105207
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105572
105208
|
dimColor: true,
|
|
105573
105209
|
children: "All other keys"
|
|
105574
105210
|
}, undefined, false, undefined, this),
|
|
@@ -105577,16 +105213,16 @@ function HelpOverlay({ visible = false }) {
|
|
|
105577
105213
|
}, undefined, true, undefined, this)
|
|
105578
105214
|
]
|
|
105579
105215
|
}, undefined, true, undefined, this),
|
|
105580
|
-
/* @__PURE__ */
|
|
105216
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
105581
105217
|
justifyContent: "center",
|
|
105582
105218
|
paddingTop: 1,
|
|
105583
105219
|
borderTop: true,
|
|
105584
105220
|
borderColor: "gray",
|
|
105585
|
-
children: /* @__PURE__ */
|
|
105221
|
+
children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105586
105222
|
dimColor: true,
|
|
105587
105223
|
children: [
|
|
105588
105224
|
"Press ",
|
|
105589
|
-
/* @__PURE__ */
|
|
105225
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
105590
105226
|
color: "yellow",
|
|
105591
105227
|
children: "Esc"
|
|
105592
105228
|
}, undefined, false, undefined, this),
|
|
@@ -105598,46 +105234,289 @@ function HelpOverlay({ visible = false }) {
|
|
|
105598
105234
|
}, undefined, true, undefined, this);
|
|
105599
105235
|
}
|
|
105600
105236
|
|
|
105601
|
-
//
|
|
105602
|
-
var
|
|
105603
|
-
|
|
105604
|
-
|
|
105605
|
-
|
|
105606
|
-
|
|
105607
|
-
|
|
105608
|
-
|
|
105609
|
-
|
|
105610
|
-
|
|
105611
|
-
|
|
105612
|
-
}
|
|
105613
|
-
},
|
|
105614
|
-
|
|
105615
|
-
|
|
105616
|
-
|
|
105617
|
-
|
|
105618
|
-
|
|
105619
|
-
|
|
105620
|
-
|
|
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,
|
|
105621
105278
|
borderStyle: "single",
|
|
105622
|
-
borderColor
|
|
105623
|
-
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,
|
|
105624
105419
|
children: [
|
|
105625
|
-
/* @__PURE__ */
|
|
105420
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
105626
105421
|
bold: true,
|
|
105627
|
-
children:
|
|
105422
|
+
children: "Run complete"
|
|
105628
105423
|
}, undefined, false, undefined, this),
|
|
105629
|
-
/* @__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, {
|
|
105630
105439
|
dimColor: true,
|
|
105631
105440
|
children: [
|
|
105632
|
-
|
|
105633
|
-
|
|
105634
|
-
strategyInfo
|
|
105441
|
+
summary.skippedStories,
|
|
105442
|
+
" skipped"
|
|
105635
105443
|
]
|
|
105636
|
-
}, 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)
|
|
105637
105449
|
]
|
|
105638
105450
|
}, undefined, true, undefined, this)
|
|
105639
105451
|
}, undefined, false, undefined, this);
|
|
105640
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
|
+
}
|
|
105641
105520
|
|
|
105642
105521
|
// src/tui/components/StoriesPanel.tsx
|
|
105643
105522
|
var import_react31 = __toESM(require_react(), 1);
|
|
@@ -105702,13 +105581,7 @@ function getStatusIcon(status) {
|
|
|
105702
105581
|
return "\u23F8\uFE0F";
|
|
105703
105582
|
}
|
|
105704
105583
|
}
|
|
105705
|
-
function
|
|
105706
|
-
const totalSeconds = Math.floor(ms / 1000);
|
|
105707
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
105708
|
-
const seconds = totalSeconds % 60;
|
|
105709
|
-
return `${minutes}m ${seconds}s`;
|
|
105710
|
-
}
|
|
105711
|
-
function StoriesPanel({ stories, totalCost, elapsedMs, width, compact: compact2 = false, maxHeight }) {
|
|
105584
|
+
function StoriesPanel({ stories, width, compact: compact2 = false, maxHeight }) {
|
|
105712
105585
|
const maxVisible = compact2 ? COMPACT_MAX_VISIBLE_STORIES : MAX_VISIBLE_STORIES;
|
|
105713
105586
|
const needsScrolling = stories.length > maxVisible;
|
|
105714
105587
|
const [scrollOffset, setScrollOffset] = import_react31.useState(0);
|
|
@@ -105781,20 +105654,37 @@ function StoriesPanel({ stories, totalCost, elapsedMs, width, compact: compact2
|
|
|
105781
105654
|
}, undefined, true, undefined, this)
|
|
105782
105655
|
}, s.story.id, false, undefined, this);
|
|
105783
105656
|
}
|
|
105784
|
-
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;
|
|
105785
105661
|
return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
105786
|
-
|
|
105787
|
-
|
|
105788
|
-
|
|
105789
|
-
|
|
105790
|
-
|
|
105791
|
-
|
|
105792
|
-
|
|
105793
|
-
|
|
105794
|
-
|
|
105795
|
-
|
|
105796
|
-
|
|
105797
|
-
|
|
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);
|
|
105798
105688
|
})
|
|
105799
105689
|
}, undefined, false, undefined, this),
|
|
105800
105690
|
needsScrolling && canScrollDown && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
@@ -105807,50 +105697,7 @@ function StoriesPanel({ stories, totalCost, elapsedMs, width, compact: compact2
|
|
|
105807
105697
|
" more below"
|
|
105808
105698
|
]
|
|
105809
105699
|
}, undefined, true, undefined, this)
|
|
105810
|
-
}, undefined, false, undefined, this)
|
|
105811
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
105812
|
-
flexDirection: "column",
|
|
105813
|
-
paddingX: 1,
|
|
105814
|
-
paddingY: 1,
|
|
105815
|
-
borderStyle: "single",
|
|
105816
|
-
borderTop: true,
|
|
105817
|
-
borderColor: "gray",
|
|
105818
|
-
children: [
|
|
105819
|
-
!compact2 && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(jsx_dev_runtime5.Fragment, {
|
|
105820
|
-
children: [
|
|
105821
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105822
|
-
children: [
|
|
105823
|
-
"Cost: ",
|
|
105824
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105825
|
-
color: "green",
|
|
105826
|
-
children: [
|
|
105827
|
-
"$",
|
|
105828
|
-
totalCost.toFixed(4)
|
|
105829
|
-
]
|
|
105830
|
-
}, undefined, true, undefined, this)
|
|
105831
|
-
]
|
|
105832
|
-
}, undefined, true, undefined, this),
|
|
105833
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105834
|
-
children: [
|
|
105835
|
-
"Time: ",
|
|
105836
|
-
/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105837
|
-
color: "cyan",
|
|
105838
|
-
children: formatElapsedTime(elapsedMs)
|
|
105839
|
-
}, undefined, false, undefined, this)
|
|
105840
|
-
]
|
|
105841
|
-
}, undefined, true, undefined, this)
|
|
105842
|
-
]
|
|
105843
|
-
}, undefined, true, undefined, this),
|
|
105844
|
-
compact2 && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
|
|
105845
|
-
children: [
|
|
105846
|
-
"$",
|
|
105847
|
-
totalCost.toFixed(2),
|
|
105848
|
-
" \xB7 ",
|
|
105849
|
-
formatElapsedTime(elapsedMs)
|
|
105850
|
-
]
|
|
105851
|
-
}, undefined, true, undefined, this)
|
|
105852
|
-
]
|
|
105853
|
-
}, undefined, true, undefined, this)
|
|
105700
|
+
}, undefined, false, undefined, this)
|
|
105854
105701
|
]
|
|
105855
105702
|
}, undefined, true, undefined, this);
|
|
105856
105703
|
}
|
|
@@ -105879,7 +105726,8 @@ function useAgentStreamEvents(bus) {
|
|
|
105879
105726
|
thinkingUpdates: 0,
|
|
105880
105727
|
usageUpdates: 0,
|
|
105881
105728
|
toolCallUpdates: 0,
|
|
105882
|
-
status: "active"
|
|
105729
|
+
status: "active",
|
|
105730
|
+
model: event.model
|
|
105883
105731
|
});
|
|
105884
105732
|
break;
|
|
105885
105733
|
}
|
|
@@ -105922,7 +105770,8 @@ function useAgentStreamEvents(bus) {
|
|
|
105922
105770
|
next.set(event.callId, {
|
|
105923
105771
|
...state,
|
|
105924
105772
|
toolCallUpdates: state.toolCallUpdates + 1,
|
|
105925
|
-
lastActivityAt: event.timestamp
|
|
105773
|
+
lastActivityAt: event.timestamp,
|
|
105774
|
+
lastToolName: event.toolName
|
|
105926
105775
|
});
|
|
105927
105776
|
}
|
|
105928
105777
|
break;
|
|
@@ -105996,128 +105845,159 @@ function useKeyboard({ focus, currentStory, onAction, disabled = false }) {
|
|
|
105996
105845
|
});
|
|
105997
105846
|
}
|
|
105998
105847
|
|
|
105999
|
-
// src/tui/hooks/
|
|
105848
|
+
// src/tui/hooks/usePipelineBusEvents.ts
|
|
105849
|
+
init_pipeline();
|
|
106000
105850
|
var import_react33 = __toESM(require_react(), 1);
|
|
106001
|
-
function
|
|
105851
|
+
function usePipelineBusEvents(initialStories) {
|
|
106002
105852
|
const [state, setState] = import_react33.useState(() => ({
|
|
106003
|
-
stories: initialStories
|
|
106004
|
-
story,
|
|
106005
|
-
status: story.passes ? "passed" : "pending",
|
|
106006
|
-
routing: story.routing,
|
|
106007
|
-
cost: 0
|
|
106008
|
-
})),
|
|
105853
|
+
stories: initialStories,
|
|
106009
105854
|
totalCost: 0,
|
|
106010
|
-
elapsedMs: 0
|
|
105855
|
+
elapsedMs: 0,
|
|
105856
|
+
runPaused: false,
|
|
105857
|
+
runErrored: false,
|
|
105858
|
+
escalationLog: []
|
|
106011
105859
|
}));
|
|
106012
105860
|
const startTimeRef = import_react33.useRef(Date.now());
|
|
106013
105861
|
import_react33.useEffect(() => {
|
|
106014
105862
|
const startTime = startTimeRef.current;
|
|
106015
|
-
|
|
106016
|
-
const startTimer = () => {
|
|
106017
|
-
if (!timer) {
|
|
106018
|
-
timer = setInterval(() => {
|
|
106019
|
-
setState((prev) => ({
|
|
106020
|
-
...prev,
|
|
106021
|
-
elapsedMs: Date.now() - startTime
|
|
106022
|
-
}));
|
|
106023
|
-
}, 1000);
|
|
106024
|
-
}
|
|
106025
|
-
};
|
|
106026
|
-
const stopTimer = () => {
|
|
106027
|
-
if (timer) {
|
|
106028
|
-
clearInterval(timer);
|
|
106029
|
-
timer = null;
|
|
106030
|
-
}
|
|
106031
|
-
};
|
|
106032
|
-
const onStoryStart = (story) => {
|
|
106033
|
-
startTimer();
|
|
105863
|
+
const timer = setInterval(() => {
|
|
106034
105864
|
setState((prev) => ({
|
|
106035
105865
|
...prev,
|
|
106036
|
-
|
|
106037
|
-
stories: prev.stories.map((s) => s.story.id === story.id ? { ...s, status: "running" } : s)
|
|
105866
|
+
elapsedMs: Date.now() - startTime
|
|
106038
105867
|
}));
|
|
106039
|
-
};
|
|
106040
|
-
const
|
|
106041
|
-
|
|
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) => {
|
|
106042
105881
|
setState((prev) => {
|
|
106043
105882
|
const newStories = prev.stories.map((s) => {
|
|
106044
|
-
if (s.story.id ===
|
|
106045
|
-
|
|
106046
|
-
|
|
106047
|
-
status = "passed";
|
|
106048
|
-
} else if (result2.action === "fail") {
|
|
106049
|
-
status = "failed";
|
|
106050
|
-
} else if (result2.action === "skip") {
|
|
106051
|
-
status = "skipped";
|
|
106052
|
-
} else if (result2.action === "pause") {
|
|
106053
|
-
status = "paused";
|
|
106054
|
-
}
|
|
106055
|
-
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;
|
|
106056
105886
|
return { ...s, status, cost: storyCost };
|
|
106057
105887
|
}
|
|
106058
105888
|
return s;
|
|
106059
105889
|
});
|
|
106060
|
-
const totalCost = newStories.reduce((sum2, s) => sum2 + (s.cost
|
|
106061
|
-
return {
|
|
106062
|
-
...prev,
|
|
106063
|
-
stories: newStories,
|
|
106064
|
-
currentStory: undefined,
|
|
106065
|
-
totalCost
|
|
106066
|
-
};
|
|
105890
|
+
const totalCost = newStories.reduce((sum2, s) => sum2 + (s.cost ?? 0), 0);
|
|
105891
|
+
return { ...prev, stories: newStories, totalCost };
|
|
106067
105892
|
});
|
|
106068
|
-
};
|
|
106069
|
-
const
|
|
105893
|
+
});
|
|
105894
|
+
const unsubFailed = pipelineEventBus.on("story:failed", (event) => {
|
|
106070
105895
|
setState((prev) => ({
|
|
106071
105896
|
...prev,
|
|
106072
|
-
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)
|
|
106073
105902
|
}));
|
|
106074
|
-
};
|
|
106075
|
-
const
|
|
105903
|
+
});
|
|
105904
|
+
const unsubSkipped = pipelineEventBus.on("story:skipped", (event) => {
|
|
106076
105905
|
setState((prev) => ({
|
|
106077
105906
|
...prev,
|
|
106078
|
-
|
|
105907
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? { ...s, status: "skipped" } : s)
|
|
106079
105908
|
}));
|
|
106080
|
-
};
|
|
106081
|
-
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
|
+
};
|
|
106082
105917
|
setState((prev) => ({
|
|
106083
105918
|
...prev,
|
|
106084
|
-
|
|
106085
|
-
|
|
105919
|
+
stories: prev.stories.map((s) => s.story.id === event.storyId ? { ...s, status: "retrying" } : s),
|
|
105920
|
+
escalationLog: [...prev.escalationLog, entry]
|
|
106086
105921
|
}));
|
|
106087
|
-
};
|
|
106088
|
-
|
|
106089
|
-
|
|
106090
|
-
|
|
106091
|
-
|
|
106092
|
-
|
|
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
|
+
});
|
|
106093
105956
|
return () => {
|
|
106094
|
-
|
|
106095
|
-
|
|
106096
|
-
|
|
106097
|
-
|
|
106098
|
-
|
|
106099
|
-
|
|
105957
|
+
clearInterval(timer);
|
|
105958
|
+
unsubStarted();
|
|
105959
|
+
unsubCompleted();
|
|
105960
|
+
unsubFailed();
|
|
105961
|
+
unsubSkipped();
|
|
105962
|
+
unsubEscalated();
|
|
105963
|
+
unsubStoryPaused();
|
|
105964
|
+
unsubPaused();
|
|
105965
|
+
unsubResumed();
|
|
105966
|
+
unsubCompleted2();
|
|
105967
|
+
unsubErrored();
|
|
106100
105968
|
};
|
|
106101
|
-
}, [
|
|
105969
|
+
}, []);
|
|
106102
105970
|
return state;
|
|
106103
105971
|
}
|
|
106104
105972
|
|
|
106105
|
-
// src/tui/hooks/
|
|
105973
|
+
// src/tui/hooks/usePipelineEvents.ts
|
|
106106
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);
|
|
106107
105987
|
var MAX_PTY_BUFFER_LINES = 500;
|
|
106108
105988
|
var MAX_LINE_LENGTH = 1e4;
|
|
106109
105989
|
var PTY_FLUSH_INTERVAL_MS = 100;
|
|
106110
105990
|
function usePty(options) {
|
|
106111
|
-
const [state, setState] =
|
|
105991
|
+
const [state, setState] = import_react35.useState(() => ({
|
|
106112
105992
|
outputLines: [],
|
|
106113
105993
|
isRunning: false
|
|
106114
105994
|
}));
|
|
106115
|
-
const [handle, setHandle] =
|
|
105995
|
+
const [handle, setHandle] = import_react35.useState(null);
|
|
106116
105996
|
const command = options?.command;
|
|
106117
105997
|
const argsJson = JSON.stringify(options?.args);
|
|
106118
105998
|
const cwd2 = options?.cwd;
|
|
106119
105999
|
const envJson = JSON.stringify(options?.env);
|
|
106120
|
-
|
|
106000
|
+
import_react35.useEffect(() => {
|
|
106121
106001
|
if (!command) {
|
|
106122
106002
|
return;
|
|
106123
106003
|
}
|
|
@@ -106186,8 +106066,8 @@ function usePty(options) {
|
|
|
106186
106066
|
proc.kill();
|
|
106187
106067
|
};
|
|
106188
106068
|
}, [command, argsJson, cwd2, envJson]);
|
|
106189
|
-
const handleResize =
|
|
106190
|
-
|
|
106069
|
+
const handleResize = import_react35.useCallback((_cols, _rows) => {}, []);
|
|
106070
|
+
import_react35.useEffect(() => {
|
|
106191
106071
|
const onResize = () => {
|
|
106192
106072
|
const cols = process.stdout.columns ?? 80;
|
|
106193
106073
|
const rows = process.stdout.rows ?? 24;
|
|
@@ -106203,6 +106083,14 @@ function usePty(options) {
|
|
|
106203
106083
|
|
|
106204
106084
|
// src/tui/App.tsx
|
|
106205
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
|
+
}
|
|
106206
106094
|
function App2({
|
|
106207
106095
|
feature,
|
|
106208
106096
|
stories: initialStories,
|
|
@@ -106212,15 +106100,21 @@ function App2({
|
|
|
106212
106100
|
agentStreamEvents
|
|
106213
106101
|
}) {
|
|
106214
106102
|
const layout = useLayout();
|
|
106215
|
-
const
|
|
106103
|
+
const busState = usePipelineBusEvents(initialStories);
|
|
106104
|
+
const { currentStage } = usePipelineEvents(events);
|
|
106216
106105
|
const { exit } = use_app_default();
|
|
106217
|
-
const [focus, setFocus] =
|
|
106218
|
-
const [showHelp, setShowHelp] =
|
|
106219
|
-
const [showCost, setShowCost] =
|
|
106220
|
-
const [showQuitConfirm, setShowQuitConfirm] =
|
|
106221
|
-
const [showAbortConfirm, setShowAbortConfirm] =
|
|
106222
|
-
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);
|
|
106223
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;
|
|
106224
106118
|
const handleKeyboardAction = async (action) => {
|
|
106225
106119
|
switch (action.type) {
|
|
106226
106120
|
case "TOGGLE_FOCUS":
|
|
@@ -106242,7 +106136,7 @@ function App2({
|
|
|
106242
106136
|
setShowAbortConfirm(false);
|
|
106243
106137
|
break;
|
|
106244
106138
|
case "QUIT":
|
|
106245
|
-
if (
|
|
106139
|
+
if (currentRunningStory) {
|
|
106246
106140
|
setShowQuitConfirm(true);
|
|
106247
106141
|
} else {
|
|
106248
106142
|
exit();
|
|
@@ -106254,7 +106148,7 @@ function App2({
|
|
|
106254
106148
|
}
|
|
106255
106149
|
break;
|
|
106256
106150
|
case "ABORT":
|
|
106257
|
-
if (
|
|
106151
|
+
if (currentRunningStory) {
|
|
106258
106152
|
setShowAbortConfirm(true);
|
|
106259
106153
|
} else if (queueFilePath) {
|
|
106260
106154
|
await writeQueueCommand(queueFilePath, { type: "ABORT" });
|
|
@@ -106296,12 +106190,18 @@ function App2({
|
|
|
106296
106190
|
});
|
|
106297
106191
|
useKeyboard({
|
|
106298
106192
|
focus,
|
|
106299
|
-
currentStory:
|
|
106193
|
+
currentStory: currentRunningStory?.story,
|
|
106300
106194
|
onAction: handleKeyboardAction,
|
|
106301
106195
|
disabled: showQuitConfirm || showAbortConfirm
|
|
106302
106196
|
});
|
|
106303
|
-
const currentRouting = state.currentStory?.routing;
|
|
106304
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;
|
|
106305
106205
|
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106306
106206
|
flexDirection: "column",
|
|
106307
106207
|
height: "100%",
|
|
@@ -106311,22 +106211,29 @@ function App2({
|
|
|
106311
106211
|
borderStyle: "single",
|
|
106312
106212
|
borderBottom: true,
|
|
106313
106213
|
borderColor: "cyan",
|
|
106314
|
-
|
|
106315
|
-
|
|
106316
|
-
|
|
106317
|
-
|
|
106318
|
-
|
|
106319
|
-
|
|
106320
|
-
|
|
106321
|
-
|
|
106322
|
-
|
|
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),
|
|
106323
106230
|
isTooSmall && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106324
106231
|
paddingX: 1,
|
|
106325
106232
|
backgroundColor: "yellow",
|
|
106326
106233
|
children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106327
106234
|
color: "black",
|
|
106328
106235
|
children: [
|
|
106329
|
-
"
|
|
106236
|
+
"Terminal too narrow (",
|
|
106330
106237
|
layout.width,
|
|
106331
106238
|
" cols). Minimum ",
|
|
106332
106239
|
MIN_TERMINAL_WIDTH,
|
|
@@ -106339,33 +106246,36 @@ function App2({
|
|
|
106339
106246
|
flexGrow: 1,
|
|
106340
106247
|
children: [
|
|
106341
106248
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(StoriesPanel, {
|
|
106342
|
-
stories:
|
|
106343
|
-
totalCost: state.totalCost,
|
|
106344
|
-
elapsedMs: state.elapsedMs,
|
|
106249
|
+
stories: busState.stories,
|
|
106345
106250
|
width: layout.mode === "single" ? layout.width : layout.storiesPanelWidth,
|
|
106346
106251
|
compact: layout.mode === "single",
|
|
106347
|
-
maxHeight
|
|
106252
|
+
maxHeight
|
|
106348
106253
|
}, undefined, false, undefined, this),
|
|
106349
|
-
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(
|
|
106254
|
+
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(LiveActivityPanel, {
|
|
106350
106255
|
focused: focus === "agent" /* Agent */,
|
|
106351
|
-
|
|
106352
|
-
|
|
106256
|
+
activeCalls,
|
|
106257
|
+
runSummary: busState.runSummary,
|
|
106258
|
+
runErrored: runErroredForPanel,
|
|
106259
|
+
escalationLog: busState.escalationLog
|
|
106353
106260
|
}, undefined, false, undefined, this)
|
|
106354
106261
|
]
|
|
106355
106262
|
}, undefined, true, undefined, this),
|
|
106356
106263
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(StatusBar, {
|
|
106357
|
-
|
|
106358
|
-
|
|
106359
|
-
modelTier:
|
|
106360
|
-
|
|
106264
|
+
currentStage,
|
|
106265
|
+
currentStoryId: currentRunningStory?.story.id,
|
|
106266
|
+
modelTier: currentRunningStory?.modelTier,
|
|
106267
|
+
runPaused: busState.runPaused,
|
|
106268
|
+
runComplete: isRunComplete,
|
|
106269
|
+
isParallel,
|
|
106270
|
+
activeCount
|
|
106361
106271
|
}, undefined, false, undefined, this),
|
|
106362
106272
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(HelpOverlay, {
|
|
106363
106273
|
visible: showHelp
|
|
106364
106274
|
}, undefined, false, undefined, this),
|
|
106365
106275
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(CostOverlay, {
|
|
106366
106276
|
visible: showCost,
|
|
106367
|
-
stories:
|
|
106368
|
-
totalCost:
|
|
106277
|
+
stories: busState.stories,
|
|
106278
|
+
totalCost: busState.totalCost
|
|
106369
106279
|
}, undefined, false, undefined, this),
|
|
106370
106280
|
showQuitConfirm && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106371
106281
|
position: "absolute",
|
|
@@ -106383,7 +106293,7 @@ function App2({
|
|
|
106383
106293
|
children: [
|
|
106384
106294
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106385
106295
|
color: "yellow",
|
|
106386
|
-
children: "
|
|
106296
|
+
children: "Story is running. Quit anyway?"
|
|
106387
106297
|
}, undefined, false, undefined, this),
|
|
106388
106298
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106389
106299
|
paddingTop: 1,
|
|
@@ -106423,7 +106333,7 @@ function App2({
|
|
|
106423
106333
|
children: [
|
|
106424
106334
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
106425
106335
|
color: "red",
|
|
106426
|
-
children: "
|
|
106336
|
+
children: "Story is running. Abort anyway?"
|
|
106427
106337
|
}, undefined, false, undefined, this),
|
|
106428
106338
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
106429
106339
|
paddingTop: 1,
|
|
@@ -106512,8 +106422,8 @@ Next: nax generate --package ${options.package}`));
|
|
|
106512
106422
|
}
|
|
106513
106423
|
return;
|
|
106514
106424
|
}
|
|
106515
|
-
const naxDir =
|
|
106516
|
-
if (
|
|
106425
|
+
const naxDir = join83(workdir, ".nax");
|
|
106426
|
+
if (existsSync36(naxDir) && !options.force) {
|
|
106517
106427
|
console.log(source_default.yellow("nax already initialized. Use --force to overwrite."));
|
|
106518
106428
|
return;
|
|
106519
106429
|
}
|
|
@@ -106541,11 +106451,11 @@ Next: nax generate --package ${options.package}`));
|
|
|
106541
106451
|
}
|
|
106542
106452
|
}
|
|
106543
106453
|
}
|
|
106544
|
-
mkdirSync7(
|
|
106545
|
-
mkdirSync7(
|
|
106454
|
+
mkdirSync7(join83(naxDir, "features"), { recursive: true });
|
|
106455
|
+
mkdirSync7(join83(naxDir, "hooks"), { recursive: true });
|
|
106546
106456
|
const initConfig = options.name ? { ...DEFAULT_CONFIG, name: options.name } : DEFAULT_CONFIG;
|
|
106547
|
-
await Bun.write(
|
|
106548
|
-
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({
|
|
106549
106459
|
hooks: {
|
|
106550
106460
|
"on-start": { command: 'echo "nax started: $NAX_FEATURE"', enabled: false },
|
|
106551
106461
|
"on-complete": { command: 'echo "nax complete: $NAX_FEATURE"', enabled: false },
|
|
@@ -106553,12 +106463,12 @@ Next: nax generate --package ${options.package}`));
|
|
|
106553
106463
|
"on-error": { command: 'echo "nax error: $NAX_REASON"', enabled: false }
|
|
106554
106464
|
}
|
|
106555
106465
|
}, null, 2));
|
|
106556
|
-
await Bun.write(
|
|
106466
|
+
await Bun.write(join83(naxDir, ".gitignore"), `# nax temp files
|
|
106557
106467
|
*.tmp
|
|
106558
106468
|
.paused.json
|
|
106559
106469
|
.nax-verifier-verdict.json
|
|
106560
106470
|
`);
|
|
106561
|
-
await Bun.write(
|
|
106471
|
+
await Bun.write(join83(naxDir, "context.md"), `# Project Context
|
|
106562
106472
|
|
|
106563
106473
|
This document defines coding standards, architectural decisions, and forbidden patterns for this project.
|
|
106564
106474
|
Run \`nax generate\` to regenerate agent config files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) from this file.
|
|
@@ -106655,7 +106565,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106655
106565
|
console.error(source_default.red("Error: --plan requires --from <spec-path>"));
|
|
106656
106566
|
process.exit(1);
|
|
106657
106567
|
}
|
|
106658
|
-
if (options.from && !
|
|
106568
|
+
if (options.from && !existsSync36(options.from)) {
|
|
106659
106569
|
console.error(source_default.red(`Error: File not found: ${options.from} (required with --plan)`));
|
|
106660
106570
|
process.exit(1);
|
|
106661
106571
|
}
|
|
@@ -106688,10 +106598,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106688
106598
|
console.error(source_default.red("nax not initialized. Run: nax init"));
|
|
106689
106599
|
process.exit(1);
|
|
106690
106600
|
}
|
|
106691
|
-
const featureDir =
|
|
106692
|
-
const prdPath =
|
|
106601
|
+
const featureDir = join83(naxDir, "features", options.feature);
|
|
106602
|
+
const prdPath = join83(featureDir, "prd.json");
|
|
106693
106603
|
if (options.plan && options.from) {
|
|
106694
|
-
if (
|
|
106604
|
+
if (existsSync36(prdPath) && !options.force) {
|
|
106695
106605
|
console.error(source_default.red(`Error: prd.json already exists for feature "${options.feature}".`));
|
|
106696
106606
|
console.error(source_default.dim(" Use --force to overwrite, or run without --plan to use the existing PRD."));
|
|
106697
106607
|
process.exit(1);
|
|
@@ -106711,10 +106621,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106711
106621
|
}
|
|
106712
106622
|
}
|
|
106713
106623
|
try {
|
|
106714
|
-
const planLogDir =
|
|
106624
|
+
const planLogDir = join83(featureDir, "plan");
|
|
106715
106625
|
mkdirSync7(planLogDir, { recursive: true });
|
|
106716
106626
|
const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
|
|
106717
|
-
const planLogPath =
|
|
106627
|
+
const planLogPath = join83(planLogDir, `${planLogId}.jsonl`);
|
|
106718
106628
|
initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
|
|
106719
106629
|
console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
|
|
106720
106630
|
console.log(source_default.dim(" [Planning phase: generating PRD from spec]"));
|
|
@@ -106753,17 +106663,17 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106753
106663
|
process.exit(1);
|
|
106754
106664
|
}
|
|
106755
106665
|
}
|
|
106756
|
-
if (!
|
|
106666
|
+
if (!existsSync36(prdPath)) {
|
|
106757
106667
|
console.error(source_default.red(`Feature "${options.feature}" not found or missing prd.json`));
|
|
106758
106668
|
process.exit(1);
|
|
106759
106669
|
}
|
|
106760
106670
|
resetLogger();
|
|
106761
|
-
const projectKey = config2.name?.trim() ||
|
|
106671
|
+
const projectKey = config2.name?.trim() || basename16(workdir);
|
|
106762
106672
|
const outputDir = projectOutputDir(projectKey, config2.outputDir);
|
|
106763
|
-
const runsDir =
|
|
106673
|
+
const runsDir = join83(outputDir, "features", options.feature, "runs");
|
|
106764
106674
|
mkdirSync7(runsDir, { recursive: true });
|
|
106765
106675
|
const runId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
|
|
106766
|
-
const logFilePath =
|
|
106676
|
+
const logFilePath = join83(runsDir, `${runId}.jsonl`);
|
|
106767
106677
|
const isTTY = process.stdout.isTTY ?? false;
|
|
106768
106678
|
const headlessFlag = options.headless ?? false;
|
|
106769
106679
|
const headlessEnv = process.env.NAX_HEADLESS === "1";
|
|
@@ -106780,7 +106690,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106780
106690
|
config2.agent.default = options.agent;
|
|
106781
106691
|
}
|
|
106782
106692
|
config2.execution.maxIterations = Number.parseInt(options.maxIterations, 10);
|
|
106783
|
-
const globalNaxDir =
|
|
106693
|
+
const globalNaxDir = join83(homedir3(), ".nax");
|
|
106784
106694
|
const hooks = await loadHooksConfig(naxDir, globalNaxDir);
|
|
106785
106695
|
const eventEmitter = new PipelineEventEmitter;
|
|
106786
106696
|
let tuiInstance;
|
|
@@ -106795,15 +106705,13 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106795
106705
|
tuiInstance = renderTui({
|
|
106796
106706
|
feature: options.feature,
|
|
106797
106707
|
stories: initialStories,
|
|
106798
|
-
totalCost: 0,
|
|
106799
|
-
elapsedMs: 0,
|
|
106800
106708
|
events: eventEmitter,
|
|
106801
106709
|
ptyOptions: null
|
|
106802
106710
|
});
|
|
106803
106711
|
} else {
|
|
106804
106712
|
console.log(source_default.dim(" [Headless mode \u2014 pipe output]"));
|
|
106805
106713
|
}
|
|
106806
|
-
const statusFilePath =
|
|
106714
|
+
const statusFilePath = join83(outputDir, "status.json");
|
|
106807
106715
|
let parallel;
|
|
106808
106716
|
if (options.parallel !== undefined) {
|
|
106809
106717
|
parallel = Number.parseInt(options.parallel, 10);
|
|
@@ -106829,9 +106737,9 @@ program2.command("run").description("Run the orchestration loop for a feature").
|
|
|
106829
106737
|
headless: useHeadless,
|
|
106830
106738
|
skipPrecheck: options.skipPrecheck ?? false
|
|
106831
106739
|
});
|
|
106832
|
-
const latestSymlink =
|
|
106740
|
+
const latestSymlink = join83(runsDir, "latest.jsonl");
|
|
106833
106741
|
try {
|
|
106834
|
-
if (
|
|
106742
|
+
if (existsSync36(latestSymlink)) {
|
|
106835
106743
|
Bun.spawnSync(["rm", latestSymlink]);
|
|
106836
106744
|
}
|
|
106837
106745
|
Bun.spawnSync(["ln", "-s", `${runId}.jsonl`, latestSymlink], {
|
|
@@ -106890,9 +106798,9 @@ features.command("create <name>").description("Create a new feature").option("-d
|
|
|
106890
106798
|
console.error(source_default.red("nax not initialized. Run: nax init"));
|
|
106891
106799
|
process.exit(1);
|
|
106892
106800
|
}
|
|
106893
|
-
const featureDir =
|
|
106801
|
+
const featureDir = join83(naxDir, "features", name);
|
|
106894
106802
|
mkdirSync7(featureDir, { recursive: true });
|
|
106895
|
-
await Bun.write(
|
|
106803
|
+
await Bun.write(join83(featureDir, "spec.md"), `# Feature: ${name}
|
|
106896
106804
|
|
|
106897
106805
|
## Overview
|
|
106898
106806
|
|
|
@@ -106925,7 +106833,7 @@ features.command("create <name>").description("Create a new feature").option("-d
|
|
|
106925
106833
|
|
|
106926
106834
|
<!-- What this feature explicitly does NOT cover. -->
|
|
106927
106835
|
`);
|
|
106928
|
-
await Bun.write(
|
|
106836
|
+
await Bun.write(join83(featureDir, "progress.txt"), `# Progress: ${name}
|
|
106929
106837
|
|
|
106930
106838
|
Created: ${new Date().toISOString()}
|
|
106931
106839
|
|
|
@@ -106951,13 +106859,13 @@ features.command("list").description("List all features").option("-d, --dir <pat
|
|
|
106951
106859
|
console.error(source_default.red("nax not initialized."));
|
|
106952
106860
|
process.exit(1);
|
|
106953
106861
|
}
|
|
106954
|
-
const featuresDir =
|
|
106955
|
-
if (!
|
|
106862
|
+
const featuresDir = join83(naxDir, "features");
|
|
106863
|
+
if (!existsSync36(featuresDir)) {
|
|
106956
106864
|
console.log(source_default.dim("No features yet."));
|
|
106957
106865
|
return;
|
|
106958
106866
|
}
|
|
106959
|
-
const { readdirSync:
|
|
106960
|
-
const entries =
|
|
106867
|
+
const { readdirSync: readdirSync9 } = await import("fs");
|
|
106868
|
+
const entries = readdirSync9(featuresDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
106961
106869
|
if (entries.length === 0) {
|
|
106962
106870
|
console.log(source_default.dim("No features yet."));
|
|
106963
106871
|
return;
|
|
@@ -106966,8 +106874,8 @@ features.command("list").description("List all features").option("-d, --dir <pat
|
|
|
106966
106874
|
Features:
|
|
106967
106875
|
`));
|
|
106968
106876
|
for (const name of entries) {
|
|
106969
|
-
const prdPath =
|
|
106970
|
-
if (
|
|
106877
|
+
const prdPath = join83(featuresDir, name, "prd.json");
|
|
106878
|
+
if (existsSync36(prdPath)) {
|
|
106971
106879
|
const prd = await loadPRD(prdPath);
|
|
106972
106880
|
const c = countStories(prd);
|
|
106973
106881
|
console.log(` ${name} \u2014 ${c.passed}/${c.total} stories done`);
|
|
@@ -107001,10 +106909,10 @@ Use: nax plan -f <feature> --from <spec>`));
|
|
|
107001
106909
|
cliOverrides.profile = options.profile;
|
|
107002
106910
|
}
|
|
107003
106911
|
const config2 = await loadConfig(workdir, cliOverrides);
|
|
107004
|
-
const featureLogDir =
|
|
106912
|
+
const featureLogDir = join83(naxDir, "features", options.feature, "plan");
|
|
107005
106913
|
mkdirSync7(featureLogDir, { recursive: true });
|
|
107006
106914
|
const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
|
|
107007
|
-
const planLogPath =
|
|
106915
|
+
const planLogPath = join83(featureLogDir, `${planLogId}.jsonl`);
|
|
107008
106916
|
initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
|
|
107009
106917
|
console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
|
|
107010
106918
|
try {
|
|
@@ -107169,19 +107077,6 @@ program2.command("logs").description("Display run logs with filtering and follow
|
|
|
107169
107077
|
process.exit(1);
|
|
107170
107078
|
}
|
|
107171
107079
|
});
|
|
107172
|
-
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) => {
|
|
107173
|
-
try {
|
|
107174
|
-
await diagnose({
|
|
107175
|
-
feature: options.feature,
|
|
107176
|
-
workdir: options.dir,
|
|
107177
|
-
json: options.json,
|
|
107178
|
-
verbose: options.verbose
|
|
107179
|
-
});
|
|
107180
|
-
} catch (err) {
|
|
107181
|
-
console.error(source_default.red(`Error: ${err.message}`));
|
|
107182
|
-
process.exit(1);
|
|
107183
|
-
}
|
|
107184
|
-
});
|
|
107185
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) => {
|
|
107186
107081
|
try {
|
|
107187
107082
|
await precheckCommand({
|