@nathapp/nax 0.67.7 → 0.67.9
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 +236 -46
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -21312,7 +21312,7 @@ class AgentManager {
|
|
|
21312
21312
|
return { result, fallbacks, finalBundle: updatedBundle, finalPrompt, finalAgent: currentAgent };
|
|
21313
21313
|
}
|
|
21314
21314
|
const isFailStale = result.adapterFailure?.outcome === "fail-stale";
|
|
21315
|
-
const maxStaleRetries = this._config.agent?.idleWatchdog?.maxRetryAttempts ??
|
|
21315
|
+
const maxStaleRetries = this._config.agent?.idleWatchdog?.maxRetryAttempts ?? 3;
|
|
21316
21316
|
if (isFailStale && result.adapterFailure?.retriable && staleRetryAttempts < maxStaleRetries) {
|
|
21317
21317
|
staleRetryAttempts++;
|
|
21318
21318
|
const retryHop = {
|
|
@@ -21330,7 +21330,8 @@ class AgentManager {
|
|
|
21330
21330
|
logger?.info("agent-manager", "fail-stale: immediate same-agent retry", {
|
|
21331
21331
|
storyId: request.runOptions.storyId,
|
|
21332
21332
|
attempt: staleRetryAttempts,
|
|
21333
|
-
agent: currentAgent
|
|
21333
|
+
agent: currentAgent,
|
|
21334
|
+
reason: result.adapterFailure?.reason
|
|
21334
21335
|
});
|
|
21335
21336
|
currentHopKind = { kind: "stale-retry", attempt: staleRetryAttempts };
|
|
21336
21337
|
continue;
|
|
@@ -21461,6 +21462,8 @@ class AgentManager {
|
|
|
21461
21462
|
const primaryAgent = primaryAgentOverride ?? this.getDefault();
|
|
21462
21463
|
let currentAgent = primaryAgent;
|
|
21463
21464
|
let hopsSoFar = 0;
|
|
21465
|
+
let staleRetryAttempts = 0;
|
|
21466
|
+
const maxStaleRetries = this._config.agent?.idleWatchdog?.maxRetryAttempts ?? 3;
|
|
21464
21467
|
const _opStartMs = Date.now();
|
|
21465
21468
|
const _agentChain = [primaryAgent];
|
|
21466
21469
|
let _finalStatus = "error";
|
|
@@ -21497,10 +21500,45 @@ class AgentManager {
|
|
|
21497
21500
|
};
|
|
21498
21501
|
}
|
|
21499
21502
|
_totalCostUsd += result.estimatedCostUsd;
|
|
21503
|
+
if (!result.adapterFailure && !result.output?.trim()) {
|
|
21504
|
+
result = {
|
|
21505
|
+
...result,
|
|
21506
|
+
adapterFailure: {
|
|
21507
|
+
outcome: "fail-stale",
|
|
21508
|
+
category: "availability",
|
|
21509
|
+
retriable: true,
|
|
21510
|
+
message: "[completeWithFallback] agent returned no output",
|
|
21511
|
+
reason: "empty-output"
|
|
21512
|
+
}
|
|
21513
|
+
};
|
|
21514
|
+
}
|
|
21500
21515
|
if (!result.adapterFailure) {
|
|
21501
21516
|
_finalStatus = "ok";
|
|
21502
21517
|
return { result, fallbacks };
|
|
21503
21518
|
}
|
|
21519
|
+
const isFailStale = result.adapterFailure.outcome === "fail-stale";
|
|
21520
|
+
if (isFailStale && result.adapterFailure.retriable && staleRetryAttempts < maxStaleRetries) {
|
|
21521
|
+
staleRetryAttempts++;
|
|
21522
|
+
const retryHop = {
|
|
21523
|
+
storyId: options.storyId,
|
|
21524
|
+
priorAgent: currentAgent,
|
|
21525
|
+
newAgent: currentAgent,
|
|
21526
|
+
hop: staleRetryAttempts,
|
|
21527
|
+
outcome: result.adapterFailure.outcome,
|
|
21528
|
+
category: result.adapterFailure.category,
|
|
21529
|
+
timestamp: new Date().toISOString(),
|
|
21530
|
+
costUsd: result.estimatedCostUsd
|
|
21531
|
+
};
|
|
21532
|
+
fallbacks.push(retryHop);
|
|
21533
|
+
this._emitter.emit("onSwapAttempt", retryHop);
|
|
21534
|
+
logger?.info("agent-manager", "completeWithFallback: fail-stale same-agent retry", {
|
|
21535
|
+
storyId: options.storyId,
|
|
21536
|
+
attempt: staleRetryAttempts,
|
|
21537
|
+
agent: currentAgent,
|
|
21538
|
+
reason: result.adapterFailure.reason
|
|
21539
|
+
});
|
|
21540
|
+
continue;
|
|
21541
|
+
}
|
|
21504
21542
|
if (!this.shouldSwap(result.adapterFailure, hopsSoFar, true)) {
|
|
21505
21543
|
_finalStatus = hopsSoFar > 0 ? "exhausted" : "error";
|
|
21506
21544
|
return { result, fallbacks };
|
|
@@ -30343,18 +30381,19 @@ Schema: {"passed": boolean, "findings": [{"severity": string, "category": string
|
|
|
30343
30381
|
const line = opts.finding.verifiedBy?.line ?? opts.finding.line;
|
|
30344
30382
|
return `Your previous verifiedBy.observed value did not match the referenced file on disk.
|
|
30345
30383
|
|
|
30384
|
+
You MUST use your file-reading tool to open ${file3} and copy the actual bytes around line ${line}. Do NOT quote from memory or from the prior conversation \u2014 the previous quote was wrong precisely because it was not read from disk. If you reply without a file-read tool call, the quote will be rejected.
|
|
30385
|
+
|
|
30346
30386
|
Return ONLY this JSON object:
|
|
30347
30387
|
{"file":"${file3}","line":${line},"observed":"exact 1-3 line quote"}
|
|
30348
30388
|
|
|
30349
30389
|
Finding issue: ${opts.finding.issue}
|
|
30350
30390
|
Referenced file: ${file3}
|
|
30351
30391
|
Referenced line: ${line}
|
|
30352
|
-
Previous observed: ${opts.previousObserved}
|
|
30353
30392
|
|
|
30354
30393
|
Rules:
|
|
30355
|
-
-
|
|
30356
|
-
- observed must be a 1-3 line excerpt that proves the claim.
|
|
30357
|
-
- If you cannot
|
|
30394
|
+
- Read ${file3} with your file tool first. Then copy observed verbatim from the read result.
|
|
30395
|
+
- observed must be a 1-3 line excerpt that proves the claim, taken from at or near line ${line}.
|
|
30396
|
+
- If after reading the file you cannot find anything that proves the claim, set observed to "".
|
|
30358
30397
|
- Do not return a full review. Do not include markdown fences or explanation.`;
|
|
30359
30398
|
}
|
|
30360
30399
|
}
|
|
@@ -31813,7 +31852,20 @@ async function checkFindingEvidence(opts) {
|
|
|
31813
31852
|
const contents = await readSafeFile(opts.workdir, file3);
|
|
31814
31853
|
if (contents === null)
|
|
31815
31854
|
return { status: "unreadable", file: file3, line, observed };
|
|
31816
|
-
return
|
|
31855
|
+
return matchesEvidence(contents, observed, line) ? { status: "matched", file: file3, line, observed } : { status: "unmatched", file: file3, line, observed };
|
|
31856
|
+
}
|
|
31857
|
+
function matchesEvidence(contents, observed, line) {
|
|
31858
|
+
if (!line || line <= 0) {
|
|
31859
|
+
return normalizedIncludes(contents, observed);
|
|
31860
|
+
}
|
|
31861
|
+
const lines = contents.split(`
|
|
31862
|
+
`);
|
|
31863
|
+
const cited = Math.min(Math.max(0, line - 1), lines.length - 1);
|
|
31864
|
+
const start = Math.max(0, cited - EVIDENCE_LINE_WINDOW);
|
|
31865
|
+
const end = Math.min(lines.length, cited + EVIDENCE_LINE_WINDOW + 1);
|
|
31866
|
+
const windowText = lines.slice(start, end).join(`
|
|
31867
|
+
`);
|
|
31868
|
+
return normalizedIncludes(windowText, observed);
|
|
31817
31869
|
}
|
|
31818
31870
|
function downgradeUnsubstantiatedFinding(opts) {
|
|
31819
31871
|
_evidenceDeps.getLogger()?.warn("review", "Downgraded unsubstantiated review finding", {
|
|
@@ -31861,7 +31913,7 @@ function stripWrappingQuotes(text) {
|
|
|
31861
31913
|
function isMatchingWrapper(first, last) {
|
|
31862
31914
|
return first === "`" && last === "`" || first === `"` && last === `"` || first === "'" && last === "'";
|
|
31863
31915
|
}
|
|
31864
|
-
var OBSERVED_PREVIEW_CHARS = 160, ISSUE_PREVIEW_CHARS = 200, SEMANTIC_FINDING_DOWNGRADED_EVENT = "review.semantic.finding.downgraded", ADVERSARIAL_FINDING_DOWNGRADED_EVENT = "review.adversarial.finding.downgraded", _evidenceDeps;
|
|
31916
|
+
var OBSERVED_PREVIEW_CHARS = 160, ISSUE_PREVIEW_CHARS = 200, EVIDENCE_LINE_WINDOW = 10, SEMANTIC_FINDING_DOWNGRADED_EVENT = "review.semantic.finding.downgraded", ADVERSARIAL_FINDING_DOWNGRADED_EVENT = "review.adversarial.finding.downgraded", _evidenceDeps;
|
|
31865
31917
|
var init_semantic_evidence = __esm(() => {
|
|
31866
31918
|
init_logger2();
|
|
31867
31919
|
init_path_security2();
|
|
@@ -34951,6 +35003,53 @@ var init_acceptance_fix = __esm(() => {
|
|
|
34951
35003
|
};
|
|
34952
35004
|
});
|
|
34953
35005
|
|
|
35006
|
+
// src/review/requote-response.ts
|
|
35007
|
+
function parseRequoteResponse(output) {
|
|
35008
|
+
const parsed = tryParseLLMJson(output);
|
|
35009
|
+
if (!isRecord(parsed))
|
|
35010
|
+
return null;
|
|
35011
|
+
const canonical = extractCanonical(parsed);
|
|
35012
|
+
if (canonical)
|
|
35013
|
+
return canonical;
|
|
35014
|
+
const findings = parsed.findings;
|
|
35015
|
+
if (!Array.isArray(findings) || findings.length !== 1)
|
|
35016
|
+
return null;
|
|
35017
|
+
const finding = findings[0];
|
|
35018
|
+
if (!isRecord(finding))
|
|
35019
|
+
return null;
|
|
35020
|
+
return extractCanonical(finding.verifiedBy) ?? extractCanonical(finding);
|
|
35021
|
+
}
|
|
35022
|
+
function extractCanonical(value) {
|
|
35023
|
+
if (!isRecord(value))
|
|
35024
|
+
return null;
|
|
35025
|
+
if (typeof value.file !== "string" || typeof value.observed !== "string")
|
|
35026
|
+
return null;
|
|
35027
|
+
const file3 = value.file.trim();
|
|
35028
|
+
if (!file3)
|
|
35029
|
+
return null;
|
|
35030
|
+
const line = coerceLine(value.line);
|
|
35031
|
+
if (line === null)
|
|
35032
|
+
return null;
|
|
35033
|
+
return {
|
|
35034
|
+
file: file3,
|
|
35035
|
+
line: line === undefined ? undefined : line,
|
|
35036
|
+
observed: value.observed
|
|
35037
|
+
};
|
|
35038
|
+
}
|
|
35039
|
+
function coerceLine(value) {
|
|
35040
|
+
if (value == null)
|
|
35041
|
+
return;
|
|
35042
|
+
if (typeof value === "number")
|
|
35043
|
+
return value;
|
|
35044
|
+
if (typeof value === "string" && /^\d+$/.test(value))
|
|
35045
|
+
return Number.parseInt(value, 10);
|
|
35046
|
+
return null;
|
|
35047
|
+
}
|
|
35048
|
+
function isRecord(value) {
|
|
35049
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35050
|
+
}
|
|
35051
|
+
var init_requote_response = () => {};
|
|
35052
|
+
|
|
34954
35053
|
// src/operations/semantic-review.ts
|
|
34955
35054
|
async function requoteBlockingFindings(findings, ctx) {
|
|
34956
35055
|
const threshold = ctx.input.blockingThreshold ?? "error";
|
|
@@ -34972,7 +35071,7 @@ async function requoteBlockingFindings(findings, ctx) {
|
|
|
34972
35071
|
if (used >= maxRequotes)
|
|
34973
35072
|
break;
|
|
34974
35073
|
used += 1;
|
|
34975
|
-
const retry = await ctx.send(ReviewPromptBuilder.requoteVerbatim({ finding
|
|
35074
|
+
const retry = await ctx.send(ReviewPromptBuilder.requoteVerbatim({ finding }));
|
|
34976
35075
|
extraCostUsd += retry.estimatedCostUsd ?? 0;
|
|
34977
35076
|
const requote = parseRequoteResponse(retry.output);
|
|
34978
35077
|
if (!requote) {
|
|
@@ -35021,18 +35120,6 @@ async function requoteBlockingFindings(findings, ctx) {
|
|
|
35021
35120
|
}
|
|
35022
35121
|
return { findings: next, changed, extraCostUsd };
|
|
35023
35122
|
}
|
|
35024
|
-
function parseRequoteResponse(output) {
|
|
35025
|
-
const parsed = tryParseLLMJson(output);
|
|
35026
|
-
if (!parsed || typeof parsed.file !== "string" || typeof parsed.observed !== "string")
|
|
35027
|
-
return null;
|
|
35028
|
-
if (parsed.line != null && typeof parsed.line !== "number")
|
|
35029
|
-
return null;
|
|
35030
|
-
return {
|
|
35031
|
-
file: parsed.file,
|
|
35032
|
-
line: typeof parsed.line === "number" ? parsed.line : undefined,
|
|
35033
|
-
observed: parsed.observed
|
|
35034
|
-
};
|
|
35035
|
-
}
|
|
35036
35123
|
var FAIL_OPEN2, SEMANTIC_REQUOTE_RECOVERED_EVENT = "review.semantic.finding.requote_recovered", SEMANTIC_REQUOTE_FAILED_EVENT = "review.semantic.finding.requote_failed", DEFAULT_MAX_REQUOTES = 5, semanticReviewHopBody = async (initialPrompt, ctx) => {
|
|
35037
35124
|
const turn = await ctx.sendWithParseRetry(initialPrompt);
|
|
35038
35125
|
const parsed = validateLLMShape(tryParseLLMJson(turn.output));
|
|
@@ -35041,9 +35128,10 @@ var FAIL_OPEN2, SEMANTIC_REQUOTE_RECOVERED_EVENT = "review.semantic.finding.requ
|
|
|
35041
35128
|
const requoted = await requoteBlockingFindings(parsed.findings, ctx);
|
|
35042
35129
|
if (!requoted.changed)
|
|
35043
35130
|
return turn;
|
|
35131
|
+
const passed = !requoted.findings.some((finding) => isBlockingSeverity(finding.severity, ctx.input.blockingThreshold ?? "error"));
|
|
35044
35132
|
return {
|
|
35045
35133
|
...turn,
|
|
35046
|
-
output: JSON.stringify({ passed
|
|
35134
|
+
output: JSON.stringify({ passed, findings: requoted.findings }),
|
|
35047
35135
|
estimatedCostUsd: (turn.estimatedCostUsd ?? 0) + requoted.extraCostUsd
|
|
35048
35136
|
};
|
|
35049
35137
|
}, semanticReviewOp;
|
|
@@ -35052,6 +35140,7 @@ var init_semantic_review = __esm(() => {
|
|
|
35052
35140
|
init_config();
|
|
35053
35141
|
init_logger2();
|
|
35054
35142
|
init_prompts();
|
|
35143
|
+
init_requote_response();
|
|
35055
35144
|
init_semantic_evidence();
|
|
35056
35145
|
init_semantic_helpers();
|
|
35057
35146
|
FAIL_OPEN2 = { passed: true, findings: [], failOpen: true };
|
|
@@ -37259,14 +37348,45 @@ var init_full_suite_rectify = __esm(() => {
|
|
|
37259
37348
|
init_implement();
|
|
37260
37349
|
});
|
|
37261
37350
|
|
|
37351
|
+
// src/operations/_finding-to-check.ts
|
|
37352
|
+
function findingsToFailedChecks(findings) {
|
|
37353
|
+
const grouped = new Map;
|
|
37354
|
+
for (const finding of findings) {
|
|
37355
|
+
const check2 = SOURCE_TO_CHECK[finding.source];
|
|
37356
|
+
if (!check2)
|
|
37357
|
+
continue;
|
|
37358
|
+
const bucket = grouped.get(check2) ?? [];
|
|
37359
|
+
bucket.push(finding);
|
|
37360
|
+
grouped.set(check2, bucket);
|
|
37361
|
+
}
|
|
37362
|
+
return [...grouped.entries()].map(([check2, grpFindings]) => ({
|
|
37363
|
+
check: check2,
|
|
37364
|
+
success: false,
|
|
37365
|
+
command: "",
|
|
37366
|
+
exitCode: 1,
|
|
37367
|
+
output: "",
|
|
37368
|
+
durationMs: 0,
|
|
37369
|
+
findings: grpFindings
|
|
37370
|
+
}));
|
|
37371
|
+
}
|
|
37372
|
+
var SOURCE_TO_CHECK;
|
|
37373
|
+
var init__finding_to_check = __esm(() => {
|
|
37374
|
+
SOURCE_TO_CHECK = {
|
|
37375
|
+
"semantic-review": "semantic",
|
|
37376
|
+
"adversarial-review": "adversarial",
|
|
37377
|
+
lint: "lint",
|
|
37378
|
+
typecheck: "typecheck"
|
|
37379
|
+
};
|
|
37380
|
+
});
|
|
37381
|
+
|
|
37262
37382
|
// src/operations/autofix-implementer-strategy.ts
|
|
37263
37383
|
function makeAutofixImplementerStrategy(story) {
|
|
37264
37384
|
return {
|
|
37265
37385
|
name: "autofix-implementer",
|
|
37266
37386
|
appliesTo: (f) => f.fixTarget === "source" && IMPLEMENTER_SOURCES.has(f.source),
|
|
37267
37387
|
fixOp: implementerRectifyOp,
|
|
37268
|
-
buildInput: (
|
|
37269
|
-
failedChecks:
|
|
37388
|
+
buildInput: (findings, _prior, _cycleCtx) => ({
|
|
37389
|
+
failedChecks: findingsToFailedChecks(findings),
|
|
37270
37390
|
story
|
|
37271
37391
|
}),
|
|
37272
37392
|
extractApplied: (output) => ({
|
|
@@ -37279,6 +37399,7 @@ function makeAutofixImplementerStrategy(story) {
|
|
|
37279
37399
|
}
|
|
37280
37400
|
var IMPLEMENTER_SOURCES;
|
|
37281
37401
|
var init_autofix_implementer_strategy = __esm(() => {
|
|
37402
|
+
init__finding_to_check();
|
|
37282
37403
|
init_autofix_implementer();
|
|
37283
37404
|
IMPLEMENTER_SOURCES = new Set(["lint", "typecheck", "semantic-review"]);
|
|
37284
37405
|
});
|
|
@@ -37289,8 +37410,8 @@ function makeAutofixTestWriterStrategy(story, config2) {
|
|
|
37289
37410
|
name: "autofix-test-writer",
|
|
37290
37411
|
appliesTo: (f) => f.fixTarget === "test" || f.source === "adversarial-review",
|
|
37291
37412
|
fixOp: testWriterRectifyOp,
|
|
37292
|
-
buildInput: (
|
|
37293
|
-
failedChecks:
|
|
37413
|
+
buildInput: (findings, _prior, _cycleCtx) => ({
|
|
37414
|
+
failedChecks: findingsToFailedChecks(findings),
|
|
37294
37415
|
story,
|
|
37295
37416
|
blockingThreshold: config2.review?.blockingThreshold
|
|
37296
37417
|
}),
|
|
@@ -37299,6 +37420,7 @@ function makeAutofixTestWriterStrategy(story, config2) {
|
|
|
37299
37420
|
};
|
|
37300
37421
|
}
|
|
37301
37422
|
var init_autofix_test_writer_strategy = __esm(() => {
|
|
37423
|
+
init__finding_to_check();
|
|
37302
37424
|
init_autofix_test_writer();
|
|
37303
37425
|
});
|
|
37304
37426
|
|
|
@@ -37782,6 +37904,7 @@ var init_operations = __esm(() => {
|
|
|
37782
37904
|
init_full_suite_rectify();
|
|
37783
37905
|
init_autofix_implementer_strategy();
|
|
37784
37906
|
init_autofix_test_writer_strategy();
|
|
37907
|
+
init__finding_to_check();
|
|
37785
37908
|
init_mechanical_lintfix_strategy();
|
|
37786
37909
|
init_mechanical_formatfix_strategy();
|
|
37787
37910
|
init_lint_check();
|
|
@@ -37987,7 +38110,10 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
|
|
|
37987
38110
|
if (allExhausted) {
|
|
37988
38111
|
let liteFindingsAfter;
|
|
37989
38112
|
try {
|
|
37990
|
-
liteFindingsAfter = await cycle.validate(ctx, {
|
|
38113
|
+
liteFindingsAfter = await cycle.validate(ctx, {
|
|
38114
|
+
mode: "lite",
|
|
38115
|
+
strategiesRun: group.map((s) => s.name)
|
|
38116
|
+
});
|
|
37991
38117
|
} catch (err) {
|
|
37992
38118
|
const finishedAt3 = now();
|
|
37993
38119
|
cycle.iterations.push({
|
|
@@ -38059,7 +38185,7 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
|
|
|
38059
38185
|
let validatorAttempt = 0;
|
|
38060
38186
|
for (;; ) {
|
|
38061
38187
|
try {
|
|
38062
|
-
findingsAfter = await cycle.validate(ctx, { mode: "full" });
|
|
38188
|
+
findingsAfter = await cycle.validate(ctx, { mode: "full", strategiesRun: group.map((s) => s.name) });
|
|
38063
38189
|
break;
|
|
38064
38190
|
} catch (err) {
|
|
38065
38191
|
if (validatorAttempt >= cycle.config.validatorRetries) {
|
|
@@ -39743,6 +39869,7 @@ var init_review = __esm(() => {
|
|
|
39743
39869
|
init_diff_utils();
|
|
39744
39870
|
init_finding_projection();
|
|
39745
39871
|
init_runner2();
|
|
39872
|
+
init_requote_response();
|
|
39746
39873
|
init_severity();
|
|
39747
39874
|
});
|
|
39748
39875
|
|
|
@@ -41251,8 +41378,8 @@ var init_prompts = __esm(() => {
|
|
|
41251
41378
|
// src/operations/build-hop-callback.ts
|
|
41252
41379
|
function turnResultToAgentResult(r) {
|
|
41253
41380
|
return {
|
|
41254
|
-
success:
|
|
41255
|
-
exitCode: 0,
|
|
41381
|
+
success: !r.adapterFailure,
|
|
41382
|
+
exitCode: r.adapterFailure ? 1 : 0,
|
|
41256
41383
|
output: r.output,
|
|
41257
41384
|
rateLimited: false,
|
|
41258
41385
|
durationMs: 0,
|
|
@@ -41260,7 +41387,8 @@ function turnResultToAgentResult(r) {
|
|
|
41260
41387
|
exactCostUsd: r.exactCostUsd,
|
|
41261
41388
|
tokenUsage: r.tokenUsage,
|
|
41262
41389
|
protocolIds: r.protocolIds,
|
|
41263
|
-
internalRoundTrips: r.internalRoundTrips
|
|
41390
|
+
internalRoundTrips: r.internalRoundTrips,
|
|
41391
|
+
...r.adapterFailure ? { adapterFailure: r.adapterFailure } : {}
|
|
41264
41392
|
};
|
|
41265
41393
|
}
|
|
41266
41394
|
function buildHopCallback(ctx, sessionId, _initialOptions) {
|
|
@@ -41629,13 +41757,26 @@ async function callOp(ctx, op, input) {
|
|
|
41629
41757
|
let lastRetryTurn;
|
|
41630
41758
|
const sendWithFileOutput = async (promptText, bodyCtx) => {
|
|
41631
41759
|
const turn = await bodyCtx.send(promptText);
|
|
41632
|
-
|
|
41633
|
-
|
|
41634
|
-
|
|
41635
|
-
|
|
41636
|
-
|
|
41760
|
+
let effective = turn;
|
|
41761
|
+
if (fileOutputPath) {
|
|
41762
|
+
const fileContent = await _callOpDeps.readFileOutput(fileOutputPath);
|
|
41763
|
+
if (fileContent !== null) {
|
|
41764
|
+
effective = { ...turn, output: fileContent };
|
|
41765
|
+
}
|
|
41637
41766
|
}
|
|
41638
|
-
|
|
41767
|
+
if (!effective.output?.trim() && !effective.adapterFailure) {
|
|
41768
|
+
return {
|
|
41769
|
+
...effective,
|
|
41770
|
+
adapterFailure: {
|
|
41771
|
+
outcome: "fail-stale",
|
|
41772
|
+
category: "availability",
|
|
41773
|
+
retriable: true,
|
|
41774
|
+
message: `[${op.name}] agent returned no output`,
|
|
41775
|
+
reason: "empty-output"
|
|
41776
|
+
}
|
|
41777
|
+
};
|
|
41778
|
+
}
|
|
41779
|
+
return effective;
|
|
41639
41780
|
};
|
|
41640
41781
|
const sendWithParseRetry = async (initialPrompt, bodyCtx) => {
|
|
41641
41782
|
retryFallback = undefined;
|
|
@@ -43828,7 +43969,8 @@ class SessionManager {
|
|
|
43828
43969
|
category: "availability",
|
|
43829
43970
|
outcome: "fail-stale",
|
|
43830
43971
|
retriable: true,
|
|
43831
|
-
message: "idle watchdog cancelled session \u2014 no stream activity"
|
|
43972
|
+
message: "idle watchdog cancelled session \u2014 no stream activity",
|
|
43973
|
+
reason: "idle-watchdog"
|
|
43832
43974
|
});
|
|
43833
43975
|
}
|
|
43834
43976
|
}
|
|
@@ -51884,9 +52026,19 @@ function extractPhaseFindings(output) {
|
|
|
51884
52026
|
const success2 = "success" in record2 ? record2.success === true : ("passed" in record2) ? record2.passed === true : findings.length === 0;
|
|
51885
52027
|
return success2 ? [] : findings;
|
|
51886
52028
|
}
|
|
51887
|
-
function
|
|
52029
|
+
function shouldSkipPhaseForRectification(phase, state, phaseOutputs) {
|
|
52030
|
+
if (phase.kind !== "full-suite-gate")
|
|
52031
|
+
return false;
|
|
52032
|
+
const verifierName = state.verifier?.slot.op.name;
|
|
52033
|
+
if (!verifierName)
|
|
52034
|
+
return false;
|
|
52035
|
+
return phaseExplicitlyPassed(phaseOutputs[verifierName]);
|
|
52036
|
+
}
|
|
52037
|
+
function gatherRectificationFindings(phaseOutputs, phases, state) {
|
|
51888
52038
|
const findings = [];
|
|
51889
52039
|
for (const phase of phases) {
|
|
52040
|
+
if (shouldSkipPhaseForRectification(phase, state, phaseOutputs))
|
|
52041
|
+
continue;
|
|
51890
52042
|
findings.push(...extractPhaseFindings(phaseOutputs[phase.slot.op.name]));
|
|
51891
52043
|
}
|
|
51892
52044
|
return findings;
|
|
@@ -51902,6 +52054,21 @@ function collectRectificationPhases(state) {
|
|
|
51902
52054
|
state.adversarialReview
|
|
51903
52055
|
].filter((phase) => phase !== undefined);
|
|
51904
52056
|
}
|
|
52057
|
+
function phasesToRevalidate(strategiesRun, allPhases) {
|
|
52058
|
+
const sourceFiltered = allPhases.filter((p) => p.kind !== "verifier");
|
|
52059
|
+
if (!strategiesRun || strategiesRun.length === 0)
|
|
52060
|
+
return sourceFiltered;
|
|
52061
|
+
const unknown2 = strategiesRun.some((name) => STRATEGY_TO_REVALIDATION_PHASES[name] === undefined);
|
|
52062
|
+
if (unknown2)
|
|
52063
|
+
return sourceFiltered;
|
|
52064
|
+
const needed = new Set;
|
|
52065
|
+
for (const name of strategiesRun) {
|
|
52066
|
+
for (const kind of STRATEGY_TO_REVALIDATION_PHASES[name] ?? []) {
|
|
52067
|
+
needed.add(kind);
|
|
52068
|
+
}
|
|
52069
|
+
}
|
|
52070
|
+
return sourceFiltered.filter((p) => needed.has(p.kind));
|
|
52071
|
+
}
|
|
51905
52072
|
function toReviewDecisionPayload(opName, output) {
|
|
51906
52073
|
if (output === null || output === undefined || typeof output !== "object")
|
|
51907
52074
|
return null;
|
|
@@ -52057,7 +52224,7 @@ async function runRectification(ctx, state, phaseCosts, phaseOutputs) {
|
|
|
52057
52224
|
if (ctx.runtime.signal?.aborted) {
|
|
52058
52225
|
return {};
|
|
52059
52226
|
}
|
|
52060
|
-
const initialFindings = gatherRectificationFindings(phaseOutputs, validationPhases);
|
|
52227
|
+
const initialFindings = gatherRectificationFindings(phaseOutputs, validationPhases, state);
|
|
52061
52228
|
if (initialFindings.length === 0) {
|
|
52062
52229
|
return {};
|
|
52063
52230
|
}
|
|
@@ -52077,13 +52244,22 @@ async function runRectification(ctx, state, phaseCosts, phaseOutputs) {
|
|
|
52077
52244
|
validate: async (_validateCtx, opts) => {
|
|
52078
52245
|
if (ctx.runtime.signal?.aborted)
|
|
52079
52246
|
return [];
|
|
52080
|
-
const lite = opts?.mode === "lite";
|
|
52247
|
+
const lite = (opts?.mode ?? "full") === "lite";
|
|
52248
|
+
const phases = phasesToRevalidate(opts?.strategiesRun, validationPhases);
|
|
52249
|
+
getSafeLogger()?.debug("story-orchestrator", "rectification validate scope", {
|
|
52250
|
+
storyId: ctx.storyId,
|
|
52251
|
+
mode: opts?.mode ?? "full",
|
|
52252
|
+
strategiesRun: opts?.strategiesRun,
|
|
52253
|
+
phasesSelected: phases.map((p) => p.kind)
|
|
52254
|
+
});
|
|
52081
52255
|
const findings = [];
|
|
52082
|
-
for (const phase of
|
|
52256
|
+
for (const phase of phases) {
|
|
52083
52257
|
if (lite && phase.kind === "full-suite-gate") {
|
|
52084
52258
|
continue;
|
|
52085
52259
|
}
|
|
52086
52260
|
await runPhase(ctx, phase.slot, phaseCosts, phaseOutputs);
|
|
52261
|
+
if (shouldSkipPhaseForRectification(phase, state, phaseOutputs))
|
|
52262
|
+
continue;
|
|
52087
52263
|
findings.push(...extractPhaseFindings(phaseOutputs[phase.slot.op.name]));
|
|
52088
52264
|
}
|
|
52089
52265
|
return findings;
|
|
@@ -52230,7 +52406,7 @@ class StoryOrchestratorBuilder {
|
|
|
52230
52406
|
return new ExecutionPlan(ctx, { ...this.state }, opts.isThreeSession ?? false);
|
|
52231
52407
|
}
|
|
52232
52408
|
}
|
|
52233
|
-
var _storyOrchestratorDeps, TDD_OP_NAMES, CANONICAL_ORDER, PHASE_KIND_TO_STATE_KEY;
|
|
52409
|
+
var _storyOrchestratorDeps, TDD_OP_NAMES, CANONICAL_ORDER, PHASE_KIND_TO_STATE_KEY, STRATEGY_TO_REVALIDATION_PHASES;
|
|
52234
52410
|
var init_story_orchestrator = __esm(() => {
|
|
52235
52411
|
init_errors();
|
|
52236
52412
|
init_findings();
|
|
@@ -52268,6 +52444,20 @@ var init_story_orchestrator = __esm(() => {
|
|
|
52268
52444
|
"semantic-review": "semanticReview",
|
|
52269
52445
|
"adversarial-review": "adversarialReview"
|
|
52270
52446
|
};
|
|
52447
|
+
STRATEGY_TO_REVALIDATION_PHASES = {
|
|
52448
|
+
"mechanical-lintfix": ["lint-check"],
|
|
52449
|
+
"mechanical-formatfix": ["lint-check"],
|
|
52450
|
+
"autofix-implementer": [
|
|
52451
|
+
"lint-check",
|
|
52452
|
+
"typecheck-check",
|
|
52453
|
+
"full-suite-gate",
|
|
52454
|
+
"verify-scoped",
|
|
52455
|
+
"semantic-review",
|
|
52456
|
+
"adversarial-review"
|
|
52457
|
+
],
|
|
52458
|
+
"autofix-test-writer": ["lint-check", "typecheck-check", "full-suite-gate", "verify-scoped", "adversarial-review"],
|
|
52459
|
+
"full-suite-rectify": ["lint-check", "typecheck-check", "full-suite-gate", "verify-scoped", "semantic-review"]
|
|
52460
|
+
};
|
|
52271
52461
|
});
|
|
52272
52462
|
|
|
52273
52463
|
// src/execution/build-plan-for-strategy.ts
|
|
@@ -56753,7 +56943,7 @@ var package_default;
|
|
|
56753
56943
|
var init_package = __esm(() => {
|
|
56754
56944
|
package_default = {
|
|
56755
56945
|
name: "@nathapp/nax",
|
|
56756
|
-
version: "0.67.
|
|
56946
|
+
version: "0.67.9",
|
|
56757
56947
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
56758
56948
|
type: "module",
|
|
56759
56949
|
bin: {
|
|
@@ -56848,8 +57038,8 @@ var init_version = __esm(() => {
|
|
|
56848
57038
|
NAX_VERSION = package_default.version;
|
|
56849
57039
|
NAX_COMMIT = (() => {
|
|
56850
57040
|
try {
|
|
56851
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
56852
|
-
return "
|
|
57041
|
+
if (/^[0-9a-f]{6,10}$/.test("ab2db4bb"))
|
|
57042
|
+
return "ab2db4bb";
|
|
56853
57043
|
} catch {}
|
|
56854
57044
|
try {
|
|
56855
57045
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|