@straiffi/archon 1.6.1 → 1.7.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.
Files changed (163) hide show
  1. package/dist/client/assets/GitHubActionsDialog-B9_WJBOp.js +1 -0
  2. package/dist/client/assets/TestsDialog-DKvbjH_M.js +4 -0
  3. package/dist/client/assets/TicketChangesModal-C8rFoKjY.js +1 -0
  4. package/dist/client/assets/{arc-CnuHRbeq.js → arc-D2Nn9xIj.js} +1 -1
  5. package/dist/client/assets/architecture-7EHR7CIX-C-4Cp4ml.js +1 -0
  6. package/dist/client/assets/{architectureDiagram-3BPJPVTR-cWqD9YRv.js → architectureDiagram-3BPJPVTR-DXRSRLL9.js} +1 -1
  7. package/dist/client/assets/{blockDiagram-GPEHLZMM-B8yyMr1c.js → blockDiagram-GPEHLZMM-D7EE6Dnv.js} +1 -1
  8. package/dist/client/assets/{c4Diagram-AAUBKEIU-B_yL8Tbe.js → c4Diagram-AAUBKEIU-UhVzFafr.js} +1 -1
  9. package/dist/client/assets/channel-CNoEXkwa.js +1 -0
  10. package/dist/client/assets/{chunk-2J33WTMH-BF8hfYEU.js → chunk-2J33WTMH-obbfylVr.js} +1 -1
  11. package/dist/client/assets/{chunk-3OPIFGDE-BPDdyRDK.js → chunk-3OPIFGDE-DPVuS-uo.js} +1 -1
  12. package/dist/client/assets/{chunk-4BX2VUAB-_WBpCe0m.js → chunk-4BX2VUAB-CtLS8D71.js} +1 -1
  13. package/dist/client/assets/{chunk-4EGX6M5U-BBQHxMeA.js → chunk-4EGX6M5U-Btnm0QNe.js} +1 -1
  14. package/dist/client/assets/{chunk-55IACEB6-B-d-YzxI.js → chunk-55IACEB6-74CcJaub.js} +1 -1
  15. package/dist/client/assets/{chunk-5DO6E6H7-BA-oSVa-.js → chunk-5DO6E6H7-WLZ8L4ko.js} +1 -1
  16. package/dist/client/assets/{chunk-5ZQYHXKU-DEi4bnIa.js → chunk-5ZQYHXKU-Dsc03vy9.js} +1 -1
  17. package/dist/client/assets/{chunk-727SXJPM-BTXHOTJi.js → chunk-727SXJPM-COE-iq_Z.js} +1 -1
  18. package/dist/client/assets/{chunk-AQP2D5EJ-D2TAJwxM.js → chunk-AQP2D5EJ-DnbAdr8m.js} +1 -1
  19. package/dist/client/assets/{chunk-BR22UD5L-prWX503j.js → chunk-BR22UD5L-Cou5beGe.js} +1 -1
  20. package/dist/client/assets/{chunk-BSJP7CBP-CNtf2uaW.js → chunk-BSJP7CBP-DJ57XcV5.js} +1 -1
  21. package/dist/client/assets/{chunk-CSCIHK7Q-Bdgg7p9T.js → chunk-CSCIHK7Q-DbTzC_WS.js} +2 -2
  22. package/dist/client/assets/{chunk-FHYWG6QK-BQ8n0J0S.js → chunk-FHYWG6QK-Ba10e2kj.js} +1 -1
  23. package/dist/client/assets/{chunk-FMBD7UC4-CWQN4V4s.js → chunk-FMBD7UC4-CEo2wZMx.js} +1 -1
  24. package/dist/client/assets/{chunk-KSCS5N6A-Cey3fOI1.js → chunk-KSCS5N6A-xvviIayr.js} +1 -1
  25. package/dist/client/assets/{chunk-L5ZTLDWV-BSNGBgBH.js → chunk-L5ZTLDWV-DY4Q9Til.js} +1 -1
  26. package/dist/client/assets/{chunk-LZXEDZCA-B8qP34jM.js → chunk-LZXEDZCA-Bbeq2DZs.js} +2 -2
  27. package/dist/client/assets/{chunk-MPE355IW-gHN8AuU_.js → chunk-MPE355IW-MqEt-J8G.js} +1 -1
  28. package/dist/client/assets/{chunk-MZUSXYTE-Clzaz1kK.js → chunk-MZUSXYTE-DdNi9lhx.js} +1 -1
  29. package/dist/client/assets/{chunk-N66VUXT2-CkkAOkdt.js → chunk-N66VUXT2-CjemTW4E.js} +1 -1
  30. package/dist/client/assets/{chunk-ND2GUHAM-COde7fTi.js → chunk-ND2GUHAM-CylX1p3K.js} +1 -1
  31. package/dist/client/assets/{chunk-NZK2D7GU-C62VVWrt.js → chunk-NZK2D7GU-BTcALpQq.js} +1 -1
  32. package/dist/client/assets/{chunk-O5CBEL6O-_20MzuKm.js → chunk-O5CBEL6O-Be_5dk2_.js} +1 -1
  33. package/dist/client/assets/{chunk-PUPMXCY4-DAdQFv8j.js → chunk-PUPMXCY4-ZvwTw0To.js} +1 -1
  34. package/dist/client/assets/chunk-QZHKN3VN-LI_RZca2.js +1 -0
  35. package/dist/client/assets/{chunk-UIBZB4QT-BRR84OYN.js → chunk-UIBZB4QT-BTY9be9s.js} +1 -1
  36. package/dist/client/assets/{chunk-WCWK7LTN-CQU7Fs_W.js → chunk-WCWK7LTN-Db1n3n3-.js} +1 -1
  37. package/dist/client/assets/chunk-WU5MYG2G-DXPsSM4Q.js +1 -0
  38. package/dist/client/assets/{chunk-XPW4576I-DafcxlUi.js → chunk-XPW4576I-DObFPxjB.js} +1 -1
  39. package/dist/client/assets/classDiagram-4FO5ZUOK-BgmK8-LI.js +1 -0
  40. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Dj5LqBjo.js +1 -0
  41. package/dist/client/assets/{cose-bilkent-S5V4N54A-DhJHP9hr.js → cose-bilkent-S5V4N54A-MlOPiG6P.js} +1 -1
  42. package/dist/client/assets/{dagre-BM42HDAG-jLUWHvr3.js → dagre-BM42HDAG-CABUW7xK.js} +1 -1
  43. package/dist/client/assets/{dagre-CdwzCXQr.js → dagre-BWNHuDdf.js} +1 -1
  44. package/dist/client/assets/{diagram-2AECGRRQ-B6D2TKLb.js → diagram-2AECGRRQ-KvcNrpvf.js} +1 -1
  45. package/dist/client/assets/{diagram-5GNKFQAL-bFJLLDWx.js → diagram-5GNKFQAL-DQV6-I4e.js} +1 -1
  46. package/dist/client/assets/{diagram-KO2AKTUF-Bp01SL5f.js → diagram-KO2AKTUF-DYDk9roD.js} +1 -1
  47. package/dist/client/assets/{diagram-LMA3HP47-DwoeZFg9.js → diagram-LMA3HP47-Da-0u-HG.js} +1 -1
  48. package/dist/client/assets/{diagram-OG6HWLK6-CjRd_tge.js → diagram-OG6HWLK6-CuD5eRBv.js} +1 -1
  49. package/dist/client/assets/{erDiagram-TEJ5UH35-DzfIVd9j.js → erDiagram-TEJ5UH35-BL5dBE-b.js} +1 -1
  50. package/dist/client/assets/eventmodeling-FCH6USID-Dqb6QKoI.js +1 -0
  51. package/dist/client/assets/{flowDiagram-I6XJVG4X-Dq04zf9A.js → flowDiagram-I6XJVG4X-Bke5cWs7.js} +1 -1
  52. package/dist/client/assets/{ganttDiagram-6RSMTGT7-D5f16YYP.js → ganttDiagram-6RSMTGT7-5OD-ayGn.js} +1 -1
  53. package/dist/client/assets/gitGraph-WXDBUCRP-DYEsqh93.js +1 -0
  54. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CCD1CXBG.js → gitGraphDiagram-PVQCEYII-7Cf6FVfO.js} +1 -1
  55. package/dist/client/assets/index-D8EniXuq.css +2 -0
  56. package/dist/client/assets/index-DXuxAAzf.js +270 -0
  57. package/dist/client/assets/info-J43DQDTF-CfjXFZai.js +1 -0
  58. package/dist/client/assets/{infoDiagram-5YYISTIA-Bde4Z0o8.js → infoDiagram-5YYISTIA-BchMN9V-.js} +1 -1
  59. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CJ89ymGL.js → ishikawaDiagram-YF4QCWOH-D6TchjQy.js} +1 -1
  60. package/dist/client/assets/{journeyDiagram-JHISSGLW-Dw_sScmo.js → journeyDiagram-JHISSGLW-CwEcoeX-.js} +1 -1
  61. package/dist/client/assets/{kanban-definition-UN3LZRKU-DfWOcnxV.js → kanban-definition-UN3LZRKU-S2V9CLGR.js} +1 -1
  62. package/dist/client/assets/{line-CUQIbS7r.js → line-DRheChzQ.js} +1 -1
  63. package/dist/client/assets/{linear-DFIW-KnM.js → linear-DT4rSZvy.js} +1 -1
  64. package/dist/client/assets/{mermaid-parser.core-d287AjoM.js → mermaid-parser.core-CN13XjLe.js} +2 -2
  65. package/dist/client/assets/{mermaid.core-QqY2ZNMl.js → mermaid.core-JhdSpoF5.js} +3 -3
  66. package/dist/client/assets/{mindmap-definition-RKZ34NQL-Bz3Yc70v.js → mindmap-definition-RKZ34NQL-657TKwRB.js} +1 -1
  67. package/dist/client/assets/{ordinal-C1FS1Sfe.js → ordinal-k--hYEme.js} +1 -1
  68. package/dist/client/assets/packet-YPE3B663-Dv0HkRHU.js +1 -0
  69. package/dist/client/assets/pie-LRSECV5Y-S5zPzZFN.js +1 -0
  70. package/dist/client/assets/{pieDiagram-4H26LBE5-BjMDHR6y.js → pieDiagram-4H26LBE5-DJ8eQ94X.js} +1 -1
  71. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BWDqf0X1.js → quadrantDiagram-W4KKPZXB-GpYFqyb1.js} +1 -1
  72. package/dist/client/assets/radar-GUYGQ44K-B7psLv22.js +1 -0
  73. package/dist/client/assets/{requirementDiagram-4Y6WPE33-kspE4S60.js → requirementDiagram-4Y6WPE33-COZFWgq1.js} +1 -1
  74. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-EuLhHbDR.js → sankeyDiagram-5OEKKPKP-BdCHyfcQ.js} +1 -1
  75. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BvXG3DJh.js → sequenceDiagram-3UESZ5HK-DAh3Ogx0.js} +1 -1
  76. package/dist/client/assets/{stateDiagram-AJRCARHV-B-D0PYkH.js → stateDiagram-AJRCARHV-Ck8Yie8_.js} +1 -1
  77. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B6zibRqD.js +1 -0
  78. package/dist/client/assets/{timeline-definition-PNZ67QCA-CJnod6Jh.js → timeline-definition-PNZ67QCA-kYr9DNtP.js} +1 -1
  79. package/dist/client/assets/treeView-BLDUP644-B8H0kT67.js +1 -0
  80. package/dist/client/assets/treemap-LRROVOQU-DPLhFHnh.js +1 -0
  81. package/dist/client/assets/{vennDiagram-CIIHVFJN-CBh3tqZu.js → vennDiagram-CIIHVFJN-CC_SlRiC.js} +1 -1
  82. package/dist/client/assets/wardley-L42UT6IY-B5-Vb08V.js +1 -0
  83. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BBQOjYBd.js → wardleyDiagram-YWT4CUSO-CZ17ccSN.js} +1 -1
  84. package/dist/client/assets/{xychartDiagram-2RQKCTM6-C8gU1LNj.js → xychartDiagram-2RQKCTM6-Blqaj-ci.js} +1 -1
  85. package/dist/client/index.html +2 -2
  86. package/dist/server/db.js +133 -0
  87. package/dist/server/db.js.map +1 -1
  88. package/dist/server/index.js +299 -17
  89. package/dist/server/index.js.map +1 -1
  90. package/dist/server/lib/agent.js +12 -11
  91. package/dist/server/lib/agent.js.map +1 -1
  92. package/dist/server/lib/buildOpenQuestions.js +263 -0
  93. package/dist/server/lib/buildOpenQuestions.js.map +1 -0
  94. package/dist/server/lib/bundleReviewOperations.js +17 -3
  95. package/dist/server/lib/bundleReviewOperations.js.map +1 -1
  96. package/dist/server/lib/git.js +19 -3
  97. package/dist/server/lib/git.js.map +1 -1
  98. package/dist/server/lib/lightweightPrompt.js +2 -1
  99. package/dist/server/lib/lightweightPrompt.js.map +1 -1
  100. package/dist/server/lib/planModeQuestions.js +23 -1
  101. package/dist/server/lib/planModeQuestions.js.map +1 -1
  102. package/dist/server/lib/previewProxy.js +5 -0
  103. package/dist/server/lib/previewProxy.js.map +1 -1
  104. package/dist/server/lib/projectAutoConfig.js +2 -1
  105. package/dist/server/lib/projectAutoConfig.js.map +1 -1
  106. package/dist/server/lib/projectFiles.js +313 -0
  107. package/dist/server/lib/projectFiles.js.map +1 -0
  108. package/dist/server/lib/projects.js +10 -0
  109. package/dist/server/lib/projects.js.map +1 -1
  110. package/dist/server/lib/ticketAutomation.js +16 -4
  111. package/dist/server/lib/ticketAutomation.js.map +1 -1
  112. package/dist/server/lib/ticketAutomationCommit.js +10 -10
  113. package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
  114. package/dist/server/lib/ticketOpenQuestions.js +17 -0
  115. package/dist/server/lib/ticketOpenQuestions.js.map +1 -1
  116. package/dist/server/lib/ticketWorkflowOperations.js +1 -1
  117. package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
  118. package/dist/server/lib/tickets.js +48 -6
  119. package/dist/server/lib/tickets.js.map +1 -1
  120. package/dist/server/workers/build.js +55 -12
  121. package/dist/server/workers/build.js.map +1 -1
  122. package/dist/server/workers/chat.js +2 -5
  123. package/dist/server/workers/chat.js.map +1 -1
  124. package/dist/server/workers/followUp.js +120 -18
  125. package/dist/server/workers/followUp.js.map +1 -1
  126. package/dist/server/workers/plan.js +4 -7
  127. package/dist/server/workers/plan.js.map +1 -1
  128. package/dist/server/workers/review.js +25 -8
  129. package/dist/server/workers/review.js.map +1 -1
  130. package/dist/server/workers/specSession.js +2 -5
  131. package/dist/server/workers/specSession.js.map +1 -1
  132. package/package.json +1 -1
  133. package/dist/client/assets/GitHubActionsDialog-BLJ3yCeK.js +0 -1
  134. package/dist/client/assets/TestsDialog-ar_RUzA3.js +0 -4
  135. package/dist/client/assets/architecture-7EHR7CIX-tSrokdFP.js +0 -1
  136. package/dist/client/assets/channel-1Ezn2R-x.js +0 -1
  137. package/dist/client/assets/chunk-QZHKN3VN-biOr9EeQ.js +0 -1
  138. package/dist/client/assets/chunk-WU5MYG2G-C4G-J1jx.js +0 -1
  139. package/dist/client/assets/classDiagram-4FO5ZUOK-DrjiwEWN.js +0 -1
  140. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DWHyuysv.js +0 -1
  141. package/dist/client/assets/eventmodeling-FCH6USID-DapHLQIh.js +0 -1
  142. package/dist/client/assets/gitGraph-WXDBUCRP-BTBN_hfb.js +0 -1
  143. package/dist/client/assets/index-DI9Vi2-3.js +0 -265
  144. package/dist/client/assets/index-DSap5tSX.css +0 -2
  145. package/dist/client/assets/info-J43DQDTF-CgiMJYKF.js +0 -1
  146. package/dist/client/assets/packet-YPE3B663-Bnwqjena.js +0 -1
  147. package/dist/client/assets/pie-LRSECV5Y-Ctj0ef-4.js +0 -1
  148. package/dist/client/assets/radar-GUYGQ44K-DE0H_saz.js +0 -1
  149. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-f36jgr8A.js +0 -1
  150. package/dist/client/assets/treeView-BLDUP644-CSAZL2OH.js +0 -1
  151. package/dist/client/assets/treemap-LRROVOQU-tYm4XKfP.js +0 -1
  152. package/dist/client/assets/wardley-L42UT6IY-DdiEFppm.js +0 -1
  153. /package/dist/client/assets/{array-B57E4cSs.js → array-BNor45A1.js} +0 -0
  154. /package/dist/client/assets/{chunk-NNHCCRGN-DRSAMe5H.js → chunk-NNHCCRGN-CZB-V-Gv.js} +0 -0
  155. /package/dist/client/assets/{cytoscape.esm-CVYSm6AJ.js → cytoscape.esm-B2lJcMSI.js} +0 -0
  156. /package/dist/client/assets/{defaultLocale-6WHJ3B09.js → defaultLocale-DPzUsThw.js} +0 -0
  157. /package/dist/client/assets/{dist-By2zKKTF.js → dist-CERhmQhR.js} +0 -0
  158. /package/dist/client/assets/{graphlib-B0DVs0bw.js → graphlib-BHOW-eWz.js} +0 -0
  159. /package/dist/client/assets/{init-DiYCGS1R.js → init-C0L3woqb.js} +0 -0
  160. /package/dist/client/assets/{katex-bgJu_0Fy.js → katex-CpjQsUQe.js} +0 -0
  161. /package/dist/client/assets/{path-DL_QDy2X.js → path-sMK4d_s9.js} +0 -0
  162. /package/dist/client/assets/{rough.esm-Bbn_-PMU.js → rough.esm-BoTisKeL.js} +0 -0
  163. /package/dist/client/assets/{src-Bi_byJUe.js → src-BRjoYtUW.js} +0 -0
@@ -0,0 +1,263 @@
1
+ import { createHash, randomUUID } from 'crypto';
2
+ import db from '../db.js';
3
+ export const BUILD_OPEN_QUESTIONS_CHANGED_CODE = 'build_open_questions_changed';
4
+ class BuildOpenQuestionsChangedError extends Error {
5
+ }
6
+ const normalizeQuestions = (questions) => {
7
+ return questions
8
+ .map(question => question.trim())
9
+ .filter(Boolean)
10
+ .filter((question, index, values) => values.indexOf(question) === index);
11
+ };
12
+ export const listBuildOpenQuestionsForTicket = (ticketId) => {
13
+ return db.prepare(`
14
+ SELECT * FROM build_open_questions
15
+ WHERE ticket_id = ? AND status = 'open'
16
+ ORDER BY created_at ASC, rowid ASC
17
+ `).all(ticketId);
18
+ };
19
+ export const listBuildOpenQuestionsForBundle = (projectId, bundleId) => {
20
+ return db.prepare(`
21
+ SELECT * FROM build_open_questions
22
+ WHERE project_id = ? AND worktree_bundle_id = ? AND status = 'open'
23
+ ORDER BY created_at ASC, rowid ASC
24
+ `).all(projectId, bundleId);
25
+ };
26
+ export const listBuildOpenQuestionAudit = (projectId, bundleId) => {
27
+ return db.prepare(`
28
+ SELECT * FROM build_open_questions
29
+ WHERE project_id = ? AND worktree_bundle_id = ?
30
+ ORDER BY created_at ASC, rowid ASC
31
+ `).all(projectId, bundleId);
32
+ };
33
+ export const listAnsweredBuildOpenQuestionsForBundle = (projectId, bundleId) => {
34
+ return db.prepare(`
35
+ SELECT build_open_questions.*, tickets.title AS ticket_title
36
+ FROM build_open_questions
37
+ JOIN tickets ON tickets.id = build_open_questions.ticket_id
38
+ WHERE build_open_questions.project_id = ?
39
+ AND build_open_questions.worktree_bundle_id = ?
40
+ AND build_open_questions.status = 'answered'
41
+ ORDER BY build_open_questions.answered_at ASC, build_open_questions.id ASC
42
+ `).all(projectId, bundleId);
43
+ };
44
+ export const listAnsweredBuildOpenQuestionsForBatch = (batchId) => {
45
+ return db.prepare(`
46
+ SELECT build_open_questions.*, tickets.title AS ticket_title
47
+ FROM build_open_questions
48
+ JOIN tickets ON tickets.id = build_open_questions.ticket_id
49
+ WHERE build_open_questions.resolution_batch_id = ?
50
+ AND build_open_questions.status = 'answered'
51
+ ORDER BY build_open_questions.answered_at ASC, build_open_questions.id ASC
52
+ `).all(batchId);
53
+ };
54
+ export const loadBuildOpenQuestionsByTicketIds = (ticketIds) => {
55
+ const result = new Map(ticketIds.map(ticketId => [ticketId, []]));
56
+ if (ticketIds.length === 0) {
57
+ return result;
58
+ }
59
+ const placeholders = ticketIds.map(() => '?').join(', ');
60
+ const rows = db.prepare(`
61
+ SELECT * FROM build_open_questions
62
+ WHERE status = 'open' AND ticket_id IN (${placeholders})
63
+ ORDER BY created_at ASC, id ASC
64
+ `).all(...ticketIds);
65
+ for (const row of rows) {
66
+ result.get(row.ticket_id)?.push(row);
67
+ }
68
+ return result;
69
+ };
70
+ export const loadBuildOpenQuestionsByBundleIds = (projectId, bundleIds) => {
71
+ const result = new Map(bundleIds.map(bundleId => [bundleId, []]));
72
+ if (bundleIds.length === 0) {
73
+ return result;
74
+ }
75
+ const placeholders = bundleIds.map(() => '?').join(', ');
76
+ const rows = db.prepare(`
77
+ SELECT * FROM build_open_questions
78
+ WHERE project_id = ? AND status = 'open' AND worktree_bundle_id IN (${placeholders})
79
+ ORDER BY created_at ASC, id ASC
80
+ `).all(projectId, ...bundleIds);
81
+ for (const row of rows) {
82
+ result.get(row.worktree_bundle_id)?.push(row);
83
+ }
84
+ return result;
85
+ };
86
+ export const reconcileBuildOpenQuestions = ({ projectId, bundleId, ticketId, questions, sourceKey, }) => {
87
+ const nextQuestions = normalizeQuestions(questions);
88
+ const reconcile = db.transaction(() => {
89
+ const current = listBuildOpenQuestionsForTicket(ticketId);
90
+ const retainedIds = new Set();
91
+ for (const question of nextQuestions) {
92
+ const existing = current.find(row => row.question_text === question && !retainedIds.has(row.id));
93
+ if (existing) {
94
+ retainedIds.add(existing.id);
95
+ continue;
96
+ }
97
+ const id = randomUUID();
98
+ const digest = createHash('sha256').update(question).digest('hex');
99
+ db.prepare(`
100
+ INSERT OR IGNORE INTO build_open_questions (
101
+ id, project_id, worktree_bundle_id, ticket_id, source_key, question_text
102
+ ) VALUES (?, ?, ?, ?, ?, ?)
103
+ `).run(id, projectId, bundleId, ticketId, `${sourceKey}:${digest}`, question);
104
+ }
105
+ for (const question of current) {
106
+ if (!retainedIds.has(question.id)) {
107
+ db.prepare(`
108
+ UPDATE build_open_questions
109
+ SET status = 'superseded', superseded_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP
110
+ WHERE id = ? AND status = 'open'
111
+ `).run(question.id);
112
+ }
113
+ }
114
+ return listBuildOpenQuestionsForTicket(ticketId);
115
+ });
116
+ return reconcile();
117
+ };
118
+ export const validateExactBuildOpenQuestionSet = (projectId, bundleId, questionIds) => {
119
+ const questions = listBuildOpenQuestionsForBundle(projectId, bundleId);
120
+ const expected = questions.map(question => question.id).sort();
121
+ const received = [...new Set(questionIds)].sort();
122
+ if (received.length !== questionIds.length || expected.length !== received.length) {
123
+ return {
124
+ ok: false,
125
+ error: 'question_ids must exactly match the bundle open question set',
126
+ code: BUILD_OPEN_QUESTIONS_CHANGED_CODE,
127
+ };
128
+ }
129
+ if (expected.some((id, index) => id !== received[index])) {
130
+ return {
131
+ ok: false,
132
+ error: 'question_ids must exactly match the bundle open question set',
133
+ code: BUILD_OPEN_QUESTIONS_CHANGED_CODE,
134
+ };
135
+ }
136
+ return { ok: true, questions };
137
+ };
138
+ export const createBuildOpenQuestionResolutionBatch = ({ projectId, bundleId, resolutions, }) => {
139
+ if (resolutions.some(resolution => Boolean(resolution.dismiss) === Boolean(resolution.answer?.trim()))) {
140
+ return { ok: false, error: 'Each open question must be answered or dismissed' };
141
+ }
142
+ const create = db.transaction(() => {
143
+ if (hasActiveBuildOpenQuestionBatch(projectId, bundleId)) {
144
+ return { ok: false, error: 'Build open question resolution is already in progress' };
145
+ }
146
+ const validation = validateExactBuildOpenQuestionSet(projectId, bundleId, resolutions.map(resolution => resolution.questionId));
147
+ if (!validation.ok || validation.questions.length === 0) {
148
+ return validation.ok
149
+ ? { ok: false, error: 'The bundle has no open Build questions' }
150
+ : validation;
151
+ }
152
+ const id = randomUUID();
153
+ const hasAnswers = resolutions.some(resolution => Boolean(resolution.answer?.trim()));
154
+ db.prepare(`
155
+ INSERT INTO build_open_question_batches (
156
+ id, project_id, worktree_bundle_id, status, question_ids_json
157
+ ) VALUES (?, ?, ?, 'pending', ?)
158
+ `).run(id, projectId, bundleId, JSON.stringify(resolutions.map(resolution => resolution.questionId)));
159
+ for (const resolution of resolutions) {
160
+ const result = resolution.dismiss
161
+ ? db.prepare(`
162
+ UPDATE build_open_questions
163
+ SET status = 'dismissed', dismissed_at = CURRENT_TIMESTAMP, dismissed_by = ?,
164
+ dismissal_reason = ?, resolution_batch_id = ?, updated_at = CURRENT_TIMESTAMP
165
+ WHERE id = ? AND project_id = ? AND worktree_bundle_id = ? AND status = 'open'
166
+ `).run(resolution.dismissedBy ?? null, resolution.dismissalReason?.trim() || null, id, resolution.questionId, projectId, bundleId)
167
+ : db.prepare(`
168
+ UPDATE build_open_questions
169
+ SET status = 'answered', answer_text = ?, answered_at = CURRENT_TIMESTAMP,
170
+ resolution_batch_id = ?, updated_at = CURRENT_TIMESTAMP
171
+ WHERE id = ? AND project_id = ? AND worktree_bundle_id = ? AND status = 'open'
172
+ `).run(resolution.answer?.trim() ?? '', id, resolution.questionId, projectId, bundleId);
173
+ if (result.changes !== 1) {
174
+ throw new BuildOpenQuestionsChangedError('Build open questions changed while the batch was being resolved');
175
+ }
176
+ }
177
+ if (!hasAnswers) {
178
+ setBuildOpenQuestionBatchStatus(id, 'done');
179
+ }
180
+ const batch = db.prepare('SELECT * FROM build_open_question_batches WHERE id = ?').get(id);
181
+ return { ok: true, batch };
182
+ });
183
+ try {
184
+ return create();
185
+ }
186
+ catch (error) {
187
+ if (error instanceof BuildOpenQuestionsChangedError) {
188
+ return {
189
+ ok: false,
190
+ error: error.message,
191
+ code: BUILD_OPEN_QUESTIONS_CHANGED_CODE,
192
+ };
193
+ }
194
+ throw error;
195
+ }
196
+ };
197
+ export const setBuildOpenQuestionBatchStatus = (batchId, status, errorMessage = null) => {
198
+ db.prepare(`
199
+ UPDATE build_open_question_batches
200
+ SET status = ?,
201
+ error_message = ?,
202
+ started_at = CASE WHEN ? = 'running' AND started_at IS NULL THEN CURRENT_TIMESTAMP ELSE started_at END,
203
+ completed_at = CASE WHEN ? IN ('done', 'error') THEN CURRENT_TIMESTAMP ELSE completed_at END,
204
+ updated_at = CURRENT_TIMESTAMP
205
+ WHERE id = ?
206
+ `).run(status, errorMessage, status, status, batchId);
207
+ return db.prepare('SELECT * FROM build_open_question_batches WHERE id = ?').get(batchId) ?? null;
208
+ };
209
+ export const failBuildOpenQuestionBatch = (batchId, errorMessage) => {
210
+ const fail = db.transaction(() => {
211
+ const batch = setBuildOpenQuestionBatchStatus(batchId, 'error', errorMessage);
212
+ if (!batch) {
213
+ return null;
214
+ }
215
+ db.prepare(`
216
+ UPDATE build_open_questions
217
+ SET status = 'open', answer_text = NULL, answered_at = NULL,
218
+ dismissed_at = NULL, dismissed_by = NULL, dismissal_reason = NULL,
219
+ resolution_batch_id = NULL, updated_at = CURRENT_TIMESTAMP
220
+ WHERE resolution_batch_id = ? AND status IN ('answered', 'dismissed')
221
+ `).run(batchId);
222
+ return batch;
223
+ });
224
+ return fail();
225
+ };
226
+ export const hasActiveBuildOpenQuestionBatch = (projectId, bundleId) => {
227
+ const row = db.prepare(`
228
+ SELECT 1 AS active FROM build_open_question_batches
229
+ WHERE project_id = ? AND worktree_bundle_id = ? AND status IN ('pending', 'running')
230
+ LIMIT 1
231
+ `).get(projectId, bundleId);
232
+ return Boolean(row?.active);
233
+ };
234
+ export const getLatestBuildOpenQuestionBatchStatus = (projectId, bundleId) => {
235
+ const row = db.prepare(`
236
+ SELECT status FROM build_open_question_batches
237
+ WHERE project_id = ? AND worktree_bundle_id = ?
238
+ ORDER BY created_at DESC, rowid DESC
239
+ LIMIT 1
240
+ `).get(projectId, bundleId);
241
+ return row?.status ?? null;
242
+ };
243
+ export const formatBuildOpenQuestionAnswersPrompt = (questions) => {
244
+ const answered = questions.filter(question => question.status === 'answered' && question.answer_text);
245
+ if (answered.length === 0) {
246
+ return '';
247
+ }
248
+ const groups = new Map();
249
+ for (const question of answered) {
250
+ const title = question.ticket_title?.trim() || question.ticket_id;
251
+ groups.set(title, [...(groups.get(title) ?? []), question]);
252
+ }
253
+ return [
254
+ '<supplemental_requirements>',
255
+ 'The following answered Build questions are authoritative supplemental requirements. Review the implementation against them in addition to the code or specification context. Do not infer requirements from dismissed questions.',
256
+ ...[...groups.entries()].flatMap(([title, entries]) => [
257
+ `## ${title}`,
258
+ ...entries.flatMap(entry => [`Q: ${entry.question_text}`, `A: ${entry.answer_text}`]),
259
+ ]),
260
+ '</supplemental_requirements>',
261
+ ].join('\n');
262
+ };
263
+ //# sourceMappingURL=buildOpenQuestions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildOpenQuestions.js","sourceRoot":"","sources":["../../../server/lib/buildOpenQuestions.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,9 @@ import config from './config.js';
3
3
  import { getBundle, getTicket, listTickets, assignTicketLaneOrder, resolveTicketTool } from './tickets.js';
4
4
  import { getActiveBundleStageChangeHead } from './ticketUndo.js';
5
5
  import { startReview } from '../workers/review.js';
6
+ import { hasActiveBuildOpenQuestionBatch, listBuildOpenQuestionsForBundle } from './buildOpenQuestions.js';
7
+ import { getProjectById } from './projects.js';
8
+ import { resolveAutomationConfig } from './ticketAutomation.js';
6
9
  const getBundleTickets = (projectId, bundleId) => {
7
10
  return listTickets(projectId).filter(ticket => ticket.worktree_bundle_id === bundleId);
8
11
  };
@@ -28,7 +31,18 @@ export const resolveBundleReviewOwner = (projectId, bundleId) => {
28
31
  }
29
32
  return tickets.find(ticket => ticket.state === 'review' && ticket.undo?.stage === 'review') ?? null;
30
33
  };
31
- const getBundleReviewEligibilityError = (projectId, bundleId) => {
34
+ const getBundleReviewEligibilityError = (projectId, bundleId, options) => {
35
+ if (hasActiveBuildOpenQuestionBatch(projectId, bundleId)) {
36
+ return 'Build open question resolution is still in progress';
37
+ }
38
+ if (options.automatic) {
39
+ const project = getProjectById(projectId);
40
+ const bundle = getBundle(bundleId, projectId);
41
+ const automationConfig = resolveAutomationConfig(bundle, project);
42
+ if (automationConfig.pauseOnOpenQuestions && listBuildOpenQuestionsForBundle(projectId, bundleId).length > 0) {
43
+ return 'Resolve or dismiss all Build open questions before starting automatic Review';
44
+ }
45
+ }
32
46
  const buildTickets = getBundleSliceTickets(projectId, bundleId, 'build');
33
47
  if (buildTickets.length === 0) {
34
48
  const reviewTickets = getBundleSliceTickets(projectId, bundleId, 'review');
@@ -43,8 +57,8 @@ const getBundleReviewEligibilityError = (projectId, bundleId) => {
43
57
  }
44
58
  return null;
45
59
  };
46
- export const transitionBundleToReview = (projectId, bundleId, broadcaster) => {
47
- const eligibilityError = getBundleReviewEligibilityError(projectId, bundleId);
60
+ export const transitionBundleToReview = (projectId, bundleId, broadcaster, options = {}) => {
61
+ const eligibilityError = getBundleReviewEligibilityError(projectId, bundleId, options);
48
62
  if (eligibilityError) {
49
63
  return { ok: false, status: 409, error: eligibilityError };
50
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bundleReviewOperations.js","sourceRoot":"","sources":["../../../server/lib/bundleReviewOperations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundleReviewOperations.js","sourceRoot":"","sources":["../../../server/lib/bundleReviewOperations.ts"],"names":[],"mappings":"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"}
@@ -642,12 +642,23 @@ const parsePorcelainEntry = (entry, originalPath = null) => {
642
642
  if (kind !== '1' && kind !== '2' && kind !== 'u') {
643
643
  return null;
644
644
  }
645
- const parts = entry.split(' ');
646
- if (parts.length < 9) {
645
+ const pathFieldIndex = kind === '1' ? 8 : kind === '2' ? 9 : 10;
646
+ let fieldStart = 0;
647
+ const parts = [];
648
+ for (let index = 0; index < pathFieldIndex; index += 1) {
649
+ const separatorIndex = entry.indexOf(' ', fieldStart);
650
+ if (separatorIndex === -1) {
651
+ return null;
652
+ }
653
+ parts.push(entry.slice(fieldStart, separatorIndex));
654
+ fieldStart = separatorIndex + 1;
655
+ }
656
+ parts.push(entry.slice(fieldStart));
657
+ if (parts.length <= pathFieldIndex) {
647
658
  return null;
648
659
  }
649
660
  const xy = parts[1] ?? '..';
650
- const path = kind === '2' ? (parts[9] ?? '') : (parts[8] ?? '');
661
+ const path = parts[pathFieldIndex] ?? '';
651
662
  if (!path) {
652
663
  return null;
653
664
  }
@@ -1139,6 +1150,11 @@ export const getProjectBranch = (project = null, options = {}) => {
1139
1150
  diff_stats: includeDiffStats ? summarizeTicketDiffFiles(getGitDiffFiles(repoPath)) : null,
1140
1151
  };
1141
1152
  };
1153
+ export const getLocalProjectBranch = (project = null) => {
1154
+ const repoPath = getRepoPath(project);
1155
+ const output = runGitText(['status', '--porcelain=v2', '--branch', '-z'], repoPath);
1156
+ return getBranchSyncState(output.split('\0').filter(Boolean), repoPath).branch;
1157
+ };
1142
1158
  export const pullGitBranch = async (cwd, branch = null, project = null) => {
1143
1159
  const gitStatus = getGitStatus(cwd, branch, project, { refreshRemote: true });
1144
1160
  if (gitStatus.pull_disabled_reason) {