@pmelab/gtd 52.1.0 → 54.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 (94) 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-CXzUXJHL.mjs} +12 -5
  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 +321 -677
  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/testkit/steps.ts +23 -0
  39. package/src/wire/BeatDocument.ts +2 -12
  40. package/src/wire/BeatStatus.ts +0 -3
  41. package/src/wire/WireSchema.test.ts +0 -18
  42. package/src/wire/index.ts +0 -2
  43. package/src/wire/types.ts +0 -7
  44. package/src/workflow/Workflow.ts +1 -9
  45. package/src/workflows/feature/criteria.test.ts +1 -14
  46. package/src/workflows/feature/criteria.ts +6 -38
  47. package/src/workflows/feature/feature.ts +34 -118
  48. package/src/workflows/feature/hands-on-skip.feature +2 -70
  49. package/src/workflows/feature/index.ts +0 -1
  50. package/src/workflows/feature/lens-review.feature +50 -0
  51. package/src/workflows/feature/one-step-land.feature +0 -4
  52. package/src/workflows/feature/prototype-rounds.feature +1 -1
  53. package/src/workflows/feature/prototype.feature +3 -3
  54. package/src/workflows/feature/prototype.ts +18 -29
  55. package/src/workflows/feature/refactor-absorbs.feature +3 -8
  56. package/src/workflows/feature/refactor-first.feature +0 -5
  57. package/src/workflows/feature/refactor-rebuild.feature +0 -6
  58. package/src/workflows/feature/refactor-review.feature +49 -11
  59. package/src/workflows/feature/refactor.ts +30 -64
  60. package/src/workflows/feature/review-gate.feature +1 -1
  61. package/src/workflows/feature/reviewer-walkthrough.feature +0 -31
  62. package/src/workflows/feature/seam-rejection.feature +0 -4
  63. package/src/workflows/feature/seam.test.ts +7 -26
  64. package/src/workflows/feature/seam.ts +52 -165
  65. package/src/workflows/index.ts +0 -1
  66. package/src/workflows/shared/lenses.ts +0 -13
  67. package/src/workflows/shared/options.test.ts +2 -11
  68. package/src/workflows/shared/options.ts +4 -21
  69. package/src/workflows/shared/review.test.ts +3 -3
  70. package/src/workflows/shared/review.ts +12 -2
  71. package/src/workflows/shared/steps.ts +0 -2
  72. package/src/workflows/shared/text.test.ts +10 -80
  73. package/src/workflows/shared/text.ts +35 -211
  74. package/src/workflows/shared/vars.ts +2 -8
  75. package/src/workflows/shared/workflows.steps.ts +0 -13
  76. package/claude/hooks/context.ts +0 -66
  77. package/src/replay/Slices.test.ts +0 -73
  78. package/src/replay/Slices.ts +0 -45
  79. package/src/wire/ContextLimit.fixture.ts +0 -30
  80. package/src/wire/ContextLimit.test.ts +0 -96
  81. package/src/wire/ContextLimit.ts +0 -169
  82. package/src/wire/Slices.ts +0 -25
  83. package/src/wire/golden/1/slices.json +0 -11
  84. package/src/workflows/feature/context-limit.feature +0 -37
  85. package/src/workflows/feature/continuation-cap.feature +0 -69
  86. package/src/workflows/feature/continuation-rebuild.feature +0 -92
  87. package/src/workflows/feature/continuation-slices.feature +0 -68
  88. package/src/workflows/feature/continuation.feature +0 -209
  89. package/src/workflows/feature/slice-findings.feature +0 -256
  90. package/src/workflows/feature/slicing-cap.feature +0 -23
  91. package/src/workflows/feature/slicing.feature +0 -297
  92. package/src/workflows/feature/slicing.test.ts +0 -49
  93. package/src/workflows/feature/slicing.ts +0 -105
  94. package/src/workflows/shared/continuation.ts +0 -92
@@ -1,8 +1,8 @@
1
- import { agent, answered, applyScript, changes, changesSince, check, codeChanges, env, hasThreadFor, head, human, judge, judgeDiffShape, kept, mark, matches, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireThreadsClosed, revertScript, run, scope, slice, start, vars, wrote } from "../flows.mjs";
1
+ import { agent, answered, applyScript, changes, changesSince, check, codeChanges, env, hasThreadFor, head, human, judge, judgeDiffShape, kept, mark, matches, quote, read, refuse, removeScript, requireAnswers, requireProgress, requireReplies, requireThreadsClosed, revertScript, run, scope, start, vars, wrote } from "../flows.mjs";
2
2
  import { lensEntriesOf } from "../workflow-kit.mjs";
3
- import { $ as naivePassPrompt, At as unwindFailedMessage, C as coder, Ct as seamByHandMessage, Dt as testerSystem, E as fixNits, Et as startGateBlockedMessage, Ft as defaults, G as designTriagePrompt, H as designGateAnswerMessage, I as builderSystem, It as envDefaults, Lt as testFileGlobs, N as agentWithSkills, P as buildReviewCollectingPrompt, Q as naiveApplyFailure, R as clearCriteriaMessage, St as reviewerSystem, Tt as slicingPrompt, U as designImpactPrompt, V as criterionLine, W as designSystem, X as implementBuildingPrompt, Y as idleMessage, Z as implementFixPrompt, _ as REFACTOR_NOTE, a as flagModeOn, at as prototypeOpenMessage, b as SLICES, d as healthy, dt as refactorBuildingPrompt, et as normaliseCriteriaScript, f as FEEDBACK, ft as refactorDroppedRefusal, g as REFACTOR, ht as refactorRules, i as skills, it as prototypeFixingPrompt, jt as unwindFailure, k as planner, l as gate, m as PROTOTYPE, mt as refactorNotePrompt, n as summary, nt as observableQuestion, ot as prototypeTestingPrompt, p as HANDOFF, pt as refactorFixPrompt, r as access, rt as oversizedMessage, s as shipped, st as prototypeUnguidedMessage, t as steering, tt as observableMessage, v as REQUIREMENTS, w as collecting, wt as seamSteerMessage, x as answerReviewQuestions, z as clearCriteriaQuestion } from "../chunks/reserved-DxB5CROj.mjs";
4
- import { a as refusePendingHandOff, c as joinReports, o as tail } from "../chunks/tail-QZc7Uz2U.mjs";
5
- import { i as reUnwind, n as humanReview, r as isCode$1, t as buildTail } from "../chunks/review-CKMSdvgW.mjs";
3
+ import { $ as observableMessage, B as designGateAnswerMessage, Ct as testerSystem, D as planner, Dt as unwindFailure, Et as unwindFailedMessage, H as designSystem, I as clearCriteriaMessage, J as implementBuildingPrompt, L as clearCriteriaQuestion, M as buildReviewCollectingPrompt, Mt as envDefaults, Nt as testFileGlobs, P as builderSystem, Q as normaliseCriteriaScript, S as collecting, St as startGateBlockedMessage, U as designTriagePrompt, V as designImpactPrompt, X as naiveApplyFailure, Y as implementFixPrompt, Z as naivePassPrompt, _ as REQUIREMENTS, a as flagModeOn, bt as seamByHandMessage, ct as refactorBuildingPrompt, d as healthy, dt as refactorNotePrompt, et as observableQuestion, f as FEEDBACK, ft as refactorRules, g as REFACTOR_NOTE, h as REFACTOR, i as skills, it as prototypeUnguidedMessage, j as agentWithSkills, jt as defaults, l as gate, lt as refactorDroppedRefusal, n as summary, nt as prototypeOpenMessage, p as PROTOTYPE, q as idleMessage, r as access, rt as prototypeTestingPrompt, s as shipped, t as steering, tt as prototypeFixingPrompt, ut as refactorFixPrompt, w as fixNits, x as coder, xt as seamSteerMessage, y as answerReviewQuestions, yt as reviewerSystem, z as criterionLine } from "../chunks/reserved-CQ7amcKG.mjs";
4
+ import { a as refusePendingHandOff, o as tail } from "../chunks/tail-JZ9PAOwp.mjs";
5
+ import { i as reUnwind, n as humanReview, r as isCode$1, t as buildTail } from "../chunks/review-CXzUXJHL.mjs";
6
6
  import { posix } from "node:path";
7
7
  //#region src/workflows/shared/fences.ts
8
8
  const markFenced = (text) => {
@@ -26,7 +26,7 @@ const ITEM = /^ ?(?:[-*+]|\d+[.)])\s+(?:\[[ xX]\]\s+)?(.*)$/;
26
26
  //#region src/workflows/feature/criteria.ts
27
27
  /** Below this the judge's `yes` is not trusted: a wrong skip builds against criteria nobody can check. */
28
28
  const CLEAR_MIN_P = .8;
29
- const ID$1 = /^(AC-\d+)(\s*\(no hands-on\))?:\s*(.*)$/;
29
+ const ID = /^(AC-\d+)(\s*\(no hands-on\))?:\s*(.*)$/;
30
30
  const criterion = (id, as = id[1]) => ({
31
31
  id: as,
32
32
  text: id[3],
@@ -59,24 +59,22 @@ const listUnder = (text, title, level) => {
59
59
  };
60
60
  /** The `- AC-<n>: …` list of `## Acceptance Criteria`, or `undefined` when the section is missing. */
61
61
  const criteriaOf = (text) => listUnder(text, /^acceptance criteria$/i, 2)?.map((item) => {
62
- const id = ID$1.exec(item);
62
+ const id = ID.exec(item);
63
63
  return id === null ? {
64
64
  id: "",
65
65
  text: item
66
66
  } : criterion(id);
67
67
  });
68
- /** The ID'd criteria of `text`, only `slice`'s when given. */
69
- const criterionIds = (text, slice) => (criteriaOf(text) ?? []).map((c) => c.id).filter((id) => id !== "" && (slice?.only === void 0 || slice.only.includes(id)) && !(slice?.except ?? []).includes(id));
70
- /** The ID'd criteria of `text` (`slice`'s when given) a person can try by hand: none tagged `(no hands-on)`. */
71
- const handsOnIds = (text, slice) => {
68
+ /** The ID'd criteria of `text`. */
69
+ const criterionIds = (text) => (criteriaOf(text) ?? []).map((c) => c.id).filter((id) => id !== "");
70
+ /** The ID'd criteria of `text` a person can try by hand: none tagged `(no hands-on)`. */
71
+ const handsOnIds = (text) => {
72
72
  const tagged = (criteriaOf(text) ?? []).filter((c) => c.noHandsOn).map((c) => c.id);
73
- return criterionIds(text, slice).filter((id) => !tagged.includes(id));
73
+ return criterionIds(text).filter((id) => !tagged.includes(id));
74
74
  };
75
- /** `slice`'s IDs in `.gtd/REQUIREMENTS.md` as it is now; `undefined` for an unsliced change. */
76
- const sliceIds = (slice) => slice === void 0 ? void 0 : criterionIds(read(".gtd/REQUIREMENTS.md") ?? "", slice);
77
75
  /** Items numbered `AC-1`…, unless every one already carries its own distinct ID. */
78
76
  const numbered = (items) => {
79
- const ids = items.map((item) => ID$1.exec(item));
77
+ const ids = items.map((item) => ID.exec(item));
80
78
  const own = ids.every((id) => id !== null) && new Set(ids.map((id) => id[1])).size === ids.length;
81
79
  return items.map((item, i) => {
82
80
  const id = ids[i];
@@ -213,13 +211,6 @@ const skipDesign = (stated) => stated === void 0 ? Promise.resolve(false) : scop
213
211
  await impact();
214
212
  return true;
215
213
  });
216
- /** After a gate that invites narrowing the requirements: an edit must leave valid criteria. */
217
- const requireCriteriaIfEdited = () => {
218
- const change = changes().get(REQUIREMENTS);
219
- if (change === void 0) return;
220
- if (change.status === "deleted") refuse(`gtd land: criteria-missing: ${REQUIREMENTS} must stay — narrow its criteria, never delete it`);
221
- requireCriteria(REQUIREMENTS);
222
- };
223
214
  //#endregion
224
215
  //#region src/workflows/feature/tier.ts
225
216
  /** GTD_FLAG_RISK_TIER: pinned at process start, so a mid-process flip never moves a process. */
@@ -385,12 +376,12 @@ const requireReport = (ids, retest) => {
385
376
  };
386
377
  };
387
378
  /**
388
- * The slice's criteria a person can observe by using the change, by the
389
- * judge: those tagged `(no hands-on)` are never asked about.
379
+ * The criteria a person can observe by using the change, by the judge: those
380
+ * tagged `(no hands-on)` are never asked about.
390
381
  */
391
- const observable = async (slice) => {
382
+ const observable = async () => {
392
383
  const requirements = read(".gtd/REQUIREMENTS.md") ?? "";
393
- const own = handsOnIds(requirements, slice);
384
+ const own = handsOnIds(requirements);
394
385
  const criteria = (criteriaOf(requirements) ?? []).filter((c) => own.includes(c.id));
395
386
  if (criteria.length === 0) return [];
396
387
  const { answers } = await judge("observable", {
@@ -402,10 +393,9 @@ const observable = async (slice) => {
402
393
  return own.filter((id) => !answered(answers[id], "no", UNOBSERVABLE_MIN_P));
403
394
  };
404
395
  const frozen = () => requireCriteriaFrozen(REQUIREMENTS);
405
- const testing = async (slice, ids, retest) => {
406
- const skipped = criterionIds(read(".gtd/REQUIREMENTS.md") ?? "", slice).filter((id) => !ids.includes(id));
407
- await agentWithSkills("testing", prototypeTestingPrompt(sliceIds(slice), skipped, retest), {
408
- label: retest ? "Re-testing the slice by hand" : "Testing the slice by hand",
396
+ const testing = async (ids, retest) => {
397
+ await agentWithSkills("testing", prototypeTestingPrompt(criterionIds(read(".gtd/REQUIREMENTS.md") ?? "").filter((id) => !ids.includes(id)), retest), {
398
+ label: retest ? "Re-testing the change by hand" : "Testing the change by hand",
409
399
  file: PROTOTYPE,
410
400
  model: coder(),
411
401
  system: testerSystem(),
@@ -413,8 +403,8 @@ const testing = async (slice, ids, retest) => {
413
403
  });
414
404
  return requireReport(ids, retest);
415
405
  };
416
- const fixing = async (slice, guard) => {
417
- await scope("fix", () => agentWithSkills("fixing", prototypeFixingPrompt(sliceIds(slice)), {
406
+ const fixing = async (guard) => {
407
+ await scope("fix", () => agentWithSkills("fixing", prototypeFixingPrompt(), {
418
408
  label: "Fixing what the hands-on test found",
419
409
  file: PROTOTYPE,
420
410
  model: coder(),
@@ -438,29 +428,29 @@ const askPerson = async (name, message, label) => {
438
428
  return true;
439
429
  };
440
430
  /**
441
- * Use the slice by hand: a testing turn reports on every criterion a person
442
- * can observe, a fix turn takes each failure, and the slice is tested again —
431
+ * Use the change by hand: a testing turn reports on every criterion a person
432
+ * can observe, a fix turn takes each failure, and the change is tested again —
443
433
  * until the report is clean, or `prototypeRounds` fixes are spent and a person
444
- * decides. A slice with no such criterion is not tested by hand. `guard` holds
445
- * every fix turn, as it holds the implementation's.
434
+ * decides. A change with no such criterion is not tested by hand. `guard`
435
+ * holds every fix turn, as it holds the implementation's.
446
436
  */
447
- const prototypeTest = async (slice, guard) => {
437
+ const prototypeTest = async (guard) => {
448
438
  const cap = prototypeRounds();
449
439
  if (cap === 0) return;
450
440
  await scope("prototype", async () => {
451
- const ids = await observable(slice);
441
+ const ids = await observable();
452
442
  if (ids.length === 0) return;
453
443
  let fixes = 0;
454
444
  let retest = false;
455
445
  for (;;) {
456
- const { unguided, open } = await testing(slice, ids, retest);
446
+ const { unguided, open } = await testing(ids, retest);
457
447
  retest = !unguided;
458
448
  if (unguided) {
459
449
  if (!await askPerson("unguided", prototypeUnguidedMessage(), "No way to test by hand")) return;
460
450
  } else if (open.length === 0) return;
461
451
  else if (fixes < cap && open.some((i) => i.verdict === "fail")) {
462
452
  fixes++;
463
- await fixing(slice, guard);
453
+ await fixing(guard);
464
454
  } else {
465
455
  if (!await askPerson("open", prototypeOpenMessage(open, fixes), "Hands-on test still failing")) return;
466
456
  fixes = 0;
@@ -470,53 +460,6 @@ const prototypeTest = async (slice, guard) => {
470
460
  });
471
461
  };
472
462
  //#endregion
473
- //#region src/workflows/shared/continuation.ts
474
- const phase = (name, steered) => ({
475
- name,
476
- spent: false,
477
- count: 0,
478
- stalled: 0,
479
- steered
480
- });
481
- const own = (fn) => fn();
482
- const continued = (fn) => scope("continue", fn);
483
- const afresh = (fn) => scope("fresh", fn);
484
- const setting = (name, least) => {
485
- const raw = vars[name] ?? defaults[name];
486
- const n = Number(raw);
487
- if (raw.trim() === "" || !Number.isInteger(n) || n < least) refuse(`gtd: ${name} must be a whole number of at least ${least}, got ${JSON.stringify(raw)}`);
488
- return n;
489
- };
490
- /**
491
- * Run `turn` until one ends without a handoff note: each stopped turn is picked
492
- * up by a continuation in a fresh conversation. Past `continuations` of them in
493
- * the phase, or after `continuationStall` in a row that close nothing still
494
- * open, the phase rests at `oversized` for a person; landing there grants a new round.
495
- */
496
- const continuing = async (phase, turn) => {
497
- const cap = setting("continuations", 0);
498
- const stall = setting("continuationStall", 1);
499
- let last = await turn(void 0, phase.spent ? afresh : own);
500
- while (last.handoff !== void 0) {
501
- phase.spent = true;
502
- const from = last.handoff;
503
- if (phase.count >= cap || phase.stalled >= stall) {
504
- await human("oversized", {
505
- message: oversizedMessage(phase.name, from, phase.count >= cap ? { cap } : { stall }, phase.steered !== void 0),
506
- label: "Too big for its context",
507
- acceptClean: true
508
- });
509
- phase.steered?.();
510
- phase.count = 0;
511
- phase.stalled = 0;
512
- }
513
- last = await turn(from, continued);
514
- phase.count++;
515
- phase.stalled = from.open.length === 0 || from.open.some((item) => !(last.handoff?.open ?? []).includes(item)) ? 0 : phase.stalled + 1;
516
- }
517
- return last.result;
518
- };
519
- //#endregion
520
463
  //#region src/workflows/feature/refactor.ts
521
464
  const REFACTOR_PACKAGE = REFACTOR;
522
465
  const isCode = (path) => path !== ".gtd" && !path.startsWith(".gtd/");
@@ -662,7 +605,7 @@ const guardOf = ({ pattern, strays }, entry) => () => {
662
605
  requireNoNewFlags(pattern, entry);
663
606
  };
664
607
  /** Derive, build, check and close one refactor lap; `feedback` is the collected review text of the lap before. */
665
- const refactorLap = async (p, guard, refactor, feedback) => {
608
+ const refactorLap = async (p, guard, feedback) => {
666
609
  const { pattern, strays, reference, note } = p;
667
610
  await run("deriving", deriveScript([
668
611
  ...packageLines(strays, pattern, reference),
@@ -682,48 +625,32 @@ const refactorLap = async (p, guard, refactor, feedback) => {
682
625
  label: "Deriving the refactor package",
683
626
  file: REFACTOR_PACKAGE
684
627
  });
685
- const reached = /* @__PURE__ */ new Set();
686
- await continuing(refactor, async (from, fresh) => {
687
- await fresh(() => agentWithSkills("building", refactorBuildingPrompt({
688
- pkg: REFACTOR_PACKAGE,
689
- strays,
690
- pattern,
691
- reference,
692
- feedback: feedback !== void 0,
693
- note: note !== void 0,
694
- from
695
- }), {
696
- label: from === void 0 ? "Refactoring" : "Continuing the refactor",
628
+ await agentWithSkills("building", refactorBuildingPrompt({
629
+ pkg: REFACTOR_PACKAGE,
630
+ strays,
631
+ pattern,
632
+ reference,
633
+ feedback: feedback !== void 0,
634
+ note: note !== void 0
635
+ }), {
636
+ label: "Refactoring",
637
+ model: coder(),
638
+ system: builderSystem()
639
+ });
640
+ guard();
641
+ await healthy(async () => {
642
+ await agentWithSkills("fix.suite.fixing", refactorFixPrompt(strays, pattern), {
643
+ label: "Fixing the check",
644
+ file: FEEDBACK,
697
645
  model: coder(),
698
646
  system: builderSystem()
699
- }));
700
- const left = read(HANDOFF);
701
- guard();
702
- const snapshot = head();
703
- for (const c of changes()) reached.add(c.path);
704
- await healthy(async () => {
705
- await agentWithSkills("fix.suite.fixing", refactorFixPrompt(strays, pattern), {
706
- label: "Fixing the check",
707
- file: FEEDBACK,
708
- model: coder(),
709
- system: builderSystem()
710
- });
711
- guard();
712
- }, {
713
- describeGuard: guard,
714
- rules: refactorRules(strays, pattern)
715
647
  });
716
- if (left === void 0) return { result: void 0 };
717
- return {
718
- result: void 0,
719
- handoff: {
720
- snapshot,
721
- note: left.trim(),
722
- open: strays.filter((path) => !reached.has(path))
723
- }
724
- };
648
+ guard();
649
+ }, {
650
+ describeGuard: guard,
651
+ rules: refactorRules(strays, pattern)
725
652
  });
726
- await run("closing", removeScript([REFACTOR_PACKAGE, HANDOFF]), { label: "Closing out the refactor" });
653
+ await run("closing", removeScript([REFACTOR_PACKAGE]), { label: "Closing out the refactor" });
727
654
  };
728
655
  const strayAccess = (strays) => ({ write: [
729
656
  ...strays,
@@ -737,7 +664,7 @@ const refactorFirst = async (shape, options = {}) => {
737
664
  name: "refactor",
738
665
  access: strayAccess(p.strays)
739
666
  }, async () => {
740
- await refactorLap(p, guardOf(p, head()), phase("refactor"));
667
+ await refactorLap(p, guardOf(p, head()));
741
668
  return true;
742
669
  });
743
670
  };
@@ -762,10 +689,9 @@ const reviewedRefactor = async (shape, options = {}) => {
762
689
  unmatched: "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",
763
690
  dropped: refactorDroppedRefusal
764
691
  };
765
- const refactor = phase("refactor");
766
692
  let collected;
767
693
  for (;;) {
768
- await refactorLap(p, guard, refactor, collected);
694
+ await refactorLap(p, guard, collected);
769
695
  const outcome = await buildTail(entry, {
770
696
  green: true,
771
697
  guard,
@@ -795,32 +721,12 @@ const judgeSeam = (tip) => judgeDiffShape("judge", {
795
721
  allow: (vars.seamAllow ?? defaults.seamAllow).split(",").map((glob) => glob.trim()).filter((glob) => glob !== ""),
796
722
  exempt: tip.changes.filter((c) => c.status === "added").map((c) => c.path)
797
723
  });
798
- const naivePass = (retry, slice, from) => agentWithSkills("naive", naivePassPrompt(retry, sliceIds(slice), from), {
799
- label: from !== void 0 ? "Continuing the naive pass" : retry === void 0 ? "Writing the naive pass" : "Rewriting the naive pass",
724
+ const naivePass = (retry) => agentWithSkills("naive", naivePassPrompt(retry), {
725
+ label: retry === void 0 ? "Writing the naive pass" : "Rewriting the naive pass",
800
726
  keep: true,
801
727
  model: coder(),
802
728
  system: builderSystem()
803
729
  });
804
- const handoffOf = (tip, slice) => {
805
- const note = tip.changes.find((c) => c.path === ".gtd/HANDOFF.md" && c.after !== void 0);
806
- if (note === void 0) return void 0;
807
- return {
808
- snapshot: tip.hash,
809
- note: note.after.trim(),
810
- open: unnamed(idsOf(REQUIREMENTS, slice), acceptanceTests(tip.changes))
811
- };
812
- };
813
- /** A naive pass, continued until a pass ends without a handoff note: the snapshot is its kept tip. */
814
- const naiveContinued = (retry, slice, naive) => continuing(naive, async (from, fresh) => {
815
- const tip = await fresh(async () => {
816
- await naivePass(retry, slice, from);
817
- return kept("naive");
818
- });
819
- return {
820
- result: tip,
821
- handoff: handoffOf(tip, slice)
822
- };
823
- });
824
730
  const IMPORTED = /(?:\bfrom|\bimport|\brequire\s*\(|\bmock\s*\()\s*\(?\s*(["'`])([^"'`\n]+)\1/g;
825
731
  const EXTENSION = /\.[\w-]+$/;
826
732
  const ALIAS = /^(?:[@~]\/|#)/;
@@ -856,7 +762,7 @@ const addedLines = (change) => {
856
762
  return change.after.split("\n").filter((line) => !before.has(line)).join("\n");
857
763
  };
858
764
  const acceptanceTests = (changes) => changes.filter((c) => c.after !== void 0 && isCode$1(c.path) && isTestFile(c.path));
859
- const idsOf = (file, slice) => criterionIds(read(file) ?? "", slice);
765
+ const idsOf = (file) => criterionIds(read(file) ?? "");
860
766
  const unnamed = (ids, tests) => {
861
767
  const lines = tests.map(addedLines);
862
768
  return ids.filter((id) => !lines.some((text) => named(id, text)));
@@ -866,9 +772,9 @@ const unnamed = (ids, tests) => {
866
772
  * test line of the pass names, or a test importing a file the pass added —
867
773
  * naive structure a reset and refactor replaces, which the tests must survive.
868
774
  */
869
- const acceptanceFault = (file, tip, slice) => {
775
+ const acceptanceFault = (file, tip) => {
870
776
  const tests = acceptanceTests(tip.changes);
871
- const untested = unnamed(idsOf(file, slice), tests);
777
+ const untested = unnamed(idsOf(file), tests);
872
778
  if (untested.length > 0) return `acceptance-tests: no test of the naive pass names ${untested.join(", ")} — write a behaviour-level test for each criterion with its ID in the test or scenario name, e.g. "[${untested[0]}] …"`;
873
779
  const added = tip.changes.filter((c) => c.status === "added" && isCode$1(c.path) && !isTestFile(c.path)).map((c) => c.path);
874
780
  const reaching = tests.filter((test) => holdsCallSites(test.path)).flatMap((test) => {
@@ -878,8 +784,8 @@ const acceptanceFault = (file, tip, slice) => {
878
784
  if (reaching.length > 0) return `acceptance-internals: these tests import files the naive pass added — test through code that existed before it (a public entry point, an existing module's exports):\n${reaching.join("\n")}`;
879
785
  };
880
786
  /** What a rebuild carries over from the naive pass `tip`: the IDs its tests name, and those test files. */
881
- const naiveAcceptance = (tip, slice) => {
882
- const ids = idsOf(REQUIREMENTS, slice);
787
+ const naiveAcceptance = (tip) => {
788
+ const ids = idsOf(REQUIREMENTS);
883
789
  const perTest = acceptanceTests(tip.changes).map((c) => {
884
790
  const lines = addedLines(c);
885
791
  return {
@@ -949,31 +855,19 @@ const applied = async (tip) => {
949
855
  return !wrote(".gtd/FEEDBACK.md") && codeChanges().length > 0;
950
856
  };
951
857
  /** `carried` limited to the criteria `.gtd/REQUIREMENTS.md` lists now; a file listing none narrows nothing. */
952
- const settled = (carried, slice) => {
953
- const listed = idsOf(REQUIREMENTS, slice);
954
- if (carried === void 0) return listed;
858
+ const settled = (carried) => {
859
+ const listed = idsOf(REQUIREMENTS);
955
860
  return listed.length === 0 ? carried : carried.filter((id) => listed.includes(id));
956
861
  };
957
- const build = (options) => continuing(phase("build", requireCriteriaIfEdited), async (from, fresh) => {
958
- await fresh(() => agentWithSkills("building", implementBuildingPrompt(options.reference, options.tier, options.amend, options.afterRefactor, flagModeOn(), options.rebuild, sliceIds(options.slice), from), {
959
- label: from === void 0 ? "Implementing" : "Continuing the implementation",
862
+ const build = async (options) => {
863
+ await agentWithSkills("building", implementBuildingPrompt(options.reference, options.tier, options.amend, options.afterRefactor, flagModeOn(), options.rebuild), {
864
+ label: "Implementing",
960
865
  model: coder(),
961
866
  system: builderSystem(),
962
867
  ...options.afterRefactor === true ? { allowEmpty: true } : {}
963
- }));
868
+ });
964
869
  requireCriteriaFrozen(REQUIREMENTS);
965
- const note = read(HANDOFF);
966
- if (note === void 0) return { result: void 0 };
967
- const ids = settled(options.rebuild?.acceptance?.ids, options.slice);
968
- return {
969
- result: void 0,
970
- handoff: {
971
- snapshot: head(),
972
- note: note.trim(),
973
- open: unnamed(ids, acceptanceTests(changesSince(start())))
974
- }
975
- };
976
- });
870
+ };
977
871
  async function implement(first, tier, amend) {
978
872
  await implementing(typeof first === "object" && first !== null ? first : {
979
873
  reference: first,
@@ -990,30 +884,19 @@ const implementing = (options) => scope("implement", async () => {
990
884
  else requireCriteriaFrozen(REQUIREMENTS);
991
885
  if (built && acceptance !== void 0) requireAcceptance({
992
886
  ...acceptance,
993
- ids: settled(acceptance.ids, options.slice)
887
+ ids: settled(acceptance.ids)
994
888
  }, since);
995
889
  const keepsTests = built && acceptance !== void 0 ? () => requireAcceptanceKept(acceptance) : void 0;
996
890
  await green(keepsTests);
997
- await prototypeTest(options.slice, keepsTests);
891
+ await prototypeTest(keepsTests);
998
892
  const ids = criterionIds(read(".gtd/REQUIREMENTS.md") ?? "");
999
- await closing(moreToBuild(options.more));
893
+ await run("closing", removeScript([
894
+ REQUIREMENTS,
895
+ REFACTOR_NOTE,
896
+ PROTOTYPE
897
+ ]), { label: "Closing out the implementation" });
1000
898
  return ids;
1001
899
  });
1002
- const moreToBuild = (more) => typeof more === "function" ? more() : more === true;
1003
- /** The last slice's closing, for a last slice a steer left with no criterion to build. */
1004
- const closeOut = () => scope("implement", () => closing(false));
1005
- /** A slice with `more` after it keeps the criteria and the slicing for the next one. */
1006
- const closing = (more) => run("closing", removeScript(more ? [
1007
- REFACTOR_NOTE,
1008
- HANDOFF,
1009
- PROTOTYPE
1010
- ] : [
1011
- REQUIREMENTS,
1012
- REFACTOR_NOTE,
1013
- SLICES,
1014
- HANDOFF,
1015
- PROTOTYPE
1016
- ]), { label: "Closing out the implementation" });
1017
900
  /** Resolves `true` when the human steered (edited), `false` on a clean overrule. */
1018
901
  const steer = async (retry) => {
1019
902
  await human("steer", {
@@ -1044,8 +927,8 @@ const budget = () => {
1044
927
  };
1045
928
  };
1046
929
  /** Sends a pass whose tests fall short or run red back (`undefined`: it goes on, an overruled one as it is). */
1047
- const vetted = async (tip, vetting, slice) => {
1048
- const fault = vetting.waived ? void 0 : acceptanceFault(REQUIREMENTS, tip, slice);
930
+ const vetted = async (tip, vetting) => {
931
+ const fault = vetting.waived ? void 0 : acceptanceFault(REQUIREMENTS, tip);
1049
932
  if (fault !== void 0) {
1050
933
  const verdict = await vetting.again({
1051
934
  fault,
@@ -1079,16 +962,16 @@ const ruled = async (tip, again) => {
1079
962
  tip
1080
963
  } : next;
1081
964
  };
1082
- const decide = (slice) => scope("seam", async () => {
965
+ const decide = () => scope("seam", async () => {
1083
966
  const vetting = {
1084
967
  again: budget(),
1085
968
  waived: false
1086
969
  };
1087
- const naive = phase("naive pass", requireCriteriaIfEdited);
1088
970
  let retry;
1089
971
  for (;;) {
1090
- const tip = await naiveContinued(retry, slice, naive);
1091
- const outcome = await vetted(tip, vetting, slice) ?? (flagModeOn() ? await ruled(tip, vetting.again) : {
972
+ await naivePass(retry);
973
+ const tip = kept("naive");
974
+ const outcome = await vetted(tip, vetting) ?? (flagModeOn() ? await ruled(tip, vetting.again) : {
1092
975
  reference: tip.hash,
1093
976
  tip
1094
977
  });
@@ -1109,8 +992,8 @@ const refactorNote = async (reference, strays) => {
1109
992
  if (others.length > 0 || note.trim() === "") refuse(`gtd land: refactor-note: write ${REFACTOR_NOTE} and change nothing else${others.length > 0 ? ` — revert these:\n${others.map((path) => ` - ${path}`).join("\n")}` : ""}`);
1110
993
  return note;
1111
994
  };
1112
- const seamBuild = async (base, slice$1 = {}) => {
1113
- const { reference, tip, shape } = await decide(slice$1.criteria);
995
+ const seamBuild = async (base) => {
996
+ const { reference, tip, shape } = await decide();
1114
997
  if (shape === void 0) return {
1115
998
  reference,
1116
999
  base,
@@ -1125,107 +1008,31 @@ const seamBuild = async (base, slice$1 = {}) => {
1125
1008
  return {
1126
1009
  reference,
1127
1010
  base,
1128
- rebuild: { acceptance: naiveAcceptance(tip, slice$1.criteria) }
1011
+ rebuild: { acceptance: naiveAcceptance(tip) }
1129
1012
  };
1130
1013
  }
1131
1014
  const strays = refactorStrays(shape);
1132
1015
  if (strays.length === 0) return {
1133
1016
  reference,
1134
1017
  base,
1135
- rebuild: { acceptance: naiveAcceptance(tip, slice$1.criteria) }
1018
+ rebuild: { acceptance: naiveAcceptance(tip) }
1136
1019
  };
1137
1020
  const note = await scope("seam", () => refactorNote(reference, strays));
1138
- const refactored = await slice(slice$1.refactor ?? "refactor", () => reviewedRefactor(shape, {
1021
+ const refactored = await reviewedRefactor(shape, {
1139
1022
  reference,
1140
1023
  note
1141
- }));
1024
+ });
1142
1025
  return {
1143
1026
  reference,
1144
1027
  base: head(),
1145
1028
  refactored,
1146
1029
  rebuild: {
1147
1030
  note,
1148
- acceptance: naiveAcceptance(tip, slice$1.criteria)
1031
+ acceptance: naiveAcceptance(tip)
1149
1032
  }
1150
1033
  };
1151
1034
  };
1152
1035
  //#endregion
1153
- //#region src/workflows/feature/slicing.ts
1154
- const ID = /^(AC-\d+)(?![\w-])/;
1155
- /** The `sliceMaxCriteria` setting. Anything but a positive integer fails rather than guess a cap. */
1156
- const sliceCap = () => {
1157
- const value = vars.sliceMaxCriteria ?? defaults.sliceMaxCriteria;
1158
- if (!/^[1-9]\d*$/.test(value)) refuse(`gtd: sliceMaxCriteria must be a positive integer, got ${JSON.stringify(value)}`);
1159
- return Number(value);
1160
- };
1161
- /** Each `## ` heading of `text` with the list items under it; an item not led by an ID keeps an empty one. */
1162
- const slicesOf = (text) => {
1163
- const slices = [];
1164
- let open = false;
1165
- for (const { line, fenced } of markFenced(text)) {
1166
- if (fenced) continue;
1167
- const heading = HEADING.exec(line);
1168
- if (heading !== null) {
1169
- open = heading[1] === "##";
1170
- if (open) slices.push({
1171
- title: heading[2],
1172
- ids: []
1173
- });
1174
- continue;
1175
- }
1176
- const item = ITEM.exec(line);
1177
- if (item !== null && open) slices.at(-1).ids.push(ID.exec(item[1])?.[1] ?? "");
1178
- }
1179
- return slices;
1180
- };
1181
- const twice = (list) => [...new Set(list.filter((id, i) => list.indexOf(id) !== i))];
1182
- /** Why `slices` fail to put each of `ids` in exactly one slice of at most `cap`, or `undefined`. */
1183
- const sliceFault = (slices, ids, cap) => {
1184
- const listed = slices.flatMap((s) => s.ids);
1185
- if (slices.length === 0) return `no "## " slice`;
1186
- const empty = slices.filter((s) => s.ids.length === 0).map((s) => s.title);
1187
- if (empty.length > 0) return `a slice with no criterion: ${empty.join(", ")}`;
1188
- if (listed.includes("")) return "a list item not led by a criterion ID";
1189
- const over = slices.filter((s) => s.ids.length > cap).map((s) => s.title);
1190
- if (over.length > 0) return `more than ${cap} criteria in: ${over.join(", ")}`;
1191
- const repeated = twice(listed);
1192
- if (repeated.length > 0) return `an ID in more than one slice: ${repeated.join(", ")}`;
1193
- const unknown = listed.filter((id) => !ids.includes(id));
1194
- if (unknown.length > 0) return `an ID ${REQUIREMENTS} does not list: ${unknown.join(", ")}`;
1195
- const missing = ids.filter((id) => !listed.includes(id));
1196
- if (missing.length > 0) return `no slice for: ${missing.join(", ")}`;
1197
- };
1198
- /** Refuse a turn whose `.gtd/SLICES.md` does not put each of `ids` in exactly one slice of at most `cap`. */
1199
- const requireSlices = (ids, cap) => {
1200
- const slices = slicesOf(read(".gtd/SLICES.md") ?? "");
1201
- const why = sliceFault(slices, ids, cap);
1202
- if (why !== void 0) refuse(`gtd land: slices: ${SLICES} has ${why} — list each slice as a "## <title>" heading over "- AC-<n>" items, every criterion of ${REQUIREMENTS} in exactly one slice, at most ${cap} per slice`);
1203
- return slices;
1204
- };
1205
- /**
1206
- * The slices to build, in order. Criteria within `sliceMaxCriteria` are one
1207
- * slice and no turn; above it `design.slicing` groups them.
1208
- */
1209
- const slicing = async () => {
1210
- const all = criterionIds(read(".gtd/REQUIREMENTS.md") ?? "");
1211
- const cap = sliceCap();
1212
- if (all.length <= cap) return [{
1213
- title: "",
1214
- ids: all
1215
- }];
1216
- return scope("design", async () => {
1217
- await agentWithSkills("slicing", slicingPrompt(cap), {
1218
- label: "Slicing the change",
1219
- file: SLICES,
1220
- model: planner(),
1221
- system: designSystem()
1222
- });
1223
- return requireSlices(all, cap);
1224
- });
1225
- };
1226
- /** Slice `i`'s criteria; `undefined` when `slices` is the one slice of an unsliced change. */
1227
- const sliceCriteria = (slices, i) => slices.length === 1 ? void 0 : i < slices.length - 1 ? { only: slices[i].ids } : { except: slices.slice(0, -1).flatMap((s) => s.ids) };
1228
- //#endregion
1229
1036
  //#region src/workflows/feature/feature.ts
1230
1037
  /** Revert the sketch that started the process out of the working tree; its intent survives in history. */
1231
1038
  const unwind = () => {
@@ -1233,94 +1040,37 @@ const unwind = () => {
1233
1040
  return run("unwind", revertScript(commit, FEEDBACK, unwindFailure(commit)), { label: "Unwinding your input" });
1234
1041
  };
1235
1042
  /**
1236
- * The slices `design.slicing` grouped the criteria into, each built in turn
1237
- * from where the previous one landed; design must have run since `firstBase`.
1043
+ * A naive pass (judged only with `flagMode` on), then implement and the
1044
+ * quality lap, then the review; design must have run since `firstBase`.
1238
1045
  */
1239
1046
  const buildFeature = async (firstBase) => {
1240
1047
  const tier = riskTierOn() ? recordRisk() : void 0;
1241
- const slices = await slicing();
1242
1048
  const handedOut = new Set(listedIds());
1243
- const one = slices.length === 1;
1244
- const built = (i) => sliceIds(sliceCriteria(slices, i))?.length !== 0;
1245
- const reports = [];
1246
- for (const i of slices.keys()) {
1247
- if (!built(i)) continue;
1248
- const n = one ? "" : `-${i + 1}`;
1249
- await buildSlice(i === 0 ? firstBase : head(), {
1250
- number: `${i + 1}`,
1251
- tier,
1252
- criteria: sliceCriteria(slices, i),
1253
- refactor: `refactor${n}`,
1254
- feature: `feature${n}`,
1255
- more: () => slices.some((_, j) => j > i && built(j)),
1256
- reviewBase: one ? void 0 : firstBase,
1257
- handedOut,
1258
- laps: reports
1259
- });
1260
- }
1049
+ const seam = await seamBuild(firstBase);
1050
+ const used = gather(handedOut);
1051
+ const closed = await implementing({
1052
+ reference: seam.reference,
1053
+ tier,
1054
+ afterRefactor: seam.refactored,
1055
+ naive: seam.land === true ? seam.reference : void 0,
1056
+ rebuild: seam.rebuild
1057
+ });
1058
+ const carried = seam.rebuild?.acceptance?.tests ?? [];
1059
+ const base = seam.refactored === true && !changesSince(seam.base).some((c) => isCode$1(c.path) && !carried.includes(c.path)) ? firstBase : seam.base;
1060
+ const outcome = await reviewedTail(base, base);
1061
+ await featureFeedback(outcome, base, {
1062
+ closed,
1063
+ used
1064
+ });
1261
1065
  };
1262
1066
  const listedIds = () => criterionIds(read(".gtd/REQUIREMENTS.md") ?? "");
1263
1067
  const gather = (handedOut) => {
1264
1068
  for (const id of listedIds()) handedOut.add(id);
1265
1069
  return [...handedOut];
1266
1070
  };
1267
- /** A naive pass (judged only with `flagMode` on), then implement and the quality lap; after the last slice, the review. */
1268
- const buildSlice = async (sliceBase, build) => {
1269
- const seam = await seamBuild(sliceBase, {
1270
- criteria: build.criteria,
1271
- refactor: build.refactor
1272
- });
1273
- const used = gather(build.handedOut);
1274
- await slice(build.feature, async () => {
1275
- const closed = await implementing({
1276
- reference: seam.reference,
1277
- tier: build.tier,
1278
- afterRefactor: seam.refactored,
1279
- naive: seam.land === true ? seam.reference : void 0,
1280
- rebuild: seam.rebuild,
1281
- slice: build.criteria,
1282
- more: build.more
1283
- });
1284
- const more = build.more();
1285
- const carried = seam.rebuild?.acceptance?.tests ?? [];
1286
- const base = seam.refactored === true && !changesSince(seam.base).some((c) => isCode$1(c.path) && !carried.includes(c.path)) ? sliceBase : seam.base;
1287
- if (more) {
1288
- const guard = () => requireCriteriaFrozen(REQUIREMENTS);
1289
- const report = await tail(async (_, report) => report, {
1290
- green: true,
1291
- lensBase: base,
1292
- guard,
1293
- guardRests: false
1294
- });
1295
- build.laps.push({
1296
- slice: build.number,
1297
- report
1298
- });
1299
- return;
1300
- }
1301
- const reviewBase = build.reviewBase ?? base;
1302
- const outcome = await reviewedTail(reviewBase, base, {
1303
- slice: build.number,
1304
- laps: build.laps
1305
- });
1306
- await featureFeedback(outcome, base, {
1307
- closed,
1308
- used
1309
- });
1310
- });
1311
- };
1312
- /**
1313
- * The quality lap of slice `last.slice`, then a reviewer's walkthrough since
1314
- * `base` for the human, carrying what earlier slices' `laps` left too.
1315
- */
1316
- const reviewedTail = (base, lensBase, last = {
1317
- slice: "",
1318
- laps: []
1319
- }, lap = "first") => tail((escalations, report) => humanReview(base, escalations, {
1320
- report: last.laps.length === 0 ? report : joinReports([...last.laps, {
1321
- slice: last.slice,
1322
- report
1323
- }]),
1071
+ /** The quality lap, then a reviewer's walkthrough since `base` for the human. */
1072
+ const reviewedTail = (base, lensBase, lap = "first") => tail((escalations, report) => humanReview(base, escalations, {
1073
+ report,
1324
1074
  walkthrough: true,
1325
1075
  lap
1326
1076
  }), {
@@ -1345,7 +1095,7 @@ const featureFeedback = async (first, lensBase, ids) => {
1345
1095
  tier: riskTierOn() ? recordRisk() : void 0,
1346
1096
  amend: true
1347
1097
  });
1348
- outcome = await reviewedTail(outcome.base, lensBase, void 0, "feedback");
1098
+ outcome = await reviewedTail(outcome.base, lensBase, "feedback");
1349
1099
  }
1350
1100
  };
1351
1101
  /** Design — skipped when the sketch's own criteria are judged clear — then `buildFeature`. */
@@ -1353,7 +1103,7 @@ const planAndBuild = async (firstBase, stated) => {
1353
1103
  if (!await skipDesign(riskTierOn() ? void 0 : stated)) await design(firstBase);
1354
1104
  await buildFeature(firstBase);
1355
1105
  };
1356
- /** After a tail that skipped planning: stop on sign-off, re-plan on feedback. Opens no slice: slices cannot nest. */
1106
+ /** After a tail that skipped planning: stop on sign-off, re-plan on feedback. */
1357
1107
  const afterTail = async (first) => {
1358
1108
  let outcome = first;
1359
1109
  while (outcome.verdict === "feedback") {
@@ -1375,7 +1125,6 @@ const ordinaryStart = async () => {
1375
1125
  });
1376
1126
  refusePendingHandOff();
1377
1127
  flagModeOn();
1378
- sliceCap();
1379
1128
  prototypeRounds();
1380
1129
  const stated = statedCriteria(changes(), head());
1381
1130
  await unwind();
@@ -1392,4 +1141,4 @@ const feature = shipped(ordinaryStart);
1392
1141
  //#region src/workflows/feature/index.ts
1393
1142
  var feature_default = feature;
1394
1143
  //#endregion
1395
- export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, closeOut, collecting, criteriaOf, criterionIds, feature_default as default, defaults, design, envDefaults, feature, fixNits, handsOnIds, hasImpact, holdsCallSites, implement, implementing, isTestFile, judgeSeam, naiveAcceptance, naivePass, ordinaryStart, planAndBuild, reUnwind, refactorCollecting, refactorFirst, refactorNote, refactorStrays, requireAcceptance, requireAcceptanceKept, requireCriteria, requireCriteriaFrozen, requireCriteriaIfEdited, requireImpact, requireImpactOnly, requireNoNewFlags, requireNoTestFiles, requireSlices, requireStableIds, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, sliceCap, sliceCriteria, sliceIds, slicesOf, slicing, statedCriteria, steering, summary, triage, unstableIds, unwind };
1144
+ export { COMMENT, REFACTOR_PACKAGE, acceptanceFault, access, afterTail, answerProductQuestions, answerReviewQuestions, buildFeature, buildTail, collecting, criteriaOf, criterionIds, feature_default as default, defaults, design, envDefaults, feature, fixNits, handsOnIds, hasImpact, holdsCallSites, implement, implementing, isTestFile, judgeSeam, naiveAcceptance, naivePass, ordinaryStart, planAndBuild, reUnwind, refactorCollecting, refactorFirst, refactorNote, refactorStrays, requireAcceptance, requireAcceptanceKept, requireCriteria, requireCriteriaFrozen, requireImpact, requireImpactOnly, requireNoNewFlags, requireNoTestFiles, requireStableIds, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, statedCriteria, steering, summary, triage, unstableIds, unwind };