@pmelab/gtd 54.0.0 → 55.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 (31) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +56 -50
  3. package/dist/chunks/{reserved-CQ7amcKG.mjs → reserved-DHafcW7t.mjs} +47 -27
  4. package/dist/chunks/{review-CXzUXJHL.mjs → review-BJGKwlYv.mjs} +2 -2
  5. package/dist/chunks/{tail-JZ9PAOwp.mjs → tail-B9Hw2AFB.mjs} +12 -8
  6. package/dist/workflows/cleanup.mjs +2 -2
  7. package/dist/workflows/feature.mjs +41 -94
  8. package/dist/workflows/fix.mjs +2 -2
  9. package/dist/workflows/review.mjs +3 -3
  10. package/dist/workflows/rollout.mjs +1 -1
  11. package/dist/workflows.mjs +97 -126
  12. package/package.json +1 -1
  13. package/src/workflows/feature/criteria-coverage.feature +109 -0
  14. package/src/workflows/feature/feature.ts +9 -4
  15. package/src/workflows/feature/green.ts +2 -5
  16. package/src/workflows/feature/naive-acceptance.feature +31 -32
  17. package/src/workflows/feature/prototype.ts +5 -8
  18. package/src/workflows/feature/refactor-rebuild.feature +16 -12
  19. package/src/workflows/feature/seam.test.ts +19 -101
  20. package/src/workflows/feature/seam.ts +13 -89
  21. package/src/workflows/fix/fix-quality.feature +4 -2
  22. package/src/workflows/shared/access.test.ts +1 -0
  23. package/src/workflows/shared/review.test.ts +3 -1
  24. package/src/workflows/shared/skills.test.ts +3 -1
  25. package/src/workflows/shared/steps.test.ts +9 -6
  26. package/src/workflows/shared/steps.ts +12 -3
  27. package/src/workflows/shared/tail.test.ts +20 -2
  28. package/src/workflows/shared/tail.ts +20 -7
  29. package/src/workflows/shared/text.test.ts +19 -6
  30. package/src/workflows/shared/text.ts +50 -29
  31. package/src/workflows/shared/vars.ts +1 -1
@@ -1,8 +1,8 @@
1
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 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";
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-DHafcW7t.mjs";
4
+ import { a as refusePendingHandOff, o as tail } from "../chunks/tail-B9Hw2AFB.mjs";
5
+ import { i as reUnwind, n as humanReview, r as isCode$1, t as buildTail } from "../chunks/review-BJGKwlYv.mjs";
6
6
  import { posix } from "node:path";
7
7
  //#region src/workflows/shared/fences.ts
8
8
  const markFenced = (text) => {
@@ -304,16 +304,13 @@ const design = (base, guard) => scope("design", async () => {
304
304
  });
305
305
  //#endregion
306
306
  //#region src/workflows/feature/green.ts
307
- const green = (guard) => healthy(() => agentWithSkills("fix.suite.fixing", implementFixPrompt(), {
307
+ const green = () => healthy(() => agentWithSkills("fix.suite.fixing", implementFixPrompt(), {
308
308
  label: "Fixing the check",
309
309
  file: FEEDBACK,
310
310
  model: coder(),
311
311
  system: builderSystem()
312
312
  }), {
313
- guard: () => {
314
- requireCriteriaFrozen(REQUIREMENTS);
315
- guard?.();
316
- },
313
+ guard: () => requireCriteriaFrozen(REQUIREMENTS),
317
314
  guardRests: false
318
315
  });
319
316
  //#endregion
@@ -403,7 +400,7 @@ const testing = async (ids, retest) => {
403
400
  });
404
401
  return requireReport(ids, retest);
405
402
  };
406
- const fixing = async (guard) => {
403
+ const fixing = async () => {
407
404
  await scope("fix", () => agentWithSkills("fixing", prototypeFixingPrompt(), {
408
405
  label: "Fixing what the hands-on test found",
409
406
  file: PROTOTYPE,
@@ -413,7 +410,6 @@ const fixing = async (guard) => {
413
410
  }));
414
411
  if (changes().some((c) => c.path === ".gtd/PROTOTYPE.md")) refuse(`gtd land: prototype-fix: leave ${PROTOTYPE} as it is — the next round re-tests from it`);
415
412
  frozen();
416
- guard?.();
417
413
  };
418
414
  /** A person's rest; resolves `true` when they changed something to test again, `false` on a clean overrule. */
419
415
  const askPerson = async (name, message, label) => {
@@ -431,10 +427,9 @@ const askPerson = async (name, message, label) => {
431
427
  * Use the change by hand: a testing turn reports on every criterion a person
432
428
  * can observe, a fix turn takes each failure, and the change is tested again —
433
429
  * until the report is clean, or `prototypeRounds` fixes are spent and a person
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.
430
+ * decides. A change with no such criterion is not tested by hand.
436
431
  */
437
- const prototypeTest = async (guard) => {
432
+ const prototypeTest = async () => {
438
433
  const cap = prototypeRounds();
439
434
  if (cap === 0) return;
440
435
  await scope("prototype", async () => {
@@ -450,12 +445,12 @@ const prototypeTest = async (guard) => {
450
445
  } else if (open.length === 0) return;
451
446
  else if (fixes < cap && open.some((i) => i.verdict === "fail")) {
452
447
  fixes++;
453
- await fixing(guard);
448
+ await fixing();
454
449
  } else {
455
450
  if (!await askPerson("open", prototypeOpenMessage(open, fixes), "Hands-on test still failing")) return;
456
451
  fixes = 0;
457
452
  }
458
- await green(guard);
453
+ await green();
459
454
  }
460
455
  });
461
456
  };
@@ -755,69 +750,25 @@ const importsOf = (test) => [...(test.after ?? "").replace(COMMENT, "").matchAll
755
750
  }));
756
751
  });
757
752
  const reaches = (imports, added) => namesOf(added).some((name) => imports.some(({ path, tail }) => name === path || tail && name.endsWith(`/${path}`)));
758
- const named = (id, text) => new RegExp(`(?<![\\w-])${id}(?!\\d)`).test(text);
759
- /** The lines `change` added: an ID an earlier change left in the file does not count. */
760
- const addedLines = (change) => {
761
- const before = new Set((change.before ?? "").split("\n"));
762
- return change.after.split("\n").filter((line) => !before.has(line)).join("\n");
763
- };
764
753
  const acceptanceTests = (changes) => changes.filter((c) => c.after !== void 0 && isCode$1(c.path) && isTestFile(c.path));
765
- const idsOf = (file) => criterionIds(read(file) ?? "");
766
- const unnamed = (ids, tests) => {
767
- const lines = tests.map(addedLines);
768
- return ids.filter((id) => !lines.some((text) => named(id, text)));
769
- };
770
754
  /**
771
- * Why `tip`'s tests fall short, or `undefined`: a criterion ID of `file` no
772
- * test line of the pass names, or a test importing a file the pass added —
773
- * naive structure a reset and refactor replaces, which the tests must survive.
755
+ * Why `tip`'s tests fall short, or `undefined`: a test importing a file the
756
+ * pass added — naive structure a reset and refactor replaces, which the tests
757
+ * must survive.
774
758
  */
775
- const acceptanceFault = (file, tip) => {
776
- const tests = acceptanceTests(tip.changes);
777
- const untested = unnamed(idsOf(file), tests);
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]}] …"`;
759
+ const acceptanceFault = (tip) => {
779
760
  const added = tip.changes.filter((c) => c.status === "added" && isCode$1(c.path) && !isTestFile(c.path)).map((c) => c.path);
780
- const reaching = tests.filter((test) => holdsCallSites(test.path)).flatMap((test) => {
761
+ const reaching = acceptanceTests(tip.changes).filter((test) => holdsCallSites(test.path)).flatMap((test) => {
781
762
  const imports = importsOf(test);
782
763
  return added.filter((path) => reaches(imports, path)).map((path) => ` - ${test.path} → ${path}`);
783
764
  });
784
765
  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")}`;
785
766
  };
786
- /** What a rebuild carries over from the naive pass `tip`: the IDs its tests name, and those test files. */
787
- const naiveAcceptance = (tip) => {
788
- const ids = idsOf(REQUIREMENTS);
789
- const perTest = acceptanceTests(tip.changes).map((c) => {
790
- const lines = addedLines(c);
791
- return {
792
- path: c.path,
793
- ids: ids.filter((id) => named(id, lines))
794
- };
795
- });
796
- return {
797
- hash: tip.hash,
798
- tests: perTest.filter((c) => c.ids.length > 0).map((c) => c.path),
799
- ids: ids.filter((id) => perTest.some((c) => c.ids.includes(id)))
800
- };
801
- };
802
- /**
803
- * Refuse a rebuild whose test changes since `since` leave out an ID the naive
804
- * pass's tests named. A skipped test still counts: the gate reads text, never runs it.
805
- */
806
- const requireAcceptance = (acceptance, since) => {
807
- const missing = unnamed(acceptance.ids, acceptanceTests(changesSince(since)));
808
- if (missing.length === 0) return;
809
- refuse(`gtd land: rebuild-acceptance: the rebuild's tests leave out ${missing.join(", ")} — carry over the naive pass's acceptance tests (\`git show ${acceptance.hash} -- ${acceptance.tests.map(quote).join(" ")}\`), each with its ID in the test or scenario name`);
810
- };
811
- /**
812
- * Refuse a fix turn that, on its own, drops an ID the naive pass's tests named
813
- * from a test file. Turn-local, so a person's edit at an escalation rest never
814
- * wedges later fix turns.
815
- */
816
- const requireAcceptanceKept = (acceptance) => {
817
- const dropped = acceptance.ids.filter((id) => changes().filter((c) => isCode$1(c.path) && isTestFile(c.path)).some((c) => named(id, c.before ?? "") && !named(id, c.after ?? "")));
818
- if (dropped.length === 0) return;
819
- refuse(`gtd land: rebuild-acceptance: this turn drops ${dropped.join(", ")} from the tests — the naive pass's acceptance tests stay; fix the code, not them`);
820
- };
767
+ /** What a rebuild carries over from the naive pass `tip`: every test file it added or changed. */
768
+ const naiveAcceptance = (tip) => ({
769
+ hash: tip.hash,
770
+ tests: acceptanceTests(tip.changes).map((c) => c.path)
771
+ });
821
772
  const restore = (path) => `if git cat-file -e ${quote(`HEAD:${path}`)} 2>/dev/null; then git checkout -q HEAD -- ${quote(path)}; else rm -f -- ${quote(path)}; fi`;
822
773
  /**
823
774
  * Run the suite with `tip`'s diff applied, then take it out again; resolves
@@ -854,11 +805,6 @@ const applied = async (tip) => {
854
805
  await run("applying", applyScript(tip, FEEDBACK, naiveApplyFailure(tip), [".gtd"]), { label: "Applying the naive pass" });
855
806
  return !wrote(".gtd/FEEDBACK.md") && codeChanges().length > 0;
856
807
  };
857
- /** `carried` limited to the criteria `.gtd/REQUIREMENTS.md` lists now; a file listing none narrows nothing. */
858
- const settled = (carried) => {
859
- const listed = idsOf(REQUIREMENTS);
860
- return listed.length === 0 ? carried : carried.filter((id) => listed.includes(id));
861
- };
862
808
  const build = async (options) => {
863
809
  await agentWithSkills("building", implementBuildingPrompt(options.reference, options.tier, options.amend, options.afterRefactor, flagModeOn(), options.rebuild), {
864
810
  label: "Implementing",
@@ -877,18 +823,10 @@ async function implement(first, tier, amend) {
877
823
  }
878
824
  /** `implement`, resolving with the criterion IDs the requirements listed when it closed. */
879
825
  const implementing = (options) => scope("implement", async () => {
880
- const since = head();
881
- const acceptance = options.rebuild?.acceptance;
882
- const built = options.naive === void 0 || !await applied(options.naive);
883
- if (built) await build(options);
826
+ if (options.naive === void 0 || !await applied(options.naive)) await build(options);
884
827
  else requireCriteriaFrozen(REQUIREMENTS);
885
- if (built && acceptance !== void 0) requireAcceptance({
886
- ...acceptance,
887
- ids: settled(acceptance.ids)
888
- }, since);
889
- const keepsTests = built && acceptance !== void 0 ? () => requireAcceptanceKept(acceptance) : void 0;
890
- await green(keepsTests);
891
- await prototypeTest(keepsTests);
828
+ await green();
829
+ await prototypeTest();
892
830
  const ids = criterionIds(read(".gtd/REQUIREMENTS.md") ?? "");
893
831
  await run("closing", removeScript([
894
832
  REQUIREMENTS,
@@ -928,7 +866,7 @@ const budget = () => {
928
866
  };
929
867
  /** Sends a pass whose tests fall short or run red back (`undefined`: it goes on, an overruled one as it is). */
930
868
  const vetted = async (tip, vetting) => {
931
- const fault = vetting.waived ? void 0 : acceptanceFault(REQUIREMENTS, tip);
869
+ const fault = vetting.waived ? void 0 : acceptanceFault(tip);
932
870
  if (fault !== void 0) {
933
871
  const verdict = await vetting.again({
934
872
  fault,
@@ -1048,6 +986,7 @@ const buildFeature = async (firstBase) => {
1048
986
  const handedOut = new Set(listedIds());
1049
987
  const seam = await seamBuild(firstBase);
1050
988
  const used = gather(handedOut);
989
+ const requirements = read(REQUIREMENTS);
1051
990
  const closed = await implementing({
1052
991
  reference: seam.reference,
1053
992
  tier,
@@ -1057,7 +996,7 @@ const buildFeature = async (firstBase) => {
1057
996
  });
1058
997
  const carried = seam.rebuild?.acceptance?.tests ?? [];
1059
998
  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);
999
+ const outcome = await reviewedTail(base, base, requirements);
1061
1000
  await featureFeedback(outcome, base, {
1062
1001
  closed,
1063
1002
  used
@@ -1069,13 +1008,14 @@ const gather = (handedOut) => {
1069
1008
  return [...handedOut];
1070
1009
  };
1071
1010
  /** 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, {
1011
+ const reviewedTail = (base, lensBase, requirements, lap = "first") => tail((escalations, report) => humanReview(base, escalations, {
1073
1012
  report,
1074
1013
  walkthrough: true,
1075
1014
  lap
1076
1015
  }), {
1077
1016
  green: true,
1078
- lensBase
1017
+ lensBase,
1018
+ requirements
1079
1019
  });
1080
1020
  const featureFeedback = async (first, lensBase, ids) => {
1081
1021
  let outcome = first;
@@ -1091,11 +1031,13 @@ const featureFeedback = async (first, lensBase, ids) => {
1091
1031
  requireStableIds(REQUIREMENTS, lap);
1092
1032
  gather(handedOut);
1093
1033
  });
1034
+ const tier = riskTierOn() ? recordRisk() : void 0;
1035
+ const requirements = read(REQUIREMENTS);
1094
1036
  closed = await implementing({
1095
- tier: riskTierOn() ? recordRisk() : void 0,
1037
+ tier,
1096
1038
  amend: true
1097
1039
  });
1098
- outcome = await reviewedTail(outcome.base, lensBase, "feedback");
1040
+ outcome = await reviewedTail(outcome.base, lensBase, requirements, "feedback");
1099
1041
  }
1100
1042
  };
1101
1043
  /** Design — skipped when the sketch's own criteria are judged clear — then `buildFeature`. */
@@ -1109,11 +1051,16 @@ const afterTail = async (first) => {
1109
1051
  while (outcome.verdict === "feedback") {
1110
1052
  await reUnwind(outcome);
1111
1053
  await design(outcome.base);
1054
+ const tier = riskTierOn() ? recordRisk() : void 0;
1055
+ const requirements = read(REQUIREMENTS);
1112
1056
  await implement({
1113
- tier: riskTierOn() ? recordRisk() : void 0,
1057
+ tier,
1114
1058
  amend: true
1115
1059
  });
1116
- outcome = await buildTail(outcome.base, { green: true });
1060
+ outcome = await buildTail(outcome.base, {
1061
+ green: true,
1062
+ requirements
1063
+ });
1117
1064
  }
1118
1065
  };
1119
1066
  /** An ordinary start: wait at `idle`, unwind the sketch, check the baseline, then plan and build. */
@@ -1141,4 +1088,4 @@ const feature = shipped(ordinaryStart);
1141
1088
  //#region src/workflows/feature/index.ts
1142
1089
  var feature_default = feature;
1143
1090
  //#endregion
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 };
1091
+ 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, requireCriteria, requireCriteriaFrozen, requireImpact, requireImpactOnly, requireNoNewFlags, requireNoTestFiles, requireStableIds, requireTestCallSitesOnly, requireWithin, reviewedRefactor, seamBuild, skills, skipDesign, statedCriteria, steering, summary, triage, unstableIds, unwind };
@@ -1,7 +1,7 @@
1
1
  import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
2
2
  import { _ as reviewNotes, v as reviewRisks } from "../chunks/steering-CLhu8C7q.mjs";
3
- import { G as fixReviewNotesPrompt, Mt as envDefaults, W as finisherSystem, c as baseline, i as skills, j as agentWithSkills, jt as defaults, n as summary, r as access, s as shipped, t as steering, v as REVIEW, x as coder } from "../chunks/reserved-CQ7amcKG.mjs";
4
- import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-JZ9PAOwp.mjs";
3
+ import { G as fixReviewNotesPrompt, Mt as envDefaults, W as finisherSystem, c as baseline, i as skills, j as agentWithSkills, jt as defaults, n as summary, r as access, s as shipped, t as steering, v as REVIEW, x as coder } from "../chunks/reserved-DHafcW7t.mjs";
4
+ import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-B9Hw2AFB.mjs";
5
5
  //#region src/workflows/fix/fix.ts
6
6
  /**
7
7
  * Fix every note a human left in a handed-off `.gtd/REVIEW.md` and every
@@ -1,7 +1,7 @@
1
1
  import { read, refuse, removeScript, run, start } from "../flows.mjs";
2
- import { Mt as envDefaults, W as finisherSystem, _ as REQUIREMENTS, gt as reviewGateBlockedMessage, ht as reviewFeedbackFixPrompt, i as skills, j as agentWithSkills, jt as defaults, l as gate, n as summary, r as access, s as shipped, t as steering, x as coder } from "../chunks/reserved-CQ7amcKG.mjs";
3
- import { a as refusePendingHandOff } from "../chunks/tail-JZ9PAOwp.mjs";
4
- import { i as reUnwind, t as buildTail } from "../chunks/review-CXzUXJHL.mjs";
2
+ import { Mt as envDefaults, W as finisherSystem, _ as REQUIREMENTS, gt as reviewGateBlockedMessage, ht as reviewFeedbackFixPrompt, i as skills, j as agentWithSkills, jt as defaults, l as gate, n as summary, r as access, s as shipped, t as steering, x as coder } from "../chunks/reserved-DHafcW7t.mjs";
3
+ import { a as refusePendingHandOff } from "../chunks/tail-B9Hw2AFB.mjs";
4
+ import { i as reUnwind, t as buildTail } from "../chunks/review-BJGKwlYv.mjs";
5
5
  //#region src/workflows/review/review.ts
6
6
  const fixFeedback = async () => {
7
7
  await agentWithSkills("feedback.fixing", reviewFeedbackFixPrompt(), {
@@ -1,5 +1,5 @@
1
1
  import { agent, changesSince, glob, head, mark, read, refuse, removeScript, run, scope, vars } from "../flows.mjs";
2
- import { Gt as flipProblems, Mt as envDefaults, Ut as flagMentions, f as FEEDBACK, i as skills, jt as defaults, l as gate, n as summary, o as flagShipped, qt as requireFlag, r as access, t as steering, x as coder } from "../chunks/reserved-CQ7amcKG.mjs";
2
+ import { Gt as flipProblems, Mt as envDefaults, Ut as flagMentions, f as FEEDBACK, i as skills, jt as defaults, l as gate, n as summary, o as flagShipped, qt as requireFlag, r as access, t as steering, x as coder } from "../chunks/reserved-DHafcW7t.mjs";
3
3
  //#region src/workflows/rollout/rollout.ts
4
4
  const flippingPrompt = (name, registry) => `Roll out the release flag "${name}": in ${registry}, set \`defaultOn: true\` on its entry. Change nothing else — no other entry, no other field, no other file, no comments.`;
5
5
  const suiteBlockedMessage = () => "The suite is red after the rollout. Fix it by hand — a rollout may only touch the flag's registry entry — then land.";