@nathapp/nax 0.73.4 → 0.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/nax.js CHANGED
@@ -17787,6 +17787,40 @@ var init_schemas3 = __esm(() => {
17787
17787
  enabled: exports_external.boolean().default(false),
17788
17788
  draft: exports_external.boolean().default(true)
17789
17789
  }).optional().default({ enabled: false, draft: true }),
17790
+ finish: exports_external.object({
17791
+ autoFlow: exports_external.object({
17792
+ enabled: exports_external.boolean().default(false),
17793
+ flowPath: exports_external.string().default("flows/nax-finish/nax-finish.flow.ts"),
17794
+ defaultAgent: exports_external.string().nullable().default(null),
17795
+ reviewers: exports_external.object({
17796
+ spec: exports_external.string().nullable().default(null),
17797
+ quality: exports_external.string().nullable().default(null)
17798
+ }).default({ spec: null, quality: null }),
17799
+ escalate: exports_external.object({ telegram: exports_external.boolean().default(true) }).default({ telegram: true }),
17800
+ timeouts: exports_external.object({
17801
+ acceptanceMs: exports_external.number().int().positive().default(600000),
17802
+ gateMs: exports_external.number().int().positive().default(900000),
17803
+ flowMs: exports_external.number().int().positive().default(5400000),
17804
+ stepMs: exports_external.number().int().positive().nullable().default(null)
17805
+ }).default({ acceptanceMs: 600000, gateMs: 900000, flowMs: 5400000, stepMs: null })
17806
+ }).default({
17807
+ enabled: false,
17808
+ flowPath: "flows/nax-finish/nax-finish.flow.ts",
17809
+ defaultAgent: null,
17810
+ reviewers: { spec: null, quality: null },
17811
+ escalate: { telegram: true },
17812
+ timeouts: { acceptanceMs: 600000, gateMs: 900000, flowMs: 5400000, stepMs: null }
17813
+ })
17814
+ }).default({
17815
+ autoFlow: {
17816
+ enabled: false,
17817
+ flowPath: "flows/nax-finish/nax-finish.flow.ts",
17818
+ defaultAgent: null,
17819
+ reviewers: { spec: null, quality: null },
17820
+ escalate: { telegram: true },
17821
+ timeouts: { acceptanceMs: 600000, gateMs: 900000, flowMs: 5400000, stepMs: null }
17822
+ }
17823
+ }),
17790
17824
  reporters: ReportersConfigSchema,
17791
17825
  profile: exports_external.string().default("default"),
17792
17826
  profileChain: exports_external.array(exports_external.string()).default([])
@@ -19476,7 +19510,7 @@ function reshapeSelector(name, fn) {
19476
19510
  }
19477
19511
 
19478
19512
  // src/config/selectors.ts
19479
- var reviewConfigSelector, planConfigSelector, decomposeConfigSelector, rectifyConfigSelector, acceptanceConfigSelector, acceptanceFixConfigSelector, acceptanceGenConfigSelector, tddConfigSelector, debateConfigSelector, routingConfigSelector, verifyConfigSelector, mutationCheckConfigSelector, rectificationGateConfigSelector, agentConfigSelector, agentManagerConfigSelector, interactionConfigSelector, precheckConfigSelector, qualityConfigSelector, autofixConfigSelector, executionGatesConfigSelector, testPatternConfigSelector, contextConfigSelector, contextToolRuntimeConfigSelector, promptLoaderConfigSelector, llmRoutingConfigSelector;
19513
+ var reviewConfigSelector, planConfigSelector, decomposeConfigSelector, rectifyConfigSelector, acceptanceConfigSelector, acceptanceFixConfigSelector, acceptanceGenConfigSelector, tddConfigSelector, debateConfigSelector, routingConfigSelector, verifyConfigSelector, mutationCheckConfigSelector, rectificationGateConfigSelector, agentConfigSelector, agentManagerConfigSelector, interactionConfigSelector, precheckConfigSelector, qualityConfigSelector, autofixConfigSelector, executionGatesConfigSelector, testPatternConfigSelector, contextConfigSelector, contextToolRuntimeConfigSelector, promptLoaderConfigSelector, llmRoutingConfigSelector, finishConfigSelector;
19480
19514
  var init_selectors = __esm(() => {
19481
19515
  reviewConfigSelector = pickSelector("review", "review", "debate", "models", "execution", "project", "quality", "agent");
19482
19516
  planConfigSelector = pickSelector("plan", "plan", "debate", "agent", "project", "routing");
@@ -19506,6 +19540,7 @@ var init_selectors = __esm(() => {
19506
19540
  contextToolRuntimeConfigSelector = pickSelector("context-tool-runtime", "context", "execution", "project", "quality");
19507
19541
  promptLoaderConfigSelector = pickSelector("prompt-loader", "prompts", "context", "project");
19508
19542
  llmRoutingConfigSelector = pickSelector("llm-routing", "routing", "models", "agent", "tdd", "execution", "precheck");
19543
+ finishConfigSelector = pickSelector("finish", "finish", "interaction", "quality");
19509
19544
  });
19510
19545
 
19511
19546
  // src/config/loader-runtime.ts
@@ -19649,7 +19684,8 @@ When a spec is provided, these rules govern acceptance criteria generation:
19649
19684
  3. **Respect story scope.** Each story's criteria must only cover what the spec says for that story. Do not assign criteria that belong to a different story's scope (wrong feature area, wrong file, wrong dependency chain).
19650
19685
  4. **\`suggestedCriteria\` format.** Each element must be a plain behavioral assertion \u2014 an observable output, return value, state change, or error condition that a test can assert. Never include implementation details (imports, internal structure), design suggestions, or vague descriptions.
19651
19686
  5. **Enumerate failure-mode tables.** If the spec contains a "Failure handling", "Error handling", "Failure modes", or equivalent table/section enumerating error/exception scenarios, every row MUST produce at least one acceptance criterion in the matching story. Walk the table row by row; do not skip rows because they look minor. A failure-mode row without an AC is treated as a missing AC and will cause rejection.
19652
- 6. **Resolve internal spec contradictions toward the AC.** If the spec's prose, design table, or interface block contradicts a stated acceptance criterion (e.g. design table says \`lookback or strategy_lookback\` but the AC says \`lookback=None\`), the AC is authoritative. Implement the AC; do NOT echo the contradicting prose into the description.`, DESCRIPTION_QUALITY_RULES = `## Description Quality Rules
19687
+ 6. **Preserve the spec's out-of-scope statements.** If the spec has an "Out of Scope", "Non-Goals", or "Not in scope" section \u2014 or an inline \`**Out of scope \u2026:**\` lead-in \u2014 copy every item **verbatim** into the top-level \`outOfScope\` string array. This is what the feature deliberately does NOT do; it is the only channel by which a deferred arc reaches the implementer, which never sees the spec. Never drop an item, never merge two into one, and never turn one into an acceptance criterion. Echo an item into a story's \`**Scope** \u2014 Out:\` bullet as well whenever that story sits close enough to the boundary that an implementer might stray across it. Omit \`outOfScope\` only when the spec declares nothing.
19688
+ 7. **Resolve internal spec contradictions toward the AC.** If the spec's prose, design table, or interface block contradicts a stated acceptance criterion (e.g. design table says \`lookback or strategy_lookback\` but the AC says \`lookback=None\`), the AC is authoritative. Implement the AC; do NOT echo the contradicting prose into the description.`, DESCRIPTION_QUALITY_RULES = `## Description Quality Rules
19653
19689
 
19654
19690
  When a spec contains a design subsection for a story (e.g. \`### N. <Topic>\` under \`## Design\`), the story description MUST embed that subsection's interface declarations, algorithms, and design notes verbatim.
19655
19691
 
@@ -19666,6 +19702,7 @@ When a spec contains a design subsection for a story (e.g. \`### N. <Topic>\` un
19666
19702
  ### Rules
19667
19703
 
19668
19704
  1. Do NOT paraphrase spec design sections \u2014 embed them verbatim.
19705
+ 1a. \`**Scope** \u2014 Out:\` states *inter-story* boundaries \u2014 work that belongs to a different story in this PRD. Feature-level exclusions (what the whole feature defers) belong in the top-level \`outOfScope\` array, not here. List an item in both places when this story sits close enough to a feature-level boundary that an implementer might stray across it.
19669
19706
  2. A one-sentence description is almost always too short for implementation stories that have spec design content.
19670
19707
  3. The implementer receives only this description \u2014 no access to the spec. Design decisions lost here are permanently invisible to the implementer.
19671
19708
  4. **Self-check before emitting.** After drafting each description, re-read it against the story's \`acceptanceCriteria\`. If any sentence in the description contradicts an AC (e.g. description says behaviour X, AC says behaviour not-X), the description is wrong \u2014 rewrite the offending sentence to match the AC, or delete it. The AC is authoritative. Embedding contradicting spec prose verbatim still counts as a contradiction; resolve it.
@@ -19784,6 +19821,7 @@ __export(exports_config, {
19784
19821
  globalConfigPath: () => globalConfigPath,
19785
19822
  globalConfigDir: () => globalConfigDir,
19786
19823
  getAcQualityRules: () => getAcQualityRules,
19824
+ finishConfigSelector: () => finishConfigSelector,
19787
19825
  findProjectDir: () => findProjectDir,
19788
19826
  executionGatesConfigSelector: () => executionGatesConfigSelector,
19789
19827
  deepMergeConfig: () => deepMergeConfig,
@@ -28368,6 +28406,247 @@ var init_static_rules = __esm(() => {
28368
28406
  LEGACY_CANDIDATE_FILES = ["CLAUDE.md", ".cursorrules", "AGENTS.md"];
28369
28407
  });
28370
28408
 
28409
+ // src/prd/out-of-scope.ts
28410
+ function stripEmphasis(text) {
28411
+ return text.replace(/\*\*/g, "").replace(/[*`_]/g, "");
28412
+ }
28413
+ function outOfScopeHeadingLevel(line, nextLine) {
28414
+ const atx = stripEmphasis(line).match(OUT_OF_SCOPE_HEADING);
28415
+ if (atx)
28416
+ return atx[1].length;
28417
+ if (nextLine !== undefined && SETEXT_UNDERLINE.test(nextLine)) {
28418
+ const title = stripEmphasis(line).trim().replace(/:$/, "");
28419
+ if (OUT_OF_SCOPE_TITLE.test(title))
28420
+ return nextLine.trim().startsWith("=") ? 1 : 2;
28421
+ }
28422
+ return null;
28423
+ }
28424
+ function isSetextUnderline(lines, index) {
28425
+ if (!SETEXT_UNDERLINE.test(lines[index]))
28426
+ return false;
28427
+ const prev = lines[index - 1];
28428
+ return prev !== undefined && prev.trim().length > 0 && !ANY_HEADING.test(prev);
28429
+ }
28430
+ function canonical(text) {
28431
+ return text.replace(/`/g, "").replace(/\s+/g, " ").trim().toLowerCase();
28432
+ }
28433
+ function stripBullet(line) {
28434
+ return line.replace(LIST_ITEM_START, "").trim();
28435
+ }
28436
+ function sectionLines(lines, startIndex, level) {
28437
+ const collected = [];
28438
+ let inFence = false;
28439
+ for (let i = startIndex + 1;i < lines.length; i++) {
28440
+ const line = lines[i];
28441
+ if (FENCE.test(line)) {
28442
+ inFence = !inFence;
28443
+ continue;
28444
+ }
28445
+ if (inFence)
28446
+ continue;
28447
+ const heading = line.match(ANY_HEADING);
28448
+ if (heading && (heading[1].length <= level || level === 1))
28449
+ break;
28450
+ if (heading) {
28451
+ collected.push("");
28452
+ continue;
28453
+ }
28454
+ if (isSetextUnderline(lines, i)) {
28455
+ const setextLevel = line.trim().startsWith("=") ? 1 : 2;
28456
+ if (setextLevel <= level) {
28457
+ collected.pop();
28458
+ break;
28459
+ }
28460
+ collected.pop();
28461
+ continue;
28462
+ }
28463
+ collected.push(line);
28464
+ }
28465
+ return collected;
28466
+ }
28467
+ function itemsFromSection(body) {
28468
+ const items = [];
28469
+ let current = [];
28470
+ const flush = () => {
28471
+ const text = current.join(" ").replace(INLINE_MARKER, "").replace(/\s+/g, " ").trim();
28472
+ if (text)
28473
+ items.push(text);
28474
+ current = [];
28475
+ };
28476
+ const hasBullets = body.some((line) => LIST_ITEM_START.test(line));
28477
+ for (const [index, line] of body.entries()) {
28478
+ if (line.trim().length === 0) {
28479
+ flush();
28480
+ continue;
28481
+ }
28482
+ if (TABLE_ROW.test(line) && TABLE_SEPARATOR.test(body[index + 1] ?? ""))
28483
+ continue;
28484
+ if (TABLE_SEPARATOR.test(line))
28485
+ continue;
28486
+ if (TABLE_ROW.test(line)) {
28487
+ flush();
28488
+ const cells = line.trim().replace(/^\||\|$/g, "").split("|").map((c) => c.trim()).filter((c) => c.length > 0);
28489
+ if (cells.length > 0)
28490
+ current.push(cells.join(" \u2014 "));
28491
+ flush();
28492
+ continue;
28493
+ }
28494
+ if (hasBullets && LIST_ITEM_START.test(line)) {
28495
+ flush();
28496
+ current.push(stripBullet(line));
28497
+ continue;
28498
+ }
28499
+ current.push(line.trim());
28500
+ }
28501
+ flush();
28502
+ return items;
28503
+ }
28504
+ function fencedLineIndices(lines) {
28505
+ const fenced = new Set;
28506
+ let inFence = false;
28507
+ for (const [i, line] of lines.entries()) {
28508
+ if (FENCE.test(line)) {
28509
+ fenced.add(i);
28510
+ inFence = !inFence;
28511
+ continue;
28512
+ }
28513
+ if (inFence)
28514
+ fenced.add(i);
28515
+ }
28516
+ return fenced;
28517
+ }
28518
+ function itemsFromInlineMarkers(lines, fenced, boundary) {
28519
+ const items = [];
28520
+ for (let i = 0;i < boundary; i++) {
28521
+ if (fenced.has(i) || !INLINE_MARKER.test(lines[i]))
28522
+ continue;
28523
+ const remainder = lines[i].replace(INLINE_MARKER, "").trim();
28524
+ let j = i + 1;
28525
+ if (remainder.length === 0) {
28526
+ const body = [];
28527
+ while (j < lines.length && !fenced.has(j) && lines[j].trim().length > 0 && !ANY_HEADING.test(lines[j])) {
28528
+ body.push(lines[j]);
28529
+ j += 1;
28530
+ }
28531
+ items.push(...itemsFromSection(body));
28532
+ i = j - 1;
28533
+ continue;
28534
+ }
28535
+ const parts = [remainder];
28536
+ while (j < lines.length && !fenced.has(j) && lines[j].trim().length > 0 && !ANY_HEADING.test(lines[j]) && !LIST_ITEM_START.test(lines[j])) {
28537
+ parts.push(lines[j].trim());
28538
+ j += 1;
28539
+ }
28540
+ const text = parts.join(" ").replace(/\s+/g, " ").trim();
28541
+ if (text)
28542
+ items.push(text);
28543
+ i = j - 1;
28544
+ }
28545
+ return items;
28546
+ }
28547
+ function isListLeadIn(item) {
28548
+ return item.trimEnd().endsWith(":");
28549
+ }
28550
+ function dedupeAndCap(items) {
28551
+ const seen = new Set;
28552
+ const out = [];
28553
+ for (const item of items) {
28554
+ const key = canonical(item);
28555
+ if (EMPTY_SENTINELS.has(key) || isListLeadIn(item))
28556
+ continue;
28557
+ if (key.length === 0 || seen.has(key))
28558
+ continue;
28559
+ seen.add(key);
28560
+ out.push(item);
28561
+ if (out.length >= MAX_OUT_OF_SCOPE_ITEMS)
28562
+ break;
28563
+ }
28564
+ return out;
28565
+ }
28566
+ function storyScopeBoundary(lines) {
28567
+ const index = lines.findIndex((line) => STORY_SECTION_HEADING.test(stripEmphasis(line)));
28568
+ return index === -1 ? lines.length : index;
28569
+ }
28570
+ function normalizeOutOfScopeList(raw) {
28571
+ if (!Array.isArray(raw))
28572
+ return;
28573
+ const strings = raw.filter((item) => typeof item === "string" && item.trim().length > 0);
28574
+ const items = dedupeAndCap(strings.map((item) => item.trim()));
28575
+ return items.length > 0 ? items : undefined;
28576
+ }
28577
+ function extractSpecOutOfScope(specContent) {
28578
+ if (!specContent.trim())
28579
+ return [];
28580
+ const lines = specContent.split(`
28581
+ `);
28582
+ const fenced = fencedLineIndices(lines);
28583
+ const boundary = storyScopeBoundary(lines);
28584
+ const items = [];
28585
+ for (let i = 0;i < lines.length; i++) {
28586
+ if (fenced.has(i))
28587
+ continue;
28588
+ const level = outOfScopeHeadingLevel(lines[i], lines[i + 1]);
28589
+ if (level === null)
28590
+ continue;
28591
+ if (level > 2 && i > boundary)
28592
+ continue;
28593
+ const bodyStart = SETEXT_UNDERLINE.test(lines[i + 1] ?? "") ? i + 1 : i;
28594
+ items.push(...itemsFromSection(sectionLines(lines, bodyStart, level)));
28595
+ }
28596
+ items.push(...itemsFromInlineMarkers(lines, fenced, boundary));
28597
+ return dedupeAndCap(items);
28598
+ }
28599
+ function findMissingOutOfScope(specContent, prd) {
28600
+ const declared = extractSpecOutOfScope(specContent);
28601
+ if (declared.length === 0)
28602
+ return [];
28603
+ const present = (prd.outOfScope ?? []).map(canonical);
28604
+ return declared.filter((item) => !present.some((entry) => entry.includes(canonical(item))));
28605
+ }
28606
+ function applyOutOfScopeFallback(prd, specContent) {
28607
+ const missing = findMissingOutOfScope(specContent, prd);
28608
+ if (missing.length === 0)
28609
+ return prd;
28610
+ return { ...prd, outOfScope: dedupeAndCap([...missing, ...prd.outOfScope ?? []]) };
28611
+ }
28612
+ function propagateOutOfScopeToStories(prd) {
28613
+ const featureLevel = prd.outOfScope ?? [];
28614
+ if (featureLevel.length === 0)
28615
+ return prd;
28616
+ const userStories = prd.userStories.map((story) => ({
28617
+ ...story,
28618
+ outOfScope: dedupeAndCap([...featureLevel, ...story.outOfScope ?? []])
28619
+ }));
28620
+ return { ...prd, userStories };
28621
+ }
28622
+ function stripPropagatedOutOfScope(prd) {
28623
+ const featureLevel = new Set((prd.outOfScope ?? []).map(canonical));
28624
+ if (featureLevel.size === 0)
28625
+ return prd;
28626
+ if (!prd.userStories.some((story) => (story.outOfScope ?? []).length > 0))
28627
+ return prd;
28628
+ const userStories = prd.userStories.map((story) => {
28629
+ const specific = (story.outOfScope ?? []).filter((item) => !featureLevel.has(canonical(item)));
28630
+ const { outOfScope: _dropped, ...rest } = story;
28631
+ return specific.length > 0 ? { ...rest, outOfScope: specific } : rest;
28632
+ });
28633
+ return { ...prd, userStories };
28634
+ }
28635
+ var MAX_OUT_OF_SCOPE_ITEMS = 25, OUT_OF_SCOPE_TITLE, OUT_OF_SCOPE_HEADING, ANY_HEADING, FENCE, TABLE_SEPARATOR, TABLE_ROW, STORY_SECTION_HEADING, SETEXT_UNDERLINE, INLINE_MARKER, LIST_ITEM_START, EMPTY_SENTINELS;
28636
+ var init_out_of_scope = __esm(() => {
28637
+ OUT_OF_SCOPE_TITLE = /^(?:out[\s-]?of[\s-]?scope|non[\s-]?goals?|not[\s-]in[\s-]scope)\b/i;
28638
+ OUT_OF_SCOPE_HEADING = /^(#{1,6})\s*(?:out[\s-]?of[\s-]?scope|non[\s-]?goals?|not[\s-]in[\s-]scope)\b/i;
28639
+ ANY_HEADING = /^(#{1,6})\s/;
28640
+ FENCE = /^\s*(?:```|~~~)/;
28641
+ TABLE_SEPARATOR = /^\s*\|?[\s:|-]+\|[\s:|-]*$/;
28642
+ TABLE_ROW = /^\s*\|.*\|\s*$/;
28643
+ STORY_SECTION_HEADING = /^#{1,3}\s*(?:stories|acceptance\s+criteria|user\s+stories)\b/i;
28644
+ SETEXT_UNDERLINE = /^\s*(?:=+|-+)\s*$/;
28645
+ INLINE_MARKER = /^\s*(?:[-*]\s*)?\*\*\s*(?:out[\s-]?of[\s-]?scope|non[\s-]?goals?)[^*]*\*\*\s*:?\s*/i;
28646
+ LIST_ITEM_START = /^\s*(?:[-*+\u2022\u2023\u25E6\u2043\u2219]|\d+\.)\s+/;
28647
+ EMPTY_SENTINELS = new Set(["none", "none.", "n/a", "na", "nothing", "nothing.", "tbd", "-"]);
28648
+ });
28649
+
28371
28650
  // src/prd/types.ts
28372
28651
  function getContextFiles(story) {
28373
28652
  const legacyFiles = story.relevantFiles;
@@ -28425,7 +28704,7 @@ function normalizeWs(text) {
28425
28704
  function stripBackticks(text) {
28426
28705
  return text.replace(/`/g, "");
28427
28706
  }
28428
- function canonical(text) {
28707
+ function canonical2(text) {
28429
28708
  return normalizeWs(stripBackticks(text));
28430
28709
  }
28431
28710
  function leadingTagGroup(line) {
@@ -28440,7 +28719,7 @@ function isContinuation(line) {
28440
28719
  return false;
28441
28720
  if (HEADING.test(line))
28442
28721
  return false;
28443
- if (LIST_ITEM_START.test(line))
28722
+ if (LIST_ITEM_START2.test(line))
28444
28723
  return false;
28445
28724
  return true;
28446
28725
  }
@@ -28466,13 +28745,13 @@ function extractVerbatimAcs(specContent) {
28466
28745
  return blocks;
28467
28746
  }
28468
28747
  function prdAcPayloads(prd) {
28469
- return (prd.userStories ?? []).flatMap((story) => (story.acceptanceCriteria ?? []).map(canonical));
28748
+ return (prd.userStories ?? []).flatMap((story) => (story.acceptanceCriteria ?? []).map(canonical2));
28470
28749
  }
28471
28750
  function findMissingVerbatimAcs(specContent, prd) {
28472
28751
  const prdAcs = prdAcPayloads(prd);
28473
28752
  const missing = [];
28474
28753
  for (const block of extractVerbatimAcs(specContent)) {
28475
- const payload = canonical(stripTagPrefix(block));
28754
+ const payload = canonical2(stripTagPrefix(block));
28476
28755
  if (payload.length === 0)
28477
28756
  continue;
28478
28757
  if (!prdAcs.some((ac) => ac.includes(payload)))
@@ -28480,10 +28759,10 @@ function findMissingVerbatimAcs(specContent, prd) {
28480
28759
  }
28481
28760
  return missing;
28482
28761
  }
28483
- var LEADING_TAG_GROUP, LIST_ITEM_START, HEADING;
28762
+ var LEADING_TAG_GROUP, LIST_ITEM_START2, HEADING;
28484
28763
  var init_verbatim_fidelity = __esm(() => {
28485
28764
  LEADING_TAG_GROUP = /^\s*(?:[-*]|\d+\.)?\s*((?:\[[a-z][a-z-]*\]\s*)+)/i;
28486
- LIST_ITEM_START = /^\s*(?:[-*]|\d+\.)\s/;
28765
+ LIST_ITEM_START2 = /^\s*(?:[-*]|\d+\.)\s/;
28487
28766
  HEADING = /^\s*#/;
28488
28767
  });
28489
28768
 
@@ -28699,6 +28978,7 @@ function validateStory(raw, index, allIds) {
28699
28978
  suggestedCriteria = coerced;
28700
28979
  }
28701
28980
  }
28981
+ const storyOutOfScope = normalizeOutOfScopeList(s.outOfScope);
28702
28982
  const routing = typeof s.routing === "object" && s.routing !== null ? s.routing : {};
28703
28983
  const rawComplexity = routing.complexity ?? s.complexity;
28704
28984
  if (rawComplexity === undefined || rawComplexity === null) {
@@ -28839,6 +29119,7 @@ function validateStory(raw, index, allIds) {
28839
29119
  ...contextFiles.length > 0 ? { contextFiles } : {},
28840
29120
  ...expectedFiles.length > 0 ? { expectedFiles } : {},
28841
29121
  ...suggestedCriteria !== undefined ? { suggestedCriteria } : {},
29122
+ ...storyOutOfScope !== undefined ? { outOfScope: storyOutOfScope } : {},
28842
29123
  ...verifiedBy !== undefined ? { verifiedBy } : {},
28843
29124
  ...intent !== undefined ? { intent } : {}
28844
29125
  };
@@ -28893,6 +29174,7 @@ function validatePlanOutput(raw, feature, branch) {
28893
29174
  }
28894
29175
  const userStories = rawStories.map((story, index) => validateStory(story, index, allIds));
28895
29176
  const now = new Date().toISOString();
29177
+ const featureOutOfScope = normalizeOutOfScopeList(obj.outOfScope);
28896
29178
  return {
28897
29179
  project: typeof obj.project === "string" && obj.project !== "" ? obj.project : feature,
28898
29180
  feature,
@@ -28900,13 +29182,15 @@ function validatePlanOutput(raw, feature, branch) {
28900
29182
  createdAt: typeof obj.createdAt === "string" ? obj.createdAt : now,
28901
29183
  updatedAt: now,
28902
29184
  userStories,
28903
- ...typeof obj.analysis === "string" && obj.analysis.trim() !== "" ? { analysis: obj.analysis.trim() } : {}
29185
+ ...typeof obj.analysis === "string" && obj.analysis.trim() !== "" ? { analysis: obj.analysis.trim() } : {},
29186
+ ...featureOutOfScope !== undefined ? { outOfScope: featureOutOfScope } : {}
28904
29187
  };
28905
29188
  }
28906
29189
  var VALID_COMPLEXITY, STORY_ID_NO_SEPARATOR;
28907
29190
  var init_schema2 = __esm(() => {
28908
29191
  init_test_strategy();
28909
29192
  init_errors();
29193
+ init_out_of_scope();
28910
29194
  VALID_COMPLEXITY = ["simple", "medium", "complex", "expert"];
28911
29195
  STORY_ID_NO_SEPARATOR = /^([A-Za-z]+)(\d+)$/;
28912
29196
  });
@@ -28916,10 +29200,13 @@ var exports_prd = {};
28916
29200
  __export(exports_prd, {
28917
29201
  validatePlanOutput: () => validatePlanOutput,
28918
29202
  validateInjectedStory: () => validateInjectedStory,
29203
+ stripPropagatedOutOfScope: () => stripPropagatedOutOfScope,
28919
29204
  setStoryPriority: () => setStoryPriority,
28920
29205
  savePRD: () => savePRD,
28921
29206
  resetStoryToPending: () => resetStoryToPending,
28922
29207
  resetFailedStoriesToPending: () => resetFailedStoriesToPending,
29208
+ propagateOutOfScopeToStories: () => propagateOutOfScopeToStories,
29209
+ normalizeOutOfScopeList: () => normalizeOutOfScopeList,
28923
29210
  markStorySkipped: () => markStorySkipped,
28924
29211
  markStoryPaused: () => markStoryPaused,
28925
29212
  markStoryPassed: () => markStoryPassed,
@@ -28935,10 +29222,14 @@ __export(exports_prd, {
28935
29222
  generateHumanHaltSummary: () => generateHumanHaltSummary,
28936
29223
  findSpecDriftViolations: () => findSpecDriftViolations,
28937
29224
  findMissingVerbatimAcs: () => findMissingVerbatimAcs,
29225
+ findMissingOutOfScope: () => findMissingOutOfScope,
28938
29226
  extractVerbatimAcs: () => extractVerbatimAcs,
29227
+ extractSpecOutOfScope: () => extractSpecOutOfScope,
28939
29228
  deriveNextStoryId: () => deriveNextStoryId,
28940
29229
  countStories: () => countStories,
28941
- PRD_MAX_FILE_SIZE: () => PRD_MAX_FILE_SIZE
29230
+ applyOutOfScopeFallback: () => applyOutOfScopeFallback,
29231
+ PRD_MAX_FILE_SIZE: () => PRD_MAX_FILE_SIZE,
29232
+ MAX_OUT_OF_SCOPE_ITEMS: () => MAX_OUT_OF_SCOPE_ITEMS
28942
29233
  });
28943
29234
  import { existsSync as existsSync4, statSync } from "fs";
28944
29235
  async function loadPRD(path) {
@@ -28971,11 +29262,11 @@ async function loadPRD(path) {
28971
29262
  }
28972
29263
  story.storyPoints = story.storyPoints ?? 1;
28973
29264
  }
28974
- return prd;
29265
+ return propagateOutOfScopeToStories(prd);
28975
29266
  }
28976
29267
  async function savePRD(prd, path) {
28977
29268
  prd.updatedAt = new Date().toISOString();
28978
- await saveJsonFile(path, prd, "prd");
29269
+ await saveJsonFile(path, stripPropagatedOutOfScope(prd), "prd");
28979
29270
  }
28980
29271
  function hasSatisfiedDependencies(story, storyIds, completedIds) {
28981
29272
  return story.dependencies.every((dep) => !storyIds.has(dep) || completedIds.has(dep));
@@ -29129,8 +29420,10 @@ var PRD_MAX_FILE_SIZE;
29129
29420
  var init_prd = __esm(() => {
29130
29421
  init_errors();
29131
29422
  init_json_file();
29423
+ init_out_of_scope();
29132
29424
  init_verbatim_fidelity();
29133
29425
  init_spec_drift();
29426
+ init_out_of_scope();
29134
29427
  init_inject();
29135
29428
  init_schema2();
29136
29429
  PRD_MAX_FILE_SIZE = 5 * 1024 * 1024;
@@ -31204,7 +31497,49 @@ var init_role_task = __esm(() => {
31204
31497
  init_test_runners();
31205
31498
  });
31206
31499
 
31500
+ // src/prompts/sections/out-of-scope.ts
31501
+ function buildOutOfScopeLines(items) {
31502
+ if (!items || items.length === 0)
31503
+ return [];
31504
+ return [
31505
+ "",
31506
+ "**Out of Scope \u2014 do NOT implement these:**",
31507
+ ...items.map((item) => `- ${item}`),
31508
+ "",
31509
+ "Treat the list above as a hard boundary. If satisfying an acceptance criterion appears to require",
31510
+ "one of these, implement only what the criterion states and note the tension in your final message \u2014",
31511
+ "do not expand into the excluded work."
31512
+ ];
31513
+ }
31514
+ function buildReviewOutOfScopeBlock(items, opts = {}) {
31515
+ if (!items || items.length === 0)
31516
+ return "";
31517
+ const header = [
31518
+ "",
31519
+ "**Out of Scope (feature-level \u2014 NOT acceptance criteria):**",
31520
+ ...items.map((item, i) => `${i + 1}. ${item}`),
31521
+ "",
31522
+ "These state what the feature deliberately does not do. They are not acceptance criteria:",
31523
+ "never cite one as `acQuote`/`acIndex`, and never treat the absence of this work as a defect."
31524
+ ];
31525
+ if (!opts.citable) {
31526
+ return [...header, "Report nothing against this list; it is context so you do not demand excluded work."].join(`
31527
+ `);
31528
+ }
31529
+ return [
31530
+ ...header,
31531
+ 'To report work that crossed one of these boundaries, set `category` to `"out-of-scope"`, quote the',
31532
+ "entry verbatim in `scopeQuote`, and set `scopeIndex` to its number above. Emit these as",
31533
+ '`severity: "warning"` \u2014 never `"error"`. Set `scopeQuote`/`scopeIndex` ONLY on an `"out-of-scope"`',
31534
+ "finding; on any other finding they are ignored."
31535
+ ].join(`
31536
+ `);
31537
+ }
31538
+
31207
31539
  // src/prompts/sections/story.ts
31540
+ function outOfScopeLines(story) {
31541
+ return buildOutOfScopeLines(story.outOfScope);
31542
+ }
31208
31543
  function buildBatchStorySection(stories) {
31209
31544
  const storyBlocks = stories.map((story, i) => {
31210
31545
  const criteria = story.acceptanceCriteria.map((c, j) => `${j + 1}. ${c}`).join(`
@@ -31215,7 +31550,8 @@ function buildBatchStorySection(stories) {
31215
31550
  story.description,
31216
31551
  "",
31217
31552
  "**Acceptance Criteria:**",
31218
- criteria
31553
+ criteria,
31554
+ ...outOfScopeLines(story)
31219
31555
  ].join(`
31220
31556
  `);
31221
31557
  });
@@ -31255,6 +31591,7 @@ function buildStoryReminderSection(story) {
31255
31591
  "",
31256
31592
  "**Acceptance Criteria:**",
31257
31593
  criteria,
31594
+ ...outOfScopeLines(story),
31258
31595
  "",
31259
31596
  "<!-- END USER-SUPPLIED DATA -->"
31260
31597
  ].join(`
@@ -31277,11 +31614,13 @@ function buildStorySection(story) {
31277
31614
  "",
31278
31615
  "**Acceptance Criteria:**",
31279
31616
  criteria,
31617
+ ...outOfScopeLines(story),
31280
31618
  "",
31281
31619
  "<!-- END USER-SUPPLIED DATA -->"
31282
31620
  ].join(`
31283
31621
  `);
31284
31622
  }
31623
+ var init_story = () => {};
31285
31624
 
31286
31625
  // src/prompts/sections/verdict.ts
31287
31626
  function buildVerdictSection(story) {
@@ -31528,6 +31867,7 @@ When the story is ambiguous, pick an interpretation, proceed, and document the c
31528
31867
  var init_sections2 = __esm(() => {
31529
31868
  init_hermetic();
31530
31869
  init_role_task();
31870
+ init_story();
31531
31871
  init_acceptance();
31532
31872
  });
31533
31873
 
@@ -32292,6 +32632,7 @@ Notes:
32292
32632
  - \`inspectedFiles\` must list the relative paths you actually opened while reviewing. A \`passed:true\` verdict with an empty or absent \`inspectedFiles\` is invalid \u2014 walk each AC against the real files before passing.
32293
32633
  If all ACs are correctly implemented after inspecting the code, respond with { "passed": true, "inspectedFiles": ["..."], "findings": [] }.`, ReviewPromptBuilder;
32294
32634
  var init_review_builder = __esm(() => {
32635
+ init_sections2();
32295
32636
  SEMANTIC_ROLE = "You are a semantic code reviewer with access to the repository files. " + "Your job is to walk each acceptance criterion (AC) and judge whether the production code fulfills it \u2014 fully, partially, or not at all. " + "Test coverage gaps and convention/lint issues are out of scope \u2014 adversarial review and lint/typecheck handle those.";
32296
32637
  ReviewPromptBuilder = class ReviewPromptBuilder {
32297
32638
  buildSemanticReviewPrompt(story, semanticConfig, options) {
@@ -32317,7 +32658,7 @@ ${semanticConfig.rules.map((r, i) => `${i + 1}. ${r}`).join(`
32317
32658
  ${story.description}
32318
32659
 
32319
32660
  ### Acceptance Criteria
32320
- ${acList}
32661
+ ${acList}${buildReviewOutOfScopeBlock(story.outOfScope)}
32321
32662
  ${customRulesBlock}${priorIterationsBlock}
32322
32663
  ${SEMANTIC_INSTRUCTIONS}
32323
32664
  ${SEMANTIC_OUTPUT_SCHEMA}
@@ -32557,13 +32898,15 @@ Respond with ONLY a JSON object \u2014 no preamble, no explanation outside the J
32557
32898
  "findings": [
32558
32899
  {
32559
32900
  "severity": "error" | "warning" | "info" | "unverifiable",
32560
- "category": "input" | "error-path" | "abandonment" | "test-gap" | "convention" | "assumption",
32901
+ "category": "input" | "error-path" | "abandonment" | "test-gap" | "convention" | "assumption" | "out-of-scope",
32561
32902
  "file": "relative/path/to/file.ts",
32562
32903
  "line": 42,
32563
32904
  "issue": "Precise description of the weakness",
32564
32905
  "suggestion": "Concrete fix or mitigation",
32565
32906
  "acQuote": "<verbatim substring of one AC bullet constraining this locus \u2014 required for 'error'>",
32566
32907
  "acIndex": 2,
32908
+ "scopeQuote": "<out-of-scope findings ONLY: verbatim substring of one Out of Scope entry>",
32909
+ "scopeIndex": 1,
32567
32910
  "verifiedBy": {
32568
32911
  "command": "command used to inspect the current codebase",
32569
32912
  "file": "relative/path/to/file.ts",
@@ -32609,10 +32952,19 @@ Worked example:
32609
32952
  **Exception \u2014 the trap does NOT apply to \`category:"test-gap"\` findings.** A fake/placeholder/missing test is the *absence* of verification for an AC's behaviour; it cannot name a symbol that is present in the (worthless) test file, because the defect is precisely that the symbol-under-test is never exercised. A \`test-gap\` finding is grounded by the AC whose behaviour goes unverified \u2014 cite that AC's \`acIndex\` and a verbatim \`acQuote\` substring from it, and keep severity \`"error"\`. The symbol-naming requirement is waived for this category.
32610
32953
 
32611
32954
  **Scope constraints are not Acceptance Criteria:**
32612
- The story description may contain a "Scope" section with "In:" and "Out:" bullets. These are implementation guidelines, not ACs. A finding about code changed outside the stated scope (e.g., a file listed under "Out:") cannot cite a scope constraint as its \`acQuote\`/\`acIndex\` because scope text is not in the numbered AC list. Emit scope-violation findings as \`"warning"\` \u2014 never \`"error"\`. Never use \`acIndex: 0\`; \`acIndex\` is 1-based (first AC bullet = 1).
32955
+ Scope boundaries reach you two ways: the story description may contain a "Scope" section with "In:" and "Out:" bullets (inter-story boundaries), and the story may carry a numbered **Out of Scope** list (feature-level exclusions the spec declared). Neither is an AC.
32956
+
32957
+ A finding about code that crossed one of these boundaries must NOT cite an AC \u2014 \`acQuote\`/\`acIndex\` are for acceptance criteria only, and scope text is not in the numbered AC list. Instead:
32958
+ - Set \`category\` to \`"out-of-scope"\`.
32959
+ - When the boundary comes from the numbered **Out of Scope** list, set \`scopeQuote\` to a verbatim substring of that entry and \`scopeIndex\` to its 1-based number. A \`scopeQuote\` that is not a verbatim substring of the entry you indexed is discarded.
32960
+ - When the boundary is only a description "Out:" bullet, quote it in \`issue\` and leave \`scopeQuote\`/\`scopeIndex\` unset.
32961
+ - Emit scope-violation findings as \`"warning"\` \u2014 never \`"error"\`. Reporting the boundary is the goal; it does not block the story.
32962
+
32963
+ Never use \`acIndex: 0\`; \`acIndex\` is 1-based (first AC bullet = 1). The same applies to \`scopeIndex\`.
32613
32964
 
32614
32965
  If you cannot find an AC that names the **specific symbol** in your finding, downgrade to \`"info"\` or \`"warning"\`. A finding dropped by the validator is worse than one correctly classified as advisory.`, AdversarialReviewPromptBuilder;
32615
32966
  var init_adversarial_review_builder = __esm(() => {
32967
+ init_sections2();
32616
32968
  AdversarialReviewPromptBuilder = class AdversarialReviewPromptBuilder {
32617
32969
  buildAdversarialReviewPrompt(story, config2, options) {
32618
32970
  const {
@@ -32636,7 +32988,7 @@ var init_adversarial_review_builder = __esm(() => {
32636
32988
 
32637
32989
  **Acceptance Criteria:**
32638
32990
  ${story.acceptanceCriteria.map((ac, i) => `${i + 1}. ${ac}`).join(`
32639
- `)}
32991
+ `)}${buildReviewOutOfScopeBlock(story.outOfScope, { citable: true })}
32640
32992
 
32641
32993
  `;
32642
32994
  const customRulesBlock = config2.rules.length > 0 ? `## Project-Specific Adversarial Rules
@@ -33190,7 +33542,49 @@ function filterByAcGroundingMinimal(findings, acceptanceCriteria) {
33190
33542
  }
33191
33543
  return { accepted, dropped };
33192
33544
  }
33193
- var BLOCKING_SEVERITIES;
33545
+ function claimsScopeViolation(finding) {
33546
+ return finding.category === "out-of-scope";
33547
+ }
33548
+ function validateScopeQuote(finding, outOfScope) {
33549
+ if (!claimsScopeViolation(finding))
33550
+ return { valid: true };
33551
+ const { scopeQuote, scopeIndex } = finding;
33552
+ if (scopeQuote === undefined)
33553
+ return { valid: true };
33554
+ if (typeof scopeQuote !== "string" || scopeQuote.trim().length < MIN_SCOPE_QUOTE_LENGTH) {
33555
+ return { valid: false, code: "missing_scope_quote" };
33556
+ }
33557
+ if (outOfScope.length === 0) {
33558
+ return { valid: false, code: "no_out_of_scope_declared" };
33559
+ }
33560
+ if (typeof scopeIndex !== "number" || scopeIndex < 1 || scopeIndex > outOfScope.length) {
33561
+ return { valid: false, code: "scope_index_out_of_range" };
33562
+ }
33563
+ const entry = normalizeWs2(stripMarkdownInline(outOfScope[scopeIndex - 1]));
33564
+ const quote = normalizeWs2(stripMarkdownInline(scopeQuote));
33565
+ if (!entry.toLowerCase().includes(quote.toLowerCase())) {
33566
+ return { valid: false, code: "scope_quote_not_substring" };
33567
+ }
33568
+ return { valid: true };
33569
+ }
33570
+ function filterByScopeQuote(findings, outOfScope) {
33571
+ const accepted = [];
33572
+ const dropped = [];
33573
+ for (const finding of findings) {
33574
+ if (!claimsScopeViolation(finding)) {
33575
+ accepted.push(finding.scopeQuote === undefined && finding.scopeIndex === undefined ? finding : { ...finding, scopeQuote: undefined, scopeIndex: undefined });
33576
+ continue;
33577
+ }
33578
+ const result = validateScopeQuote(finding, outOfScope);
33579
+ if (result.valid) {
33580
+ accepted.push(finding);
33581
+ } else {
33582
+ dropped.push({ finding, code: result.code });
33583
+ }
33584
+ }
33585
+ return { accepted, dropped };
33586
+ }
33587
+ var BLOCKING_SEVERITIES, MIN_SCOPE_QUOTE_LENGTH = 3;
33194
33588
  var init_ac_quote_validator = __esm(() => {
33195
33589
  BLOCKING_SEVERITIES = new Set(["error", "critical"]);
33196
33590
  });
@@ -33393,6 +33787,17 @@ function warnOnDroppedVerbatimAcs(prd, specContent, featureName) {
33393
33787
  getSafeLogger()?.warn("plan", "[verbatim] spec acceptance criteria dropped from PRD \u2014 run spec-review --prd before executing", { featureName, missingCount: missing.length, missing });
33394
33788
  }
33395
33789
  }
33790
+ function backfillOutOfScope(prd, specContent, featureName) {
33791
+ const missing = findMissingOutOfScope(specContent, prd);
33792
+ if (missing.length === 0)
33793
+ return prd;
33794
+ getSafeLogger()?.warn("plan", "Spec out-of-scope statements dropped from PRD \u2014 backfilled verbatim from the spec", {
33795
+ featureName,
33796
+ missingCount: missing.length,
33797
+ missing
33798
+ });
33799
+ return applyOutOfScopeFallback(prd, specContent);
33800
+ }
33396
33801
  function warnOnSpecDrift(prd, featureName) {
33397
33802
  const violations = findSpecDriftViolations(prd);
33398
33803
  if (violations.length > 0) {
@@ -33461,7 +33866,7 @@ ${outputFormat}`, overridable: false }
33461
33866
  if (!parsed.userStories || parsed.userStories.length === 0)
33462
33867
  return null;
33463
33868
  warnOnDroppedVerbatimAcs(parsed, input.specContent, input.featureName);
33464
- return parsed;
33869
+ return backfillOutOfScope(parsed, input.specContent, input.featureName);
33465
33870
  },
33466
33871
  recover: async (input, ctx) => {
33467
33872
  const content = await ctx.readFile(input.outputPath);
@@ -33659,6 +34064,32 @@ function verbatimSelfHealStep(builder) {
33659
34064
  }
33660
34065
  });
33661
34066
  }
34067
+ async function readMissingOutOfScope(input) {
34068
+ const content = await _planRefineDeps.readFile(input.outputPath);
34069
+ if (!content)
34070
+ return [];
34071
+ try {
34072
+ const prd = validatePlanOutput(content, input.featureName, input.branchName);
34073
+ return findMissingOutOfScope(input.specContent, prd);
34074
+ } catch (err) {
34075
+ getSafeLogger()?.debug("plan", "Skipped out-of-scope self-heal \u2014 draft PRD not yet parseable", {
34076
+ featureName: input.featureName,
34077
+ error: errorMessage(err)
34078
+ });
34079
+ return [];
34080
+ }
34081
+ }
34082
+ function outOfScopeSelfHealStep(builder) {
34083
+ return makeSelfHealStep({
34084
+ detect: (input) => readMissingOutOfScope(input),
34085
+ buildRepair: (missing, input) => builder.buildOutOfScopeRepair(missing, input.outputPath),
34086
+ log: {
34087
+ kind: "plan",
34088
+ message: "Refine dropped spec out-of-scope statements \u2014 issuing one repair turn",
34089
+ meta: (input, missing) => ({ featureName: input.featureName, missingCount: missing.length })
34090
+ }
34091
+ });
34092
+ }
33662
34093
  function specDriftSelfHealStep(builder) {
33663
34094
  return makeSelfHealStep({
33664
34095
  detect: (input) => readSpecDriftViolations(input),
@@ -33765,6 +34196,7 @@ ${outputFormat}`,
33765
34196
  };
33766
34197
  const steps = [
33767
34198
  verbatimSelfHealStep(builder),
34199
+ outOfScopeSelfHealStep(builder),
33768
34200
  ...specGuard ? [specDriftSelfHealStep(builder)] : []
33769
34201
  ];
33770
34202
  return runSelfHealChain(ctx, seed, steps);
@@ -33778,7 +34210,8 @@ ${outputFormat}`,
33778
34210
  if (ctx.config.plan.specGuard) {
33779
34211
  warnOnSpecDrift(validated, input.featureName);
33780
34212
  }
33781
- return await normalizeCreatedContextFiles(validated, input.workdir, ctx.fileExists);
34213
+ const scoped = backfillOutOfScope(validated, input.specContent, input.featureName);
34214
+ return await normalizeCreatedContextFiles(scoped, input.workdir, ctx.fileExists);
33782
34215
  },
33783
34216
  recover: async (input, ctx) => {
33784
34217
  const content = await ctx.readFile(input.outputPath);
@@ -35201,6 +35634,8 @@ var init_ac_structural_counterfactual = __esm(() => {
35201
35634
 
35202
35635
  // src/review/category-fix-target.ts
35203
35636
  function categoryToFixTarget(category) {
35637
+ if (category === "out-of-scope")
35638
+ return "source";
35204
35639
  return category != null && BLOCKING_CATEGORIES.has(category) ? "source" : "test";
35205
35640
  }
35206
35641
  var init_category_fix_target = __esm(() => {
@@ -35239,6 +35674,10 @@ function toAdversarialReviewFindings(findings) {
35239
35674
  metaExtras.acIndex = f.acIndex;
35240
35675
  if (f.verifiedBy)
35241
35676
  metaExtras.verifiedBy = f.verifiedBy;
35677
+ if (f.scopeQuote)
35678
+ metaExtras.scopeQuote = f.scopeQuote;
35679
+ if (f.scopeIndex != null)
35680
+ metaExtras.scopeIndex = f.scopeIndex;
35242
35681
  return {
35243
35682
  source: "adversarial-review",
35244
35683
  severity: normalizeSeverity(f.severity),
@@ -35479,9 +35918,9 @@ function parseRequoteResponse(output) {
35479
35918
  const parsed = tryParseLLMJson(output);
35480
35919
  if (!isRecord(parsed))
35481
35920
  return null;
35482
- const canonical2 = extractCanonical(parsed);
35483
- if (canonical2)
35484
- return canonical2;
35921
+ const canonical3 = extractCanonical(parsed);
35922
+ if (canonical3)
35923
+ return canonical3;
35485
35924
  const findings = parsed.findings;
35486
35925
  if (!Array.isArray(findings) || findings.length !== 1)
35487
35926
  return null;
@@ -36195,7 +36634,28 @@ var init_adversarial_review = __esm(() => {
36195
36634
  storyId: input.story.id,
36196
36635
  blockingThreshold: threshold
36197
36636
  });
36198
- const { accepted, dropped } = filterByAcQuote(substantiated, input.story.acceptanceCriteria);
36637
+ const { accepted: scopeGrounded, dropped: scopeDropped } = filterByScopeQuote(substantiated, input.story.outOfScope ?? []);
36638
+ for (const entry of scopeDropped) {
36639
+ getSafeLogger()?.info("review", "Adversarial scope finding dropped (ungrounded scopeQuote)", {
36640
+ storyId: input.story.id,
36641
+ event: "review.adversarial.scope_quote_dropped",
36642
+ file: entry.finding.file,
36643
+ code: entry.code
36644
+ });
36645
+ }
36646
+ for (const finding of scopeGrounded) {
36647
+ if (finding.category !== "out-of-scope" && finding.scopeQuote === undefined)
36648
+ continue;
36649
+ getSafeLogger()?.info("review", "Adversarial scope finding accepted (advisory)", {
36650
+ storyId: input.story.id,
36651
+ event: "review.adversarial.scope_finding_accepted",
36652
+ file: finding.file,
36653
+ severity: finding.severity,
36654
+ grounded: finding.scopeQuote !== undefined,
36655
+ declaredExclusions: (input.story.outOfScope ?? []).length
36656
+ });
36657
+ }
36658
+ const { accepted, dropped } = filterByAcQuote(scopeGrounded, input.story.acceptanceCriteria);
36199
36659
  const recurrenceCfg = input.adversarialConfig.recurrenceDemotion ?? { enabled: true, maxBlockingRounds: 2 };
36200
36660
  const patterns = input.resolvedTestPatterns?.regex ?? [];
36201
36661
  const testFileMatch = (file3) => patterns.some((re) => re.test(file3));
@@ -41815,7 +42275,7 @@ var package_default;
41815
42275
  var init_package = __esm(() => {
41816
42276
  package_default = {
41817
42277
  name: "@nathapp/nax",
41818
- version: "0.73.4",
42278
+ version: "0.74.0",
41819
42279
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
41820
42280
  type: "module",
41821
42281
  bin: {
@@ -41826,9 +42286,9 @@ var init_package = __esm(() => {
41826
42286
  dev: "bun run bin/nax.ts",
41827
42287
  build: 'bun build bin/nax.ts --outdir dist --target bun --define "GIT_COMMIT=\\"$(git rev-parse --short HEAD)\\""',
41828
42288
  typecheck: "bun x tsc --noEmit && bun x tsc --noEmit -p tsconfig.contracts.json",
41829
- lint: "bun x biome check src/ bin/ && bun run check:no-real-global-nax && bun run check:alias-internals && bun run check:deep-relatives && bun run check:nax-error && bun run check:logger-storyid && bun run check:log-format-layering && bun run check:file-sizes",
41830
- "lint:json": "bun x biome check src/ bin/ --reporter json && bun run check:nax-error 1>&2 && bun run check:logger-storyid 1>&2",
41831
- "lint:fix": "bun x biome check --write src/ bin/",
42289
+ lint: "bun x biome check src/ bin/ flows/ && bun run check:no-real-global-nax && bun run check:alias-internals && bun run check:deep-relatives && bun run check:nax-error && bun run check:logger-storyid && bun run check:log-format-layering && bun run check:file-sizes",
42290
+ "lint:json": "bun x biome check src/ bin/ flows/ --reporter json && bun run check:nax-error 1>&2 && bun run check:logger-storyid 1>&2",
42291
+ "lint:fix": "bun x biome check --write src/ bin/ flows/",
41832
42292
  "check:no-real-global-nax": "bun run scripts/check-no-real-global-nax.ts",
41833
42293
  "check:alias-internals": "bun run scripts/check-alias-internals.ts",
41834
42294
  "check:deep-relatives": "bun run scripts/check-deep-relatives.ts",
@@ -41865,6 +42325,7 @@ var init_package = __esm(() => {
41865
42325
  },
41866
42326
  dependencies: {
41867
42327
  "@types/react": "^19.2.14",
42328
+ acpx: "^0.12.1",
41868
42329
  chalk: "^5.6.2",
41869
42330
  commander: "^13.1.0",
41870
42331
  ink: "^6.7.0",
@@ -41890,6 +42351,7 @@ var init_package = __esm(() => {
41890
42351
  ],
41891
42352
  files: [
41892
42353
  "dist/",
42354
+ "flows/",
41893
42355
  "README.md",
41894
42356
  "CHANGELOG.md"
41895
42357
  ],
@@ -41916,8 +42378,8 @@ var init_version = __esm(() => {
41916
42378
  NAX_VERSION = package_default.version;
41917
42379
  NAX_COMMIT = (() => {
41918
42380
  try {
41919
- if (/^[0-9a-f]{6,10}$/.test("ec04b570"))
41920
- return "ec04b570";
42381
+ if (/^[0-9a-f]{6,10}$/.test("91bb7306"))
42382
+ return "91bb7306";
41921
42383
  } catch {}
41922
42384
  try {
41923
42385
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -45067,6 +45529,9 @@ Re-check routing.complexity and routing.testStrategy against the current codebas
45067
45529
  #### regression-coverage
45068
45530
  If a story changes existing behavior, extracts a shared helper, extends an existing function signature, or replaces a warning/stub path with real behavior, ensure there is at least one acceptance criterion protecting backward compatibility or proving the old placeholder behavior is gone.
45069
45531
 
45532
+ #### out-of-scope-preservation
45533
+ If the spec has an "Out of Scope", "Non-Goals", or "Not in scope" section \u2014 or an inline \`**Out of scope \u2026:**\` lead-in \u2014 enumerate every item it states and confirm each appears in the top-level \`outOfScope\` array. Restore any that are missing, verbatim. Never convert one into an acceptance criterion, and never delete one because it looks obvious. Where a story sits close to one of these boundaries, echo the item into that story's \`**Scope** \u2014 Out:\` bullet too.
45534
+
45070
45535
  #### scope-consistency
45071
45536
  Check each story's title, description, scope, contextFiles, and acceptance criteria for internal consistency. If the story says a file or command is in scope anywhere else, do not list it as out of scope. If the title or acceptance criteria clearly include CLI, output, tests, or helper extraction work, the Scope section must reflect that accurately.${specGuardItems}
45072
45537
 
@@ -45105,6 +45570,24 @@ For each one:
45105
45570
  - Preserve every backtick-quoted command, file path, regex, and count exactly as written in the spec. Do not paraphrase, retag, split, or move them into a description.
45106
45571
  - Do not remove or weaken any acceptance criteria that are already correct.
45107
45572
 
45573
+ Write the corrected PRD to this file path: ${outputFilePath}
45574
+ Do not output the PRD in chat. After writing the file, reply with a brief text confirmation only.`;
45575
+ }
45576
+ buildOutOfScopeRepair(missing, outputFilePath) {
45577
+ const list = missing.map((item) => `- ${item}`).join(`
45578
+ `);
45579
+ return `Your revised PRD dropped feature-level exclusions the spec declared out of scope. These are the only channel by which a deferred arc reaches the implementer \u2014 the implementer never sees the spec, so a dropped exclusion means nothing stops it from building work this feature deliberately defers.
45580
+
45581
+ The following out-of-scope statements are missing from the top-level \`outOfScope\` array:
45582
+
45583
+ ${list}
45584
+
45585
+ For each one:
45586
+ - Add it to the top-level \`outOfScope\` array, preserving the spec's wording. You may append a short clarifier, but never drop or merge an item.
45587
+ - Never convert an out-of-scope statement into an acceptance criterion \u2014 it describes work NOT to do.
45588
+ - Where a story sits close enough to the boundary that an implementer might stray across it, also echo the item into that story's \`**Scope** \u2014 Out:\` bullet.
45589
+ - Do not remove or weaken anything already correct.
45590
+
45108
45591
  Write the corrected PRD to this file path: ${outputFilePath}
45109
45592
  Do not output the PRD in chat. After writing the file, reply with a brief text confirmation only.`;
45110
45593
  }
@@ -45185,6 +45668,7 @@ Generate a JSON object with this exact structure (no markdown, no explanation \u
45185
45668
  "branchName": "string \u2014 git branch (e.g. feat/my-feature)",
45186
45669
  "createdAt": "ISO 8601 timestamp",
45187
45670
  "updatedAt": "ISO 8601 timestamp",
45671
+ ${OUT_OF_SCOPE_SCHEMA_FIELD}
45188
45672
  "userStories": [
45189
45673
  {
45190
45674
  "id": "string \u2014 e.g. US-001",
@@ -45193,6 +45677,7 @@ Generate a JSON object with this exact structure (no markdown, no explanation \u
45193
45677
  "acceptanceCriteria": ["string \u2014 behavioral, testable criteria. Format: 'When [X], then [Y]'. One assertion per AC. Never include quality gates."],${suggestedCriteriaField}
45194
45678
  "contextFiles": ["string \u2014 EXISTING source files the agent should read (max 5, relative paths)"],
45195
45679
  ${EXPECTED_FILES_SCHEMA_FIELD}
45680
+ ${STORY_OUT_OF_SCOPE_SCHEMA_FIELD}
45196
45681
  "tags": ["string \u2014 routing tags, e.g. feature, security, api"],
45197
45682
  "dependencies": ["string \u2014 story IDs this story depends on"],${workdirField}
45198
45683
  "status": "pending",
@@ -45284,6 +45769,7 @@ Produce a JSON object with this exact structure. Field names are mandatory \u201
45284
45769
  "project": "string \u2014 project name",
45285
45770
  "feature": "string \u2014 feature name (copy from above)",
45286
45771
  "branchName": "string \u2014 git branch name",
45772
+ ${OUT_OF_SCOPE_SCHEMA_FIELD}
45287
45773
  "userStories": [
45288
45774
  {
45289
45775
  "id": "string \u2014 e.g. US-001",
@@ -45292,6 +45778,7 @@ Produce a JSON object with this exact structure. Field names are mandatory \u201
45292
45778
  "acceptanceCriteria": ["string \u2014 behavioral criterion, format: 'When [X], then [Y]'. One assertion per item."],${suggestedCriteriaField}
45293
45779
  "contextFiles": ["string \u2014 EXISTING relative paths the implementer should read (max 5)"],
45294
45780
  ${EXPECTED_FILES_SCHEMA_FIELD}
45781
+ ${STORY_OUT_OF_SCOPE_SCHEMA_FIELD}
45295
45782
  "tags": ["string"],
45296
45783
  "dependencies": ["string \u2014 story IDs this story depends on"],${workdirField}
45297
45784
  "routing": {
@@ -45335,7 +45822,7 @@ ${rows.join(`
45335
45822
  }
45336
45823
  var CONTEXT_VS_EXPECTED_FILES_RULE = `**\`contextFiles\` rule \u2014 files readable when this story runs.** List paths that already exist in the repo today, PLUS any file an UPSTREAM dependency story creates (it does not exist now but will exist by the time this story runs, because dependencies execute first). The pipeline verifies every \`contextFiles\` entry against the filesystem; a path that exists neither on disk nor in an upstream dependency's outputs is treated as a missing-context warning.
45337
45824
 
45338
- **\`expectedFiles\` rule \u2014 files THIS story CREATES.** List every NEW file this story authors (relative paths). A file this story creates belongs here, NEVER in \`contextFiles\` \u2014 these are the story's outputs, not files to read first. A file created by an upstream dependency and only read/modified here belongs in \`contextFiles\`, NOT here (this story does not author it). A single path may appear in \`contextFiles\` (an existing sibling to mirror) AND \`expectedFiles\` (the new file itself), but the same path must never be in both.`, EXPECTED_FILES_SCHEMA_FIELD = `"expectedFiles": ["string \u2014 NEW files this story creates (relative paths, omit if none)"],`;
45825
+ **\`expectedFiles\` rule \u2014 files THIS story CREATES.** List every NEW file this story authors (relative paths). A file this story creates belongs here, NEVER in \`contextFiles\` \u2014 these are the story's outputs, not files to read first. A file created by an upstream dependency and only read/modified here belongs in \`contextFiles\`, NOT here (this story does not author it). A single path may appear in \`contextFiles\` (an existing sibling to mirror) AND \`expectedFiles\` (the new file itself), but the same path must never be in both.`, EXPECTED_FILES_SCHEMA_FIELD = `"expectedFiles": ["string \u2014 NEW files this story creates (relative paths, omit if none)"],`, OUT_OF_SCOPE_SCHEMA_FIELD = `"outOfScope": ["string \u2014 verbatim from the spec's Out of Scope / Non-Goals section: what this feature deliberately does NOT do. Omit if the spec declares none."],`, STORY_OUT_OF_SCOPE_SCHEMA_FIELD = `"outOfScope": ["string \u2014 optional, exclusions specific to THIS story beyond the feature-level list. Omit if none."],`;
45339
45826
  var init_plan_builder = __esm(() => {
45340
45827
  init_config();
45341
45828
  init_one_shot_builder();
@@ -45775,6 +46262,7 @@ var init_prompts = __esm(() => {
45775
46262
  init_tdd_builder();
45776
46263
  init_tdd_builder();
45777
46264
  init_debate_builder();
46265
+ init_sections2();
45778
46266
  init_review_builder();
45779
46267
  init_adversarial_review_builder();
45780
46268
  init_acceptance_builder();
@@ -57896,15 +58384,26 @@ function recordOscillations(store, storyId, delta) {
57896
58384
  function getOscillations(store, storyId) {
57897
58385
  return store.get(storyId) ?? 0;
57898
58386
  }
58387
+ function sourceSet(findings) {
58388
+ return new Set((Array.isArray(findings) ? findings : []).map((f) => f.source));
58389
+ }
57899
58390
  function countOscillationOutcomes(iterations) {
58391
+ const resolvedSources = new Set;
57900
58392
  let count = 0;
57901
58393
  for (const iteration of iterations) {
57902
- if (iteration.outcome === OSCILLATION_OUTCOME)
57903
- count += 1;
58394
+ const beforeSources = sourceSet(iteration.findingsBefore);
58395
+ const afterSources = sourceSet(iteration.findingsAfter);
58396
+ for (const source of afterSources) {
58397
+ if (resolvedSources.has(source))
58398
+ count += 1;
58399
+ }
58400
+ for (const source of beforeSources) {
58401
+ if (!afterSources.has(source))
58402
+ resolvedSources.add(source);
58403
+ }
57904
58404
  }
57905
58405
  return count;
57906
58406
  }
57907
- var OSCILLATION_OUTCOME = "regressed-different-source";
57908
58407
 
57909
58408
  // src/execution/checkpoint/resume-plan.ts
57910
58409
  function buildResumePlan(cp, current) {
@@ -63473,6 +63972,218 @@ var init_curator = __esm(() => {
63473
63972
  };
63474
63973
  });
63475
63974
 
63975
+ // src/plugins/builtin/nax-finish/config.ts
63976
+ function selectFinish(config2) {
63977
+ if (!config2 || typeof config2 !== "object")
63978
+ return;
63979
+ return finishConfigSelector.select(config2)?.finish;
63980
+ }
63981
+ function getFinishAutoFlowConfig(ctx) {
63982
+ const autoFlow = selectFinish(ctx.config)?.autoFlow;
63983
+ if (!autoFlow)
63984
+ return DEFAULT_FINISH_AUTO_FLOW_CONFIG;
63985
+ const defaults = DEFAULT_FINISH_AUTO_FLOW_CONFIG;
63986
+ return {
63987
+ enabled: autoFlow.enabled === true,
63988
+ flowPath: autoFlow.flowPath ?? defaults.flowPath,
63989
+ defaultAgent: autoFlow.defaultAgent ?? null,
63990
+ reviewers: {
63991
+ spec: autoFlow.reviewers?.spec ?? null,
63992
+ quality: autoFlow.reviewers?.quality ?? null
63993
+ },
63994
+ escalate: { telegram: autoFlow.escalate?.telegram !== false },
63995
+ timeouts: {
63996
+ acceptanceMs: autoFlow.timeouts?.acceptanceMs ?? defaults.timeouts.acceptanceMs,
63997
+ gateMs: autoFlow.timeouts?.gateMs ?? defaults.timeouts.gateMs,
63998
+ flowMs: autoFlow.timeouts?.flowMs ?? defaults.timeouts.flowMs,
63999
+ stepMs: autoFlow.timeouts?.stepMs ?? defaults.timeouts.stepMs
64000
+ }
64001
+ };
64002
+ }
64003
+ function telegramCreds(config2) {
64004
+ const interaction = config2?.interaction;
64005
+ const tg = interaction?.plugin === "telegram" ? interaction.config ?? {} : {};
64006
+ const token = tg.botToken ?? process.env.NAX_TELEGRAM_TOKEN ?? process.env.TELEGRAM_BOT_TOKEN ?? null;
64007
+ const chatId = tg.chatId ?? process.env.NAX_TELEGRAM_CHAT_ID ?? null;
64008
+ return token && chatId ? { token, chatId } : null;
64009
+ }
64010
+ var DEFAULT_FINISH_AUTO_FLOW_CONFIG;
64011
+ var init_config2 = __esm(() => {
64012
+ init_config();
64013
+ DEFAULT_FINISH_AUTO_FLOW_CONFIG = {
64014
+ enabled: false,
64015
+ flowPath: "flows/nax-finish/nax-finish.flow.ts",
64016
+ defaultAgent: null,
64017
+ reviewers: { spec: null, quality: null },
64018
+ escalate: { telegram: true },
64019
+ timeouts: { acceptanceMs: 600000, gateMs: 900000, flowMs: 5400000, stepMs: null }
64020
+ };
64021
+ });
64022
+
64023
+ // src/plugins/builtin/nax-finish/telegram.ts
64024
+ async function sendTelegramNotify(cfg, text) {
64025
+ const res = await _telegramDeps.fetch(`https://api.telegram.org/bot${cfg.token}/sendMessage`, {
64026
+ method: "POST",
64027
+ headers: { "content-type": "application/json" },
64028
+ body: JSON.stringify({ chat_id: cfg.chatId, text, parse_mode: "Markdown" })
64029
+ });
64030
+ return res.ok;
64031
+ }
64032
+ var _telegramDeps;
64033
+ var init_telegram2 = __esm(() => {
64034
+ _telegramDeps = { fetch: (...a) => fetch(...a) };
64035
+ });
64036
+
64037
+ // src/plugins/builtin/nax-finish/index.ts
64038
+ import * as path21 from "path";
64039
+ async function defaultRun2(cmd, opts) {
64040
+ const proc = Bun.spawn(cmd, { cwd: opts.cwd, env: opts.env, stdout: "pipe", stderr: "pipe" });
64041
+ let timedOut = false;
64042
+ const timer = opts.timeoutMs && opts.timeoutMs > 0 ? setTimeout(() => {
64043
+ timedOut = true;
64044
+ proc.kill();
64045
+ }, opts.timeoutMs) : undefined;
64046
+ try {
64047
+ const [exitCode, stdout, stderr] = await Promise.all([
64048
+ proc.exited,
64049
+ new Response(proc.stdout).text(),
64050
+ new Response(proc.stderr).text()
64051
+ ]);
64052
+ return timedOut ? {
64053
+ exitCode: exitCode === 0 ? 124 : exitCode,
64054
+ stdout,
64055
+ stderr: `${stderr}
64056
+ [nax-finish] flow killed after ${opts.timeoutMs}ms timeout`
64057
+ } : { exitCode, stdout, stderr };
64058
+ } finally {
64059
+ if (timer)
64060
+ clearTimeout(timer);
64061
+ }
64062
+ }
64063
+ async function defaultReadResult(workdir) {
64064
+ const f = Bun.file(path21.join(workdir, ".nax", "nax-finish-result.json"));
64065
+ if (!await f.exists())
64066
+ return null;
64067
+ return JSON.parse(await f.text());
64068
+ }
64069
+ function isFeatureBranch(b) {
64070
+ return b !== "main" && b !== "master" && b.length > 0;
64071
+ }
64072
+ async function resolveFlowPath(workdir, flowPath, deps = _naxFinishDeps) {
64073
+ if (path21.isAbsolute(flowPath)) {
64074
+ return await deps.exists(flowPath) ? flowPath : null;
64075
+ }
64076
+ const candidates = [];
64077
+ let dir = deps.moduleDir;
64078
+ for (let i = 0;i < PACKAGE_ROOT_SEARCH_DEPTH; i += 1) {
64079
+ dir = path21.dirname(dir);
64080
+ if (await deps.exists(path21.join(dir, "package.json")))
64081
+ candidates.push(path21.resolve(dir, flowPath));
64082
+ }
64083
+ candidates.push(path21.resolve(workdir, flowPath));
64084
+ for (const candidate of candidates) {
64085
+ if (await deps.exists(candidate))
64086
+ return candidate;
64087
+ }
64088
+ return null;
64089
+ }
64090
+ function buildFlowArgv(flowPath, inputJson, defaultAgent, stepMs) {
64091
+ const stepTimeout = stepMs && stepMs > 0 ? ["--timeout", String(Math.ceil(stepMs / 1000))] : [];
64092
+ return [
64093
+ "acpx",
64094
+ "--approve-all",
64095
+ ...stepTimeout,
64096
+ "flow",
64097
+ "run",
64098
+ flowPath,
64099
+ "--input-json",
64100
+ inputJson,
64101
+ ...defaultAgent ? ["--default-agent", defaultAgent] : []
64102
+ ];
64103
+ }
64104
+ function buildFlowEnv(cfg) {
64105
+ const env2 = { ...process.env };
64106
+ if (cfg.reviewers.spec)
64107
+ env2.NAX_FINISH_SPEC_PROFILE = cfg.reviewers.spec;
64108
+ if (cfg.reviewers.quality)
64109
+ env2.NAX_FINISH_QUALITY_PROFILE = cfg.reviewers.quality;
64110
+ return env2;
64111
+ }
64112
+ var PLUGIN_NAME4 = "nax-finish", PLUGIN_VERSION4 = "0.1.0", PACKAGE_ROOT_SEARCH_DEPTH = 6, _naxFinishDeps, naxFinishAction, naxFinishPlugin;
64113
+ var init_nax_finish = __esm(() => {
64114
+ init_config2();
64115
+ init_telegram2();
64116
+ _naxFinishDeps = {
64117
+ run: defaultRun2,
64118
+ readResult: defaultReadResult,
64119
+ exists: (p) => Bun.file(p).exists(),
64120
+ moduleDir: import.meta.dir,
64121
+ notify: sendTelegramNotify
64122
+ };
64123
+ naxFinishAction = {
64124
+ name: PLUGIN_NAME4,
64125
+ description: "Autonomously finishes a feature (acceptance -> review -> gates -> PR) via an acpx flow after a successful run",
64126
+ async shouldRun(ctx) {
64127
+ const cfg = getFinishAutoFlowConfig(ctx);
64128
+ if (!cfg.enabled)
64129
+ return false;
64130
+ const s = ctx.storySummary;
64131
+ if (s.completed === 0 || s.failed > 0 || s.paused > 0)
64132
+ return false;
64133
+ return isFeatureBranch(ctx.branch);
64134
+ },
64135
+ async execute(ctx) {
64136
+ try {
64137
+ const cfg = getFinishAutoFlowConfig(ctx);
64138
+ const flowPath = await resolveFlowPath(ctx.workdir, cfg.flowPath);
64139
+ if (!flowPath) {
64140
+ return {
64141
+ success: false,
64142
+ message: `nax-finish: flow module "${cfg.flowPath}" not found in the nax install or ${ctx.workdir}`
64143
+ };
64144
+ }
64145
+ const creds = telegramCreds(ctx.config);
64146
+ const escalateTelegram = cfg.escalate.telegram && creds !== null;
64147
+ const input = {
64148
+ feature: ctx.feature,
64149
+ workdir: ctx.workdir,
64150
+ branch: ctx.branch,
64151
+ prdPath: ctx.prdPath,
64152
+ escalateTelegram,
64153
+ timeouts: { acceptanceMs: cfg.timeouts.acceptanceMs, gateMs: cfg.timeouts.gateMs }
64154
+ };
64155
+ const cmd = buildFlowArgv(flowPath, JSON.stringify(input), cfg.defaultAgent, cfg.timeouts.stepMs);
64156
+ const res = await _naxFinishDeps.run(cmd, {
64157
+ cwd: ctx.workdir,
64158
+ env: buildFlowEnv(cfg),
64159
+ timeoutMs: cfg.timeouts.flowMs
64160
+ });
64161
+ const result = await _naxFinishDeps.readResult(ctx.workdir);
64162
+ if (!result) {
64163
+ return { success: res.exitCode === 0, message: `nax-finish flow exited ${res.exitCode} (no result file)` };
64164
+ }
64165
+ if (result.status === "escalated" && escalateTelegram && creds) {
64166
+ await _naxFinishDeps.notify(creds, `nax-finish escalated *${result.feature}*: ${result.escalationReason ?? ""}`);
64167
+ }
64168
+ return { success: true, message: `nax-finish: ${result.status}`, url: result.url };
64169
+ } catch (err) {
64170
+ ctx.logger.warn("nax-finish execute failed", { error: String(err) });
64171
+ return { success: false, message: `nax-finish failed: ${String(err)}` };
64172
+ }
64173
+ }
64174
+ };
64175
+ naxFinishPlugin = {
64176
+ name: PLUGIN_NAME4,
64177
+ version: PLUGIN_VERSION4,
64178
+ provides: ["post-run-action"],
64179
+ async setup(_config, _logger) {},
64180
+ async teardown() {},
64181
+ extensions: {
64182
+ postRunAction: naxFinishAction
64183
+ }
64184
+ };
64185
+ });
64186
+
63476
64187
  // src/plugins/builtin/reporter-shared/interpolate.ts
63477
64188
  function interpolateHeaders(headers, env2 = process.env) {
63478
64189
  const resolved = {};
@@ -64075,14 +64786,14 @@ var init_validator = __esm(() => {
64075
64786
 
64076
64787
  // src/plugins/loader.ts
64077
64788
  import * as fs from "fs/promises";
64078
- import * as path21 from "path";
64789
+ import * as path22 from "path";
64079
64790
  function getSafeLogger6() {
64080
64791
  return getSafeLogger();
64081
64792
  }
64082
64793
  function extractPluginName(pluginPath) {
64083
- const basename12 = path21.basename(pluginPath);
64794
+ const basename12 = path22.basename(pluginPath);
64084
64795
  if (basename12 === "index.ts" || basename12 === "index.js" || basename12 === "index.mjs") {
64085
- return path21.basename(path21.dirname(pluginPath));
64796
+ return path22.basename(path22.dirname(pluginPath));
64086
64797
  }
64087
64798
  return basename12.replace(/\.(ts|js|mjs)$/, "");
64088
64799
  }
@@ -64118,6 +64829,17 @@ async function loadPlugins(globalDir, projectDir, configPlugins, projectRoot, di
64118
64829
  } else {
64119
64830
  logger?.info("plugins", `Skipping disabled plugin: '${autoPrPlugin.name}' (built-in)`);
64120
64831
  }
64832
+ if (!disabledSet.has(naxFinishPlugin.name)) {
64833
+ if (naxFinishPlugin.setup) {
64834
+ const pluginLogger = createPluginLogger(naxFinishPlugin.name);
64835
+ await naxFinishPlugin.setup({}, pluginLogger);
64836
+ }
64837
+ const action = naxFinishPlugin.extensions.postRunAction;
64838
+ if (action)
64839
+ builtinPostRunActions.push(action);
64840
+ } else {
64841
+ logger?.info("plugins", `Skipping disabled plugin: '${naxFinishPlugin.name}' (built-in)`);
64842
+ }
64121
64843
  if (!disabledSet.has(autoRoutePlugin.name)) {
64122
64844
  if (autoRoutePlugin.setup) {
64123
64845
  const pluginLogger = createPluginLogger(autoRoutePlugin.name);
@@ -64219,7 +64941,7 @@ async function discoverPlugins(dir, isTestFileFn) {
64219
64941
  try {
64220
64942
  const entries = await fs.readdir(dir, { withFileTypes: true });
64221
64943
  for (const entry of entries) {
64222
- const fullPath = path21.join(dir, entry.name);
64944
+ const fullPath = path22.join(dir, entry.name);
64223
64945
  if (entry.isFile()) {
64224
64946
  if (isPluginFile(entry.name, isTestFileFn)) {
64225
64947
  discovered.push({ path: fullPath });
@@ -64227,7 +64949,7 @@ async function discoverPlugins(dir, isTestFileFn) {
64227
64949
  } else if (entry.isDirectory()) {
64228
64950
  const indexPaths = ["index.ts", "index.js", "index.mjs"];
64229
64951
  for (const indexFile of indexPaths) {
64230
- const indexPath = path21.join(fullPath, indexFile);
64952
+ const indexPath = path22.join(fullPath, indexFile);
64231
64953
  try {
64232
64954
  await fs.access(indexPath);
64233
64955
  discovered.push({ path: indexPath });
@@ -64252,13 +64974,13 @@ function isPluginFile(filename, isTestFileFn) {
64252
64974
  return !FALLBACK_TEST_FILE_RE.test(filename);
64253
64975
  }
64254
64976
  function resolveModulePath(modulePath, projectRoot) {
64255
- if (path21.isAbsolute(modulePath) || !modulePath.startsWith("./") && !modulePath.startsWith("../")) {
64977
+ if (path22.isAbsolute(modulePath) || !modulePath.startsWith("./") && !modulePath.startsWith("../")) {
64256
64978
  return modulePath;
64257
64979
  }
64258
64980
  if (projectRoot) {
64259
- return path21.resolve(projectRoot, modulePath);
64981
+ return path22.resolve(projectRoot, modulePath);
64260
64982
  }
64261
- return path21.resolve(modulePath);
64983
+ return path22.resolve(modulePath);
64262
64984
  }
64263
64985
  async function loadAndValidatePlugin(initialModulePath, config2, allowedRoots = [], originalPath) {
64264
64986
  let attemptedPath = initialModulePath;
@@ -64320,6 +65042,7 @@ var init_loader4 = __esm(() => {
64320
65042
  init_auto_pr();
64321
65043
  init_auto_route();
64322
65044
  init_curator();
65045
+ init_nax_finish();
64323
65046
  init_otel_reporter();
64324
65047
  init_webhook_reporter();
64325
65048
  init_plugin_logger();
@@ -64376,7 +65099,7 @@ var init_writer = __esm(() => {
64376
65099
  });
64377
65100
 
64378
65101
  // src/execution/checkpoint/reader.ts
64379
- import { join as join81 } from "path";
65102
+ import { join as join82 } from "path";
64380
65103
  function isValidRecord(value) {
64381
65104
  if (!value || typeof value !== "object")
64382
65105
  return false;
@@ -64409,7 +65132,7 @@ async function defaultRead(filePath) {
64409
65132
  return file3.text();
64410
65133
  }
64411
65134
  async function loadCheckpoints(featureDir, options = { _deps: { read: defaultRead } }) {
64412
- const filePath = join81(featureDir, "checkpoint.jsonl");
65135
+ const filePath = join82(featureDir, "checkpoint.jsonl");
64413
65136
  const deps = options._deps ?? { read: defaultRead };
64414
65137
  let content;
64415
65138
  try {
@@ -64479,7 +65202,7 @@ var init_reader = __esm(() => {
64479
65202
  });
64480
65203
 
64481
65204
  // src/execution/checkpoint/resume-cli.ts
64482
- import { join as join82 } from "path";
65205
+ import { join as join83 } from "path";
64483
65206
  function applyResumeModeDeps(featureDir, mode = "auto") {
64484
65207
  if (mode === "fresh" || mode === "no-resume") {
64485
65208
  _storyOrchestratorDeps.loadCheckpoints = async (_fd) => new Map;
@@ -64489,7 +65212,7 @@ function applyResumeModeDeps(featureDir, mode = "auto") {
64489
65212
  _storyOrchestratorDeps.loadCheckpoints = async (_fd) => loadCheckpoints(target);
64490
65213
  }
64491
65214
  function applyRecordGreenDeps(featureDir, runId) {
64492
- const writer = createCheckpointWriter(join82(featureDir, "checkpoint.jsonl"), runId);
65215
+ const writer = createCheckpointWriter(join83(featureDir, "checkpoint.jsonl"), runId);
64493
65216
  _storyOrchestratorDeps.recordGreen = (storyId, phase, tree) => writer.recordGreen(storyId, phase, tree);
64494
65217
  }
64495
65218
  var init_resume_cli = __esm(() => {
@@ -64519,11 +65242,11 @@ var init_checkpoint = __esm(() => {
64519
65242
  });
64520
65243
 
64521
65244
  // src/hooks/runner.ts
64522
- import { join as join83 } from "path";
65245
+ import { join as join84 } from "path";
64523
65246
  function createDrainDeadline2(deadlineMs) {
64524
65247
  let timeoutId;
64525
- const promise2 = new Promise((resolve16) => {
64526
- timeoutId = setTimeout(() => resolve16(""), deadlineMs);
65248
+ const promise2 = new Promise((resolve17) => {
65249
+ timeoutId = setTimeout(() => resolve17(""), deadlineMs);
64527
65250
  });
64528
65251
  return {
64529
65252
  promise: promise2,
@@ -64538,14 +65261,14 @@ async function loadHooksConfig(projectDir, globalDir) {
64538
65261
  let globalHooks = { hooks: {} };
64539
65262
  let projectHooks = { hooks: {} };
64540
65263
  let skipGlobal = false;
64541
- const projectPath = join83(projectDir, "hooks.json");
65264
+ const projectPath = join84(projectDir, "hooks.json");
64542
65265
  const projectData = await loadJsonFile(projectPath, "hooks");
64543
65266
  if (projectData) {
64544
65267
  projectHooks = projectData;
64545
65268
  skipGlobal = projectData.skipGlobal ?? false;
64546
65269
  }
64547
65270
  if (!skipGlobal && globalDir) {
64548
- const globalPath = join83(globalDir, "hooks.json");
65271
+ const globalPath = join84(globalDir, "hooks.json");
64549
65272
  const globalData = await loadJsonFile(globalPath, "hooks");
64550
65273
  if (globalData) {
64551
65274
  globalHooks = globalData;
@@ -65053,7 +65776,7 @@ var init_crash_recovery = __esm(() => {
65053
65776
  });
65054
65777
 
65055
65778
  // src/acceptance/import-resolution.ts
65056
- import { resolve as resolve16, sep as sep5 } from "path";
65779
+ import { resolve as resolve17, sep as sep5 } from "path";
65057
65780
  function languageFromExtension(testFilePath) {
65058
65781
  if (!testFilePath)
65059
65782
  return;
@@ -65075,8 +65798,8 @@ async function resolveLanguage(opts) {
65075
65798
  return "typescript";
65076
65799
  }
65077
65800
  async function readCapped(relPath, packageDir) {
65078
- const resolvedPackageDir = resolve16(packageDir);
65079
- const fullPath = resolve16(resolvedPackageDir, relPath);
65801
+ const resolvedPackageDir = resolve17(packageDir);
65802
+ const fullPath = resolve17(resolvedPackageDir, relPath);
65080
65803
  if (fullPath !== resolvedPackageDir && !fullPath.startsWith(resolvedPackageDir + sep5)) {
65081
65804
  return null;
65082
65805
  }
@@ -65258,7 +65981,7 @@ var init_fix_diagnosis = __esm(() => {
65258
65981
  });
65259
65982
 
65260
65983
  // src/execution/lifecycle/acceptance-helpers.ts
65261
- import path23 from "path";
65984
+ import path24 from "path";
65262
65985
  function isStubTestFile(content) {
65263
65986
  return isStubTestContent(content);
65264
65987
  }
@@ -65277,7 +66000,7 @@ function isTestLevelFailure(failedACs, totalACs, semanticVerdicts) {
65277
66000
  async function loadSpecContent(featureDir) {
65278
66001
  if (!featureDir)
65279
66002
  return "";
65280
- const specPath = path23.join(featureDir, "spec.md");
66003
+ const specPath = path24.join(featureDir, "spec.md");
65281
66004
  const specFile = Bun.file(specPath);
65282
66005
  return await specFile.exists() ? await specFile.text() : "";
65283
66006
  }
@@ -65297,7 +66020,7 @@ async function loadAcceptanceTestContent2(featureDir, testPaths, configuredTestP
65297
66020
  }
65298
66021
  if (!configuredTestPath)
65299
66022
  return [];
65300
- const resolvedPath = path23.join(featureDir, configuredTestPath);
66023
+ const resolvedPath = path24.join(featureDir, configuredTestPath);
65301
66024
  const testFile = Bun.file(resolvedPath);
65302
66025
  const content = await testFile.exists() ? await testFile.text() : "";
65303
66026
  return [{ content, path: resolvedPath }];
@@ -65314,7 +66037,7 @@ async function regenerateAcceptanceTest(testPath, acceptanceContext) {
65314
66037
  const { unlink: unlink3 } = await import("fs/promises");
65315
66038
  await unlink3(testPath);
65316
66039
  if (acceptanceContext.featureDir) {
65317
- const metaPath = path23.join(acceptanceContext.featureDir, "acceptance-meta.json");
66040
+ const metaPath = path24.join(acceptanceContext.featureDir, "acceptance-meta.json");
65318
66041
  try {
65319
66042
  await unlink3(metaPath);
65320
66043
  } catch {}
@@ -65328,7 +66051,7 @@ async function regenerateAcceptanceTest(testPath, acceptanceContext) {
65328
66051
  const changedFilesRaw = diffOutput.split(`
65329
66052
  `).map((f) => f.trim()).filter((f) => f.length > 0);
65330
66053
  const repoRoot = acceptanceContext.projectDir ?? workdir;
65331
- const packageDir = acceptanceContext.story.workdir && acceptanceContext.projectDir ? path23.join(acceptanceContext.projectDir, acceptanceContext.story.workdir) : undefined;
66054
+ const packageDir = acceptanceContext.story.workdir && acceptanceContext.projectDir ? path24.join(acceptanceContext.projectDir, acceptanceContext.story.workdir) : undefined;
65332
66055
  const ignoreMatchers = acceptanceContext.naxIgnoreIndex?.getMatchers(packageDir) ?? await resolveNaxIgnorePatterns(repoRoot, packageDir);
65333
66056
  const changedFiles = filterNaxInternalPaths(changedFilesRaw, ignoreMatchers);
65334
66057
  const MAX_BYTES = 51200;
@@ -65337,7 +66060,7 @@ async function regenerateAcceptanceTest(testPath, acceptanceContext) {
65337
66060
  for (const file3 of changedFiles) {
65338
66061
  if (totalBytes >= MAX_BYTES)
65339
66062
  break;
65340
- const filePath = path23.join(workdir, file3);
66063
+ const filePath = path24.join(workdir, file3);
65341
66064
  try {
65342
66065
  const fileContent = await _regenerateDeps.readFile(filePath);
65343
66066
  const remaining = MAX_BYTES - totalBytes;
@@ -65775,15 +66498,15 @@ var init_acceptance_loop = __esm(() => {
65775
66498
 
65776
66499
  // src/session/scratch-purge.ts
65777
66500
  import { mkdir as mkdir12, rename, rm } from "fs/promises";
65778
- import { dirname as dirname13, join as join84 } from "path";
66501
+ import { dirname as dirname14, join as join85 } from "path";
65779
66502
  async function purgeStaleScratch(projectDir, featureName, retentionDays, archiveInsteadOfDelete = false) {
65780
- const sessionsDir = join84(projectDir, ".nax", "features", featureName, "sessions");
66503
+ const sessionsDir = join85(projectDir, ".nax", "features", featureName, "sessions");
65781
66504
  const sessionIds = await _scratchPurgeDeps.listSessionDirs(sessionsDir);
65782
66505
  const cutoffMs = _scratchPurgeDeps.now() - retentionDays * 86400000;
65783
66506
  let purged = 0;
65784
66507
  for (const sessionId of sessionIds) {
65785
- const sessionDir = join84(sessionsDir, sessionId);
65786
- const descriptorPath = join84(sessionDir, "descriptor.json");
66508
+ const sessionDir = join85(sessionsDir, sessionId);
66509
+ const descriptorPath = join85(sessionDir, "descriptor.json");
65787
66510
  if (!await _scratchPurgeDeps.fileExists(descriptorPath))
65788
66511
  continue;
65789
66512
  let lastActivityAt;
@@ -65799,7 +66522,7 @@ async function purgeStaleScratch(projectDir, featureName, retentionDays, archive
65799
66522
  if (new Date(lastActivityAt).getTime() >= cutoffMs)
65800
66523
  continue;
65801
66524
  if (archiveInsteadOfDelete) {
65802
- const archiveDest = join84(projectDir, ".nax", "features", featureName, "_archive", "sessions", sessionId);
66525
+ const archiveDest = join85(projectDir, ".nax", "features", featureName, "_archive", "sessions", sessionId);
65803
66526
  await _scratchPurgeDeps.move(sessionDir, archiveDest);
65804
66527
  } else {
65805
66528
  await _scratchPurgeDeps.remove(sessionDir);
@@ -65822,11 +66545,11 @@ var init_scratch_purge = __esm(() => {
65822
66545
  return [];
65823
66546
  }
65824
66547
  },
65825
- fileExists: (path24) => Bun.file(path24).exists(),
65826
- readFile: (path24) => Bun.file(path24).text(),
65827
- remove: (path24) => rm(path24, { recursive: true, force: true }),
66548
+ fileExists: (path25) => Bun.file(path25).exists(),
66549
+ readFile: (path25) => Bun.file(path25).text(),
66550
+ remove: (path25) => rm(path25, { recursive: true, force: true }),
65828
66551
  move: async (src, dest) => {
65829
- await mkdir12(dirname13(dest), { recursive: true });
66552
+ await mkdir12(dirname14(dest), { recursive: true });
65830
66553
  await rename(src, dest);
65831
66554
  },
65832
66555
  now: () => Date.now()
@@ -66670,7 +67393,7 @@ var init_headless_formatter = __esm(() => {
66670
67393
  });
66671
67394
 
66672
67395
  // src/execution/runner-completion.ts
66673
- import path24 from "path";
67396
+ import path25 from "path";
66674
67397
  async function runCompletionPhase(options) {
66675
67398
  const logger = getSafeLogger();
66676
67399
  logger?.debug("execution", "Completion phase started", {
@@ -66690,11 +67413,11 @@ async function runCompletionPhase(options) {
66690
67413
  options.statusWriter.setPostRunPhase("acceptance", { status: "running" });
66691
67414
  pipelineEventBus.emit({ type: "postrun:phase:started", phase: "acceptance" });
66692
67415
  const acceptanceTestPaths = options.featureDir ? await Promise.all((await groupStoriesByPackage(options.prd, options.workdir, options.feature, options.config.acceptance.testPath, options.config.project?.language)).map(async (g) => {
66693
- const relativeWorkdir = path24.relative(options.workdir, g.packageDir);
67416
+ const relativeWorkdir = path25.relative(options.workdir, g.packageDir);
66694
67417
  let groupConfig = options.config;
66695
67418
  if (relativeWorkdir && relativeWorkdir !== ".") {
66696
67419
  try {
66697
- groupConfig = await _runnerCompletionDeps.loadConfigForWorkdir(path24.join(options.workdir, ".nax", "config.json"), relativeWorkdir);
67420
+ groupConfig = await _runnerCompletionDeps.loadConfigForWorkdir(path25.join(options.workdir, ".nax", "config.json"), relativeWorkdir);
66698
67421
  } catch (error48) {
66699
67422
  logger?.warn("execution", "Falling back to root config for package acceptance settings", {
66700
67423
  packageDir: g.packageDir,
@@ -66924,7 +67647,7 @@ function precomputeBatchPlan(stories, maxBatchSize = DEFAULT_MAX_BATCH_SIZE) {
66924
67647
  var DEFAULT_MAX_BATCH_SIZE = 4;
66925
67648
 
66926
67649
  // src/execution/ensure-package-dirs.ts
66927
- import path25 from "path";
67650
+ import path26 from "path";
66928
67651
  async function ensureStoryPackageDirs(prd, workdir, deps = _ensurePackageDirsDeps) {
66929
67652
  const logger = getSafeLogger();
66930
67653
  const relToStoryId = new Map;
@@ -66937,8 +67660,8 @@ async function ensureStoryPackageDirs(prd, workdir, deps = _ensurePackageDirsDep
66937
67660
  }
66938
67661
  const created = [];
66939
67662
  for (const [rel, storyId] of relToStoryId) {
66940
- const abs = path25.resolve(workdir, rel);
66941
- const rootWithSep = workdir.endsWith(path25.sep) ? workdir : workdir + path25.sep;
67663
+ const abs = path26.resolve(workdir, rel);
67664
+ const rootWithSep = workdir.endsWith(path26.sep) ? workdir : workdir + path26.sep;
66942
67665
  if (abs !== workdir && !abs.startsWith(rootWithSep)) {
66943
67666
  logger?.warn("execution", "Skipping story workdir outside repo root", {
66944
67667
  storyId,
@@ -66980,12 +67703,12 @@ var init_ensure_package_dirs = __esm(() => {
66980
67703
 
66981
67704
  // src/pipeline/subscribers/events-writer.ts
66982
67705
  import { appendFile as appendFile5, mkdir as mkdir13 } from "fs/promises";
66983
- import { basename as basename15, join as join85 } from "path";
67706
+ import { basename as basename15, join as join86 } from "path";
66984
67707
  function wireEventsWriter(bus, feature, runId, workdir) {
66985
67708
  const logger = getSafeLogger();
66986
67709
  const project = basename15(workdir);
66987
- const eventsDir = join85(getEventsRootDir(), project);
66988
- const eventsFile = join85(eventsDir, "events.jsonl");
67710
+ const eventsDir = join86(getEventsRootDir(), project);
67711
+ const eventsFile = join86(eventsDir, "events.jsonl");
66989
67712
  let dirReady = false;
66990
67713
  const write = (line) => {
66991
67714
  return (async () => {
@@ -67166,12 +67889,12 @@ var init_interaction2 = __esm(() => {
67166
67889
 
67167
67890
  // src/pipeline/subscribers/registry.ts
67168
67891
  import { mkdir as mkdir14, writeFile as writeFile2 } from "fs/promises";
67169
- import { basename as basename16, join as join86 } from "path";
67892
+ import { basename as basename16, join as join87 } from "path";
67170
67893
  function wireRegistry(bus, feature, runId, workdir, outputDir) {
67171
67894
  const logger = getSafeLogger();
67172
67895
  const project = basename16(workdir);
67173
- const runDir = join86(getRunsDir(), `${project}-${feature}-${runId}`);
67174
- const metaFile = join86(runDir, "meta.json");
67896
+ const runDir = join87(getRunsDir(), `${project}-${feature}-${runId}`);
67897
+ const metaFile = join87(runDir, "meta.json");
67175
67898
  const unsub = bus.on("run:started", (_ev) => {
67176
67899
  return (async () => {
67177
67900
  try {
@@ -67181,8 +67904,8 @@ function wireRegistry(bus, feature, runId, workdir, outputDir) {
67181
67904
  project,
67182
67905
  feature,
67183
67906
  workdir,
67184
- statusPath: join86(outputDir, "features", feature, "status.json"),
67185
- eventsDir: join86(outputDir, "features", feature, "runs"),
67907
+ statusPath: join87(outputDir, "features", feature, "status.json"),
67908
+ eventsDir: join87(outputDir, "features", feature, "runs"),
67186
67909
  registeredAt: new Date().toISOString()
67187
67910
  };
67188
67911
  await writeFile2(metaFile, JSON.stringify(meta3, null, 2));
@@ -67428,7 +68151,7 @@ var init_types10 = __esm(() => {
67428
68151
 
67429
68152
  // src/worktree/dependencies.ts
67430
68153
  import { existsSync as existsSync33 } from "fs";
67431
- import { join as join87 } from "path";
68154
+ import { join as join88 } from "path";
67432
68155
  async function prepareWorktreeDependencies(options) {
67433
68156
  const mode = options.config.execution.worktreeDependencies.mode;
67434
68157
  const resolvedCwd = resolveDependencyCwd(options);
@@ -67442,7 +68165,7 @@ async function prepareWorktreeDependencies(options) {
67442
68165
  }
67443
68166
  }
67444
68167
  function resolveDependencyCwd(options) {
67445
- return options.storyWorkdir ? join87(options.worktreeRoot, options.storyWorkdir) : options.worktreeRoot;
68168
+ return options.storyWorkdir ? join88(options.worktreeRoot, options.storyWorkdir) : options.worktreeRoot;
67446
68169
  }
67447
68170
  function resolveInheritedDependencies(options, resolvedCwd) {
67448
68171
  if (hasDependencyManifests(options.worktreeRoot, resolvedCwd)) {
@@ -67452,7 +68175,7 @@ function resolveInheritedDependencies(options, resolvedCwd) {
67452
68175
  }
67453
68176
  function hasDependencyManifests(worktreeRoot, resolvedCwd) {
67454
68177
  const directories = resolvedCwd === worktreeRoot ? [worktreeRoot] : [worktreeRoot, resolvedCwd];
67455
- return directories.some((directory) => PHASE_ONE_INHERIT_UNSUPPORTED_FILES.some((filename) => _worktreeDependencyDeps.existsSync(join87(directory, filename))));
68178
+ return directories.some((directory) => PHASE_ONE_INHERIT_UNSUPPORTED_FILES.some((filename) => _worktreeDependencyDeps.existsSync(join88(directory, filename))));
67456
68179
  }
67457
68180
  async function provisionDependencies(config2, worktreeRoot, resolvedCwd) {
67458
68181
  const setupCommand2 = config2.execution.worktreeDependencies.setupCommand;
@@ -67516,13 +68239,13 @@ __export(exports_manager, {
67516
68239
  });
67517
68240
  import { existsSync as existsSync34, symlinkSync } from "fs";
67518
68241
  import { mkdir as mkdir15 } from "fs/promises";
67519
- import { join as join88 } from "path";
68242
+ import { join as join89 } from "path";
67520
68243
 
67521
68244
  class WorktreeManager {
67522
68245
  async ensureGitExcludes(projectRoot) {
67523
68246
  const logger = getSafeLogger();
67524
- const infoDir = join88(projectRoot, ".git", "info");
67525
- const excludePath = join88(infoDir, "exclude");
68247
+ const infoDir = join89(projectRoot, ".git", "info");
68248
+ const excludePath = join89(infoDir, "exclude");
67526
68249
  try {
67527
68250
  await mkdir15(infoDir, { recursive: true });
67528
68251
  let existing = "";
@@ -67549,7 +68272,7 @@ ${missing.join(`
67549
68272
  }
67550
68273
  async create(projectRoot, storyId) {
67551
68274
  validateStoryId(storyId);
67552
- const worktreePath = join88(projectRoot, ".nax-wt", storyId);
68275
+ const worktreePath = join89(projectRoot, ".nax-wt", storyId);
67553
68276
  const branchName = `nax/${storyId}`;
67554
68277
  try {
67555
68278
  const pruneProc = _managerDeps.spawn(["git", "worktree", "prune"], {
@@ -67610,9 +68333,9 @@ ${missing.join(`
67610
68333
  projectRoot
67611
68334
  });
67612
68335
  }
67613
- const envSource = join88(projectRoot, ".env");
68336
+ const envSource = join89(projectRoot, ".env");
67614
68337
  if (existsSync34(envSource)) {
67615
- const envTarget = join88(worktreePath, ".env");
68338
+ const envTarget = join89(worktreePath, ".env");
67616
68339
  try {
67617
68340
  symlinkSync(envSource, envTarget, "file");
67618
68341
  } catch (error48) {
@@ -67628,7 +68351,7 @@ ${missing.join(`
67628
68351
  }
67629
68352
  async remove(projectRoot, storyId) {
67630
68353
  validateStoryId(storyId);
67631
- const worktreePath = join88(projectRoot, ".nax-wt", storyId);
68354
+ const worktreePath = join89(projectRoot, ".nax-wt", storyId);
67632
68355
  const branchName = `nax/${storyId}`;
67633
68356
  try {
67634
68357
  const proc = _managerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
@@ -68097,9 +68820,9 @@ var _quoteIntegrityDeps, CONTEXT_LINES = 3;
68097
68820
  var init_quote_integrity = __esm(() => {
68098
68821
  init_logger2();
68099
68822
  _quoteIntegrityDeps = {
68100
- readFile: async (path26) => {
68823
+ readFile: async (path27) => {
68101
68824
  try {
68102
- return await Bun.file(path26).text();
68825
+ return await Bun.file(path27).text();
68103
68826
  } catch {
68104
68827
  return null;
68105
68828
  }
@@ -68388,7 +69111,7 @@ var exports_merge_conflict_rectify = {};
68388
69111
  __export(exports_merge_conflict_rectify, {
68389
69112
  rectifyConflictedStory: () => rectifyConflictedStory
68390
69113
  });
68391
- import path26 from "path";
69114
+ import path27 from "path";
68392
69115
  async function closeStaleAcpSession(worktreePath, sessionName) {
68393
69116
  const logger = getSafeLogger();
68394
69117
  try {
@@ -68415,7 +69138,7 @@ async function rectifyConflictedStory(options) {
68415
69138
  await worktreeManager.remove(workdir, storyId);
68416
69139
  } catch {}
68417
69140
  await worktreeManager.create(workdir, storyId);
68418
- const worktreePath = path26.join(workdir, ".nax-wt", storyId);
69141
+ const worktreePath = path27.join(workdir, ".nax-wt", storyId);
68419
69142
  const { formatSessionName: formatSessionName2 } = await Promise.resolve().then(() => (init_naming(), exports_naming));
68420
69143
  const staleSessionName = formatSessionName2({
68421
69144
  workdir: worktreePath,
@@ -68480,10 +69203,10 @@ var init_merge_conflict_rectify = __esm(() => {
68480
69203
  });
68481
69204
 
68482
69205
  // src/execution/pipeline-result-handler.ts
68483
- import { join as join89 } from "path";
69206
+ import { join as join90 } from "path";
68484
69207
  async function removeWorktreeDirectory(projectRoot, storyId) {
68485
69208
  const logger = getSafeLogger();
68486
- const worktreePath = join89(projectRoot, ".nax-wt", storyId);
69209
+ const worktreePath = join90(projectRoot, ".nax-wt", storyId);
68487
69210
  try {
68488
69211
  const proc = _resultHandlerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
68489
69212
  cwd: projectRoot,
@@ -68700,7 +69423,7 @@ var init_pipeline_result_handler = __esm(() => {
68700
69423
 
68701
69424
  // src/execution/iteration-runner.ts
68702
69425
  import { existsSync as existsSync35 } from "fs";
68703
- import { join as join90 } from "path";
69426
+ import { join as join91 } from "path";
68704
69427
  async function runIteration(ctx, prd, selection, iterations, totalCost2, allStoryMetrics) {
68705
69428
  const { story, storiesToExecute, routing, isBatchExecution } = selection;
68706
69429
  if (ctx.dryRun) {
@@ -68725,7 +69448,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost2, allStor
68725
69448
  const storyStartTime = Date.now();
68726
69449
  let effectiveWorkdir = ctx.workdir;
68727
69450
  if (ctx.config.execution.storyIsolation === "worktree") {
68728
- const worktreePath = join90(ctx.workdir, ".nax-wt", story.id);
69451
+ const worktreePath = join91(ctx.workdir, ".nax-wt", story.id);
68729
69452
  const worktreeExists = _iterationRunnerDeps.existsSync(worktreePath);
68730
69453
  if (!worktreeExists) {
68731
69454
  await _iterationRunnerDeps.worktreeManager.ensureGitExcludes(ctx.workdir);
@@ -68745,7 +69468,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost2, allStor
68745
69468
  }
68746
69469
  const accumulatedAttemptCost = (story.priorFailures || []).reduce((sum, f) => sum + (f.cost || 0), 0);
68747
69470
  const profileOverride = profileOverrideFromConfig(ctx.config);
68748
- const effectiveConfig = story.workdir ? await _iterationRunnerDeps.loadConfigForWorkdir(join90(ctx.workdir, ".nax", "config.json"), story.workdir, profileOverride) : ctx.config;
69471
+ const effectiveConfig = story.workdir ? await _iterationRunnerDeps.loadConfigForWorkdir(join91(ctx.workdir, ".nax", "config.json"), story.workdir, profileOverride) : ctx.config;
68749
69472
  let dependencyContext;
68750
69473
  if (ctx.config.execution.storyIsolation === "worktree") {
68751
69474
  try {
@@ -68772,7 +69495,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost2, allStor
68772
69495
  };
68773
69496
  }
68774
69497
  }
68775
- const resolvedWorkdir = dependencyContext?.cwd ? dependencyContext.cwd : ctx.config.execution.storyIsolation === "worktree" ? story.workdir ? join90(effectiveWorkdir, story.workdir) : effectiveWorkdir : story.workdir ? join90(ctx.workdir, story.workdir) : ctx.workdir;
69498
+ const resolvedWorkdir = dependencyContext?.cwd ? dependencyContext.cwd : ctx.config.execution.storyIsolation === "worktree" ? story.workdir ? join91(effectiveWorkdir, story.workdir) : effectiveWorkdir : story.workdir ? join91(ctx.workdir, story.workdir) : ctx.workdir;
68776
69499
  const pipelineContext = {
68777
69500
  config: effectiveConfig,
68778
69501
  rootConfig: ctx.config,
@@ -68975,7 +69698,7 @@ __export(exports_parallel_worker, {
68975
69698
  buildWorktreePipelineContext: () => buildWorktreePipelineContext,
68976
69699
  _parallelWorkerDeps: () => _parallelWorkerDeps
68977
69700
  });
68978
- import { join as join91 } from "path";
69701
+ import { join as join92 } from "path";
68979
69702
  function buildWorktreePipelineContext(base, _story) {
68980
69703
  return { ...base, prd: structuredClone(base.prd) };
68981
69704
  }
@@ -68998,7 +69721,7 @@ async function executeStoryInWorktree(story, worktreePath, dependencyContext, co
68998
69721
  story,
68999
69722
  stories: [story],
69000
69723
  projectDir: context.projectDir,
69001
- workdir: dependencyContext.cwd ?? (story.workdir ? join91(worktreePath, story.workdir) : worktreePath),
69724
+ workdir: dependencyContext.cwd ?? (story.workdir ? join92(worktreePath, story.workdir) : worktreePath),
69002
69725
  worktreeDependencyContext: dependencyContext,
69003
69726
  routing,
69004
69727
  storyGitRef: storyGitRef ?? undefined
@@ -69099,7 +69822,7 @@ __export(exports_parallel_batch, {
69099
69822
  runParallelBatch: () => runParallelBatch,
69100
69823
  _parallelBatchDeps: () => _parallelBatchDeps
69101
69824
  });
69102
- import path27 from "path";
69825
+ import path28 from "path";
69103
69826
  async function runParallelBatch(options) {
69104
69827
  const { stories, ctx, prd } = options;
69105
69828
  const { workdir, config: config2, maxConcurrency, pipelineContext, eventEmitter, agentGetFn, hooks, pluginRegistry } = ctx;
@@ -69118,9 +69841,9 @@ async function runParallelBatch(options) {
69118
69841
  });
69119
69842
  throw error48;
69120
69843
  }
69121
- worktreePaths.set(story.id, path27.join(workdir, ".nax-wt", story.id));
69844
+ worktreePaths.set(story.id, path28.join(workdir, ".nax-wt", story.id));
69122
69845
  }
69123
- const rootConfigPath = path27.join(workdir, ".nax", "config.json");
69846
+ const rootConfigPath = path28.join(workdir, ".nax", "config.json");
69124
69847
  const profileOverride = profileOverrideFromConfig(config2);
69125
69848
  const storyEffectiveConfigs = new Map;
69126
69849
  const configResults = await Promise.allSettled(stories.filter((story) => story.workdir).map(async (story) => {
@@ -69958,7 +70681,7 @@ var init_runner_execution = __esm(() => {
69958
70681
 
69959
70682
  // src/execution/status-file.ts
69960
70683
  import { rename as rename2, unlink as unlink3 } from "fs/promises";
69961
- import { resolve as resolve17 } from "path";
70684
+ import { resolve as resolve18 } from "path";
69962
70685
  function countProgress(prd) {
69963
70686
  const stories = prd.userStories;
69964
70687
  const passed = stories.filter((s) => s.status === "passed").length;
@@ -70003,7 +70726,7 @@ function buildStatusSnapshot(state) {
70003
70726
  return snapshot;
70004
70727
  }
70005
70728
  async function writeStatusFile(filePath, status) {
70006
- const resolvedPath = resolve17(filePath);
70729
+ const resolvedPath = resolve18(filePath);
70007
70730
  if (filePath.includes("../") || filePath.includes("..\\")) {
70008
70731
  throw new Error("Invalid status file path: path traversal detected");
70009
70732
  }
@@ -70017,7 +70740,7 @@ async function writeStatusFile(filePath, status) {
70017
70740
  var init_status_file = () => {};
70018
70741
 
70019
70742
  // src/execution/status-writer.ts
70020
- import { join as join92 } from "path";
70743
+ import { join as join93 } from "path";
70021
70744
 
70022
70745
  class StatusWriter {
70023
70746
  statusFile;
@@ -70136,7 +70859,7 @@ class StatusWriter {
70136
70859
  if (!this._prd)
70137
70860
  return;
70138
70861
  const safeLogger = getSafeLogger();
70139
- const featureStatusPath = join92(featureDir, "status.json");
70862
+ const featureStatusPath = join93(featureDir, "status.json");
70140
70863
  const write = async () => {
70141
70864
  try {
70142
70865
  const base = this.getSnapshot(totalCost2, iterations);
@@ -70169,7 +70892,7 @@ __export(exports_migrate, {
70169
70892
  });
70170
70893
  import { existsSync as existsSync36 } from "fs";
70171
70894
  import { mkdir as mkdir16, readdir as readdir5, rename as rename3 } from "fs/promises";
70172
- import path28 from "path";
70895
+ import path29 from "path";
70173
70896
  async function detectGeneratedContent(naxDir) {
70174
70897
  if (!existsSync36(naxDir))
70175
70898
  return [];
@@ -70182,17 +70905,17 @@ async function detectGeneratedContent(naxDir) {
70182
70905
  }
70183
70906
  for (const entry of entries) {
70184
70907
  if (GENERATED_NAMES.has(entry)) {
70185
- candidates.push({ name: entry, srcPath: path28.join(naxDir, entry) });
70908
+ candidates.push({ name: entry, srcPath: path29.join(naxDir, entry) });
70186
70909
  }
70187
70910
  }
70188
- const featuresDir = path28.join(naxDir, "features");
70911
+ const featuresDir = path29.join(naxDir, "features");
70189
70912
  if (existsSync36(featuresDir)) {
70190
70913
  let featureDirs = [];
70191
70914
  try {
70192
70915
  featureDirs = await readdir5(featuresDir);
70193
70916
  } catch {}
70194
70917
  for (const fid of featureDirs) {
70195
- const featureDir = path28.join(featuresDir, fid);
70918
+ const featureDir = path29.join(featuresDir, fid);
70196
70919
  let subEntries = [];
70197
70920
  try {
70198
70921
  subEntries = await readdir5(featureDir);
@@ -70202,12 +70925,12 @@ async function detectGeneratedContent(naxDir) {
70202
70925
  for (const sub of subEntries) {
70203
70926
  if (GENERATED_FEATURE_SUBNAMES.has(sub)) {
70204
70927
  candidates.push({
70205
- name: path28.join("features", fid, sub),
70206
- srcPath: path28.join(featureDir, sub)
70928
+ name: path29.join("features", fid, sub),
70929
+ srcPath: path29.join(featureDir, sub)
70207
70930
  });
70208
70931
  }
70209
70932
  if (sub === "stories") {
70210
- const storiesDir = path28.join(featureDir, "stories");
70933
+ const storiesDir = path29.join(featureDir, "stories");
70211
70934
  let storyDirs = [];
70212
70935
  try {
70213
70936
  storyDirs = await readdir5(storiesDir);
@@ -70215,7 +70938,7 @@ async function detectGeneratedContent(naxDir) {
70215
70938
  continue;
70216
70939
  }
70217
70940
  for (const sid of storyDirs) {
70218
- const storyDir = path28.join(storiesDir, sid);
70941
+ const storyDir = path29.join(storiesDir, sid);
70219
70942
  let storyEntries = [];
70220
70943
  try {
70221
70944
  storyEntries = await readdir5(storyDir);
@@ -70225,8 +70948,8 @@ async function detectGeneratedContent(naxDir) {
70225
70948
  for (const se of storyEntries) {
70226
70949
  if (se.startsWith("context-manifest-") && se.endsWith(".json")) {
70227
70950
  candidates.push({
70228
- name: path28.join("features", fid, "stories", sid, se),
70229
- srcPath: path28.join(storyDir, se)
70951
+ name: path29.join("features", fid, "stories", sid, se),
70952
+ srcPath: path29.join(storyDir, se)
70230
70953
  });
70231
70954
  }
70232
70955
  }
@@ -70247,15 +70970,15 @@ async function migrateCommand(options) {
70247
70970
  name: options.reclaim
70248
70971
  });
70249
70972
  }
70250
- const src = path28.join(globalConfigDir(), options.reclaim);
70973
+ const src = path29.join(globalConfigDir(), options.reclaim);
70251
70974
  if (!existsSync36(src)) {
70252
70975
  throw new NaxError(`Nothing to reclaim: ~/.nax/${options.reclaim} does not exist`, "MIGRATE_RECLAIM_NOT_FOUND", {
70253
70976
  stage: "migrate",
70254
70977
  name: options.reclaim
70255
70978
  });
70256
70979
  }
70257
- const archiveBase = path28.join(globalConfigDir(), "_archive");
70258
- const archiveDest = path28.join(archiveBase, `${options.reclaim}-${Date.now()}`);
70980
+ const archiveBase = path29.join(globalConfigDir(), "_archive");
70981
+ const archiveDest = path29.join(archiveBase, `${options.reclaim}-${Date.now()}`);
70259
70982
  await mkdir16(archiveBase, { recursive: true });
70260
70983
  await rename3(src, archiveDest);
70261
70984
  logger.info("migrate", `Reclaimed: archived to ${archiveDest}`, { storyId: "_migrate" });
@@ -70292,8 +71015,8 @@ async function migrateCommand(options) {
70292
71015
  logger.info("migrate", `Merged: identity for "${options.merge}" updated`, { storyId: "_migrate" });
70293
71016
  return;
70294
71017
  }
70295
- const naxDir = path28.join(options.workdir, ".nax");
70296
- const configPath = path28.join(naxDir, "config.json");
71018
+ const naxDir = path29.join(options.workdir, ".nax");
71019
+ const configPath = path29.join(naxDir, "config.json");
70297
71020
  if (!existsSync36(configPath)) {
70298
71021
  throw new NaxError("No .nax/config.json found \u2014 run nax init first", "MIGRATE_NO_CONFIG", {
70299
71022
  stage: "migrate",
@@ -70309,7 +71032,7 @@ async function migrateCommand(options) {
70309
71032
  cause: e
70310
71033
  });
70311
71034
  }
70312
- const projectKey = config2.name?.trim() || path28.basename(options.workdir);
71035
+ const projectKey = config2.name?.trim() || path29.basename(options.workdir);
70313
71036
  const destBase = projectOutputDir(projectKey, config2.outputDir);
70314
71037
  const candidates = await detectGeneratedContent(naxDir);
70315
71038
  if (candidates.length === 0) {
@@ -70318,7 +71041,7 @@ async function migrateCommand(options) {
70318
71041
  }
70319
71042
  if (options.dryRun) {
70320
71043
  for (const c of candidates) {
70321
- logger.info("migrate", `[dry-run] Would move: ${c.srcPath} -> ${path28.join(destBase, c.name)}`, {
71044
+ logger.info("migrate", `[dry-run] Would move: ${c.srcPath} -> ${path29.join(destBase, c.name)}`, {
70322
71045
  storyId: "_migrate"
70323
71046
  });
70324
71047
  }
@@ -70327,8 +71050,8 @@ async function migrateCommand(options) {
70327
71050
  await mkdir16(destBase, { recursive: true });
70328
71051
  let moved = 0;
70329
71052
  for (const candidate of candidates) {
70330
- const dest = path28.join(destBase, candidate.name);
70331
- await mkdir16(path28.dirname(dest), { recursive: true });
71053
+ const dest = path29.join(destBase, candidate.name);
71054
+ await mkdir16(path29.dirname(dest), { recursive: true });
70332
71055
  if (existsSync36(dest)) {
70333
71056
  throw new NaxError(`Migration conflict: destination already exists.
70334
71057
  Source: ${candidate.srcPath}
@@ -70358,7 +71081,7 @@ async function migrateCommand(options) {
70358
71081
  moved++;
70359
71082
  logger.info("migrate", `Moved: ${candidate.name}`, { storyId: "_migrate" });
70360
71083
  }
70361
- await Bun.write(path28.join(destBase, ".migrated-from"), JSON.stringify({ from: options.workdir, migratedAt: new Date().toISOString() }, null, 2));
71084
+ await Bun.write(path29.join(destBase, ".migrated-from"), JSON.stringify({ from: options.workdir, migratedAt: new Date().toISOString() }, null, 2));
70362
71085
  logger.info("migrate", `Migration complete: ${moved} entries moved`, {
70363
71086
  storyId: "_migrate",
70364
71087
  destBase
@@ -70475,7 +71198,7 @@ __export(exports_precheck_runner, {
70475
71198
  runPrecheckValidation: () => runPrecheckValidation
70476
71199
  });
70477
71200
  import { mkdirSync as mkdirSync7 } from "fs";
70478
- import path29 from "path";
71201
+ import path30 from "path";
70479
71202
  async function runPrecheckValidation(ctx) {
70480
71203
  const logger = getSafeLogger();
70481
71204
  if (process.env.NAX_PRECHECK !== "1") {
@@ -70490,7 +71213,7 @@ async function runPrecheckValidation(ctx) {
70490
71213
  silent: true
70491
71214
  });
70492
71215
  if (ctx.logFilePath) {
70493
- mkdirSync7(path29.dirname(ctx.logFilePath), { recursive: true });
71216
+ mkdirSync7(path30.dirname(ctx.logFilePath), { recursive: true });
70494
71217
  const precheckLog = {
70495
71218
  type: "precheck",
70496
71219
  timestamp: new Date().toISOString(),
@@ -70580,7 +71303,7 @@ __export(exports_run_initialization, {
70580
71303
  initializeRun: () => initializeRun,
70581
71304
  _reconcileDeps: () => _reconcileDeps
70582
71305
  });
70583
- import { join as join93 } from "path";
71306
+ import { join as join94 } from "path";
70584
71307
  async function reconcileState(prd, prdPath, workdir, config2) {
70585
71308
  const logger = getSafeLogger();
70586
71309
  let reconciledCount = 0;
@@ -70597,7 +71320,7 @@ async function reconcileState(prd, prdPath, workdir, config2) {
70597
71320
  });
70598
71321
  continue;
70599
71322
  }
70600
- const effectiveWorkdir = story.workdir ? join93(workdir, story.workdir) : workdir;
71323
+ const effectiveWorkdir = story.workdir ? join94(workdir, story.workdir) : workdir;
70601
71324
  try {
70602
71325
  const reviewResult = await _reconcileDeps.runReview(config2.review, effectiveWorkdir, config2.execution);
70603
71326
  if (!reviewResult.success) {
@@ -70803,7 +71526,7 @@ __export(exports_run_setup, {
70803
71526
  setupRun: () => setupRun,
70804
71527
  _runSetupDeps: () => _runSetupDeps
70805
71528
  });
70806
- import path30 from "path";
71529
+ import path31 from "path";
70807
71530
  function warnProfileMismatch(prd, config2, logger) {
70808
71531
  const profiles = config2.routing?.agents?.profiles ?? [];
70809
71532
  const profileIds = new Set(profiles.map((p) => p.id));
@@ -70924,7 +71647,7 @@ async function setupRun(options) {
70924
71647
  statusWriter.setPrd(prd);
70925
71648
  {
70926
71649
  const { detectGeneratedContent: detectGeneratedContent2, migrateCommand: migrateCommand2 } = await Promise.resolve().then(() => (init_migrate(), exports_migrate));
70927
- const naxDir = path30.join(workdir, ".nax");
71650
+ const naxDir = path31.join(workdir, ".nax");
70928
71651
  const candidates = await detectGeneratedContent2(naxDir).catch(() => []);
70929
71652
  if (candidates.length > 0) {
70930
71653
  logger?.info("setup", "Found generated content under .nax/ \u2014 migrating to output dir", {
@@ -70951,7 +71674,7 @@ async function setupRun(options) {
70951
71674
  remoteUrl = new TextDecoder().decode(gitResult.stdout).trim() || null;
70952
71675
  }
70953
71676
  } catch {}
70954
- const projectKey = config2.name?.trim() || path30.basename(workdir);
71677
+ const projectKey = config2.name?.trim() || path31.basename(workdir);
70955
71678
  await claimProjectIdentity2(projectKey, workdir, remoteUrl).catch((err) => {
70956
71679
  if (err instanceof NaxError && err.code === "RUN_NAME_COLLISION") {
70957
71680
  throw err;
@@ -71006,8 +71729,8 @@ async function setupRun(options) {
71006
71729
  explicit: Object.fromEntries(explicitFields.map((f) => [f, existingProjectConfig[f]])),
71007
71730
  detected: Object.fromEntries(autodetectedFields.map((f) => [f, detectedProfile[f]]))
71008
71731
  });
71009
- const globalPluginsDir = path30.join(globalConfigDir(), "plugins");
71010
- const projectPluginsDir = path30.join(workdir, ".nax", "plugins");
71732
+ const globalPluginsDir = path31.join(globalConfigDir(), "plugins");
71733
+ const projectPluginsDir = path31.join(workdir, ".nax", "plugins");
71011
71734
  const configPlugins = config2.plugins || [];
71012
71735
  const resolvedPatterns = await resolveTestFilePatterns(config2, workdir);
71013
71736
  const isTestFileFn = (filename) => resolvedPatterns.regex.some((re) => re.test(filename));
@@ -71941,14 +72664,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
71941
72664
  prevActScopeDepth !== actScopeDepth - 1 && console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ");
71942
72665
  actScopeDepth = prevActScopeDepth;
71943
72666
  }
71944
- function recursivelyFlushAsyncActWork(returnValue, resolve18, reject) {
72667
+ function recursivelyFlushAsyncActWork(returnValue, resolve19, reject) {
71945
72668
  var queue = ReactSharedInternals.actQueue;
71946
72669
  if (queue !== null)
71947
72670
  if (queue.length !== 0)
71948
72671
  try {
71949
72672
  flushActQueue(queue);
71950
72673
  enqueueTask(function() {
71951
- return recursivelyFlushAsyncActWork(returnValue, resolve18, reject);
72674
+ return recursivelyFlushAsyncActWork(returnValue, resolve19, reject);
71952
72675
  });
71953
72676
  return;
71954
72677
  } catch (error48) {
@@ -71956,7 +72679,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
71956
72679
  }
71957
72680
  else
71958
72681
  ReactSharedInternals.actQueue = null;
71959
- 0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve18(returnValue);
72682
+ 0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve19(returnValue);
71960
72683
  }
71961
72684
  function flushActQueue(queue) {
71962
72685
  if (!isFlushing) {
@@ -72132,14 +72855,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
72132
72855
  didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = true, console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"));
72133
72856
  });
72134
72857
  return {
72135
- then: function(resolve18, reject) {
72858
+ then: function(resolve19, reject) {
72136
72859
  didAwaitActCall = true;
72137
72860
  thenable.then(function(returnValue) {
72138
72861
  popActScope(prevActQueue, prevActScopeDepth);
72139
72862
  if (prevActScopeDepth === 0) {
72140
72863
  try {
72141
72864
  flushActQueue(queue), enqueueTask(function() {
72142
- return recursivelyFlushAsyncActWork(returnValue, resolve18, reject);
72865
+ return recursivelyFlushAsyncActWork(returnValue, resolve19, reject);
72143
72866
  });
72144
72867
  } catch (error$0) {
72145
72868
  ReactSharedInternals.thrownErrors.push(error$0);
@@ -72150,7 +72873,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
72150
72873
  reject(_thrownError);
72151
72874
  }
72152
72875
  } else
72153
- resolve18(returnValue);
72876
+ resolve19(returnValue);
72154
72877
  }, function(error48) {
72155
72878
  popActScope(prevActQueue, prevActScopeDepth);
72156
72879
  0 < ReactSharedInternals.thrownErrors.length ? (error48 = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(error48)) : reject(error48);
@@ -72166,11 +72889,11 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
72166
72889
  if (0 < ReactSharedInternals.thrownErrors.length)
72167
72890
  throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
72168
72891
  return {
72169
- then: function(resolve18, reject) {
72892
+ then: function(resolve19, reject) {
72170
72893
  didAwaitActCall = true;
72171
72894
  prevActScopeDepth === 0 ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
72172
- return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve18, reject);
72173
- })) : resolve18(returnValue$jscomp$0);
72895
+ return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve19, reject);
72896
+ })) : resolve19(returnValue$jscomp$0);
72174
72897
  }
72175
72898
  };
72176
72899
  };
@@ -72870,11 +73593,11 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
72870
73593
  fiber = fiber.next, id--;
72871
73594
  return fiber;
72872
73595
  }
72873
- function copyWithSetImpl(obj, path31, index, value) {
72874
- if (index >= path31.length)
73596
+ function copyWithSetImpl(obj, path32, index, value) {
73597
+ if (index >= path32.length)
72875
73598
  return value;
72876
- var key = path31[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
72877
- updated[key] = copyWithSetImpl(obj[key], path31, index + 1, value);
73599
+ var key = path32[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
73600
+ updated[key] = copyWithSetImpl(obj[key], path32, index + 1, value);
72878
73601
  return updated;
72879
73602
  }
72880
73603
  function copyWithRename(obj, oldPath, newPath) {
@@ -72894,11 +73617,11 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
72894
73617
  index + 1 === oldPath.length ? (updated[newPath[index]] = updated[oldKey], isArrayImpl(updated) ? updated.splice(oldKey, 1) : delete updated[oldKey]) : updated[oldKey] = copyWithRenameImpl(obj[oldKey], oldPath, newPath, index + 1);
72895
73618
  return updated;
72896
73619
  }
72897
- function copyWithDeleteImpl(obj, path31, index) {
72898
- var key = path31[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
72899
- if (index + 1 === path31.length)
73620
+ function copyWithDeleteImpl(obj, path32, index) {
73621
+ var key = path32[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
73622
+ if (index + 1 === path32.length)
72900
73623
  return isArrayImpl(updated) ? updated.splice(key, 1) : delete updated[key], updated;
72901
- updated[key] = copyWithDeleteImpl(obj[key], path31, index + 1);
73624
+ updated[key] = copyWithDeleteImpl(obj[key], path32, index + 1);
72902
73625
  return updated;
72903
73626
  }
72904
73627
  function shouldSuspendImpl() {
@@ -75012,8 +75735,8 @@ It can also happen if the client has a browser extension installed which messes
75012
75735
  currentEntangledActionThenable = {
75013
75736
  status: "pending",
75014
75737
  value: undefined,
75015
- then: function(resolve18) {
75016
- entangledListeners.push(resolve18);
75738
+ then: function(resolve19) {
75739
+ entangledListeners.push(resolve19);
75017
75740
  }
75018
75741
  };
75019
75742
  }
@@ -75037,8 +75760,8 @@ It can also happen if the client has a browser extension installed which messes
75037
75760
  status: "pending",
75038
75761
  value: null,
75039
75762
  reason: null,
75040
- then: function(resolve18) {
75041
- listeners.push(resolve18);
75763
+ then: function(resolve19) {
75764
+ listeners.push(resolve19);
75042
75765
  }
75043
75766
  };
75044
75767
  thenable.then(function() {
@@ -82921,29 +83644,29 @@ Check the top-level render call using <` + componentName2 + ">.");
82921
83644
  var didWarnAboutNestedUpdates = false;
82922
83645
  var didWarnAboutFindNodeInStrictMode = {};
82923
83646
  var overrideHookState = null, overrideHookStateDeletePath = null, overrideHookStateRenamePath = null, overrideProps = null, overridePropsDeletePath = null, overridePropsRenamePath = null, scheduleUpdate = null, scheduleRetry = null, setErrorHandler = null, setSuspenseHandler = null;
82924
- overrideHookState = function(fiber, id, path31, value) {
83647
+ overrideHookState = function(fiber, id, path32, value) {
82925
83648
  id = findHook(fiber, id);
82926
- id !== null && (path31 = copyWithSetImpl(id.memoizedState, path31, 0, value), id.memoizedState = path31, id.baseState = path31, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path31 = enqueueConcurrentRenderForLane(fiber, 2), path31 !== null && scheduleUpdateOnFiber(path31, fiber, 2));
83649
+ id !== null && (path32 = copyWithSetImpl(id.memoizedState, path32, 0, value), id.memoizedState = path32, id.baseState = path32, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path32 = enqueueConcurrentRenderForLane(fiber, 2), path32 !== null && scheduleUpdateOnFiber(path32, fiber, 2));
82927
83650
  };
82928
- overrideHookStateDeletePath = function(fiber, id, path31) {
83651
+ overrideHookStateDeletePath = function(fiber, id, path32) {
82929
83652
  id = findHook(fiber, id);
82930
- id !== null && (path31 = copyWithDeleteImpl(id.memoizedState, path31, 0), id.memoizedState = path31, id.baseState = path31, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path31 = enqueueConcurrentRenderForLane(fiber, 2), path31 !== null && scheduleUpdateOnFiber(path31, fiber, 2));
83653
+ id !== null && (path32 = copyWithDeleteImpl(id.memoizedState, path32, 0), id.memoizedState = path32, id.baseState = path32, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path32 = enqueueConcurrentRenderForLane(fiber, 2), path32 !== null && scheduleUpdateOnFiber(path32, fiber, 2));
82931
83654
  };
82932
83655
  overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) {
82933
83656
  id = findHook(fiber, id);
82934
83657
  id !== null && (oldPath = copyWithRename(id.memoizedState, oldPath, newPath), id.memoizedState = oldPath, id.baseState = oldPath, fiber.memoizedProps = assign2({}, fiber.memoizedProps), oldPath = enqueueConcurrentRenderForLane(fiber, 2), oldPath !== null && scheduleUpdateOnFiber(oldPath, fiber, 2));
82935
83658
  };
82936
- overrideProps = function(fiber, path31, value) {
82937
- fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path31, 0, value);
83659
+ overrideProps = function(fiber, path32, value) {
83660
+ fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path32, 0, value);
82938
83661
  fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
82939
- path31 = enqueueConcurrentRenderForLane(fiber, 2);
82940
- path31 !== null && scheduleUpdateOnFiber(path31, fiber, 2);
83662
+ path32 = enqueueConcurrentRenderForLane(fiber, 2);
83663
+ path32 !== null && scheduleUpdateOnFiber(path32, fiber, 2);
82941
83664
  };
82942
- overridePropsDeletePath = function(fiber, path31) {
82943
- fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path31, 0);
83665
+ overridePropsDeletePath = function(fiber, path32) {
83666
+ fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path32, 0);
82944
83667
  fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
82945
- path31 = enqueueConcurrentRenderForLane(fiber, 2);
82946
- path31 !== null && scheduleUpdateOnFiber(path31, fiber, 2);
83668
+ path32 = enqueueConcurrentRenderForLane(fiber, 2);
83669
+ path32 !== null && scheduleUpdateOnFiber(path32, fiber, 2);
82947
83670
  };
82948
83671
  overridePropsRenamePath = function(fiber, oldPath, newPath) {
82949
83672
  fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath);
@@ -86998,8 +87721,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
86998
87721
  }
86999
87722
  return false;
87000
87723
  }
87001
- function utils_getInObject(object2, path31) {
87002
- return path31.reduce(function(reduced, attr2) {
87724
+ function utils_getInObject(object2, path32) {
87725
+ return path32.reduce(function(reduced, attr2) {
87003
87726
  if (reduced) {
87004
87727
  if (utils_hasOwnProperty.call(reduced, attr2)) {
87005
87728
  return reduced[attr2];
@@ -87011,11 +87734,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87011
87734
  return null;
87012
87735
  }, object2);
87013
87736
  }
87014
- function deletePathInObject(object2, path31) {
87015
- var length = path31.length;
87016
- var last2 = path31[length - 1];
87737
+ function deletePathInObject(object2, path32) {
87738
+ var length = path32.length;
87739
+ var last2 = path32[length - 1];
87017
87740
  if (object2 != null) {
87018
- var parent = utils_getInObject(object2, path31.slice(0, length - 1));
87741
+ var parent = utils_getInObject(object2, path32.slice(0, length - 1));
87019
87742
  if (parent) {
87020
87743
  if (src_isArray(parent)) {
87021
87744
  parent.splice(last2, 1);
@@ -87041,11 +87764,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87041
87764
  }
87042
87765
  }
87043
87766
  }
87044
- function utils_setInObject(object2, path31, value) {
87045
- var length = path31.length;
87046
- var last2 = path31[length - 1];
87767
+ function utils_setInObject(object2, path32, value) {
87768
+ var length = path32.length;
87769
+ var last2 = path32[length - 1];
87047
87770
  if (object2 != null) {
87048
- var parent = utils_getInObject(object2, path31.slice(0, length - 1));
87771
+ var parent = utils_getInObject(object2, path32.slice(0, length - 1));
87049
87772
  if (parent) {
87050
87773
  parent[last2] = value;
87051
87774
  }
@@ -87576,8 +88299,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87576
88299
  unserializable: Symbol("unserializable")
87577
88300
  };
87578
88301
  var LEVEL_THRESHOLD = 2;
87579
- function createDehydrated(type, inspectable, data, cleaned, path31) {
87580
- cleaned.push(path31);
88302
+ function createDehydrated(type, inspectable, data, cleaned, path32) {
88303
+ cleaned.push(path32);
87581
88304
  var dehydrated = {
87582
88305
  inspectable,
87583
88306
  type,
@@ -87595,13 +88318,13 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87595
88318
  }
87596
88319
  return dehydrated;
87597
88320
  }
87598
- function dehydrate(data, cleaned, unserializable, path31, isPathAllowed) {
88321
+ function dehydrate(data, cleaned, unserializable, path32, isPathAllowed) {
87599
88322
  var level = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
87600
88323
  var type = getDataType(data);
87601
88324
  var isPathAllowedCheck;
87602
88325
  switch (type) {
87603
88326
  case "html_element":
87604
- cleaned.push(path31);
88327
+ cleaned.push(path32);
87605
88328
  return {
87606
88329
  inspectable: false,
87607
88330
  preview_short: formatDataForPreview(data, false),
@@ -87610,7 +88333,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87610
88333
  type
87611
88334
  };
87612
88335
  case "function":
87613
- cleaned.push(path31);
88336
+ cleaned.push(path32);
87614
88337
  return {
87615
88338
  inspectable: false,
87616
88339
  preview_short: formatDataForPreview(data, false),
@@ -87619,14 +88342,14 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87619
88342
  type
87620
88343
  };
87621
88344
  case "string":
87622
- isPathAllowedCheck = isPathAllowed(path31);
88345
+ isPathAllowedCheck = isPathAllowed(path32);
87623
88346
  if (isPathAllowedCheck) {
87624
88347
  return data;
87625
88348
  } else {
87626
88349
  return data.length <= 500 ? data : data.slice(0, 500) + "...";
87627
88350
  }
87628
88351
  case "bigint":
87629
- cleaned.push(path31);
88352
+ cleaned.push(path32);
87630
88353
  return {
87631
88354
  inspectable: false,
87632
88355
  preview_short: formatDataForPreview(data, false),
@@ -87635,7 +88358,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87635
88358
  type
87636
88359
  };
87637
88360
  case "symbol":
87638
- cleaned.push(path31);
88361
+ cleaned.push(path32);
87639
88362
  return {
87640
88363
  inspectable: false,
87641
88364
  preview_short: formatDataForPreview(data, false),
@@ -87644,9 +88367,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87644
88367
  type
87645
88368
  };
87646
88369
  case "react_element": {
87647
- isPathAllowedCheck = isPathAllowed(path31);
88370
+ isPathAllowedCheck = isPathAllowed(path32);
87648
88371
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87649
- cleaned.push(path31);
88372
+ cleaned.push(path32);
87650
88373
  return {
87651
88374
  inspectable: true,
87652
88375
  preview_short: formatDataForPreview(data, false),
@@ -87663,19 +88386,19 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87663
88386
  preview_long: formatDataForPreview(data, true),
87664
88387
  name: getDisplayNameForReactElement(data) || "Unknown"
87665
88388
  };
87666
- unserializableValue.key = dehydrate(data.key, cleaned, unserializable, path31.concat(["key"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88389
+ unserializableValue.key = dehydrate(data.key, cleaned, unserializable, path32.concat(["key"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87667
88390
  if (data.$$typeof === REACT_LEGACY_ELEMENT_TYPE) {
87668
- unserializableValue.ref = dehydrate(data.ref, cleaned, unserializable, path31.concat(["ref"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88391
+ unserializableValue.ref = dehydrate(data.ref, cleaned, unserializable, path32.concat(["ref"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87669
88392
  }
87670
- unserializableValue.props = dehydrate(data.props, cleaned, unserializable, path31.concat(["props"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87671
- unserializable.push(path31);
88393
+ unserializableValue.props = dehydrate(data.props, cleaned, unserializable, path32.concat(["props"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88394
+ unserializable.push(path32);
87672
88395
  return unserializableValue;
87673
88396
  }
87674
88397
  case "react_lazy": {
87675
- isPathAllowedCheck = isPathAllowed(path31);
88398
+ isPathAllowedCheck = isPathAllowed(path32);
87676
88399
  var payload = data._payload;
87677
88400
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87678
- cleaned.push(path31);
88401
+ cleaned.push(path32);
87679
88402
  var inspectable = payload !== null && hydration_typeof(payload) === "object" && (payload._status === 1 || payload._status === 2 || payload.status === "fulfilled" || payload.status === "rejected");
87680
88403
  return {
87681
88404
  inspectable,
@@ -87692,13 +88415,13 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87692
88415
  preview_long: formatDataForPreview(data, true),
87693
88416
  name: "lazy()"
87694
88417
  };
87695
- _unserializableValue._payload = dehydrate(payload, cleaned, unserializable, path31.concat(["_payload"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87696
- unserializable.push(path31);
88418
+ _unserializableValue._payload = dehydrate(payload, cleaned, unserializable, path32.concat(["_payload"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88419
+ unserializable.push(path32);
87697
88420
  return _unserializableValue;
87698
88421
  }
87699
88422
  case "array_buffer":
87700
88423
  case "data_view":
87701
- cleaned.push(path31);
88424
+ cleaned.push(path32);
87702
88425
  return {
87703
88426
  inspectable: false,
87704
88427
  preview_short: formatDataForPreview(data, false),
@@ -87708,21 +88431,21 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87708
88431
  type
87709
88432
  };
87710
88433
  case "array":
87711
- isPathAllowedCheck = isPathAllowed(path31);
88434
+ isPathAllowedCheck = isPathAllowed(path32);
87712
88435
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87713
- return createDehydrated(type, true, data, cleaned, path31);
88436
+ return createDehydrated(type, true, data, cleaned, path32);
87714
88437
  }
87715
88438
  var arr = [];
87716
88439
  for (var i = 0;i < data.length; i++) {
87717
- arr[i] = dehydrateKey(data, i, cleaned, unserializable, path31.concat([i]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88440
+ arr[i] = dehydrateKey(data, i, cleaned, unserializable, path32.concat([i]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87718
88441
  }
87719
88442
  return arr;
87720
88443
  case "html_all_collection":
87721
88444
  case "typed_array":
87722
88445
  case "iterator":
87723
- isPathAllowedCheck = isPathAllowed(path31);
88446
+ isPathAllowedCheck = isPathAllowed(path32);
87724
88447
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87725
- return createDehydrated(type, true, data, cleaned, path31);
88448
+ return createDehydrated(type, true, data, cleaned, path32);
87726
88449
  } else {
87727
88450
  var _unserializableValue2 = {
87728
88451
  unserializable: true,
@@ -87734,13 +88457,13 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87734
88457
  name: typeof data.constructor !== "function" || typeof data.constructor.name !== "string" || data.constructor.name === "Object" ? "" : data.constructor.name
87735
88458
  };
87736
88459
  Array.from(data).forEach(function(item, i2) {
87737
- return _unserializableValue2[i2] = dehydrate(item, cleaned, unserializable, path31.concat([i2]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88460
+ return _unserializableValue2[i2] = dehydrate(item, cleaned, unserializable, path32.concat([i2]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87738
88461
  });
87739
- unserializable.push(path31);
88462
+ unserializable.push(path32);
87740
88463
  return _unserializableValue2;
87741
88464
  }
87742
88465
  case "opaque_iterator":
87743
- cleaned.push(path31);
88466
+ cleaned.push(path32);
87744
88467
  return {
87745
88468
  inspectable: false,
87746
88469
  preview_short: formatDataForPreview(data, false),
@@ -87749,7 +88472,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87749
88472
  type
87750
88473
  };
87751
88474
  case "date":
87752
- cleaned.push(path31);
88475
+ cleaned.push(path32);
87753
88476
  return {
87754
88477
  inspectable: false,
87755
88478
  preview_short: formatDataForPreview(data, false),
@@ -87758,7 +88481,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87758
88481
  type
87759
88482
  };
87760
88483
  case "regexp":
87761
- cleaned.push(path31);
88484
+ cleaned.push(path32);
87762
88485
  return {
87763
88486
  inspectable: false,
87764
88487
  preview_short: formatDataForPreview(data, false),
@@ -87767,9 +88490,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87767
88490
  type
87768
88491
  };
87769
88492
  case "thenable":
87770
- isPathAllowedCheck = isPathAllowed(path31);
88493
+ isPathAllowedCheck = isPathAllowed(path32);
87771
88494
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87772
- cleaned.push(path31);
88495
+ cleaned.push(path32);
87773
88496
  return {
87774
88497
  inspectable: data.status === "fulfilled" || data.status === "rejected",
87775
88498
  preview_short: formatDataForPreview(data, false),
@@ -87790,8 +88513,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87790
88513
  preview_long: formatDataForPreview(data, true),
87791
88514
  name: "fulfilled Thenable"
87792
88515
  };
87793
- _unserializableValue3.value = dehydrate(data.value, cleaned, unserializable, path31.concat(["value"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87794
- unserializable.push(path31);
88516
+ _unserializableValue3.value = dehydrate(data.value, cleaned, unserializable, path32.concat(["value"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88517
+ unserializable.push(path32);
87795
88518
  return _unserializableValue3;
87796
88519
  }
87797
88520
  case "rejected": {
@@ -87802,12 +88525,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87802
88525
  preview_long: formatDataForPreview(data, true),
87803
88526
  name: "rejected Thenable"
87804
88527
  };
87805
- _unserializableValue4.reason = dehydrate(data.reason, cleaned, unserializable, path31.concat(["reason"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87806
- unserializable.push(path31);
88528
+ _unserializableValue4.reason = dehydrate(data.reason, cleaned, unserializable, path32.concat(["reason"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88529
+ unserializable.push(path32);
87807
88530
  return _unserializableValue4;
87808
88531
  }
87809
88532
  default:
87810
- cleaned.push(path31);
88533
+ cleaned.push(path32);
87811
88534
  return {
87812
88535
  inspectable: false,
87813
88536
  preview_short: formatDataForPreview(data, false),
@@ -87817,21 +88540,21 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87817
88540
  };
87818
88541
  }
87819
88542
  case "object":
87820
- isPathAllowedCheck = isPathAllowed(path31);
88543
+ isPathAllowedCheck = isPathAllowed(path32);
87821
88544
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87822
- return createDehydrated(type, true, data, cleaned, path31);
88545
+ return createDehydrated(type, true, data, cleaned, path32);
87823
88546
  } else {
87824
88547
  var object2 = {};
87825
88548
  getAllEnumerableKeys(data).forEach(function(key) {
87826
88549
  var name = key.toString();
87827
- object2[name] = dehydrateKey(data, key, cleaned, unserializable, path31.concat([name]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88550
+ object2[name] = dehydrateKey(data, key, cleaned, unserializable, path32.concat([name]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87828
88551
  });
87829
88552
  return object2;
87830
88553
  }
87831
88554
  case "class_instance": {
87832
- isPathAllowedCheck = isPathAllowed(path31);
88555
+ isPathAllowedCheck = isPathAllowed(path32);
87833
88556
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87834
- return createDehydrated(type, true, data, cleaned, path31);
88557
+ return createDehydrated(type, true, data, cleaned, path32);
87835
88558
  }
87836
88559
  var value = {
87837
88560
  unserializable: true,
@@ -87843,15 +88566,15 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87843
88566
  };
87844
88567
  getAllEnumerableKeys(data).forEach(function(key) {
87845
88568
  var keyAsString = key.toString();
87846
- value[keyAsString] = dehydrate(data[key], cleaned, unserializable, path31.concat([keyAsString]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88569
+ value[keyAsString] = dehydrate(data[key], cleaned, unserializable, path32.concat([keyAsString]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87847
88570
  });
87848
- unserializable.push(path31);
88571
+ unserializable.push(path32);
87849
88572
  return value;
87850
88573
  }
87851
88574
  case "error": {
87852
- isPathAllowedCheck = isPathAllowed(path31);
88575
+ isPathAllowedCheck = isPathAllowed(path32);
87853
88576
  if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
87854
- return createDehydrated(type, true, data, cleaned, path31);
88577
+ return createDehydrated(type, true, data, cleaned, path32);
87855
88578
  }
87856
88579
  var _value = {
87857
88580
  unserializable: true,
@@ -87861,22 +88584,22 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87861
88584
  preview_long: formatDataForPreview(data, true),
87862
88585
  name: data.name
87863
88586
  };
87864
- _value.message = dehydrate(data.message, cleaned, unserializable, path31.concat(["message"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87865
- _value.stack = dehydrate(data.stack, cleaned, unserializable, path31.concat(["stack"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88587
+ _value.message = dehydrate(data.message, cleaned, unserializable, path32.concat(["message"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88588
+ _value.stack = dehydrate(data.stack, cleaned, unserializable, path32.concat(["stack"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87866
88589
  if ("cause" in data) {
87867
- _value.cause = dehydrate(data.cause, cleaned, unserializable, path31.concat(["cause"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88590
+ _value.cause = dehydrate(data.cause, cleaned, unserializable, path32.concat(["cause"]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87868
88591
  }
87869
88592
  getAllEnumerableKeys(data).forEach(function(key) {
87870
88593
  var keyAsString = key.toString();
87871
- _value[keyAsString] = dehydrate(data[key], cleaned, unserializable, path31.concat([keyAsString]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
88594
+ _value[keyAsString] = dehydrate(data[key], cleaned, unserializable, path32.concat([keyAsString]), isPathAllowed, isPathAllowedCheck ? 1 : level + 1);
87872
88595
  });
87873
- unserializable.push(path31);
88596
+ unserializable.push(path32);
87874
88597
  return _value;
87875
88598
  }
87876
88599
  case "infinity":
87877
88600
  case "nan":
87878
88601
  case "undefined":
87879
- cleaned.push(path31);
88602
+ cleaned.push(path32);
87880
88603
  return {
87881
88604
  type
87882
88605
  };
@@ -87884,10 +88607,10 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87884
88607
  return data;
87885
88608
  }
87886
88609
  }
87887
- function dehydrateKey(parent, key, cleaned, unserializable, path31, isPathAllowed) {
88610
+ function dehydrateKey(parent, key, cleaned, unserializable, path32, isPathAllowed) {
87888
88611
  var level = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 0;
87889
88612
  try {
87890
- return dehydrate(parent[key], cleaned, unserializable, path31, isPathAllowed, level);
88613
+ return dehydrate(parent[key], cleaned, unserializable, path32, isPathAllowed, level);
87891
88614
  } catch (error48) {
87892
88615
  var preview = "";
87893
88616
  if (hydration_typeof(error48) === "object" && error48 !== null && typeof error48.stack === "string") {
@@ -87895,7 +88618,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87895
88618
  } else if (typeof error48 === "string") {
87896
88619
  preview = error48;
87897
88620
  }
87898
- cleaned.push(path31);
88621
+ cleaned.push(path32);
87899
88622
  return {
87900
88623
  inspectable: false,
87901
88624
  preview_short: "[Exception]",
@@ -87905,8 +88628,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87905
88628
  };
87906
88629
  }
87907
88630
  }
87908
- function fillInPath(object2, data, path31, value) {
87909
- var target = getInObject(object2, path31);
88631
+ function fillInPath(object2, data, path32, value) {
88632
+ var target = getInObject(object2, path32);
87910
88633
  if (target != null) {
87911
88634
  if (!target[meta3.unserializable]) {
87912
88635
  delete target[meta3.inspectable];
@@ -87921,9 +88644,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87921
88644
  }
87922
88645
  if (value !== null && data.unserializable.length > 0) {
87923
88646
  var unserializablePath = data.unserializable[0];
87924
- var isMatch2 = unserializablePath.length === path31.length;
87925
- for (var i = 0;i < path31.length; i++) {
87926
- if (path31[i] !== unserializablePath[i]) {
88647
+ var isMatch2 = unserializablePath.length === path32.length;
88648
+ for (var i = 0;i < path32.length; i++) {
88649
+ if (path32[i] !== unserializablePath[i]) {
87927
88650
  isMatch2 = false;
87928
88651
  break;
87929
88652
  }
@@ -87932,13 +88655,13 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87932
88655
  upgradeUnserializable(value, value);
87933
88656
  }
87934
88657
  }
87935
- setInObject(object2, path31, value);
88658
+ setInObject(object2, path32, value);
87936
88659
  }
87937
88660
  function hydrate(object2, cleaned, unserializable) {
87938
- cleaned.forEach(function(path31) {
87939
- var length = path31.length;
87940
- var last2 = path31[length - 1];
87941
- var parent = getInObject(object2, path31.slice(0, length - 1));
88661
+ cleaned.forEach(function(path32) {
88662
+ var length = path32.length;
88663
+ var last2 = path32[length - 1];
88664
+ var parent = getInObject(object2, path32.slice(0, length - 1));
87942
88665
  if (!parent || !parent.hasOwnProperty(last2)) {
87943
88666
  return;
87944
88667
  }
@@ -87964,10 +88687,10 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
87964
88687
  parent[last2] = replaced;
87965
88688
  }
87966
88689
  });
87967
- unserializable.forEach(function(path31) {
87968
- var length = path31.length;
87969
- var last2 = path31[length - 1];
87970
- var parent = getInObject(object2, path31.slice(0, length - 1));
88690
+ unserializable.forEach(function(path32) {
88691
+ var length = path32.length;
88692
+ var last2 = path32[length - 1];
88693
+ var parent = getInObject(object2, path32.slice(0, length - 1));
87971
88694
  if (!parent || !parent.hasOwnProperty(last2)) {
87972
88695
  return;
87973
88696
  }
@@ -88088,11 +88811,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
88088
88811
  return gte2(version2, FIRST_DEVTOOLS_BACKEND_LOCKSTEP_VER);
88089
88812
  }
88090
88813
  function cleanForBridge(data, isPathAllowed) {
88091
- var path31 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
88814
+ var path32 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
88092
88815
  if (data !== null) {
88093
88816
  var cleanedPaths = [];
88094
88817
  var unserializablePaths = [];
88095
- var cleanedData = dehydrate(data, cleanedPaths, unserializablePaths, path31, isPathAllowed);
88818
+ var cleanedData = dehydrate(data, cleanedPaths, unserializablePaths, path32, isPathAllowed);
88096
88819
  return {
88097
88820
  data: cleanedData,
88098
88821
  cleaned: cleanedPaths,
@@ -88102,18 +88825,18 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
88102
88825
  return null;
88103
88826
  }
88104
88827
  }
88105
- function copyWithDelete(obj, path31) {
88828
+ function copyWithDelete(obj, path32) {
88106
88829
  var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
88107
- var key = path31[index];
88830
+ var key = path32[index];
88108
88831
  var updated = shared_isArray(obj) ? obj.slice() : utils_objectSpread({}, obj);
88109
- if (index + 1 === path31.length) {
88832
+ if (index + 1 === path32.length) {
88110
88833
  if (shared_isArray(updated)) {
88111
88834
  updated.splice(key, 1);
88112
88835
  } else {
88113
88836
  delete updated[key];
88114
88837
  }
88115
88838
  } else {
88116
- updated[key] = copyWithDelete(obj[key], path31, index + 1);
88839
+ updated[key] = copyWithDelete(obj[key], path32, index + 1);
88117
88840
  }
88118
88841
  return updated;
88119
88842
  }
@@ -88134,14 +88857,14 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
88134
88857
  }
88135
88858
  return updated;
88136
88859
  }
88137
- function copyWithSet(obj, path31, value) {
88860
+ function copyWithSet(obj, path32, value) {
88138
88861
  var index = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
88139
- if (index >= path31.length) {
88862
+ if (index >= path32.length) {
88140
88863
  return value;
88141
88864
  }
88142
- var key = path31[index];
88865
+ var key = path32[index];
88143
88866
  var updated = shared_isArray(obj) ? obj.slice() : utils_objectSpread({}, obj);
88144
- updated[key] = copyWithSet(obj[key], path31, value, index + 1);
88867
+ updated[key] = copyWithSet(obj[key], path32, value, index + 1);
88145
88868
  return updated;
88146
88869
  }
88147
88870
  function getEffectDurations(root) {
@@ -89469,12 +90192,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89469
90192
  }
89470
90193
  });
89471
90194
  bridge_defineProperty(_this, "overrideValueAtPath", function(_ref) {
89472
- var { id, path: path31, rendererID, type, value } = _ref;
90195
+ var { id, path: path32, rendererID, type, value } = _ref;
89473
90196
  switch (type) {
89474
90197
  case "context":
89475
90198
  _this.send("overrideContext", {
89476
90199
  id,
89477
- path: path31,
90200
+ path: path32,
89478
90201
  rendererID,
89479
90202
  wasForwarded: true,
89480
90203
  value
@@ -89483,7 +90206,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89483
90206
  case "hooks":
89484
90207
  _this.send("overrideHookState", {
89485
90208
  id,
89486
- path: path31,
90209
+ path: path32,
89487
90210
  rendererID,
89488
90211
  wasForwarded: true,
89489
90212
  value
@@ -89492,7 +90215,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89492
90215
  case "props":
89493
90216
  _this.send("overrideProps", {
89494
90217
  id,
89495
- path: path31,
90218
+ path: path32,
89496
90219
  rendererID,
89497
90220
  wasForwarded: true,
89498
90221
  value
@@ -89501,7 +90224,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89501
90224
  case "state":
89502
90225
  _this.send("overrideState", {
89503
90226
  id,
89504
- path: path31,
90227
+ path: path32,
89505
90228
  rendererID,
89506
90229
  wasForwarded: true,
89507
90230
  value
@@ -89835,12 +90558,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89835
90558
  }
89836
90559
  });
89837
90560
  agent_defineProperty(_this, "copyElementPath", function(_ref5) {
89838
- var { id, path: path31, rendererID } = _ref5;
90561
+ var { id, path: path32, rendererID } = _ref5;
89839
90562
  var renderer = _this._rendererInterfaces[rendererID];
89840
90563
  if (renderer == null) {
89841
90564
  console.warn('Invalid renderer id "'.concat(rendererID, '" for element "').concat(id, '"'));
89842
90565
  } else {
89843
- var value = renderer.getSerializedElementValueByPath(id, path31);
90566
+ var value = renderer.getSerializedElementValueByPath(id, path32);
89844
90567
  if (value != null) {
89845
90568
  _this._bridge.send("saveToClipboard", value);
89846
90569
  } else {
@@ -89849,12 +90572,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89849
90572
  }
89850
90573
  });
89851
90574
  agent_defineProperty(_this, "deletePath", function(_ref6) {
89852
- var { hookID, id, path: path31, rendererID, type } = _ref6;
90575
+ var { hookID, id, path: path32, rendererID, type } = _ref6;
89853
90576
  var renderer = _this._rendererInterfaces[rendererID];
89854
90577
  if (renderer == null) {
89855
90578
  console.warn('Invalid renderer id "'.concat(rendererID, '" for element "').concat(id, '"'));
89856
90579
  } else {
89857
- renderer.deletePath(type, id, hookID, path31);
90580
+ renderer.deletePath(type, id, hookID, path32);
89858
90581
  }
89859
90582
  });
89860
90583
  agent_defineProperty(_this, "getBackendVersion", function() {
@@ -89891,12 +90614,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89891
90614
  }
89892
90615
  });
89893
90616
  agent_defineProperty(_this, "inspectElement", function(_ref9) {
89894
- var { forceFullData, id, path: path31, rendererID, requestID } = _ref9;
90617
+ var { forceFullData, id, path: path32, rendererID, requestID } = _ref9;
89895
90618
  var renderer = _this._rendererInterfaces[rendererID];
89896
90619
  if (renderer == null) {
89897
90620
  console.warn('Invalid renderer id "'.concat(rendererID, '" for element "').concat(id, '"'));
89898
90621
  } else {
89899
- _this._bridge.send("inspectedElement", renderer.inspectElement(requestID, id, path31, forceFullData));
90622
+ _this._bridge.send("inspectedElement", renderer.inspectElement(requestID, id, path32, forceFullData));
89900
90623
  if (_this._persistedSelectionMatch === null || _this._persistedSelectionMatch.id !== id) {
89901
90624
  _this._persistedSelection = null;
89902
90625
  _this._persistedSelectionMatch = null;
@@ -89930,15 +90653,15 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89930
90653
  }
89931
90654
  for (var rendererID in _this._rendererInterfaces) {
89932
90655
  var renderer = _this._rendererInterfaces[rendererID];
89933
- var path31 = null;
90656
+ var path32 = null;
89934
90657
  if (suspendedByPathIndex !== null && rendererPath !== null) {
89935
90658
  var suspendedByPathRendererIndex = suspendedByPathIndex - suspendedByOffset;
89936
90659
  var rendererHasRequestedSuspendedByPath = renderer.getElementAttributeByPath(id, ["suspendedBy", suspendedByPathRendererIndex]) !== undefined;
89937
90660
  if (rendererHasRequestedSuspendedByPath) {
89938
- path31 = ["suspendedBy", suspendedByPathRendererIndex].concat(rendererPath);
90661
+ path32 = ["suspendedBy", suspendedByPathRendererIndex].concat(rendererPath);
89939
90662
  }
89940
90663
  }
89941
- var inspectedRootsPayload = renderer.inspectElement(requestID, id, path31, forceFullData);
90664
+ var inspectedRootsPayload = renderer.inspectElement(requestID, id, path32, forceFullData);
89942
90665
  switch (inspectedRootsPayload.type) {
89943
90666
  case "hydrated-path":
89944
90667
  inspectedRootsPayload.path[1] += suspendedByOffset;
@@ -90032,20 +90755,20 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90032
90755
  }
90033
90756
  });
90034
90757
  agent_defineProperty(_this, "overrideValueAtPath", function(_ref15) {
90035
- var { hookID, id, path: path31, rendererID, type, value } = _ref15;
90758
+ var { hookID, id, path: path32, rendererID, type, value } = _ref15;
90036
90759
  var renderer = _this._rendererInterfaces[rendererID];
90037
90760
  if (renderer == null) {
90038
90761
  console.warn('Invalid renderer id "'.concat(rendererID, '" for element "').concat(id, '"'));
90039
90762
  } else {
90040
- renderer.overrideValueAtPath(type, id, hookID, path31, value);
90763
+ renderer.overrideValueAtPath(type, id, hookID, path32, value);
90041
90764
  }
90042
90765
  });
90043
90766
  agent_defineProperty(_this, "overrideContext", function(_ref16) {
90044
- var { id, path: path31, rendererID, wasForwarded, value } = _ref16;
90767
+ var { id, path: path32, rendererID, wasForwarded, value } = _ref16;
90045
90768
  if (!wasForwarded) {
90046
90769
  _this.overrideValueAtPath({
90047
90770
  id,
90048
- path: path31,
90771
+ path: path32,
90049
90772
  rendererID,
90050
90773
  type: "context",
90051
90774
  value
@@ -90053,11 +90776,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90053
90776
  }
90054
90777
  });
90055
90778
  agent_defineProperty(_this, "overrideHookState", function(_ref17) {
90056
- var { id, hookID, path: path31, rendererID, wasForwarded, value } = _ref17;
90779
+ var { id, hookID, path: path32, rendererID, wasForwarded, value } = _ref17;
90057
90780
  if (!wasForwarded) {
90058
90781
  _this.overrideValueAtPath({
90059
90782
  id,
90060
- path: path31,
90783
+ path: path32,
90061
90784
  rendererID,
90062
90785
  type: "hooks",
90063
90786
  value
@@ -90065,11 +90788,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90065
90788
  }
90066
90789
  });
90067
90790
  agent_defineProperty(_this, "overrideProps", function(_ref18) {
90068
- var { id, path: path31, rendererID, wasForwarded, value } = _ref18;
90791
+ var { id, path: path32, rendererID, wasForwarded, value } = _ref18;
90069
90792
  if (!wasForwarded) {
90070
90793
  _this.overrideValueAtPath({
90071
90794
  id,
90072
- path: path31,
90795
+ path: path32,
90073
90796
  rendererID,
90074
90797
  type: "props",
90075
90798
  value
@@ -90077,11 +90800,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90077
90800
  }
90078
90801
  });
90079
90802
  agent_defineProperty(_this, "overrideState", function(_ref19) {
90080
- var { id, path: path31, rendererID, wasForwarded, value } = _ref19;
90803
+ var { id, path: path32, rendererID, wasForwarded, value } = _ref19;
90081
90804
  if (!wasForwarded) {
90082
90805
  _this.overrideValueAtPath({
90083
90806
  id,
90084
- path: path31,
90807
+ path: path32,
90085
90808
  rendererID,
90086
90809
  type: "state",
90087
90810
  value
@@ -90148,12 +90871,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90148
90871
  _this._bridge.send("stopInspectingHost", selected);
90149
90872
  });
90150
90873
  agent_defineProperty(_this, "storeAsGlobal", function(_ref23) {
90151
- var { count, id, path: path31, rendererID } = _ref23;
90874
+ var { count, id, path: path32, rendererID } = _ref23;
90152
90875
  var renderer = _this._rendererInterfaces[rendererID];
90153
90876
  if (renderer == null) {
90154
90877
  console.warn('Invalid renderer id "'.concat(rendererID, '" for element "').concat(id, '"'));
90155
90878
  } else {
90156
- renderer.storeAsGlobal(id, path31, count);
90879
+ renderer.storeAsGlobal(id, path32, count);
90157
90880
  }
90158
90881
  });
90159
90882
  agent_defineProperty(_this, "updateHookSettings", function(settings) {
@@ -90170,12 +90893,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90170
90893
  var rendererID = +rendererIDString;
90171
90894
  var renderer = _this._rendererInterfaces[rendererID];
90172
90895
  if (_this._lastSelectedRendererID === rendererID) {
90173
- var path31 = renderer.getPathForElement(_this._lastSelectedElementID);
90174
- if (path31 !== null) {
90175
- renderer.setTrackedPath(path31);
90896
+ var path32 = renderer.getPathForElement(_this._lastSelectedElementID);
90897
+ if (path32 !== null) {
90898
+ renderer.setTrackedPath(path32);
90176
90899
  _this._persistedSelection = {
90177
90900
  rendererID,
90178
- path: path31
90901
+ path: path32
90179
90902
  };
90180
90903
  }
90181
90904
  }
@@ -90250,11 +90973,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90250
90973
  var rendererID = _this._lastSelectedRendererID;
90251
90974
  var id = _this._lastSelectedElementID;
90252
90975
  var renderer = _this._rendererInterfaces[rendererID];
90253
- var path31 = renderer != null ? renderer.getPathForElement(id) : null;
90254
- if (path31 !== null) {
90976
+ var path32 = renderer != null ? renderer.getPathForElement(id) : null;
90977
+ if (path32 !== null) {
90255
90978
  storage_sessionStorageSetItem(SESSION_STORAGE_LAST_SELECTION_KEY, JSON.stringify({
90256
90979
  rendererID,
90257
- path: path31
90980
+ path: path32
90258
90981
  }));
90259
90982
  } else {
90260
90983
  storage_sessionStorageRemoveItem(SESSION_STORAGE_LAST_SELECTION_KEY);
@@ -90977,7 +91700,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
90977
91700
  hasElementWithId: function hasElementWithId() {
90978
91701
  return false;
90979
91702
  },
90980
- inspectElement: function inspectElement(requestID, id, path31) {
91703
+ inspectElement: function inspectElement(requestID, id, path32) {
90981
91704
  return {
90982
91705
  id,
90983
91706
  responseID: requestID,
@@ -96247,9 +96970,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
96247
96970
  }
96248
96971
  return null;
96249
96972
  }
96250
- function getElementAttributeByPath(id, path31) {
96973
+ function getElementAttributeByPath(id, path32) {
96251
96974
  if (isMostRecentlyInspectedElement(id)) {
96252
- return utils_getInObject(mostRecentlyInspectedElement, path31);
96975
+ return utils_getInObject(mostRecentlyInspectedElement, path32);
96253
96976
  }
96254
96977
  return;
96255
96978
  }
@@ -96952,9 +97675,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
96952
97675
  function isMostRecentlyInspectedElementCurrent(id) {
96953
97676
  return isMostRecentlyInspectedElement(id) && !hasElementUpdatedSinceLastInspected;
96954
97677
  }
96955
- function mergeInspectedPaths(path31) {
97678
+ function mergeInspectedPaths(path32) {
96956
97679
  var current = currentlyInspectedPaths;
96957
- path31.forEach(function(key) {
97680
+ path32.forEach(function(key) {
96958
97681
  if (!current[key]) {
96959
97682
  current[key] = {};
96960
97683
  }
@@ -96962,21 +97685,21 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
96962
97685
  });
96963
97686
  }
96964
97687
  function createIsPathAllowed(key, secondaryCategory) {
96965
- return function isPathAllowed(path31) {
97688
+ return function isPathAllowed(path32) {
96966
97689
  switch (secondaryCategory) {
96967
97690
  case "hooks":
96968
- if (path31.length === 1) {
97691
+ if (path32.length === 1) {
96969
97692
  return true;
96970
97693
  }
96971
- if (path31[path31.length - 2] === "hookSource" && path31[path31.length - 1] === "fileName") {
97694
+ if (path32[path32.length - 2] === "hookSource" && path32[path32.length - 1] === "fileName") {
96972
97695
  return true;
96973
97696
  }
96974
- if (path31[path31.length - 1] === "subHooks" || path31[path31.length - 2] === "subHooks") {
97697
+ if (path32[path32.length - 1] === "subHooks" || path32[path32.length - 2] === "subHooks") {
96975
97698
  return true;
96976
97699
  }
96977
97700
  break;
96978
97701
  case "suspendedBy":
96979
- if (path31.length < 5) {
97702
+ if (path32.length < 5) {
96980
97703
  return true;
96981
97704
  }
96982
97705
  break;
@@ -96987,8 +97710,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
96987
97710
  if (!current) {
96988
97711
  return false;
96989
97712
  }
96990
- for (var i = 0;i < path31.length; i++) {
96991
- current = current[path31[i]];
97713
+ for (var i = 0;i < path32.length; i++) {
97714
+ current = current[path32[i]];
96992
97715
  if (!current) {
96993
97716
  return false;
96994
97717
  }
@@ -97042,38 +97765,38 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
97042
97765
  break;
97043
97766
  }
97044
97767
  }
97045
- function storeAsGlobal(id, path31, count) {
97768
+ function storeAsGlobal(id, path32, count) {
97046
97769
  if (isMostRecentlyInspectedElement(id)) {
97047
- var value = utils_getInObject(mostRecentlyInspectedElement, path31);
97770
+ var value = utils_getInObject(mostRecentlyInspectedElement, path32);
97048
97771
  var key = "$reactTemp".concat(count);
97049
97772
  window[key] = value;
97050
97773
  console.log(key);
97051
97774
  console.log(value);
97052
97775
  }
97053
97776
  }
97054
- function getSerializedElementValueByPath(id, path31) {
97777
+ function getSerializedElementValueByPath(id, path32) {
97055
97778
  if (isMostRecentlyInspectedElement(id)) {
97056
- var valueToCopy = utils_getInObject(mostRecentlyInspectedElement, path31);
97779
+ var valueToCopy = utils_getInObject(mostRecentlyInspectedElement, path32);
97057
97780
  return serializeToString(valueToCopy);
97058
97781
  }
97059
97782
  }
97060
- function inspectElement(requestID, id, path31, forceFullData) {
97061
- if (path31 !== null) {
97062
- mergeInspectedPaths(path31);
97783
+ function inspectElement(requestID, id, path32, forceFullData) {
97784
+ if (path32 !== null) {
97785
+ mergeInspectedPaths(path32);
97063
97786
  }
97064
97787
  if (isMostRecentlyInspectedElement(id) && !forceFullData) {
97065
97788
  if (!hasElementUpdatedSinceLastInspected) {
97066
- if (path31 !== null) {
97789
+ if (path32 !== null) {
97067
97790
  var secondaryCategory = null;
97068
- if (path31[0] === "hooks" || path31[0] === "suspendedBy") {
97069
- secondaryCategory = path31[0];
97791
+ if (path32[0] === "hooks" || path32[0] === "suspendedBy") {
97792
+ secondaryCategory = path32[0];
97070
97793
  }
97071
97794
  return {
97072
97795
  id,
97073
97796
  responseID: requestID,
97074
97797
  type: "hydrated-path",
97075
- path: path31,
97076
- value: cleanForBridge(utils_getInObject(mostRecentlyInspectedElement, path31), createIsPathAllowed(null, secondaryCategory), path31)
97798
+ path: path32,
97799
+ value: cleanForBridge(utils_getInObject(mostRecentlyInspectedElement, path32), createIsPathAllowed(null, secondaryCategory), path32)
97077
97800
  };
97078
97801
  } else {
97079
97802
  return {
@@ -97269,7 +97992,7 @@ The error thrown in the component is:
97269
97992
  console.groupEnd();
97270
97993
  }
97271
97994
  }
97272
- function deletePath(type, id, hookID, path31) {
97995
+ function deletePath(type, id, hookID, path32) {
97273
97996
  var devtoolsInstance = idToDevToolsInstanceMap.get(id);
97274
97997
  if (devtoolsInstance === undefined) {
97275
97998
  console.warn('Could not find DevToolsInstance with id "'.concat(id, '"'));
@@ -97283,11 +98006,11 @@ The error thrown in the component is:
97283
98006
  var instance2 = fiber.stateNode;
97284
98007
  switch (type) {
97285
98008
  case "context":
97286
- path31 = path31.slice(1);
98009
+ path32 = path32.slice(1);
97287
98010
  switch (fiber.tag) {
97288
98011
  case ClassComponent:
97289
- if (path31.length === 0) {} else {
97290
- deletePathInObject(instance2.context, path31);
98012
+ if (path32.length === 0) {} else {
98013
+ deletePathInObject(instance2.context, path32);
97291
98014
  }
97292
98015
  instance2.forceUpdate();
97293
98016
  break;
@@ -97297,21 +98020,21 @@ The error thrown in the component is:
97297
98020
  break;
97298
98021
  case "hooks":
97299
98022
  if (typeof overrideHookStateDeletePath === "function") {
97300
- overrideHookStateDeletePath(fiber, hookID, path31);
98023
+ overrideHookStateDeletePath(fiber, hookID, path32);
97301
98024
  }
97302
98025
  break;
97303
98026
  case "props":
97304
98027
  if (instance2 === null) {
97305
98028
  if (typeof overridePropsDeletePath === "function") {
97306
- overridePropsDeletePath(fiber, path31);
98029
+ overridePropsDeletePath(fiber, path32);
97307
98030
  }
97308
98031
  } else {
97309
- fiber.pendingProps = copyWithDelete(instance2.props, path31);
98032
+ fiber.pendingProps = copyWithDelete(instance2.props, path32);
97310
98033
  instance2.forceUpdate();
97311
98034
  }
97312
98035
  break;
97313
98036
  case "state":
97314
- deletePathInObject(instance2.state, path31);
98037
+ deletePathInObject(instance2.state, path32);
97315
98038
  instance2.forceUpdate();
97316
98039
  break;
97317
98040
  }
@@ -97366,7 +98089,7 @@ The error thrown in the component is:
97366
98089
  }
97367
98090
  }
97368
98091
  }
97369
- function overrideValueAtPath(type, id, hookID, path31, value) {
98092
+ function overrideValueAtPath(type, id, hookID, path32, value) {
97370
98093
  var devtoolsInstance = idToDevToolsInstanceMap.get(id);
97371
98094
  if (devtoolsInstance === undefined) {
97372
98095
  console.warn('Could not find DevToolsInstance with id "'.concat(id, '"'));
@@ -97380,13 +98103,13 @@ The error thrown in the component is:
97380
98103
  var instance2 = fiber.stateNode;
97381
98104
  switch (type) {
97382
98105
  case "context":
97383
- path31 = path31.slice(1);
98106
+ path32 = path32.slice(1);
97384
98107
  switch (fiber.tag) {
97385
98108
  case ClassComponent:
97386
- if (path31.length === 0) {
98109
+ if (path32.length === 0) {
97387
98110
  instance2.context = value;
97388
98111
  } else {
97389
- utils_setInObject(instance2.context, path31, value);
98112
+ utils_setInObject(instance2.context, path32, value);
97390
98113
  }
97391
98114
  instance2.forceUpdate();
97392
98115
  break;
@@ -97396,18 +98119,18 @@ The error thrown in the component is:
97396
98119
  break;
97397
98120
  case "hooks":
97398
98121
  if (typeof overrideHookState === "function") {
97399
- overrideHookState(fiber, hookID, path31, value);
98122
+ overrideHookState(fiber, hookID, path32, value);
97400
98123
  }
97401
98124
  break;
97402
98125
  case "props":
97403
98126
  switch (fiber.tag) {
97404
98127
  case ClassComponent:
97405
- fiber.pendingProps = copyWithSet(instance2.props, path31, value);
98128
+ fiber.pendingProps = copyWithSet(instance2.props, path32, value);
97406
98129
  instance2.forceUpdate();
97407
98130
  break;
97408
98131
  default:
97409
98132
  if (typeof overrideProps === "function") {
97410
- overrideProps(fiber, path31, value);
98133
+ overrideProps(fiber, path32, value);
97411
98134
  }
97412
98135
  break;
97413
98136
  }
@@ -97415,7 +98138,7 @@ The error thrown in the component is:
97415
98138
  case "state":
97416
98139
  switch (fiber.tag) {
97417
98140
  case ClassComponent:
97418
- utils_setInObject(instance2.state, path31, value);
98141
+ utils_setInObject(instance2.state, path32, value);
97419
98142
  instance2.forceUpdate();
97420
98143
  break;
97421
98144
  }
@@ -97701,14 +98424,14 @@ The error thrown in the component is:
97701
98424
  var trackedPathMatchInstance = null;
97702
98425
  var trackedPathMatchDepth = -1;
97703
98426
  var mightBeOnTrackedPath = false;
97704
- function setTrackedPath(path31) {
97705
- if (path31 === null) {
98427
+ function setTrackedPath(path32) {
98428
+ if (path32 === null) {
97706
98429
  trackedPathMatchFiber = null;
97707
98430
  trackedPathMatchInstance = null;
97708
98431
  trackedPathMatchDepth = -1;
97709
98432
  mightBeOnTrackedPath = false;
97710
98433
  }
97711
- trackedPath = path31;
98434
+ trackedPath = path32;
97712
98435
  }
97713
98436
  function updateTrackedPathStateBeforeMount(fiber, fiberInstance) {
97714
98437
  if (trackedPath === null || !mightBeOnTrackedPath) {
@@ -98472,9 +99195,9 @@ The error thrown in the component is:
98472
99195
  }
98473
99196
  var currentlyInspectedElementID = null;
98474
99197
  var currentlyInspectedPaths = {};
98475
- function mergeInspectedPaths(path31) {
99198
+ function mergeInspectedPaths(path32) {
98476
99199
  var current = currentlyInspectedPaths;
98477
- path31.forEach(function(key) {
99200
+ path32.forEach(function(key) {
98478
99201
  if (!current[key]) {
98479
99202
  current[key] = {};
98480
99203
  }
@@ -98482,13 +99205,13 @@ The error thrown in the component is:
98482
99205
  });
98483
99206
  }
98484
99207
  function createIsPathAllowed(key) {
98485
- return function isPathAllowed(path31) {
99208
+ return function isPathAllowed(path32) {
98486
99209
  var current = currentlyInspectedPaths[key];
98487
99210
  if (!current) {
98488
99211
  return false;
98489
99212
  }
98490
- for (var i = 0;i < path31.length; i++) {
98491
- current = current[path31[i]];
99213
+ for (var i = 0;i < path32.length; i++) {
99214
+ current = current[path32[i]];
98492
99215
  if (!current) {
98493
99216
  return false;
98494
99217
  }
@@ -98538,24 +99261,24 @@ The error thrown in the component is:
98538
99261
  break;
98539
99262
  }
98540
99263
  }
98541
- function storeAsGlobal(id, path31, count) {
99264
+ function storeAsGlobal(id, path32, count) {
98542
99265
  var inspectedElement = inspectElementRaw(id);
98543
99266
  if (inspectedElement !== null) {
98544
- var value = utils_getInObject(inspectedElement, path31);
99267
+ var value = utils_getInObject(inspectedElement, path32);
98545
99268
  var key = "$reactTemp".concat(count);
98546
99269
  window[key] = value;
98547
99270
  console.log(key);
98548
99271
  console.log(value);
98549
99272
  }
98550
99273
  }
98551
- function getSerializedElementValueByPath(id, path31) {
99274
+ function getSerializedElementValueByPath(id, path32) {
98552
99275
  var inspectedElement = inspectElementRaw(id);
98553
99276
  if (inspectedElement !== null) {
98554
- var valueToCopy = utils_getInObject(inspectedElement, path31);
99277
+ var valueToCopy = utils_getInObject(inspectedElement, path32);
98555
99278
  return serializeToString(valueToCopy);
98556
99279
  }
98557
99280
  }
98558
- function inspectElement(requestID, id, path31, forceFullData) {
99281
+ function inspectElement(requestID, id, path32, forceFullData) {
98559
99282
  if (forceFullData || currentlyInspectedElementID !== id) {
98560
99283
  currentlyInspectedElementID = id;
98561
99284
  currentlyInspectedPaths = {};
@@ -98568,8 +99291,8 @@ The error thrown in the component is:
98568
99291
  type: "not-found"
98569
99292
  };
98570
99293
  }
98571
- if (path31 !== null) {
98572
- mergeInspectedPaths(path31);
99294
+ if (path32 !== null) {
99295
+ mergeInspectedPaths(path32);
98573
99296
  }
98574
99297
  updateSelectedElement(id);
98575
99298
  inspectedElement.context = cleanForBridge(inspectedElement.context, createIsPathAllowed("context"));
@@ -98772,10 +99495,10 @@ The error thrown in the component is:
98772
99495
  console.groupEnd();
98773
99496
  }
98774
99497
  }
98775
- function getElementAttributeByPath(id, path31) {
99498
+ function getElementAttributeByPath(id, path32) {
98776
99499
  var inspectedElement = inspectElementRaw(id);
98777
99500
  if (inspectedElement !== null) {
98778
- return utils_getInObject(inspectedElement, path31);
99501
+ return utils_getInObject(inspectedElement, path32);
98779
99502
  }
98780
99503
  return;
98781
99504
  }
@@ -98792,14 +99515,14 @@ The error thrown in the component is:
98792
99515
  }
98793
99516
  return element.type;
98794
99517
  }
98795
- function deletePath(type, id, hookID, path31) {
99518
+ function deletePath(type, id, hookID, path32) {
98796
99519
  var internalInstance = idToInternalInstanceMap.get(id);
98797
99520
  if (internalInstance != null) {
98798
99521
  var publicInstance = internalInstance._instance;
98799
99522
  if (publicInstance != null) {
98800
99523
  switch (type) {
98801
99524
  case "context":
98802
- deletePathInObject(publicInstance.context, path31);
99525
+ deletePathInObject(publicInstance.context, path32);
98803
99526
  forceUpdate(publicInstance);
98804
99527
  break;
98805
99528
  case "hooks":
@@ -98807,12 +99530,12 @@ The error thrown in the component is:
98807
99530
  case "props":
98808
99531
  var element = internalInstance._currentElement;
98809
99532
  internalInstance._currentElement = legacy_renderer_objectSpread(legacy_renderer_objectSpread({}, element), {}, {
98810
- props: copyWithDelete(element.props, path31)
99533
+ props: copyWithDelete(element.props, path32)
98811
99534
  });
98812
99535
  forceUpdate(publicInstance);
98813
99536
  break;
98814
99537
  case "state":
98815
- deletePathInObject(publicInstance.state, path31);
99538
+ deletePathInObject(publicInstance.state, path32);
98816
99539
  forceUpdate(publicInstance);
98817
99540
  break;
98818
99541
  }
@@ -98846,14 +99569,14 @@ The error thrown in the component is:
98846
99569
  }
98847
99570
  }
98848
99571
  }
98849
- function overrideValueAtPath(type, id, hookID, path31, value) {
99572
+ function overrideValueAtPath(type, id, hookID, path32, value) {
98850
99573
  var internalInstance = idToInternalInstanceMap.get(id);
98851
99574
  if (internalInstance != null) {
98852
99575
  var publicInstance = internalInstance._instance;
98853
99576
  if (publicInstance != null) {
98854
99577
  switch (type) {
98855
99578
  case "context":
98856
- utils_setInObject(publicInstance.context, path31, value);
99579
+ utils_setInObject(publicInstance.context, path32, value);
98857
99580
  forceUpdate(publicInstance);
98858
99581
  break;
98859
99582
  case "hooks":
@@ -98861,12 +99584,12 @@ The error thrown in the component is:
98861
99584
  case "props":
98862
99585
  var element = internalInstance._currentElement;
98863
99586
  internalInstance._currentElement = legacy_renderer_objectSpread(legacy_renderer_objectSpread({}, element), {}, {
98864
- props: copyWithSet(element.props, path31, value)
99587
+ props: copyWithSet(element.props, path32, value)
98865
99588
  });
98866
99589
  forceUpdate(publicInstance);
98867
99590
  break;
98868
99591
  case "state":
98869
- utils_setInObject(publicInstance.state, path31, value);
99592
+ utils_setInObject(publicInstance.state, path32, value);
98870
99593
  forceUpdate(publicInstance);
98871
99594
  break;
98872
99595
  }
@@ -98907,7 +99630,7 @@ The error thrown in the component is:
98907
99630
  return [];
98908
99631
  }
98909
99632
  function setTraceUpdatesEnabled(enabled) {}
98910
- function setTrackedPath(path31) {}
99633
+ function setTrackedPath(path32) {}
98911
99634
  function getOwnersList(id) {
98912
99635
  return null;
98913
99636
  }
@@ -100937,9 +101660,9 @@ var init_ranking = __esm(() => {
100937
101660
  });
100938
101661
 
100939
101662
  // src/bakeoff/coordinator.ts
100940
- import { join as join98 } from "path";
101663
+ import { join as join99 } from "path";
100941
101664
  async function persistBakeoffResult(result2, outputDir) {
100942
- const filePath = join98(outputDir, "bakeoff.json");
101665
+ const filePath = join99(outputDir, "bakeoff.json");
100943
101666
  await Bun.write(filePath, JSON.stringify(result2, null, 2));
100944
101667
  }
100945
101668
  async function runBakeoff(options, deps = {}) {
@@ -101127,7 +101850,7 @@ __export(exports_curator, {
101127
101850
  });
101128
101851
  import { readdirSync as readdirSync9 } from "fs";
101129
101852
  import { unlink as unlink4 } from "fs/promises";
101130
- import { basename as basename18, join as join99 } from "path";
101853
+ import { basename as basename18, join as join100 } from "path";
101131
101854
  function getProjectKey(config2, projectDir) {
101132
101855
  return config2.name?.trim() || basename18(projectDir);
101133
101856
  }
@@ -101210,7 +101933,7 @@ async function curatorStatus(options) {
101210
101933
  const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
101211
101934
  const projectKey = getProjectKey(config2, resolved.projectDir);
101212
101935
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
101213
- const runsDir = join99(outputDir, "runs");
101936
+ const runsDir = join100(outputDir, "runs");
101214
101937
  const runIds = listRunIds(runsDir);
101215
101938
  let runId;
101216
101939
  if (options.run) {
@@ -101227,8 +101950,8 @@ async function curatorStatus(options) {
101227
101950
  runId = runIds[runIds.length - 1];
101228
101951
  }
101229
101952
  console.log(`Run: ${runId}`);
101230
- const runDir = join99(runsDir, runId);
101231
- const observationsPath = join99(runDir, "observations.jsonl");
101953
+ const runDir = join100(runsDir, runId);
101954
+ const observationsPath = join100(runDir, "observations.jsonl");
101232
101955
  const observations = await parseObservations(observationsPath);
101233
101956
  const counts = new Map;
101234
101957
  for (const obs of observations) {
@@ -101238,7 +101961,7 @@ async function curatorStatus(options) {
101238
101961
  for (const [kind, count] of counts.entries()) {
101239
101962
  console.log(` ${kind}: ${count}`);
101240
101963
  }
101241
- const proposalsPath = join99(runDir, "curator-proposals.md");
101964
+ const proposalsPath = join100(runDir, "curator-proposals.md");
101242
101965
  const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
101243
101966
  if (proposalText !== null) {
101244
101967
  console.log("");
@@ -101252,8 +101975,8 @@ async function curatorCommit(options) {
101252
101975
  const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
101253
101976
  const projectKey = getProjectKey(config2, resolved.projectDir);
101254
101977
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
101255
- const runDir = join99(outputDir, "runs", options.runId);
101256
- const proposalsPath = join99(runDir, "curator-proposals.md");
101978
+ const runDir = join100(outputDir, "runs", options.runId);
101979
+ const proposalsPath = join100(runDir, "curator-proposals.md");
101257
101980
  const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
101258
101981
  if (proposalText === null) {
101259
101982
  console.log(`curator-proposals.md not found for run ${options.runId}.`);
@@ -101269,7 +101992,7 @@ async function curatorCommit(options) {
101269
101992
  const dropFileState = new Map;
101270
101993
  const skippedDrops = new Set;
101271
101994
  for (const drop2 of drops) {
101272
- const targetPath = join99(resolved.projectDir, drop2.canonicalFile);
101995
+ const targetPath = join100(resolved.projectDir, drop2.canonicalFile);
101273
101996
  if (!dropFileState.has(targetPath)) {
101274
101997
  const fileExists2 = await Bun.file(targetPath).exists();
101275
101998
  const existing = fileExists2 ? await _curatorCmdDeps.readFile(targetPath).catch(() => "") : "";
@@ -101303,7 +102026,7 @@ async function curatorCommit(options) {
101303
102026
  if (skippedDrops.has(drop2)) {
101304
102027
  continue;
101305
102028
  }
101306
- const targetPath = join99(resolved.projectDir, drop2.canonicalFile);
102029
+ const targetPath = join100(resolved.projectDir, drop2.canonicalFile);
101307
102030
  const existing = await _curatorCmdDeps.readFile(targetPath).catch(() => "");
101308
102031
  const filtered = filterDropContent(existing, drop2.description);
101309
102032
  await _curatorCmdDeps.writeFile(targetPath, filtered);
@@ -101312,7 +102035,7 @@ async function curatorCommit(options) {
101312
102035
  }
101313
102036
  const adds = proposals.filter((p) => p.action === "add" || p.action === "advisory");
101314
102037
  for (const add2 of adds) {
101315
- const targetPath = join99(resolved.projectDir, add2.canonicalFile);
102038
+ const targetPath = join100(resolved.projectDir, add2.canonicalFile);
101316
102039
  const content = buildAddContent(add2);
101317
102040
  await _curatorCmdDeps.appendFile(targetPath, content);
101318
102041
  modifiedFiles.add(targetPath);
@@ -101349,7 +102072,7 @@ async function curatorDryrun(options) {
101349
102072
  const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
101350
102073
  const projectKey = getProjectKey(config2, resolved.projectDir);
101351
102074
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
101352
- const runsDir = join99(outputDir, "runs");
102075
+ const runsDir = join100(outputDir, "runs");
101353
102076
  const runIds = listRunIds(runsDir);
101354
102077
  if (runIds.length === 0) {
101355
102078
  console.log("No runs found.");
@@ -101360,7 +102083,7 @@ async function curatorDryrun(options) {
101360
102083
  console.log(`Run ${options.run} not found in ${runsDir}.`);
101361
102084
  return;
101362
102085
  }
101363
- const observationsPath = join99(runsDir, runId, "observations.jsonl");
102086
+ const observationsPath = join100(runsDir, runId, "observations.jsonl");
101364
102087
  const observations = await parseObservations(observationsPath);
101365
102088
  const thresholds = getThresholds(config2);
101366
102089
  const proposals = runHeuristics(observations, thresholds);
@@ -101401,12 +102124,12 @@ async function curatorGc(options) {
101401
102124
  await _curatorCmdDeps.writeFile(rollupPath, newContent);
101402
102125
  const projectKey = getProjectKey(config2, resolved.projectDir);
101403
102126
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
101404
- const perRunsDir = join99(outputDir, "runs");
102127
+ const perRunsDir = join100(outputDir, "runs");
101405
102128
  for (const runId of uniqueRunIds) {
101406
102129
  if (!keepSet.has(runId)) {
101407
- const runDir = join99(perRunsDir, runId);
101408
- await _curatorCmdDeps.removeFile(join99(runDir, "observations.jsonl"));
101409
- await _curatorCmdDeps.removeFile(join99(runDir, "curator-proposals.md"));
102130
+ const runDir = join100(perRunsDir, runId);
102131
+ await _curatorCmdDeps.removeFile(join100(runDir, "observations.jsonl"));
102132
+ await _curatorCmdDeps.removeFile(join100(runDir, "curator-proposals.md"));
101410
102133
  }
101411
102134
  }
101412
102135
  console.log(`[gc] Pruned rollup to ${keep} most recent runs (was ${uniqueRunIds.length}).`);
@@ -101451,7 +102174,7 @@ var init_curator2 = __esm(() => {
101451
102174
  init_source();
101452
102175
  import { existsSync as existsSync39, mkdirSync as mkdirSync8 } from "fs";
101453
102176
  import { homedir as homedir3 } from "os";
101454
- import { basename as basename19, join as join100 } from "path";
102177
+ import { basename as basename19, join as join101 } from "path";
101455
102178
 
101456
102179
  // node_modules/commander/esm.mjs
101457
102180
  var import__ = __toESM(require_commander(), 1);
@@ -101716,7 +102439,8 @@ class DebatePlanStrategy {
101716
102439
  if (debateResult.outcome !== "failed" && debateResult.output) {
101717
102440
  const prd2 = validatePlanOutput(debateResult.output, ctx.options.feature, ctx.branchName);
101718
102441
  warnOnDroppedVerbatimAcs(prd2, ctx.specContent, ctx.options.feature);
101719
- const withProject2 = { ...prd2, project: ctx.projectName };
102442
+ const scoped2 = backfillOutOfScope(prd2, ctx.specContent, ctx.options.feature);
102443
+ const withProject2 = { ...scoped2, project: ctx.projectName };
101720
102444
  return _debatePlanDeps.writeOrRecoverPrd(ctx, withProject2);
101721
102445
  }
101722
102446
  const prd = await callOp({
@@ -101814,7 +102538,8 @@ class PipelinePlanStrategy {
101814
102538
  if (verdict.outcome !== "passed") {
101815
102539
  throw new NaxError(verdict.specDeltasPath ? `Plan pipeline failed; see ${verdict.specDeltasPath}` : "Plan pipeline failed with no spec-deltas path", "PLAN_CRITIC_BLOCKED", { stage: "plan", specDeltasPath: verdict.specDeltasPath });
101816
102540
  }
101817
- const prdToWrite = finalizePrdRouting({ ...verdict.prd, project: ctx.projectName }, ctx.config.routing?.agents, ctx.profileName);
102541
+ const scoped2 = backfillOutOfScope(verdict.prd, ctx.specContent, ctx.options.feature);
102542
+ const prdToWrite = finalizePrdRouting({ ...scoped2, project: ctx.projectName }, ctx.config.routing?.agents, ctx.profileName);
101818
102543
  await ctx.deps.writeFile(ctx.outputPath, JSON.stringify(prdToWrite, null, 2));
101819
102544
  return ctx.outputPath;
101820
102545
  } finally {
@@ -102216,10 +102941,10 @@ init_setup_write();
102216
102941
  // src/cli/plugins.ts
102217
102942
  init_paths();
102218
102943
  init_loader4();
102219
- import * as path22 from "path";
102944
+ import * as path23 from "path";
102220
102945
  async function pluginsListCommand(config2, workdir, overrideGlobalPluginsDir) {
102221
- const globalPluginsDir = overrideGlobalPluginsDir ?? path22.join(globalConfigDir(), "plugins");
102222
- const projectPluginsDir = path22.join(workdir, ".nax", "plugins");
102946
+ const globalPluginsDir = overrideGlobalPluginsDir ?? path23.join(globalConfigDir(), "plugins");
102947
+ const projectPluginsDir = path23.join(workdir, ".nax", "plugins");
102223
102948
  const configPlugins = config2.plugins || [];
102224
102949
  const registry3 = await loadPlugins(globalPluginsDir, projectPluginsDir, configPlugins, workdir, config2.disabledPlugins);
102225
102950
  const plugins = registry3.plugins;
@@ -102269,10 +102994,10 @@ function formatSource(type, sourcePath) {
102269
102994
  return `built-in (${sourcePath})`;
102270
102995
  }
102271
102996
  if (type === "global") {
102272
- return `global (${path22.basename(sourcePath)})`;
102997
+ return `global (${path23.basename(sourcePath)})`;
102273
102998
  }
102274
102999
  if (type === "project") {
102275
- return `project (${path22.basename(sourcePath)})`;
103000
+ return `project (${path23.basename(sourcePath)})`;
102276
103001
  }
102277
103002
  return `config (${sourcePath})`;
102278
103003
  }
@@ -102287,7 +103012,7 @@ init_source();
102287
103012
  init_loader();
102288
103013
  init_generator2();
102289
103014
  import { existsSync as existsSync24 } from "fs";
102290
- import { join as join67 } from "path";
103015
+ import { join as join68 } from "path";
102291
103016
  var VALID_AGENTS = ["claude", "codex", "opencode", "cursor", "windsurf", "aider", "gemini"];
102292
103017
  async function generateCommand(options) {
102293
103018
  const workdir = options.dir ?? process.cwd();
@@ -102330,7 +103055,7 @@ async function generateCommand(options) {
102330
103055
  return;
102331
103056
  }
102332
103057
  if (options.package) {
102333
- const packageDir = join67(workdir, options.package);
103058
+ const packageDir = join68(workdir, options.package);
102334
103059
  if (dryRun) {
102335
103060
  console.log(source_default.yellow("\u26A0 Dry run \u2014 no files will be written"));
102336
103061
  }
@@ -102350,8 +103075,8 @@ async function generateCommand(options) {
102350
103075
  process.exit(1);
102351
103076
  return;
102352
103077
  }
102353
- const contextPath = options.context ? join67(workdir, options.context) : join67(workdir, ".nax/context.md");
102354
- const outputDir = options.output ? join67(workdir, options.output) : workdir;
103078
+ const contextPath = options.context ? join68(workdir, options.context) : join68(workdir, ".nax/context.md");
103079
+ const outputDir = options.output ? join68(workdir, options.output) : workdir;
102355
103080
  const autoInject = !options.noAutoInject;
102356
103081
  if (!existsSync24(contextPath)) {
102357
103082
  console.error(source_default.red(`\u2717 Context file not found: ${contextPath}`));
@@ -102457,7 +103182,7 @@ async function generateCommand(options) {
102457
103182
  // src/cli/config-display.ts
102458
103183
  init_loader();
102459
103184
  import { existsSync as existsSync26 } from "fs";
102460
- import { join as join69 } from "path";
103185
+ import { join as join70 } from "path";
102461
103186
 
102462
103187
  // src/cli/config-descriptions.ts
102463
103188
  var FIELD_DESCRIPTIONS = {
@@ -102665,10 +103390,10 @@ function deepDiffConfigs(global2, project, currentPath = []) {
102665
103390
  for (const key of Object.keys(project)) {
102666
103391
  const projectValue = project[key];
102667
103392
  const globalValue = global2[key];
102668
- const path23 = [...currentPath, key];
102669
- const pathStr = path23.join(".");
103393
+ const path24 = [...currentPath, key];
103394
+ const pathStr = path24.join(".");
102670
103395
  if (projectValue !== null && typeof projectValue === "object" && !Array.isArray(projectValue) && globalValue !== null && typeof globalValue === "object" && !Array.isArray(globalValue)) {
102671
- const nestedDiffs = deepDiffConfigs(globalValue, projectValue, path23);
103396
+ const nestedDiffs = deepDiffConfigs(globalValue, projectValue, path24);
102672
103397
  diffs.push(...nestedDiffs);
102673
103398
  } else {
102674
103399
  if (!deepEqual(projectValue, globalValue)) {
@@ -102710,12 +103435,12 @@ function deepEqual(a, b) {
102710
103435
  init_defaults();
102711
103436
  init_loader();
102712
103437
  import { existsSync as existsSync25 } from "fs";
102713
- import { join as join68 } from "path";
102714
- async function loadConfigFile(path23) {
102715
- if (!existsSync25(path23))
103438
+ import { join as join69 } from "path";
103439
+ async function loadConfigFile(path24) {
103440
+ if (!existsSync25(path24))
102716
103441
  return null;
102717
103442
  try {
102718
- return await Bun.file(path23).json();
103443
+ return await Bun.file(path24).json();
102719
103444
  } catch {
102720
103445
  return null;
102721
103446
  }
@@ -102732,7 +103457,7 @@ async function loadProjectConfig() {
102732
103457
  const projectDir = findProjectDir();
102733
103458
  if (!projectDir)
102734
103459
  return null;
102735
- const projectPath = join68(projectDir, "config.json");
103460
+ const projectPath = join69(projectDir, "config.json");
102736
103461
  return await loadConfigFile(projectPath);
102737
103462
  }
102738
103463
 
@@ -102762,10 +103487,10 @@ async function configCommand(config2, options = {}) {
102762
103487
  console.log(`${"Field".padEnd(40)}${"Project Value".padEnd(20)}Global Value`);
102763
103488
  console.log("\u2500".repeat(80));
102764
103489
  for (const diff2 of diffs) {
102765
- const path23 = diff2.path.padEnd(40);
103490
+ const path24 = diff2.path.padEnd(40);
102766
103491
  const projectVal = formatValueForTable(diff2.projectValue);
102767
103492
  const globalVal = formatValueForTable(diff2.globalValue);
102768
- console.log(`${path23}${projectVal.padEnd(20)}${globalVal}`);
103493
+ console.log(`${path24}${projectVal.padEnd(20)}${globalVal}`);
102769
103494
  const description = FIELD_DESCRIPTIONS[diff2.path];
102770
103495
  if (description) {
102771
103496
  console.log(`${"".padEnd(40)}\u21B3 ${description}`);
@@ -102792,32 +103517,32 @@ async function configCommand(config2, options = {}) {
102792
103517
  function determineConfigSources() {
102793
103518
  const globalPath = globalConfigPath();
102794
103519
  const projectDir = findProjectDir();
102795
- const projectPath = projectDir ? join69(projectDir, "config.json") : null;
103520
+ const projectPath = projectDir ? join70(projectDir, "config.json") : null;
102796
103521
  return {
102797
103522
  global: fileExists(globalPath) ? globalPath : null,
102798
103523
  project: projectPath && fileExists(projectPath) ? projectPath : null
102799
103524
  };
102800
103525
  }
102801
- function fileExists(path23) {
102802
- return existsSync26(path23);
103526
+ function fileExists(path24) {
103527
+ return existsSync26(path24);
102803
103528
  }
102804
- function displayConfigWithDescriptions(obj, path23, sources, indent = 0) {
103529
+ function displayConfigWithDescriptions(obj, path24, sources, indent = 0) {
102805
103530
  const indentStr = " ".repeat(indent);
102806
- const pathStr = path23.join(".");
103531
+ const pathStr = path24.join(".");
102807
103532
  if (obj === null || obj === undefined || typeof obj !== "object" || Array.isArray(obj)) {
102808
103533
  const description = FIELD_DESCRIPTIONS[pathStr];
102809
103534
  const value = formatValue(obj);
102810
103535
  if (description) {
102811
103536
  console.log(`${indentStr}# ${description}`);
102812
103537
  }
102813
- const key = path23[path23.length - 1] || "";
103538
+ const key = path24[path24.length - 1] || "";
102814
103539
  console.log(`${indentStr}${key}: ${value}`);
102815
103540
  console.log();
102816
103541
  return;
102817
103542
  }
102818
103543
  const entries = Object.entries(obj);
102819
103544
  const objAsRecord = obj;
102820
- const isPromptsSection = path23.join(".") === "prompts";
103545
+ const isPromptsSection = path24.join(".") === "prompts";
102821
103546
  if (isPromptsSection && !objAsRecord.overrides) {
102822
103547
  const description = FIELD_DESCRIPTIONS["prompts.overrides"];
102823
103548
  if (description) {
@@ -102840,7 +103565,7 @@ function displayConfigWithDescriptions(obj, path23, sources, indent = 0) {
102840
103565
  }
102841
103566
  for (let i = 0;i < entries.length; i++) {
102842
103567
  const [key, value] = entries[i];
102843
- const currentPath = [...path23, key];
103568
+ const currentPath = [...path24, key];
102844
103569
  const currentPathStr = currentPath.join(".");
102845
103570
  const description = FIELD_DESCRIPTIONS[currentPathStr];
102846
103571
  if (description) {
@@ -102941,15 +103666,15 @@ init_paths();
102941
103666
  init_profile();
102942
103667
  import { mkdirSync as mkdirSync5 } from "fs";
102943
103668
  import { readdirSync as readdirSync5 } from "fs";
102944
- import { join as join70 } from "path";
103669
+ import { join as join71 } from "path";
102945
103670
  var _profileCLIDeps = {
102946
103671
  env: process.env
102947
103672
  };
102948
103673
  var SENSITIVE_KEY_PATTERN = /key|token|secret|password|credential/i;
102949
103674
  var VAR_PATTERN = /\$[A-Za-z_][A-Za-z0-9_]*/;
102950
103675
  async function profileListCommand(startDir) {
102951
- const globalProfilesDir = join70(globalConfigDir(), "profiles");
102952
- const projectProfilesDir = join70(projectConfigDir(startDir), "profiles");
103676
+ const globalProfilesDir = join71(globalConfigDir(), "profiles");
103677
+ const projectProfilesDir = join71(projectConfigDir(startDir), "profiles");
102953
103678
  const globalProfiles = scanProfileDir(globalProfilesDir);
102954
103679
  const projectProfiles = scanProfileDir(projectProfilesDir);
102955
103680
  const activeProfile = await resolveProfileName({}, _profileCLIDeps.env, startDir);
@@ -103008,7 +103733,7 @@ function maskProfileValues(obj) {
103008
103733
  return result;
103009
103734
  }
103010
103735
  async function profileUseCommand(profileName, startDir) {
103011
- const configPath = join70(projectConfigDir(startDir), "config.json");
103736
+ const configPath = join71(projectConfigDir(startDir), "config.json");
103012
103737
  const configFile = Bun.file(configPath);
103013
103738
  let existing = {};
103014
103739
  if (await configFile.exists()) {
@@ -103027,8 +103752,8 @@ async function profileCurrentCommand(startDir) {
103027
103752
  return resolveProfileName({}, _profileCLIDeps.env, startDir);
103028
103753
  }
103029
103754
  async function profileCreateCommand(profileName, startDir) {
103030
- const profilesDir = join70(projectConfigDir(startDir), "profiles");
103031
- const profilePath = join70(profilesDir, `${profileName}.json`);
103755
+ const profilesDir = join71(projectConfigDir(startDir), "profiles");
103756
+ const profilePath = join71(profilesDir, `${profileName}.json`);
103032
103757
  const profileFile = Bun.file(profilePath);
103033
103758
  if (await profileFile.exists()) {
103034
103759
  throw new Error(`Profile "${profileName}" already exists at ${profilePath}`);
@@ -103150,22 +103875,22 @@ async function contextInspectCommand(options) {
103150
103875
  init_canonical_loader();
103151
103876
  init_errors();
103152
103877
  import { mkdir as mkdir11 } from "fs/promises";
103153
- import { basename as basename13, join as join71 } from "path";
103878
+ import { basename as basename13, join as join72 } from "path";
103154
103879
  var _rulesCLIDeps = {
103155
- readFile: async (path23) => Bun.file(path23).text(),
103156
- writeFile: async (path23, content) => {
103157
- await Bun.write(path23, content);
103880
+ readFile: async (path24) => Bun.file(path24).text(),
103881
+ writeFile: async (path24, content) => {
103882
+ await Bun.write(path24, content);
103158
103883
  },
103159
- fileExists: async (path23) => Bun.file(path23).exists(),
103884
+ fileExists: async (path24) => Bun.file(path24).exists(),
103160
103885
  globInDir: (dir) => {
103161
103886
  try {
103162
- return [...new Bun.Glob("*.md").scanSync({ cwd: dir })].sort().map((f) => join71(dir, f));
103887
+ return [...new Bun.Glob("*.md").scanSync({ cwd: dir })].sort().map((f) => join72(dir, f));
103163
103888
  } catch {
103164
103889
  return [];
103165
103890
  }
103166
103891
  },
103167
- mkdir: async (path23) => {
103168
- await mkdir11(path23, { recursive: true });
103892
+ mkdir: async (path24) => {
103893
+ await mkdir11(path24, { recursive: true });
103169
103894
  },
103170
103895
  globCanonicalRuleFiles: (workdir) => {
103171
103896
  try {
@@ -103208,7 +103933,7 @@ ${r.content}`).join(`
103208
103933
  `);
103209
103934
  const shimContent = `${header + body}
103210
103935
  `;
103211
- const shimPath = join71(workdir, shimFileName);
103936
+ const shimPath = join72(workdir, shimFileName);
103212
103937
  if (options.dryRun) {
103213
103938
  console.log(`[dry-run] Would write ${shimPath} (${shimContent.length} bytes)`);
103214
103939
  return;
@@ -103237,14 +103962,14 @@ function neutralizeContent(content) {
103237
103962
  }
103238
103963
  async function collectMigrationSources(workdir) {
103239
103964
  const sources = [];
103240
- const claudeMdPath = join71(workdir, "CLAUDE.md");
103965
+ const claudeMdPath = join72(workdir, "CLAUDE.md");
103241
103966
  if (await _rulesCLIDeps.fileExists(claudeMdPath)) {
103242
103967
  const content = await _rulesCLIDeps.readFile(claudeMdPath);
103243
103968
  if (content.trim()) {
103244
103969
  sources.push({ sourcePath: claudeMdPath, targetFileName: "project-conventions.md", content });
103245
103970
  }
103246
103971
  }
103247
- const rulesDir = join71(workdir, ".claude", "rules");
103972
+ const rulesDir = join72(workdir, ".claude", "rules");
103248
103973
  const ruleFiles = _rulesCLIDeps.globInDir(rulesDir);
103249
103974
  for (const filePath of ruleFiles) {
103250
103975
  try {
@@ -103264,7 +103989,7 @@ async function rulesMigrateCommand(options) {
103264
103989
  console.log("[WARN] No source files found (checked CLAUDE.md and .claude/rules/*.md). Nothing to migrate.");
103265
103990
  return;
103266
103991
  }
103267
- const targetDir = join71(workdir, CANONICAL_RULES_DIR);
103992
+ const targetDir = join72(workdir, CANONICAL_RULES_DIR);
103268
103993
  if (!options.dryRun) {
103269
103994
  try {
103270
103995
  await _rulesCLIDeps.mkdir(targetDir);
@@ -103275,7 +104000,7 @@ async function rulesMigrateCommand(options) {
103275
104000
  let written = 0;
103276
104001
  let skipped = 0;
103277
104002
  for (const { sourcePath, targetFileName, content } of sources) {
103278
- const targetPath = join71(targetDir, targetFileName);
104003
+ const targetPath = join72(targetDir, targetFileName);
103279
104004
  if (!force && !options.dryRun && await _rulesCLIDeps.fileExists(targetPath)) {
103280
104005
  console.log(`[skip] ${targetFileName} already exists (use --force to overwrite)`);
103281
104006
  skipped++;
@@ -103314,7 +104039,7 @@ function collectCanonicalRuleRoots(workdir) {
103314
104039
  const packageRel = normalized.slice(0, idx);
103315
104040
  if (!packageRel)
103316
104041
  continue;
103317
- roots.add(join71(workdir, packageRel));
104042
+ roots.add(join72(workdir, packageRel));
103318
104043
  }
103319
104044
  return [...roots].sort();
103320
104045
  }
@@ -103338,8 +104063,8 @@ async function resolveRunProfileOverride(opts) {
103338
104063
  return cliChain;
103339
104064
  if (opts.envProfile)
103340
104065
  return;
103341
- const readJson = opts._readJson ?? (async (path23) => {
103342
- const file3 = Bun.file(path23);
104066
+ const readJson = opts._readJson ?? (async (path24) => {
104067
+ const file3 = Bun.file(path24);
103343
104068
  if (!await file3.exists())
103344
104069
  return;
103345
104070
  return file3.json();
@@ -103362,7 +104087,7 @@ async function resolveRunProfileOverride(opts) {
103362
104087
  // src/cli/features-resolve.ts
103363
104088
  init_config();
103364
104089
  import { existsSync as existsSync28, readdirSync as readdirSync6 } from "fs";
103365
- import { join as join73, relative as relative16 } from "path";
104090
+ import { join as join74, relative as relative16 } from "path";
103366
104091
 
103367
104092
  // src/cli/features-acceptance.ts
103368
104093
  init_acceptance2();
@@ -103370,7 +104095,7 @@ init_config();
103370
104095
  init_logger2();
103371
104096
  init_prd();
103372
104097
  import { existsSync as existsSync27 } from "fs";
103373
- import { join as join72, relative as relative15 } from "path";
104098
+ import { join as join73, relative as relative15 } from "path";
103374
104099
  async function resolveFeatureAcceptance(featureName, workdir) {
103375
104100
  let enabled = true;
103376
104101
  try {
@@ -103378,13 +104103,13 @@ async function resolveFeatureAcceptance(featureName, workdir) {
103378
104103
  if (!naxDir) {
103379
104104
  return { status: "no-prd", enabled, groups: [] };
103380
104105
  }
103381
- const repoRoot = join72(naxDir, "..");
104106
+ const repoRoot = join73(naxDir, "..");
103382
104107
  const config2 = await loadConfig(workdir);
103383
104108
  enabled = config2.acceptance?.enabled ?? true;
103384
104109
  if (!enabled) {
103385
104110
  return { status: "disabled", enabled: false, groups: [] };
103386
104111
  }
103387
- const prdPath = join72(naxDir, "features", featureName, "prd.json");
104112
+ const prdPath = join73(naxDir, "features", featureName, "prd.json");
103388
104113
  if (!existsSync27(prdPath)) {
103389
104114
  return { status: "no-prd", enabled, groups: [] };
103390
104115
  }
@@ -103427,10 +104152,10 @@ async function isNonEmptyFile(absolutePath) {
103427
104152
  }
103428
104153
  async function searchSpecSource(naxDir, repoRoot, name) {
103429
104154
  const candidates = [
103430
- { abs: join73(naxDir, "features", name, "spec.md"), kind: "markdown" },
103431
- { abs: join73(naxDir, "specs", `${name}.md`), kind: "markdown" }
104155
+ { abs: join74(naxDir, "features", name, "spec.md"), kind: "markdown" },
104156
+ { abs: join74(naxDir, "specs", `${name}.md`), kind: "markdown" }
103432
104157
  ];
103433
- const docsSpecExact = join73(repoRoot, "docs", "specs", `SPEC-${name}.md`);
104158
+ const docsSpecExact = join74(repoRoot, "docs", "specs", `SPEC-${name}.md`);
103434
104159
  candidates.push({ abs: docsSpecExact, kind: "markdown" });
103435
104160
  const checked = candidates.map((c) => relative16(repoRoot, c.abs));
103436
104161
  for (const { abs, kind } of candidates.slice(0, 2)) {
@@ -103444,11 +104169,11 @@ async function searchSpecSource(naxDir, repoRoot, name) {
103444
104169
  if (await isNonEmptyFile(docsSpecExact)) {
103445
104170
  return { source: { kind: "markdown", path: relative16(repoRoot, docsSpecExact) }, checked };
103446
104171
  }
103447
- const docsSpecsDir = join73(repoRoot, "docs", "specs");
104172
+ const docsSpecsDir = join74(repoRoot, "docs", "specs");
103448
104173
  if (existsSync28(docsSpecsDir)) {
103449
104174
  const glob = new Bun.Glob(`*${name}*.md`);
103450
104175
  for (const match of glob.scanSync({ cwd: docsSpecsDir, absolute: false })) {
103451
- const abs = join73(docsSpecsDir, match);
104176
+ const abs = join74(docsSpecsDir, match);
103452
104177
  if (await isNonEmptyFile(abs)) {
103453
104178
  const relPath = relative16(repoRoot, abs);
103454
104179
  if (!checked.includes(relPath))
@@ -103457,7 +104182,7 @@ async function searchSpecSource(naxDir, repoRoot, name) {
103457
104182
  }
103458
104183
  }
103459
104184
  }
103460
- const prdAbs = join73(naxDir, "features", name, "prd.json");
104185
+ const prdAbs = join74(naxDir, "features", name, "prd.json");
103461
104186
  const prdRel = relative16(repoRoot, prdAbs);
103462
104187
  if (!checked.includes(prdRel))
103463
104188
  checked.push(prdRel);
@@ -103467,14 +104192,14 @@ async function searchSpecSource(naxDir, repoRoot, name) {
103467
104192
  return { source: null, checked };
103468
104193
  }
103469
104194
  function discoverCandidates(naxDir) {
103470
- const featuresDir = join73(naxDir, "features");
104195
+ const featuresDir = join74(naxDir, "features");
103471
104196
  if (!existsSync28(featuresDir))
103472
104197
  return [];
103473
104198
  return readdirSync6(featuresDir, { withFileTypes: true }).filter((e) => {
103474
104199
  if (!e.isDirectory())
103475
104200
  return false;
103476
- const dir = join73(featuresDir, e.name);
103477
- return existsSync28(join73(dir, "prd.json")) || existsSync28(join73(dir, "spec.md"));
104201
+ const dir = join74(featuresDir, e.name);
104202
+ return existsSync28(join74(dir, "prd.json")) || existsSync28(join74(dir, "spec.md"));
103478
104203
  }).map((e) => e.name).sort();
103479
104204
  }
103480
104205
  async function resolveFeatureSpec(name, workdir) {
@@ -103485,9 +104210,9 @@ async function resolveFeatureSpec(name, workdir) {
103485
104210
  message: `not a nax repo: no .nax/config.json found from ${workdir}`
103486
104211
  };
103487
104212
  }
103488
- const repoRoot = join73(naxDir, "..");
104213
+ const repoRoot = join74(naxDir, "..");
103489
104214
  if (name !== undefined && (name.startsWith("./") || name.startsWith("/") || name.endsWith(".md"))) {
103490
- const abs = name.startsWith("/") ? name : join73(workdir, name);
104215
+ const abs = name.startsWith("/") ? name : join74(workdir, name);
103491
104216
  if (!existsSync28(abs)) {
103492
104217
  return {
103493
104218
  status: "missing",
@@ -103526,7 +104251,7 @@ async function resolveFeatureSpec(name, workdir) {
103526
104251
  message: `resolved spec: ${source2.path}`
103527
104252
  };
103528
104253
  }
103529
- const featureDir = join73(naxDir, "features", name);
104254
+ const featureDir = join74(naxDir, "features", name);
103530
104255
  if (existsSync28(featureDir)) {
103531
104256
  return {
103532
104257
  status: "missing",
@@ -103588,14 +104313,14 @@ init_runtime();
103588
104313
  init_json_file();
103589
104314
  init_routing();
103590
104315
  import { mkdirSync as mkdirSync6 } from "fs";
103591
- import { basename as basename14, join as join74 } from "path";
104316
+ import { basename as basename14, join as join75 } from "path";
103592
104317
  var _routingCalibrateDeps = {
103593
104318
  loadRunMetrics: (outputDir) => loadRunMetrics(outputDir),
103594
104319
  readConfig: (workdir) => loadConfig(workdir),
103595
104320
  writeConfig: async (workdir, config2) => {
103596
104321
  const dir = projectInputDir(workdir);
103597
104322
  mkdirSync6(dir, { recursive: true });
103598
- const filePath = join74(dir, "config.json");
104323
+ const filePath = join75(dir, "config.json");
103599
104324
  await saveJsonFile(filePath, config2, "routing-calibrate");
103600
104325
  },
103601
104326
  stdout: (msg) => {
@@ -103722,7 +104447,7 @@ init_logger2();
103722
104447
  init_detect2();
103723
104448
  init_workspace();
103724
104449
  init_common();
103725
- import { join as join75 } from "path";
104450
+ import { join as join76 } from "path";
103726
104451
  function resolveEffective(detected, configPatterns) {
103727
104452
  if (configPatterns !== undefined)
103728
104453
  return "config";
@@ -103730,14 +104455,14 @@ function resolveEffective(detected, configPatterns) {
103730
104455
  return "detected";
103731
104456
  return "none";
103732
104457
  }
103733
- async function loadRawConfig(path23) {
103734
- const f = Bun.file(path23);
104458
+ async function loadRawConfig(path24) {
104459
+ const f = Bun.file(path24);
103735
104460
  if (!await f.exists())
103736
104461
  return {};
103737
104462
  return JSON.parse(await f.text());
103738
104463
  }
103739
- async function writeRawConfig(path23, data) {
103740
- await Bun.write(path23, `${JSON.stringify(data, null, 2)}
104464
+ async function writeRawConfig(path24, data) {
104465
+ await Bun.write(path24, `${JSON.stringify(data, null, 2)}
103741
104466
  `);
103742
104467
  }
103743
104468
  function deepSet(obj, keyPath, value) {
@@ -103807,7 +104532,7 @@ async function detectCommand(options) {
103807
104532
  const rootDetected = detectionMap[""] ?? { patterns: [], confidence: "empty", sources: [] };
103808
104533
  const pkgEntries = await Promise.all(packageDirs.map(async (dir) => {
103809
104534
  const det = detectionMap[dir] ?? { patterns: [], confidence: "empty", sources: [] };
103810
- const pkgConfigPath = join75(workdir, ".nax", "mono", dir, "config.json");
104535
+ const pkgConfigPath = join76(workdir, ".nax", "mono", dir, "config.json");
103811
104536
  const pkgRaw = await loadRawConfig(pkgConfigPath);
103812
104537
  const pkgPatterns = deepGet(pkgRaw, TEST_PATTERNS_KEY);
103813
104538
  const effective = Array.isArray(pkgPatterns) ? pkgPatterns : undefined;
@@ -103861,13 +104586,13 @@ async function detectCommand(options) {
103861
104586
  if (rootDetected.confidence === "empty") {
103862
104587
  console.log(source_default.yellow(" root: skipped (empty detection)"));
103863
104588
  } else {
103864
- const rootConfigPath = join75(workdir, ".nax", "config.json");
104589
+ const rootConfigPath = join76(workdir, ".nax", "config.json");
103865
104590
  try {
103866
104591
  const status = await applyToConfig(rootConfigPath, rootDetected.patterns, options.force ?? false);
103867
104592
  if (status === "skipped") {
103868
104593
  console.log(source_default.dim(" root: skipped (testFilePatterns already set; use --force to overwrite)"));
103869
104594
  } else {
103870
- console.log(source_default.green(` root: ${status} \u2192 ${join75(".nax", "config.json")}`));
104595
+ console.log(source_default.green(` root: ${status} \u2192 ${join76(".nax", "config.json")}`));
103871
104596
  }
103872
104597
  } catch (err) {
103873
104598
  console.error(source_default.red(` root: write failed \u2014 ${err.message}`));
@@ -103880,13 +104605,13 @@ async function detectCommand(options) {
103880
104605
  console.log(source_default.dim(` ${dir}: skipped (empty detection)`));
103881
104606
  continue;
103882
104607
  }
103883
- const pkgConfigPath = join75(workdir, ".nax", "mono", dir, "config.json");
104608
+ const pkgConfigPath = join76(workdir, ".nax", "mono", dir, "config.json");
103884
104609
  try {
103885
104610
  const status = await applyToConfig(pkgConfigPath, det.patterns, options.force ?? false);
103886
104611
  if (status === "skipped") {
103887
104612
  console.log(source_default.dim(` ${dir}: skipped (already set)`));
103888
104613
  } else {
103889
- console.log(source_default.green(` ${dir}: ${status} \u2192 ${join75(".nax", "mono", dir, "config.json")}`));
104614
+ console.log(source_default.green(` ${dir}: ${status} \u2192 ${join76(".nax", "mono", dir, "config.json")}`));
103890
104615
  }
103891
104616
  } catch (err) {
103892
104617
  console.error(source_default.red(` ${dir}: write failed \u2014 ${err.message}`));
@@ -103904,19 +104629,19 @@ async function detectCommand(options) {
103904
104629
  // src/commands/logs.ts
103905
104630
  init_common();
103906
104631
  import { existsSync as existsSync30 } from "fs";
103907
- import { join as join78 } from "path";
104632
+ import { join as join79 } from "path";
103908
104633
 
103909
104634
  // src/commands/logs-formatter.ts
103910
104635
  init_source();
103911
104636
  init_formatter();
103912
104637
  import { readdirSync as readdirSync8 } from "fs";
103913
- import { join as join77 } from "path";
104638
+ import { join as join78 } from "path";
103914
104639
 
103915
104640
  // src/commands/logs-reader.ts
103916
104641
  init_paths3();
103917
104642
  import { existsSync as existsSync29, readdirSync as readdirSync7 } from "fs";
103918
104643
  import { readdir as readdir3 } from "fs/promises";
103919
- import { join as join76 } from "path";
104644
+ import { join as join77 } from "path";
103920
104645
  var _logsReaderDeps = {
103921
104646
  getRunsDir
103922
104647
  };
@@ -103930,7 +104655,7 @@ async function resolveRunFileFromRegistry(runId) {
103930
104655
  }
103931
104656
  let matched = null;
103932
104657
  for (const entry of entries) {
103933
- const metaPath = join76(runsDir, entry, "meta.json");
104658
+ const metaPath = join77(runsDir, entry, "meta.json");
103934
104659
  try {
103935
104660
  const meta3 = await Bun.file(metaPath).json();
103936
104661
  if (meta3.runId === runId || meta3.runId.startsWith(runId)) {
@@ -103952,14 +104677,14 @@ async function resolveRunFileFromRegistry(runId) {
103952
104677
  return null;
103953
104678
  }
103954
104679
  const specificFile = files.find((f) => f === `${matched.runId}.jsonl`);
103955
- return join76(matched.eventsDir, specificFile ?? files[0]);
104680
+ return join77(matched.eventsDir, specificFile ?? files[0]);
103956
104681
  }
103957
104682
  async function selectRunFile(runsDir) {
103958
104683
  const files = readdirSync7(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
103959
104684
  if (files.length === 0) {
103960
104685
  return null;
103961
104686
  }
103962
- return join76(runsDir, files[0]);
104687
+ return join77(runsDir, files[0]);
103963
104688
  }
103964
104689
  async function extractRunSummary(filePath) {
103965
104690
  const file3 = Bun.file(filePath);
@@ -104045,7 +104770,7 @@ Runs:
104045
104770
  console.log(source_default.gray(" Timestamp Stories Duration Cost Status"));
104046
104771
  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"));
104047
104772
  for (const file3 of files) {
104048
- const filePath = join77(runsDir, file3);
104773
+ const filePath = join78(runsDir, file3);
104049
104774
  const summary = await extractRunSummary(filePath);
104050
104775
  const timestamp = file3.replace(".jsonl", "");
104051
104776
  const stories = summary ? `${summary.passed}/${summary.total}` : "?/?";
@@ -104159,7 +104884,7 @@ async function logsCommand(options) {
104159
104884
  return;
104160
104885
  }
104161
104886
  const resolved = resolveProject2({ dir: options.dir });
104162
- const naxDir = join78(resolved.projectDir, ".nax");
104887
+ const naxDir = join79(resolved.projectDir, ".nax");
104163
104888
  const configPath = resolved.configPath;
104164
104889
  const configFile = Bun.file(configPath);
104165
104890
  const config2 = await configFile.json();
@@ -104167,8 +104892,8 @@ async function logsCommand(options) {
104167
104892
  if (!featureName) {
104168
104893
  throw new Error("No feature specified in config.json");
104169
104894
  }
104170
- const featureDir = join78(naxDir, "features", featureName);
104171
- const runsDir = join78(featureDir, "runs");
104895
+ const featureDir = join79(naxDir, "features", featureName);
104896
+ const runsDir = join79(featureDir, "runs");
104172
104897
  if (!existsSync30(runsDir)) {
104173
104898
  throw new Error(`No runs directory found for feature: ${featureName}`);
104174
104899
  }
@@ -104194,7 +104919,7 @@ init_prd();
104194
104919
  init_precheck();
104195
104920
  init_common();
104196
104921
  import { existsSync as existsSync31 } from "fs";
104197
- import { join as join79 } from "path";
104922
+ import { join as join80 } from "path";
104198
104923
  async function precheckCommand(options) {
104199
104924
  const resolved = resolveProject2({
104200
104925
  dir: options.dir,
@@ -104216,9 +104941,9 @@ async function precheckCommand(options) {
104216
104941
  process.exit(1);
104217
104942
  }
104218
104943
  }
104219
- const naxDir = join79(resolved.projectDir, ".nax");
104220
- const featureDir = join79(naxDir, "features", featureName);
104221
- const prdPath = join79(featureDir, "prd.json");
104944
+ const naxDir = join80(resolved.projectDir, ".nax");
104945
+ const featureDir = join80(naxDir, "features", featureName);
104946
+ const prdPath = join80(featureDir, "prd.json");
104222
104947
  if (!existsSync31(featureDir)) {
104223
104948
  console.error(source_default.red(`Feature not found: ${featureName}`));
104224
104949
  process.exit(1);
@@ -104240,13 +104965,13 @@ async function precheckCommand(options) {
104240
104965
  // src/commands/replay.ts
104241
104966
  init_errors();
104242
104967
  import { existsSync as existsSync32 } from "fs";
104243
- import { dirname as dirname12 } from "path";
104968
+ import { dirname as dirname13 } from "path";
104244
104969
 
104245
104970
  // src/replay/discovery.ts
104246
104971
  init_errors();
104247
104972
  init_paths3();
104248
104973
  import { readdir as readdir4 } from "fs/promises";
104249
- import { join as join80 } from "path";
104974
+ import { join as join81 } from "path";
104250
104975
  var _discoveryDeps = {
104251
104976
  getRunsDir
104252
104977
  };
@@ -104260,7 +104985,7 @@ async function loadMetas(runsDir) {
104260
104985
  const metas = [];
104261
104986
  for (const entry of entries) {
104262
104987
  try {
104263
- const meta3 = await Bun.file(join80(runsDir, entry, "meta.json")).json();
104988
+ const meta3 = await Bun.file(join81(runsDir, entry, "meta.json")).json();
104264
104989
  metas.push(meta3);
104265
104990
  } catch {}
104266
104991
  }
@@ -104277,7 +105002,7 @@ async function discoverRun(query, depsArg = _discoveryDeps) {
104277
105002
  throw new NaxError("No runs registered", "RUN_NOT_FOUND", { runsDir });
104278
105003
  }
104279
105004
  const latest = metas.reduce((acc, m) => m.runId > acc.runId ? m : acc);
104280
- return { meta: latest, jsonlPath: join80(latest.eventsDir, `${latest.runId}.jsonl`) };
105005
+ return { meta: latest, jsonlPath: join81(latest.eventsDir, `${latest.runId}.jsonl`) };
104281
105006
  }
104282
105007
  const matched = metas.filter((m) => matches(m, query));
104283
105008
  if (matched.length === 0) {
@@ -104294,7 +105019,7 @@ async function discoverRun(query, depsArg = _discoveryDeps) {
104294
105019
  });
104295
105020
  }
104296
105021
  const meta3 = matched[0];
104297
- return { meta: meta3, jsonlPath: join80(meta3.eventsDir, `${meta3.runId}.jsonl`) };
105022
+ return { meta: meta3, jsonlPath: join81(meta3.eventsDir, `${meta3.runId}.jsonl`) };
104298
105023
  }
104299
105024
 
104300
105025
  // src/replay/json.ts
@@ -104525,10 +105250,10 @@ function renderReport(timeline, options = {}) {
104525
105250
  }
104526
105251
 
104527
105252
  // src/commands/replay.ts
104528
- async function readJsonlLenient(path23) {
104529
- if (!existsSync32(path23))
105253
+ async function readJsonlLenient(path24) {
105254
+ if (!existsSync32(path24))
104530
105255
  return [];
104531
- const content = await Bun.file(path23).text();
105256
+ const content = await Bun.file(path24).text();
104532
105257
  const lines = content.split(`
104533
105258
  `);
104534
105259
  const entries = [];
@@ -104542,18 +105267,18 @@ async function readJsonlLenient(path23) {
104542
105267
  }
104543
105268
  return entries;
104544
105269
  }
104545
- async function readJsonOrUndefined(path23) {
104546
- if (!existsSync32(path23))
105270
+ async function readJsonOrUndefined(path24) {
105271
+ if (!existsSync32(path24))
104547
105272
  return;
104548
105273
  try {
104549
- return await Bun.file(path23).json();
105274
+ return await Bun.file(path24).json();
104550
105275
  } catch {
104551
105276
  return;
104552
105277
  }
104553
105278
  }
104554
105279
  async function readMetricsFromProject(meta3) {
104555
105280
  const { loadRunMetrics: loadRunMetrics2 } = await Promise.resolve().then(() => (init_tracker(), exports_tracker));
104556
- const outputDir = dirname12(dirname12(dirname12(meta3.eventsDir)));
105281
+ const outputDir = dirname13(dirname13(dirname13(meta3.eventsDir)));
104557
105282
  const all = await loadRunMetrics2(outputDir);
104558
105283
  return all.find((m) => m.runId === meta3.runId);
104559
105284
  }
@@ -104632,11 +105357,11 @@ init_errors();
104632
105357
  init_checkpoint();
104633
105358
  init_runtime();
104634
105359
  import { existsSync as existsSync37 } from "fs";
104635
- import { basename as basename17, join as join94 } from "path";
105360
+ import { basename as basename17, join as join95 } from "path";
104636
105361
  async function defaultCheckpointExists(featureDir) {
104637
105362
  if (!featureDir || !existsSync37(featureDir))
104638
105363
  return false;
104639
- return existsSync37(join94(featureDir, "checkpoint.jsonl"));
105364
+ return existsSync37(join95(featureDir, "checkpoint.jsonl"));
104640
105365
  }
104641
105366
  async function defaultLoadCheckpoints(featureDir) {
104642
105367
  return loadCheckpoints(featureDir);
@@ -104696,12 +105421,12 @@ function registerResumeCommand(program2) {
104696
105421
  `);
104697
105422
  process.exit(1);
104698
105423
  }
104699
- const featureDir = join94(naxDir, "features", cmdOpts.feature);
105424
+ const featureDir = join95(naxDir, "features", cmdOpts.feature);
104700
105425
  const deps = {
104701
105426
  ..._resumeCmdDeps,
104702
105427
  runInvocation: async (feature, opts) => {
104703
105428
  const config2 = await loadConfig2(naxDir ?? undefined);
104704
- const prdPath = join94(opts.featureDir ?? "", "prd.json");
105429
+ const prdPath = join95(opts.featureDir ?? "", "prd.json");
104705
105430
  if (!existsSync38(prdPath)) {
104706
105431
  process.stderr.write(`Feature "${feature}" not found or missing prd.json
104707
105432
  `);
@@ -104713,7 +105438,7 @@ function registerResumeCommand(program2) {
104713
105438
  applyResumeModeDeps2(opts.featureDir ?? "", "auto");
104714
105439
  const projectKey = config2.name?.trim() || basename17(cmdOpts.dir);
104715
105440
  const outputDir = projectOutputDir(projectKey, config2.outputDir);
104716
- const statusFilePath = join94(outputDir, "status.json");
105441
+ const statusFilePath = join95(outputDir, "status.json");
104717
105442
  const result = await run2({
104718
105443
  prdPath,
104719
105444
  workdir: cmdOpts.dir,
@@ -104748,7 +105473,7 @@ function registerResumeCommand(program2) {
104748
105473
  init_source();
104749
105474
  init_paths3();
104750
105475
  import { readdir as readdir6 } from "fs/promises";
104751
- import { join as join95 } from "path";
105476
+ import { join as join96 } from "path";
104752
105477
  var DEFAULT_LIMIT = 20;
104753
105478
  var _runsCmdDeps = {
104754
105479
  getRunsDir
@@ -104805,7 +105530,7 @@ async function runsCommand(options = {}) {
104805
105530
  }
104806
105531
  const rows = [];
104807
105532
  for (const entry of entries) {
104808
- const metaPath = join95(runsDir, entry, "meta.json");
105533
+ const metaPath = join96(runsDir, entry, "meta.json");
104809
105534
  let meta3;
104810
105535
  try {
104811
105536
  meta3 = await Bun.file(metaPath).json();
@@ -104882,7 +105607,7 @@ async function runsCommand(options = {}) {
104882
105607
 
104883
105608
  // src/commands/unlock.ts
104884
105609
  init_source();
104885
- import { join as join96 } from "path";
105610
+ import { join as join97 } from "path";
104886
105611
  function isProcessAlive2(pid) {
104887
105612
  try {
104888
105613
  process.kill(pid, 0);
@@ -104897,7 +105622,7 @@ function formatLockAge(ageMs) {
104897
105622
  }
104898
105623
  async function unlockCommand(options) {
104899
105624
  const workdir = options.dir ?? process.cwd();
104900
- const lockPath = join96(workdir, "nax.lock");
105625
+ const lockPath = join97(workdir, "nax.lock");
104901
105626
  const lockFile = Bun.file(lockPath);
104902
105627
  const exists = await lockFile.exists();
104903
105628
  if (!exists) {
@@ -109842,8 +110567,8 @@ function Text({ color, backgroundColor, dimColor = false, bold = false, italic =
109842
110567
  }
109843
110568
 
109844
110569
  // node_modules/ink/build/components/ErrorOverview.js
109845
- var cleanupPath = (path31) => {
109846
- return path31?.replace(`file://${cwd()}/`, "");
110570
+ var cleanupPath = (path32) => {
110571
+ return path32?.replace(`file://${cwd()}/`, "");
109847
110572
  };
109848
110573
  var stackUtils = new import_stack_utils.default({
109849
110574
  cwd: cwd(),
@@ -110547,8 +111272,8 @@ class Ink {
110547
111272
  }
110548
111273
  }
110549
111274
  async waitUntilExit() {
110550
- this.exitPromise ||= new Promise((resolve18, reject2) => {
110551
- this.resolveExitPromise = resolve18;
111275
+ this.exitPromise ||= new Promise((resolve19, reject2) => {
111276
+ this.resolveExitPromise = resolve19;
110552
111277
  this.rejectExitPromise = reject2;
110553
111278
  });
110554
111279
  if (!this.beforeExitHandler) {
@@ -112802,7 +113527,7 @@ async function promptForConfirmation(question) {
112802
113527
  if (!process.stdin.isTTY) {
112803
113528
  return true;
112804
113529
  }
112805
- return new Promise((resolve18) => {
113530
+ return new Promise((resolve19) => {
112806
113531
  process.stdout.write(source_default.bold(`${question} [Y/n] `));
112807
113532
  process.stdin.setRawMode(true);
112808
113533
  process.stdin.resume();
@@ -112815,9 +113540,9 @@ async function promptForConfirmation(question) {
112815
113540
  process.stdout.write(`
112816
113541
  `);
112817
113542
  if (answer === "n") {
112818
- resolve18(false);
113543
+ resolve19(false);
112819
113544
  } else {
112820
- resolve18(true);
113545
+ resolve19(true);
112821
113546
  }
112822
113547
  };
112823
113548
  process.stdin.on("data", handler);
@@ -112846,7 +113571,7 @@ Next: nax generate --package ${options.package}`));
112846
113571
  }
112847
113572
  return;
112848
113573
  }
112849
- const naxDir = join100(workdir, ".nax");
113574
+ const naxDir = join101(workdir, ".nax");
112850
113575
  if (existsSync39(naxDir) && !options.force) {
112851
113576
  console.log(source_default.yellow("nax already initialized. Use --force to overwrite."));
112852
113577
  return;
@@ -112875,11 +113600,11 @@ Next: nax generate --package ${options.package}`));
112875
113600
  }
112876
113601
  }
112877
113602
  }
112878
- mkdirSync8(join100(naxDir, "features"), { recursive: true });
112879
- mkdirSync8(join100(naxDir, "hooks"), { recursive: true });
113603
+ mkdirSync8(join101(naxDir, "features"), { recursive: true });
113604
+ mkdirSync8(join101(naxDir, "hooks"), { recursive: true });
112880
113605
  const initConfig = options.name ? { ...DEFAULT_CONFIG, name: options.name } : DEFAULT_CONFIG;
112881
- await Bun.write(join100(naxDir, "config.json"), JSON.stringify(initConfig, null, 2));
112882
- await Bun.write(join100(naxDir, "hooks.json"), JSON.stringify({
113606
+ await Bun.write(join101(naxDir, "config.json"), JSON.stringify(initConfig, null, 2));
113607
+ await Bun.write(join101(naxDir, "hooks.json"), JSON.stringify({
112883
113608
  hooks: {
112884
113609
  "on-start": { command: 'echo "nax started: $NAX_FEATURE"', enabled: false },
112885
113610
  "on-complete": { command: 'echo "nax complete: $NAX_FEATURE"', enabled: false },
@@ -112887,12 +113612,12 @@ Next: nax generate --package ${options.package}`));
112887
113612
  "on-error": { command: 'echo "nax error: $NAX_REASON"', enabled: false }
112888
113613
  }
112889
113614
  }, null, 2));
112890
- await Bun.write(join100(naxDir, ".gitignore"), `# nax temp files
113615
+ await Bun.write(join101(naxDir, ".gitignore"), `# nax temp files
112891
113616
  *.tmp
112892
113617
  .paused.json
112893
113618
  .nax-verifier-verdict.json
112894
113619
  `);
112895
- await Bun.write(join100(naxDir, "context.md"), `# Project Context
113620
+ await Bun.write(join101(naxDir, "context.md"), `# Project Context
112896
113621
 
112897
113622
  This document defines coding standards, architectural decisions, and forbidden patterns for this project.
112898
113623
  Run \`nax generate\` to regenerate agent config files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) from this file.
@@ -113076,7 +113801,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
113076
113801
  const cliOverrides = {};
113077
113802
  const cliProfiles = options.profile ?? [];
113078
113803
  const profileOverride = naxDir ? await resolveRunProfileOverride({
113079
- prdPath: join100(naxDir, "features", options.feature, "prd.json"),
113804
+ prdPath: join101(naxDir, "features", options.feature, "prd.json"),
113080
113805
  projectRoot: workdir,
113081
113806
  cliProfile: cliProfiles,
113082
113807
  envProfile: process.env.NAX_PROFILE
@@ -113089,8 +113814,8 @@ program2.command("run").description("Run the orchestration loop for a feature").
113089
113814
  console.error(source_default.red("nax not initialized. Run: nax init"));
113090
113815
  process.exit(1);
113091
113816
  }
113092
- const featureDir = join100(naxDir, "features", options.feature);
113093
- const prdPath = join100(featureDir, "prd.json");
113817
+ const featureDir = join101(naxDir, "features", options.feature);
113818
+ const prdPath = join101(featureDir, "prd.json");
113094
113819
  if (options.plan && options.from) {
113095
113820
  if (existsSync39(prdPath) && !options.force) {
113096
113821
  console.error(source_default.red(`Error: prd.json already exists for feature "${options.feature}".`));
@@ -113112,10 +113837,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
113112
113837
  }
113113
113838
  }
113114
113839
  try {
113115
- const planLogDir = join100(featureDir, "plan");
113840
+ const planLogDir = join101(featureDir, "plan");
113116
113841
  mkdirSync8(planLogDir, { recursive: true });
113117
113842
  const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
113118
- const planLogPath = join100(planLogDir, `${planLogId}.jsonl`);
113843
+ const planLogPath = join101(planLogDir, `${planLogId}.jsonl`);
113119
113844
  initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
113120
113845
  console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
113121
113846
  console.log(source_default.dim(" [Planning phase: generating PRD from spec]"));
@@ -113161,10 +113886,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
113161
113886
  resetLogger();
113162
113887
  const projectKey = config2.name?.trim() || basename19(workdir);
113163
113888
  const outputDir = projectOutputDir(projectKey, config2.outputDir);
113164
- const runsDir = join100(outputDir, "features", options.feature, "runs");
113889
+ const runsDir = join101(outputDir, "features", options.feature, "runs");
113165
113890
  mkdirSync8(runsDir, { recursive: true });
113166
113891
  const runId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
113167
- const logFilePath = join100(runsDir, `${runId}.jsonl`);
113892
+ const logFilePath = join101(runsDir, `${runId}.jsonl`);
113168
113893
  const isTTY = process.stdout.isTTY ?? false;
113169
113894
  const headlessFlag = options.headless ?? false;
113170
113895
  const headlessEnv = process.env.NAX_HEADLESS === "1";
@@ -113190,7 +113915,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
113190
113915
  }
113191
113916
  config2.execution.costLimit = maxCost;
113192
113917
  }
113193
- const globalNaxDir = join100(homedir3(), ".nax");
113918
+ const globalNaxDir = join101(homedir3(), ".nax");
113194
113919
  const hooks = await loadHooksConfig(naxDir, globalNaxDir);
113195
113920
  const eventEmitter = new PipelineEventEmitter;
113196
113921
  const agentStreamEvents = useHeadless ? undefined : new AgentStreamEventBus;
@@ -113209,12 +113934,12 @@ program2.command("run").description("Run the orchestration loop for a feature").
113209
113934
  stories: initialStories,
113210
113935
  events: eventEmitter,
113211
113936
  agentStreamEvents,
113212
- queueFilePath: join100(workdir, ".queue.txt")
113937
+ queueFilePath: join101(workdir, ".queue.txt")
113213
113938
  });
113214
113939
  } else {
113215
113940
  console.log(source_default.dim(" [Headless mode \u2014 pipe output]"));
113216
113941
  }
113217
- const statusFilePath = join100(outputDir, "status.json");
113942
+ const statusFilePath = join101(outputDir, "status.json");
113218
113943
  let parallel;
113219
113944
  if (options.parallel !== undefined) {
113220
113945
  parallel = Number.parseInt(options.parallel, 10);
@@ -113277,7 +114002,7 @@ Scheduled run cancelled.`));
113277
114002
  agentStreamEvents,
113278
114003
  resumeMode: options.fresh === true || options.resume === false ? "fresh" : "auto"
113279
114004
  });
113280
- const latestSymlink = join100(runsDir, "latest.jsonl");
114005
+ const latestSymlink = join101(runsDir, "latest.jsonl");
113281
114006
  try {
113282
114007
  if (existsSync39(latestSymlink)) {
113283
114008
  Bun.spawnSync(["rm", latestSymlink]);
@@ -113374,9 +114099,9 @@ features.command("create <name>").description("Create a new feature").option("-d
113374
114099
  console.error(source_default.red("nax not initialized. Run: nax init"));
113375
114100
  process.exit(1);
113376
114101
  }
113377
- const featureDir = join100(naxDir, "features", name);
114102
+ const featureDir = join101(naxDir, "features", name);
113378
114103
  mkdirSync8(featureDir, { recursive: true });
113379
- await Bun.write(join100(featureDir, "spec.md"), `# Feature: ${name}
114104
+ await Bun.write(join101(featureDir, "spec.md"), `# Feature: ${name}
113380
114105
 
113381
114106
  ## Overview
113382
114107
 
@@ -113409,7 +114134,7 @@ features.command("create <name>").description("Create a new feature").option("-d
113409
114134
 
113410
114135
  <!-- What this feature explicitly does NOT cover. -->
113411
114136
  `);
113412
- await Bun.write(join100(featureDir, "progress.txt"), `# Progress: ${name}
114137
+ await Bun.write(join101(featureDir, "progress.txt"), `# Progress: ${name}
113413
114138
 
113414
114139
  Created: ${new Date().toISOString()}
113415
114140
 
@@ -113435,7 +114160,7 @@ features.command("list").description("List all features").option("-d, --dir <pat
113435
114160
  console.error(source_default.red("nax not initialized."));
113436
114161
  process.exit(1);
113437
114162
  }
113438
- const featuresDir = join100(naxDir, "features");
114163
+ const featuresDir = join101(naxDir, "features");
113439
114164
  if (!existsSync39(featuresDir)) {
113440
114165
  console.log(source_default.dim("No features yet."));
113441
114166
  return;
@@ -113450,7 +114175,7 @@ features.command("list").description("List all features").option("-d, --dir <pat
113450
114175
  Features:
113451
114176
  `));
113452
114177
  for (const name of entries) {
113453
- const prdPath = join100(featuresDir, name, "prd.json");
114178
+ const prdPath = join101(featuresDir, name, "prd.json");
113454
114179
  if (existsSync39(prdPath)) {
113455
114180
  const prd = await loadPRD(prdPath);
113456
114181
  const c = countStories(prd);
@@ -113523,10 +114248,10 @@ Use: nax plan -f <feature> --from <spec>`));
113523
114248
  cliOverrides.profile = cliProfiles;
113524
114249
  }
113525
114250
  const config2 = await loadConfig(workdir, cliOverrides);
113526
- const featureLogDir = join100(naxDir, "features", options.feature, "plan");
114251
+ const featureLogDir = join101(naxDir, "features", options.feature, "plan");
113527
114252
  mkdirSync8(featureLogDir, { recursive: true });
113528
114253
  const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
113529
- const planLogPath = join100(featureLogDir, `${planLogId}.jsonl`);
114254
+ const planLogPath = join101(featureLogDir, `${planLogId}.jsonl`);
113530
114255
  initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
113531
114256
  console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
113532
114257
  try {
@@ -113633,8 +114358,8 @@ configProfileCmd.command("current").description("Show the currently active profi
113633
114358
  });
113634
114359
  configProfileCmd.command("create <name>").description("Create a new empty profile").option("-d, --dir <path>", "Project directory", process.cwd()).action(async (name, options) => {
113635
114360
  try {
113636
- const path31 = await profileCreateCommand(name, options.dir);
113637
- console.log(`Created profile at: ${path31}`);
114361
+ const path32 = await profileCreateCommand(name, options.dir);
114362
+ console.log(`Created profile at: ${path32}`);
113638
114363
  } catch (err) {
113639
114364
  console.error(source_default.red(`Error: ${err.message}`));
113640
114365
  process.exit(1);