fifony 0.1.37 → 0.1.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/app/dist/assets/{CommandPalette-jM1LVTly.js → CommandPalette-Ct6qhS6N.js} +1 -1
  2. package/app/dist/assets/{KeyboardShortcutsHelp-DuMbbWoK.js → KeyboardShortcutsHelp-CuBWBOeU.js} +1 -1
  3. package/app/dist/assets/{OnboardingWizard-CRNV-Tiy.js → OnboardingWizard-9qzUVfYb.js} +1 -1
  4. package/app/dist/assets/{analytics.lazy-BoFSI6cI.js → analytics.lazy-C25zZ3JA.js} +1 -1
  5. package/app/dist/assets/createLucideIcon-R47sXufx.js +1 -0
  6. package/app/dist/assets/{index-ChQVBIk9.js → index-LC--nUBy.js} +8 -8
  7. package/app/dist/index.html +2 -2
  8. package/app/dist/service-worker.js +1 -1
  9. package/dist/agent/run-local.js +4 -4
  10. package/dist/{agent-B3GQHWDL.js → agent-YAUMQQUS.js} +5 -5
  11. package/dist/{chunk-6BUKDXKZ.js → chunk-DYOLZYEC.js} +11 -11
  12. package/dist/{chunk-4RUGXGUX.js → chunk-FDR47R6J.js} +3 -3
  13. package/dist/{chunk-AZYLLJVZ.js → chunk-VOA5UMXD.js} +2 -2
  14. package/dist/{chunk-YJHD4BE4.js → chunk-YBMQIQ2X.js} +94 -86
  15. package/dist/cli.js +4 -4
  16. package/dist/{issue-runner-PNYGUY3S.js → issue-runner-VVZVUMRF.js} +5 -5
  17. package/dist/{issue-state-machine-NCD3ZFOI.js → issue-state-machine-A6NMZG5W.js} +3 -3
  18. package/dist/{issues-IW6CFOSR.js → issues-2X2H3SBN.js} +5 -5
  19. package/dist/{queue-workers-2NJZE6L2.js → queue-workers-6MZWSPBW.js} +2 -2
  20. package/dist/{scheduler-YMQ3JZUU.js → scheduler-OZRHGZIU.js} +5 -5
  21. package/dist/{store-GZVWNJ6V.js → store-O3UNJU26.js} +11 -5
  22. package/dist/{workspace-HJEJZMTO.js → workspace-E26GGQES.js} +2 -2
  23. package/package.json +8 -8
  24. package/app/dist/assets/createLucideIcon-CBw-4t9s.js +0 -1
@@ -20,11 +20,11 @@
20
20
  <link rel="icon" href="/assets/icon-32.png" sizes="32x32" type="image/png" />
21
21
  <link rel="icon" href="/assets/icon-16.png" sizes="16x16" type="image/png" />
22
22
  <link rel="apple-touch-icon" href="/assets/apple-touch-icon.png" />
23
- <script type="module" crossorigin src="/assets/assets/index-ChQVBIk9.js"></script>
23
+ <script type="module" crossorigin src="/assets/assets/index-LC--nUBy.js"></script>
24
24
  <link rel="modulepreload" crossorigin href="/assets/assets/rolldown-runtime-Dw2cE7zH.js">
25
25
  <link rel="modulepreload" crossorigin href="/assets/assets/api-ChEctgc5.js">
26
26
  <link rel="modulepreload" crossorigin href="/assets/assets/vendor-DkWeBvNl.js">
27
- <link rel="modulepreload" crossorigin href="/assets/assets/createLucideIcon-CBw-4t9s.js">
27
+ <link rel="modulepreload" crossorigin href="/assets/assets/createLucideIcon-R47sXufx.js">
28
28
  <link rel="stylesheet" crossorigin href="/assets/assets/index-BWB0OQnx.css">
29
29
  </head>
30
30
  <body>
@@ -1,4 +1,4 @@
1
- const CACHE_VERSION = "1774283198226";
1
+ const CACHE_VERSION = "1774286410206";
2
2
  const CORE_CACHE = `fifony-core-${CACHE_VERSION}`;
3
3
  const ASSET_CACHE = `fifony-assets-${CACHE_VERSION}`;
4
4
  const APP_SHELL_ROUTES = ["/kanban", "/issues", "/agents", "/settings", "/onboarding"];
@@ -23,10 +23,10 @@ import {
23
23
  startApiServer,
24
24
  syncRuntimeConfigSettings,
25
25
  validateConfig
26
- } from "../chunk-YJHD4BE4.js";
26
+ } from "../chunk-YBMQIQ2X.js";
27
27
  import {
28
28
  computeMetrics
29
- } from "../chunk-4RUGXGUX.js";
29
+ } from "../chunk-FDR47R6J.js";
30
30
  import {
31
31
  detectAvailableProviders,
32
32
  detectDefaultBranch,
@@ -34,7 +34,7 @@ import {
34
34
  getProviderDefaultCommand,
35
35
  resolveDefaultProvider,
36
36
  setSkipSource
37
- } from "../chunk-AZYLLJVZ.js";
37
+ } from "../chunk-VOA5UMXD.js";
38
38
  import {
39
39
  debugBoot,
40
40
  fail,
@@ -47,7 +47,7 @@ import {
47
47
  recoverOrphans,
48
48
  recoverState,
49
49
  stopQueueWorkers
50
- } from "../chunk-6BUKDXKZ.js";
50
+ } from "../chunk-DYOLZYEC.js";
51
51
  import {
52
52
  initLogger,
53
53
  logger
@@ -15,8 +15,8 @@ import {
15
15
  runIssueOnce,
16
16
  runPlanningJob,
17
17
  tryParseJsonOutput
18
- } from "./chunk-YJHD4BE4.js";
19
- import "./chunk-4RUGXGUX.js";
18
+ } from "./chunk-YBMQIQ2X.js";
19
+ import "./chunk-FDR47R6J.js";
20
20
  import {
21
21
  buildPrompt,
22
22
  buildProviderBasePrompt,
@@ -33,9 +33,9 @@ import {
33
33
  runCommandWithTimeout,
34
34
  runHook,
35
35
  shouldSkipMergePath
36
- } from "./chunk-AZYLLJVZ.js";
36
+ } from "./chunk-VOA5UMXD.js";
37
37
  import "./chunk-T2YJOZ6N.js";
38
- import "./chunk-6BUKDXKZ.js";
38
+ import "./chunk-DYOLZYEC.js";
39
39
  import "./chunk-DVU3CXWA.js";
40
40
  import "./chunk-37N5OFHM.js";
41
41
  export {
@@ -71,4 +71,4 @@ export {
71
71
  shouldSkipMergePath,
72
72
  tryParseJsonOutput
73
73
  };
74
- //# sourceMappingURL=agent-B3GQHWDL.js.map
74
+ //# sourceMappingURL=agent-YAUMQQUS.js.map
@@ -26,7 +26,7 @@ async function initQueueWorkers(state) {
26
26
  }, 3e4);
27
27
  persistInterval = setInterval(() => {
28
28
  if (!active || !runtimeState) return;
29
- import("./store-GZVWNJ6V.js").then(
29
+ import("./store-O3UNJU26.js").then(
30
30
  ({ persistState }) => persistState(runtimeState).catch(() => {
31
31
  })
32
32
  ).catch(() => {
@@ -116,11 +116,11 @@ function sortQueue() {
116
116
  }
117
117
  async function dispatchPlan(issue) {
118
118
  logger.info({ issueId: issue.id, identifier: issue.identifier }, "[Queue] Dispatching plan job");
119
- const { runPlanningJob } = await import("./issue-runner-PNYGUY3S.js");
119
+ const { runPlanningJob } = await import("./issue-runner-VVZVUMRF.js");
120
120
  await runPlanningJob(runtimeState, issue);
121
121
  }
122
122
  async function dispatchExecute(issue) {
123
- const { runIssueOnce } = await import("./issue-runner-PNYGUY3S.js");
123
+ const { runIssueOnce } = await import("./issue-runner-VVZVUMRF.js");
124
124
  while (active && runtimeState) {
125
125
  const current = getCurrentIssue(issue.id);
126
126
  if (!current || current.state !== "Queued" && current.state !== "Running") break;
@@ -130,12 +130,12 @@ async function dispatchExecute(issue) {
130
130
  }
131
131
  async function dispatchReview(issue) {
132
132
  logger.info({ issueId: issue.id, identifier: issue.identifier }, "[Queue] Dispatching review job");
133
- const { runIssueOnce } = await import("./issue-runner-PNYGUY3S.js");
133
+ const { runIssueOnce } = await import("./issue-runner-VVZVUMRF.js");
134
134
  await runIssueOnce(runtimeState, issue, running);
135
135
  }
136
136
  async function checkStaleIssues() {
137
137
  if (!runtimeState) return;
138
- const { ensureNotStale } = await import("./scheduler-YMQ3JZUU.js");
138
+ const { ensureNotStale } = await import("./scheduler-OZRHGZIU.js");
139
139
  await ensureNotStale(runtimeState, runtimeState.config.staleInProgressTimeoutMs);
140
140
  }
141
141
  var draining = false;
@@ -186,7 +186,7 @@ async function enqueue(issue, job) {
186
186
  async function recoverState() {
187
187
  if (!runtimeState) return;
188
188
  try {
189
- const { getIssueStateMachinePlugin, ISSUE_STATE_MACHINE_ID } = await import("./issue-state-machine-NCD3ZFOI.js");
189
+ const { getIssueStateMachinePlugin, ISSUE_STATE_MACHINE_ID } = await import("./issue-state-machine-A6NMZG5W.js");
190
190
  const fsmPlugin = getIssueStateMachinePlugin();
191
191
  if (fsmPlugin?.getState) {
192
192
  for (const issue of runtimeState.issues) {
@@ -218,9 +218,9 @@ async function recoverState() {
218
218
  }
219
219
  async function recoverOrphans() {
220
220
  if (!runtimeState) return;
221
- const { isAgentStillRunning, cleanStalePidFile } = await import("./agent-B3GQHWDL.js");
222
- const { executeTransition } = await import("./issue-state-machine-NCD3ZFOI.js");
223
- const { addEvent } = await import("./issues-IW6CFOSR.js");
221
+ const { isAgentStillRunning, cleanStalePidFile } = await import("./agent-YAUMQQUS.js");
222
+ const { executeTransition } = await import("./issue-state-machine-A6NMZG5W.js");
223
+ const { addEvent } = await import("./issues-2X2H3SBN.js");
224
224
  const candidates = runtimeState.issues.filter((i) => i.state === "Running" || i.state === "Queued");
225
225
  logger.debug({ count: candidates.length }, "[Queue] Checking for orphaned agent processes");
226
226
  for (const issue of candidates) {
@@ -258,7 +258,7 @@ function cleanTerminalWorkspaces() {
258
258
  logger.info({ count: terminals.length }, "[Queue] Scheduling terminal workspace cleanup in background");
259
259
  const state = runtimeState;
260
260
  setImmediate(async () => {
261
- const { cleanWorkspace } = await import("./agent-B3GQHWDL.js");
261
+ const { cleanWorkspace } = await import("./agent-YAUMQQUS.js");
262
262
  for (const issue of terminals) {
263
263
  try {
264
264
  await cleanWorkspace(issue.id, issue, state);
@@ -292,4 +292,4 @@ export {
292
292
  cleanTerminalWorkspaces,
293
293
  getQueueStats
294
294
  };
295
- //# sourceMappingURL=chunk-6BUKDXKZ.js.map
295
+ //# sourceMappingURL=chunk-DYOLZYEC.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  computeDiffStats,
3
3
  syncIssueDiffStatsToStore
4
- } from "./chunk-AZYLLJVZ.js";
4
+ } from "./chunk-VOA5UMXD.js";
5
5
  import {
6
6
  isoWeek,
7
7
  now
@@ -337,7 +337,7 @@ function emitFsmEvent(issueId, kind, message) {
337
337
  }
338
338
  }
339
339
  async function lazyEnqueue(issue, job) {
340
- const { enqueue } = await import("./queue-workers-2NJZE6L2.js");
340
+ const { enqueue } = await import("./queue-workers-6MZWSPBW.js");
341
341
  return enqueue(issue, job);
342
342
  }
343
343
  var ISSUE_STATE_MACHINE_ID = "issue-lifecycle";
@@ -870,4 +870,4 @@ export {
870
870
  canTransitionIssue,
871
871
  visualizeStateMachine
872
872
  };
873
- //# sourceMappingURL=chunk-4RUGXGUX.js.map
873
+ //# sourceMappingURL=chunk-FDR47R6J.js.map
@@ -2118,7 +2118,7 @@ function parseDiffStats(issue, raw) {
2118
2118
  }
2119
2119
  async function syncIssueDiffStatsToStore(issue) {
2120
2120
  if (!issue?.id) return;
2121
- const { getIssueStateResource } = await import("./store-GZVWNJ6V.js");
2121
+ const { getIssueStateResource } = await import("./store-O3UNJU26.js");
2122
2122
  const issueResource = getIssueStateResource();
2123
2123
  if (!issueResource) return;
2124
2124
  const toNumber = (value) => {
@@ -2381,4 +2381,4 @@ export {
2381
2381
  hydrateIssuePathsFromWorkspace,
2382
2382
  writeVersionedArtifacts
2383
2383
  };
2384
- //# sourceMappingURL=chunk-AZYLLJVZ.js.map
2384
+ //# sourceMappingURL=chunk-VOA5UMXD.js.map
@@ -14,14 +14,13 @@ import {
14
14
  markAllIssuesDirty,
15
15
  markEventDirty,
16
16
  markIssueDirty,
17
- markIssuePlanDirty,
18
17
  setFsmEventEmitter,
19
18
  setIssueResourceStateApi,
20
19
  setIssueStateMachinePlugin,
21
20
  snapshotAndClearDirtyEventIds,
22
21
  snapshotAndClearDirtyIssueIds,
23
22
  snapshotAndClearDirtyIssuePlanIds
24
- } from "./chunk-4RUGXGUX.js";
23
+ } from "./chunk-FDR47R6J.js";
25
24
  import {
26
25
  ADAPTERS,
27
26
  assertIssueHasGitWorktree,
@@ -51,7 +50,7 @@ import {
51
50
  readCodexConfig,
52
51
  runCommandWithTimeout,
53
52
  runHook
54
- } from "./chunk-AZYLLJVZ.js";
53
+ } from "./chunk-VOA5UMXD.js";
55
54
  import {
56
55
  appendFileTail,
57
56
  clamp,
@@ -76,7 +75,7 @@ import {
76
75
  } from "./chunk-T2YJOZ6N.js";
77
76
  import {
78
77
  enqueue
79
- } from "./chunk-6BUKDXKZ.js";
78
+ } from "./chunk-DYOLZYEC.js";
80
79
  import {
81
80
  logger
82
81
  } from "./chunk-DVU3CXWA.js";
@@ -2229,8 +2228,6 @@ var issues_resource_default = {
2229
2228
  tokenUsage: "json|optional",
2230
2229
  tokensByPhase: "json|optional",
2231
2230
  tokensByModel: "json|optional",
2232
- plan: "json|optional",
2233
- planHistory: "json|optional",
2234
2231
  planVersion: "number|optional",
2235
2232
  planningStatus: "string|optional",
2236
2233
  planningStartedAt: "datetime|optional",
@@ -2321,9 +2318,14 @@ var issue_plans_resource_default = {
2321
2318
  name: S3DB_ISSUE_PLAN_RESOURCE,
2322
2319
  attributes: {
2323
2320
  id: "string|required",
2324
- plan: "json|optional",
2325
- planHistory: "json|optional",
2326
- planVersion: "number|required"
2321
+ issueId: "string|required",
2322
+ version: "number|required",
2323
+ current: "boolean|required",
2324
+ plan: "json|required"
2325
+ },
2326
+ partitions: {
2327
+ byIssue: { fields: { issueId: "string" } },
2328
+ byIssueCurrent: { fields: { issueId: "string", current: "boolean" } }
2327
2329
  },
2328
2330
  behavior: "body-overflow",
2329
2331
  paranoid: false,
@@ -3617,12 +3619,7 @@ async function replanIssueCommand(input, deps) {
3617
3619
  if (issue.state === "Running" || issue.state === "Reviewing" || issue.state === "Queued") {
3618
3620
  throw new Error(`Cannot replan issue in ${issue.state} state \u2014 wait for it to finish or cancel it first.`);
3619
3621
  }
3620
- if (issue.plan) {
3621
- if (!Array.isArray(issue.planHistory)) issue.planHistory = [];
3622
- issue.planHistory.push(issue.plan);
3623
- issue.plan = void 0;
3624
- markIssuePlanDirty(issue.id);
3625
- }
3622
+ issue.plan = void 0;
3626
3623
  issue.planVersion = (issue.planVersion ?? 0) + 1;
3627
3624
  issue.executeAttempt = 0;
3628
3625
  issue.reviewAttempt = 0;
@@ -3756,7 +3753,7 @@ function registerStateRoutes(app, state) {
3756
3753
  if (!issueId) return c.json({ ok: false, error: "Issue id is required." }, 400);
3757
3754
  const issue = findIssue(state, issueId);
3758
3755
  if (!issue) return c.json({ ok: false, error: "Issue not found." }, 404);
3759
- const { dryMerge } = await import("./workspace-HJEJZMTO.js");
3756
+ const { dryMerge } = await import("./workspace-E26GGQES.js");
3760
3757
  const result = dryMerge(issue);
3761
3758
  return c.json({ ok: true, ...result });
3762
3759
  } catch (error) {
@@ -3771,7 +3768,7 @@ function registerStateRoutes(app, state) {
3771
3768
  if (!issueId) return c.json({ ok: false, error: "Issue id is required." }, 400);
3772
3769
  const issue = findIssue(state, issueId);
3773
3770
  if (!issue) return c.json({ ok: false, error: "Issue not found." }, 404);
3774
- const { rebaseWorktree } = await import("./workspace-HJEJZMTO.js");
3771
+ const { rebaseWorktree } = await import("./workspace-E26GGQES.js");
3775
3772
  const result = rebaseWorktree(issue);
3776
3773
  if (result.success) {
3777
3774
  addEvent(state, issue.id, "info", `Branch ${issue.branchName} rebased onto ${issue.baseBranch}.`);
@@ -3907,7 +3904,7 @@ function registerStateRoutes(app, state) {
3907
3904
  const issue = findIssue(state, issueId);
3908
3905
  if (!issue) return c.json({ ok: false, error: "Issue not found." }, 404);
3909
3906
  try {
3910
- const { getIssueTransitionHistory } = await import("./issue-state-machine-NCD3ZFOI.js");
3907
+ const { getIssueTransitionHistory } = await import("./issue-state-machine-A6NMZG5W.js");
3911
3908
  const limit = parseInt(c.req.query("limit") ?? "50", 10);
3912
3909
  const offset = parseInt(c.req.query("offset") ?? "0", 10);
3913
3910
  const transitions = await getIssueTransitionHistory(issue.id, { limit, offset });
@@ -3918,7 +3915,7 @@ function registerStateRoutes(app, state) {
3918
3915
  });
3919
3916
  app.get("/api/state-machine/transitions", async (c) => {
3920
3917
  try {
3921
- const { getStateMachineTransitions } = await import("./issue-state-machine-NCD3ZFOI.js");
3918
+ const { getStateMachineTransitions } = await import("./issue-state-machine-A6NMZG5W.js");
3922
3919
  return c.json({ ok: true, transitions: getStateMachineTransitions() });
3923
3920
  } catch (error) {
3924
3921
  return c.json({ ok: false, error: error instanceof Error ? error.message : String(error) }, 500);
@@ -3926,7 +3923,7 @@ function registerStateRoutes(app, state) {
3926
3923
  });
3927
3924
  app.get("/api/state-machine/visualize", async (c) => {
3928
3925
  try {
3929
- const { visualizeStateMachine } = await import("./issue-state-machine-NCD3ZFOI.js");
3926
+ const { visualizeStateMachine } = await import("./issue-state-machine-A6NMZG5W.js");
3930
3927
  const dot = visualizeStateMachine();
3931
3928
  if (!dot) return c.json({ ok: false, error: "Visualization not available." }, 404);
3932
3929
  return c.json({ ok: true, dot });
@@ -4900,7 +4897,6 @@ function generatePlanInBackground(issue, config, _workflowDefinition, callbacks,
4900
4897
  generatePlan(issue.title, issue.description, config, null, { fast }).then(async ({ plan, usage }) => {
4901
4898
  issue.plan = plan;
4902
4899
  issue.planVersion = Math.max(issue.planVersion ?? 0, 1);
4903
- markIssuePlanDirty(issue.id);
4904
4900
  issue.planningStatus = "idle";
4905
4901
  issue.planningStartedAt = void 0;
4906
4902
  issue.planningError = void 0;
@@ -4908,16 +4904,8 @@ function generatePlanInBackground(issue, config, _workflowDefinition, callbacks,
4908
4904
  applyUsage(issue, usage);
4909
4905
  applySuggestions(issue, plan);
4910
4906
  try {
4911
- const { getIssuePlanResource: getIssuePlanResource2 } = await import("./store-GZVWNJ6V.js");
4912
- const planRes = getIssuePlanResource2();
4913
- if (planRes) {
4914
- await planRes.replace(issue.id, {
4915
- id: issue.id,
4916
- plan: issue.plan,
4917
- planHistory: issue.planHistory,
4918
- planVersion: issue.planVersion
4919
- });
4920
- }
4907
+ const { savePlanForIssue: savePlanForIssue2 } = await import("./store-O3UNJU26.js");
4908
+ await savePlanForIssue2(issue.id, plan, issue.planVersion);
4921
4909
  } catch {
4922
4910
  }
4923
4911
  addEvent2(issue.id, "progress", `${fast ? "Fast plan" : "Plan"} generated for ${issue.identifier}: ${plan.steps.length} steps, complexity: ${plan.estimatedComplexity}.`);
@@ -4946,7 +4934,6 @@ function refinePlanInBackground(issue, feedback, config, _workflowDefinition, ca
4946
4934
  refinePlan(issue, feedback, config, null).then(async ({ plan, usage }) => {
4947
4935
  issue.plan = plan;
4948
4936
  issue.planVersion = Math.max(issue.planVersion ?? 0, 1);
4949
- markIssuePlanDirty(issue.id);
4950
4937
  issue.planningStatus = "idle";
4951
4938
  issue.planningStartedAt = void 0;
4952
4939
  issue.planningError = void 0;
@@ -4954,16 +4941,8 @@ function refinePlanInBackground(issue, feedback, config, _workflowDefinition, ca
4954
4941
  applyUsage(issue, usage);
4955
4942
  applySuggestions(issue, plan);
4956
4943
  try {
4957
- const { getIssuePlanResource: getIssuePlanResource2 } = await import("./store-GZVWNJ6V.js");
4958
- const planRes = getIssuePlanResource2();
4959
- if (planRes) {
4960
- await planRes.replace(issue.id, {
4961
- id: issue.id,
4962
- plan: issue.plan,
4963
- planHistory: issue.planHistory,
4964
- planVersion: issue.planVersion
4965
- });
4966
- }
4944
+ const { savePlanForIssue: savePlanForIssue2 } = await import("./store-O3UNJU26.js");
4945
+ await savePlanForIssue2(issue.id, plan, issue.planVersion);
4967
4946
  } catch {
4968
4947
  }
4969
4948
  const feedbackPreview = feedback.length > 80 ? `${feedback.slice(0, 77)}...` : feedback;
@@ -6233,6 +6212,7 @@ async function startApiServer(state, port, options) {
6233
6212
  }
6234
6213
 
6235
6214
  // src/persistence/store.ts
6215
+ import { randomUUID as randomUUID3 } from "crypto";
6236
6216
  var loadedS3dbModule = null;
6237
6217
  var stateDb = null;
6238
6218
  var runtimeStateResource = null;
@@ -6266,6 +6246,58 @@ function getAgentSessionResource() {
6266
6246
  function getAgentPipelineResource() {
6267
6247
  return agentPipelineResource;
6268
6248
  }
6249
+ async function savePlanForIssue(issueId, plan, version) {
6250
+ if (!issuePlanResource) throw new Error("Issue plan resource not initialized");
6251
+ try {
6252
+ const existing = await issuePlanResource.list({
6253
+ partition: "byIssueCurrent",
6254
+ partitionValues: { issueId, current: true }
6255
+ });
6256
+ if (Array.isArray(existing)) {
6257
+ for (const old of existing) {
6258
+ if (old?.id) await issuePlanResource.patch(old.id, { current: false });
6259
+ }
6260
+ }
6261
+ } catch {
6262
+ }
6263
+ const planId = `plan-${randomUUID3()}`;
6264
+ await issuePlanResource.insert({
6265
+ id: planId,
6266
+ issueId,
6267
+ version,
6268
+ current: true,
6269
+ plan
6270
+ });
6271
+ return planId;
6272
+ }
6273
+ async function getCurrentPlanForIssue(issueId) {
6274
+ if (!issuePlanResource) return null;
6275
+ try {
6276
+ const results = await issuePlanResource.list({
6277
+ partition: "byIssueCurrent",
6278
+ partitionValues: { issueId, current: true },
6279
+ limit: 1
6280
+ });
6281
+ if (Array.isArray(results) && results.length > 0 && results[0]?.plan) {
6282
+ return { id: results[0].id, plan: results[0].plan, version: results[0].version ?? 1 };
6283
+ }
6284
+ } catch {
6285
+ }
6286
+ return null;
6287
+ }
6288
+ async function getPlansForIssue(issueId) {
6289
+ if (!issuePlanResource) return [];
6290
+ try {
6291
+ const results = await issuePlanResource.list({
6292
+ partition: "byIssue",
6293
+ partitionValues: { issueId }
6294
+ });
6295
+ if (!Array.isArray(results)) return [];
6296
+ return results.filter((r) => r?.id && r?.plan).map((r) => ({ id: r.id, plan: r.plan, version: r.version ?? 1, current: !!r.current })).sort((a, b) => a.version - b.version);
6297
+ } catch {
6298
+ return [];
6299
+ }
6300
+ }
6269
6301
  function setActiveApiPlugin(plugin) {
6270
6302
  activeApiPlugin = plugin;
6271
6303
  }
@@ -6429,18 +6461,15 @@ async function recoverStateFromIssueResource() {
6429
6461
  const issues = records.filter((r) => r?.id && r?.identifier && r?.state).map((r) => r);
6430
6462
  if (issues.length === 0) return null;
6431
6463
  logger.info(`Recovered ${issues.length} issue(s) from s3db issue resource.`);
6432
- if (issuePlanResource) {
6433
- for (const issue of issues) {
6434
- try {
6435
- const planRecord = await issuePlanResource.get(issue.id);
6436
- if (planRecord?.plan) {
6437
- issue.plan = planRecord.plan;
6438
- logger.debug({ issueId: issue.id, hasSteps: !!issue.plan?.steps?.length }, "[Recovery] Hydrated plan from issue_plans resource");
6439
- }
6440
- if (planRecord?.planHistory) issue.planHistory = planRecord.planHistory;
6441
- } catch (err) {
6442
- logger.warn({ issueId: issue.id, err: String(err) }, "[Recovery] Failed to load plan from issue_plans resource");
6464
+ for (const issue of issues) {
6465
+ try {
6466
+ const current = await getCurrentPlanForIssue(issue.id);
6467
+ if (current) {
6468
+ issue.plan = current.plan;
6469
+ logger.debug({ issueId: issue.id, version: current.version }, "[Recovery] Hydrated current plan");
6443
6470
  }
6471
+ } catch (err) {
6472
+ logger.warn({ issueId: issue.id, err: String(err) }, "[Recovery] Failed to load plan");
6444
6473
  }
6445
6474
  }
6446
6475
  return {
@@ -6502,22 +6531,7 @@ async function persistState(state) {
6502
6531
  }
6503
6532
  }
6504
6533
  }
6505
- const dirtyIssuePlans = issuePlanResource ? snapshotAndClearDirtyIssuePlanIds() : /* @__PURE__ */ new Set();
6506
- if (issuePlanResource && dirtyIssuePlans.size > 0) {
6507
- for (const issue of state.issues) {
6508
- if (!dirtyIssuePlans.has(issue.id)) continue;
6509
- try {
6510
- await issuePlanResource.replace(issue.id, {
6511
- id: issue.id,
6512
- plan: issue.plan,
6513
- planHistory: issue.planHistory,
6514
- planVersion: issue.planVersion ?? 0
6515
- });
6516
- } catch (error) {
6517
- logger.warn(`Failed to persist issue plan ${issue.id}: ${String(error)}`);
6518
- }
6519
- }
6520
- }
6534
+ snapshotAndClearDirtyIssuePlanIds();
6521
6535
  const dirtyEvents = eventStateResource ? snapshotAndClearDirtyEventIds() : /* @__PURE__ */ new Set();
6522
6536
  if (eventStateResource && dirtyEvents.size > 0) {
6523
6537
  for (const event of state.events) {
@@ -7563,21 +7577,12 @@ async function runPlanningJob(state, issue) {
7563
7577
  );
7564
7578
  issue.plan = plan;
7565
7579
  issue.planVersion = Math.max(issue.planVersion ?? 0, 1);
7566
- markIssuePlanDirty(issue.id);
7567
7580
  try {
7568
- const { getIssuePlanResource: getIssuePlanResource2 } = await import("./store-GZVWNJ6V.js");
7569
- const planRes = getIssuePlanResource2();
7570
- if (planRes) {
7571
- await planRes.replace(issue.id, {
7572
- id: issue.id,
7573
- plan: issue.plan,
7574
- planHistory: issue.planHistory,
7575
- planVersion: issue.planVersion
7576
- });
7577
- logger.debug({ issueId: issue.id, planVersion: issue.planVersion }, "[Agent] Plan flushed to issue_plans resource");
7578
- }
7579
- } catch (flushErr) {
7580
- logger.warn({ err: String(flushErr), issueId: issue.id }, "[Agent] Failed to flush plan to issue_plans resource");
7581
+ const { savePlanForIssue: savePlanForIssue2 } = await import("./store-O3UNJU26.js");
7582
+ await savePlanForIssue2(issue.id, plan, issue.planVersion);
7583
+ logger.debug({ issueId: issue.id, planVersion: issue.planVersion }, "[Agent] Plan saved to issue_plans resource");
7584
+ } catch (err) {
7585
+ logger.warn({ err: String(err), issueId: issue.id }, "[Agent] Failed to save plan");
7581
7586
  }
7582
7587
  if (plan.suggestedPaths?.length && !issue.paths?.length) issue.paths = plan.suggestedPaths;
7583
7588
  if (plan.suggestedEffort && !issue.effort) issue.effort = plan.suggestedEffort;
@@ -7809,7 +7814,7 @@ async function runIssueOnce(state, issue, running) {
7809
7814
  const { workspacePath, promptText, promptFile } = await prepareWorkspace(issue, state, state.config.defaultBranch);
7810
7815
  container.issueRepository.markDirty(issue.id);
7811
7816
  try {
7812
- const { getIssueStateResource: getIssueStateResource2 } = await import("./store-GZVWNJ6V.js");
7817
+ const { getIssueStateResource: getIssueStateResource2 } = await import("./store-O3UNJU26.js");
7813
7818
  const res = getIssueStateResource2();
7814
7819
  if (res) {
7815
7820
  await res.patch(issue.id, {
@@ -7850,7 +7855,7 @@ async function runIssueOnce(state, issue, running) {
7850
7855
  await container.persistencePort.persistState(state);
7851
7856
  if (issue.state === "Reviewing") {
7852
7857
  try {
7853
- const { enqueue: enqueue2 } = await import("./queue-workers-2NJZE6L2.js");
7858
+ const { enqueue: enqueue2 } = await import("./queue-workers-6MZWSPBW.js");
7854
7859
  await enqueue2(issue, "review");
7855
7860
  } catch {
7856
7861
  }
@@ -7907,6 +7912,9 @@ export {
7907
7912
  getSettingStateResource,
7908
7913
  getAgentSessionResource,
7909
7914
  getAgentPipelineResource,
7915
+ savePlanForIssue,
7916
+ getCurrentPlanForIssue,
7917
+ getPlansForIssue,
7910
7918
  setActiveApiPlugin,
7911
7919
  loadS3dbModule,
7912
7920
  initStateStore,
@@ -7927,4 +7935,4 @@ export {
7927
7935
  syncReferenceRepositories,
7928
7936
  importReferenceArtifacts
7929
7937
  };
7930
- //# sourceMappingURL=chunk-YJHD4BE4.js.map
7938
+ //# sourceMappingURL=chunk-YBMQIQ2X.js.map
package/dist/cli.js CHANGED
@@ -3,11 +3,11 @@ import {
3
3
  importReferenceArtifacts,
4
4
  listReferenceRepositories,
5
5
  syncReferenceRepositories
6
- } from "./chunk-YJHD4BE4.js";
7
- import "./chunk-4RUGXGUX.js";
8
- import "./chunk-AZYLLJVZ.js";
6
+ } from "./chunk-YBMQIQ2X.js";
7
+ import "./chunk-FDR47R6J.js";
8
+ import "./chunk-VOA5UMXD.js";
9
9
  import "./chunk-T2YJOZ6N.js";
10
- import "./chunk-6BUKDXKZ.js";
10
+ import "./chunk-DYOLZYEC.js";
11
11
  import "./chunk-DVU3CXWA.js";
12
12
  import "./chunk-37N5OFHM.js";
13
13
 
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  runIssueOnce,
3
3
  runPlanningJob
4
- } from "./chunk-YJHD4BE4.js";
5
- import "./chunk-4RUGXGUX.js";
6
- import "./chunk-AZYLLJVZ.js";
4
+ } from "./chunk-YBMQIQ2X.js";
5
+ import "./chunk-FDR47R6J.js";
6
+ import "./chunk-VOA5UMXD.js";
7
7
  import "./chunk-T2YJOZ6N.js";
8
- import "./chunk-6BUKDXKZ.js";
8
+ import "./chunk-DYOLZYEC.js";
9
9
  import "./chunk-DVU3CXWA.js";
10
10
  import "./chunk-37N5OFHM.js";
11
11
  export {
12
12
  runIssueOnce,
13
13
  runPlanningJob
14
14
  };
15
- //# sourceMappingURL=issue-runner-PNYGUY3S.js.map
15
+ //# sourceMappingURL=issue-runner-VVZVUMRF.js.map
@@ -15,8 +15,8 @@ import {
15
15
  setIssueResourceStateApi,
16
16
  setIssueStateMachinePlugin,
17
17
  visualizeStateMachine
18
- } from "./chunk-4RUGXGUX.js";
19
- import "./chunk-AZYLLJVZ.js";
18
+ } from "./chunk-FDR47R6J.js";
19
+ import "./chunk-VOA5UMXD.js";
20
20
  import "./chunk-T2YJOZ6N.js";
21
21
  import "./chunk-DVU3CXWA.js";
22
22
  import "./chunk-37N5OFHM.js";
@@ -38,4 +38,4 @@ export {
38
38
  setIssueStateMachinePlugin,
39
39
  visualizeStateMachine
40
40
  };
41
- //# sourceMappingURL=issue-state-machine-NCD3ZFOI.js.map
41
+ //# sourceMappingURL=issue-state-machine-A6NMZG5W.js.map
@@ -11,13 +11,13 @@ import {
11
11
  normalizeIssue,
12
12
  transitionIssue,
13
13
  validateConfig
14
- } from "./chunk-YJHD4BE4.js";
14
+ } from "./chunk-YBMQIQ2X.js";
15
15
  import {
16
16
  computeMetrics
17
- } from "./chunk-4RUGXGUX.js";
18
- import "./chunk-AZYLLJVZ.js";
17
+ } from "./chunk-FDR47R6J.js";
18
+ import "./chunk-VOA5UMXD.js";
19
19
  import "./chunk-T2YJOZ6N.js";
20
- import "./chunk-6BUKDXKZ.js";
20
+ import "./chunk-DYOLZYEC.js";
21
21
  import "./chunk-DVU3CXWA.js";
22
22
  import "./chunk-37N5OFHM.js";
23
23
  export {
@@ -35,4 +35,4 @@ export {
35
35
  transitionIssue,
36
36
  validateConfig
37
37
  };
38
- //# sourceMappingURL=issues-IW6CFOSR.js.map
38
+ //# sourceMappingURL=issues-2X2H3SBN.js.map
@@ -7,7 +7,7 @@ import {
7
7
  recoverOrphans,
8
8
  recoverState,
9
9
  stopQueueWorkers
10
- } from "./chunk-6BUKDXKZ.js";
10
+ } from "./chunk-DYOLZYEC.js";
11
11
  import "./chunk-DVU3CXWA.js";
12
12
  import "./chunk-37N5OFHM.js";
13
13
  export {
@@ -20,4 +20,4 @@ export {
20
20
  recoverState,
21
21
  stopQueueWorkers
22
22
  };
23
- //# sourceMappingURL=queue-workers-2NJZE6L2.js.map
23
+ //# sourceMappingURL=queue-workers-6MZWSPBW.js.map
@@ -4,11 +4,11 @@ import {
4
4
  hasTerminalQueue,
5
5
  installGracefulShutdown,
6
6
  isShuttingDown
7
- } from "./chunk-YJHD4BE4.js";
8
- import "./chunk-4RUGXGUX.js";
9
- import "./chunk-AZYLLJVZ.js";
7
+ } from "./chunk-YBMQIQ2X.js";
8
+ import "./chunk-FDR47R6J.js";
9
+ import "./chunk-VOA5UMXD.js";
10
10
  import "./chunk-T2YJOZ6N.js";
11
- import "./chunk-6BUKDXKZ.js";
11
+ import "./chunk-DYOLZYEC.js";
12
12
  import "./chunk-DVU3CXWA.js";
13
13
  import "./chunk-37N5OFHM.js";
14
14
  export {
@@ -18,4 +18,4 @@ export {
18
18
  installGracefulShutdown,
19
19
  isShuttingDown
20
20
  };
21
- //# sourceMappingURL=scheduler-YMQ3JZUU.js.map
21
+ //# sourceMappingURL=scheduler-OZRHGZIU.js.map