@pmelab/gtd 45.2.0 → 47.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 (39) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +15 -30
  3. package/dist/chunks/{reserved-FWrjy7zo.mjs → reserved-DF1HD6jL.mjs} +42 -48
  4. package/dist/chunks/{review-Dhl4vvDe.mjs → review-Bv40kZu9.mjs} +9 -23
  5. package/dist/chunks/{tail-B-Es6Hwj.mjs → tail-D89fU_wf.mjs} +68 -39
  6. package/dist/gtd.bundle.mjs +5 -7
  7. package/dist/testkit.mjs +5 -7
  8. package/dist/workflows/cleanup.mjs +2 -2
  9. package/dist/workflows/feature.mjs +26 -22
  10. package/dist/workflows/fix.mjs +2 -2
  11. package/dist/workflows/review.mjs +14 -4
  12. package/dist/workflows/rollout.mjs +1 -1
  13. package/dist/workflows.mjs +270 -429
  14. package/package.json +1 -6
  15. package/src/install/ConfigScaffold.ts +1 -2
  16. package/src/install/Install.ts +4 -5
  17. package/src/workflows/cleanup/cleanup.test.ts +11 -9
  18. package/src/workflows/feature/feature.ts +38 -28
  19. package/src/workflows/feature/lens-review.feature +3 -1
  20. package/src/workflows/feature/slice-findings.feature +198 -0
  21. package/src/workflows/fix/fix-lens-origin.feature +101 -0
  22. package/src/workflows/fix/fix-quality.feature +131 -0
  23. package/src/workflows/index.ts +1 -3
  24. package/src/workflows/review/review.ts +15 -3
  25. package/src/workflows/shared/lenses.ts +30 -9
  26. package/src/workflows/shared/options.ts +1 -21
  27. package/src/workflows/shared/review.ts +5 -27
  28. package/src/workflows/shared/skills.test.ts +0 -2
  29. package/src/workflows/shared/skills.ts +0 -3
  30. package/src/workflows/shared/tail.ts +74 -57
  31. package/src/workflows/shared/text.ts +86 -33
  32. package/src/workflows/shared/vars.ts +0 -8
  33. package/dist/workflows/tests.mjs +0 -193
  34. package/src/workflows/feature/quality-unresolved.feature +0 -121
  35. package/src/workflows/tests/index.ts +0 -6
  36. package/src/workflows/tests/tests-options.feature +0 -52
  37. package/src/workflows/tests/tests.feature +0 -266
  38. package/src/workflows/tests/tests.test.ts +0 -51
  39. package/src/workflows/tests/tests.ts +0 -270
@@ -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, slice, start, vars, wrote } from "../flows.mjs";
2
2
  import { lensEntriesOf } from "../workflow-kit.mjs";
3
- import { $ as implementFixPrompt, A as planner, Ct as unwindFailedMessage, D as fixNits, Dt as testFileGlobs, E as fixCheck, Et as envDefaults, F as buildReviewCollectingPrompt, G as designGateAnswerMessage, H as coverageQuestion, K as designSystem, L as builderSystem, P as agentWithSkills, Q as implementBuildingPrompt, R as clearCriteriaMessage, S as answerReviewQuestions, St as uncoveredMessage, T as collecting, Tt as defaults, U as coveringPrompt, V as coverageMessage, W as criterionLine, Z as idleMessage, _ as REFACTOR, _t as reviewerSystem, a as flagModeOn, bt as slicingPrompt, ct as refactorDroppedRefusal, d as gate, dt as refactorRules, et as naiveApplyFailure, g as QUALITY, h as HANDOFF, i as skills, lt as refactorFixPrompt, m as FEEDBACK, n as summary, nt as normaliseCriteriaScript, ot as qualityUnresolvedMessage, p as healthy, q as designTriagePrompt, r as access, rt as oversizedMessage, s as shipped, st as refactorBuildingPrompt, t as steering, tt as naivePassPrompt, ut as refactorNotePrompt, v as REFACTOR_NOTE, vt as seamByHandMessage, w as coder, wt as unwindFailure, x as SLICES, xt as startGateBlockedMessage, y as REQUIREMENTS, yt as seamSteerMessage, z as clearCriteriaQuestion } from "../chunks/reserved-FWrjy7zo.mjs";
4
- import { a as refusePendingHandOff, o as tail } from "../chunks/tail-B-Es6Hwj.mjs";
5
- import { a as reUnwind, i as isCode$1, r as humanReview, t as buildTail } from "../chunks/review-Dhl4vvDe.mjs";
3
+ import { $ as naivePassPrompt, B as coverageQuestion, C as collecting, Ct as defaults, F as builderSystem, G as designTriagePrompt, H as criterionLine, I as clearCriteriaMessage, L as clearCriteriaQuestion, M as agentWithSkills, N as buildReviewCollectingPrompt, O as planner, Q as naiveApplyFailure, S as coder, T as fixNits, Tt as testFileGlobs, U as designGateAnswerMessage, V as coveringPrompt, W as designSystem, X as implementBuildingPrompt, Y as idleMessage, Z as implementFixPrompt, _ as REQUIREMENTS, _t as slicingPrompt, a as flagModeOn, at as refactorDroppedRefusal, b as answerReviewQuestions, bt as unwindFailedMessage, ct as refactorRules, d as healthy, et as normaliseCriteriaScript, f as FEEDBACK, g as REFACTOR_NOTE, gt as seamSteerMessage, h as REFACTOR, ht as seamByHandMessage, i as skills, it as refactorBuildingPrompt, l as gate, mt as reviewerSystem, n as summary, ot as refactorFixPrompt, p as HANDOFF, r as access, s as shipped, st as refactorNotePrompt, t as steering, tt as oversizedMessage, vt as startGateBlockedMessage, wt as envDefaults, xt as unwindFailure, y as SLICES, yt as uncoveredMessage, z as coverageMessage } from "../chunks/reserved-DF1HD6jL.mjs";
4
+ import { a as refusePendingHandOff, c as joinReports, o as tail } from "../chunks/tail-D89fU_wf.mjs";
5
+ import { i as reUnwind, n as humanReview, r as isCode$1, t as buildTail } from "../chunks/review-Bv40kZu9.mjs";
6
6
  import { posix } from "node:path";
7
7
  //#region src/workflows/shared/fences.ts
8
8
  const markFenced = (text) => {
@@ -1103,17 +1103,20 @@ const buildFeature = async (firstBase) => {
1103
1103
  const handedOut = new Set(listedIds());
1104
1104
  const one = slices.length === 1;
1105
1105
  const built = (i) => sliceIds(sliceCriteria(slices, i))?.length !== 0;
1106
+ const reports = [];
1106
1107
  for (const i of slices.keys()) {
1107
1108
  if (!built(i)) continue;
1108
1109
  const n = one ? "" : `-${i + 1}`;
1109
1110
  await buildSlice(i === 0 ? firstBase : head(), {
1111
+ number: `${i + 1}`,
1110
1112
  tier,
1111
1113
  criteria: sliceCriteria(slices, i),
1112
1114
  refactor: `refactor${n}`,
1113
1115
  feature: `feature${n}`,
1114
1116
  more: () => slices.some((_, j) => j > i && built(j)),
1115
1117
  reviewBase: one ? void 0 : firstBase,
1116
- handedOut
1118
+ handedOut,
1119
+ laps: reports
1117
1120
  });
1118
1121
  }
1119
1122
  };
@@ -1145,38 +1148,39 @@ const buildSlice = async (sliceBase, build) => {
1145
1148
  const base = seam.refactored === true && !changesSince(seam.base).some((c) => isCode$1(c.path) && !carried.includes(c.path)) ? sliceBase : seam.base;
1146
1149
  if (more) {
1147
1150
  const guard = () => requireCriteriaFrozen(REQUIREMENTS);
1148
- await tail(settleQuality, {
1151
+ const report = await tail(async (_, report) => report, {
1149
1152
  green: true,
1150
1153
  lensBase: base,
1151
1154
  guard,
1152
1155
  guardRests: false
1153
1156
  });
1157
+ build.laps.push({
1158
+ slice: build.number,
1159
+ report
1160
+ });
1154
1161
  return;
1155
1162
  }
1156
1163
  const reviewBase = build.reviewBase ?? base;
1157
- await featureFeedback(await reviewedTail(reviewBase, base), base, {
1164
+ const outcome = await reviewedTail(reviewBase, base, {
1165
+ slice: build.number,
1166
+ laps: build.laps
1167
+ });
1168
+ await featureFeedback(outcome, base, {
1158
1169
  closed,
1159
1170
  used
1160
1171
  });
1161
1172
  });
1162
1173
  };
1163
- const settleQuality = async () => {
1164
- let rested = false;
1165
- while ((read(".gtd/QUALITY.md") ?? "").length > 0) {
1166
- rested = true;
1167
- await human("quality-unresolved", {
1168
- message: qualityUnresolvedMessage(),
1169
- label: "Quality findings left unresolved",
1170
- file: QUALITY
1171
- });
1172
- }
1173
- if (rested) await healthy(() => fixCheck());
1174
- };
1175
- /** The triaged quality lap, then the human review since `base`. */
1176
- const reviewedTail = (base, lensBase) => tail((escalations, report) => humanReview(base, escalations, { report }), {
1174
+ /** The quality lap of slice `last.slice`, then the human review since `base`, listing what earlier slices' `laps` left too. */
1175
+ const reviewedTail = (base, lensBase, last = {
1176
+ slice: "",
1177
+ laps: []
1178
+ }) => tail((escalations, report) => humanReview(base, escalations, { report: last.laps.length === 0 ? report : joinReports([...last.laps, {
1179
+ slice: last.slice,
1180
+ report
1181
+ }]) }), {
1177
1182
  green: true,
1178
- lensBase,
1179
- triage: true
1183
+ lensBase
1180
1184
  });
1181
1185
  const featureFeedback = async (first, lensBase, ids) => {
1182
1186
  let outcome = first;
@@ -1,7 +1,7 @@
1
1
  import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
2
2
  import { g as reviewRisks, h as reviewNotes } from "../chunks/steering-D7hWeMgE.mjs";
3
- import { Et as envDefaults, J as finisherSystem, P as agentWithSkills, Tt as defaults, Y as fixReviewNotesPrompt, b as REVIEW, i as skills, l as baseline, n as summary, r as access, s as shipped, t as steering, w as coder } from "../chunks/reserved-FWrjy7zo.mjs";
4
- import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-B-Es6Hwj.mjs";
3
+ import { Ct as defaults, K as finisherSystem, M as agentWithSkills, S as coder, c as baseline, i as skills, n as summary, q as fixReviewNotesPrompt, r as access, s as shipped, t as steering, v as REVIEW, wt as envDefaults } from "../chunks/reserved-DF1HD6jL.mjs";
4
+ import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-D89fU_wf.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,8 +1,18 @@
1
- import { read, refuse, start } from "../flows.mjs";
2
- import { Et as envDefaults, Tt as defaults, d as gate, ht as reviewGateBlockedMessage, i as skills, n as summary, r as access, s as shipped, t as steering, y as REQUIREMENTS } from "../chunks/reserved-FWrjy7zo.mjs";
3
- import { a as refusePendingHandOff } from "../chunks/tail-B-Es6Hwj.mjs";
4
- import { a as reUnwind, n as fixFeedback, t as buildTail } from "../chunks/review-Dhl4vvDe.mjs";
1
+ import { read, refuse, removeScript, run, start } from "../flows.mjs";
2
+ import { Ct as defaults, K as finisherSystem, M as agentWithSkills, S as coder, _ as REQUIREMENTS, dt as reviewFeedbackFixPrompt, ft as reviewGateBlockedMessage, i as skills, l as gate, n as summary, r as access, s as shipped, t as steering, wt as envDefaults } from "../chunks/reserved-DF1HD6jL.mjs";
3
+ import { a as refusePendingHandOff } from "../chunks/tail-D89fU_wf.mjs";
4
+ import { i as reUnwind, t as buildTail } from "../chunks/review-Bv40kZu9.mjs";
5
5
  //#region src/workflows/review/review.ts
6
+ const fixFeedback = async () => {
7
+ await agentWithSkills("feedback.fixing", reviewFeedbackFixPrompt(), {
8
+ label: "Fixing your review feedback",
9
+ file: REQUIREMENTS,
10
+ model: coder(),
11
+ system: finisherSystem(),
12
+ allowEmpty: true
13
+ });
14
+ await run("feedback.closing", removeScript([REQUIREMENTS]), { label: "Closing the feedback" });
15
+ };
6
16
  /**
7
17
  * The feature's review of everything since `reviewBase` — a green gate, the
8
18
  * triaged quality lap, then the human review — with no design phase: a
@@ -1,5 +1,5 @@
1
1
  import { agent, changesSince, glob, head, mark, read, refuse, removeScript, run, scope, vars } from "../flows.mjs";
2
- import { Bt as flipProblems, Et as envDefaults, Ht as requireFlag, Rt as flagMentions, Tt as defaults, d as gate, i as skills, m as FEEDBACK, n as summary, o as flagShipped, r as access, t as steering, w as coder } from "../chunks/reserved-FWrjy7zo.mjs";
2
+ import { Ct as defaults, Ft as flagMentions, Lt as flipProblems, S as coder, f as FEEDBACK, i as skills, l as gate, n as summary, o as flagShipped, r as access, t as steering, wt as envDefaults, zt as requireFlag } from "../chunks/reserved-DF1HD6jL.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.";