@llm4ts/flow 2.0.0 → 2.2.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 (70) hide show
  1. package/dist/Approval.d.ts +1 -1
  2. package/dist/Approval.d.ts.map +1 -1
  3. package/dist/Artifacts.d.ts +2 -2
  4. package/dist/Artifacts.d.ts.map +1 -1
  5. package/dist/BenchReport.d.ts +2 -2
  6. package/dist/BenchReport.d.ts.map +1 -1
  7. package/dist/BoardSync.d.ts +12 -5
  8. package/dist/BoardSync.d.ts.map +1 -1
  9. package/dist/BoardSync.js +27 -6
  10. package/dist/BoardSync.js.map +1 -1
  11. package/dist/CostLedger.d.ts +2 -2
  12. package/dist/CostLedger.d.ts.map +1 -1
  13. package/dist/Decisions.d.ts +187 -0
  14. package/dist/Decisions.d.ts.map +1 -0
  15. package/dist/Decisions.js +677 -0
  16. package/dist/Decisions.js.map +1 -0
  17. package/dist/Domains.d.ts +125 -0
  18. package/dist/Domains.d.ts.map +1 -0
  19. package/dist/Domains.js +528 -0
  20. package/dist/Domains.js.map +1 -0
  21. package/dist/Equiv.d.ts +3 -3
  22. package/dist/Equiv.d.ts.map +1 -1
  23. package/dist/Flow.d.ts +1 -1
  24. package/dist/Flow.d.ts.map +1 -1
  25. package/dist/FlowError.d.ts +25 -1
  26. package/dist/FlowError.d.ts.map +1 -1
  27. package/dist/FlowError.js +33 -1
  28. package/dist/FlowError.js.map +1 -1
  29. package/dist/Pack.d.ts +16 -0
  30. package/dist/Pack.d.ts.map +1 -1
  31. package/dist/Pack.js +53 -1
  32. package/dist/Pack.js.map +1 -1
  33. package/dist/PageSpec.d.ts +21 -7
  34. package/dist/PageSpec.d.ts.map +1 -1
  35. package/dist/PageSpec.js +83 -14
  36. package/dist/PageSpec.js.map +1 -1
  37. package/dist/Persistence.d.ts +2 -2
  38. package/dist/Persistence.d.ts.map +1 -1
  39. package/dist/PlanExecution.d.ts +1 -1
  40. package/dist/PlanExecution.d.ts.map +1 -1
  41. package/dist/ProgramJudge.d.ts +1 -1
  42. package/dist/ProgramJudge.d.ts.map +1 -1
  43. package/dist/Replay.d.ts +2 -2
  44. package/dist/Replay.d.ts.map +1 -1
  45. package/dist/Review.d.ts +2 -2
  46. package/dist/Review.d.ts.map +1 -1
  47. package/dist/ReviewCache.d.ts +1 -1
  48. package/dist/ReviewCache.d.ts.map +1 -1
  49. package/dist/SpecChecks.d.ts +8 -0
  50. package/dist/SpecChecks.d.ts.map +1 -1
  51. package/dist/SpecChecks.js +7 -1
  52. package/dist/SpecChecks.js.map +1 -1
  53. package/dist/Stories.d.ts +5 -4
  54. package/dist/Stories.d.ts.map +1 -1
  55. package/dist/Stories.js +20 -10
  56. package/dist/Stories.js.map +1 -1
  57. package/dist/StoryPlan.d.ts +2 -1
  58. package/dist/StoryPlan.d.ts.map +1 -1
  59. package/dist/StoryPlan.js +1 -1
  60. package/dist/StoryPlan.js.map +1 -1
  61. package/package.json +4 -2
  62. package/src/BoardSync.ts +35 -6
  63. package/src/Decisions.ts +844 -0
  64. package/src/Domains.ts +650 -0
  65. package/src/FlowError.ts +41 -1
  66. package/src/Pack.ts +79 -1
  67. package/src/PageSpec.ts +132 -8
  68. package/src/SpecChecks.ts +15 -1
  69. package/src/Stories.ts +20 -10
  70. package/src/StoryPlan.ts +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llm4ts/flow",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Effect-native LLM workflow, persistence, review, and repository automation",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,6 +28,8 @@
28
28
  "./Context": "./dist/Context.js",
29
29
  "./CostLedger": "./dist/CostLedger.js",
30
30
  "./CostTracker": "./dist/CostTracker.js",
31
+ "./Decisions": "./dist/Decisions.js",
32
+ "./Domains": "./dist/Domains.js",
31
33
  "./Equiv": "./dist/Equiv.js",
32
34
  "./EquivReport": "./dist/EquivReport.js",
33
35
  "./EstimatedUsage": "./dist/EstimatedUsage.js",
@@ -91,7 +93,7 @@
91
93
  "typescript"
92
94
  ],
93
95
  "dependencies": {
94
- "@llm4ts/core": "2.0.0"
96
+ "@llm4ts/core": "2.2.0"
95
97
  },
96
98
  "peerDependencies": {
97
99
  "effect": "4.0.0-rc.115"
package/src/BoardSync.ts CHANGED
@@ -7,7 +7,7 @@ import { FlowAborted, type FlowError } from "./FlowError.ts"
7
7
  import { loadVersioned, saveVersioned, type PlainFileStoreShape } from "./Persistence.ts"
8
8
 
9
9
  // The progress board of the conversion scenario: a port with the work-item
10
- // lifecycle (plan → start → complete/fail/skip) and two adapters — a local
10
+ // lifecycle (plan → start → complete/fail/wait/skip) and two adapters — a local
11
11
  // file board (the default, fully offline: board.json + rendered board.md)
12
12
  // and an Azure DevOps adapter (the stretch goal) mapping the same lifecycle
13
13
  // onto work items. Flows depend only on the port; which board the client
@@ -15,7 +15,14 @@ import { loadVersioned, saveVersioned, type PlainFileStoreShape } from "./Persis
15
15
 
16
16
  export const BoardVersion = 1
17
17
 
18
- export const BoardStatus = Schema.Literals(["planned", "active", "done", "failed", "skipped"])
18
+ export const BoardStatus = Schema.Literals([
19
+ "planned",
20
+ "active",
21
+ "waiting",
22
+ "done",
23
+ "failed",
24
+ "skipped"
25
+ ])
19
26
  export type BoardStatus = typeof BoardStatus.Type
20
27
 
21
28
  export class BoardItem extends Schema.Class<BoardItem>("BoardItem")({
@@ -25,7 +32,7 @@ export class BoardItem extends Schema.Class<BoardItem>("BoardItem")({
25
32
  status: BoardStatus,
26
33
  branch: Schema.optionalKey(Schema.String),
27
34
  reportPath: Schema.optionalKey(Schema.String),
28
- /** Free-form note: a failure reason, a skip rationale, a triage disposition. */
35
+ /** Free-form note: a failure reason, what an item waits for, a triage disposition. */
29
36
  detail: Schema.optionalKey(Schema.String),
30
37
  /** ESTIMATES, never measurements — see EstimatedUsage (ADR 0012). */
31
38
  estimatedTokens: Schema.optionalKey(Schema.Int),
@@ -51,13 +58,20 @@ export interface BoardSyncShape {
51
58
  readonly start: (id: string) => Effect.Effect<void, FlowError>
52
59
  readonly complete: (id: string, result: BoardItemResult) => Effect.Effect<void, FlowError>
53
60
  readonly fail: (id: string, reason: string) => Effect.Effect<void, FlowError>
61
+ /** Final: the item is deliberately left out (a page triaged as dead, say). */
54
62
  readonly skip: (id: string, reason: string) => Effect.Effect<void, FlowError>
63
+ /**
64
+ * On hold: the item waits for something that failed (a predecessor story)
65
+ * and runs once that is fixed — unlike `skip`, it is not final.
66
+ */
67
+ readonly wait: (id: string, reason: string) => Effect.Effect<void, FlowError>
55
68
  readonly snapshot: Effect.Effect<Board, FlowError>
56
69
  }
57
70
 
58
71
  const sectionOrder: ReadonlyArray<readonly [BoardStatus, string]> = [
59
72
  ["active", "Active"],
60
73
  ["planned", "Planned"],
74
+ ["waiting", "Waiting"],
61
75
  ["done", "Done"],
62
76
  ["failed", "Failed"],
63
77
  ["skipped", "Skipped"]
@@ -193,6 +207,8 @@ export const makeLocalBoardSync = (
193
207
  update(id, (item) => BoardItem.make({ ...item, status: "failed", detail: reason })),
194
208
  skip: (id, reason) =>
195
209
  update(id, (item) => BoardItem.make({ ...item, status: "skipped", detail: reason })),
210
+ wait: (id, reason) =>
211
+ update(id, (item) => BoardItem.make({ ...item, status: "waiting", detail: reason })),
196
212
  snapshot: load
197
213
  }
198
214
  }
@@ -213,6 +229,7 @@ export const composeBoardSync = (boards: ReadonlyArray<BoardSyncShape>): BoardSy
213
229
  complete: (id, result) => each((board) => board.complete(id, result)),
214
230
  fail: (id, reason) => each((board) => board.fail(id, reason)),
215
231
  skip: (id, reason) => each((board) => board.skip(id, reason)),
232
+ wait: (id, reason) => each((board) => board.wait(id, reason)),
216
233
  snapshot:
217
234
  first === undefined
218
235
  ? Effect.succeed(Board.make({ title: "empty", items: [] }))
@@ -242,8 +259,9 @@ const markerQuery = (tag: string, id: string): string =>
242
259
  * The stretch adapter (ADR 0012): the same lifecycle mapped onto Azure DevOps
243
260
  * work items through the az-CLI AzureDevOpsTool (ADR 0011). Idempotent by
244
261
  * title marker — `[<id>]` plus the board tag — so a re-run finds its items
245
- * instead of duplicating them. Failure and skip are tags plus a comment,
246
- * never invented states.
262
+ * instead of duplicating them. Failure, waiting and skip are tags plus a
263
+ * comment, never invented states; a waiting tag is lifted when the item is
264
+ * started again.
247
265
  */
248
266
  export const makeAdoBoardSync = Effect.fn("@llm4ts/flow/BoardSync.makeAdo")(function* (
249
267
  ado: AzureDevOpsToolShape,
@@ -334,6 +352,12 @@ export const makeAdoBoardSync = Effect.fn("@llm4ts/flow/BoardSync.makeAdo")(func
334
352
  yield* ado.editTags(workItem, [`${tag}-skipped`], [])
335
353
  yield* ado.writeComment(workItem, `SKIPPED: ${reason}`)
336
354
  }),
355
+ wait: (id, reason) =>
356
+ Effect.gen(function* () {
357
+ const workItem = yield* lookup(id)
358
+ yield* ado.editTags(workItem, [`${tag}-waiting`], [])
359
+ yield* ado.writeComment(workItem, `WAITING: ${reason}`)
360
+ }),
337
361
  snapshot: Effect.gen(function* () {
338
362
  const found = yield* ado.wiqlIds(
339
363
  `SELECT [System.Id] FROM WorkItems WHERE [System.Tags] CONTAINS ${quoteWiql(tag)}`
@@ -344,6 +368,9 @@ export const makeAdoBoardSync = Effect.fn("@llm4ts/flow/BoardSync.makeAdo")(func
344
368
  const match = /^\[([^\]]+)\] (.*)$/.exec(workItem.title)
345
369
  const failed = workItem.tags.includes(`${tag}-failed`)
346
370
  const skipped = workItem.tags.includes(`${tag}-skipped`)
371
+ const waiting = workItem.tags.includes(`${tag}-waiting`)
372
+ // A live state outranks a waiting tag: an item started again after
373
+ // its predecessor was fixed is active, whatever tag it still carries.
347
374
  const status: BoardStatus = failed
348
375
  ? "failed"
349
376
  : skipped
@@ -352,7 +379,9 @@ export const makeAdoBoardSync = Effect.fn("@llm4ts/flow/BoardSync.makeAdo")(func
352
379
  ? "done"
353
380
  : workItem.state === states.active
354
381
  ? "active"
355
- : "planned"
382
+ : waiting
383
+ ? "waiting"
384
+ : "planned"
356
385
  items.push(
357
386
  BoardItem.make({
358
387
  id: match?.[1] ?? String(workItemId),