fifony 0.1.42 → 0.1.43
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/app/dist/assets/{CommandPalette-DNR5umI1.js → CommandPalette-M4VAMxCU.js} +1 -1
- package/app/dist/assets/{KeyboardShortcutsHelp-Dpl19F20.js → KeyboardShortcutsHelp-DkvPUXQq.js} +1 -1
- package/app/dist/assets/OnboardingWizard-B7V9hoCR.js +1 -0
- package/app/dist/assets/analytics.lazy-zVJdF880.js +1 -0
- package/app/dist/assets/{api-ChEctgc5.js → api-CkVfYg_m.js} +1 -1
- package/app/dist/assets/{createLucideIcon-R47sXufx.js → createLucideIcon-Dfk_Hxud.js} +1 -1
- package/app/dist/assets/index-BpiCi7Ew.css +1 -0
- package/app/dist/assets/index-D2INW0zc.js +47 -0
- package/app/dist/assets/vendor-BEoYbFV1.js +9 -0
- package/app/dist/index.html +5 -5
- package/app/dist/service-worker.js +9 -4
- package/bin/fifony.js +3 -0
- package/dist/agent/pty-daemon.js +177 -0
- package/dist/agent/run-local.js +177 -43
- package/dist/{agent-NNGZEKZH.js → agent-RMQTTUEC.js} +37 -16
- package/dist/analytics-broadcaster-O6YBP66L.js +145 -0
- package/dist/chunk-3NE23NYW.js +82 -0
- package/dist/chunk-42AMQAJG.js +404 -0
- package/dist/{chunk-H5N7O5NP.js → chunk-AILXZ2TD.js} +79 -147
- package/dist/{chunk-I2UHVKHS.js → chunk-BRSR26VK.js} +2 -2
- package/dist/chunk-E2EWEYA4.js +1302 -0
- package/dist/chunk-ESWHDHH6.js +102 -0
- package/dist/{chunk-NB44PCD2.js → chunk-FJNH3G2Z.js} +1061 -1138
- package/dist/chunk-MVTGAKQK.js +493 -0
- package/dist/chunk-QQQLP3PL.js +155 -0
- package/dist/chunk-SOBLO4YZ.js +2016 -0
- package/dist/chunk-YRSH2CLW.js +13784 -0
- package/dist/cli.js +335 -44
- package/dist/{issue-state-machine-GPQNZYUZ.js → fsm-issue-YGGF7SIL.js} +9 -5
- package/dist/helpers-L7NYO5XS.js +53 -0
- package/dist/issue-log-broadcaster-WZAHISYB.js +84 -0
- package/dist/{issues-MZLRSXD6.js → issues-3QRR7KM6.js} +10 -8
- package/dist/log-analyzer-K7MXQB4T.js +287 -0
- package/dist/mcp/server.js +109 -137
- package/dist/parallel-executor-6INE6NDO.js +118 -0
- package/dist/pid-manager-UBWXVSMD.js +21 -0
- package/dist/queue-workers-XFZK3TT5.js +32 -0
- package/dist/replan-issue.command-4UCWYHGZ.js +15 -0
- package/dist/scheduler-ZP7GOZDW.js +26 -0
- package/dist/{settings-NGY33WQE.js → settings-ZAWDCFP2.js} +32 -8
- package/dist/settings.resource-5CW456AZ.js +24 -0
- package/dist/store-M6NCKMZY.js +97 -0
- package/dist/{web-push-CRVDJKWR.js → web-push-AX5IIK3P.js} +2 -2
- package/dist/{workspace-D3F3XGSI.js → workspace-CJTWFWTJ.js} +5 -4
- package/package.json +8 -7
- package/app/dist/assets/OnboardingWizard-CijMhJDW.js +0 -1
- package/app/dist/assets/analytics.lazy-Dq90a756.js +0 -1
- package/app/dist/assets/index-Dy_fM427.js +0 -54
- package/app/dist/assets/index-Q9jBP0Pz.css +0 -1
- package/app/dist/assets/vendor-DkWeBvNl.js +0 -9
- package/dist/chunk-2CVTK5F2.js +0 -288
- package/dist/chunk-37N5OFHM.js +0 -125
- package/dist/chunk-JTKUWIQD.js +0 -8406
- package/dist/chunk-RBDBGU2C.js +0 -303
- package/dist/issue-runner-CMZPSVC7.js +0 -16
- package/dist/queue-workers-XZ6DGH4W.js +0 -23
- package/dist/scheduler-NVE6L3P7.js +0 -22
- package/dist/store-4HCGBN4L.js +0 -65
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import {
|
|
2
|
+
serializeReviewRouteSnapshot
|
|
3
|
+
} from "./chunk-FJNH3G2Z.js";
|
|
4
|
+
|
|
5
|
+
// src/domains/metrics.ts
|
|
6
|
+
function resolveAnalyticsReviewRun(issue) {
|
|
7
|
+
const reviewRuns = Array.isArray(issue.reviewRuns) ? issue.reviewRuns : [];
|
|
8
|
+
const completed = reviewRuns.filter((entry) => entry.status === "completed");
|
|
9
|
+
const candidates = completed.filter((entry) => entry.scope === "final");
|
|
10
|
+
const pool = candidates.length > 0 ? candidates : completed;
|
|
11
|
+
if (pool.length === 0) return null;
|
|
12
|
+
return [...pool].sort((left, right) => {
|
|
13
|
+
const leftAt = Date.parse(left.completedAt ?? left.startedAt);
|
|
14
|
+
const rightAt = Date.parse(right.completedAt ?? right.startedAt);
|
|
15
|
+
if (!Number.isNaN(leftAt) && !Number.isNaN(rightAt) && leftAt !== rightAt) return rightAt - leftAt;
|
|
16
|
+
return right.attempt - left.attempt;
|
|
17
|
+
})[0] ?? null;
|
|
18
|
+
}
|
|
19
|
+
function formatReviewerRoute(reviewRun) {
|
|
20
|
+
if (!reviewRun) return "unknown";
|
|
21
|
+
return serializeReviewRouteSnapshot(reviewRun.routing);
|
|
22
|
+
}
|
|
23
|
+
function resolveAnalyticsContractNegotiationRuns(issue) {
|
|
24
|
+
const runs = Array.isArray(issue.contractNegotiationRuns) ? issue.contractNegotiationRuns : [];
|
|
25
|
+
const completed = runs.filter((entry) => entry.status === "completed");
|
|
26
|
+
if (completed.length === 0) return [];
|
|
27
|
+
const latestPlanVersion = completed.reduce((maxPlanVersion, entry) => Math.max(maxPlanVersion, entry.planVersion ?? 0), 0);
|
|
28
|
+
return completed.filter((entry) => (entry.planVersion ?? 0) === latestPlanVersion).sort((left, right) => {
|
|
29
|
+
if ((left.attempt ?? 0) !== (right.attempt ?? 0)) return (left.attempt ?? 0) - (right.attempt ?? 0);
|
|
30
|
+
const leftAt = Date.parse(left.completedAt ?? left.startedAt);
|
|
31
|
+
const rightAt = Date.parse(right.completedAt ?? right.startedAt);
|
|
32
|
+
if (!Number.isNaN(leftAt) && !Number.isNaN(rightAt) && leftAt !== rightAt) return leftAt - rightAt;
|
|
33
|
+
return left.id.localeCompare(right.id);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function resolveAnalyticsCheckpointReviewRuns(issue) {
|
|
37
|
+
const reviewRuns = Array.isArray(issue.reviewRuns) ? issue.reviewRuns : [];
|
|
38
|
+
const completed = reviewRuns.filter((entry) => entry.status === "completed" && entry.scope === "checkpoint");
|
|
39
|
+
if (completed.length === 0) return [];
|
|
40
|
+
const latestPlanVersion = completed.reduce((maxPlanVersion, entry) => Math.max(maxPlanVersion, entry.planVersion ?? 0), 0);
|
|
41
|
+
return completed.filter((entry) => (entry.planVersion ?? 0) === latestPlanVersion).sort((left, right) => {
|
|
42
|
+
if ((left.attempt ?? 0) !== (right.attempt ?? 0)) return (left.attempt ?? 0) - (right.attempt ?? 0);
|
|
43
|
+
const leftAt = Date.parse(left.completedAt ?? left.startedAt);
|
|
44
|
+
const rightAt = Date.parse(right.completedAt ?? right.startedAt);
|
|
45
|
+
if (!Number.isNaN(leftAt) && !Number.isNaN(rightAt) && leftAt !== rightAt) return leftAt - rightAt;
|
|
46
|
+
return left.id.localeCompare(right.id);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function computeMetrics(issues) {
|
|
50
|
+
let planning = 0;
|
|
51
|
+
let queued = 0;
|
|
52
|
+
let inProgress = 0;
|
|
53
|
+
let blocked = 0;
|
|
54
|
+
let done = 0;
|
|
55
|
+
let merged = 0;
|
|
56
|
+
let cancelled = 0;
|
|
57
|
+
const completionTimes = [];
|
|
58
|
+
for (const issue of issues) {
|
|
59
|
+
if (issue.state === "Merged") {
|
|
60
|
+
const duration = issue.durationMs;
|
|
61
|
+
const candidate = typeof duration === "number" && Number.isFinite(duration) ? duration : Number.isFinite(Date.parse(issue.startedAt ?? "")) && Number.isFinite(Date.parse(issue.completedAt ?? "")) ? Date.parse(issue.completedAt) - Date.parse(issue.startedAt) : NaN;
|
|
62
|
+
if (Number.isFinite(candidate) && candidate >= 0) {
|
|
63
|
+
completionTimes.push(candidate);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
switch (issue.state) {
|
|
67
|
+
case "Planning":
|
|
68
|
+
planning += 1;
|
|
69
|
+
break;
|
|
70
|
+
case "PendingApproval":
|
|
71
|
+
queued += 1;
|
|
72
|
+
break;
|
|
73
|
+
case "Queued":
|
|
74
|
+
case "Running":
|
|
75
|
+
case "Reviewing":
|
|
76
|
+
case "PendingDecision":
|
|
77
|
+
inProgress += 1;
|
|
78
|
+
break;
|
|
79
|
+
case "Blocked":
|
|
80
|
+
blocked += 1;
|
|
81
|
+
break;
|
|
82
|
+
case "Approved":
|
|
83
|
+
done += 1;
|
|
84
|
+
break;
|
|
85
|
+
case "Merged":
|
|
86
|
+
merged += 1;
|
|
87
|
+
break;
|
|
88
|
+
case "Cancelled":
|
|
89
|
+
cancelled += 1;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (completionTimes.length === 0) {
|
|
94
|
+
return {
|
|
95
|
+
total: issues.length,
|
|
96
|
+
planning,
|
|
97
|
+
queued,
|
|
98
|
+
inProgress,
|
|
99
|
+
blocked,
|
|
100
|
+
done,
|
|
101
|
+
merged,
|
|
102
|
+
cancelled,
|
|
103
|
+
activeWorkers: 0
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const sortedCompletionTimes = completionTimes.slice().sort((a, b) => a - b);
|
|
107
|
+
const totalCompletionMs = sortedCompletionTimes.reduce((acc, value) => acc + value, 0);
|
|
108
|
+
const mid = Math.floor(sortedCompletionTimes.length / 2);
|
|
109
|
+
const medianCompletionMs = sortedCompletionTimes.length % 2 === 1 ? sortedCompletionTimes[mid] : Math.round((sortedCompletionTimes[mid - 1] + sortedCompletionTimes[mid]) / 2);
|
|
110
|
+
return {
|
|
111
|
+
total: issues.length,
|
|
112
|
+
planning,
|
|
113
|
+
queued,
|
|
114
|
+
inProgress,
|
|
115
|
+
blocked,
|
|
116
|
+
done,
|
|
117
|
+
merged,
|
|
118
|
+
cancelled,
|
|
119
|
+
activeWorkers: 0,
|
|
120
|
+
avgCompletionMs: Math.round(totalCompletionMs / completionTimes.length),
|
|
121
|
+
medianCompletionMs,
|
|
122
|
+
fastestCompletionMs: sortedCompletionTimes[0],
|
|
123
|
+
slowestCompletionMs: sortedCompletionTimes[sortedCompletionTimes.length - 1]
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function computeQualityGateMetrics(issues) {
|
|
127
|
+
const reviewedIssues = issues.filter(
|
|
128
|
+
(issue) => (issue.reviewAttempt ?? 0) > 0 || !!issue.gradingReport || !!issue.reviewingAt
|
|
129
|
+
);
|
|
130
|
+
const completedReviewedIssues = reviewedIssues.filter((issue) => issue.state === "Approved" || issue.state === "Merged");
|
|
131
|
+
const reviewReworkIssues = reviewedIssues.filter(
|
|
132
|
+
(issue) => (issue.previousAttemptSummaries ?? []).some((summary) => summary.phase === "review")
|
|
133
|
+
);
|
|
134
|
+
const firstPassPasses = completedReviewedIssues.filter(
|
|
135
|
+
(issue) => (issue.reviewAttempt ?? 0) <= 1 && !(issue.previousAttemptSummaries ?? []).some((summary) => summary.phase === "review")
|
|
136
|
+
);
|
|
137
|
+
const criteriaByCategory = {};
|
|
138
|
+
const byReviewerRoute = {};
|
|
139
|
+
const byReviewProfile = {
|
|
140
|
+
"general-quality": { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 },
|
|
141
|
+
"ui-polish": { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 },
|
|
142
|
+
"workflow-fsm": { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 },
|
|
143
|
+
"integration-safety": { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 },
|
|
144
|
+
"api-contract": { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 },
|
|
145
|
+
"security-hardening": { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 },
|
|
146
|
+
unknown: { reviewedIssues: 0, completedReviewedIssues: 0, failedCriteria: 0, blockingFailedCriteria: 0, advisoryFailedCriteria: 0 }
|
|
147
|
+
};
|
|
148
|
+
const contractNegotiationByProfile = {
|
|
149
|
+
"general-quality": { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 },
|
|
150
|
+
"ui-polish": { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 },
|
|
151
|
+
"workflow-fsm": { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 },
|
|
152
|
+
"integration-safety": { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 },
|
|
153
|
+
"api-contract": { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 },
|
|
154
|
+
"security-hardening": { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 },
|
|
155
|
+
unknown: { negotiatedIssues: 0, approvedIssues: 0, firstPassApprovals: 0, revisedIssues: 0, blockingConcernIssues: 0, totalRounds: 0 }
|
|
156
|
+
};
|
|
157
|
+
const byHarnessMode = {
|
|
158
|
+
solo: { reviewedIssues: 0, completedReviewedIssues: 0, reworkIssues: 0, firstPassPasses: 0, totalCriteria: 0, failedCriteria: 0, advisoryFailedCriteria: 0, blockingFailedCriteria: 0 },
|
|
159
|
+
standard: { reviewedIssues: 0, completedReviewedIssues: 0, reworkIssues: 0, firstPassPasses: 0, totalCriteria: 0, failedCriteria: 0, advisoryFailedCriteria: 0, blockingFailedCriteria: 0 },
|
|
160
|
+
contractual: { reviewedIssues: 0, completedReviewedIssues: 0, reworkIssues: 0, firstPassPasses: 0, totalCriteria: 0, failedCriteria: 0, advisoryFailedCriteria: 0, blockingFailedCriteria: 0 }
|
|
161
|
+
};
|
|
162
|
+
const byCheckpointPolicy = {
|
|
163
|
+
final_only: {
|
|
164
|
+
reviewedIssues: 0,
|
|
165
|
+
completedReviewedIssues: 0,
|
|
166
|
+
gatePasses: 0,
|
|
167
|
+
firstPassPasses: 0,
|
|
168
|
+
reworkIssues: 0,
|
|
169
|
+
checkpointRuns: 0,
|
|
170
|
+
checkpointPassedIssues: 0,
|
|
171
|
+
checkpointFailedIssues: 0
|
|
172
|
+
},
|
|
173
|
+
checkpointed: {
|
|
174
|
+
reviewedIssues: 0,
|
|
175
|
+
completedReviewedIssues: 0,
|
|
176
|
+
gatePasses: 0,
|
|
177
|
+
firstPassPasses: 0,
|
|
178
|
+
reworkIssues: 0,
|
|
179
|
+
checkpointRuns: 0,
|
|
180
|
+
checkpointPassedIssues: 0,
|
|
181
|
+
checkpointFailedIssues: 0
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
let totalCriteria = 0;
|
|
185
|
+
let failedCriteria = 0;
|
|
186
|
+
let blockingFailedCriteria = 0;
|
|
187
|
+
let advisoryFailedCriteria = 0;
|
|
188
|
+
const contractNegotiationSummary = {
|
|
189
|
+
negotiatedIssues: 0,
|
|
190
|
+
approvedIssues: 0,
|
|
191
|
+
firstPassApprovals: 0,
|
|
192
|
+
revisedIssues: 0,
|
|
193
|
+
blockingConcernIssues: 0,
|
|
194
|
+
totalRounds: 0
|
|
195
|
+
};
|
|
196
|
+
const policyDecisionSummary = {
|
|
197
|
+
total: 0,
|
|
198
|
+
harnessModeChanges: 0,
|
|
199
|
+
checkpointPolicyChanges: 0,
|
|
200
|
+
reviewRecoveryReplans: 0,
|
|
201
|
+
byKind: {
|
|
202
|
+
"harness-mode": 0,
|
|
203
|
+
"checkpoint-policy": 0,
|
|
204
|
+
"review-recovery": 0
|
|
205
|
+
},
|
|
206
|
+
byBasis: {
|
|
207
|
+
historical: 0,
|
|
208
|
+
heuristic: 0,
|
|
209
|
+
runtime: 0
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
const memoryPipeline = {
|
|
213
|
+
issuesWithMemoryFlushes: 0,
|
|
214
|
+
totalMemoryFlushes: 0,
|
|
215
|
+
issuesWithContextReports: 0,
|
|
216
|
+
issuesWithStageReports: 0,
|
|
217
|
+
issuesWithCompaction: 0,
|
|
218
|
+
byRole: {
|
|
219
|
+
planner: { reports: 0, selectedHits: 0, totalHits: 0, discardedHits: 0 },
|
|
220
|
+
executor: { reports: 0, selectedHits: 0, totalHits: 0, discardedHits: 0 },
|
|
221
|
+
reviewer: { reports: 0, selectedHits: 0, totalHits: 0, discardedHits: 0 }
|
|
222
|
+
},
|
|
223
|
+
byLayer: {
|
|
224
|
+
bootstrap: { hitCount: 0, selectedHitCount: 0, discardedHitCount: 0 },
|
|
225
|
+
"workspace-memory": { hitCount: 0, selectedHitCount: 0, discardedHitCount: 0 },
|
|
226
|
+
"issue-memory": { hitCount: 0, selectedHitCount: 0, discardedHitCount: 0 },
|
|
227
|
+
retrieval: { hitCount: 0, selectedHitCount: 0, discardedHitCount: 0 }
|
|
228
|
+
},
|
|
229
|
+
byStage: {
|
|
230
|
+
ingest: { reports: 0, completed: 0, skipped: 0, totalDurationMs: 0, totalInputCount: 0, totalOutputCount: 0, budgetedRuns: 0, totalBudgetLimit: 0 },
|
|
231
|
+
"flush-memory": { reports: 0, completed: 0, skipped: 0, totalDurationMs: 0, totalInputCount: 0, totalOutputCount: 0, budgetedRuns: 0, totalBudgetLimit: 0 },
|
|
232
|
+
retrieve: { reports: 0, completed: 0, skipped: 0, totalDurationMs: 0, totalInputCount: 0, totalOutputCount: 0, budgetedRuns: 0, totalBudgetLimit: 0 },
|
|
233
|
+
budget: { reports: 0, completed: 0, skipped: 0, totalDurationMs: 0, totalInputCount: 0, totalOutputCount: 0, budgetedRuns: 0, totalBudgetLimit: 0 },
|
|
234
|
+
compact: { reports: 0, completed: 0, skipped: 0, totalDurationMs: 0, totalInputCount: 0, totalOutputCount: 0, budgetedRuns: 0, totalBudgetLimit: 0 },
|
|
235
|
+
assemble: { reports: 0, completed: 0, skipped: 0, totalDurationMs: 0, totalInputCount: 0, totalOutputCount: 0, budgetedRuns: 0, totalBudgetLimit: 0 }
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
for (const issue of reviewedIssues) {
|
|
239
|
+
const harnessMode = issue.plan?.harnessMode ?? "standard";
|
|
240
|
+
const harnessBucket = byHarnessMode[harnessMode];
|
|
241
|
+
const checkpointPolicy = issue.plan?.executionContract?.checkpointPolicy === "checkpointed" ? "checkpointed" : "final_only";
|
|
242
|
+
const checkpointBucket = byCheckpointPolicy[checkpointPolicy];
|
|
243
|
+
const reviewProfile = issue.reviewProfile?.primary ?? "unknown";
|
|
244
|
+
const reviewProfileBucket = byReviewProfile[reviewProfile];
|
|
245
|
+
const reviewRouteKey = formatReviewerRoute(resolveAnalyticsReviewRun(issue));
|
|
246
|
+
const reviewRouteBucket = byReviewerRoute[reviewRouteKey] ||= {
|
|
247
|
+
reviewedIssues: 0,
|
|
248
|
+
completedReviewedIssues: 0,
|
|
249
|
+
failedCriteria: 0,
|
|
250
|
+
blockingFailedCriteria: 0,
|
|
251
|
+
advisoryFailedCriteria: 0
|
|
252
|
+
};
|
|
253
|
+
harnessBucket.reviewedIssues += 1;
|
|
254
|
+
if (harnessMode === "contractual") checkpointBucket.reviewedIssues += 1;
|
|
255
|
+
reviewProfileBucket.reviewedIssues += 1;
|
|
256
|
+
reviewRouteBucket.reviewedIssues += 1;
|
|
257
|
+
if (issue.state === "Approved" || issue.state === "Merged") harnessBucket.completedReviewedIssues += 1;
|
|
258
|
+
if ((issue.state === "Approved" || issue.state === "Merged") && harnessMode === "contractual") checkpointBucket.completedReviewedIssues += 1;
|
|
259
|
+
if (issue.state === "Approved" || issue.state === "Merged") reviewProfileBucket.completedReviewedIssues += 1;
|
|
260
|
+
if (issue.state === "Approved" || issue.state === "Merged") reviewRouteBucket.completedReviewedIssues += 1;
|
|
261
|
+
if ((issue.previousAttemptSummaries ?? []).some((summary) => summary.phase === "review")) harnessBucket.reworkIssues += 1;
|
|
262
|
+
if ((issue.previousAttemptSummaries ?? []).some((summary) => summary.phase === "review") && harnessMode === "contractual") checkpointBucket.reworkIssues += 1;
|
|
263
|
+
if ((issue.reviewAttempt ?? 0) <= 1 && !(issue.previousAttemptSummaries ?? []).some((summary) => summary.phase === "review")) {
|
|
264
|
+
harnessBucket.firstPassPasses += 1;
|
|
265
|
+
if (harnessMode === "contractual" && (issue.state === "Approved" || issue.state === "Merged")) checkpointBucket.firstPassPasses += 1;
|
|
266
|
+
}
|
|
267
|
+
const finalReviewRun = resolveAnalyticsReviewRun(issue);
|
|
268
|
+
if (finalReviewRun?.blockingVerdict === "PASS" && harnessMode === "contractual") checkpointBucket.gatePasses += 1;
|
|
269
|
+
if (harnessMode === "contractual" && checkpointPolicy === "checkpointed") {
|
|
270
|
+
const checkpointRuns = resolveAnalyticsCheckpointReviewRuns(issue);
|
|
271
|
+
checkpointBucket.checkpointRuns += checkpointRuns.length;
|
|
272
|
+
if (checkpointRuns.some((entry) => entry.blockingVerdict === "PASS")) checkpointBucket.checkpointPassedIssues += 1;
|
|
273
|
+
if (checkpointRuns.some((entry) => entry.blockingVerdict === "FAIL")) checkpointBucket.checkpointFailedIssues += 1;
|
|
274
|
+
}
|
|
275
|
+
for (const criterion of issue.gradingReport?.criteria ?? []) {
|
|
276
|
+
totalCriteria += 1;
|
|
277
|
+
harnessBucket.totalCriteria += 1;
|
|
278
|
+
if (criterion.result === "FAIL") {
|
|
279
|
+
failedCriteria += 1;
|
|
280
|
+
harnessBucket.failedCriteria += 1;
|
|
281
|
+
reviewProfileBucket.failedCriteria += 1;
|
|
282
|
+
reviewRouteBucket.failedCriteria += 1;
|
|
283
|
+
if (criterion.blocking) {
|
|
284
|
+
blockingFailedCriteria += 1;
|
|
285
|
+
harnessBucket.blockingFailedCriteria += 1;
|
|
286
|
+
reviewProfileBucket.blockingFailedCriteria += 1;
|
|
287
|
+
reviewRouteBucket.blockingFailedCriteria += 1;
|
|
288
|
+
} else {
|
|
289
|
+
advisoryFailedCriteria += 1;
|
|
290
|
+
harnessBucket.advisoryFailedCriteria += 1;
|
|
291
|
+
reviewProfileBucket.advisoryFailedCriteria += 1;
|
|
292
|
+
reviewRouteBucket.advisoryFailedCriteria += 1;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const bucket = criteriaByCategory[criterion.category] ||= { pass: 0, fail: 0, skip: 0 };
|
|
296
|
+
if (criterion.result === "PASS") bucket.pass += 1;
|
|
297
|
+
if (criterion.result === "FAIL") bucket.fail += 1;
|
|
298
|
+
if (criterion.result === "SKIP") bucket.skip += 1;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
for (const issue of issues) {
|
|
302
|
+
if ((issue.memoryFlushCount ?? 0) > 0) {
|
|
303
|
+
memoryPipeline.issuesWithMemoryFlushes += 1;
|
|
304
|
+
memoryPipeline.totalMemoryFlushes += issue.memoryFlushCount ?? 0;
|
|
305
|
+
}
|
|
306
|
+
const contextReportsByRole = issue.contextReportsByRole ?? {};
|
|
307
|
+
const roles = Object.entries(contextReportsByRole).filter(([, report]) => report && typeof report === "object");
|
|
308
|
+
if (roles.length > 0) {
|
|
309
|
+
memoryPipeline.issuesWithContextReports += 1;
|
|
310
|
+
}
|
|
311
|
+
let stageReportsRecorded = false;
|
|
312
|
+
let compactionObserved = false;
|
|
313
|
+
for (const [role, report] of roles) {
|
|
314
|
+
if (!(role in memoryPipeline.byRole) || !report) continue;
|
|
315
|
+
const roleBucket = memoryPipeline.byRole[role];
|
|
316
|
+
roleBucket.reports += 1;
|
|
317
|
+
roleBucket.selectedHits += report.selectedHits ?? 0;
|
|
318
|
+
roleBucket.totalHits += report.totalHits ?? 0;
|
|
319
|
+
roleBucket.discardedHits += report.discardedHits ?? 0;
|
|
320
|
+
for (const layer of report.layers ?? []) {
|
|
321
|
+
if (!(layer.name in memoryPipeline.byLayer)) continue;
|
|
322
|
+
const layerBucket = memoryPipeline.byLayer[layer.name];
|
|
323
|
+
layerBucket.hitCount += layer.hitCount ?? 0;
|
|
324
|
+
layerBucket.selectedHitCount += layer.selectedHitCount ?? 0;
|
|
325
|
+
layerBucket.discardedHitCount += layer.discardedHitCount ?? 0;
|
|
326
|
+
}
|
|
327
|
+
for (const stage of report.stages ?? []) {
|
|
328
|
+
if (!(stage.name in memoryPipeline.byStage)) continue;
|
|
329
|
+
const stageBucket = memoryPipeline.byStage[stage.name];
|
|
330
|
+
stageBucket.reports += 1;
|
|
331
|
+
if (stage.status === "completed") stageBucket.completed += 1;
|
|
332
|
+
if (stage.status === "skipped") stageBucket.skipped += 1;
|
|
333
|
+
stageBucket.totalDurationMs += stage.durationMs ?? 0;
|
|
334
|
+
stageBucket.totalInputCount += stage.inputCount ?? 0;
|
|
335
|
+
stageBucket.totalOutputCount += stage.outputCount ?? 0;
|
|
336
|
+
if (typeof stage.budgetLimit === "number") {
|
|
337
|
+
stageBucket.budgetedRuns += 1;
|
|
338
|
+
stageBucket.totalBudgetLimit += stage.budgetLimit;
|
|
339
|
+
}
|
|
340
|
+
stageReportsRecorded = true;
|
|
341
|
+
if (stage.name === "compact" && stage.status === "completed") compactionObserved = true;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (stageReportsRecorded) {
|
|
345
|
+
memoryPipeline.issuesWithStageReports += 1;
|
|
346
|
+
}
|
|
347
|
+
if (compactionObserved) {
|
|
348
|
+
memoryPipeline.issuesWithCompaction += 1;
|
|
349
|
+
}
|
|
350
|
+
const negotiationRuns = resolveAnalyticsContractNegotiationRuns(issue);
|
|
351
|
+
if (negotiationRuns.length === 0) continue;
|
|
352
|
+
const latestRun = negotiationRuns[negotiationRuns.length - 1];
|
|
353
|
+
const profileName = latestRun.reviewProfile?.primary ?? "unknown";
|
|
354
|
+
const bucket = contractNegotiationByProfile[profileName];
|
|
355
|
+
contractNegotiationSummary.negotiatedIssues += 1;
|
|
356
|
+
contractNegotiationSummary.totalRounds += negotiationRuns.length;
|
|
357
|
+
bucket.negotiatedIssues += 1;
|
|
358
|
+
bucket.totalRounds += negotiationRuns.length;
|
|
359
|
+
if (latestRun.decisionStatus === "approved") {
|
|
360
|
+
contractNegotiationSummary.approvedIssues += 1;
|
|
361
|
+
bucket.approvedIssues += 1;
|
|
362
|
+
}
|
|
363
|
+
if (negotiationRuns.length === 1 && negotiationRuns[0]?.decisionStatus === "approved") {
|
|
364
|
+
contractNegotiationSummary.firstPassApprovals += 1;
|
|
365
|
+
bucket.firstPassApprovals += 1;
|
|
366
|
+
}
|
|
367
|
+
if (negotiationRuns.some((entry) => entry.decisionStatus === "revise" || entry.appliedRefinement)) {
|
|
368
|
+
contractNegotiationSummary.revisedIssues += 1;
|
|
369
|
+
bucket.revisedIssues += 1;
|
|
370
|
+
}
|
|
371
|
+
if (negotiationRuns.some((entry) => (entry.blockingConcernsCount ?? 0) > 0)) {
|
|
372
|
+
contractNegotiationSummary.blockingConcernIssues += 1;
|
|
373
|
+
bucket.blockingConcernIssues += 1;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
for (const issue of issues) {
|
|
377
|
+
for (const decision of issue.policyDecisions ?? []) {
|
|
378
|
+
policyDecisionSummary.total += 1;
|
|
379
|
+
if (decision.kind === "harness-mode") policyDecisionSummary.harnessModeChanges += 1;
|
|
380
|
+
if (decision.kind === "checkpoint-policy") policyDecisionSummary.checkpointPolicyChanges += 1;
|
|
381
|
+
if (decision.kind === "review-recovery" && decision.to === "replan") {
|
|
382
|
+
policyDecisionSummary.reviewRecoveryReplans += 1;
|
|
383
|
+
}
|
|
384
|
+
if (decision.kind in policyDecisionSummary.byKind) {
|
|
385
|
+
policyDecisionSummary.byKind[decision.kind] += 1;
|
|
386
|
+
}
|
|
387
|
+
if (decision.basis in policyDecisionSummary.byBasis) {
|
|
388
|
+
policyDecisionSummary.byBasis[decision.basis] += 1;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const average = (values) => values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null;
|
|
393
|
+
const finalizeContractBucket = (bucket) => ({
|
|
394
|
+
...bucket,
|
|
395
|
+
approvalRate: bucket.negotiatedIssues ? bucket.approvedIssues / bucket.negotiatedIssues : null,
|
|
396
|
+
firstPassApprovalRate: bucket.negotiatedIssues ? bucket.firstPassApprovals / bucket.negotiatedIssues : null,
|
|
397
|
+
revisionRate: bucket.negotiatedIssues ? bucket.revisedIssues / bucket.negotiatedIssues : null,
|
|
398
|
+
blockingConcernRate: bucket.negotiatedIssues ? bucket.blockingConcernIssues / bucket.negotiatedIssues : null,
|
|
399
|
+
avgRoundsPerIssue: bucket.negotiatedIssues ? bucket.totalRounds / bucket.negotiatedIssues : null
|
|
400
|
+
});
|
|
401
|
+
const finalizeCheckpointBucket = (bucket) => ({
|
|
402
|
+
...bucket,
|
|
403
|
+
gatePassRate: bucket.reviewedIssues ? bucket.gatePasses / bucket.reviewedIssues : null,
|
|
404
|
+
firstPassReviewPassRate: bucket.completedReviewedIssues ? bucket.firstPassPasses / bucket.completedReviewedIssues : null,
|
|
405
|
+
reviewReworkRate: bucket.reviewedIssues ? bucket.reworkIssues / bucket.reviewedIssues : null,
|
|
406
|
+
checkpointCatchRate: bucket.reviewedIssues ? bucket.checkpointFailedIssues / bucket.reviewedIssues : null,
|
|
407
|
+
checkpointPassRate: bucket.reviewedIssues ? bucket.checkpointPassedIssues / bucket.reviewedIssues : null,
|
|
408
|
+
avgCheckpointRunsPerIssue: bucket.reviewedIssues ? bucket.checkpointRuns / bucket.reviewedIssues : null
|
|
409
|
+
});
|
|
410
|
+
const finalizeStageBucket = (bucket) => ({
|
|
411
|
+
...bucket,
|
|
412
|
+
completionRate: bucket.reports ? bucket.completed / bucket.reports : null,
|
|
413
|
+
avgDurationMs: bucket.reports ? bucket.totalDurationMs / bucket.reports : null,
|
|
414
|
+
avgInputCount: bucket.reports ? bucket.totalInputCount / bucket.reports : null,
|
|
415
|
+
avgOutputCount: bucket.reports ? bucket.totalOutputCount / bucket.reports : null,
|
|
416
|
+
avgBudgetLimit: bucket.budgetedRuns ? bucket.totalBudgetLimit / bucket.budgetedRuns : null
|
|
417
|
+
});
|
|
418
|
+
return {
|
|
419
|
+
reviewedIssues: reviewedIssues.length,
|
|
420
|
+
completedReviewedIssues: completedReviewedIssues.length,
|
|
421
|
+
reviewReworkRate: reviewedIssues.length ? reviewReworkIssues.length / reviewedIssues.length : null,
|
|
422
|
+
firstPassReviewPassRate: completedReviewedIssues.length ? firstPassPasses.length / completedReviewedIssues.length : null,
|
|
423
|
+
avgReviewAttempts: average(reviewedIssues.map((issue) => issue.reviewAttempt ?? 0)),
|
|
424
|
+
avgExecuteAttempts: average(reviewedIssues.map((issue) => issue.executeAttempt ?? 0)),
|
|
425
|
+
totalCriteria,
|
|
426
|
+
failedCriteria,
|
|
427
|
+
blockingFailedCriteria,
|
|
428
|
+
advisoryFailedCriteria,
|
|
429
|
+
criteriaFailureRate: totalCriteria ? failedCriteria / totalCriteria : null,
|
|
430
|
+
criteriaByCategory,
|
|
431
|
+
contractNegotiation: {
|
|
432
|
+
...finalizeContractBucket(contractNegotiationSummary),
|
|
433
|
+
byReviewProfile: {
|
|
434
|
+
"general-quality": finalizeContractBucket(contractNegotiationByProfile["general-quality"]),
|
|
435
|
+
"ui-polish": finalizeContractBucket(contractNegotiationByProfile["ui-polish"]),
|
|
436
|
+
"workflow-fsm": finalizeContractBucket(contractNegotiationByProfile["workflow-fsm"]),
|
|
437
|
+
"integration-safety": finalizeContractBucket(contractNegotiationByProfile["integration-safety"]),
|
|
438
|
+
"api-contract": finalizeContractBucket(contractNegotiationByProfile["api-contract"]),
|
|
439
|
+
"security-hardening": finalizeContractBucket(contractNegotiationByProfile["security-hardening"]),
|
|
440
|
+
unknown: finalizeContractBucket(contractNegotiationByProfile.unknown)
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
checkpointPolicy: {
|
|
444
|
+
final_only: finalizeCheckpointBucket(byCheckpointPolicy.final_only),
|
|
445
|
+
checkpointed: finalizeCheckpointBucket(byCheckpointPolicy.checkpointed)
|
|
446
|
+
},
|
|
447
|
+
memoryPipeline: {
|
|
448
|
+
...memoryPipeline,
|
|
449
|
+
memoryFlushCoverageRate: issues.length ? memoryPipeline.issuesWithMemoryFlushes / issues.length : null,
|
|
450
|
+
contextReportCoverageRate: issues.length ? memoryPipeline.issuesWithContextReports / issues.length : null,
|
|
451
|
+
stageReportCoverageRate: issues.length ? memoryPipeline.issuesWithStageReports / issues.length : null,
|
|
452
|
+
compactionCoverageRate: issues.length ? memoryPipeline.issuesWithCompaction / issues.length : null,
|
|
453
|
+
avgFlushesPerIssueWithMemory: memoryPipeline.issuesWithMemoryFlushes ? memoryPipeline.totalMemoryFlushes / memoryPipeline.issuesWithMemoryFlushes : null,
|
|
454
|
+
byStage: {
|
|
455
|
+
ingest: finalizeStageBucket(memoryPipeline.byStage.ingest),
|
|
456
|
+
"flush-memory": finalizeStageBucket(memoryPipeline.byStage["flush-memory"]),
|
|
457
|
+
retrieve: finalizeStageBucket(memoryPipeline.byStage.retrieve),
|
|
458
|
+
budget: finalizeStageBucket(memoryPipeline.byStage.budget),
|
|
459
|
+
compact: finalizeStageBucket(memoryPipeline.byStage.compact),
|
|
460
|
+
assemble: finalizeStageBucket(memoryPipeline.byStage.assemble)
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
policyDecisions: policyDecisionSummary,
|
|
464
|
+
byReviewProfile,
|
|
465
|
+
byReviewerRoute,
|
|
466
|
+
byHarnessMode: {
|
|
467
|
+
solo: {
|
|
468
|
+
...byHarnessMode.solo,
|
|
469
|
+
reviewReworkRate: byHarnessMode.solo.reviewedIssues ? byHarnessMode.solo.reworkIssues / byHarnessMode.solo.reviewedIssues : null,
|
|
470
|
+
firstPassReviewPassRate: byHarnessMode.solo.completedReviewedIssues ? byHarnessMode.solo.firstPassPasses / byHarnessMode.solo.completedReviewedIssues : null,
|
|
471
|
+
criteriaFailureRate: byHarnessMode.solo.totalCriteria ? byHarnessMode.solo.failedCriteria / byHarnessMode.solo.totalCriteria : null
|
|
472
|
+
},
|
|
473
|
+
standard: {
|
|
474
|
+
...byHarnessMode.standard,
|
|
475
|
+
reviewReworkRate: byHarnessMode.standard.reviewedIssues ? byHarnessMode.standard.reworkIssues / byHarnessMode.standard.reviewedIssues : null,
|
|
476
|
+
firstPassReviewPassRate: byHarnessMode.standard.completedReviewedIssues ? byHarnessMode.standard.firstPassPasses / byHarnessMode.standard.completedReviewedIssues : null,
|
|
477
|
+
criteriaFailureRate: byHarnessMode.standard.totalCriteria ? byHarnessMode.standard.failedCriteria / byHarnessMode.standard.totalCriteria : null
|
|
478
|
+
},
|
|
479
|
+
contractual: {
|
|
480
|
+
...byHarnessMode.contractual,
|
|
481
|
+
reviewReworkRate: byHarnessMode.contractual.reviewedIssues ? byHarnessMode.contractual.reworkIssues / byHarnessMode.contractual.reviewedIssues : null,
|
|
482
|
+
firstPassReviewPassRate: byHarnessMode.contractual.completedReviewedIssues ? byHarnessMode.contractual.firstPassPasses / byHarnessMode.contractual.completedReviewedIssues : null,
|
|
483
|
+
criteriaFailureRate: byHarnessMode.contractual.totalCriteria ? byHarnessMode.contractual.failedCriteria / byHarnessMode.contractual.totalCriteria : null
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export {
|
|
490
|
+
computeMetrics,
|
|
491
|
+
computeQualityGateMetrics
|
|
492
|
+
};
|
|
493
|
+
//# sourceMappingURL=chunk-MVTGAKQK.js.map
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ISSUE_STATE_MACHINE_ID,
|
|
3
|
+
findIssueStateMachineTransitionPath,
|
|
4
|
+
getIssueResourceStateApi,
|
|
5
|
+
getIssueStateMachinePlugin,
|
|
6
|
+
getIssueTransitionHistory,
|
|
7
|
+
getStateMachineTransitions,
|
|
8
|
+
visualizeStateMachine
|
|
9
|
+
} from "./chunk-AILXZ2TD.js";
|
|
10
|
+
import {
|
|
11
|
+
transitionIssue
|
|
12
|
+
} from "./chunk-E2EWEYA4.js";
|
|
13
|
+
import {
|
|
14
|
+
markIssueDirty
|
|
15
|
+
} from "./chunk-FJNH3G2Z.js";
|
|
16
|
+
import {
|
|
17
|
+
logger
|
|
18
|
+
} from "./chunk-DVU3CXWA.js";
|
|
19
|
+
import {
|
|
20
|
+
TERMINAL_STATES,
|
|
21
|
+
now
|
|
22
|
+
} from "./chunk-42AMQAJG.js";
|
|
23
|
+
|
|
24
|
+
// src/domains/issue-state.ts
|
|
25
|
+
function syncIssueStateInMemory(issue, targetState, options = {}) {
|
|
26
|
+
const previousState = issue.state;
|
|
27
|
+
if (previousState === targetState) {
|
|
28
|
+
return {
|
|
29
|
+
changed: false,
|
|
30
|
+
previousState,
|
|
31
|
+
currentState: issue.state
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
issue.state = targetState;
|
|
35
|
+
issue.updatedAt = now();
|
|
36
|
+
issue.history.push(
|
|
37
|
+
`[${issue.updatedAt}] ${options.reason ?? `Issue state synchronized in memory from ${previousState} to ${targetState}.`}`
|
|
38
|
+
);
|
|
39
|
+
markIssueDirty(issue.id);
|
|
40
|
+
return {
|
|
41
|
+
changed: true,
|
|
42
|
+
previousState,
|
|
43
|
+
currentState: targetState
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function syncIssueStateFromFsm(issue, options = {}) {
|
|
47
|
+
const sourceState = await getIssueStateMachineState(issue.id);
|
|
48
|
+
if (!sourceState) {
|
|
49
|
+
return {
|
|
50
|
+
changed: false,
|
|
51
|
+
previousState: issue.state,
|
|
52
|
+
currentState: issue.state
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return syncIssueStateInMemory(issue, sourceState, {
|
|
56
|
+
reason: options.reason ?? `Issue state synchronized from FSM source of truth to ${sourceState}.`
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function getIssueStateMachineTransitions() {
|
|
60
|
+
return getStateMachineTransitions();
|
|
61
|
+
}
|
|
62
|
+
function getIssueStateMachineVisualization() {
|
|
63
|
+
return visualizeStateMachine();
|
|
64
|
+
}
|
|
65
|
+
async function getIssueTransitionHistoryForIssue(issueId, options) {
|
|
66
|
+
return getIssueTransitionHistory(issueId, options);
|
|
67
|
+
}
|
|
68
|
+
function getIssueStateMachineTransitionPath(currentState, targetState) {
|
|
69
|
+
return findIssueStateMachineTransitionPath(null, currentState, targetState);
|
|
70
|
+
}
|
|
71
|
+
async function getIssueStateMachineState(issueId) {
|
|
72
|
+
const plugin = getIssueStateMachinePlugin();
|
|
73
|
+
if (!plugin?.getState) return null;
|
|
74
|
+
try {
|
|
75
|
+
const state = await plugin.getState(ISSUE_STATE_MACHINE_ID, issueId);
|
|
76
|
+
if (typeof state === "string") {
|
|
77
|
+
return state;
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
async function deleteIssueStateMachineResourceState(issueId) {
|
|
85
|
+
const fsmApi = getIssueResourceStateApi();
|
|
86
|
+
if (!fsmApi?.delete) return false;
|
|
87
|
+
await fsmApi.delete(issueId);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/commands/transition-issue.command.ts
|
|
92
|
+
async function transitionIssueCommand(input, _deps) {
|
|
93
|
+
const { issue, target, note } = input;
|
|
94
|
+
let currentState = issue.state;
|
|
95
|
+
const syncResult = await syncIssueStateFromFsm(issue, {
|
|
96
|
+
reason: "Transition command reconciled issue state from FSM source of truth."
|
|
97
|
+
});
|
|
98
|
+
if (syncResult.changed) {
|
|
99
|
+
logger.debug(
|
|
100
|
+
{
|
|
101
|
+
issueId: issue.id,
|
|
102
|
+
memoryState: syncResult.previousState,
|
|
103
|
+
fsmState: syncResult.currentState
|
|
104
|
+
},
|
|
105
|
+
"[Transition] Syncing stale in-memory state with FSM"
|
|
106
|
+
);
|
|
107
|
+
currentState = syncResult.currentState;
|
|
108
|
+
}
|
|
109
|
+
if (currentState === target) return;
|
|
110
|
+
const path = getIssueStateMachineTransitionPath(currentState, target);
|
|
111
|
+
if (!path || path.length === 0) {
|
|
112
|
+
throw new Error(`State machine does not allow transition from '${currentState}' to '${target}' for issue ${issue.id}.`);
|
|
113
|
+
}
|
|
114
|
+
for (const event of path) {
|
|
115
|
+
await transitionIssue(issue, event, { note });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/commands/replan-issue.command.ts
|
|
120
|
+
async function replanIssueCommand(input, deps) {
|
|
121
|
+
const { issue } = input;
|
|
122
|
+
if (issue.planningStatus === "planning") {
|
|
123
|
+
throw new Error("Cannot replan while planning is in progress.");
|
|
124
|
+
}
|
|
125
|
+
if (TERMINAL_STATES.has(issue.state)) {
|
|
126
|
+
throw new Error(`Cannot replan issue in terminal state ${issue.state}.`);
|
|
127
|
+
}
|
|
128
|
+
if (issue.state === "Queued") {
|
|
129
|
+
throw new Error(`Cannot replan issue in ${issue.state} state \u2014 move it out of the execution queue first.`);
|
|
130
|
+
}
|
|
131
|
+
issue.plan = void 0;
|
|
132
|
+
issue.planVersion = (issue.planVersion ?? 0) + 1;
|
|
133
|
+
issue.executeAttempt = 0;
|
|
134
|
+
issue.reviewAttempt = 0;
|
|
135
|
+
await transitionIssueCommand(
|
|
136
|
+
{ issue, target: "Planning", note: "Replan requested." },
|
|
137
|
+
deps
|
|
138
|
+
);
|
|
139
|
+
issue.planningStatus = "idle";
|
|
140
|
+
issue.planningError = void 0;
|
|
141
|
+
issue.planningStartedAt = void 0;
|
|
142
|
+
deps.eventStore.addEvent(issue.id, "manual", `Replan requested for ${issue.identifier} \u2014 now at plan v${issue.planVersion}.`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export {
|
|
146
|
+
syncIssueStateInMemory,
|
|
147
|
+
syncIssueStateFromFsm,
|
|
148
|
+
getIssueStateMachineTransitions,
|
|
149
|
+
getIssueStateMachineVisualization,
|
|
150
|
+
getIssueTransitionHistoryForIssue,
|
|
151
|
+
deleteIssueStateMachineResourceState,
|
|
152
|
+
transitionIssueCommand,
|
|
153
|
+
replanIssueCommand
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=chunk-QQQLP3PL.js.map
|