@llm4ts/flow 2.9.6 → 2.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 (51) 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/CostLedger.d.ts +2 -2
  8. package/dist/CostLedger.d.ts.map +1 -1
  9. package/dist/Equiv.d.ts +3 -3
  10. package/dist/Equiv.d.ts.map +1 -1
  11. package/dist/Flow.d.ts +1 -1
  12. package/dist/Flow.d.ts.map +1 -1
  13. package/dist/FlowError.d.ts +18 -1
  14. package/dist/FlowError.d.ts.map +1 -1
  15. package/dist/FlowError.js +21 -0
  16. package/dist/FlowError.js.map +1 -1
  17. package/dist/GitTool.d.ts +8 -0
  18. package/dist/GitTool.d.ts.map +1 -1
  19. package/dist/GitTool.js +17 -0
  20. package/dist/GitTool.js.map +1 -1
  21. package/dist/Judgment.d.ts +2 -2
  22. package/dist/Judgment.d.ts.map +1 -1
  23. package/dist/Landing.d.ts +35 -0
  24. package/dist/Landing.d.ts.map +1 -0
  25. package/dist/Landing.js +122 -0
  26. package/dist/Landing.js.map +1 -0
  27. package/dist/Persistence.d.ts +2 -2
  28. package/dist/Persistence.d.ts.map +1 -1
  29. package/dist/PlanExecution.d.ts +1 -1
  30. package/dist/PlanExecution.d.ts.map +1 -1
  31. package/dist/ProgramJudge.d.ts +1 -1
  32. package/dist/ProgramJudge.d.ts.map +1 -1
  33. package/dist/Replay.d.ts +2 -2
  34. package/dist/Replay.d.ts.map +1 -1
  35. package/dist/Review.d.ts +3 -3
  36. package/dist/Review.d.ts.map +1 -1
  37. package/dist/ReviewCache.d.ts +1 -1
  38. package/dist/ReviewCache.d.ts.map +1 -1
  39. package/dist/Roster.d.ts +1 -1
  40. package/dist/Roster.d.ts.map +1 -1
  41. package/dist/Roster.js +9 -5
  42. package/dist/Roster.js.map +1 -1
  43. package/dist/RosterSeats.d.ts +1 -1
  44. package/dist/RosterSeats.d.ts.map +1 -1
  45. package/dist/Stories.d.ts +1 -1
  46. package/dist/Stories.d.ts.map +1 -1
  47. package/package.json +3 -2
  48. package/src/FlowError.ts +23 -0
  49. package/src/GitTool.ts +29 -0
  50. package/src/Landing.ts +182 -0
  51. package/src/Roster.ts +9 -5
@@ -1 +1 @@
1
- {"version":3,"file":"Stories.d.ts","sourceRoot":"","sources":["../src/Stories.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Stories.d.ts","sourceRoot":"","sources":["../src/Stories.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llm4ts/flow",
3
- "version": "2.9.6",
3
+ "version": "2.10.0",
4
4
  "description": "Effect-native LLM workflow, persistence, review, and repository automation",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,6 +41,7 @@
41
41
  "./FlowRecorder": "./dist/FlowRecorder.js",
42
42
  "./GitHubTool": "./dist/GitHubTool.js",
43
43
  "./GitTool": "./dist/GitTool.js",
44
+ "./Landing": "./dist/Landing.js",
44
45
  "./Interaction": "./dist/Interaction.js",
45
46
  "./McpServer": "./dist/McpServer.js",
46
47
  "./Mermaid": "./dist/Mermaid.js",
@@ -100,7 +101,7 @@
100
101
  "typescript"
101
102
  ],
102
103
  "dependencies": {
103
- "@llm4ts/core": "2.9.6"
104
+ "@llm4ts/core": "2.10.0"
104
105
  },
105
106
  "peerDependencies": {
106
107
  "effect": "4.0.0-rc.115"
package/src/FlowError.ts CHANGED
@@ -216,6 +216,27 @@ export class RosterInvalid extends Schema.TaggedError<RosterInvalid>()("RosterIn
216
216
  }
217
217
  }
218
218
 
219
+ /** An epic asked to land while some of its stories are not merged into the epic branch yet. */
220
+ export class EpicIncomplete extends Schema.TaggedError<EpicIncomplete>()("EpicIncomplete", {
221
+ epicId: Schema.String,
222
+ stories: Schema.Array(Schema.String)
223
+ }) {
224
+ get message(): string {
225
+ return `epic '${this.epicId}' is not finished; not merged yet: ${this.stories.join(", ")} — run the epic until every story merges, then land it`
226
+ }
227
+ }
228
+
229
+ /** Landing an epic failed; the target branch was left untouched. */
230
+ export class LandingFailed extends Schema.TaggedError<LandingFailed>()("LandingFailed", {
231
+ epicBranch: Schema.String,
232
+ target: Schema.String,
233
+ reason: Schema.String
234
+ }) {
235
+ get message(): string {
236
+ return `landing '${this.epicBranch}' on '${this.target}' failed, '${this.target}' is untouched: ${this.reason}`
237
+ }
238
+ }
239
+
219
240
  /** The start of every `RosterExhausted` message, so it is recognisable once wrapped. */
220
241
  export const rosterExhaustedPrefix = "roster exhausted: no executor can ever take the role"
221
242
 
@@ -302,6 +323,8 @@ export const FlowError = Schema.Union([
302
323
  EpicCheckoutDirty,
303
324
  RosterExhausted,
304
325
  RosterInvalid,
326
+ EpicIncomplete,
327
+ LandingFailed,
305
328
  StoryFailed,
306
329
  DecisionsInvalid,
307
330
  OpenPointsPending,
package/src/GitTool.ts CHANGED
@@ -99,6 +99,14 @@ export interface GitToolShape {
99
99
  message: string,
100
100
  options?: MergeOptions
101
101
  ) => Effect.Effect<void, FlowError>
102
+ /**
103
+ * Starts a merge of `branch` and stops before committing, conflicts left
104
+ * in place for someone to resolve: returns the conflicted paths (empty for
105
+ * a clean merge, still uncommitted). `commitAll` completes the merge and
106
+ * `rollback` to an earlier checkpoint abandons it. A merge git refuses to
107
+ * start fails typed, as `merge` does.
108
+ */
109
+ readonly mergeNoCommit: (branch: string) => Effect.Effect<ReadonlyArray<string>, FlowError>
102
110
  }
103
111
 
104
112
  export interface MergeOptions {
@@ -438,6 +446,27 @@ export const makeGitTool = (
438
446
  )
439
447
  )
440
448
  ),
449
+ mergeNoCommit: (branch) =>
450
+ write(
451
+ "git merge --no-commit",
452
+ Effect.gen(function* () {
453
+ const result = yield* run(["merge", "--no-ff", "--no-commit", branch])
454
+ if (result.exitCode === 0) {
455
+ return []
456
+ }
457
+ const unmerged = yield* run(["diff", "--name-only", "--diff-filter=U"])
458
+ const paths = text(unmerged.stdout)
459
+ .split(/\r?\n/)
460
+ .map((line) => line.trim())
461
+ .filter((line) => line.length > 0)
462
+ if (paths.length > 0) {
463
+ return paths
464
+ }
465
+ const into = yield* runOrFail(["rev-parse", "--abbrev-ref", "HEAD"])
466
+ yield* run(["merge", "--abort"])
467
+ return yield* MergeConflict.make({ branch, into, paths: [], detail: problem(result) })
468
+ })
469
+ ),
441
470
  merge: (branch, message, options = {}) =>
442
471
  write(
443
472
  "git merge",
package/src/Landing.ts ADDED
@@ -0,0 +1,182 @@
1
+ // Landing a finished epic (`epic-stories --land`): every story merged into the
2
+ // epic branch, the target (main by default) merged INTO the epic branch first
3
+ // so conflicts are resolved on the epic side, a coder resolving them in a
4
+ // bounded loop with the target's gates as the bar, and only then a merge
5
+ // commit on the target. Nothing touches the target until the epic branch is
6
+ // green with the target's history in it.
7
+ import * as Effect from "effect/Effect"
8
+ import type { LlmServiceShape } from "@llm4ts/core/LlmService"
9
+ import { makeChat } from "./Chat.ts"
10
+ import type { FlowContextShape } from "./FlowContext.ts"
11
+ import { EpicCheckoutDirty, EpicIncomplete, LandingFailed, type FlowError } from "./FlowError.ts"
12
+ import { Info } from "./FlowEvents.ts"
13
+ import { statusPaths } from "./GitTool.ts"
14
+ import { loadVersioned, type PlainFileStoreShape } from "./Persistence.ts"
15
+ import type { ReviewResult } from "./Review.ts"
16
+ import { StoryState, StoryStateVersion } from "./Stories.ts"
17
+ import type { StoryPlan } from "./StoryPlan.ts"
18
+
19
+ const join = (root: string, path: string): string =>
20
+ `${root.replace(/[\\/]+$/, "")}/${path.replace(/^[\\/]+/, "")}`
21
+
22
+ export interface LandOptions {
23
+ readonly plan: StoryPlan
24
+ readonly files: PlainFileStoreShape
25
+ /** The executor's state directory, where each story's state says whether it merged. */
26
+ readonly stateDir: string
27
+ /** Default `epic/<epicId>`. */
28
+ readonly epicBranch?: string
29
+ /** Default `main`. */
30
+ readonly target?: string
31
+ /** The target's gates, run in the epic checkout. */
32
+ readonly gates: (workDir: string) => Effect.Effect<ReviewResult, FlowError>
33
+ /** Who resolves conflicts and red gates. Default: the context's coder. */
34
+ readonly coder?: LlmServiceShape
35
+ /** House rules for the coder. */
36
+ readonly system?: string
37
+ /** Fix rounds before giving up. Default 3. */
38
+ readonly maxRounds?: number
39
+ }
40
+
41
+ export interface LandReport {
42
+ readonly epicBranch: string
43
+ readonly target: string
44
+ /** The target's paths that conflicted with the epic, if any. */
45
+ readonly conflicts: ReadonlyArray<string>
46
+ /** Coder rounds it took (0: clean and green on the first try). */
47
+ readonly rounds: number
48
+ }
49
+
50
+ const markerPattern = /^(<{7} |={7}$|>{7} )/m
51
+
52
+ const issueLines = (result: ReviewResult): string =>
53
+ result.issues
54
+ .map(
55
+ (issue) =>
56
+ `- ${issue.title}${issue.description.length === 0 ? "" : `: ${issue.description.slice(-1500)}`}`
57
+ )
58
+ .join("\n")
59
+
60
+ export const landEpic = Effect.fn("@llm4ts/flow/Landing.land")(function* (
61
+ context: FlowContextShape,
62
+ options: LandOptions
63
+ ): Effect.fn.Return<LandReport, FlowError> {
64
+ const { plan, files } = options
65
+ const git = context.git
66
+ const events = context.events
67
+ const epicBranch = options.epicBranch ?? `epic/${plan.epicId}`
68
+ const target = options.target ?? "main"
69
+ const maxRounds = Math.max(1, options.maxRounds ?? 3)
70
+ const say = (message: string) => events.publish(Info.make({ message: `land: ${message}` }))
71
+ const failed = (reason: string) => LandingFailed.make({ epicBranch, target, reason })
72
+
73
+ // 1. Only a finished epic lands.
74
+ const unmerged: Array<string> = []
75
+ for (const story of plan.stories) {
76
+ const state = yield* loadVersioned(
77
+ files,
78
+ join(options.stateDir, `stories/${story.id}.json`),
79
+ StoryStateVersion,
80
+ StoryState
81
+ )
82
+ if (state?.status !== "merged") {
83
+ unmerged.push(story.id)
84
+ }
85
+ }
86
+ if (unmerged.length > 0) {
87
+ return yield* EpicIncomplete.make({ epicId: plan.epicId, stories: unmerged })
88
+ }
89
+ if (!(yield* git.branchExists(target))) {
90
+ return yield* failed(`there is no branch '${target}'`)
91
+ }
92
+ const dirty = statusPaths(yield* git.status)
93
+ if (dirty.length > 0) {
94
+ return yield* EpicCheckoutDirty.make({ checkout: context.workDir, paths: dirty })
95
+ }
96
+
97
+ // 2. Bring the target's history into the epic branch, on the epic side.
98
+ yield* git.checkout(epicBranch)
99
+ const before = yield* git.checkpoint
100
+ const behind = !(yield* git.isAncestor(target, epicBranch))
101
+ const conflicts = behind ? yield* git.mergeNoCommit(target) : []
102
+ if (behind) {
103
+ yield* say(
104
+ conflicts.length === 0
105
+ ? `merged ${target} into ${epicBranch} cleanly; checking the gates`
106
+ : `merging ${target} into ${epicBranch} conflicted in ${conflicts.length} file(s): ${conflicts.join(", ")}`
107
+ )
108
+ } else {
109
+ yield* say(`${epicBranch} already contains ${target}; checking the gates`)
110
+ }
111
+
112
+ // 3. Conflicts and red gates go to the coder, a bounded number of times.
113
+ const coder = options.coder ?? context.coder
114
+ const chat = yield* makeChat(coder, {
115
+ ...(options.system === undefined ? {} : { system: options.system }),
116
+ events,
117
+ agent: "coder"
118
+ })
119
+ const stories = plan.stories.map((story) => `- ${story.id}: ${story.provides.join("; ")}`)
120
+ let rounds = 0
121
+ while (true) {
122
+ const withMarkers: Array<string> = []
123
+ for (const path of conflicts) {
124
+ const text = yield* files.read(join(context.workDir, path))
125
+ if (text !== undefined && markerPattern.test(text)) {
126
+ withMarkers.push(path)
127
+ }
128
+ }
129
+ const gate = withMarkers.length > 0 ? undefined : yield* options.gates(context.workDir)
130
+ if (withMarkers.length === 0 && gate !== undefined && gate.isClean) {
131
+ break
132
+ }
133
+ if (rounds >= maxRounds) {
134
+ yield* git.rollback(before)
135
+ return yield* failed(
136
+ withMarkers.length > 0
137
+ ? `conflict markers still in ${withMarkers.join(", ")} after ${rounds} round(s)`
138
+ : `the gates are still red after ${rounds} round(s):\n${gate === undefined ? "" : issueLines(gate)}`
139
+ )
140
+ }
141
+ rounds += 1
142
+ yield* say(
143
+ withMarkers.length > 0
144
+ ? `round ${rounds}: asking the coder to resolve ${withMarkers.length} conflicted file(s)`
145
+ : `round ${rounds}: asking the coder to fix ${gate?.issues.length ?? 0} gate failure(s)`
146
+ )
147
+ yield* chat.ask(
148
+ withMarkers.length > 0
149
+ ? [
150
+ `The finished epic "${plan.epic}" (branch ${epicBranch}) is landing on ${target}.`,
151
+ `Merging ${target} into ${epicBranch} left conflicts in these files:`,
152
+ ...withMarkers.map((path) => `- ${path}`),
153
+ "",
154
+ `${target} holds newer mainline work; ${epicBranch} holds the epic's stories, which provide:`,
155
+ ...stories,
156
+ "",
157
+ "Resolve every conflict so both sides' intent survives, remove every conflict marker,",
158
+ "and keep the repository's gates (typecheck, lint, tests, build) green. Do not commit,",
159
+ "do not switch branches, and do not run git merge or git rebase: the flow owns git."
160
+ ].join("\n")
161
+ : [
162
+ `After merging ${target} into ${epicBranch}, the repository's gates fail:`,
163
+ gate === undefined ? "" : issueLines(gate),
164
+ "",
165
+ "Fix them without weakening any test. Do not commit or switch branches."
166
+ ].join("\n")
167
+ )
168
+ }
169
+
170
+ // 4. Green with the target's history: record it, then land on the target.
171
+ if (behind) {
172
+ yield* git.commitAll(`${plan.epicId}: merge ${target} into ${epicBranch} before landing`)
173
+ } else if (rounds > 0) {
174
+ yield* git.commitAll(`${plan.epicId}: fix the gates before landing`)
175
+ }
176
+ yield* git.checkout(target)
177
+ yield* git.merge(epicBranch, `${plan.epicId}: land ${epicBranch}`)
178
+ yield* say(
179
+ `landed ${epicBranch} on ${target}${rounds === 0 ? "" : ` after ${rounds} fix round(s)`}`
180
+ )
181
+ return { epicBranch, target, conflicts, rounds }
182
+ })
package/src/Roster.ts CHANGED
@@ -511,15 +511,19 @@ export const makeRoster = Effect.fn("@llm4ts/flow/Roster.make")(function* (
511
511
  const pick = (role: Role, leaseOptions: LeaseOptions): ExecutorSpec | undefined => {
512
512
  const avoid = leaseOptions.avoid ?? []
513
513
  const candidates = eligible(role, avoid).filter((spec) => freeFor(spec, role))
514
- const preferred = candidates.find((spec) => spec.id === leaseOptions.prefer)
515
- if (preferred !== undefined) {
516
- return preferred
517
- }
518
- return [...candidates].sort(
514
+ const best = [...candidates].sort(
519
515
  (left, right) =>
520
516
  priorityOf(left, role) - priorityOf(right, role) ||
521
517
  (lastLeased.get(left.id) ?? -1) - (lastLeased.get(right.id) ?? -1)
522
518
  )[0]
519
+ // The executor a resumed context held before keeps it only while it
520
+ // still ranks with the best free one: continuity breaks ties, it never
521
+ // overrides a priority the operator changed.
522
+ const preferred = candidates.find((spec) => spec.id === leaseOptions.prefer)
523
+ return preferred !== undefined &&
524
+ (best === undefined || priorityOf(preferred, role) <= priorityOf(best, role))
525
+ ? preferred
526
+ : best
523
527
  }
524
528
 
525
529
  const release = (spec: ExecutorSpec, role: Role): Effect.Effect<void> =>