@nathapp/nax 0.75.5 → 0.75.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 +201 -101
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -17377,7 +17377,11 @@ var init_schemas_review = __esm(() => {
|
|
|
17377
17377
|
maxRequotes: 5
|
|
17378
17378
|
}),
|
|
17379
17379
|
excludePatterns: exports_external.array(exports_external.string()).optional(),
|
|
17380
|
-
demandInspectionTrail: exports_external.boolean().default(true)
|
|
17380
|
+
demandInspectionTrail: exports_external.boolean().default(true),
|
|
17381
|
+
recurrenceDemotion: exports_external.object({
|
|
17382
|
+
enabled: exports_external.boolean().default(false),
|
|
17383
|
+
maxBlockingRounds: exports_external.number().int().min(1).default(2)
|
|
17384
|
+
}).default({ enabled: false, maxBlockingRounds: 2 })
|
|
17381
17385
|
});
|
|
17382
17386
|
AdversarialReviewConfigSchema = exports_external.object({
|
|
17383
17387
|
model: ConfiguredModelSchema.default("balanced"),
|
|
@@ -17641,6 +17645,7 @@ var init_schemas3 = __esm(() => {
|
|
|
17641
17645
|
rules: [],
|
|
17642
17646
|
timeoutMs: 600000,
|
|
17643
17647
|
demandInspectionTrail: true,
|
|
17648
|
+
recurrenceDemotion: { enabled: false, maxBlockingRounds: 2 },
|
|
17644
17649
|
substantiation: {
|
|
17645
17650
|
requote: true,
|
|
17646
17651
|
maxRequotes: 5
|
|
@@ -21657,7 +21662,7 @@ class AcpAgentAdapter {
|
|
|
21657
21662
|
}
|
|
21658
21663
|
}
|
|
21659
21664
|
}
|
|
21660
|
-
var
|
|
21665
|
+
var INTERACTION_TIMEOUT_MS, AGENT_REGISTRY, DEFAULT_ENTRY, ACP_ADAPTER_NAMES;
|
|
21661
21666
|
var init_adapter = __esm(() => {
|
|
21662
21667
|
init_errors();
|
|
21663
21668
|
init_logger2();
|
|
@@ -22947,11 +22952,38 @@ var init_compose = __esm(() => {
|
|
|
22947
22952
|
|
|
22948
22953
|
// src/review/truncation.ts
|
|
22949
22954
|
function looksLikeTruncatedJson(raw) {
|
|
22950
|
-
|
|
22955
|
+
const text = raw.trimEnd();
|
|
22956
|
+
if (text.length === 0)
|
|
22957
|
+
return false;
|
|
22958
|
+
let depth = 0;
|
|
22959
|
+
let inString = false;
|
|
22960
|
+
let escaped = false;
|
|
22961
|
+
let opened = false;
|
|
22962
|
+
for (const ch of text) {
|
|
22963
|
+
if (escaped) {
|
|
22964
|
+
escaped = false;
|
|
22965
|
+
continue;
|
|
22966
|
+
}
|
|
22967
|
+
if (inString) {
|
|
22968
|
+
if (ch === "\\")
|
|
22969
|
+
escaped = true;
|
|
22970
|
+
else if (ch === '"')
|
|
22971
|
+
inString = false;
|
|
22972
|
+
continue;
|
|
22973
|
+
}
|
|
22974
|
+
if (ch === '"') {
|
|
22975
|
+
inString = true;
|
|
22976
|
+
continue;
|
|
22977
|
+
}
|
|
22978
|
+
if (ch === "{" || ch === "[") {
|
|
22979
|
+
depth++;
|
|
22980
|
+
opened = true;
|
|
22981
|
+
} else if (ch === "}" || ch === "]") {
|
|
22982
|
+
depth--;
|
|
22983
|
+
}
|
|
22984
|
+
}
|
|
22985
|
+
return opened && (inString || depth > 0);
|
|
22951
22986
|
}
|
|
22952
|
-
var init_truncation = __esm(() => {
|
|
22953
|
-
init_adapter();
|
|
22954
|
-
});
|
|
22955
22987
|
|
|
22956
22988
|
// src/utils/llm-json.ts
|
|
22957
22989
|
function extractJsonFromMarkdown(text) {
|
|
@@ -23094,9 +23126,9 @@ function makeParseRetryStrategy(opts) {
|
|
|
23094
23126
|
}
|
|
23095
23127
|
};
|
|
23096
23128
|
}
|
|
23129
|
+
var UNPARSED_PREVIEW_BYTES = 600;
|
|
23097
23130
|
var init_parse_retry = __esm(() => {
|
|
23098
23131
|
init_logger2();
|
|
23099
|
-
init_truncation();
|
|
23100
23132
|
init_types4();
|
|
23101
23133
|
});
|
|
23102
23134
|
|
|
@@ -23114,7 +23146,7 @@ function makeTieredParseRetryStrategy(opts) {
|
|
|
23114
23146
|
if (attempt >= opts.maxAttempts - 1) {
|
|
23115
23147
|
return { retry: false, fallback: opts.exhaustedFallback(inspection, ctx.lastOutput) };
|
|
23116
23148
|
}
|
|
23117
|
-
const isTruncated = ctx.lastOutput
|
|
23149
|
+
const isTruncated = looksLikeTruncatedJson(ctx.lastOutput);
|
|
23118
23150
|
const logger = opts._logger ?? getSafeLogger();
|
|
23119
23151
|
logger?.warn(opts.reviewerKind, `Parse retry \u2014 ${inspection.kind ?? "unknown"}`, {
|
|
23120
23152
|
storyId: ctx.storyId,
|
|
@@ -23128,7 +23160,6 @@ function makeTieredParseRetryStrategy(opts) {
|
|
|
23128
23160
|
}
|
|
23129
23161
|
var init_tiered_parse_retry = __esm(() => {
|
|
23130
23162
|
init_logger2();
|
|
23131
|
-
init_adapter();
|
|
23132
23163
|
init_types4();
|
|
23133
23164
|
});
|
|
23134
23165
|
|
|
@@ -36189,6 +36220,89 @@ var init_finding_filters = __esm(() => {
|
|
|
36189
36220
|
init_ac_quote_validator();
|
|
36190
36221
|
});
|
|
36191
36222
|
|
|
36223
|
+
// src/review/recurrence-demotion.ts
|
|
36224
|
+
function normalizeIssueText(s) {
|
|
36225
|
+
return s.replace(/`/g, "").replace(/\s+/g, " ").trim().toLowerCase().slice(0, MAX_ISSUE_PREFIX);
|
|
36226
|
+
}
|
|
36227
|
+
function normalizeFingerprintPath(file3) {
|
|
36228
|
+
return (file3 ?? "").replace(/\\/g, "/").replace(/^(?:\.{1,2}\/)+/, "");
|
|
36229
|
+
}
|
|
36230
|
+
function fingerprintFor(file3, category, text, acIndex) {
|
|
36231
|
+
const normFile = normalizeFingerprintPath(file3);
|
|
36232
|
+
if (typeof acIndex === "number" && Number.isInteger(acIndex) && acIndex >= 1) {
|
|
36233
|
+
return `${normFile}|ac${acIndex}`;
|
|
36234
|
+
}
|
|
36235
|
+
return `${normFile}|${category ?? ""}|${normalizeIssueText(text).slice(0, FP_ISSUE_PREFIX)}`;
|
|
36236
|
+
}
|
|
36237
|
+
function lookupPriorAppearance(priorCounts, finding) {
|
|
36238
|
+
const acKey = finding.acIndex === undefined ? undefined : priorCounts.get(fingerprintFor(finding.file, finding.category, finding.issue, finding.acIndex));
|
|
36239
|
+
const proseKey = priorCounts.get(fingerprintFor(finding.file, finding.category, finding.issue));
|
|
36240
|
+
if (!acKey)
|
|
36241
|
+
return proseKey;
|
|
36242
|
+
if (!proseKey)
|
|
36243
|
+
return acKey;
|
|
36244
|
+
return acKey.count >= proseKey.count ? acKey : proseKey;
|
|
36245
|
+
}
|
|
36246
|
+
function countPriorAppearances(priorIterations, source = "adversarial-review") {
|
|
36247
|
+
const counts = new Map;
|
|
36248
|
+
for (const it of priorIterations) {
|
|
36249
|
+
const seenThisIter = new Map;
|
|
36250
|
+
for (const f of it.findingsAfter ?? []) {
|
|
36251
|
+
if (f.source !== source)
|
|
36252
|
+
continue;
|
|
36253
|
+
const acIndex = typeof f.meta?.acIndex === "number" ? f.meta.acIndex : undefined;
|
|
36254
|
+
seenThisIter.set(fingerprintFor(f.file, f.category, f.message), f.severity);
|
|
36255
|
+
if (acIndex !== undefined) {
|
|
36256
|
+
seenThisIter.set(fingerprintFor(f.file, f.category, f.message, acIndex), f.severity);
|
|
36257
|
+
}
|
|
36258
|
+
}
|
|
36259
|
+
for (const [fp, sev] of seenThisIter) {
|
|
36260
|
+
const cur = counts.get(fp);
|
|
36261
|
+
counts.set(fp, { count: (cur?.count ?? 0) + 1, lastSeverity: sev });
|
|
36262
|
+
}
|
|
36263
|
+
}
|
|
36264
|
+
return counts;
|
|
36265
|
+
}
|
|
36266
|
+
function tagCoverageGap(findings) {
|
|
36267
|
+
return findings.map((f) => ({ ...f, meta: { ...f.meta ?? {}, coverageGap: true } }));
|
|
36268
|
+
}
|
|
36269
|
+
function classifyRecurrence(accepted, priorIterations, cfg, testFileMatch, threshold, source = "adversarial-review") {
|
|
36270
|
+
const blocking = [];
|
|
36271
|
+
const advisory = [];
|
|
36272
|
+
const demoted = [];
|
|
36273
|
+
if (!cfg.enabled) {
|
|
36274
|
+
for (const f of accepted)
|
|
36275
|
+
(isBlockingSeverity(f.severity, threshold) ? blocking : advisory).push(f);
|
|
36276
|
+
return { blocking, advisory, demoted };
|
|
36277
|
+
}
|
|
36278
|
+
const priorCounts = countPriorAppearances(priorIterations, source);
|
|
36279
|
+
for (const f of accepted) {
|
|
36280
|
+
if (f.category === "test-gap" && testFileMatch(f.file) && isBlockingSeverity(f.severity, threshold)) {
|
|
36281
|
+
blocking.push(f);
|
|
36282
|
+
continue;
|
|
36283
|
+
}
|
|
36284
|
+
if (!isBlockingSeverity(f.severity, threshold)) {
|
|
36285
|
+
advisory.push(f);
|
|
36286
|
+
continue;
|
|
36287
|
+
}
|
|
36288
|
+
const prior = lookupPriorAppearance(priorCounts, f);
|
|
36289
|
+
const n = (prior?.count ?? 0) + 1;
|
|
36290
|
+
const prevWasBlocking = prior !== undefined && isBlockingSeverity(prior.lastSeverity, threshold);
|
|
36291
|
+
if (n >= cfg.maxBlockingRounds + 1) {
|
|
36292
|
+
demoted.push(f);
|
|
36293
|
+
} else if (n === 1 || prevWasBlocking) {
|
|
36294
|
+
blocking.push(f);
|
|
36295
|
+
} else {
|
|
36296
|
+
advisory.push(f);
|
|
36297
|
+
}
|
|
36298
|
+
}
|
|
36299
|
+
return { blocking, advisory, demoted };
|
|
36300
|
+
}
|
|
36301
|
+
var MAX_ISSUE_PREFIX = 160, FP_ISSUE_PREFIX = 48;
|
|
36302
|
+
var init_recurrence_demotion = __esm(() => {
|
|
36303
|
+
init_adversarial_helpers();
|
|
36304
|
+
});
|
|
36305
|
+
|
|
36192
36306
|
// src/review/requote-response.ts
|
|
36193
36307
|
function parseRequoteResponse(output) {
|
|
36194
36308
|
const parsed = tryParseLLMJson(output);
|
|
@@ -36236,6 +36350,17 @@ function isRecord(value) {
|
|
|
36236
36350
|
}
|
|
36237
36351
|
var init_requote_response = () => {};
|
|
36238
36352
|
|
|
36353
|
+
// src/operations/_review-fallback.ts
|
|
36354
|
+
function reviewExhaustedFallback(lastOutput, failOpen) {
|
|
36355
|
+
const unparsedPreview = previewOutput(lastOutput, UNPARSED_PREVIEW_BYTES);
|
|
36356
|
+
if (!/"passed"\s*:\s*false/.test(lastOutput))
|
|
36357
|
+
return { ...failOpen, unparsedPreview };
|
|
36358
|
+
return { ...failOpen, passed: false, failOpen: false, looksLikeFail: true, unparsedPreview };
|
|
36359
|
+
}
|
|
36360
|
+
var init__review_fallback = __esm(() => {
|
|
36361
|
+
init_retry();
|
|
36362
|
+
});
|
|
36363
|
+
|
|
36239
36364
|
// src/operations/semantic-review.ts
|
|
36240
36365
|
function withRepromptMarker(output, info) {
|
|
36241
36366
|
const parsed = tryParseLLMJson(output);
|
|
@@ -36454,7 +36579,9 @@ var init_semantic_review = __esm(() => {
|
|
|
36454
36579
|
init_logger2();
|
|
36455
36580
|
init_prompts();
|
|
36456
36581
|
init_finding_filters();
|
|
36582
|
+
init_recurrence_demotion();
|
|
36457
36583
|
init_requote_response();
|
|
36584
|
+
init__review_fallback();
|
|
36458
36585
|
FAIL_OPEN = {
|
|
36459
36586
|
passed: true,
|
|
36460
36587
|
findings: [],
|
|
@@ -36478,7 +36605,8 @@ var init_semantic_review = __esm(() => {
|
|
|
36478
36605
|
invalid: () => ReviewPromptBuilder.jsonRetry(),
|
|
36479
36606
|
truncated: () => ReviewPromptBuilder.jsonRetryCondensed({ blockingThreshold: input.blockingThreshold })
|
|
36480
36607
|
},
|
|
36481
|
-
exhaustedFallback: (lastOutput) =>
|
|
36608
|
+
exhaustedFallback: (lastOutput) => reviewExhaustedFallback(lastOutput, FAIL_OPEN),
|
|
36609
|
+
outputPreviewBytes: UNPARSED_PREVIEW_BYTES,
|
|
36482
36610
|
logContext: { blockingThreshold: input.blockingThreshold ?? "error" }
|
|
36483
36611
|
}),
|
|
36484
36612
|
hopBody: semanticReviewHopBody,
|
|
@@ -36510,6 +36638,7 @@ var init_semantic_review = __esm(() => {
|
|
|
36510
36638
|
repromptEvent
|
|
36511
36639
|
};
|
|
36512
36640
|
}
|
|
36641
|
+
const unparsedPreview = previewOutput(output, UNPARSED_PREVIEW_BYTES);
|
|
36513
36642
|
if (/"passed"\s*:\s*false/.test(output)) {
|
|
36514
36643
|
return {
|
|
36515
36644
|
passed: false,
|
|
@@ -36517,10 +36646,11 @@ var init_semantic_review = __esm(() => {
|
|
|
36517
36646
|
normalizedFindings: [],
|
|
36518
36647
|
acDropped: [],
|
|
36519
36648
|
looksLikeFail: true,
|
|
36649
|
+
unparsedPreview,
|
|
36520
36650
|
repromptEvent
|
|
36521
36651
|
};
|
|
36522
36652
|
}
|
|
36523
|
-
return FAIL_OPEN;
|
|
36653
|
+
return { ...FAIL_OPEN, unparsedPreview };
|
|
36524
36654
|
},
|
|
36525
36655
|
async verify(parsed, input, _verifyCtx) {
|
|
36526
36656
|
if (parsed.failOpen || parsed.looksLikeFail)
|
|
@@ -36532,84 +36662,30 @@ var init_semantic_review = __esm(() => {
|
|
|
36532
36662
|
const sanitized = sanitizeRefModeFindings(findings, input.mode, threshold);
|
|
36533
36663
|
const substantiated = await substantiateSemanticEvidence(sanitized, input.mode, input.workdir, input.story.id, threshold, input.repoRoot);
|
|
36534
36664
|
const { accepted, dropped } = filterByAcGroundingMinimal(substantiated, input.story.acceptanceCriteria);
|
|
36535
|
-
const
|
|
36665
|
+
const isTestFile3 = semanticTestFileMatch(input);
|
|
36666
|
+
const recurrenceCfg = input.semanticConfig.recurrenceDemotion ?? { enabled: false, maxBlockingRounds: 2 };
|
|
36667
|
+
const {
|
|
36668
|
+
blocking,
|
|
36669
|
+
advisory: subThreshold,
|
|
36670
|
+
demoted
|
|
36671
|
+
} = classifyRecurrence(accepted, input.priorSemanticIterations ?? [], recurrenceCfg, isTestFile3, threshold, "semantic-review");
|
|
36672
|
+
const advisoryFindings = [
|
|
36673
|
+
...toReviewFindings(subThreshold.filter((f) => isBlockingSeverity(f.severity, threshold)), { isTestFile: isTestFile3 }),
|
|
36674
|
+
...tagCoverageGap(toReviewFindings(demoted, { isTestFile: isTestFile3 }))
|
|
36675
|
+
];
|
|
36536
36676
|
const passed = blocking.length === 0 && (parsed.passed || accepted.length > 0);
|
|
36537
36677
|
return {
|
|
36538
36678
|
...parsed,
|
|
36539
36679
|
passed,
|
|
36540
36680
|
findings: accepted,
|
|
36541
|
-
normalizedFindings: toReviewFindings(blocking, { isTestFile:
|
|
36681
|
+
normalizedFindings: toReviewFindings(blocking, { isTestFile: isTestFile3 }),
|
|
36682
|
+
advisoryFindings,
|
|
36542
36683
|
acDropped: dropped
|
|
36543
36684
|
};
|
|
36544
36685
|
}
|
|
36545
36686
|
};
|
|
36546
36687
|
});
|
|
36547
36688
|
|
|
36548
|
-
// src/review/recurrence-demotion.ts
|
|
36549
|
-
function normalizeIssueText(s) {
|
|
36550
|
-
return s.replace(/`/g, "").replace(/\s+/g, " ").trim().toLowerCase().slice(0, MAX_ISSUE_PREFIX);
|
|
36551
|
-
}
|
|
36552
|
-
function fingerprintFor(file3, category, text) {
|
|
36553
|
-
const normFile = (file3 ?? "").replace(/\\/g, "/");
|
|
36554
|
-
return `${normFile}|${category ?? ""}|${normalizeIssueText(text).slice(0, FP_ISSUE_PREFIX)}`;
|
|
36555
|
-
}
|
|
36556
|
-
function countPriorAppearances(priorIterations) {
|
|
36557
|
-
const counts = new Map;
|
|
36558
|
-
for (const it of priorIterations) {
|
|
36559
|
-
const seenThisIter = new Map;
|
|
36560
|
-
for (const f of it.findingsAfter ?? []) {
|
|
36561
|
-
if (f.source !== "adversarial-review")
|
|
36562
|
-
continue;
|
|
36563
|
-
const fp = fingerprintFor(f.file, f.category, f.message);
|
|
36564
|
-
seenThisIter.set(fp, f.severity);
|
|
36565
|
-
}
|
|
36566
|
-
for (const [fp, sev] of seenThisIter) {
|
|
36567
|
-
const cur = counts.get(fp);
|
|
36568
|
-
counts.set(fp, { count: (cur?.count ?? 0) + 1, lastSeverity: sev });
|
|
36569
|
-
}
|
|
36570
|
-
}
|
|
36571
|
-
return counts;
|
|
36572
|
-
}
|
|
36573
|
-
function tagCoverageGap(findings) {
|
|
36574
|
-
return findings.map((f) => ({ ...f, meta: { ...f.meta ?? {}, coverageGap: true } }));
|
|
36575
|
-
}
|
|
36576
|
-
function classifyRecurrence(accepted, priorIterations, cfg, testFileMatch, threshold) {
|
|
36577
|
-
const blocking = [];
|
|
36578
|
-
const advisory = [];
|
|
36579
|
-
const demoted = [];
|
|
36580
|
-
if (!cfg.enabled) {
|
|
36581
|
-
for (const f of accepted)
|
|
36582
|
-
(isBlockingSeverity(f.severity, threshold) ? blocking : advisory).push(f);
|
|
36583
|
-
return { blocking, advisory, demoted };
|
|
36584
|
-
}
|
|
36585
|
-
const priorCounts = countPriorAppearances(priorIterations);
|
|
36586
|
-
for (const f of accepted) {
|
|
36587
|
-
if (f.category === "test-gap" && testFileMatch(f.file) && isBlockingSeverity(f.severity, threshold)) {
|
|
36588
|
-
blocking.push(f);
|
|
36589
|
-
continue;
|
|
36590
|
-
}
|
|
36591
|
-
if (!isBlockingSeverity(f.severity, threshold)) {
|
|
36592
|
-
advisory.push(f);
|
|
36593
|
-
continue;
|
|
36594
|
-
}
|
|
36595
|
-
const prior = priorCounts.get(fingerprintFor(f.file, f.category, f.issue));
|
|
36596
|
-
const n = (prior?.count ?? 0) + 1;
|
|
36597
|
-
const prevWasBlocking = prior !== undefined && isBlockingSeverity(prior.lastSeverity, threshold);
|
|
36598
|
-
if (n >= cfg.maxBlockingRounds + 1) {
|
|
36599
|
-
demoted.push(f);
|
|
36600
|
-
} else if (n === 1 || prevWasBlocking) {
|
|
36601
|
-
blocking.push(f);
|
|
36602
|
-
} else {
|
|
36603
|
-
advisory.push(f);
|
|
36604
|
-
}
|
|
36605
|
-
}
|
|
36606
|
-
return { blocking, advisory, demoted };
|
|
36607
|
-
}
|
|
36608
|
-
var MAX_ISSUE_PREFIX = 160, FP_ISSUE_PREFIX = 48;
|
|
36609
|
-
var init_recurrence_demotion = __esm(() => {
|
|
36610
|
-
init_adversarial_helpers();
|
|
36611
|
-
});
|
|
36612
|
-
|
|
36613
36689
|
// src/operations/adversarial-review.ts
|
|
36614
36690
|
function withRepromptMarker2(output, info) {
|
|
36615
36691
|
const parsed = tryParseLLMJson(output);
|
|
@@ -36794,7 +36870,8 @@ var FAIL_OPEN2, ADVERSARIAL_REQUOTE_RECOVERED_EVENT = "review.adversarial.findin
|
|
|
36794
36870
|
invalid: () => ReviewPromptBuilder.jsonRetry(),
|
|
36795
36871
|
truncated: () => ReviewPromptBuilder.jsonRetryCondensed({ blockingThreshold: input.blockingThreshold })
|
|
36796
36872
|
},
|
|
36797
|
-
exhaustedFallback: (lastOutput) =>
|
|
36873
|
+
exhaustedFallback: (lastOutput) => reviewExhaustedFallback(lastOutput, FAIL_OPEN2),
|
|
36874
|
+
outputPreviewBytes: UNPARSED_PREVIEW_BYTES,
|
|
36798
36875
|
logContext: { blockingThreshold: input.blockingThreshold ?? "error" }
|
|
36799
36876
|
}), adversarialReviewOp;
|
|
36800
36877
|
var init_adversarial_review = __esm(() => {
|
|
@@ -36806,6 +36883,7 @@ var init_adversarial_review = __esm(() => {
|
|
|
36806
36883
|
init_finding_filters();
|
|
36807
36884
|
init_recurrence_demotion();
|
|
36808
36885
|
init_requote_response();
|
|
36886
|
+
init__review_fallback();
|
|
36809
36887
|
FAIL_OPEN2 = {
|
|
36810
36888
|
passed: true,
|
|
36811
36889
|
findings: [],
|
|
@@ -38726,7 +38804,6 @@ var init_ground = __esm(() => {
|
|
|
38726
38804
|
init_errors();
|
|
38727
38805
|
init_logger2();
|
|
38728
38806
|
init_prompts();
|
|
38729
|
-
init_truncation();
|
|
38730
38807
|
groundOp = {
|
|
38731
38808
|
kind: "run",
|
|
38732
38809
|
name: "ground",
|
|
@@ -42163,11 +42240,11 @@ var init_findings = __esm(() => {
|
|
|
42163
42240
|
init_cycle();
|
|
42164
42241
|
});
|
|
42165
42242
|
|
|
42166
|
-
// src/review/
|
|
42167
|
-
function
|
|
42243
|
+
// src/review/review-iteration-store.ts
|
|
42244
|
+
function getReviewIterations(store, storyId) {
|
|
42168
42245
|
return store.get(storyId) ?? [];
|
|
42169
42246
|
}
|
|
42170
|
-
function
|
|
42247
|
+
function recordReviewIteration(store, storyId, roundFindings) {
|
|
42171
42248
|
const prior = store.get(storyId) ?? [];
|
|
42172
42249
|
const findingsBefore = prior.length > 0 ? prior[prior.length - 1].findingsAfter : [];
|
|
42173
42250
|
const findingsAfter = [...roundFindings];
|
|
@@ -42183,7 +42260,7 @@ function recordAdversarialIteration(store, storyId, roundFindings) {
|
|
|
42183
42260
|
};
|
|
42184
42261
|
store.set(storyId, [...prior, iteration]);
|
|
42185
42262
|
}
|
|
42186
|
-
var
|
|
42263
|
+
var init_review_iteration_store = __esm(() => {
|
|
42187
42264
|
init_findings();
|
|
42188
42265
|
});
|
|
42189
42266
|
|
|
@@ -42626,7 +42703,7 @@ var package_default;
|
|
|
42626
42703
|
var init_package = __esm(() => {
|
|
42627
42704
|
package_default = {
|
|
42628
42705
|
name: "@nathapp/nax",
|
|
42629
|
-
version: "0.75.
|
|
42706
|
+
version: "0.75.6",
|
|
42630
42707
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
42631
42708
|
type: "module",
|
|
42632
42709
|
bin: {
|
|
@@ -42730,8 +42807,8 @@ var init_version = __esm(() => {
|
|
|
42730
42807
|
NAX_VERSION = package_default.version;
|
|
42731
42808
|
NAX_COMMIT = (() => {
|
|
42732
42809
|
try {
|
|
42733
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
42734
|
-
return "
|
|
42810
|
+
if (/^[0-9a-f]{6,10}$/.test("064f9083"))
|
|
42811
|
+
return "064f9083";
|
|
42735
42812
|
} catch {}
|
|
42736
42813
|
try {
|
|
42737
42814
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -42778,6 +42855,8 @@ function toPersistedEntry(entry, epochMs) {
|
|
|
42778
42855
|
blockingThreshold: entry.blockingThreshold ?? "error",
|
|
42779
42856
|
result: entry.result,
|
|
42780
42857
|
advisoryFindings: entry.advisoryFindings ?? null,
|
|
42858
|
+
acDropped: entry.acDropped ?? null,
|
|
42859
|
+
...entry.parsed ? {} : { unparsedPreview: entry.unparsedPreview ?? null },
|
|
42781
42860
|
diffAvailable: entry.diffAvailable ?? null,
|
|
42782
42861
|
adversarialDropAnalysis: entry.adversarialDropAnalysis ?? null,
|
|
42783
42862
|
adversarialAcceptAnalysis: entry.adversarialAcceptAnalysis ?? null
|
|
@@ -44749,7 +44828,7 @@ var init_review = __esm(() => {
|
|
|
44749
44828
|
init_category_fix_target();
|
|
44750
44829
|
init_finding_filters();
|
|
44751
44830
|
init_ac_quote_validator();
|
|
44752
|
-
|
|
44831
|
+
init_review_iteration_store();
|
|
44753
44832
|
init_ac_structural_counterfactual();
|
|
44754
44833
|
init_adversarial();
|
|
44755
44834
|
init_semantic_evidence();
|
|
@@ -48172,6 +48251,8 @@ function attachReviewAuditSubscriber(bus, auditor, runId) {
|
|
|
48172
48251
|
blockingThreshold: event.blockingThreshold,
|
|
48173
48252
|
result: event.result,
|
|
48174
48253
|
advisoryFindings: event.advisoryFindings,
|
|
48254
|
+
acDropped: event.acDropped ? [...event.acDropped] : undefined,
|
|
48255
|
+
unparsedPreview: event.unparsedPreview,
|
|
48175
48256
|
diffAvailable: event.diffAvailable,
|
|
48176
48257
|
adversarialDropAnalysis: event.adversarialDropAnalysis,
|
|
48177
48258
|
adversarialAcceptAnalysis: event.adversarialAcceptAnalysis
|
|
@@ -49863,6 +49944,7 @@ function createRuntime(config2, workdir, opts) {
|
|
|
49863
49944
|
const logger = getLogger();
|
|
49864
49945
|
const quarantineMemo = createQuarantineMemo();
|
|
49865
49946
|
const adversarialIterations = new Map;
|
|
49947
|
+
const semanticIterations = new Map;
|
|
49866
49948
|
const rectificationOscillations = new Map;
|
|
49867
49949
|
let closed = false;
|
|
49868
49950
|
return {
|
|
@@ -49886,6 +49968,7 @@ function createRuntime(config2, workdir, opts) {
|
|
|
49886
49968
|
logger,
|
|
49887
49969
|
quarantineMemo,
|
|
49888
49970
|
adversarialIterations,
|
|
49971
|
+
semanticIterations,
|
|
49889
49972
|
rectificationOscillations,
|
|
49890
49973
|
get signal() {
|
|
49891
49974
|
return controller.signal;
|
|
@@ -59246,11 +59329,12 @@ function toReviewDecisionPayload(opName, output) {
|
|
|
59246
59329
|
const reviewer = opName === "semantic-review" ? "semantic" : opName === "adversarial-review" ? "adversarial" : null;
|
|
59247
59330
|
if (!reviewer)
|
|
59248
59331
|
return null;
|
|
59332
|
+
const unparsedPreview = typeof record2.unparsedPreview === "string" ? record2.unparsedPreview : undefined;
|
|
59249
59333
|
if (record2.failOpen === true) {
|
|
59250
|
-
return { reviewer, parsed: false, passed: true, failOpen: true, result: null };
|
|
59334
|
+
return { reviewer, parsed: false, passed: true, failOpen: true, result: null, unparsedPreview };
|
|
59251
59335
|
}
|
|
59252
59336
|
if (record2.looksLikeFail === true) {
|
|
59253
|
-
return { reviewer, parsed: false, passed: false, looksLikeFail: true, result: null };
|
|
59337
|
+
return { reviewer, parsed: false, passed: false, looksLikeFail: true, result: null, unparsedPreview };
|
|
59254
59338
|
}
|
|
59255
59339
|
if (typeof record2.passed !== "boolean" || !Array.isArray(record2.findings)) {
|
|
59256
59340
|
return null;
|
|
@@ -59272,7 +59356,8 @@ function toReviewDecisionPayload(opName, output) {
|
|
|
59272
59356
|
parsed: true,
|
|
59273
59357
|
passed: record2.passed,
|
|
59274
59358
|
result: { passed: record2.passed, findings: record2.findings },
|
|
59275
|
-
acDropped
|
|
59359
|
+
acDropped,
|
|
59360
|
+
...Array.isArray(record2.advisoryFindings) ? { advisoryFindings: record2.advisoryFindings } : {}
|
|
59276
59361
|
};
|
|
59277
59362
|
}
|
|
59278
59363
|
function emitReviewDecision(ctx, opName, output) {
|
|
@@ -59293,7 +59378,10 @@ function emitReviewDecision(ctx, opName, output) {
|
|
|
59293
59378
|
looksLikeFail: payload.parsed ? undefined : payload.looksLikeFail,
|
|
59294
59379
|
failOpen: payload.parsed ? false : payload.failOpen,
|
|
59295
59380
|
passed: payload.passed,
|
|
59296
|
-
result: payload.result
|
|
59381
|
+
result: payload.result,
|
|
59382
|
+
advisoryFindings: payload.parsed ? payload.advisoryFindings : undefined,
|
|
59383
|
+
acDropped: payload.parsed ? payload.acDropped : undefined,
|
|
59384
|
+
unparsedPreview: payload.parsed ? undefined : payload.unparsedPreview
|
|
59297
59385
|
});
|
|
59298
59386
|
}
|
|
59299
59387
|
function logUnifiedReviewPhaseStart(storyId, opName) {
|
|
@@ -59430,13 +59518,19 @@ async function runPhase(ctx, slot, phaseCosts, phaseOutputs, isThreeSession = fa
|
|
|
59430
59518
|
dispatchInput = await refreshReviewInputForDispatch(opName, dispatchInput);
|
|
59431
59519
|
let advIterationBefore = 0;
|
|
59432
59520
|
if (opName === "adversarial-review" && ctx.storyId) {
|
|
59433
|
-
const priorIterations =
|
|
59521
|
+
const priorIterations = getReviewIterations(ctx.runtime.adversarialIterations, ctx.storyId);
|
|
59434
59522
|
advIterationBefore = priorIterations.length;
|
|
59435
59523
|
dispatchInput = {
|
|
59436
59524
|
...dispatchInput,
|
|
59437
59525
|
priorAdversarialIterations: priorIterations
|
|
59438
59526
|
};
|
|
59439
59527
|
}
|
|
59528
|
+
if (opName === "semantic-review" && ctx.storyId) {
|
|
59529
|
+
dispatchInput = {
|
|
59530
|
+
...dispatchInput,
|
|
59531
|
+
priorSemanticIterations: getReviewIterations(ctx.runtime.semanticIterations, ctx.storyId)
|
|
59532
|
+
};
|
|
59533
|
+
}
|
|
59440
59534
|
if (isTddPhase) {
|
|
59441
59535
|
logger?.info("tdd", `-> Session: ${opName}`, { storyId: ctx.storyId, role: opName, ...progressData });
|
|
59442
59536
|
} else if (isThreeSession && opName === "full-suite-gate") {
|
|
@@ -59458,11 +59552,18 @@ async function runPhase(ctx, slot, phaseCosts, phaseOutputs, isThreeSession = fa
|
|
|
59458
59552
|
emitReviewDecision(ctx, opName, output);
|
|
59459
59553
|
if (opName === "adversarial-review" && ctx.storyId) {
|
|
59460
59554
|
const advOut = output;
|
|
59461
|
-
|
|
59555
|
+
recordReviewIteration(ctx.runtime.adversarialIterations, ctx.storyId, [
|
|
59462
59556
|
...advOut.normalizedFindings ?? [],
|
|
59463
59557
|
...advOut.advisoryFindings ?? []
|
|
59464
59558
|
]);
|
|
59465
59559
|
}
|
|
59560
|
+
if (opName === "semantic-review" && ctx.storyId) {
|
|
59561
|
+
const semOut = output;
|
|
59562
|
+
recordReviewIteration(ctx.runtime.semanticIterations, ctx.storyId, [
|
|
59563
|
+
...semOut.normalizedFindings ?? [],
|
|
59564
|
+
...semOut.advisoryFindings ?? []
|
|
59565
|
+
]);
|
|
59566
|
+
}
|
|
59466
59567
|
logUnifiedReviewPhaseResult(ctx.storyId, opName, output);
|
|
59467
59568
|
logDeterministicPhaseOutcome(ctx.storyId, opName, output, Date.now() - phaseStartedAt, isTddPhase, slot.op.stage, progressData);
|
|
59468
59569
|
outcome = derivePhaseOutcome(output);
|
|
@@ -60224,6 +60325,7 @@ var init_story_orchestrator = __esm(() => {
|
|
|
60224
60325
|
init_rectification();
|
|
60225
60326
|
init_nbf_flake_triage();
|
|
60226
60327
|
init_run_phase();
|
|
60328
|
+
init_review_decision();
|
|
60227
60329
|
init_types9();
|
|
60228
60330
|
});
|
|
60229
60331
|
|
|
@@ -60573,7 +60675,6 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
60573
60675
|
diff: prepared.diff,
|
|
60574
60676
|
excludePatterns: prepared.excludePatterns,
|
|
60575
60677
|
featureCtxBlock: buildFeatureCtxBlock(ctx, "reviewer-semantic"),
|
|
60576
|
-
priorSemanticIterations: ctx.priorSemanticIterations,
|
|
60577
60678
|
resolvedTestPatterns,
|
|
60578
60679
|
blockingThreshold: ctx.config.review.blockingThreshold,
|
|
60579
60680
|
_refresh: {
|
|
@@ -60611,7 +60712,6 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
60611
60712
|
testGlobs: prepared.testGlobs,
|
|
60612
60713
|
refExcludePatterns: prepared.refExcludePatterns,
|
|
60613
60714
|
featureCtxBlock: buildFeatureCtxBlock(ctx, "reviewer-adversarial"),
|
|
60614
|
-
priorAdversarialIterations: ctx.priorAdversarialIterations,
|
|
60615
60715
|
resolvedTestPatterns,
|
|
60616
60716
|
blockingThreshold: ctx.config.review.blockingThreshold,
|
|
60617
60717
|
_refresh: {
|
|
@@ -62113,7 +62213,7 @@ async function fanOutReporters(reporters, hook, invoke) {
|
|
|
62113
62213
|
}
|
|
62114
62214
|
}
|
|
62115
62215
|
}
|
|
62116
|
-
function wireReporters(bus, pluginRegistry, runId, startTime) {
|
|
62216
|
+
function wireReporters(bus, pluginRegistry, runId, startTime, projectKey) {
|
|
62117
62217
|
const logger = getSafeLogger();
|
|
62118
62218
|
const safe = (name, fn) => {
|
|
62119
62219
|
return fn().catch((err) => logger?.warn("reporters-subscriber", `Reporter "${name}" error`, { error: String(err) })).catch(() => {});
|
|
@@ -62163,7 +62263,8 @@ function wireReporters(bus, pluginRegistry, runId, startTime) {
|
|
|
62163
62263
|
runId,
|
|
62164
62264
|
feature: ev.feature,
|
|
62165
62265
|
totalStories: ev.totalStories,
|
|
62166
|
-
startTime: new Date(startTime).toISOString()
|
|
62266
|
+
startTime: new Date(startTime).toISOString(),
|
|
62267
|
+
project: projectKey
|
|
62167
62268
|
});
|
|
62168
62269
|
} catch (err) {
|
|
62169
62270
|
logger?.warn("plugins", `Reporter '${r.name}' onRunStart failed`, { error: err });
|
|
@@ -71317,8 +71418,6 @@ function releaseHeavyPipelineContext(ctx) {
|
|
|
71317
71418
|
ctx.constitution = undefined;
|
|
71318
71419
|
ctx.acceptanceFailures = undefined;
|
|
71319
71420
|
ctx.autofixPriorIterations = undefined;
|
|
71320
|
-
ctx.priorSemanticIterations = undefined;
|
|
71321
|
-
ctx.priorAdversarialIterations = undefined;
|
|
71322
71421
|
ctx.reviewFindings = undefined;
|
|
71323
71422
|
ctx.selfVerification = undefined;
|
|
71324
71423
|
ctx.tddIsolations = undefined;
|
|
@@ -71977,7 +72076,7 @@ async function executeUnified(ctx, initialPrd) {
|
|
|
71977
72076
|
_prevRunUnsubscribers = [];
|
|
71978
72077
|
const thisRunUnsubscribers = [
|
|
71979
72078
|
wireHooks(pipelineEventBus, ctx.hooks, ctx.workdir, ctx.feature),
|
|
71980
|
-
wireReporters(pipelineEventBus, ctx.pluginRegistry, ctx.runId, ctx.startTime),
|
|
72079
|
+
wireReporters(pipelineEventBus, ctx.pluginRegistry, ctx.runId, ctx.startTime, ctx.runtime.projectKey),
|
|
71981
72080
|
wireInteraction(pipelineEventBus, ctx.interactionChain, ctx.config),
|
|
71982
72081
|
wireEventsWriter(pipelineEventBus, ctx.feature, ctx.runId, ctx.workdir),
|
|
71983
72082
|
wireRegistry(pipelineEventBus, ctx.feature, ctx.runId, ctx.workdir, ctx.runtime.outputDir)
|
|
@@ -74160,6 +74259,7 @@ var exports_execution = {};
|
|
|
74160
74259
|
__export(exports_execution, {
|
|
74161
74260
|
writeExitSummary: () => writeExitSummary,
|
|
74162
74261
|
withIncreasingFailuresBail: () => withIncreasingFailuresBail,
|
|
74262
|
+
toReviewDecisionPayload: () => toReviewDecisionPayload,
|
|
74163
74263
|
synthesizeBackfillMetric: () => synthesizeBackfillMetric,
|
|
74164
74264
|
stopHeartbeat: () => stopHeartbeat,
|
|
74165
74265
|
startHeartbeat: () => startHeartbeat2,
|