@llm4ts/flow 0.15.1 → 0.16.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 (50) hide show
  1. package/dist/BenchReport.d.ts +2 -2
  2. package/dist/BenchReport.d.ts.map +1 -1
  3. package/dist/CostLedger.d.ts +2 -2
  4. package/dist/CostLedger.d.ts.map +1 -1
  5. package/dist/Equiv.d.ts +3 -3
  6. package/dist/Equiv.d.ts.map +1 -1
  7. package/dist/Flow.d.ts +1 -1
  8. package/dist/Flow.d.ts.map +1 -1
  9. package/dist/FlowContext.d.ts +10 -0
  10. package/dist/FlowContext.d.ts.map +1 -1
  11. package/dist/FlowContext.js.map +1 -1
  12. package/dist/FlowError.d.ts +42 -1
  13. package/dist/FlowError.d.ts.map +1 -1
  14. package/dist/FlowError.js +60 -1
  15. package/dist/FlowError.js.map +1 -1
  16. package/dist/GitTool.d.ts +15 -1
  17. package/dist/GitTool.d.ts.map +1 -1
  18. package/dist/GitTool.js +30 -2
  19. package/dist/GitTool.js.map +1 -1
  20. package/dist/Perimeter.d.ts +13 -0
  21. package/dist/Perimeter.d.ts.map +1 -0
  22. package/dist/Perimeter.js +34 -0
  23. package/dist/Perimeter.js.map +1 -0
  24. package/dist/Persistence.d.ts +2 -2
  25. package/dist/Persistence.d.ts.map +1 -1
  26. package/dist/PlanExecution.d.ts +1 -1
  27. package/dist/PlanExecution.d.ts.map +1 -1
  28. package/dist/ProgramJudge.d.ts +1 -1
  29. package/dist/ProgramJudge.d.ts.map +1 -1
  30. package/dist/Replay.d.ts +2 -2
  31. package/dist/Replay.d.ts.map +1 -1
  32. package/dist/Review.d.ts +2 -2
  33. package/dist/Review.d.ts.map +1 -1
  34. package/dist/ReviewCache.d.ts +1 -1
  35. package/dist/ReviewCache.d.ts.map +1 -1
  36. package/dist/Stories.d.ts +109 -0
  37. package/dist/Stories.d.ts.map +1 -0
  38. package/dist/Stories.js +432 -0
  39. package/dist/Stories.js.map +1 -0
  40. package/dist/StoryPlan.d.ts +81 -0
  41. package/dist/StoryPlan.d.ts.map +1 -0
  42. package/dist/StoryPlan.js +242 -0
  43. package/dist/StoryPlan.js.map +1 -0
  44. package/package.json +5 -2
  45. package/src/FlowContext.ts +10 -0
  46. package/src/FlowError.ts +74 -1
  47. package/src/GitTool.ts +74 -4
  48. package/src/Perimeter.ts +49 -0
  49. package/src/Stories.ts +670 -0
  50. package/src/StoryPlan.ts +353 -0
@@ -0,0 +1,49 @@
1
+ // The story perimeter check (ADR 0013): a story branch may only change what
2
+ // the story owns. Enforced after the fact on the branch's changed files —
3
+ // the prompt states the rule, this is what makes it true.
4
+ import * as Effect from "effect/Effect"
5
+ import { PerimeterViolation } from "./FlowError.ts"
6
+ import { pathWithin, type Story } from "./StoryPlan.ts"
7
+
8
+ export interface PerimeterCheck {
9
+ /** Changed paths under a `sharedReadOnly` prefix — the worse class, reported first. */
10
+ readonly sharedReadOnly: ReadonlyArray<string>
11
+ /** Changed paths under neither `owned` nor `sharedReadOnly`. */
12
+ readonly outside: ReadonlyArray<string>
13
+ }
14
+
15
+ export const checkPerimeter = (
16
+ changedPaths: ReadonlyArray<string>,
17
+ story: Story
18
+ ): PerimeterCheck => {
19
+ const sharedReadOnly: Array<string> = []
20
+ const outside: Array<string> = []
21
+ for (const path of changedPaths) {
22
+ if (story.owned.some((prefix) => pathWithin(path, prefix))) {
23
+ continue
24
+ }
25
+ if (story.sharedReadOnly.some((prefix) => pathWithin(path, prefix))) {
26
+ sharedReadOnly.push(path)
27
+ } else {
28
+ outside.push(path)
29
+ }
30
+ }
31
+ return { sharedReadOnly, outside }
32
+ }
33
+
34
+ export const isWithinPerimeter = (check: PerimeterCheck): boolean =>
35
+ check.sharedReadOnly.length === 0 && check.outside.length === 0
36
+
37
+ export const enforcePerimeter = Effect.fn("@llm4ts/flow/Perimeter.enforce")(function* (
38
+ changedPaths: ReadonlyArray<string>,
39
+ story: Story
40
+ ): Effect.fn.Return<void, PerimeterViolation> {
41
+ const check = checkPerimeter(changedPaths, story)
42
+ if (!isWithinPerimeter(check)) {
43
+ return yield* PerimeterViolation.make({
44
+ story: story.id,
45
+ outside: check.outside,
46
+ sharedReadOnly: check.sharedReadOnly
47
+ })
48
+ }
49
+ })