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
|
@@ -2,18 +2,22 @@ import {
|
|
|
2
2
|
computeDiffStats,
|
|
3
3
|
removeTestWorkspace,
|
|
4
4
|
syncIssueDiffStatsToStore
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SOBLO4YZ.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-2CVTK5F2.js";
|
|
7
|
+
computeMetrics
|
|
8
|
+
} from "./chunk-MVTGAKQK.js";
|
|
10
9
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "./chunk-37N5OFHM.js";
|
|
10
|
+
markIssueDirty
|
|
11
|
+
} from "./chunk-FJNH3G2Z.js";
|
|
14
12
|
import {
|
|
15
13
|
logger
|
|
16
14
|
} from "./chunk-DVU3CXWA.js";
|
|
15
|
+
import {
|
|
16
|
+
S3DB_ISSUE_RESOURCE,
|
|
17
|
+
TERMINAL_STATES,
|
|
18
|
+
isoWeek,
|
|
19
|
+
now
|
|
20
|
+
} from "./chunk-42AMQAJG.js";
|
|
17
21
|
|
|
18
22
|
// src/agents/failure-analyzer.ts
|
|
19
23
|
function extractFilePaths(output) {
|
|
@@ -170,85 +174,6 @@ ${output}` : "";
|
|
|
170
174
|
};
|
|
171
175
|
}
|
|
172
176
|
|
|
173
|
-
// src/domains/metrics.ts
|
|
174
|
-
function computeMetrics(issues) {
|
|
175
|
-
let planning = 0;
|
|
176
|
-
let queued = 0;
|
|
177
|
-
let inProgress = 0;
|
|
178
|
-
let blocked = 0;
|
|
179
|
-
let done = 0;
|
|
180
|
-
let merged = 0;
|
|
181
|
-
let cancelled = 0;
|
|
182
|
-
const completionTimes = [];
|
|
183
|
-
for (const issue of issues) {
|
|
184
|
-
if (issue.state === "Merged") {
|
|
185
|
-
const duration = issue.durationMs;
|
|
186
|
-
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;
|
|
187
|
-
if (Number.isFinite(candidate) && candidate >= 0) {
|
|
188
|
-
completionTimes.push(candidate);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
switch (issue.state) {
|
|
192
|
-
case "Planning":
|
|
193
|
-
planning += 1;
|
|
194
|
-
break;
|
|
195
|
-
case "PendingApproval":
|
|
196
|
-
queued += 1;
|
|
197
|
-
break;
|
|
198
|
-
case "Queued":
|
|
199
|
-
case "Running":
|
|
200
|
-
case "Reviewing":
|
|
201
|
-
case "PendingDecision":
|
|
202
|
-
inProgress += 1;
|
|
203
|
-
break;
|
|
204
|
-
case "Blocked":
|
|
205
|
-
blocked += 1;
|
|
206
|
-
break;
|
|
207
|
-
case "Approved":
|
|
208
|
-
done += 1;
|
|
209
|
-
break;
|
|
210
|
-
case "Merged":
|
|
211
|
-
merged += 1;
|
|
212
|
-
break;
|
|
213
|
-
case "Cancelled":
|
|
214
|
-
cancelled += 1;
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
if (completionTimes.length === 0) {
|
|
219
|
-
return {
|
|
220
|
-
total: issues.length,
|
|
221
|
-
planning,
|
|
222
|
-
queued,
|
|
223
|
-
inProgress,
|
|
224
|
-
blocked,
|
|
225
|
-
done,
|
|
226
|
-
merged,
|
|
227
|
-
cancelled,
|
|
228
|
-
activeWorkers: 0
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
const sortedCompletionTimes = completionTimes.slice().sort((a, b) => a - b);
|
|
232
|
-
const totalCompletionMs = sortedCompletionTimes.reduce((acc, value) => acc + value, 0);
|
|
233
|
-
const mid = Math.floor(sortedCompletionTimes.length / 2);
|
|
234
|
-
const medianCompletionMs = sortedCompletionTimes.length % 2 === 1 ? sortedCompletionTimes[mid] : Math.round((sortedCompletionTimes[mid - 1] + sortedCompletionTimes[mid]) / 2);
|
|
235
|
-
return {
|
|
236
|
-
total: issues.length,
|
|
237
|
-
planning,
|
|
238
|
-
queued,
|
|
239
|
-
inProgress,
|
|
240
|
-
blocked,
|
|
241
|
-
done,
|
|
242
|
-
merged,
|
|
243
|
-
cancelled,
|
|
244
|
-
activeWorkers: 0,
|
|
245
|
-
avgCompletionMs: Math.round(totalCompletionMs / completionTimes.length),
|
|
246
|
-
medianCompletionMs,
|
|
247
|
-
fastestCompletionMs: sortedCompletionTimes[0],
|
|
248
|
-
slowestCompletionMs: sortedCompletionTimes[sortedCompletionTimes.length - 1]
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
|
|
252
177
|
// src/persistence/metrics-cache.ts
|
|
253
178
|
var cachedMetrics = null;
|
|
254
179
|
var metricsStale = true;
|
|
@@ -262,60 +187,57 @@ function getMetrics(issues) {
|
|
|
262
187
|
return cachedMetrics;
|
|
263
188
|
}
|
|
264
189
|
|
|
265
|
-
// src/persistence/
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
function markIssuePlanDirty(id) {
|
|
273
|
-
dirtyIssuePlanIds.add(id);
|
|
274
|
-
}
|
|
275
|
-
function markEventDirty(id) {
|
|
276
|
-
dirtyEventIds.add(id);
|
|
277
|
-
}
|
|
278
|
-
function hasDirtyState() {
|
|
279
|
-
return dirtyIssueIds.size > 0 || dirtyEventIds.size > 0;
|
|
280
|
-
}
|
|
281
|
-
function getDirtyIssueIds() {
|
|
282
|
-
return dirtyIssueIds;
|
|
283
|
-
}
|
|
284
|
-
function getDirtyEventIds() {
|
|
285
|
-
return dirtyEventIds;
|
|
286
|
-
}
|
|
287
|
-
function snapshotAndClearDirtyIssueIds() {
|
|
288
|
-
const snapshot = new Set(dirtyIssueIds);
|
|
289
|
-
for (const id of snapshot) dirtyIssueIds.delete(id);
|
|
290
|
-
return snapshot;
|
|
291
|
-
}
|
|
292
|
-
function snapshotAndClearDirtyIssuePlanIds() {
|
|
293
|
-
const snapshot = new Set(dirtyIssuePlanIds);
|
|
294
|
-
for (const id of snapshot) dirtyIssuePlanIds.delete(id);
|
|
295
|
-
return snapshot;
|
|
296
|
-
}
|
|
297
|
-
function snapshotAndClearDirtyEventIds() {
|
|
298
|
-
const snapshot = new Set(dirtyEventIds);
|
|
299
|
-
for (const id of snapshot) dirtyEventIds.delete(id);
|
|
300
|
-
return snapshot;
|
|
190
|
+
// src/persistence/plugins/fsm-issue.ts
|
|
191
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
192
|
+
import { join } from "path";
|
|
193
|
+
|
|
194
|
+
// src/domains/contract-negotiation.ts
|
|
195
|
+
function requiresContractNegotiation(issue) {
|
|
196
|
+
return issue.plan?.harnessMode === "contractual";
|
|
301
197
|
}
|
|
302
|
-
function
|
|
303
|
-
|
|
198
|
+
function needsContractNegotiationWork(issue) {
|
|
199
|
+
return requiresContractNegotiation(issue) && issue.contractNegotiationStatus !== "approved" && issue.contractNegotiationStatus !== "failed";
|
|
304
200
|
}
|
|
305
|
-
function
|
|
306
|
-
|
|
201
|
+
function getPlanExecutionBlocker(issue) {
|
|
202
|
+
if (issue.planningStatus === "planning") {
|
|
203
|
+
return `Cannot advance ${issue.identifier} while planning is still running.`;
|
|
204
|
+
}
|
|
205
|
+
if (!issue.plan?.steps?.length) {
|
|
206
|
+
return `Cannot advance ${issue.identifier} because no execution plan is available yet.`;
|
|
207
|
+
}
|
|
208
|
+
if (!requiresContractNegotiation(issue)) return null;
|
|
209
|
+
if (issue.contractNegotiationStatus === "running") {
|
|
210
|
+
return `Cannot advance ${issue.identifier} while contract negotiation is still running.`;
|
|
211
|
+
}
|
|
212
|
+
if (issue.contractNegotiationStatus !== "approved" && issue.contractNegotiationStatus !== "failed") {
|
|
213
|
+
const status = issue.contractNegotiationStatus ?? "pending";
|
|
214
|
+
return `Cannot advance ${issue.identifier} because contractual harness requires approved contract negotiation. Current status: ${status}.`;
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
307
217
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
218
|
+
function assertPlanReadyForExecution(issue, action) {
|
|
219
|
+
const blocker = getPlanExecutionBlocker(issue);
|
|
220
|
+
if (!blocker) return;
|
|
221
|
+
throw new Error(`${blocker} Refine, replan, or wait for negotiation before trying to ${action}.`);
|
|
310
222
|
}
|
|
311
223
|
|
|
312
|
-
// src/persistence/plugins/issue
|
|
313
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
314
|
-
import { join } from "path";
|
|
224
|
+
// src/persistence/plugins/fsm-issue.ts
|
|
315
225
|
var fsmEventEmitter = null;
|
|
316
226
|
function setFsmEventEmitter(emitter) {
|
|
317
227
|
fsmEventEmitter = emitter;
|
|
318
228
|
}
|
|
229
|
+
var persistNowFn = null;
|
|
230
|
+
function setPersistNowFn(fn) {
|
|
231
|
+
persistNowFn = fn;
|
|
232
|
+
}
|
|
233
|
+
function triggerImmediatePersist() {
|
|
234
|
+
if (persistNowFn) {
|
|
235
|
+
try {
|
|
236
|
+
persistNowFn();
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
319
241
|
function cleanupActiveTestWorkspace(issue) {
|
|
320
242
|
if (!issue.testApplied) return;
|
|
321
243
|
try {
|
|
@@ -333,9 +255,9 @@ function emitFsmEvent(issueId, kind, message) {
|
|
|
333
255
|
}
|
|
334
256
|
}
|
|
335
257
|
if (kind === "state") {
|
|
336
|
-
import("./web-push-
|
|
258
|
+
import("./web-push-AX5IIK3P.js").then(({ sendPushToAll, isWebPushReady, SETTING_ID_PUSH_SUBSCRIPTIONS }) => {
|
|
337
259
|
if (!isWebPushReady()) return;
|
|
338
|
-
import("./settings-
|
|
260
|
+
import("./settings-ZAWDCFP2.js").then(({ persistSetting }) => {
|
|
339
261
|
sendPushToAll(
|
|
340
262
|
{ title: "fifony", body: message, tag: issueId, url: "/kanban" },
|
|
341
263
|
async (subs) => {
|
|
@@ -391,10 +313,12 @@ var issueStateMachineConfig = {
|
|
|
391
313
|
states: {
|
|
392
314
|
Planning: {
|
|
393
315
|
on: { PLANNED: "PendingApproval", CANCEL: "Cancelled" },
|
|
316
|
+
guards: { PLANNED: "requireReadyExecutionPlan" },
|
|
394
317
|
entry: "onEnterPlanning"
|
|
395
318
|
},
|
|
396
319
|
PendingApproval: {
|
|
397
320
|
on: { QUEUE: "Queued", REPLAN: "Planning", CANCEL: "Cancelled" },
|
|
321
|
+
guards: { QUEUE: "requireReadyExecutionPlan" },
|
|
398
322
|
entry: "onEnterPendingApproval"
|
|
399
323
|
},
|
|
400
324
|
Queued: {
|
|
@@ -468,6 +392,12 @@ var issueStateMachineConfig = {
|
|
|
468
392
|
issue.planningError = void 0;
|
|
469
393
|
issue.nextRetryAt = void 0;
|
|
470
394
|
issue.lastError = void 0;
|
|
395
|
+
issue.checkpointAttempt = 0;
|
|
396
|
+
issue.checkpointStatus = void 0;
|
|
397
|
+
issue.checkpointPassedAt = void 0;
|
|
398
|
+
issue.checkpointReport = void 0;
|
|
399
|
+
issue.contractNegotiationAttempt = 0;
|
|
400
|
+
issue.contractNegotiationStatus = void 0;
|
|
471
401
|
emitFsmEvent(issue.id, "state", `${issue.identifier} entered Planning.`);
|
|
472
402
|
lazyEnqueue(issue, "plan").catch(() => {
|
|
473
403
|
});
|
|
@@ -550,6 +480,9 @@ var issueStateMachineConfig = {
|
|
|
550
480
|
issue.nextRetryAt = void 0;
|
|
551
481
|
issue.lastError = void 0;
|
|
552
482
|
issue.lastFailedPhase = void 0;
|
|
483
|
+
issue.checkpointStatus = void 0;
|
|
484
|
+
issue.checkpointPassedAt = void 0;
|
|
485
|
+
issue.checkpointReport = void 0;
|
|
553
486
|
logger.info({ issueId: issue.id, identifier: issue.identifier }, "[FSM] onEnterQueued \u2014 enqueuing for execution");
|
|
554
487
|
emitFsmEvent(issue.id, "state", `${issue.identifier} queued for execution.`);
|
|
555
488
|
lazyEnqueue(issue, "execute").catch((err) => {
|
|
@@ -663,6 +596,11 @@ var issueStateMachineConfig = {
|
|
|
663
596
|
guards: {
|
|
664
597
|
requireBlockReason: async (context, _event, _machine) => {
|
|
665
598
|
return typeof context.note === "string" && context.note.trim().length > 0;
|
|
599
|
+
},
|
|
600
|
+
requireReadyExecutionPlan: async (context, _event, _machine) => {
|
|
601
|
+
const issue = resolveIssue(context);
|
|
602
|
+
if (!issue) return false;
|
|
603
|
+
return getPlanExecutionBlocker(issue) === null;
|
|
666
604
|
}
|
|
667
605
|
}
|
|
668
606
|
};
|
|
@@ -823,6 +761,7 @@ async function executeTransition(issue, event, context = {}) {
|
|
|
823
761
|
issue.terminalWeek = "";
|
|
824
762
|
}
|
|
825
763
|
markDirtyAndInvalidate(issue.id);
|
|
764
|
+
triggerImmediatePersist();
|
|
826
765
|
return { previousState: previous };
|
|
827
766
|
}
|
|
828
767
|
async function getIssueTransitionHistory(issueId, options) {
|
|
@@ -859,21 +798,14 @@ function visualizeStateMachine() {
|
|
|
859
798
|
}
|
|
860
799
|
|
|
861
800
|
export {
|
|
862
|
-
computeMetrics,
|
|
863
801
|
getMetrics,
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
getDirtyEventIds,
|
|
870
|
-
snapshotAndClearDirtyIssueIds,
|
|
871
|
-
snapshotAndClearDirtyIssuePlanIds,
|
|
872
|
-
snapshotAndClearDirtyEventIds,
|
|
873
|
-
markAllIssuesDirty,
|
|
874
|
-
markAllIssuePlansDirty,
|
|
875
|
-
markAllEventsDirty,
|
|
802
|
+
requiresContractNegotiation,
|
|
803
|
+
needsContractNegotiationWork,
|
|
804
|
+
getPlanExecutionBlocker,
|
|
805
|
+
assertPlanReadyForExecution,
|
|
806
|
+
extractFailureInsights,
|
|
876
807
|
setFsmEventEmitter,
|
|
808
|
+
setPersistNowFn,
|
|
877
809
|
setEnqueueFn,
|
|
878
810
|
ISSUE_STATE_MACHINE_ID,
|
|
879
811
|
issueStateMachineConfig,
|
|
@@ -891,4 +823,4 @@ export {
|
|
|
891
823
|
canTransitionIssue,
|
|
892
824
|
visualizeStateMachine
|
|
893
825
|
};
|
|
894
|
-
//# sourceMappingURL=chunk-
|
|
826
|
+
//# sourceMappingURL=chunk-AILXZ2TD.js.map
|
|
@@ -63,7 +63,7 @@ async function sendPushToAll(payload, persistSubscriptions) {
|
|
|
63
63
|
const jsonPayload = JSON.stringify(payload);
|
|
64
64
|
let sent = 0;
|
|
65
65
|
let removed = 0;
|
|
66
|
-
|
|
66
|
+
await Promise.allSettled(
|
|
67
67
|
[...subscriptions.values()].map(async (sub) => {
|
|
68
68
|
try {
|
|
69
69
|
await webpush.sendNotification(sub, jsonPayload, { TTL: 3600 });
|
|
@@ -101,4 +101,4 @@ export {
|
|
|
101
101
|
getSubscriptionCount,
|
|
102
102
|
sendPushToAll
|
|
103
103
|
};
|
|
104
|
-
//# sourceMappingURL=chunk-
|
|
104
|
+
//# sourceMappingURL=chunk-BRSR26VK.js.map
|