@straiffi/archon 1.8.12 → 1.8.13

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 (119) hide show
  1. package/dist/client/assets/{ActivityView-CEETnHri.js → ActivityView-DD1Fom-k.js} +1 -1
  2. package/dist/client/assets/{GitHubActionsDialog-CjBW65OR.js → GitHubActionsDialog-aDf_6y6m.js} +1 -1
  3. package/dist/client/assets/{RepositoryGraphDialog-F3C0n89W.js → RepositoryGraphDialog-B4Ij2xmA.js} +1 -1
  4. package/dist/client/assets/{VerificationDialog-DD1CLydA.js → VerificationDialog-BBCRKTdr.js} +1 -1
  5. package/dist/client/assets/{architectureDiagram-3BPJPVTR-COl_GdZ6.js → architectureDiagram-3BPJPVTR-DW3kiEe6.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-GPEHLZMM-qojIlH-q.js → blockDiagram-GPEHLZMM-BVWrspTj.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AAUBKEIU-DFtG4fMg.js → c4Diagram-AAUBKEIU-CDqXjYR1.js} +1 -1
  8. package/dist/client/assets/channel-C14KP1Bm.js +1 -0
  9. package/dist/client/assets/{chunk-2J33WTMH-TJkOJXbn.js → chunk-2J33WTMH-Db4bg8nj.js} +1 -1
  10. package/dist/client/assets/{chunk-3OPIFGDE-CELQ603z.js → chunk-3OPIFGDE-DqziKs5m.js} +1 -1
  11. package/dist/client/assets/{chunk-5ZQYHXKU-BgPEJ16b.js → chunk-5ZQYHXKU-wdN7gQNo.js} +1 -1
  12. package/dist/client/assets/{chunk-727SXJPM-Biph-aPf.js → chunk-727SXJPM-Dj3aKc06.js} +1 -1
  13. package/dist/client/assets/{chunk-AQP2D5EJ-CPVToZH6.js → chunk-AQP2D5EJ-CAlE_C_J.js} +1 -1
  14. package/dist/client/assets/{chunk-CSCIHK7Q-BHO9oB4A.js → chunk-CSCIHK7Q-KstW8JRv.js} +1 -1
  15. package/dist/client/assets/{chunk-KSCS5N6A-B8vatrko.js → chunk-KSCS5N6A-DrY-9bi9.js} +1 -1
  16. package/dist/client/assets/{chunk-L5ZTLDWV-DvzBHR4-.js → chunk-L5ZTLDWV-C6fw_Dab.js} +1 -1
  17. package/dist/client/assets/{chunk-LZXEDZCA-Bm8cj-JK.js → chunk-LZXEDZCA-DaZP5hZq.js} +2 -2
  18. package/dist/client/assets/{chunk-ND2GUHAM-BPQZvPl9.js → chunk-ND2GUHAM-ChYXM7G3.js} +1 -1
  19. package/dist/client/assets/{chunk-NZK2D7GU-DEQVA6Ya.js → chunk-NZK2D7GU-JajrDJgw.js} +1 -1
  20. package/dist/client/assets/{chunk-O5CBEL6O-hPGqWilt.js → chunk-O5CBEL6O-C4HoCf_q.js} +1 -1
  21. package/dist/client/assets/{chunk-WU5MYG2G-D0VvFXkQ.js → chunk-WU5MYG2G-BdjAiDOI.js} +1 -1
  22. package/dist/client/assets/classDiagram-4FO5ZUOK-CR20Gg9e.js +1 -0
  23. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B-N-i15d.js +1 -0
  24. package/dist/client/assets/{dagre-BM42HDAG-rmJlMuw_.js → dagre-BM42HDAG-CpXupRCy.js} +1 -1
  25. package/dist/client/assets/{diagram-2AECGRRQ-BqejYr09.js → diagram-2AECGRRQ-DyopuXBv.js} +1 -1
  26. package/dist/client/assets/{diagram-5GNKFQAL-DGSf1BNT.js → diagram-5GNKFQAL-C8lS8Vro.js} +1 -1
  27. package/dist/client/assets/{diagram-KO2AKTUF-e_TRdqvx.js → diagram-KO2AKTUF-CsyC_xgK.js} +1 -1
  28. package/dist/client/assets/{diagram-LMA3HP47-CTSnwgUq.js → diagram-LMA3HP47-DWsQdA71.js} +1 -1
  29. package/dist/client/assets/{diagram-OG6HWLK6-mUn9Y0aC.js → diagram-OG6HWLK6-YkNa_Tt6.js} +1 -1
  30. package/dist/client/assets/{erDiagram-TEJ5UH35-TmdWUwfA.js → erDiagram-TEJ5UH35-VmMz5G_L.js} +1 -1
  31. package/dist/client/assets/{flowDiagram-I6XJVG4X-CoE0KTIp.js → flowDiagram-I6XJVG4X-DZAu6IJl.js} +1 -1
  32. package/dist/client/assets/{ganttDiagram-6RSMTGT7-FkX1d1D7.js → ganttDiagram-6RSMTGT7-CHJRz_2M.js} +1 -1
  33. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CXze3DV2.js → gitGraphDiagram-PVQCEYII-BfA1qYTR.js} +1 -1
  34. package/dist/client/assets/index-B4x8ZZ8N.js +275 -0
  35. package/dist/client/assets/index-CCQwWUKF.css +2 -0
  36. package/dist/client/assets/{infoDiagram-5YYISTIA-CO0CivOy.js → infoDiagram-5YYISTIA-CyqqEYvx.js} +1 -1
  37. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-pEp8gScG.js → ishikawaDiagram-YF4QCWOH-DnXMvxPm.js} +1 -1
  38. package/dist/client/assets/{journeyDiagram-JHISSGLW-BAnBAX-u.js → journeyDiagram-JHISSGLW-DBumlehf.js} +1 -1
  39. package/dist/client/assets/{kanban-definition-UN3LZRKU-Cqe-m5fR.js → kanban-definition-UN3LZRKU-D-QvfQhh.js} +1 -1
  40. package/dist/client/assets/{line-CKXoUXdX.js → line-BgwSCyaP.js} +1 -1
  41. package/dist/client/assets/{mermaid-parser.core-7XZHbu9R.js → mermaid-parser.core-qDA1puIK.js} +1 -1
  42. package/dist/client/assets/{mermaid.core-CsF9gbdO.js → mermaid.core-CFM-fuJi.js} +3 -3
  43. package/dist/client/assets/{mindmap-definition-RKZ34NQL-88fK1Uq_.js → mindmap-definition-RKZ34NQL-B93RAITk.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-4H26LBE5-DHFlSAwL.js → pieDiagram-4H26LBE5-C9arDpCE.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D5WyQ5EU.js → quadrantDiagram-W4KKPZXB-Tma_RsUu.js} +1 -1
  46. package/dist/client/assets/{requirementDiagram-4Y6WPE33-DGkMfp_N.js → requirementDiagram-4Y6WPE33-C6GCxpqT.js} +1 -1
  47. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-loJAHDiT.js → sankeyDiagram-5OEKKPKP-CY8ukFyG.js} +1 -1
  48. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-xgcwtjyW.js → sequenceDiagram-3UESZ5HK-B6MbhJm7.js} +1 -1
  49. package/dist/client/assets/{stateDiagram-AJRCARHV-BB95DmQX.js → stateDiagram-AJRCARHV-Bjy1dBVk.js} +1 -1
  50. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-asf2fsPC.js +1 -0
  51. package/dist/client/assets/{timeline-definition-PNZ67QCA-OCHTEVfL.js → timeline-definition-PNZ67QCA-KrbaHcGf.js} +1 -1
  52. package/dist/client/assets/{vennDiagram-CIIHVFJN-Bo_7YNy2.js → vennDiagram-CIIHVFJN-DQ-5gbga.js} +1 -1
  53. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DquywRz0.js → wardleyDiagram-YWT4CUSO-Cwpu-hvf.js} +1 -1
  54. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BLNrbCwd.js → xychartDiagram-2RQKCTM6-DoP4HxQE.js} +1 -1
  55. package/dist/client/index.html +2 -2
  56. package/dist/server/db.js +77 -2
  57. package/dist/server/db.js.map +1 -1
  58. package/dist/server/index.js +64 -12
  59. package/dist/server/index.js.map +1 -1
  60. package/dist/server/lib/agent.js +53 -91
  61. package/dist/server/lib/agent.js.map +1 -1
  62. package/dist/server/lib/automationReconciliation.js +20 -0
  63. package/dist/server/lib/automationReconciliation.js.map +1 -1
  64. package/dist/server/lib/automationResumeDecision.js +2 -2
  65. package/dist/server/lib/automationResumeDecision.js.map +1 -1
  66. package/dist/server/lib/buildCompletionContinuation.js +1 -1
  67. package/dist/server/lib/buildCompletionContinuation.js.map +1 -1
  68. package/dist/server/lib/executionReconciliation.js +43 -4
  69. package/dist/server/lib/executionReconciliation.js.map +1 -1
  70. package/dist/server/lib/executionRetry.js +16 -9
  71. package/dist/server/lib/executionRetry.js.map +1 -1
  72. package/dist/server/lib/executionRetryPredicates.js +12 -3
  73. package/dist/server/lib/executionRetryPredicates.js.map +1 -1
  74. package/dist/server/lib/git.js +4 -4
  75. package/dist/server/lib/git.js.map +1 -1
  76. package/dist/server/lib/lightweightPrompt.js +12 -48
  77. package/dist/server/lib/lightweightPrompt.js.map +1 -1
  78. package/dist/server/lib/opencodeErrors.js +35 -0
  79. package/dist/server/lib/opencodeErrors.js.map +1 -0
  80. package/dist/server/lib/opencodePromptOutput.js +112 -0
  81. package/dist/server/lib/opencodePromptOutput.js.map +1 -0
  82. package/dist/server/lib/postBuildCheckRuns.js +16 -12
  83. package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
  84. package/dist/server/lib/postBuildChecks.js +45 -43
  85. package/dist/server/lib/postBuildChecks.js.map +1 -1
  86. package/dist/server/lib/previewProxy.js +36 -4
  87. package/dist/server/lib/previewProxy.js.map +1 -1
  88. package/dist/server/lib/projectAutoConfig.js +18 -91
  89. package/dist/server/lib/projectAutoConfig.js.map +1 -1
  90. package/dist/server/lib/projects.js +34 -6
  91. package/dist/server/lib/projects.js.map +1 -1
  92. package/dist/server/lib/reviewContext.js +10 -5
  93. package/dist/server/lib/reviewContext.js.map +1 -1
  94. package/dist/server/lib/reviewFindings.js +186 -27
  95. package/dist/server/lib/reviewFindings.js.map +1 -1
  96. package/dist/server/lib/reviewerConfig.js +23 -0
  97. package/dist/server/lib/reviewerConfig.js.map +1 -0
  98. package/dist/server/lib/specReviewOperations.js +64 -9
  99. package/dist/server/lib/specReviewOperations.js.map +1 -1
  100. package/dist/server/lib/ticketFollowUpOperations.js +28 -0
  101. package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
  102. package/dist/server/lib/tickets.js +15 -0
  103. package/dist/server/lib/tickets.js.map +1 -1
  104. package/dist/server/lib/types.js.map +1 -1
  105. package/dist/server/workers/build.js +8 -1
  106. package/dist/server/workers/build.js.map +1 -1
  107. package/dist/server/workers/followUp.js +5 -0
  108. package/dist/server/workers/followUp.js.map +1 -1
  109. package/dist/server/workers/review.js +147 -60
  110. package/dist/server/workers/review.js.map +1 -1
  111. package/dist/server/workers/specReview.js +26 -11
  112. package/dist/server/workers/specReview.js.map +1 -1
  113. package/package.json +1 -1
  114. package/dist/client/assets/channel-DJLjk5--.js +0 -1
  115. package/dist/client/assets/classDiagram-4FO5ZUOK-aHXCyXE_.js +0 -1
  116. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CRPsGis_.js +0 -1
  117. package/dist/client/assets/index-B9S66NLn.css +0 -2
  118. package/dist/client/assets/index-CHsj9z-M.js +0 -275
  119. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DKhxPOLT.js +0 -1
@@ -50,7 +50,7 @@ import { getProjectFileManifest, ProjectFileContentError, ProjectFileTargetUnava
50
50
  import { updateProjectTargetSelection } from './lib/projectTargets.js';
51
51
  import { hasActiveBundleSpecWork } from './lib/specWorkspaceActivity.js';
52
52
  import { exportProjectMemoryArchive, importProjectMemoryArchive } from './lib/projectMemoryTransfer.js';
53
- import { buildReviewFindingsResponse, computeDiffSignature, getLatestReviewRunForContext, listReviewFindings } from './lib/reviewFindings.js';
53
+ import { buildReviewFindingsResponse, computeDiffSignature, getLatestCompletedReviewRunForContext, listReviewFindings } from './lib/reviewFindings.js';
54
54
  import { formatBuildOpenQuestionAnswersPrompt, getLatestBuildOpenQuestionBatchStatus, hasActiveBuildOpenQuestionBatch, listBuildOpenQuestionsForBundle, loadBuildOpenQuestionsByBundleIds, } from './lib/buildOpenQuestions.js';
55
55
  import { acceptBuildOpenQuestionResolution } from './lib/buildOpenQuestionOperations.js';
56
56
  import { areBundleTicketsReadyForAutomaticReview } from './lib/bundleAutomationReadiness.js';
@@ -108,11 +108,12 @@ import { getBundleReviewRecovery, recoverBundleReview, rerunTicketReviewOperatio
108
108
  import { resolveReviewContinuation } from './workers/review.js';
109
109
  import { clearTicketStageSnapshots, getActiveBundleStageChangeHead, reconcileStageSnapshots, undoTicketStage } from './lib/ticketUndo.js';
110
110
  import { closeAllTerminalSessions, createProjectTerminalSession, createTerminalSessionForWorkspace, destroyTerminalSessionById, registerTerminalSocketHandlers, } from './lib/terminal.js';
111
- import { countBundleTickets, createTicketRecord, createBundle, deleteBundle, ensureProjectRootBundle, autoParkTicketIfStale, autoParkSettledBundleTicket, isBundleSettledForAutoPark, clearAutoParkDismissalIfNeeded, assignTicketDoneOrder, assignTicketLaneOrder, getBundle, getBundleByName, getBundleByBranch, getBundleRepresentativeTicketContext, isProjectRootBundle, getTicket, isBundledTicket, listTicketsInRunContext, listBundles, listBoardTicketEnrichment, listTickets, resolveTicketBranch, resolveTicketTool, updateBundleAutomationConfig, updateBundleIdentity, } from './lib/tickets.js';
111
+ import { countBundleTickets, createTicketRecord, createBundle, deleteBundle, ensureProjectRootBundle, autoParkTicketIfStale, autoParkSettledBundleTicket, isBundleSettledForAutoPark, clearAutoParkDismissalIfNeeded, assignTicketDoneOrder, assignTicketLaneOrder, getBundle, getBundleByName, getBundleByBranch, getBundleRepresentativeTicketContext, isProjectRootBundle, getTicket, isBundledTicket, listTicketsInRunContext, listBundles, listBoardTicketEnrichment, listTickets, resolveTicketBranch, resolveTicketTool, updateBundleAutomationConfig, updateBundleReviewerConfig, updateBundleIdentity, } from './lib/tickets.js';
112
112
  import { createTicketMessage, upsertTicketDescriptionMessage } from './lib/ticketMessages.js';
113
113
  import { listAgentRunsForExecutionRun, listAgentRunsForParent, terminalizeAgentRunsForExecutionRun } from './lib/agentRuns.js';
114
114
  import { HttpError } from './lib/httpError.js';
115
115
  import { parseIncomingExternalSource } from './lib/externalSource.js';
116
+ import { resolveReviewerConfig } from './lib/reviewerConfig.js';
116
117
  import { materializeTicketsWithDependencies } from './lib/ticketBatch.js';
117
118
  import { IMPLEMENTATION_READY_DESCRIPTION_SECTION_HEADINGS } from './lib/ticketDescriptionContract.js';
118
119
  import { buildImplementationResourcesAppendix, buildSpecImplementationDraft, buildVisualizationAppendix } from './lib/specDraft.js';
@@ -1541,6 +1542,9 @@ const serializeBundleRow = (projectId, bundle, openQuestions = bundle ? loadBuil
1541
1542
  const effectivePolicy = resolveEffectiveRequiredCheckPolicyMembership(project);
1542
1543
  return {
1543
1544
  ...bundle,
1545
+ reviewer_model: bundle.kind === 'project_root' ? null : bundle.reviewer_model ?? null,
1546
+ reviewer_variant: bundle.kind === 'project_root' || !bundle.reviewer_model ? null : bundle.reviewer_variant ?? null,
1547
+ reviewer_config: resolveReviewerConfig(bundle.kind === 'project_root' ? null : bundle, project),
1544
1548
  has_prepared_worktree: hasPreparedWorktree,
1545
1549
  pull_request: getGitHubConnectionConfig(projectId)
1546
1550
  ? serializeBundlePullRequest(getBundlePullRequestRecord(bundle.id, projectId))
@@ -2083,7 +2087,7 @@ const getBundleReviewFindings = async (projectId, bundleId) => {
2083
2087
  projectId,
2084
2088
  worktreeBundleId: representativeTicket.worktree_bundle_id,
2085
2089
  };
2086
- const latestReviewRun = getLatestReviewRunForContext(context);
2090
+ const latestReviewRun = getLatestCompletedReviewRunForContext(context);
2087
2091
  return buildReviewFindingsResponse({
2088
2092
  context,
2089
2093
  isContextRunning: tickets.some(ticket => ticket.agent_status === 'running'),
@@ -2103,7 +2107,7 @@ const getTicketReviewFindings = async (ticketId) => {
2103
2107
  projectId: ticket.project_id,
2104
2108
  worktreeBundleId: ticket.worktree_bundle_id,
2105
2109
  };
2106
- const latestReviewRun = getLatestReviewRunForContext(context);
2110
+ const latestReviewRun = getLatestCompletedReviewRunForContext(context);
2107
2111
  return buildReviewFindingsResponse({
2108
2112
  context,
2109
2113
  isContextRunning: ticket.agent_status === 'running',
@@ -3867,7 +3871,7 @@ app.post('/bundles', async (req, res) => {
3867
3871
  });
3868
3872
  }
3869
3873
  }
3870
- res.status(201).json(bundle);
3874
+ res.status(201).json(serializeBundleRow(result.project.id, bundle, [], result.project));
3871
3875
  });
3872
3876
  app.delete('/bundles/:id', (req, res) => {
3873
3877
  const result = getRequiredProject(req);
@@ -3935,6 +3939,7 @@ app.patch('/bundles/:id', (req, res) => {
3935
3939
  return res.status(404).json({ error: 'Bundle not found' });
3936
3940
  }
3937
3941
  const hasNameUpdate = hasOwn(req.body, 'name');
3942
+ const hasReviewerUpdate = hasOwn(req.body, 'reviewer_model') || hasOwn(req.body, 'reviewer_variant');
3938
3943
  if (hasOwn(req.body, 'required_check_policy_override')) {
3939
3944
  return res.status(400).json({ error: 'Bundle required-check policy overrides are no longer supported; configure required checks on the project' });
3940
3945
  }
@@ -3942,7 +3947,9 @@ app.patch('/bundles/:id', (req, res) => {
3942
3947
  return res.status(409).json({
3943
3948
  error: hasNameUpdate
3944
3949
  ? 'Project root bundles cannot be renamed'
3945
- : 'Project root bundle automation cannot be overridden',
3950
+ : hasReviewerUpdate
3951
+ ? 'Project root bundle reviewer configuration cannot be overridden'
3952
+ : 'Project root bundle automation cannot be overridden',
3946
3953
  });
3947
3954
  }
3948
3955
  let nextName = bundle.name;
@@ -4028,6 +4035,37 @@ app.patch('/bundles/:id', (req, res) => {
4028
4035
  return res.status(400).json({ error: 'automation_review_max_iterations must be an integer between 1 and 10' });
4029
4036
  }
4030
4037
  }
4038
+ let reviewerModel = bundle.reviewer_model ?? null;
4039
+ let reviewerVariant = reviewerModel ? bundle.reviewer_variant ?? null : null;
4040
+ if (hasOwn(req.body, 'reviewer_model')) {
4041
+ const value = req.body.reviewer_model;
4042
+ if (value == null) {
4043
+ reviewerModel = null;
4044
+ reviewerVariant = null;
4045
+ }
4046
+ else {
4047
+ const normalized = normalizeModelId(value);
4048
+ if (!normalized) {
4049
+ return res.status(400).json({ error: 'reviewer_model must be a valid model id' });
4050
+ }
4051
+ reviewerModel = normalized;
4052
+ if (!hasOwn(req.body, 'reviewer_variant')) {
4053
+ reviewerVariant = null;
4054
+ }
4055
+ }
4056
+ }
4057
+ if (hasOwn(req.body, 'reviewer_variant')) {
4058
+ const value = req.body.reviewer_variant;
4059
+ if (value == null) {
4060
+ reviewerVariant = null;
4061
+ }
4062
+ else if (typeof value === 'string' && value.trim()) {
4063
+ reviewerVariant = reviewerModel ? value.trim() : null;
4064
+ }
4065
+ else {
4066
+ return res.status(400).json({ error: 'reviewer_variant must be a non-empty string' });
4067
+ }
4068
+ }
4031
4069
  let updated = null;
4032
4070
  try {
4033
4071
  updated = db.transaction(() => {
@@ -4039,7 +4077,7 @@ app.patch('/bundles/:id', (req, res) => {
4039
4077
  branch: nextBranch,
4040
4078
  });
4041
4079
  }
4042
- return updateBundleAutomationConfig({
4080
+ updateBundleAutomationConfig({
4043
4081
  bundleId: bundle.id,
4044
4082
  projectId: result.project.id,
4045
4083
  automationDepth,
@@ -4047,6 +4085,12 @@ app.patch('/bundles/:id', (req, res) => {
4047
4085
  automationPauseOnOpenQuestions,
4048
4086
  automationReviewMaxIterations,
4049
4087
  });
4088
+ return updateBundleReviewerConfig({
4089
+ bundleId: bundle.id,
4090
+ projectId: result.project.id,
4091
+ reviewerModel,
4092
+ reviewerVariant,
4093
+ });
4050
4094
  })();
4051
4095
  }
4052
4096
  catch (error) {
@@ -5968,7 +6012,7 @@ app.post('/projects', (req, res) => {
5968
6012
  return res.status(400).json({ error: validation.error });
5969
6013
  }
5970
6014
  const projectCount = Number(db.prepare('SELECT COUNT(*) AS count FROM projects').get()?.count ?? 0);
5971
- const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
6015
+ const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
5972
6016
  if (!repo_path) {
5973
6017
  return res.status(400).json({ error: 'repo_path must be a non-empty string' });
5974
6018
  }
@@ -6000,6 +6044,8 @@ app.post('/projects', (req, res) => {
6000
6044
  preview_capability_mode,
6001
6045
  helper_model,
6002
6046
  helper_variant,
6047
+ reviewer_model,
6048
+ reviewer_variant,
6003
6049
  commit_message_rules,
6004
6050
  commit_after_each_ticket,
6005
6051
  auto_park_stale_tickets,
@@ -6014,8 +6060,8 @@ app.post('/projects', (req, res) => {
6014
6060
  automation_review_severity,
6015
6061
  automation_review_max_iterations
6016
6062
  )
6017
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6018
- `).run(id, name, normalizedRepoPath, run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', pre_review_check_definition_ids ?? '[]', post_build_check_definition_ids ?? '[]', auto_fix_check_definition_ids ?? '[]', test_commands, run_ide ?? null, preview_service_name ?? null, preview_path ?? null, preview_capability_mode ?? null, helper_model ?? null, helper_variant ?? null, commit_message_rules ?? null, commit_after_each_ticket ?? 0, auto_park_stale_tickets ?? 0, memory_enabled ?? 0, scan_include_globs_json ?? null, scan_exclude_globs_json ?? null, worktree_sync ?? null, spec_aware_code_review_enabled ?? 0, automation_depth ?? 'manual', automation_review_fix_enabled ?? 0, automation_pause_on_open_questions ?? 0, automation_review_severity ?? 'medium', automation_review_max_iterations ?? 3);
6063
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6064
+ `).run(id, name, normalizedRepoPath, run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', pre_review_check_definition_ids ?? '[]', post_build_check_definition_ids ?? '[]', auto_fix_check_definition_ids ?? '[]', test_commands, run_ide ?? null, preview_service_name ?? null, preview_path ?? null, preview_capability_mode ?? null, helper_model ?? null, helper_variant ?? null, reviewer_model ?? null, reviewer_model ? reviewer_variant ?? null : null, commit_message_rules ?? null, commit_after_each_ticket ?? 0, auto_park_stale_tickets ?? 0, memory_enabled ?? 0, scan_include_globs_json ?? null, scan_exclude_globs_json ?? null, worktree_sync ?? null, spec_aware_code_review_enabled ?? 0, automation_depth ?? 'manual', automation_review_fix_enabled ?? 0, automation_pause_on_open_questions ?? 0, automation_review_severity ?? 'medium', automation_review_max_iterations ?? 3);
6019
6065
  replaceProjectLinks(id, linked_project_ids ?? []);
6020
6066
  ensureProjectRootBundle(id);
6021
6067
  if (projectCount === 0) {
@@ -7222,7 +7268,7 @@ app.patch('/projects/:id', (req, res) => {
7222
7268
  });
7223
7269
  }
7224
7270
  }
7225
- const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
7271
+ const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
7226
7272
  const updateProject = db.prepare(`
7227
7273
  UPDATE projects SET
7228
7274
  name = ?,
@@ -7241,6 +7287,8 @@ app.patch('/projects/:id', (req, res) => {
7241
7287
  preview_capability_mode = ?,
7242
7288
  helper_model = ?,
7243
7289
  helper_variant = ?,
7290
+ reviewer_model = ?,
7291
+ reviewer_variant = ?,
7244
7292
  commit_message_rules = ?,
7245
7293
  commit_after_each_ticket = ?,
7246
7294
  auto_park_stale_tickets = ?,
@@ -7270,6 +7318,10 @@ app.patch('/projects/:id', (req, res) => {
7270
7318
  const nextAutoFixCheckDefinitionIds = hasOwn(validation.values, 'auto_fix_check_definition_ids')
7271
7319
  ? auto_fix_check_definition_ids ?? '[]'
7272
7320
  : project.auto_fix_check_definition_ids;
7321
+ const nextReviewerModel = hasOwn(validation.values, 'reviewer_model') ? reviewer_model ?? null : project.reviewer_model;
7322
+ const nextReviewerVariant = nextReviewerModel
7323
+ ? (hasOwn(validation.values, 'reviewer_variant') ? reviewer_variant ?? null : project.reviewer_variant)
7324
+ : null;
7273
7325
  const updateResult = db.transaction(() => {
7274
7326
  const policyReferences = validateProjectRequiredCheckPolicyReferences({
7275
7327
  projectId: project.id,
@@ -7282,7 +7334,7 @@ app.patch('/projects/:id', (req, res) => {
7282
7334
  if ('error' in policyReferences) {
7283
7335
  return policyReferences;
7284
7336
  }
7285
- updateProject.run(name ?? project.name, repo_path ?? project.repo_path, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, nextPostBuildCheckDefinitionIds, nextAutoFixCheckDefinitionIds, hasOwn(validation.values, 'test_commands') ? test_commands : project.test_commands, hasOwn(validation.values, 'run_ide') ? run_ide : project.run_ide, hasOwn(validation.values, 'preview_service_name') ? preview_service_name : project.preview_service_name, hasOwn(validation.values, 'preview_path') ? preview_path : project.preview_path, hasOwn(validation.values, 'preview_capability_mode') ? preview_capability_mode : project.preview_capability_mode, hasOwn(validation.values, 'helper_model') ? helper_model : project.helper_model, hasOwn(validation.values, 'helper_variant') ? helper_variant : project.helper_variant, hasOwn(validation.values, 'commit_message_rules') ? commit_message_rules : project.commit_message_rules, hasOwn(validation.values, 'commit_after_each_ticket') ? commit_after_each_ticket : project.commit_after_each_ticket, hasOwn(validation.values, 'auto_park_stale_tickets') ? auto_park_stale_tickets : project.auto_park_stale_tickets, hasOwn(validation.values, 'memory_enabled') ? memory_enabled : project.memory_enabled, hasOwn(validation.values, 'scan_include_globs_json') ? scan_include_globs_json : project.scan_include_globs_json, hasOwn(validation.values, 'scan_exclude_globs_json') ? scan_exclude_globs_json : project.scan_exclude_globs_json, hasOwn(validation.values, 'worktree_sync') ? worktree_sync : project.worktree_sync, hasOwn(validation.values, 'spec_aware_code_review_enabled') ? spec_aware_code_review_enabled : project.spec_aware_code_review_enabled, hasOwn(validation.values, 'automation_depth') ? automation_depth : project.automation_depth, hasOwn(validation.values, 'automation_review_fix_enabled') ? automation_review_fix_enabled : project.automation_review_fix_enabled, hasOwn(validation.values, 'automation_pause_on_open_questions') ? automation_pause_on_open_questions : project.automation_pause_on_open_questions, hasOwn(validation.values, 'automation_review_severity') ? automation_review_severity : project.automation_review_severity, hasOwn(validation.values, 'automation_review_max_iterations') ? automation_review_max_iterations : project.automation_review_max_iterations, req.params.id);
7337
+ updateProject.run(name ?? project.name, repo_path ?? project.repo_path, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, nextPostBuildCheckDefinitionIds, nextAutoFixCheckDefinitionIds, hasOwn(validation.values, 'test_commands') ? test_commands : project.test_commands, hasOwn(validation.values, 'run_ide') ? run_ide : project.run_ide, hasOwn(validation.values, 'preview_service_name') ? preview_service_name : project.preview_service_name, hasOwn(validation.values, 'preview_path') ? preview_path : project.preview_path, hasOwn(validation.values, 'preview_capability_mode') ? preview_capability_mode : project.preview_capability_mode, hasOwn(validation.values, 'helper_model') ? helper_model : project.helper_model, hasOwn(validation.values, 'helper_variant') ? helper_variant : project.helper_variant, nextReviewerModel, nextReviewerVariant, hasOwn(validation.values, 'commit_message_rules') ? commit_message_rules : project.commit_message_rules, hasOwn(validation.values, 'commit_after_each_ticket') ? commit_after_each_ticket : project.commit_after_each_ticket, hasOwn(validation.values, 'auto_park_stale_tickets') ? auto_park_stale_tickets : project.auto_park_stale_tickets, hasOwn(validation.values, 'memory_enabled') ? memory_enabled : project.memory_enabled, hasOwn(validation.values, 'scan_include_globs_json') ? scan_include_globs_json : project.scan_include_globs_json, hasOwn(validation.values, 'scan_exclude_globs_json') ? scan_exclude_globs_json : project.scan_exclude_globs_json, hasOwn(validation.values, 'worktree_sync') ? worktree_sync : project.worktree_sync, hasOwn(validation.values, 'spec_aware_code_review_enabled') ? spec_aware_code_review_enabled : project.spec_aware_code_review_enabled, hasOwn(validation.values, 'automation_depth') ? automation_depth : project.automation_depth, hasOwn(validation.values, 'automation_review_fix_enabled') ? automation_review_fix_enabled : project.automation_review_fix_enabled, hasOwn(validation.values, 'automation_pause_on_open_questions') ? automation_pause_on_open_questions : project.automation_pause_on_open_questions, hasOwn(validation.values, 'automation_review_severity') ? automation_review_severity : project.automation_review_severity, hasOwn(validation.values, 'automation_review_max_iterations') ? automation_review_max_iterations : project.automation_review_max_iterations, req.params.id);
7286
7338
  if (hasOwn(validation.values, 'linked_project_ids')) {
7287
7339
  replaceProjectLinks(project.id, linked_project_ids ?? []);
7288
7340
  }