@pmelab/gtd 52.1.0 → 53.0.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 (90) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +91 -129
  3. package/claude/hooks/drive.ts +0 -3
  4. package/claude/hooks/register.tsx +3 -68
  5. package/claude/hooks/ship.ts +85 -1595
  6. package/dist/chunks/{reserved-DxB5CROj.mjs → reserved-CQ7amcKG.mjs} +45 -132
  7. package/dist/chunks/{review-CKMSdvgW.mjs → review-CNgN_V8T.mjs} +2 -2
  8. package/dist/chunks/{tail-QZc7Uz2U.mjs → tail-JZ9PAOwp.mjs} +2 -14
  9. package/dist/chunks/{wire-BJuZWR3C.mjs → wire-C12dahrH.mjs} +2 -130
  10. package/dist/flows.mjs +1 -16
  11. package/dist/gtd.bundle.mjs +476 -982
  12. package/dist/testkit.mjs +58 -417
  13. package/dist/wire.mjs +2 -2
  14. package/dist/workflows/cleanup.mjs +2 -2
  15. package/dist/workflows/feature.mjs +112 -363
  16. package/dist/workflows/fix.mjs +2 -2
  17. package/dist/workflows/review.mjs +3 -3
  18. package/dist/workflows/rollout.mjs +1 -1
  19. package/dist/workflows.mjs +311 -674
  20. package/package.json +1 -1
  21. package/src/cli/Cli.test.ts +1 -86
  22. package/src/cli/Cli.ts +13 -133
  23. package/src/cli/Metrics.test.ts +21 -31
  24. package/src/cli/Metrics.ts +25 -36
  25. package/src/cli/Program.test.ts +1 -35
  26. package/src/cli/Program.ts +5 -64
  27. package/src/cli/ToolCommands.ts +0 -3
  28. package/src/edge/Edge.test.ts +20 -322
  29. package/src/edge/Edge.ts +10 -181
  30. package/src/edge/index.ts +0 -1
  31. package/src/flows/runtime.test.ts +0 -27
  32. package/src/flows/runtime.ts +1 -49
  33. package/src/install/Install.ts +15 -24
  34. package/src/replay/Replay.test.ts +0 -169
  35. package/src/replay/Replay.ts +4 -93
  36. package/src/replay/index.ts +0 -1
  37. package/src/testkit/Layers.ts +0 -1
  38. package/src/wire/BeatDocument.ts +2 -12
  39. package/src/wire/BeatStatus.ts +0 -3
  40. package/src/wire/WireSchema.test.ts +0 -18
  41. package/src/wire/index.ts +0 -2
  42. package/src/wire/types.ts +0 -7
  43. package/src/workflow/Workflow.ts +1 -9
  44. package/src/workflows/feature/criteria.test.ts +1 -14
  45. package/src/workflows/feature/criteria.ts +6 -38
  46. package/src/workflows/feature/feature.ts +34 -118
  47. package/src/workflows/feature/hands-on-skip.feature +2 -70
  48. package/src/workflows/feature/index.ts +0 -1
  49. package/src/workflows/feature/one-step-land.feature +0 -4
  50. package/src/workflows/feature/prototype-rounds.feature +1 -1
  51. package/src/workflows/feature/prototype.feature +3 -3
  52. package/src/workflows/feature/prototype.ts +18 -29
  53. package/src/workflows/feature/refactor-absorbs.feature +3 -8
  54. package/src/workflows/feature/refactor-first.feature +0 -5
  55. package/src/workflows/feature/refactor-rebuild.feature +0 -6
  56. package/src/workflows/feature/refactor-review.feature +11 -11
  57. package/src/workflows/feature/refactor.ts +30 -64
  58. package/src/workflows/feature/review-gate.feature +1 -1
  59. package/src/workflows/feature/seam-rejection.feature +0 -4
  60. package/src/workflows/feature/seam.test.ts +7 -26
  61. package/src/workflows/feature/seam.ts +52 -165
  62. package/src/workflows/index.ts +0 -1
  63. package/src/workflows/shared/lenses.ts +0 -13
  64. package/src/workflows/shared/options.test.ts +2 -11
  65. package/src/workflows/shared/options.ts +4 -21
  66. package/src/workflows/shared/review.test.ts +3 -3
  67. package/src/workflows/shared/steps.ts +0 -2
  68. package/src/workflows/shared/text.test.ts +10 -80
  69. package/src/workflows/shared/text.ts +35 -211
  70. package/src/workflows/shared/vars.ts +2 -8
  71. package/src/workflows/shared/workflows.steps.ts +0 -13
  72. package/claude/hooks/context.ts +0 -66
  73. package/src/replay/Slices.test.ts +0 -73
  74. package/src/replay/Slices.ts +0 -45
  75. package/src/wire/ContextLimit.fixture.ts +0 -30
  76. package/src/wire/ContextLimit.test.ts +0 -96
  77. package/src/wire/ContextLimit.ts +0 -169
  78. package/src/wire/Slices.ts +0 -25
  79. package/src/wire/golden/1/slices.json +0 -11
  80. package/src/workflows/feature/context-limit.feature +0 -37
  81. package/src/workflows/feature/continuation-cap.feature +0 -69
  82. package/src/workflows/feature/continuation-rebuild.feature +0 -92
  83. package/src/workflows/feature/continuation-slices.feature +0 -68
  84. package/src/workflows/feature/continuation.feature +0 -209
  85. package/src/workflows/feature/slice-findings.feature +0 -256
  86. package/src/workflows/feature/slicing-cap.feature +0 -23
  87. package/src/workflows/feature/slicing.feature +0 -297
  88. package/src/workflows/feature/slicing.test.ts +0 -49
  89. package/src/workflows/feature/slicing.ts +0 -105
  90. package/src/workflows/shared/continuation.ts +0 -92
@@ -3,10 +3,10 @@
3
3
  Feature: a refactor that carried the whole feature still gets a quality lap over all of it
4
4
 
5
5
  With GTD_FLAG_RISK_TIER off, a refactor-first
6
- refactor can land everything the requirements ask for. The feature slice's
6
+ refactor can land everything the requirements ask for. The feature's
7
7
  implement turn then has only the naive pass's acceptance tests to carry
8
- over, and with no code but tests changed since the refactor the feature
9
- slice's quality lap covers the whole change, refactor included.
8
+ over, and with no code but tests changed since the refactor the feature's
9
+ quality lap covers the whole change, refactor included.
10
10
 
11
11
  Background:
12
12
  Given the shipped workflows, as gtd install scaffolds them
@@ -132,8 +132,3 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
132
132
  gtd(check): implement.closing → build.quality.correctness.reviewing
133
133
  gtd(agent): build.quality.correctness.reviewing → build.review.reviewing
134
134
  """
135
- And the output lines of gtd "slices" start with:
136
- """
137
- refactor
138
- feature
139
- """
@@ -160,9 +160,4 @@ Feature: a refactor-first judgment walks one fixed path to the review gate
160
160
  And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
161
161
  And the commit "gtd(judge): seam.judge → seam.note" has a body containing "\"answer\":\"refactor-first\""
162
162
  And no commit body contains "Gtd-Approved:"
163
- And the output lines of gtd "slices" start with:
164
- """
165
- refactor
166
- feature
167
- """
168
163
  And no commit body contains "Gtd-Workflow:"
@@ -197,7 +197,6 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
197
197
  Then the process rests at "implement.building"
198
198
  And "src/calc.ts" contains "op(a, b, 1)"
199
199
  And "src/calc.ts" does not contain "subtract"
200
- And the output of gtd "slices" contains "refactor "
201
200
 
202
201
  Scenario: the rebuild lands only once it carries the naive pass's acceptance tests, green
203
202
  Given step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
@@ -285,8 +284,3 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
285
284
  gtd(check): implement.health.check → implement.closing
286
285
  gtd(check): implement.closing → build.review.reviewing
287
286
  """
288
- And the output lines of gtd "slices" start with:
289
- """
290
- refactor
291
- feature
292
- """
@@ -1,9 +1,9 @@
1
1
  @inmem
2
- Feature: the refactor slice is reviewed on its own before the feature is implemented
2
+ Feature: the refactor is reviewed on its own before the feature is implemented
3
3
 
4
4
  After a refactor-first judgment the refactor is built, quality-lapped and
5
- reviewed in its own slice. Review edits re-run the refactor, never the design;
6
- the feature slice that follows is quality-lapped from the refactor's
5
+ reviewed on its own. Review edits re-run the refactor, never the design;
6
+ the feature that follows is quality-lapped from the refactor's
7
7
  sign-off, then reviewed. The flags are pinned so the per-flag test runs never move it off
8
8
  its path.
9
9
 
@@ -614,7 +614,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
614
614
  And ".gtd/REFACTOR.md" does not exist
615
615
  And ".gtd/REVIEW.md" contains "A: add and subtract differ only by sign."
616
616
 
617
- Scenario: a no-change landing after the in-gate reply signs off and the feature slice follows
617
+ Scenario: a no-change landing after the in-gate reply signs off and the feature follows
618
618
  Given step "implement.building" writes "src/calc.ts" with:
619
619
  """
620
620
  export const op = (a: number, b: number, sign: number) => a + sign * b
@@ -697,7 +697,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
697
697
  Then the process rests at "build.review.reviewing"
698
698
  And "src/calc.ts" contains "subtract"
699
699
 
700
- Scenario: a praise-only one-shot footnote signs off and the feature slice follows
700
+ Scenario: a praise-only one-shot footnote signs off and the feature follows
701
701
  Given step "implement.building" writes "src/calc.ts" with:
702
702
  """
703
703
  export const op = (a: number, b: number, sign: number) => a + sign * b
@@ -979,7 +979,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
979
979
  Then driving the process is refused with "refactor-feedback"
980
980
  And driving the process is refused with "hand-edited src/calc.ts"
981
981
 
982
- Scenario: a praise note and a concluded thread on a settled round sign off and the feature slice follows
982
+ Scenario: a praise note and a concluded thread on a settled round sign off and the feature follows
983
983
  Given step "implement.building" writes "src/calc.ts" with:
984
984
  """
985
985
  export const op = (a: number, b: number, sign: number) => a + sign * b
@@ -1066,7 +1066,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1066
1066
  Then the process rests at "build.review.reviewing"
1067
1067
  And "src/calc.ts" contains "subtract"
1068
1068
 
1069
- Scenario: a praise-only refactor review still signs off and the feature slice follows
1069
+ Scenario: a praise-only refactor review still signs off and the feature follows
1070
1070
  Given step "implement.building" writes "src/calc.ts" with:
1071
1071
  """
1072
1072
  export const op = (a: number, b: number, sign: number) => a + sign * b
@@ -1099,7 +1099,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1099
1099
  Then the process rests at "build.review.reviewing"
1100
1100
  And "src/calc.ts" contains "subtract"
1101
1101
 
1102
- Scenario: a nit fix in the refactor slice that changes a non-stray is refused, though a glob stray widens the write access
1102
+ Scenario: a nit fix in the refactor that changes a non-stray is refused, though a glob stray widens the write access
1103
1103
  Given step "seam.naive" writes "src/*.ts" with:
1104
1104
  """
1105
1105
  export const literalGlobName = 2
@@ -1130,7 +1130,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1130
1130
  When gtd lands
1131
1131
  Then driving the process is refused with "refactor-scope"
1132
1132
 
1133
- Scenario: the nit-fix turn in the refactor slice may write the strays and .gtd/** only
1133
+ Scenario: the nit-fix turn in the refactor may write the strays and .gtd/** only
1134
1134
  Given step "seam.naive" writes "src/*.ts" with:
1135
1135
  """
1136
1136
  export const literalGlobName = 2
@@ -1185,7 +1185,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1185
1185
  """
1186
1186
  And no commit body contains "refactor.build.review.composing"
1187
1187
 
1188
- Rule: with a quality lens on both slices
1188
+ Rule: with a quality lens on both the refactor and the feature
1189
1189
 
1190
1190
  Background:
1191
1191
  Given an environment variable "GTD_REFACTORQUALITYREVIEWS" set to "correctness"
@@ -1275,7 +1275,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1275
1275
  """
1276
1276
  And step "refactor.build.review.closing" runs its script
1277
1277
 
1278
- Scenario: each slice's quality lap reviews from that slice's base
1278
+ Scenario: the refactor's and the feature's quality laps each review from their own base
1279
1279
  When the process is driven
1280
1280
  Then the process rests at "refactor.build.quality.correctness.reviewing"
1281
1281
  And the resting step's content contains the hash of the commit "gtd(agent): seam.note → refactor.deriving"
@@ -15,9 +15,8 @@ import {
15
15
  } from "../../flows/index.js"
16
16
  import { lensEntriesOf } from "../../workflow-kit/index.js"
17
17
  import { markFenced } from "../shared/fences.js"
18
- import { continuing, phase, type Phase } from "../shared/continuation.js"
19
18
  import { healthy, type Guard } from "../shared/health.js"
20
- import { coder, FEEDBACK, HANDOFF, REFACTOR } from "../shared/steps.js"
19
+ import { coder, FEEDBACK, REFACTOR } from "../shared/steps.js"
21
20
  import * as t from "../shared/text.js"
22
21
  import { defaults, testFileGlobs } from "../shared/vars.js"
23
22
  import { buildTail, reUnwind, type FeedbackTarget } from "../shared/review.js"
@@ -264,12 +263,7 @@ const guardOf =
264
263
  }
265
264
 
266
265
  /** Derive, build, check and close one refactor lap; `feedback` is the collected review text of the lap before. */
267
- const refactorLap = async (
268
- p: Plan,
269
- guard: Guard,
270
- refactor: Phase,
271
- feedback?: string,
272
- ): Promise<void> => {
266
+ const refactorLap = async (p: Plan, guard: Guard, feedback?: string): Promise<void> => {
273
267
  const { pattern, strays, reference, note } = p
274
268
  await run(
275
269
  "deriving",
@@ -282,59 +276,32 @@ const refactorLap = async (
282
276
  ]),
283
277
  { label: "Deriving the refactor package", file: REFACTOR_PACKAGE },
284
278
  )
285
- const reached = new Set<string>()
286
- // Each snapshot is greened before its continuation: every sub-step keeps the old suite green.
287
- await continuing(refactor, async (from, fresh) => {
288
- await fresh(() =>
289
- t.agentWithSkills(
290
- "building",
291
- t.refactorBuildingPrompt({
292
- pkg: REFACTOR_PACKAGE,
293
- strays,
294
- pattern,
295
- reference,
296
- feedback: feedback !== undefined,
297
- note: note !== undefined,
298
- from,
299
- }),
300
- {
301
- label: from === undefined ? "Refactoring" : "Continuing the refactor",
302
- model: coder(),
303
- system: t.builderSystem(),
304
- },
305
- ),
306
- )
307
- // Committed by the snapshot, so a turn stopped again may leave it as it was: present means stopped.
308
- const left = read(HANDOFF)
309
- guard()
310
- const snapshot = head()
311
- // The building turns' own changes only: a fix turn reaching a path is not the refactor reaching it.
312
- for (const c of changes()) reached.add(c.path)
313
- await healthy(
314
- async () => {
315
- await t.agentWithSkills("fix.suite.fixing", t.refactorFixPrompt(strays, pattern), {
316
- label: "Fixing the check",
317
- file: FEEDBACK,
318
- model: coder(),
319
- system: t.builderSystem(),
320
- })
321
- guard()
322
- },
323
- { describeGuard: guard, rules: t.refactorRules(strays, pattern) },
324
- )
325
- if (left === undefined) return { result: undefined }
326
- return {
327
- result: undefined,
328
- handoff: {
329
- snapshot,
330
- note: left.trim(),
331
- open: strays.filter((path) => !reached.has(path)),
332
- },
333
- }
334
- })
335
- await run("closing", removeScript([REFACTOR_PACKAGE, HANDOFF]), {
336
- label: "Closing out the refactor",
337
- })
279
+ await t.agentWithSkills(
280
+ "building",
281
+ t.refactorBuildingPrompt({
282
+ pkg: REFACTOR_PACKAGE,
283
+ strays,
284
+ pattern,
285
+ reference,
286
+ feedback: feedback !== undefined,
287
+ note: note !== undefined,
288
+ }),
289
+ { label: "Refactoring", model: coder(), system: t.builderSystem() },
290
+ )
291
+ guard()
292
+ await healthy(
293
+ async () => {
294
+ await t.agentWithSkills("fix.suite.fixing", t.refactorFixPrompt(strays, pattern), {
295
+ label: "Fixing the check",
296
+ file: FEEDBACK,
297
+ model: coder(),
298
+ system: t.builderSystem(),
299
+ })
300
+ guard()
301
+ },
302
+ { describeGuard: guard, rules: t.refactorRules(strays, pattern) },
303
+ )
304
+ await run("closing", removeScript([REFACTOR_PACKAGE]), { label: "Closing out the refactor" })
338
305
  }
339
306
 
340
307
  const strayAccess = (strays: readonly string[]) => ({
@@ -348,7 +315,7 @@ export const refactorFirst = async (
348
315
  const p = plan(shape, options)
349
316
  if (p === undefined) return false
350
317
  return scope({ name: "refactor", access: strayAccess(p.strays) }, async () => {
351
- await refactorLap(p, guardOf(p, head()), phase("refactor"))
318
+ await refactorLap(p, guardOf(p, head()))
352
319
  return true
353
320
  })
354
321
  }
@@ -375,10 +342,9 @@ export const reviewedRefactor = async (
375
342
  "gtd land: refactor-feedback: the review feedback changed files but wrote no .gtd/REFACTOR.md — a refactor cannot act on it; revert the change, or `gtd abandon` and restart",
376
343
  dropped: t.refactorDroppedRefusal,
377
344
  }
378
- const refactor = phase("refactor")
379
345
  let collected: string | undefined
380
346
  for (;;) {
381
- await refactorLap(p, guard, refactor, collected)
347
+ await refactorLap(p, guard, collected)
382
348
  // A person's edit at an escalation rest is never refused, as in the lap.
383
349
  const outcome = await buildTail(entry, {
384
350
  green: true,
@@ -1,7 +1,7 @@
1
1
  @inmem
2
2
  Feature: a feature process ends at the human review
3
3
 
4
- After the last slice's quality lap the process rests at the review gate,
4
+ After the quality lap the process rests at the review gate,
5
5
  `.gtd/REVIEW.md`. A sign-off ends the process. A note asking for a change in
6
6
  behaviour starts a feedback lap — design, then implement with no new naive
7
7
  pass or seam judge, the hands-on test, the quality lap — and the review
@@ -136,8 +136,4 @@ Feature: rejected naive passes walk one fixed path through the steer gate to the
136
136
  And the commit "gtd(judge): seam.judge → seam.steer" has a body containing "\"answer\":\"reject\""
137
137
  And the commit "gtd(judge): seam.judge → implement.applying" has a body containing "\"answer\":\"land\""
138
138
  And no commit body contains "Gtd-Approved:"
139
- And the output lines of gtd "slices" start with:
140
- """
141
- feature
142
- """
143
139
  And no commit body contains "Gtd-Workflow:"
@@ -311,9 +311,6 @@ const reviewDoc = [
311
311
 
312
312
  interface Seamed {
313
313
  readonly names: string[]
314
- readonly slices: string[]
315
- /** Slice names entered, with the steps seen while inside each. */
316
- readonly inside: Record<string, string[]>
317
314
  readonly outcome: SeamOutcome | Error
318
315
  }
319
316
 
@@ -327,10 +324,7 @@ const driveSeam = async (
327
324
  let red = false
328
325
  let redsLeft = reds
329
326
  const names: string[] = []
330
- const slices: string[] = []
331
- const inside: Record<string, string[]> = {}
332
327
  const stack: string[] = []
333
- const open: string[] = []
334
328
  const files = new Map<string, string>([["src/a.ts", "a"]])
335
329
  let current = "c0"
336
330
  const effects: Record<string, () => void> = {
@@ -351,12 +345,6 @@ const driveSeam = async (
351
345
  },
352
346
  pushScope: (scope: { name?: string }) => void stack.push(scope.name ?? ""),
353
347
  popScope: () => void stack.pop(),
354
- enterSlice: (name: string) => {
355
- slices.push(name)
356
- open.push(name)
357
- inside[name] = []
358
- },
359
- leaveSlice: () => void open.pop(),
360
348
  read: (path: string) => files.get(path),
361
349
  head: () => current,
362
350
  kept: () => tip(stray),
@@ -372,7 +360,6 @@ const driveSeam = async (
372
360
  }
373
361
  if (full === "seam.clear") files.delete(".gtd/FEEDBACK.md")
374
362
  names.push(full)
375
- for (const name of open) inside[name]!.push(full)
376
363
  effects[request.name]?.()
377
364
  if (request.kind === "judge")
378
365
  return Promise.resolve({ answers: { shape: { answer, p: 0.9 } }, truncated: [] })
@@ -385,14 +372,13 @@ const driveSeam = async (
385
372
  } catch (error) {
386
373
  outcome = error as Error
387
374
  }
388
- return { names, slices, inside, outcome }
375
+ return { names, outcome }
389
376
  }
390
377
 
391
378
  describe("seamBuild", () => {
392
- it("land resolves the kept tip to land, with the caller's base, and enters no slice", async () => {
379
+ it("land resolves the kept tip to land, with the caller's base", async () => {
393
380
  const h = await driveSeam("land")
394
381
  expect(h.outcome).toEqual({ reference: "abc", base: "c-base", land: true })
395
- expect(h.slices).toEqual([])
396
382
  expect(h.names).toEqual(["seam.naive", "seam.check", "seam.judge"])
397
383
  })
398
384
 
@@ -432,7 +418,7 @@ describe("seamBuild", () => {
432
418
  expect(h.outcome).toEqual({ reference: "abc", base: "c-base", land: true })
433
419
  })
434
420
 
435
- it("refactor-first runs the reviewed refactor in slice refactor and resolves HEAD after it", async () => {
421
+ it("refactor-first runs the reviewed refactor right after the note and resolves HEAD after it", async () => {
436
422
  const h = await driveSeam("refactor-first")
437
423
  expect(h.outcome).toEqual({
438
424
  reference: "abc",
@@ -440,16 +426,14 @@ describe("seamBuild", () => {
440
426
  refactored: true,
441
427
  rebuild: { note: "Seam: a shared op", acceptance: { hash: "abc", tests: [], ids: [] } },
442
428
  })
443
- expect(h.slices).toEqual(["refactor"])
444
429
  expect(h.names.indexOf("seam.note")).toBe(h.names.indexOf("seam.judge") + 1)
445
- expect(h.inside.refactor).not.toContain("seam.note")
446
- expect(h.inside.refactor![0]).toBe("refactor.deriving")
447
- expect(h.inside.refactor).toContain("refactor.build.review.closing")
430
+ expect(h.names.indexOf("refactor.deriving")).toBe(h.names.indexOf("seam.note") + 1)
431
+ expect(h.names).toContain("refactor.build.review.closing")
448
432
  expect(h.names.some((n) => n.includes("approve"))).toBe(false)
449
433
  expect(h.names.some((n) => n.startsWith("implement"))).toBe(false)
450
434
  })
451
435
 
452
- it("refactor-first with only test-file strays resolves the caller's base with no slice and no by-hand", async () => {
436
+ it("refactor-first with only test-file strays resolves the caller's base with no refactor and no by-hand", async () => {
453
437
  const h = await driveSeam("refactor-first", change("src/a.test.ts", "modified"), {
454
438
  seamAllow: ".gtd/**",
455
439
  })
@@ -458,7 +442,6 @@ describe("seamBuild", () => {
458
442
  base: "c-base",
459
443
  rebuild: { acceptance: { hash: "abc", tests: [], ids: [] } },
460
444
  })
461
- expect(h.slices).toEqual([])
462
445
  expect(h.names).not.toContain("seam.by-hand")
463
446
  expect(h.names.some((n) => n.startsWith("refactor"))).toBe(false)
464
447
  })
@@ -469,18 +452,16 @@ describe("seamBuild", () => {
469
452
  { path: "src/a.test.ts", status: "modified", before: undefined, after: "b" },
470
453
  { seamAllow: ".gtd/**" },
471
454
  )
472
- expect(h.slices).toEqual([])
473
455
  expect(h.names).toContain("seam.by-hand")
474
456
  })
475
457
 
476
- it("rests unreadable strays at seam.by-hand and enters no refactor slice", async () => {
458
+ it("rests unreadable strays at seam.by-hand and runs no refactor", async () => {
477
459
  const h = await driveSeam("refactor-first", {
478
460
  path: "src/a.ts",
479
461
  status: "modified",
480
462
  before: undefined,
481
463
  after: "b",
482
464
  })
483
- expect(h.slices).toEqual([])
484
465
  expect(h.names).toContain("seam.by-hand")
485
466
  expect(h.outcome).toEqual({
486
467
  reference: "abc",