issue-flow 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +16 -0
  2. package/dist/{analyze-RBNKXWL5.js → analyze-UZYJAWAP.js} +6 -6
  3. package/dist/{chunk-J4SICTAN.js → chunk-2LNQL4XH.js} +53 -9
  4. package/dist/chunk-2LNQL4XH.js.map +1 -0
  5. package/dist/{chunk-A4M6AKIK.js → chunk-2Z7OEZZT.js} +6 -6
  6. package/dist/{chunk-F52S6ZGF.js → chunk-652DJBCN.js} +17 -3
  7. package/dist/chunk-652DJBCN.js.map +1 -0
  8. package/dist/{chunk-TGP6WK65.js → chunk-67ZO5ROQ.js} +75 -11
  9. package/dist/chunk-67ZO5ROQ.js.map +1 -0
  10. package/dist/{chunk-VSF2CR3G.js → chunk-EWA3OGCM.js} +6 -6
  11. package/dist/{chunk-VPDWTZ3F.js → chunk-EZMOEBLU.js} +2 -2
  12. package/dist/{chunk-JWZKV3CL.js → chunk-MXTGCD5C.js} +2 -2
  13. package/dist/{chunk-QO2MWMAZ.js → chunk-PPLIXZI5.js} +33 -10
  14. package/dist/chunk-PPLIXZI5.js.map +1 -0
  15. package/dist/{chunk-HSGTZ3CT.js → chunk-S67Q4I2O.js} +219 -3
  16. package/dist/chunk-S67Q4I2O.js.map +1 -0
  17. package/dist/chunk-SP7DD4ID.js +265 -0
  18. package/dist/chunk-SP7DD4ID.js.map +1 -0
  19. package/dist/{chunk-36ECROTC.js → chunk-UH4KAJBJ.js} +7 -7
  20. package/dist/{chunk-RQW5W4XC.js → chunk-UUY4PCWW.js} +2 -2
  21. package/dist/{chunk-BH7DYADV.js → chunk-V5OHFSW4.js} +319 -181
  22. package/dist/chunk-V5OHFSW4.js.map +1 -0
  23. package/dist/{chunk-J3PJBZXJ.js → chunk-VOKNTBOO.js} +3 -3
  24. package/dist/{chunk-BASRRXAM.js → chunk-VYFKOUUR.js} +222 -6
  25. package/dist/chunk-VYFKOUUR.js.map +1 -0
  26. package/dist/cli.js +98 -29
  27. package/dist/cli.js.map +1 -1
  28. package/dist/{config-R7O5YC65.js → config-YCF3HIKR.js} +7 -3
  29. package/dist/execute-QYXA225W.js +14 -0
  30. package/dist/{generate-TGJQLGMV.js → generate-TW6QKSW5.js} +6 -6
  31. package/dist/init-G57UXKDG.js +9 -0
  32. package/dist/plan-YJLGBYBQ.js +16 -0
  33. package/dist/policy-NP4ZAVF6.js +1013 -0
  34. package/dist/policy-NP4ZAVF6.js.map +1 -0
  35. package/dist/pr-V5H65MRW.js +20 -0
  36. package/dist/pr-review-RCMXKXVP.js +16 -0
  37. package/dist/prd-3XR5KYJS.js +16 -0
  38. package/dist/review-ZZG3CSUO.js +14 -0
  39. package/dist/run-DIBC3YKX.js +1860 -0
  40. package/dist/run-DIBC3YKX.js.map +1 -0
  41. package/dist/{web-JVPK2PIF.js → web-O2FVOYZW.js} +4 -4
  42. package/package.json +1 -1
  43. package/prompts/execute.md +2 -2
  44. package/prompts/plan.md +10 -1
  45. package/prompts/pr.md +9 -4
  46. package/web/CLAUDE.md +22 -8
  47. package/web/public/app.css +178 -0
  48. package/web/public/app.js +336 -17
  49. package/web/public/index.html +24 -0
  50. package/dist/chunk-BASRRXAM.js.map +0 -1
  51. package/dist/chunk-BH7DYADV.js.map +0 -1
  52. package/dist/chunk-F52S6ZGF.js.map +0 -1
  53. package/dist/chunk-HSGTZ3CT.js.map +0 -1
  54. package/dist/chunk-J4SICTAN.js.map +0 -1
  55. package/dist/chunk-MK43N4X3.js +0 -123
  56. package/dist/chunk-MK43N4X3.js.map +0 -1
  57. package/dist/chunk-QO2MWMAZ.js.map +0 -1
  58. package/dist/chunk-TGP6WK65.js.map +0 -1
  59. package/dist/execute-LU3HWA54.js +0 -14
  60. package/dist/init-WP7Z2LFQ.js +0 -9
  61. package/dist/plan-2MWMCKRY.js +0 -16
  62. package/dist/pr-XVQDEQ7B.js +0 -16
  63. package/dist/pr-review-VO6ZXAFM.js +0 -16
  64. package/dist/prd-FPZAHQEO.js +0 -16
  65. package/dist/review-AHALLMXO.js +0 -14
  66. package/dist/run-2CXVR3VZ.js +0 -733
  67. package/dist/run-2CXVR3VZ.js.map +0 -1
  68. /package/dist/{analyze-RBNKXWL5.js.map → analyze-UZYJAWAP.js.map} +0 -0
  69. /package/dist/{chunk-A4M6AKIK.js.map → chunk-2Z7OEZZT.js.map} +0 -0
  70. /package/dist/{chunk-VSF2CR3G.js.map → chunk-EWA3OGCM.js.map} +0 -0
  71. /package/dist/{chunk-VPDWTZ3F.js.map → chunk-EZMOEBLU.js.map} +0 -0
  72. /package/dist/{chunk-JWZKV3CL.js.map → chunk-MXTGCD5C.js.map} +0 -0
  73. /package/dist/{chunk-36ECROTC.js.map → chunk-UH4KAJBJ.js.map} +0 -0
  74. /package/dist/{chunk-RQW5W4XC.js.map → chunk-UUY4PCWW.js.map} +0 -0
  75. /package/dist/{chunk-J3PJBZXJ.js.map → chunk-VOKNTBOO.js.map} +0 -0
  76. /package/dist/{config-R7O5YC65.js.map → config-YCF3HIKR.js.map} +0 -0
  77. /package/dist/{execute-LU3HWA54.js.map → execute-QYXA225W.js.map} +0 -0
  78. /package/dist/{generate-TGJQLGMV.js.map → generate-TW6QKSW5.js.map} +0 -0
  79. /package/dist/{init-WP7Z2LFQ.js.map → init-G57UXKDG.js.map} +0 -0
  80. /package/dist/{plan-2MWMCKRY.js.map → plan-YJLGBYBQ.js.map} +0 -0
  81. /package/dist/{pr-XVQDEQ7B.js.map → pr-V5H65MRW.js.map} +0 -0
  82. /package/dist/{pr-review-VO6ZXAFM.js.map → pr-review-RCMXKXVP.js.map} +0 -0
  83. /package/dist/{prd-FPZAHQEO.js.map → prd-3XR5KYJS.js.map} +0 -0
  84. /package/dist/{review-AHALLMXO.js.map → review-ZZG3CSUO.js.map} +0 -0
  85. /package/dist/{web-JVPK2PIF.js.map → web-O2FVOYZW.js.map} +0 -0
@@ -1,195 +1,259 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/schemas.ts
3
+ // src/policy/schemas.ts
4
4
  import { z } from "zod";
5
- var claudeUsageSchema = z.object({
6
- inputTokens: z.number().optional(),
7
- outputTokens: z.number().optional(),
8
- cacheReadTokens: z.number().optional(),
9
- cacheCreationTokens: z.number().optional(),
10
- costUsd: z.number().optional()
5
+ var policyDiscoveryConfigSchema = z.object({
6
+ issueTemplates: z.boolean().default(true),
7
+ pullRequestTemplate: z.boolean().default(true),
8
+ docs: z.boolean().default(true),
9
+ codeowners: z.boolean().default(true),
10
+ labels: z.boolean().default(true),
11
+ issueTypes: z.boolean().default(true)
12
+ });
13
+ var policyIssuesDeclarationSchema = z.object({
14
+ titleConvention: z.string().min(1).optional()
15
+ });
16
+ var policyPullRequestsDeclarationSchema = z.object({
17
+ baseBranch: z.string().min(1).optional(),
18
+ titleConvention: z.string().min(1).optional()
19
+ });
20
+ var policyGitDeclarationSchema = z.object({
21
+ branchConvention: z.string().min(1).optional(),
22
+ commitConvention: z.string().min(1).optional()
11
23
  });
12
- var userStoryStatusSchema = z.enum(["backlog", "in_progress", "in_review", "done"]);
13
- var userStorySchema = z.object({
14
- id: z.string(),
15
- title: z.string(),
16
- description: z.string(),
17
- acceptanceCriteria: z.array(z.string()),
18
- priority: z.number().int().positive(),
19
- passes: z.boolean(),
20
- notes: z.string(),
24
+ var policyConfigSchema = z.object({
25
+ enabled: z.boolean().default(true),
26
+ discovery: policyDiscoveryConfigSchema.prefault({}),
27
+ issues: policyIssuesDeclarationSchema.prefault({}),
28
+ pullRequests: policyPullRequestsDeclarationSchema.prefault({}),
29
+ git: policyGitDeclarationSchema.prefault({})
30
+ });
31
+ var policyConfigInputSchema = z.object({
32
+ enabled: z.boolean().optional(),
33
+ // Spelled out rather than `policyDiscoveryConfigSchema.partial()`: in zod 4
34
+ // a `.default()` survives `.partial()`, so every toggle would come back
35
+ // materialized and the input layer would stop meaning "what the user wrote".
36
+ discovery: z.object({
37
+ issueTemplates: z.boolean().optional(),
38
+ pullRequestTemplate: z.boolean().optional(),
39
+ docs: z.boolean().optional(),
40
+ codeowners: z.boolean().optional(),
41
+ labels: z.boolean().optional(),
42
+ issueTypes: z.boolean().optional()
43
+ }).optional(),
44
+ issues: z.object({ titleConvention: z.string().nullish() }).optional(),
45
+ pullRequests: z.object({ baseBranch: z.string().nullish(), titleConvention: z.string().nullish() }).optional(),
46
+ git: z.object({ branchConvention: z.string().nullish(), commitConvention: z.string().nullish() }).optional()
47
+ });
48
+
49
+ // src/schemas.ts
50
+ import { z as z2 } from "zod";
51
+ var claudeUsageSchema = z2.object({
52
+ inputTokens: z2.number().optional(),
53
+ outputTokens: z2.number().optional(),
54
+ cacheReadTokens: z2.number().optional(),
55
+ cacheCreationTokens: z2.number().optional(),
56
+ costUsd: z2.number().optional()
57
+ });
58
+ var userStoryStatusSchema = z2.enum(["backlog", "in_progress", "in_review", "done"]);
59
+ var storyStageSchema = z2.enum([
60
+ "pending",
61
+ "executing",
62
+ "awaiting_review",
63
+ "in_review",
64
+ "in_correction",
65
+ "done",
66
+ "failed"
67
+ ]);
68
+ var userStorySchema = z2.object({
69
+ id: z2.string(),
70
+ title: z2.string(),
71
+ description: z2.string(),
72
+ acceptanceCriteria: z2.array(z2.string()),
73
+ priority: z2.number().int().positive(),
74
+ passes: z2.boolean(),
75
+ notes: z2.string(),
21
76
  ...claudeUsageSchema.shape,
22
- durationSeconds: z.number().optional(),
77
+ durationSeconds: z2.number().optional(),
23
78
  status: userStoryStatusSchema.optional(),
24
- dependencies: z.array(z.string()).optional()
79
+ dependencies: z2.array(z2.string()).optional(),
80
+ stage: storyStageSchema.optional(),
81
+ stageSince: z2.string().optional(),
82
+ stageDetail: z2.string().optional()
25
83
  });
26
- var pipelineStateSchema = z.object({
27
- analyzeCompleted: z.boolean().optional(),
28
- prdCompleted: z.boolean(),
29
- jsonCompleted: z.boolean(),
30
- executionCompleted: z.boolean(),
31
- reviewCompleted: z.boolean(),
32
- prCreated: z.boolean(),
33
- prReviewCompleted: z.boolean().optional()
84
+ var pipelineStateSchema = z2.object({
85
+ analyzeCompleted: z2.boolean().optional(),
86
+ prdCompleted: z2.boolean(),
87
+ jsonCompleted: z2.boolean(),
88
+ executionCompleted: z2.boolean(),
89
+ reviewCompleted: z2.boolean(),
90
+ prCreated: z2.boolean(),
91
+ prReviewCompleted: z2.boolean().optional()
34
92
  });
35
- var pullRequestRefSchema = z.object({
36
- number: z.number().int().positive(),
37
- url: z.string(),
38
- headBranch: z.string(),
39
- createdAt: z.string()
93
+ var pullRequestRefSchema = z2.object({
94
+ number: z2.number().int().positive(),
95
+ url: z2.string(),
96
+ headBranch: z2.string(),
97
+ createdAt: z2.string()
40
98
  });
41
- var prReviewRecommendationSchema = z.enum([
99
+ var prReviewRecommendationSchema = z2.enum([
42
100
  "APPROVE",
43
101
  "APPROVE_WITH_SUGGESTIONS",
44
102
  "REQUEST_CHANGES"
45
103
  ]);
46
- var prReviewStateSchema = z.object({
47
- enabled: z.boolean().default(false),
48
- pullRequestNumber: z.number().int().positive().optional(),
49
- rounds: z.number().int().min(0).default(0),
104
+ var prReviewStateSchema = z2.object({
105
+ enabled: z2.boolean().default(false),
106
+ pullRequestNumber: z2.number().int().positive().optional(),
107
+ rounds: z2.number().int().min(0).default(0),
50
108
  lastRecommendation: prReviewRecommendationSchema.optional(),
51
- lastReviewedAt: z.string().optional()
109
+ lastReviewedAt: z2.string().optional()
52
110
  });
53
- var lastErrorSchema = z.object({
54
- category: z.string(),
55
- message: z.string(),
56
- at: z.string()
111
+ var lastErrorSchema = z2.object({
112
+ category: z2.string(),
113
+ message: z2.string(),
114
+ at: z2.string()
57
115
  });
58
- var issueMetadataSchema = z.object({
59
- schemaVersion: z.literal(1),
60
- id: z.string().min(1),
61
- number: z.number().int().positive().nullable(),
62
- source: z.enum(["github", "local"]),
63
- title: z.string(),
64
- labels: z.array(z.string()),
65
- state: z.enum(["open", "closed"]),
66
- createdAt: z.string(),
67
- updatedAt: z.string(),
68
- contentHash: z.string(),
69
- remote: z.object({
70
- provider: z.enum(["github", "local"]),
71
- ref: z.string(),
72
- syncedAt: z.string(),
73
- syncedContentHash: z.string()
116
+ var issueMetadataSchema = z2.object({
117
+ schemaVersion: z2.literal(1),
118
+ id: z2.string().min(1),
119
+ number: z2.number().int().positive().nullable(),
120
+ source: z2.enum(["github", "local"]),
121
+ title: z2.string(),
122
+ labels: z2.array(z2.string()),
123
+ state: z2.enum(["open", "closed"]),
124
+ createdAt: z2.string(),
125
+ updatedAt: z2.string(),
126
+ contentHash: z2.string(),
127
+ remote: z2.object({
128
+ provider: z2.enum(["github", "local"]),
129
+ ref: z2.string(),
130
+ syncedAt: z2.string(),
131
+ syncedContentHash: z2.string()
74
132
  }).optional()
75
133
  });
76
- var taskPlanSchema = z.object({
77
- project: z.string(),
78
- issueNumber: z.union([z.number().int().positive(), z.string().min(1)]),
79
- issueUrl: z.string().optional().default(""),
80
- branchName: z.string(),
81
- noBranch: z.boolean().optional().default(false),
82
- description: z.string(),
83
- issueStatus: z.enum(["pending", "in_progress", "completed"]),
84
- completedAt: z.string().nullable(),
85
- lastAttemptAt: z.string().nullable(),
134
+ var taskPlanSchema = z2.object({
135
+ project: z2.string(),
136
+ issueNumber: z2.union([z2.number().int().positive(), z2.string().min(1)]),
137
+ issueUrl: z2.string().optional().default(""),
138
+ branchName: z2.string(),
139
+ noBranch: z2.boolean().optional().default(false),
140
+ description: z2.string(),
141
+ issueStatus: z2.enum(["pending", "in_progress", "completed"]),
142
+ completedAt: z2.string().nullable(),
143
+ lastAttemptAt: z2.string().nullable(),
86
144
  lastError: lastErrorSchema.nullable(),
87
- correctionCycle: z.number().int().min(0),
88
- maxCorrectionCycles: z.number().int().min(0),
145
+ correctionCycle: z2.number().int().min(0),
146
+ maxCorrectionCycles: z2.number().int().min(0),
89
147
  /**
90
148
  * Findings from the most recent failed review, verbatim. Non-null means the
91
149
  * issue has a pending correction even if every userStories[].passes is
92
150
  * already true — the execute phase must address these before the field is
93
151
  * cleared back to null. See core/engine.ts's early-return guards.
94
152
  */
95
- lastReviewFindings: z.string().nullable().optional().default(null),
153
+ lastReviewFindings: z2.string().nullable().optional().default(null),
96
154
  pipeline: pipelineStateSchema,
97
155
  pullRequest: pullRequestRefSchema.optional(),
98
156
  prReview: prReviewStateSchema.optional(),
99
- userStories: z.array(userStorySchema)
157
+ userStories: z2.array(userStorySchema)
100
158
  });
101
- var headlessResultSchema = z.object({
102
- success: z.boolean(),
103
- result: z.string(),
159
+ var headlessResultSchema = z2.object({
160
+ success: z2.boolean(),
161
+ result: z2.string(),
104
162
  cost: claudeUsageSchema.nullable(),
105
- error: z.string().nullable()
163
+ error: z2.string().nullable()
106
164
  });
107
- var sessionLogEntrySchema = z.object({
108
- at: z.string(),
109
- level: z.enum(["info", "warn", "error"]),
110
- message: z.string()
165
+ var sessionLogEntrySchema = z2.object({
166
+ at: z2.string(),
167
+ level: z2.enum(["info", "warn", "error"]),
168
+ message: z2.string()
111
169
  });
112
170
  var sessionUsageShape = {
113
- inputTokens: z.number().nullable().default(null),
114
- outputTokens: z.number().nullable().default(null),
115
- cacheReadTokens: z.number().nullable().default(null),
116
- cacheCreationTokens: z.number().nullable().default(null),
117
- costUsd: z.number().nullable().default(null)
171
+ inputTokens: z2.number().nullable().default(null),
172
+ outputTokens: z2.number().nullable().default(null),
173
+ cacheReadTokens: z2.number().nullable().default(null),
174
+ cacheCreationTokens: z2.number().nullable().default(null),
175
+ costUsd: z2.number().nullable().default(null)
118
176
  };
119
- var sessionPhaseSchema = z.object({
120
- name: z.string(),
121
- status: z.enum(["pending", "running", "completed", "failed"]),
122
- startedAt: z.string().nullable(),
123
- endedAt: z.string().nullable(),
124
- durationSeconds: z.number().nullable(),
125
- error: z.string().nullable(),
177
+ var sessionPhaseSchema = z2.object({
178
+ name: z2.string(),
179
+ status: z2.enum(["pending", "running", "completed", "failed"]),
180
+ startedAt: z2.string().nullable(),
181
+ endedAt: z2.string().nullable(),
182
+ durationSeconds: z2.number().nullable(),
183
+ error: z2.string().nullable(),
126
184
  ...sessionUsageShape
127
185
  });
128
- var sessionStorySchema = z.object({
129
- id: z.string(),
130
- title: z.string(),
131
- priority: z.number(),
132
- passes: z.boolean(),
133
- completedAt: z.string().nullable(),
186
+ var sessionStorySchema = z2.object({
187
+ id: z2.string(),
188
+ title: z2.string(),
189
+ priority: z2.number(),
190
+ passes: z2.boolean(),
191
+ completedAt: z2.string().nullable(),
134
192
  // Also introduced with the metrics, hence the same tolerant default.
135
- durationSeconds: z.number().nullable().default(null),
193
+ durationSeconds: z2.number().nullable().default(null),
136
194
  // Snapshot fields are always present on output and defaulted on input, so a
137
195
  // session.json written before they existed still parses. This is the mirror
138
196
  // image of userStorySchema, where the same two fields are plainly optional.
139
197
  status: userStoryStatusSchema.default("backlog"),
140
- dependencies: z.array(z.string()).default([]),
198
+ dependencies: z2.array(z2.string()).default([]),
141
199
  // Published for the panel's story detail view. Same tolerant default as the
142
200
  // fields above: absent (older session.json) and empty resolve to the same
143
201
  // value, so the client never has to tell them apart.
144
- description: z.string().default(""),
145
- acceptanceCriteria: z.array(z.string()).default([]),
202
+ description: z2.string().default(""),
203
+ acceptanceCriteria: z2.array(z2.string()).default([]),
204
+ // Additive like the rest of this schema: a session.json written before
205
+ // `stage` existed parses into 'pending'/null, the same values a fresh
206
+ // snapshot starts a story at.
207
+ stage: storyStageSchema.default("pending"),
208
+ stageSince: z2.string().nullable().default(null),
209
+ stageDetail: z2.string().nullable().default(null),
146
210
  ...sessionUsageShape
147
211
  });
148
- var sessionSnapshotSchema = z.object({
149
- schemaVersion: z.literal(1),
150
- sessionId: z.string().nullable(),
151
- readOnly: z.literal(true),
152
- capabilities: z.array(z.string()),
153
- issue: z.object({
154
- number: z.number().nullable(),
155
- url: z.string().nullable(),
212
+ var sessionSnapshotSchema = z2.object({
213
+ schemaVersion: z2.literal(1),
214
+ sessionId: z2.string().nullable(),
215
+ readOnly: z2.literal(true),
216
+ capabilities: z2.array(z2.string()),
217
+ issue: z2.object({
218
+ number: z2.number().nullable(),
219
+ url: z2.string().nullable(),
156
220
  // Additive: a session.json written before the Issue section was enriched
157
221
  // parses into the same "not reported" values createInitialSnapshot() uses.
158
- title: z.string().nullable().default(null),
159
- description: z.string().nullable().default(null),
160
- labels: z.array(z.string()).default([]),
161
- state: z.string().nullable().default(null)
222
+ title: z2.string().nullable().default(null),
223
+ description: z2.string().nullable().default(null),
224
+ labels: z2.array(z2.string()).default([]),
225
+ state: z2.string().nullable().default(null)
162
226
  }),
163
- status: z.enum(["idle", "running", "completed", "failed"]),
164
- startedAt: z.string().nullable(),
165
- updatedAt: z.string().nullable(),
166
- endedAt: z.string().nullable(),
167
- elapsedSeconds: z.number().nullable(),
168
- estimatedRemainingSeconds: z.number().nullable(),
169
- progress: z.object({
170
- percent: z.number(),
171
- phasesCompleted: z.number(),
172
- phasesTotal: z.number(),
173
- storiesCompleted: z.number(),
174
- storiesTotal: z.number()
227
+ status: z2.enum(["idle", "running", "completed", "failed"]),
228
+ startedAt: z2.string().nullable(),
229
+ updatedAt: z2.string().nullable(),
230
+ endedAt: z2.string().nullable(),
231
+ elapsedSeconds: z2.number().nullable(),
232
+ estimatedRemainingSeconds: z2.number().nullable(),
233
+ progress: z2.object({
234
+ percent: z2.number(),
235
+ phasesCompleted: z2.number(),
236
+ phasesTotal: z2.number(),
237
+ storiesCompleted: z2.number(),
238
+ storiesTotal: z2.number()
175
239
  }),
176
- currentPhase: z.string().nullable(),
177
- currentActivity: z.object({
178
- story: z.string().nullable(),
179
- tool: z.string().nullable(),
180
- detail: z.string().nullable(),
181
- since: z.string()
240
+ currentPhase: z2.string().nullable(),
241
+ currentActivity: z2.object({
242
+ story: z2.string().nullable(),
243
+ tool: z2.string().nullable(),
244
+ detail: z2.string().nullable(),
245
+ since: z2.string()
182
246
  }).nullable(),
183
- phases: z.array(sessionPhaseSchema),
184
- stories: z.array(sessionStorySchema),
247
+ phases: z2.array(sessionPhaseSchema),
248
+ stories: z2.array(sessionStorySchema),
185
249
  // The whole aggregate is additive: a snapshot from before it existed parses
186
250
  // into the same "nothing reported" object the reducer starts from.
187
- metrics: z.object({
188
- totalInputTokens: z.number().nullable().default(null),
189
- totalOutputTokens: z.number().nullable().default(null),
190
- totalCacheReadTokens: z.number().nullable().default(null),
191
- totalCacheCreationTokens: z.number().nullable().default(null),
192
- totalCostUsd: z.number().nullable().default(null)
251
+ metrics: z2.object({
252
+ totalInputTokens: z2.number().nullable().default(null),
253
+ totalOutputTokens: z2.number().nullable().default(null),
254
+ totalCacheReadTokens: z2.number().nullable().default(null),
255
+ totalCacheCreationTokens: z2.number().nullable().default(null),
256
+ totalCostUsd: z2.number().nullable().default(null)
193
257
  }).default({
194
258
  totalInputTokens: null,
195
259
  totalOutputTokens: null,
@@ -197,51 +261,51 @@ var sessionSnapshotSchema = z.object({
197
261
  totalCacheCreationTokens: null,
198
262
  totalCostUsd: null
199
263
  }),
200
- execution: z.object({
201
- iteration: z.number(),
202
- retries: z.number(),
203
- correctionCycle: z.number(),
204
- maxCorrectionCycles: z.number().nullable()
264
+ execution: z2.object({
265
+ iteration: z2.number(),
266
+ retries: z2.number(),
267
+ correctionCycle: z2.number(),
268
+ maxCorrectionCycles: z2.number().nullable()
205
269
  }),
206
- git: z.object({
207
- branch: z.string().nullable(),
208
- baseBranch: z.string().nullable(),
209
- commits: z.array(z.object({ hash: z.string(), subject: z.string() }))
270
+ git: z2.object({
271
+ branch: z2.string().nullable(),
272
+ baseBranch: z2.string().nullable(),
273
+ commits: z2.array(z2.object({ hash: z2.string(), subject: z2.string() }))
210
274
  }),
211
275
  // Additive like the metrics aggregate: a session.json written before the
212
276
  // repository section existed parses into the same all-null object
213
277
  // createInitialSnapshot() starts from.
214
- repository: z.object({
215
- name: z.string().nullable().default(null),
216
- remoteUrl: z.string().nullable().default(null),
217
- branch: z.string().nullable().default(null),
218
- headCommit: z.string().nullable().default(null),
219
- root: z.string().nullable().default(null)
278
+ repository: z2.object({
279
+ name: z2.string().nullable().default(null),
280
+ remoteUrl: z2.string().nullable().default(null),
281
+ branch: z2.string().nullable().default(null),
282
+ headCommit: z2.string().nullable().default(null),
283
+ root: z2.string().nullable().default(null)
220
284
  }).default({ name: null, remoteUrl: null, branch: null, headCommit: null, root: null }),
221
- pullRequests: z.array(z.object({ number: z.number(), url: z.string(), title: z.string() })),
222
- logs: z.array(sessionLogEntrySchema),
223
- errors: z.array(sessionLogEntrySchema),
224
- warnings: z.array(sessionLogEntrySchema),
225
- lastError: z.object({ message: z.string(), at: z.string() }).nullable(),
226
- nextSteps: z.array(z.string()),
227
- environment: z.object({ node: z.string(), platform: z.string() }).nullable()
285
+ pullRequests: z2.array(z2.object({ number: z2.number(), url: z2.string(), title: z2.string() })),
286
+ logs: z2.array(sessionLogEntrySchema),
287
+ errors: z2.array(sessionLogEntrySchema),
288
+ warnings: z2.array(sessionLogEntrySchema),
289
+ lastError: z2.object({ message: z2.string(), at: z2.string() }).nullable(),
290
+ nextSteps: z2.array(z2.string()),
291
+ environment: z2.object({ node: z2.string(), platform: z2.string() }).nullable()
228
292
  });
229
- var webConfigSchema = z.object({
230
- enabled: z.boolean().default(false),
231
- port: z.number().int().min(1).max(65535).default(3737),
232
- host: z.string().min(1).default("0.0.0.0"),
233
- refreshSeconds: z.number().positive().default(5),
234
- logLimit: z.number().int().positive().default(200),
235
- includeLogs: z.boolean().default(true)
293
+ var webConfigSchema = z2.object({
294
+ enabled: z2.boolean().default(false),
295
+ port: z2.number().int().min(1).max(65535).default(3737),
296
+ host: z2.string().min(1).default("0.0.0.0"),
297
+ refreshSeconds: z2.number().positive().default(5),
298
+ logLimit: z2.number().int().positive().default(200),
299
+ includeLogs: z2.boolean().default(true)
236
300
  });
237
- var issuesConfigSchema = z.object({
238
- defaultGenerateTarget: z.enum(["github", "local", "both"]).default("github"),
239
- preferredProvider: z.enum(["github", "local"]).default("github"),
240
- conflictPolicy: z.enum(["ask", "prefer-local", "prefer-github"]).default("ask"),
241
- requireConfirmation: z.boolean().default(true)
301
+ var issuesConfigSchema = z2.object({
302
+ defaultGenerateTarget: z2.enum(["github", "local", "both"]).default("github"),
303
+ preferredProvider: z2.enum(["github", "local"]).default("github"),
304
+ conflictPolicy: z2.enum(["ask", "prefer-local", "prefer-github"]).default("ask"),
305
+ requireConfirmation: z2.boolean().default(true)
242
306
  });
243
- var prReviewConfigSchema = z.object({
244
- publisher: z.enum(["local"]).default("local")
307
+ var prReviewConfigSchema = z2.object({
308
+ publisher: z2.enum(["local"]).default("local")
245
309
  });
246
310
 
247
311
  // src/core/session-state.ts
@@ -378,6 +442,22 @@ function reduceSessionEvent(snapshot, event, options) {
378
442
  nextSteps: deriveNextSteps(next)
379
443
  };
380
444
  }
445
+ function isTerminalStage(stage) {
446
+ return stage === "done" || stage === "failed";
447
+ }
448
+ function deriveStageOnStoriesUpdate(story, before, at) {
449
+ if (!story.passes) {
450
+ return {
451
+ stage: before?.stage ?? "pending",
452
+ stageSince: before?.stageSince ?? at,
453
+ stageDetail: before?.stageDetail ?? null
454
+ };
455
+ }
456
+ if (before?.passes) {
457
+ return { stage: before.stage, stageSince: before.stageSince, stageDetail: before.stageDetail };
458
+ }
459
+ return { stage: "awaiting_review", stageSince: at, stageDetail: null };
460
+ }
381
461
  function applyEvent(snapshot, event, options) {
382
462
  switch (event.type) {
383
463
  case "session:start": {
@@ -448,10 +528,14 @@ function applyEvent(snapshot, event, options) {
448
528
  ...emptyUsage()
449
529
  }
450
530
  ];
531
+ const stories = event.phase === "review" ? snapshot.stories.map(
532
+ (story) => story.passes ? { ...story, stage: "in_review", stageSince: event.at, stageDetail: null } : story
533
+ ) : snapshot.stories;
451
534
  return {
452
535
  ...snapshot,
453
536
  currentPhase: event.phase,
454
537
  phases,
538
+ stories,
455
539
  progress: known ? snapshot.progress : { ...snapshot.progress, phasesTotal: phases.length }
456
540
  };
457
541
  }
@@ -466,11 +550,17 @@ function applyEvent(snapshot, event, options) {
466
550
  } : p
467
551
  );
468
552
  const phasesCompleted = phases.filter((p) => p.status === "completed").length;
553
+ const stories = !event.success ? snapshot.stories.map(
554
+ (story) => isTerminalStage(story.stage) ? story : { ...story, stage: "failed", stageSince: event.at, stageDetail: null }
555
+ ) : event.phase === "review" ? snapshot.stories.map(
556
+ (story) => story.passes ? { ...story, stage: "done", stageSince: event.at, stageDetail: null } : story
557
+ ) : snapshot.stories;
469
558
  return {
470
559
  ...snapshot,
471
560
  currentPhase: snapshot.currentPhase === event.phase ? null : snapshot.currentPhase,
472
561
  currentActivity: null,
473
562
  phases,
563
+ stories,
474
564
  progress: {
475
565
  ...snapshot.progress,
476
566
  phasesCompleted,
@@ -478,11 +568,27 @@ function applyEvent(snapshot, event, options) {
478
568
  }
479
569
  };
480
570
  }
481
- case "iteration:start":
571
+ case "iteration:start": {
572
+ const storyId = event.storyId;
573
+ const stories = snapshot.stories.map((story) => {
574
+ if (story.passes) return story;
575
+ if (story.id === storyId) {
576
+ return story.stage === "executing" ? story : { ...story, stage: "executing", stageSince: event.at, stageDetail: null };
577
+ }
578
+ return story.stage === "pending" ? story : { ...story, stage: "pending", stageSince: event.at, stageDetail: null };
579
+ });
482
580
  return {
483
581
  ...snapshot,
484
- execution: { ...snapshot.execution, iteration: event.iteration }
582
+ execution: { ...snapshot.execution, iteration: event.iteration },
583
+ stories,
584
+ // Finally populates the `story` field of the activity payload during
585
+ // execute — today this phase never publishes an `activity` event at
586
+ // all (no streaming), so `currentActivity` stays whatever an earlier
587
+ // phase left it at. Left untouched when storyId is absent (every
588
+ // story already passes, or the caller could not determine one).
589
+ currentActivity: storyId !== void 0 ? { story: storyId, tool: null, detail: null, since: event.at } : snapshot.currentActivity
485
590
  };
591
+ }
486
592
  case "iteration:end":
487
593
  return { ...snapshot, currentActivity: null };
488
594
  case "retry":
@@ -516,7 +622,8 @@ function applyEvent(snapshot, event, options) {
516
622
  outputTokens: before?.outputTokens ?? null,
517
623
  cacheReadTokens: before?.cacheReadTokens ?? null,
518
624
  cacheCreationTokens: before?.cacheCreationTokens ?? null,
519
- costUsd: before?.costUsd ?? null
625
+ costUsd: before?.costUsd ?? null,
626
+ ...deriveStageOnStoriesUpdate(story, before, event.at)
520
627
  };
521
628
  });
522
629
  return {
@@ -566,15 +673,21 @@ function applyEvent(snapshot, event, options) {
566
673
  },
567
674
  pullRequests: event.pullRequests ?? snapshot.pullRequests
568
675
  };
569
- case "correction:cycle":
676
+ case "correction:cycle": {
677
+ const stageDetail = `Cycle ${event.cycle}/${event.maxCycles}`;
678
+ const stories = snapshot.stories.map(
679
+ (story) => story.passes ? { ...story, stage: "in_correction", stageSince: event.at, stageDetail } : story
680
+ );
570
681
  return {
571
682
  ...snapshot,
572
683
  execution: {
573
684
  ...snapshot.execution,
574
685
  correctionCycle: event.cycle,
575
686
  maxCorrectionCycles: event.maxCycles
576
- }
687
+ },
688
+ stories
577
689
  };
690
+ }
578
691
  case "metrics:update": {
579
692
  if (event.scope === "story") {
580
693
  if (event.storyId === void 0) return snapshot;
@@ -620,6 +733,15 @@ function applyEvent(snapshot, event, options) {
620
733
  endedAt: event.at,
621
734
  currentPhase: null,
622
735
  currentActivity: null,
736
+ // Close every non-terminal stage: the run is over, so nothing can be
737
+ // 'executing'/'in_review'/'in_correction' any more. A story that never
738
+ // reached `passes` on a run that did not complete is exactly what the
739
+ // 'failed' stage means; anything else settles as 'done'.
740
+ stories: snapshot.stories.map((story) => {
741
+ if (isTerminalStage(story.stage)) return story;
742
+ const stage = event.status === "completed" && story.passes ? "done" : "failed";
743
+ return { ...story, stage, stageSince: event.at, stageDetail: null };
744
+ }),
623
745
  lastError: event.error ? { message: stripVTControlCharacters(event.error), at: event.at } : snapshot.lastError
624
746
  };
625
747
  default:
@@ -930,6 +1052,9 @@ function allStoriesPass(plan) {
930
1052
  }
931
1053
  return plan.userStories.every((story) => story.passes === true);
932
1054
  }
1055
+ function selectActiveStory(stories) {
1056
+ return [...stories].filter((story) => !story.passes).sort((a, b) => a.priority - b.priority)[0];
1057
+ }
933
1058
  function applyStoryMetrics(plan, storyIds, share, durationSeconds) {
934
1059
  if (storyIds.length === 0) return plan;
935
1060
  const targets = new Set(storyIds);
@@ -1018,6 +1143,13 @@ function setStoryUpdateCallback(callback) {
1018
1143
  function getStoryUpdateCallback() {
1019
1144
  return _onStoryUpdate;
1020
1145
  }
1146
+ var _onStoryStage;
1147
+ function setStoryStageCallback(callback) {
1148
+ _onStoryStage = callback;
1149
+ }
1150
+ function getStoryStageCallback() {
1151
+ return _onStoryStage;
1152
+ }
1021
1153
  var _globalTimeout;
1022
1154
  function setGlobalTimeout(ms) {
1023
1155
  _globalTimeout = ms;
@@ -1173,6 +1305,9 @@ var ElapsedTimer = class {
1173
1305
  };
1174
1306
 
1175
1307
  export {
1308
+ policyConfigSchema,
1309
+ policyConfigInputSchema,
1310
+ pullRequestRefSchema,
1176
1311
  issueMetadataSchema,
1177
1312
  taskPlanSchema,
1178
1313
  sessionSnapshotSchema,
@@ -1195,6 +1330,7 @@ export {
1195
1330
  initializeState,
1196
1331
  hasPendingCorrection,
1197
1332
  allStoriesPass,
1333
+ selectActiveStory,
1198
1334
  applyStoryMetrics,
1199
1335
  markIssueInProgress,
1200
1336
  markIssueCompleted,
@@ -1207,6 +1343,8 @@ export {
1207
1343
  getOutputCallback,
1208
1344
  setStoryUpdateCallback,
1209
1345
  getStoryUpdateCallback,
1346
+ setStoryStageCallback,
1347
+ getStoryStageCallback,
1210
1348
  setGlobalTimeout,
1211
1349
  getGlobalTimeout,
1212
1350
  useUnicode,
@@ -1222,4 +1360,4 @@ export {
1222
1360
  formatDuration,
1223
1361
  ElapsedTimer
1224
1362
  };
1225
- //# sourceMappingURL=chunk-BH7DYADV.js.map
1363
+ //# sourceMappingURL=chunk-V5OHFSW4.js.map