@on-par/factory-cli 0.9.25-next.9 → 0.9.25

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.
Files changed (80) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/doctor-codex-sandbox.d.ts +8 -4
  3. package/dist/cli/doctor-codex-sandbox.d.ts.map +1 -1
  4. package/dist/cli/doctor-codex-sandbox.js +25 -5
  5. package/dist/cli/doctor-codex-sandbox.js.map +1 -1
  6. package/dist/cli/doctor-config.d.ts.map +1 -1
  7. package/dist/cli/doctor-config.js +13 -2
  8. package/dist/cli/doctor-config.js.map +1 -1
  9. package/dist/cli/doctor.d.ts +2 -0
  10. package/dist/cli/doctor.d.ts.map +1 -1
  11. package/dist/cli/doctor.js +5 -6
  12. package/dist/cli/doctor.js.map +1 -1
  13. package/dist/cli/index.d.ts +2 -9
  14. package/dist/cli/index.d.ts.map +1 -1
  15. package/dist/cli/index.js +39 -95
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cli/json-contract.d.ts.map +1 -1
  18. package/dist/cli/json-contract.js +5 -1
  19. package/dist/cli/json-contract.js.map +1 -1
  20. package/dist/cli/land.d.ts +1 -3
  21. package/dist/cli/land.d.ts.map +1 -1
  22. package/dist/cli/land.js +2 -9
  23. package/dist/cli/land.js.map +1 -1
  24. package/dist/cli/program-run-work.d.ts.map +1 -1
  25. package/dist/cli/program-run-work.js +4 -4
  26. package/dist/cli/program-run-work.js.map +1 -1
  27. package/dist/cli/repo-router.js +3 -1
  28. package/dist/cli/repo-router.js.map +1 -1
  29. package/dist/cli/run-branch.d.ts +5 -1
  30. package/dist/cli/run-branch.d.ts.map +1 -1
  31. package/dist/cli/run-branch.js +7 -4
  32. package/dist/cli/run-branch.js.map +1 -1
  33. package/dist/cli/run-brief.d.ts.map +1 -1
  34. package/dist/cli/run-brief.js +38 -10
  35. package/dist/cli/run-brief.js.map +1 -1
  36. package/dist/cli/run-lane-deps.d.ts +0 -4
  37. package/dist/cli/run-lane-deps.d.ts.map +1 -1
  38. package/dist/cli/run-lane.d.ts.map +1 -1
  39. package/dist/cli/run-lane.js +3 -26
  40. package/dist/cli/run-lane.js.map +1 -1
  41. package/dist/cli/ship-options.d.ts +3 -1
  42. package/dist/cli/ship-options.d.ts.map +1 -1
  43. package/dist/cli/ship-options.js +3 -3
  44. package/dist/cli/ship-options.js.map +1 -1
  45. package/dist/cli/ship-runtime.d.ts +1 -2
  46. package/dist/cli/ship-runtime.d.ts.map +1 -1
  47. package/dist/cli/ship-runtime.js.map +1 -1
  48. package/dist/cli/ship-steps.d.ts +1 -7
  49. package/dist/cli/ship-steps.d.ts.map +1 -1
  50. package/dist/cli/ship-steps.js +3 -23
  51. package/dist/cli/ship-steps.js.map +1 -1
  52. package/dist/cli/ship.d.ts +4 -2
  53. package/dist/cli/ship.d.ts.map +1 -1
  54. package/dist/cli/ship.js +16 -7
  55. package/dist/cli/ship.js.map +1 -1
  56. package/dist/cli/slice-index.d.ts +1 -1
  57. package/dist/cli/slice-index.d.ts.map +1 -1
  58. package/dist/cli/slice-index.js +4 -8
  59. package/dist/cli/slice-index.js.map +1 -1
  60. package/dist/cli/stack-run.d.ts +14 -2
  61. package/dist/cli/stack-run.d.ts.map +1 -1
  62. package/dist/cli/stack-run.js +50 -5
  63. package/dist/cli/stack-run.js.map +1 -1
  64. package/dist/cli/status-json.d.ts +1 -2
  65. package/dist/cli/status-json.d.ts.map +1 -1
  66. package/dist/cli/status-json.js +2 -7
  67. package/dist/cli/status-json.js.map +1 -1
  68. package/dist/cli/status.d.ts.map +1 -1
  69. package/dist/cli/status.js +4 -23
  70. package/dist/cli/status.js.map +1 -1
  71. package/package.json +4 -4
  72. package/schemas/status.schema.json +3 -1
  73. package/dist/cli/run-children.d.ts +0 -24
  74. package/dist/cli/run-children.d.ts.map +0 -1
  75. package/dist/cli/run-children.js +0 -73
  76. package/dist/cli/run-children.js.map +0 -1
  77. package/dist/cli/run-lane-decompose.d.ts +0 -12
  78. package/dist/cli/run-lane-decompose.d.ts.map +0 -1
  79. package/dist/cli/run-lane-decompose.js +0 -27
  80. package/dist/cli/run-lane-decompose.js.map +0 -1
package/dist/cli/index.js CHANGED
@@ -12,7 +12,7 @@ import { startupSweeps, warnQueueDiagnostics } from './queue-startup.js';
12
12
  import { proposeTriageQueue } from './triage-open-prs.js';
13
13
  import { makeQueuePreflightOps, preflightQueuedIssue, } from './queue-preflight.js';
14
14
  import { acquirePortLease, aggregateCosts, appendKpiHistoryLine, applyRepoConfig, buildPhase, checkPhase, clearProxyState, computeHealthKpis, ConstitutionLoader, createDefaultWorkSourceRegistry, createLogger, createLaneProxy, defaultFindPortListeners, describeEffectiveConfig, detectPostMergeDefects, diagnoseModels, probeDeclaredHarnesses, estimateTrailingSpend, fetchDefectSources, fetchSubscriptionUsage, formatUsageReport, getConstitutionsDir, getFactoryPaths, GITHUB_ISSUE_SOURCE, hasUnresolvedPark, InvalidWorkRequestInputError, isCommandAvailable, isProxyRunning, kpiBranchPrefixes, kpisToHistoryRecord, laneBaseUrl, laneEnv, laneHostLabel, loadFactoryConfigForRepo, loadModelsConfig, loadRepoConfig, loadRoutesConfig, joinClassifierOutcomes, mergeClassifierOutcomes, parseClassifierOutcomes, summarizeClassifierOutcomes, formatClassifierReport, mergedPrRefs, ModelRegistry, ModelRouter, parkReasonFor, parseKpiHistory, parseQueue, planPhase, readEvents, readPortLeases, readQueue, readUsage, reapOrphanProcesses, reconstructKpiEvents, recordLeasePgid, releasePortLease, renderKpiReport, renderKpiTrend, resolveDefectWindowDays, parseSizeGateMode, parseMaxSlices, SIZE_GATE_MODES, resolveEffectiveModelPins, resolveEnvironmentProxy, resolveMergePolicy, resolveSkipCI, resolveTimeouts, resolveUsageCap, resolveWatchdogPolicy, runAutoIngest, shipPhase, formatCostTotal, validateQueue, watchUsage, writeLocalRunReport, workKeyFromIssue, writeProxyState, } from '@on-par/factory-core';
15
- import { acquirePidFile, createCheckResumeStore, DEFAULT_GARDEN_MAX_CLUSTERS, DEFAULT_GARDEN_SINCE, capGardenClusters, clusterGarden, dedupGardenClusters, filterGardenOnlyNew, filterGardenWindow, markGardenTrackingUnknown, parseGardenDuration, readHarvestEvents, renderGardenJson, renderGardenReport, laneWorktreePath, migrateRepoConfigToYaml, readRepoConfigFile, rewriteRepoConfigFile, REPO_CONFIG_YAML_HEADER, claudeConfigDirOverride, claudeKeychainService, cleanupWorktree, createDaemonLogSink, factoryBranchIssue, factoryBranchPrefixes, createFactorydServer, createRunRuntime, createShipExecutor, createGithubQueue, createLocalSmallDryRun, createOctokitFilingClient, createOctokitGreenPrClient, createOctokitQueueClient, daemonRuntimePaths, defaultRegistryPath, ensureDir, fetchHumanEventSourcesCached, FACTORY_RUNTIME_CONFIG_KEYS, findUnmergedGreenPrs, listStatelessLaneIssues, formatGcReport, gitFetch, listMicroVms, listOrphanContainers, logCost, logEvent, planQueueMigration, pollBlockedParks, readCosts, readGithubQueueSnapshot, reapCleanShipWorktree, reapLaneWorktree, reapOrphanContainers, reapOrphanMicroVm, releaseRuntimeFiles, releaseStaleClaims, resolveBranchPrefix, resolveEffectiveConfig, resolveExperimental, resolveLocalOnly, describeDraftPrPolicy, resolveDraftPrPolicy, resolvePrClassifierPolicy, resolveReviewFloorRules, runOvernightQueue, parseRemoteSlug, setupWorktree, shellEscape, listBuiltInCheckers, sweepWorktrees, watchChecks, withFileLock, withGitLock, writePortFile, buildTriagePrompt, parseTriageCandidates, laneSlug, formatStopMarker, readStopMarker, detectClaudePlan, findSlicePlanComment, } from '@on-par/factory-core/internal';
15
+ import { acquirePidFile, createCheckResumeStore, DEFAULT_GARDEN_MAX_CLUSTERS, DEFAULT_GARDEN_SINCE, capGardenClusters, clusterGarden, dedupGardenClusters, filterGardenOnlyNew, filterGardenWindow, markGardenTrackingUnknown, parseGardenDuration, readHarvestEvents, renderGardenJson, renderGardenReport, laneWorktreePath, migrateRepoConfigToYaml, readRepoConfigFile, rewriteRepoConfigFile, REPO_CONFIG_YAML_HEADER, claudeConfigDirOverride, claudeKeychainService, cleanupWorktree, createDaemonLogSink, factoryBranchIssue, factoryBranchPrefixes, createFactorydServer, createRunRuntime, createShipExecutor, createGithubQueue, createLocalSmallDryRun, createOctokitFilingClient, createOctokitGreenPrClient, createOctokitQueueClient, daemonRuntimePaths, defaultRegistryPath, ensureDir, fetchHumanEventSourcesCached, FACTORY_RUNTIME_CONFIG_KEYS, findUnmergedGreenPrs, listStatelessLaneIssues, formatGcReport, gitFetch, listMicroVms, listOrphanContainers, logCost, logEvent, planQueueMigration, pollBlockedParks, readCosts, readGithubQueueSnapshot, reapCleanShipWorktree, reapLaneWorktree, reapOrphanContainers, reapOrphanMicroVm, releaseRuntimeFiles, releaseStaleClaims, resolveBranchPrefix, resolveEffectiveConfig, resolveExperimental, resolveLocalOnly, describeDraftPrPolicy, resolveDraftPrPolicy, resolvePrClassifierPolicy, resolveReviewFloorRules, runOvernightQueue, parseRemoteSlug, setupWorktree, shellEscape, listBuiltInCheckers, sweepWorktrees, watchChecks, withFileLock, withGitLock, writePortFile, buildTriagePrompt, parseTriageCandidates, laneSlug, formatStopMarker, readStopMarker, detectClaudePlan, findSlicePlanComment, listBlockedBy, aliasDeprecatedSizeGateMode, } from '@on-par/factory-core/internal';
16
16
  import { CliExitError } from './errors.js';
17
17
  import { baseBranchConflict, baseBranchOrExit } from './ship-options.js';
18
18
  import { runIssueStack } from './stack-run.js';
@@ -68,7 +68,6 @@ import { selectOctokit } from './github-stub.js';
68
68
  import { createFactoryOctokit } from './octokit.js';
69
69
  import { runDraftCommand } from './draft-command.js';
70
70
  import { checkErrorExit, checkReportExit, createDeepModelRunner, runIssueCheck } from './ready-check.js';
71
- import { childRunSucceeded, formatChildRunSummary, runChildrenInOrder } from './run-children.js';
72
71
  import { cmdRunBrief as cmdRunBriefWith } from './run-brief.js';
73
72
  import { readRunFlagOverrides, recordDraftPrFlag } from './run-flags.js';
74
73
  import { runStalenessGuard } from './staleness.js';
@@ -360,7 +359,6 @@ setShipRuntime(() => ({
360
359
  LaneParkError,
361
360
  LaneEnvironmentPauseError,
362
361
  IssueSkippedError,
363
- IssueDecomposedError,
364
362
  }));
365
363
  export { LaneEnvironmentPauseError, shipIssue };
366
364
  export function hasGitHubToken(env = process.env, tryToken) {
@@ -666,7 +664,7 @@ function branchPrefixOrExit(raw, configPath) {
666
664
  function sizeGateOrExit(raw) {
667
665
  if (raw === undefined)
668
666
  return undefined;
669
- const mode = parseSizeGateMode(raw);
667
+ const mode = parseSizeGateMode(aliasDeprecatedSizeGateMode(raw));
670
668
  if (mode === undefined) {
671
669
  throw new CliExitError(`factory: invalid --size-gate '${raw}' — expected one of: ${SIZE_GATE_MODES.join(', ')}`, 2);
672
670
  }
@@ -1109,7 +1107,9 @@ async function cmdClassifierBacktestEntry(opts) {
1109
1107
  const repoConfig = configLoaders.loadRepoConfig(repoRoot);
1110
1108
  const effective = resolveEffectiveConfig(repoConfig);
1111
1109
  const router = new coreOps.ModelRouter(applyRepoConfig(configLoaders.loadModelsConfig(), repoConfig), configLoaders.loadRoutesConfig(), false, undefined, effective.allowExperimental, effective.localOnly);
1112
- router.setCodexFullAccessTasks?.(configLoaders.loadFactoryConfigForRepo(paths.config).sandbox.codexFullAccessTasks);
1110
+ const sandbox = configLoaders.loadFactoryConfigForRepo(paths.config).sandbox;
1111
+ router.setCodexFullAccessTasks?.(sandbox.codexFullAccessTasks);
1112
+ router.setCodexSandbox?.(sandbox.codexSandbox);
1113
1113
  applyRouterGuards(router);
1114
1114
  try {
1115
1115
  await cmdClassifierBacktest({ ...opts, branchPrefix }, {
@@ -1360,7 +1360,9 @@ async function cmdTui(opts = {}, runTuiImpl = runTui) {
1360
1360
  const routesConfig = configLoaders.loadRoutesConfig();
1361
1361
  const effective = resolveEffectiveConfig(repoConfig);
1362
1362
  const router = new coreOps.ModelRouter(modelsConfig, routesConfig, false, undefined, effective.allowExperimental, effective.localOnly);
1363
- router.setCodexFullAccessTasks?.(configLoaders.loadFactoryConfigForRepo(paths.config).sandbox.codexFullAccessTasks);
1363
+ const sandbox = configLoaders.loadFactoryConfigForRepo(paths.config).sandbox;
1364
+ router.setCodexFullAccessTasks?.(sandbox.codexFullAccessTasks);
1365
+ router.setCodexSandbox?.(sandbox.codexSandbox);
1364
1366
  applyRouterGuards(router);
1365
1367
  const effectiveConfigLines = describeEffectiveConfig({
1366
1368
  router,
@@ -1602,6 +1604,8 @@ async function cmdShip(issueNum, opts) {
1602
1604
  }, { scope: { kind: 'issue', key: workKeyFromIssue(issueNum) } });
1603
1605
  }
1604
1606
  async function cmdRunIssue(issueNum, opts) {
1607
+ if (opts.runChildren)
1608
+ throw new CliExitError('--run-children was removed; oversized issues stack with --stack', 2);
1605
1609
  if (availableAgentClis(coreOps.isCommandAvailable).length === 0) {
1606
1610
  throw new CliExitError(`factory: ${missingAgentCliMessage()}`, 2);
1607
1611
  }
@@ -1610,22 +1614,24 @@ async function cmdRunIssue(issueNum, opts) {
1610
1614
  if (!existsSync(paths.root)) {
1611
1615
  throw new CliExitError(`factory: ${notInitializedMessage()}`, 2);
1612
1616
  }
1613
- const { runChildren, sizeGate: rawSizeGate, maxSlices: rawMaxSlices, stack, ...shipOpts } = opts;
1617
+ const { runChildren: _removed, sizeGate: rawSizeGate, maxSlices: rawMaxSlices, stack, ...shipOpts } = opts;
1614
1618
  const branchPrefix = branchPrefixOrExit(opts.branchPrefix, paths.config);
1615
- if (stack && rawSizeGate !== undefined && rawSizeGate !== 'stack') {
1619
+ const parsedSizeGate = sizeGateOrExit(rawSizeGate);
1620
+ if (stack && parsedSizeGate !== undefined && parsedSizeGate !== 'stack') {
1616
1621
  throw new CliExitError('factory: --stack is --size-gate stack — drop one of them', 2);
1617
1622
  }
1618
- const sizeGate = stack ? 'stack' : sizeGateOrExit(rawSizeGate);
1623
+ const sizeGate = stack ? 'stack' : parsedSizeGate;
1624
+ const explicitStack = stack === true || rawSizeGate === 'stack';
1619
1625
  const maxSlices = maxSlicesOrExit(rawMaxSlices);
1620
1626
  const baseBranch = baseBranchOrExit(opts.baseBranch);
1621
- const conflict = baseBranchConflict({ baseBranch, sizeGate, runChildren });
1627
+ const conflict = baseBranchConflict({ baseBranch, sizeGate });
1622
1628
  if (conflict)
1623
1629
  throw new CliExitError(conflict, 2);
1624
1630
  if (sizeGate === 'stack' && opts.pr === false) {
1625
1631
  throw new CliExitError('factory: --stack opens a PR per slice — drop --no-pr or drop --stack', 2);
1626
1632
  }
1627
- if (opts.pr === false && ((sizeGate !== undefined && sizeGate !== 'off') || runChildren)) {
1628
- throw new CliExitError('factory: --no-pr runs with the size gate off — drop --size-gate/--run-children or drop --no-pr', 2);
1633
+ if (opts.pr === false && sizeGate !== undefined && sizeGate !== 'off') {
1634
+ throw new CliExitError('factory: --no-pr runs with the size gate off — drop --size-gate or drop --no-pr', 2);
1629
1635
  }
1630
1636
  await withRepoRunLock(paths, 'factory run-issue', async () => {
1631
1637
  recordDraftPrFlag(paths.runFlags, opts.draftPr);
@@ -1657,96 +1663,43 @@ async function cmdRunIssue(issueNum, opts) {
1657
1663
  try {
1658
1664
  if (sizeGate === 'stack') {
1659
1665
  await runIssueStack(issueNum, baseBranch, {
1666
+ repo: ghRepo,
1667
+ list: (issue) => listBlockedBy({ octokit: getOctokit(), repo: ghRepo }, issue),
1668
+ shipMember: async (issue, base, onOutcome) => {
1669
+ const memberWork = issue === issueNum
1670
+ ? work
1671
+ : await workSources.resolve(GITHUB_ISSUE_SOURCE, { repo: ghRepo, issue });
1672
+ await shipIssue(issue, {
1673
+ ...shipOpts,
1674
+ branchPrefix,
1675
+ sizeGate,
1676
+ explicitStack,
1677
+ maxSlices,
1678
+ baseBranch: base,
1679
+ parkOverBudget: true,
1680
+ }, { repoRoot, ghRepo, workRequest: memberWork, onOutcome });
1681
+ },
1660
1682
  readSlicePlan: async () => {
1661
1683
  const lookup = await findSlicePlanComment({ octokit: getOctokit(), repo: ghRepo, issue: issueNum });
1662
1684
  return lookup.status === 'found' ? lookup.plan : undefined;
1663
1685
  },
1664
1686
  ship: async (base, onOutcome) => {
1665
- await shipIssue(issueNum, { ...shipOpts, branchPrefix, sizeGate, maxSlices, baseBranch: base }, { repoRoot, ghRepo, workRequest: work, onOutcome });
1687
+ await shipIssue(issueNum, { ...shipOpts, branchPrefix, sizeGate, explicitStack, maxSlices, baseBranch: base }, { repoRoot, ghRepo, workRequest: work, onOutcome });
1666
1688
  },
1667
1689
  });
1668
1690
  return;
1669
1691
  }
1670
- await shipIssue(issueNum, { ...shipOpts, branchPrefix, sizeGate, maxSlices }, { repoRoot, ghRepo, workRequest: work });
1692
+ await shipIssue(issueNum, { ...shipOpts, branchPrefix, sizeGate, explicitStack, maxSlices }, { repoRoot, ghRepo, workRequest: work });
1671
1693
  }
1672
1694
  catch (err) {
1673
1695
  if (err instanceof CliExitError)
1674
1696
  throw err;
1675
1697
  if (err instanceof IssueSkippedError)
1676
1698
  return;
1677
- if (err instanceof IssueDecomposedError && runChildren) {
1678
- await runDecomposedChildren(issueNum, err.childIssues, { ...shipOpts, branchPrefix, sizeGate, maxSlices }, { repoRoot, ghRepo, workSources });
1679
- return;
1680
- }
1681
- if (err instanceof IssueDecomposedError && !runChildren) {
1682
- const children = err.childIssues.map((n) => `#${n}`).join(', ');
1683
- throw new CliExitError(`Run failed for issue #${issueNum}: the size gate decomposed it into ${children} — no child issue was run. ` +
1684
- `Re-run with \`factory run-issue ${issueNum} --run-children\` to run them.`, 1);
1685
- }
1686
1699
  throw new CliExitError(`Run failed for issue #${issueNum}: ${err.message}`, 1);
1687
1700
  }
1688
1701
  }, { scope: { kind: 'issue', key: workKeyFromIssue(issueNum) } });
1689
1702
  }
1690
- /** Runs each decomposed child through the one-shot pipeline in build order, inside the caller's
1691
- * run lock, then prints a per-child summary. Nested decompositions expand in place and closed
1692
- * children are skipped. A failed or escalated child is recorded and the next one still runs;
1693
- * `.factory/STOP` is checked before each child starts (read only, ADR-0111). Throws CliExitError(1)
1694
- * unless every child is ready or skipped (#1747, #1748, #1749). */
1695
- async function runDecomposedChildren(parent, children, opts, env) {
1696
- const list = children.map((n) => `#${n}`).join(', ');
1697
- console.log(styleText('cyan', `run-children: #${parent} decomposed into ${list} — running them in build order`));
1698
- const paths = getFactoryPaths(env.repoRoot);
1699
- const results = await runChildrenInOrder(children, async (child) => {
1700
- let work;
1701
- try {
1702
- work = await env.workSources.resolve(GITHUB_ISSUE_SOURCE, {
1703
- repo: env.ghRepo,
1704
- issue: child,
1705
- });
1706
- }
1707
- catch (err) {
1708
- return { issue: child, status: 'failed', detail: `could not resolve issue #${child} (${errorDetail(err)})` };
1709
- }
1710
- console.log(styleText('cyan', `one-shot: resolved ${work.id} — running the pipeline (queue untouched)`));
1711
- let outcome;
1712
- try {
1713
- await withRepoRunLock(paths, 'factory run-issue', () => shipIssue(child, opts, {
1714
- repoRoot: env.repoRoot,
1715
- ghRepo: env.ghRepo,
1716
- workRequest: work,
1717
- onOutcome: (o) => {
1718
- outcome = o;
1719
- },
1720
- }), { scope: { kind: 'issue', key: workKeyFromIssue(child) } });
1721
- }
1722
- catch (err) {
1723
- if (err instanceof IssueDecomposedError) {
1724
- const again = err.childIssues.map((n) => `#${n}`).join(', ');
1725
- console.log(styleText('cyan', `run-children: #${child} decomposed into ${again} — running them in its place`));
1726
- return { issue: child, status: 'decomposed', children: err.childIssues };
1727
- }
1728
- if (err instanceof IssueSkippedError) {
1729
- return { issue: child, status: 'skipped', detail: err.message };
1730
- }
1731
- return { issue: child, status: 'failed', detail: err instanceof Error ? err.message : String(err) };
1732
- }
1733
- const done = outcome;
1734
- return { issue: child, status: 'ready', prNumber: done && 'prNumber' in done ? done.prNumber : undefined };
1735
- }, [parent], (next) => {
1736
- if (!existsSync(paths.stop))
1737
- return false;
1738
- logEvent(paths.events, 'stopped', next, 'STOP file present');
1739
- console.log(styleText('yellow', `run-children: .factory/STOP present — not starting #${next} or any later child`));
1740
- return true;
1741
- });
1742
- const ok = childRunSucceeded(results);
1743
- for (const line of formatChildRunSummary(parent, results)) {
1744
- console.log(ok ? styleText('green', line) : styleText('yellow', line));
1745
- }
1746
- if (!ok) {
1747
- throw new CliExitError(`Run failed for issue #${parent}: not every decomposed child reached ready-for-review or was skipped as closed (failed or not-run children are listed above)`, 1);
1748
- }
1749
- }
1750
1703
  async function cmdLocalSmallDryRun(issueNum, opts) {
1751
1704
  const repoRoot = await getRepoRoot();
1752
1705
  const ghRepo = await getGitHubRepo();
@@ -1997,7 +1950,9 @@ async function cmdTriage(opts) {
1997
1950
  const routesConfig = configLoaders.loadRoutesConfig();
1998
1951
  const effective = resolveEffectiveConfig(repoConfig);
1999
1952
  const router = new coreOps.ModelRouter(modelsConfig, routesConfig, false, undefined, effective.allowExperimental, effective.localOnly);
2000
- router.setCodexFullAccessTasks?.(configLoaders.loadFactoryConfigForRepo(paths.config).sandbox.codexFullAccessTasks);
1953
+ const sandbox = configLoaders.loadFactoryConfigForRepo(paths.config).sandbox;
1954
+ router.setCodexFullAccessTasks?.(sandbox.codexFullAccessTasks);
1955
+ router.setCodexSandbox?.(sandbox.codexSandbox);
2001
1956
  applyRouterGuards(router);
2002
1957
  router.skipMissingHarnessClis(coreOps.isCommandAvailable);
2003
1958
  router.setCostSink((entry) => logCost(paths.costs, { ...entry, issue: '-' }));
@@ -2548,7 +2503,6 @@ export function laneQueueDeps(queue, lane) {
2548
2503
  releaseIssue: (issue, outcome) => queue.release(issue, outcome),
2549
2504
  heartbeat: (issue) => queue.heartbeat(issue),
2550
2505
  countRemaining: async () => (await queue.list(lane)).length,
2551
- queueChildren: (parent, children) => queue.enqueueAfter(lane, parent, children),
2552
2506
  };
2553
2507
  }
2554
2508
  export { preflightQueuedIssue };
@@ -2592,16 +2546,6 @@ export class IssueSkippedError extends Error {
2592
2546
  this.reason = reason;
2593
2547
  }
2594
2548
  }
2595
- /** The target issue tripped the PLAN pre-flight size gate and was decomposed into real
2596
- * filed sub-issues; the queue was rewritten. Not a park — the lane continues with the
2597
- * children in place of the oversized issue. (#823) */
2598
- export class IssueDecomposedError extends Error {
2599
- childIssues;
2600
- constructor(message, childIssues) {
2601
- super(message);
2602
- this.childIssues = childIssues;
2603
- }
2604
- }
2605
2549
  export function issueFromFactoryBranch(branch, prefix) {
2606
2550
  return factoryBranchIssue(branch, prefix) ?? undefined;
2607
2551
  }