@straiffi/archon 1.10.8 → 1.10.10
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/ActivityView-CRkM5TeN.js +1 -0
- package/dist/client/assets/GitHubActionsDialog-KFUiR00H.js +1 -0
- package/dist/client/assets/VerificationDialog-BIDttgiW.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-CzUKSWJZ.js → architectureDiagram-3BPJPVTR-u0PSZlNP.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DoNm6BnS.js → blockDiagram-GPEHLZMM-DFXLHRIk.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-C7ocs3wQ.js → c4Diagram-AAUBKEIU-Dvic8tCt.js} +1 -1
- package/dist/client/assets/channel-Dhv_uSKx.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-DUmaxCq8.js → chunk-2J33WTMH-t5CxhRXJ.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-CX2MPsMQ.js → chunk-3OPIFGDE-YHT1dP8Q.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-B103kU_y.js → chunk-5ZQYHXKU-DcxuI7lb.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-BmLJ4h5X.js → chunk-727SXJPM-D1F6DmrT.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-Cnv1b4Vd.js → chunk-AQP2D5EJ-BIx6Ohbk.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-CkIUhpY9.js → chunk-CSCIHK7Q-B355h6HA.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-wmkCuZ5U.js → chunk-KSCS5N6A-CLHGYOLQ.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-D9AdL5mv.js → chunk-L5ZTLDWV-DFLYcMx8.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-rMyTvR3J.js → chunk-LZXEDZCA-DtljFujX.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-19HTozu8.js → chunk-ND2GUHAM-CIuUQ86K.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-DBHgwKcS.js → chunk-NZK2D7GU-CIwqlxek.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-4WpSG06s.js → chunk-O5CBEL6O-W42BEPu4.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-loqCl7ki.js → chunk-WU5MYG2G-C_zuaNxV.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-9XKvSSLq.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Dbr5_49Y.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-FVpIr0qZ.js → dagre-BM42HDAG-UKfIUJTP.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-Dgj8FaDO.js → diagram-2AECGRRQ-Xn6yojqq.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DNpYKz_a.js → diagram-5GNKFQAL-BzpY1ZEl.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-N7R7efvN.js → diagram-KO2AKTUF-Dyrvzvsg.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-hoOvd_tG.js → diagram-LMA3HP47-AqImKwAr.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-ze25ZIy6.js → diagram-OG6HWLK6-CaQQ46mi.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-780zvNNZ.js → erDiagram-TEJ5UH35-Dkw4Aa5u.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-x4UB_M_4.js → flowDiagram-I6XJVG4X-CJTuGX9h.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-B5Wl0y91.js → ganttDiagram-6RSMTGT7-CidgOdS-.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CZtVHpBH.js → gitGraphDiagram-PVQCEYII-Bj02mIQj.js} +1 -1
- package/dist/client/assets/index-ClRB9YWJ.css +2 -0
- package/dist/client/assets/index-DBMdsTvy.js +276 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BOzLwsnA.js → infoDiagram-5YYISTIA-GwJWfo_r.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-ButBhNg6.js → ishikawaDiagram-YF4QCWOH-rbrlWbUn.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CO0Db0Gn.js → journeyDiagram-JHISSGLW-BLi_uzQM.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-B6KT8yln.js → kanban-definition-UN3LZRKU-ynlywm-_.js} +1 -1
- package/dist/client/assets/{line-Cv-WaOjt.js → line-BNyTZBB4.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-DgJy4Qlx.js → mermaid-parser.core-CzUOsZAD.js} +1 -1
- package/dist/client/assets/{mermaid.core-YpvipwZo.js → mermaid.core-K0QR6SzN.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DGgtT98Y.js → mindmap-definition-RKZ34NQL-BKcgqXm0.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-CgqnLewO.js → pieDiagram-4H26LBE5-Bjx0lvDI.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Ci_0SzdR.js → quadrantDiagram-W4KKPZXB-CmUlgyUv.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-wJl0DP74.js → requirementDiagram-4Y6WPE33-Dj2mzg1y.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CE7aDnzF.js → sankeyDiagram-5OEKKPKP-DC--H6qf.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CW0bF1i6.js → sequenceDiagram-3UESZ5HK-BkNrt6Ra.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-Ccl0RXsJ.js → stateDiagram-AJRCARHV-BuxxRu1Y.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Cyo85GPN.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-TuF6SUnb.js → timeline-definition-PNZ67QCA-Db3pCVSp.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-D8OvSROI.js → vennDiagram-CIIHVFJN-BgBSGThQ.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DXW3R5NJ.js → wardleyDiagram-YWT4CUSO-BJhPdjYS.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-qdiUQDW9.js → xychartDiagram-2RQKCTM6-BY4Ra0kX.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +341 -4
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +197 -270
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agentRuns.js +14 -1
- package/dist/server/lib/agentRuns.js.map +1 -1
- package/dist/server/lib/automationLoopProjection.js +55 -12
- package/dist/server/lib/automationLoopProjection.js.map +1 -1
- package/dist/server/lib/automationProgression.js +2 -5
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/automationResumeDecision.js +19 -1
- package/dist/server/lib/automationResumeDecision.js.map +1 -1
- package/dist/server/lib/boundedProcess.js +129 -0
- package/dist/server/lib/boundedProcess.js.map +1 -0
- package/dist/server/lib/buildControlEligibility.js +4 -0
- package/dist/server/lib/buildControlEligibility.js.map +1 -0
- package/dist/server/lib/buildExecutionAdmission.js +76 -0
- package/dist/server/lib/buildExecutionAdmission.js.map +1 -0
- package/dist/server/lib/buildSequenceResume.js +79 -0
- package/dist/server/lib/buildSequenceResume.js.map +1 -0
- package/dist/server/lib/buildWorkload.js +11 -0
- package/dist/server/lib/buildWorkload.js.map +1 -0
- package/dist/server/lib/bundleReviewOperations.js +7 -0
- package/dist/server/lib/bundleReviewOperations.js.map +1 -1
- package/dist/server/lib/chats.js +12 -0
- package/dist/server/lib/chats.js.map +1 -1
- package/dist/server/lib/checkAutoFixDetails.js +36 -1
- package/dist/server/lib/checkAutoFixDetails.js.map +1 -1
- package/dist/server/lib/executionRetry.js +13 -1
- package/dist/server/lib/executionRetry.js.map +1 -1
- package/dist/server/lib/executionRunAuthority.js +2 -2
- package/dist/server/lib/executionRunAuthority.js.map +1 -1
- package/dist/server/lib/executionTargets.js +7 -4
- package/dist/server/lib/executionTargets.js.map +1 -1
- package/dist/server/lib/executionTimeline.js +8 -13
- package/dist/server/lib/executionTimeline.js.map +1 -1
- package/dist/server/lib/executionTimelineHierarchy.js +83 -0
- package/dist/server/lib/executionTimelineHierarchy.js.map +1 -0
- package/dist/server/lib/failedBuildSequenceRecovery.js +133 -0
- package/dist/server/lib/failedBuildSequenceRecovery.js.map +1 -0
- package/dist/server/lib/git.js +89 -48
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/hostRunSession.js +62 -0
- package/dist/server/lib/hostRunSession.js.map +1 -0
- package/dist/server/lib/hostServiceRecovery.js +159 -0
- package/dist/server/lib/hostServiceRecovery.js.map +1 -0
- package/dist/server/lib/hostServiceRunProvider.js +32 -0
- package/dist/server/lib/hostServiceRunProvider.js.map +1 -0
- package/dist/server/lib/integrations/github.js +49 -105
- package/dist/server/lib/integrations/github.js.map +1 -1
- package/dist/server/lib/mobileAccess.js +6 -2
- package/dist/server/lib/mobileAccess.js.map +1 -1
- package/dist/server/lib/projectAutoConfig.js +5 -2
- package/dist/server/lib/projectAutoConfig.js.map +1 -1
- package/dist/server/lib/projectTargets.js +8 -2
- package/dist/server/lib/projectTargets.js.map +1 -1
- package/dist/server/lib/projects.js +25 -1
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/reviewFindingReconciliation.js +9 -2
- package/dist/server/lib/reviewFindingReconciliation.js.map +1 -1
- package/dist/server/lib/reviewFindings.js +113 -23
- package/dist/server/lib/reviewFindings.js.map +1 -1
- package/dist/server/lib/reviewRepairAssessmentRecords.js +41 -0
- package/dist/server/lib/reviewRepairAssessmentRecords.js.map +1 -0
- package/dist/server/lib/reviewRepairCompletion.js +78 -18
- package/dist/server/lib/reviewRepairCompletion.js.map +1 -1
- package/dist/server/lib/reviewRepairIterationRecords.js +4 -2
- package/dist/server/lib/reviewRepairIterationRecords.js.map +1 -1
- package/dist/server/lib/reviewRepairIterations.js +8 -2
- package/dist/server/lib/reviewRepairIterations.js.map +1 -1
- package/dist/server/lib/reviewRepairProgress.js +177 -0
- package/dist/server/lib/reviewRepairProgress.js.map +1 -0
- package/dist/server/lib/reviewRepairReconciliation.js +119 -140
- package/dist/server/lib/reviewRepairReconciliation.js.map +1 -1
- package/dist/server/lib/reviewRepairResumeOverride.js +55 -0
- package/dist/server/lib/reviewRepairResumeOverride.js.map +1 -0
- package/dist/server/lib/run.js +523 -504
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/runProcessIdentity.js +71 -0
- package/dist/server/lib/runProcessIdentity.js.map +1 -0
- package/dist/server/lib/runProcesses.js +261 -0
- package/dist/server/lib/runProcesses.js.map +1 -0
- package/dist/server/lib/runServices.js +221 -0
- package/dist/server/lib/runServices.js.map +1 -0
- package/dist/server/lib/runSessionLifecycle.js +68 -0
- package/dist/server/lib/runSessionLifecycle.js.map +1 -0
- package/dist/server/lib/runStatus.js +7 -0
- package/dist/server/lib/runStatus.js.map +1 -0
- package/dist/server/lib/serviceRuns.js +273 -16
- package/dist/server/lib/serviceRuns.js.map +1 -1
- package/dist/server/lib/ticketAutomation.js +4 -27
- package/dist/server/lib/ticketAutomation.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +103 -34
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/tickets.js +46 -21
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/build.js +44 -69
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/plan.js +0 -7
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/review.js +95 -146
- package/dist/server/workers/review.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/ActivityView-PGEex8sS.js +0 -1
- package/dist/client/assets/GitHubActionsDialog-CwsZRevc.js +0 -1
- package/dist/client/assets/VerificationDialog-BYE1M9T2.js +0 -4
- package/dist/client/assets/channel-b-KoJfeL.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-2c5Acffy.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-ClrW9LEB.js +0 -1
- package/dist/client/assets/index-BXsDja_y.css +0 -2
- package/dist/client/assets/index-Cy3ZoenG.js +0 -276
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-k65NSsdn.js +0 -1
- package/dist/server/lib/automationDeliveryDecision.js +0 -34
- package/dist/server/lib/automationDeliveryDecision.js.map +0 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import db from '../db.js';
|
|
2
|
+
// Legacy resumes have no workload tag. Require the exact stopped parent and
|
|
3
|
+
// pre-provider failure evidence instead of inferring continuation from a ticket session.
|
|
4
|
+
// UNION also terminates malformed retry cycles; only a chain reaching the bound
|
|
5
|
+
// legacy failure, with exclusively pre-start queue failures after it, is admitted.
|
|
6
|
+
export const getFailedBuildSequenceRecovery = (projectId, runId, replacementRunId = null) => db.prepare(`
|
|
7
|
+
WITH RECURSIVE recovery_chain(id, retry_of_run_id) AS (
|
|
8
|
+
SELECT id, retry_of_run_id FROM execution_runs WHERE id = @source AND project_id = @project
|
|
9
|
+
UNION
|
|
10
|
+
SELECT prior.id, prior.retry_of_run_id FROM execution_runs prior
|
|
11
|
+
JOIN recovery_chain child ON child.retry_of_run_id = prior.id WHERE prior.project_id = @project
|
|
12
|
+
)
|
|
13
|
+
SELECT sequence.id AS sequenceId, ticket.id AS ticketId, ticket.session_id AS sessionId,
|
|
14
|
+
original.id AS parentRunId, failed.id AS boundRunId, item.finished_at AS finishedAt
|
|
15
|
+
FROM execution_runs failed
|
|
16
|
+
JOIN recovery_chain root ON root.id = failed.id
|
|
17
|
+
JOIN execution_runs original ON original.id = failed.parent_run_id AND original.project_id = failed.project_id
|
|
18
|
+
JOIN build_sequence_tickets item ON item.activation_execution_run_id = failed.id
|
|
19
|
+
JOIN build_sequences sequence ON sequence.id = item.build_sequence_id AND sequence.project_id = failed.project_id
|
|
20
|
+
JOIN tickets ticket ON ticket.id = item.ticket_id AND ticket.project_id = failed.project_id
|
|
21
|
+
WHERE failed.project_id = @project
|
|
22
|
+
AND failed.kind = 'build' AND failed.status = 'failed' AND failed.domain_status = 'error'
|
|
23
|
+
AND failed.initiated_by = 'user' AND failed.retry_of_run_id IS NULL
|
|
24
|
+
AND failed.failure_code = 'build_failed'
|
|
25
|
+
AND failed.failure_message = 'Execution run authority workload does not match the durable run intent'
|
|
26
|
+
AND (json_type(failed.metadata_json, '$.build_workload') IS NULL
|
|
27
|
+
OR json_extract(failed.metadata_json, '$.build_workload') = 'build_continuation')
|
|
28
|
+
AND original.kind = 'build' AND original.status = 'cancelled' AND original.domain_status = 'stopped'
|
|
29
|
+
AND original.initiated_by = 'user'
|
|
30
|
+
AND sequence.status = 'failed' AND item.status = 'failed'
|
|
31
|
+
AND item.execution_profile_revision_id IS NOT NULL AND item.execution_profile_fingerprint IS NOT NULL
|
|
32
|
+
AND item.execution_profile_selection_reason IS NOT NULL
|
|
33
|
+
AND ticket.worktree_bundle_id = sequence.worktree_bundle_id
|
|
34
|
+
AND ticket.state = 'build' AND ticket.agent_status = 'error'
|
|
35
|
+
AND ticket.build_completed_at IS NULL AND length(ticket.session_id) > 0
|
|
36
|
+
AND ticket.tool = json_extract(original.metadata_json, '$.retry_tool')
|
|
37
|
+
AND ticket.model IS json_extract(original.metadata_json, '$.retry_model')
|
|
38
|
+
AND ticket.variant IS json_extract(original.metadata_json, '$.retry_variant')
|
|
39
|
+
AND EXISTS (SELECT 1 FROM agent_runs agent WHERE agent.execution_run_id = original.id
|
|
40
|
+
AND agent.parent_type = 'ticket' AND agent.parent_id = ticket.id AND agent.role = 'main'
|
|
41
|
+
AND agent.agent_status = 'stopped' AND agent.session_id = ticket.session_id)
|
|
42
|
+
AND EXISTS (SELECT 1 FROM agent_runs agent WHERE agent.execution_run_id = failed.id
|
|
43
|
+
AND agent.parent_type = 'ticket' AND agent.parent_id = ticket.id AND agent.role = 'main'
|
|
44
|
+
AND agent.agent_status = 'error' AND agent.session_id IS NULL)
|
|
45
|
+
AND NOT EXISTS (SELECT 1 FROM agent_runs agent WHERE agent.execution_run_id = failed.id
|
|
46
|
+
AND (agent.session_id IS NOT NULL OR agent.response_text IS NOT NULL OR agent.streaming_response IS NOT NULL
|
|
47
|
+
OR agent.role != 'main' OR agent.agent_status != 'error'))
|
|
48
|
+
AND NOT EXISTS (SELECT 1 FROM execution_run_authorities authority
|
|
49
|
+
WHERE authority.execution_run_id IN (SELECT id FROM recovery_chain))
|
|
50
|
+
AND NOT EXISTS (
|
|
51
|
+
SELECT 1 FROM execution_runs attempt JOIN recovery_chain chain ON chain.id = attempt.id
|
|
52
|
+
WHERE attempt.id != failed.id AND (
|
|
53
|
+
attempt.kind != 'build' OR attempt.status != 'failed' OR attempt.domain_status IS NOT 'error'
|
|
54
|
+
OR attempt.initiated_by != 'user' OR attempt.failure_code IS NOT 'queue_failed'
|
|
55
|
+
OR attempt.started_at IS NOT NULL OR attempt.parent_run_id IS NOT original.id
|
|
56
|
+
OR attempt.correlation_id != failed.correlation_id
|
|
57
|
+
OR json_extract(attempt.metadata_json, '$.build_workload') IS NOT 'build_continuation'
|
|
58
|
+
OR json_extract(attempt.metadata_json, '$.retry_model') IS NOT ticket.model
|
|
59
|
+
OR json_extract(attempt.metadata_json, '$.retry_variant') IS NOT ticket.variant
|
|
60
|
+
OR EXISTS (SELECT 1 FROM agent_runs agent WHERE agent.execution_run_id = attempt.id)
|
|
61
|
+
OR EXISTS (SELECT 1 FROM execution_run_links link
|
|
62
|
+
WHERE link.execution_run_id = attempt.id AND link.relationship = 'result')
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
AND NOT EXISTS (SELECT 1 FROM build_sequences busy WHERE busy.project_id = sequence.project_id
|
|
66
|
+
AND busy.worktree_bundle_id = sequence.worktree_bundle_id AND busy.status = 'active')
|
|
67
|
+
AND NOT EXISTS (SELECT 1 FROM build_sequence_tickets other WHERE other.build_sequence_id = sequence.id
|
|
68
|
+
AND other.ticket_id != ticket.id AND other.status != 'done')
|
|
69
|
+
AND NOT EXISTS (SELECT 1 FROM execution_runs newer
|
|
70
|
+
JOIN execution_run_links link ON link.execution_run_id = newer.id AND link.project_id = newer.project_id
|
|
71
|
+
WHERE newer.project_id = failed.project_id AND link.entity_type = 'ticket'
|
|
72
|
+
AND link.entity_id = ticket.id AND link.relationship = 'primary' AND newer.id IS NOT @replacement
|
|
73
|
+
AND newer.id NOT IN (SELECT id FROM recovery_chain)
|
|
74
|
+
AND (newer.status IN ('queued', 'running', 'waiting')
|
|
75
|
+
OR (newer.created_at, newer.id) > (failed.created_at, failed.id)))
|
|
76
|
+
AND NOT EXISTS (SELECT 1 FROM execution_runs retry
|
|
77
|
+
WHERE retry.retry_of_run_id IN (SELECT id FROM recovery_chain)
|
|
78
|
+
AND retry.id NOT IN (SELECT id FROM recovery_chain) AND retry.id IS NOT @replacement)
|
|
79
|
+
AND NOT EXISTS (
|
|
80
|
+
SELECT 1 FROM execution_runs owner WHERE (owner.id = original.id OR owner.id IN (SELECT id FROM recovery_chain))
|
|
81
|
+
AND (json_extract(owner.metadata_json, '$.execution_profile_revision_id') IS NOT item.execution_profile_revision_id
|
|
82
|
+
OR json_extract(owner.metadata_json, '$.execution_profile_fingerprint') IS NOT item.execution_profile_fingerprint
|
|
83
|
+
OR json_extract(owner.metadata_json, '$.execution_profile_selection_reason') IS NOT item.execution_profile_selection_reason
|
|
84
|
+
OR json_extract(owner.metadata_json, '$.retry_tool') IS NOT ticket.tool
|
|
85
|
+
OR NOT EXISTS (SELECT 1 FROM execution_run_links link WHERE link.execution_run_id = owner.id
|
|
86
|
+
AND link.project_id = failed.project_id AND link.entity_type = 'ticket' AND link.entity_id = ticket.id AND link.relationship = 'primary')
|
|
87
|
+
OR NOT EXISTS (SELECT 1 FROM execution_run_links link WHERE link.execution_run_id = owner.id
|
|
88
|
+
AND link.project_id = failed.project_id AND link.entity_type = 'bundle' AND link.entity_id = sequence.worktree_bundle_id AND link.relationship = 'context')
|
|
89
|
+
OR NOT EXISTS (SELECT 1 FROM execution_run_links link WHERE link.execution_run_id = owner.id
|
|
90
|
+
AND link.project_id = failed.project_id AND link.entity_type = 'build_sequence' AND link.entity_id = sequence.id AND link.relationship = 'context'))
|
|
91
|
+
)
|
|
92
|
+
`).get({ replacement: replacementRunId, source: runId, project: projectId });
|
|
93
|
+
export const handoffFailedBuildSequenceRecovery = (projectId, sequenceId, ticketId, sessionId, replacementRunId) => {
|
|
94
|
+
const next = db.prepare(`SELECT retry_of_run_id AS sourceId FROM execution_runs
|
|
95
|
+
WHERE id = ? AND project_id = ? AND kind = 'build' AND status = 'queued'
|
|
96
|
+
AND initiated_by = 'user' AND json_extract(metadata_json, '$.build_workload') = 'build_continuation'`)
|
|
97
|
+
.get(replacementRunId, projectId);
|
|
98
|
+
if (!next?.sourceId) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const recovery = getFailedBuildSequenceRecovery(projectId, next.sourceId, replacementRunId);
|
|
102
|
+
if (!recovery || recovery.sequenceId !== sequenceId || recovery.ticketId !== ticketId || recovery.sessionId !== sessionId) {
|
|
103
|
+
throw new Error('The failed Build resume has no verified recovery lineage');
|
|
104
|
+
}
|
|
105
|
+
const matching = db.prepare(`SELECT 1 FROM execution_runs next
|
|
106
|
+
JOIN build_sequence_tickets item ON item.build_sequence_id = ? AND item.ticket_id = ?
|
|
107
|
+
WHERE next.id = ? AND next.parent_run_id = ?
|
|
108
|
+
AND EXISTS (SELECT 1 FROM execution_run_links link WHERE link.execution_run_id = next.id
|
|
109
|
+
AND link.project_id = next.project_id AND link.entity_type = 'ticket' AND link.entity_id = item.ticket_id AND link.relationship = 'primary')
|
|
110
|
+
AND EXISTS (SELECT 1 FROM execution_run_links link WHERE link.execution_run_id = next.id
|
|
111
|
+
AND link.project_id = next.project_id AND link.entity_type = 'build_sequence' AND link.entity_id = item.build_sequence_id AND link.relationship = 'context')
|
|
112
|
+
AND json_extract(next.metadata_json, '$.execution_profile_revision_id') = item.execution_profile_revision_id
|
|
113
|
+
AND json_extract(next.metadata_json, '$.execution_profile_fingerprint') = item.execution_profile_fingerprint
|
|
114
|
+
AND json_extract(next.metadata_json, '$.execution_profile_selection_reason') = item.execution_profile_selection_reason`)
|
|
115
|
+
.get(sequenceId, ticketId, replacementRunId, recovery.parentRunId);
|
|
116
|
+
if (!matching) {
|
|
117
|
+
throw new Error('The failed Build resume recovery profile does not match');
|
|
118
|
+
}
|
|
119
|
+
db.prepare("UPDATE build_sequences SET status = 'active', updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(sequenceId);
|
|
120
|
+
db.prepare(`UPDATE build_sequence_tickets SET status = 'active', finished_at = NULL, activation_execution_run_id = ?
|
|
121
|
+
WHERE build_sequence_id = ? AND ticket_id = ?`).run(replacementRunId, sequenceId, ticketId);
|
|
122
|
+
return () => {
|
|
123
|
+
const restored = db.prepare(`UPDATE build_sequence_tickets SET status = 'failed', finished_at = ?, activation_execution_run_id = ?
|
|
124
|
+
WHERE build_sequence_id = ? AND ticket_id = ? AND status = 'active' AND activation_execution_run_id = ?
|
|
125
|
+
AND EXISTS (SELECT 1 FROM execution_runs WHERE id = ? AND status = 'queued')`)
|
|
126
|
+
.run(recovery.finishedAt, recovery.boundRunId, sequenceId, ticketId, replacementRunId, replacementRunId);
|
|
127
|
+
if (restored.changes !== 1) {
|
|
128
|
+
throw new Error('Unable to restore the failed Build sequence');
|
|
129
|
+
}
|
|
130
|
+
db.prepare("UPDATE build_sequences SET status = 'failed', updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(sequenceId);
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=failedBuildSequenceRecovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failedBuildSequenceRecovery.js","sourceRoot":"","sources":["../../../server/lib/failedBuildSequenceRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AAEzB,4EAA4E;AAC5E,yFAAyF;AACzF,gFAAgF;AAChF,mFAAmF;AACnF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,SAAiB,EAAE,KAAa,EAAE,mBAAkC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsFtI,CAAC,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAE9D,CAAA;AAEb,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAChD,SAAiB,EAAE,UAAkB,EAAE,QAAgB,EAAE,SAAiB,EAAE,gBAAwB,EAC/E,EAAE;IACvB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;2GAEiF,CAAC;SACvG,GAAG,CAAC,gBAAgB,EAAE,SAAS,CAA4C,CAAA;IAC9E,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,QAAQ,GAAG,8BAA8B,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAA;IAC3F,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,KAAK,UAAU,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1H,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;6HAS+F,CAAC;SACzH,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;IACpE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAA;IAC5E,CAAC;IACD,EAAE,CAAC,OAAO,CAAC,2FAA2F,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACvH,EAAE,CAAC,OAAO,CAAC;kDACqC,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC7F,OAAO,GAAG,EAAE;QACV,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;qFAEqD,CAAC;aAC/E,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;QAC1G,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;QAChE,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,2FAA2F,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACzH,CAAC,CAAA;AACH,CAAC,CAAA"}
|
package/dist/server/lib/git.js
CHANGED
|
@@ -5,6 +5,7 @@ import { cp as cpAsync, lstat as lstatAsync, mkdir as mkdirAsync, stat as statAs
|
|
|
5
5
|
import { tmpdir } from 'os';
|
|
6
6
|
import { dirname, isAbsolute, join, relative, resolve } from 'path';
|
|
7
7
|
import db from '../db.js';
|
|
8
|
+
import { runBoundedProcess } from './boundedProcess.js';
|
|
8
9
|
import { getProjectWorktreeSync } from './projects.js';
|
|
9
10
|
import { createWorkspaceProcessEnvironment } from './workspaceProcessEnvironment.js';
|
|
10
11
|
export class UnpushedCommitDiffSelectionError extends Error {
|
|
@@ -12,8 +13,10 @@ export class UnpushedCommitDiffSelectionError extends Error {
|
|
|
12
13
|
const PROJECT_BRANCH_REMOTE_REFRESH_TTL_MS = 30_000;
|
|
13
14
|
const MAX_GIT_OUTPUT_BYTES = 512 * 1024 * 1024;
|
|
14
15
|
const GIT_READ_TIMEOUT_MS = 15_000;
|
|
16
|
+
const GIT_REMOTE_KILL_GRACE_MS = 500;
|
|
15
17
|
const MAX_CONCURRENT_DIFF_PROCESSES = 8;
|
|
16
18
|
const lastProjectBranchRemoteRefreshAt = new Map();
|
|
19
|
+
const projectBranchRemoteRefreshes = new Map();
|
|
17
20
|
const resolveCurrentBranchName = (cwd) => {
|
|
18
21
|
try {
|
|
19
22
|
const branch = runGitText(['branch', '--show-current'], cwd).trim();
|
|
@@ -113,6 +116,22 @@ const runGitTextAsync = (args, cwd, options = {}) => new Promise((resolvePromise
|
|
|
113
116
|
});
|
|
114
117
|
});
|
|
115
118
|
});
|
|
119
|
+
const runGitRemoteTextAsync = async (args, cwd) => {
|
|
120
|
+
const result = await runBoundedProcess('git', args, {
|
|
121
|
+
cwd,
|
|
122
|
+
env: createWorkspaceProcessEnvironment(cwd, { GIT_TERMINAL_PROMPT: '0' }),
|
|
123
|
+
timeoutMs: GIT_READ_TIMEOUT_MS,
|
|
124
|
+
killGraceMs: GIT_REMOTE_KILL_GRACE_MS,
|
|
125
|
+
maxOutputBytes: MAX_GIT_OUTPUT_BYTES,
|
|
126
|
+
});
|
|
127
|
+
if (result.code !== 0) {
|
|
128
|
+
const error = new Error(result.stderr.trim() || `git exited with code ${result.code ?? 'unknown'}`);
|
|
129
|
+
error.stderr = result.stderr;
|
|
130
|
+
error.status = result.code;
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
return { stdout: result.stdout, stderr: result.stderr };
|
|
134
|
+
};
|
|
116
135
|
const mapWithConcurrency = async (inputs, concurrency, operation) => {
|
|
117
136
|
const results = new Array(inputs.length);
|
|
118
137
|
let nextIndex = 0;
|
|
@@ -357,7 +376,7 @@ const refreshSquashUpstream = async (branch, cwd) => {
|
|
|
357
376
|
return localUpstreamCommitSha;
|
|
358
377
|
}
|
|
359
378
|
try {
|
|
360
|
-
await
|
|
379
|
+
await runGitRemoteTextAsync(['fetch', '--quiet', fetchSpec.remote, fetchSpec.branch], cwd);
|
|
361
380
|
}
|
|
362
381
|
catch {
|
|
363
382
|
throw new Error('Unable to refresh the upstream branch before squashing commits. Pull or reconcile the branch and try again.');
|
|
@@ -477,21 +496,6 @@ const getEmptyProjectBranchResponse = (status = 'unknown') => ({
|
|
|
477
496
|
can_pull: false,
|
|
478
497
|
diff_stats: null,
|
|
479
498
|
});
|
|
480
|
-
const refreshProjectBranchTracking = (repoPath, branch) => {
|
|
481
|
-
if (!branch) {
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
try {
|
|
485
|
-
const upstreamFetchSpec = resolveBranchUpstreamFetchSpec(branch, repoPath);
|
|
486
|
-
const args = upstreamFetchSpec
|
|
487
|
-
? ['fetch', '--quiet', upstreamFetchSpec.remote, upstreamFetchSpec.branch]
|
|
488
|
-
: ['fetch', '--quiet', 'origin', branch];
|
|
489
|
-
runGitText(args, repoPath);
|
|
490
|
-
}
|
|
491
|
-
catch {
|
|
492
|
-
// Keep the last known tracking state when fetch is unavailable.
|
|
493
|
-
}
|
|
494
|
-
};
|
|
495
499
|
const shouldRefreshProjectBranchTracking = (cacheKey, force) => {
|
|
496
500
|
if (force) {
|
|
497
501
|
lastProjectBranchRemoteRefreshAt.set(cacheKey, Date.now());
|
|
@@ -1390,15 +1394,9 @@ export const deleteWorktree = (branch, project = null) => {
|
|
|
1390
1394
|
export const getProjectBranch = (project = null, options = {}) => {
|
|
1391
1395
|
const repoPath = getRepoPath(project);
|
|
1392
1396
|
const includeDiffStats = options.includeDiffStats ?? true;
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
if (branchState.branch && shouldRefreshProjectBranchTracking(getProjectBranchRefreshCacheKey(repoPath, branchState.branch), options.refreshRemote ?? false)) {
|
|
1397
|
-
refreshProjectBranchTracking(repoPath, branchState.branch);
|
|
1398
|
-
output = runGitText(['status', '--porcelain=v2', '--branch', '-z'], repoPath);
|
|
1399
|
-
entries = output.split('\0').filter(Boolean);
|
|
1400
|
-
branchState = getBranchSyncState(entries, repoPath);
|
|
1401
|
-
}
|
|
1397
|
+
const output = runGitText(['status', '--porcelain=v2', '--branch', '-z'], repoPath);
|
|
1398
|
+
const entries = output.split('\0').filter(Boolean);
|
|
1399
|
+
const branchState = getBranchSyncState(entries, repoPath);
|
|
1402
1400
|
if (!branchState.branch) {
|
|
1403
1401
|
const statusLine = output.split('\0').find(entry => entry.startsWith('# branch.head ')) ?? '';
|
|
1404
1402
|
if (statusLine.endsWith('(detached)')) {
|
|
@@ -1416,13 +1414,46 @@ export const getProjectBranch = (project = null, options = {}) => {
|
|
|
1416
1414
|
diff_stats: includeDiffStats ? summarizeTicketDiffFiles(getGitDiffFiles(repoPath)) : null,
|
|
1417
1415
|
};
|
|
1418
1416
|
};
|
|
1417
|
+
export const getProjectBranchAsync = async (project = null, options = {}) => {
|
|
1418
|
+
const repoPath = getRepoPath(project);
|
|
1419
|
+
const includeDiffStats = options.includeDiffStats ?? true;
|
|
1420
|
+
const readBranchState = async () => {
|
|
1421
|
+
const output = (await runGitTextAsync(['status', '--porcelain=v2', '--branch', '-z'], repoPath, { timeoutMs: GIT_READ_TIMEOUT_MS })).stdout;
|
|
1422
|
+
const entries = output.split('\0').filter(Boolean);
|
|
1423
|
+
const branchState = await getBranchSyncStateAsync(entries, repoPath, null);
|
|
1424
|
+
return { output, branchState };
|
|
1425
|
+
};
|
|
1426
|
+
let { output, branchState } = await readBranchState();
|
|
1427
|
+
if (branchState.branch && shouldRefreshProjectBranchTracking(getProjectBranchRefreshCacheKey(repoPath, branchState.branch), options.refreshRemote ?? false)) {
|
|
1428
|
+
await refreshProjectBranchTrackingAsync(repoPath, branchState.branch);
|
|
1429
|
+
const refreshed = await readBranchState();
|
|
1430
|
+
output = refreshed.output;
|
|
1431
|
+
branchState = refreshed.branchState;
|
|
1432
|
+
}
|
|
1433
|
+
if (!branchState.branch) {
|
|
1434
|
+
const statusLine = output.split('\0').find(entry => entry.startsWith('# branch.head ')) ?? '';
|
|
1435
|
+
return getEmptyProjectBranchResponse(statusLine.endsWith('(detached)') ? 'detached' : 'unknown');
|
|
1436
|
+
}
|
|
1437
|
+
const diffStats = includeDiffStats
|
|
1438
|
+
? summarizeTicketDiffFiles(await getGitDiffFilesAsync(repoPath))
|
|
1439
|
+
: null;
|
|
1440
|
+
return {
|
|
1441
|
+
branch: branchState.branch,
|
|
1442
|
+
status: 'ready',
|
|
1443
|
+
ahead: branchState.ahead,
|
|
1444
|
+
behind: branchState.behind,
|
|
1445
|
+
has_upstream: branchState.hasUpstream,
|
|
1446
|
+
can_pull: branchState.behind > 0,
|
|
1447
|
+
diff_stats: diffStats,
|
|
1448
|
+
};
|
|
1449
|
+
};
|
|
1419
1450
|
export const getLocalProjectBranch = (project = null) => {
|
|
1420
1451
|
const repoPath = getRepoPath(project);
|
|
1421
1452
|
const output = runGitText(['status', '--porcelain=v2', '--branch', '-z'], repoPath);
|
|
1422
1453
|
return getBranchSyncState(output.split('\0').filter(Boolean), repoPath).branch;
|
|
1423
1454
|
};
|
|
1424
1455
|
export const pullGitBranch = async (cwd, branch = null, project = null) => {
|
|
1425
|
-
const gitStatus =
|
|
1456
|
+
const gitStatus = await getGitStatusAsync(cwd, branch, project, { refreshRemote: true });
|
|
1426
1457
|
if (gitStatus.pull_disabled_reason) {
|
|
1427
1458
|
throw new Error(gitStatus.pull_disabled_reason);
|
|
1428
1459
|
}
|
|
@@ -1433,16 +1464,16 @@ export const pullGitBranch = async (cwd, branch = null, project = null) => {
|
|
|
1433
1464
|
if (!upstreamFetchSpec) {
|
|
1434
1465
|
throw new Error(`Branch "${gitStatus.branch}" has no configured upstream.`);
|
|
1435
1466
|
}
|
|
1436
|
-
await
|
|
1467
|
+
await runGitRemoteTextAsync(['fetch', '--quiet', upstreamFetchSpec.remote, upstreamFetchSpec.branch], cwd);
|
|
1437
1468
|
await runGitTextAsync(['merge', '--no-edit', 'FETCH_HEAD'], cwd);
|
|
1438
1469
|
};
|
|
1439
1470
|
export const pullProjectBranch = async (project = null) => {
|
|
1440
1471
|
const repoPath = getRepoPath(project);
|
|
1441
|
-
const branchState = getProjectBranch(project, {
|
|
1472
|
+
const branchState = getProjectBranch(project, { includeDiffStats: false });
|
|
1442
1473
|
await pullGitBranch(repoPath, branchState.branch, project);
|
|
1443
1474
|
};
|
|
1444
1475
|
export const rebaseGitBranchOntoBase = async (cwd, branch = null, project = null, baseBranch = null) => {
|
|
1445
|
-
const gitStatus =
|
|
1476
|
+
const gitStatus = await getGitStatusAsync(cwd, branch, project, { refreshRemote: true });
|
|
1446
1477
|
const resolvedBaseBranch = baseBranch?.trim() || gitStatus.base_branch;
|
|
1447
1478
|
const rebaseDisabledReason = getRebaseDisabledReason(gitStatus, resolvedBaseBranch);
|
|
1448
1479
|
if (rebaseDisabledReason) {
|
|
@@ -1454,7 +1485,7 @@ export const rebaseGitBranchOntoBase = async (cwd, branch = null, project = null
|
|
|
1454
1485
|
if (!resolvedBaseBranch || resolvedBaseBranch === gitStatus.branch) {
|
|
1455
1486
|
throw new Error('No base branch is available for this target.');
|
|
1456
1487
|
}
|
|
1457
|
-
await
|
|
1488
|
+
await runGitRemoteTextAsync(['fetch', '--quiet', 'origin', resolvedBaseBranch], cwd);
|
|
1458
1489
|
await runGitTextAsync(['rebase', `origin/${resolvedBaseBranch}`], cwd);
|
|
1459
1490
|
if (project && resolve(cwd) !== getRepoPath(project)) {
|
|
1460
1491
|
const nextBaseCommit = resolveCommitBaseFromBaseRef(resolveNamedBranchRef(resolvedBaseBranch, cwd), cwd);
|
|
@@ -1633,9 +1664,6 @@ const applyGitActionState = (status, options) => {
|
|
|
1633
1664
|
export const getGitStatus = (cwd, branch = null, project = null, options = {}) => {
|
|
1634
1665
|
const recordedBase = branch && project ? resolveRecordedBaseForCwd(cwd, branch, project) : null;
|
|
1635
1666
|
const branchName = branch ?? resolveCurrentBranchName(cwd);
|
|
1636
|
-
if (branchName && (options.refreshRemote ?? false) && shouldRefreshProjectBranchTracking(getProjectBranchRefreshCacheKey(cwd, branchName), options.refreshRemote ?? false)) {
|
|
1637
|
-
refreshProjectBranchTracking(cwd, branchName);
|
|
1638
|
-
}
|
|
1639
1667
|
try {
|
|
1640
1668
|
const output = runGitText(['status', '--porcelain=v2', '--branch', '--untracked-files=all', '-z'], cwd);
|
|
1641
1669
|
const parsedOutput = parseGitStatusOutput(output);
|
|
@@ -1764,18 +1792,31 @@ const resolveFallbackBaseAsync = async (branch, project) => {
|
|
|
1764
1792
|
return null;
|
|
1765
1793
|
}
|
|
1766
1794
|
};
|
|
1767
|
-
const refreshProjectBranchTrackingAsync =
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
? ['fetch', '--quiet', fetchSpec.remote, fetchSpec.branch]
|
|
1773
|
-
: ['fetch', '--quiet', 'origin', branch];
|
|
1774
|
-
await runGitTextAsync(args, cwd, { timeoutMs: GIT_READ_TIMEOUT_MS });
|
|
1775
|
-
}
|
|
1776
|
-
catch {
|
|
1777
|
-
// Keep the last known tracking state when fetch is unavailable.
|
|
1795
|
+
const refreshProjectBranchTrackingAsync = (cwd, branch) => {
|
|
1796
|
+
const key = getProjectBranchRefreshCacheKey(cwd, branch);
|
|
1797
|
+
const existing = projectBranchRemoteRefreshes.get(key);
|
|
1798
|
+
if (existing) {
|
|
1799
|
+
return existing;
|
|
1778
1800
|
}
|
|
1801
|
+
const refresh = (async () => {
|
|
1802
|
+
try {
|
|
1803
|
+
const upstreamRef = await resolveBranchUpstreamRefAsync(branch, cwd);
|
|
1804
|
+
const fetchSpec = parseRemoteBranchRef(upstreamRef);
|
|
1805
|
+
const args = fetchSpec
|
|
1806
|
+
? ['fetch', '--quiet', fetchSpec.remote, fetchSpec.branch]
|
|
1807
|
+
: ['fetch', '--quiet', 'origin', branch];
|
|
1808
|
+
await runGitRemoteTextAsync(args, cwd);
|
|
1809
|
+
}
|
|
1810
|
+
catch {
|
|
1811
|
+
// Keep the last known tracking state when fetch is unavailable.
|
|
1812
|
+
}
|
|
1813
|
+
})().finally(() => {
|
|
1814
|
+
if (projectBranchRemoteRefreshes.get(key) === refresh) {
|
|
1815
|
+
projectBranchRemoteRefreshes.delete(key);
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
projectBranchRemoteRefreshes.set(key, refresh);
|
|
1819
|
+
return refresh;
|
|
1779
1820
|
};
|
|
1780
1821
|
const getUnreadableGitStatus = () => ({
|
|
1781
1822
|
branch: null,
|
|
@@ -1893,7 +1934,7 @@ export const getBoardGitStatus = (cwd, branch = null, project = null) => {
|
|
|
1893
1934
|
return getGitStatus(cwd, branch, project, {
|
|
1894
1935
|
refreshRemote: false,
|
|
1895
1936
|
includeFiles: false,
|
|
1896
|
-
includeWorkspaceSignature:
|
|
1937
|
+
includeWorkspaceSignature: true,
|
|
1897
1938
|
});
|
|
1898
1939
|
};
|
|
1899
1940
|
export const getBoardWorktreeGitStatus = (branch, project = null) => {
|
|
@@ -2168,7 +2209,7 @@ export const pushAutomationTarget = async (cwd, branch, targetSha, expectedOrigi
|
|
|
2168
2209
|
if (expectedOriginIdentity && getAutomationRemoteIdentity(cwd) !== expectedOriginIdentity) {
|
|
2169
2210
|
throw new Error('Automation origin remote changed after push intent was persisted');
|
|
2170
2211
|
}
|
|
2171
|
-
await
|
|
2212
|
+
await runGitRemoteTextAsync(['push', '-u', 'origin', `${targetSha}:refs/heads/${branch}`], cwd);
|
|
2172
2213
|
if (expectedOriginIdentity && getAutomationRemoteIdentity(cwd) !== expectedOriginIdentity) {
|
|
2173
2214
|
throw new Error('Automation origin remote changed while push was running');
|
|
2174
2215
|
}
|
|
@@ -2236,7 +2277,7 @@ export const fetchRemoteBranchState = async (cwd, branch, expectedOriginIdentity
|
|
|
2236
2277
|
}
|
|
2237
2278
|
let output;
|
|
2238
2279
|
try {
|
|
2239
|
-
output = await
|
|
2280
|
+
output = await runGitRemoteTextAsync(['ls-remote', '--exit-code', 'origin', `refs/heads/${branch}`], cwd);
|
|
2240
2281
|
}
|
|
2241
2282
|
catch (error) {
|
|
2242
2283
|
if (error.status === 2) {
|
|
@@ -2251,7 +2292,7 @@ export const fetchRemoteBranchState = async (cwd, branch, expectedOriginIdentity
|
|
|
2251
2292
|
if (!sha || !ref || extra || ref !== `refs/heads/${branch}` || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(sha)) {
|
|
2252
2293
|
throw new Error('Remote branch observation was incomplete');
|
|
2253
2294
|
}
|
|
2254
|
-
await
|
|
2295
|
+
await runGitRemoteTextAsync(['fetch', '--quiet', '--no-tags', 'origin', sha], cwd);
|
|
2255
2296
|
if (expectedOriginIdentity && getAutomationRemoteIdentity(cwd) !== expectedOriginIdentity) {
|
|
2256
2297
|
throw new Error('Automation origin remote changed while observing push state');
|
|
2257
2298
|
}
|