@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.
- package/dist/client/assets/GitHubActionsDialog-B9_WJBOp.js +1 -0
- package/dist/client/assets/TestsDialog-DKvbjH_M.js +4 -0
- package/dist/client/assets/TicketChangesModal-C8rFoKjY.js +1 -0
- package/dist/client/assets/{arc-CnuHRbeq.js → arc-D2Nn9xIj.js} +1 -1
- package/dist/client/assets/architecture-7EHR7CIX-C-4Cp4ml.js +1 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-cWqD9YRv.js → architectureDiagram-3BPJPVTR-DXRSRLL9.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-B8yyMr1c.js → blockDiagram-GPEHLZMM-D7EE6Dnv.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-B_yL8Tbe.js → c4Diagram-AAUBKEIU-UhVzFafr.js} +1 -1
- package/dist/client/assets/channel-CNoEXkwa.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BF8hfYEU.js → chunk-2J33WTMH-obbfylVr.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-BPDdyRDK.js → chunk-3OPIFGDE-DPVuS-uo.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-_WBpCe0m.js → chunk-4BX2VUAB-CtLS8D71.js} +1 -1
- package/dist/client/assets/{chunk-4EGX6M5U-BBQHxMeA.js → chunk-4EGX6M5U-Btnm0QNe.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-B-d-YzxI.js → chunk-55IACEB6-74CcJaub.js} +1 -1
- package/dist/client/assets/{chunk-5DO6E6H7-BA-oSVa-.js → chunk-5DO6E6H7-WLZ8L4ko.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-DEi4bnIa.js → chunk-5ZQYHXKU-Dsc03vy9.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-BTXHOTJi.js → chunk-727SXJPM-COE-iq_Z.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-D2TAJwxM.js → chunk-AQP2D5EJ-DnbAdr8m.js} +1 -1
- package/dist/client/assets/{chunk-BR22UD5L-prWX503j.js → chunk-BR22UD5L-Cou5beGe.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-CNtf2uaW.js → chunk-BSJP7CBP-DJ57XcV5.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-Bdgg7p9T.js → chunk-CSCIHK7Q-DbTzC_WS.js} +2 -2
- package/dist/client/assets/{chunk-FHYWG6QK-BQ8n0J0S.js → chunk-FHYWG6QK-Ba10e2kj.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CWQN4V4s.js → chunk-FMBD7UC4-CEo2wZMx.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-Cey3fOI1.js → chunk-KSCS5N6A-xvviIayr.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-BSNGBgBH.js → chunk-L5ZTLDWV-DY4Q9Til.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-B8qP34jM.js → chunk-LZXEDZCA-Bbeq2DZs.js} +2 -2
- package/dist/client/assets/{chunk-MPE355IW-gHN8AuU_.js → chunk-MPE355IW-MqEt-J8G.js} +1 -1
- package/dist/client/assets/{chunk-MZUSXYTE-Clzaz1kK.js → chunk-MZUSXYTE-DdNi9lhx.js} +1 -1
- package/dist/client/assets/{chunk-N66VUXT2-CkkAOkdt.js → chunk-N66VUXT2-CjemTW4E.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-COde7fTi.js → chunk-ND2GUHAM-CylX1p3K.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-C62VVWrt.js → chunk-NZK2D7GU-BTcALpQq.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-_20MzuKm.js → chunk-O5CBEL6O-Be_5dk2_.js} +1 -1
- package/dist/client/assets/{chunk-PUPMXCY4-DAdQFv8j.js → chunk-PUPMXCY4-ZvwTw0To.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-LI_RZca2.js +1 -0
- package/dist/client/assets/{chunk-UIBZB4QT-BRR84OYN.js → chunk-UIBZB4QT-BTY9be9s.js} +1 -1
- package/dist/client/assets/{chunk-WCWK7LTN-CQU7Fs_W.js → chunk-WCWK7LTN-Db1n3n3-.js} +1 -1
- package/dist/client/assets/chunk-WU5MYG2G-DXPsSM4Q.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-DafcxlUi.js → chunk-XPW4576I-DObFPxjB.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BgmK8-LI.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Dj5LqBjo.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DhJHP9hr.js → cose-bilkent-S5V4N54A-MlOPiG6P.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-jLUWHvr3.js → dagre-BM42HDAG-CABUW7xK.js} +1 -1
- package/dist/client/assets/{dagre-CdwzCXQr.js → dagre-BWNHuDdf.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-B6D2TKLb.js → diagram-2AECGRRQ-KvcNrpvf.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-bFJLLDWx.js → diagram-5GNKFQAL-DQV6-I4e.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-Bp01SL5f.js → diagram-KO2AKTUF-DYDk9roD.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DwoeZFg9.js → diagram-LMA3HP47-Da-0u-HG.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CjRd_tge.js → diagram-OG6HWLK6-CuD5eRBv.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DzfIVd9j.js → erDiagram-TEJ5UH35-BL5dBE-b.js} +1 -1
- package/dist/client/assets/eventmodeling-FCH6USID-Dqb6QKoI.js +1 -0
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Dq04zf9A.js → flowDiagram-I6XJVG4X-Bke5cWs7.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-D5f16YYP.js → ganttDiagram-6RSMTGT7-5OD-ayGn.js} +1 -1
- package/dist/client/assets/gitGraph-WXDBUCRP-DYEsqh93.js +1 -0
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CCD1CXBG.js → gitGraphDiagram-PVQCEYII-7Cf6FVfO.js} +1 -1
- package/dist/client/assets/index-D8EniXuq.css +2 -0
- package/dist/client/assets/index-DXuxAAzf.js +270 -0
- package/dist/client/assets/info-J43DQDTF-CfjXFZai.js +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-Bde4Z0o8.js → infoDiagram-5YYISTIA-BchMN9V-.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CJ89ymGL.js → ishikawaDiagram-YF4QCWOH-D6TchjQy.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-Dw_sScmo.js → journeyDiagram-JHISSGLW-CwEcoeX-.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-DfWOcnxV.js → kanban-definition-UN3LZRKU-S2V9CLGR.js} +1 -1
- package/dist/client/assets/{line-CUQIbS7r.js → line-DRheChzQ.js} +1 -1
- package/dist/client/assets/{linear-DFIW-KnM.js → linear-DT4rSZvy.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-d287AjoM.js → mermaid-parser.core-CN13XjLe.js} +2 -2
- package/dist/client/assets/{mermaid.core-QqY2ZNMl.js → mermaid.core-JhdSpoF5.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-Bz3Yc70v.js → mindmap-definition-RKZ34NQL-657TKwRB.js} +1 -1
- package/dist/client/assets/{ordinal-C1FS1Sfe.js → ordinal-k--hYEme.js} +1 -1
- package/dist/client/assets/packet-YPE3B663-Dv0HkRHU.js +1 -0
- package/dist/client/assets/pie-LRSECV5Y-S5zPzZFN.js +1 -0
- package/dist/client/assets/{pieDiagram-4H26LBE5-BjMDHR6y.js → pieDiagram-4H26LBE5-DJ8eQ94X.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BWDqf0X1.js → quadrantDiagram-W4KKPZXB-GpYFqyb1.js} +1 -1
- package/dist/client/assets/radar-GUYGQ44K-B7psLv22.js +1 -0
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-kspE4S60.js → requirementDiagram-4Y6WPE33-COZFWgq1.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-EuLhHbDR.js → sankeyDiagram-5OEKKPKP-BdCHyfcQ.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BvXG3DJh.js → sequenceDiagram-3UESZ5HK-DAh3Ogx0.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-B-D0PYkH.js → stateDiagram-AJRCARHV-Ck8Yie8_.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B6zibRqD.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CJnod6Jh.js → timeline-definition-PNZ67QCA-kYr9DNtP.js} +1 -1
- package/dist/client/assets/treeView-BLDUP644-B8H0kT67.js +1 -0
- package/dist/client/assets/treemap-LRROVOQU-DPLhFHnh.js +1 -0
- package/dist/client/assets/{vennDiagram-CIIHVFJN-CBh3tqZu.js → vennDiagram-CIIHVFJN-CC_SlRiC.js} +1 -1
- package/dist/client/assets/wardley-L42UT6IY-B5-Vb08V.js +1 -0
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BBQOjYBd.js → wardleyDiagram-YWT4CUSO-CZ17ccSN.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-C8gU1LNj.js → xychartDiagram-2RQKCTM6-Blqaj-ci.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +133 -0
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +299 -17
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +12 -11
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/buildOpenQuestions.js +263 -0
- package/dist/server/lib/buildOpenQuestions.js.map +1 -0
- package/dist/server/lib/bundleReviewOperations.js +17 -3
- package/dist/server/lib/bundleReviewOperations.js.map +1 -1
- package/dist/server/lib/git.js +19 -3
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/lightweightPrompt.js +2 -1
- package/dist/server/lib/lightweightPrompt.js.map +1 -1
- package/dist/server/lib/planModeQuestions.js +23 -1
- package/dist/server/lib/planModeQuestions.js.map +1 -1
- package/dist/server/lib/previewProxy.js +5 -0
- package/dist/server/lib/previewProxy.js.map +1 -1
- package/dist/server/lib/projectAutoConfig.js +2 -1
- package/dist/server/lib/projectAutoConfig.js.map +1 -1
- package/dist/server/lib/projectFiles.js +313 -0
- package/dist/server/lib/projectFiles.js.map +1 -0
- package/dist/server/lib/projects.js +10 -0
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/ticketAutomation.js +16 -4
- package/dist/server/lib/ticketAutomation.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +10 -10
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/ticketOpenQuestions.js +17 -0
- package/dist/server/lib/ticketOpenQuestions.js.map +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
- package/dist/server/lib/tickets.js +48 -6
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/workers/build.js +55 -12
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +2 -5
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +120 -18
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +4 -7
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/review.js +25 -8
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specSession.js +2 -5
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/GitHubActionsDialog-BLJ3yCeK.js +0 -1
- package/dist/client/assets/TestsDialog-ar_RUzA3.js +0 -4
- package/dist/client/assets/architecture-7EHR7CIX-tSrokdFP.js +0 -1
- package/dist/client/assets/channel-1Ezn2R-x.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-biOr9EeQ.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-C4G-J1jx.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DrjiwEWN.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DWHyuysv.js +0 -1
- package/dist/client/assets/eventmodeling-FCH6USID-DapHLQIh.js +0 -1
- package/dist/client/assets/gitGraph-WXDBUCRP-BTBN_hfb.js +0 -1
- package/dist/client/assets/index-DI9Vi2-3.js +0 -265
- package/dist/client/assets/index-DSap5tSX.css +0 -2
- package/dist/client/assets/info-J43DQDTF-CgiMJYKF.js +0 -1
- package/dist/client/assets/packet-YPE3B663-Bnwqjena.js +0 -1
- package/dist/client/assets/pie-LRSECV5Y-Ctj0ef-4.js +0 -1
- package/dist/client/assets/radar-GUYGQ44K-DE0H_saz.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-f36jgr8A.js +0 -1
- package/dist/client/assets/treeView-BLDUP644-CSAZL2OH.js +0 -1
- package/dist/client/assets/treemap-LRROVOQU-tYm4XKfP.js +0 -1
- package/dist/client/assets/wardley-L42UT6IY-DdiEFppm.js +0 -1
- /package/dist/client/assets/{array-B57E4cSs.js → array-BNor45A1.js} +0 -0
- /package/dist/client/assets/{chunk-NNHCCRGN-DRSAMe5H.js → chunk-NNHCCRGN-CZB-V-Gv.js} +0 -0
- /package/dist/client/assets/{cytoscape.esm-CVYSm6AJ.js → cytoscape.esm-B2lJcMSI.js} +0 -0
- /package/dist/client/assets/{defaultLocale-6WHJ3B09.js → defaultLocale-DPzUsThw.js} +0 -0
- /package/dist/client/assets/{dist-By2zKKTF.js → dist-CERhmQhR.js} +0 -0
- /package/dist/client/assets/{graphlib-B0DVs0bw.js → graphlib-BHOW-eWz.js} +0 -0
- /package/dist/client/assets/{init-DiYCGS1R.js → init-C0L3woqb.js} +0 -0
- /package/dist/client/assets/{katex-bgJu_0Fy.js → katex-CpjQsUQe.js} +0 -0
- /package/dist/client/assets/{path-DL_QDy2X.js → path-sMK4d_s9.js} +0 -0
- /package/dist/client/assets/{rough.esm-Bbn_-PMU.js → rough.esm-BoTisKeL.js} +0 -0
- /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":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AACzB,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC1G,OAAO,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"bundleReviewOperations.js","sourceRoot":"","sources":["../../../server/lib/bundleReviewOperations.ts"],"names":[],"mappings":"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"}
|
package/dist/server/lib/git.js
CHANGED
|
@@ -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
|
|
646
|
-
|
|
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 =
|
|
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) {
|