@pmelab/gtd 45.1.0 → 46.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 (41) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +18 -29
  3. package/claude/hooks/pr.ts +342 -0
  4. package/claude/hooks/register.tsx +148 -5
  5. package/claude/types/index.d.ts +18 -0
  6. package/dist/chunks/{reserved-ulcSkND6.mjs → reserved-BENPy6IJ.mjs} +4 -29
  7. package/dist/chunks/{review-Da2ndnB1.mjs → review-DcbgUwr7.mjs} +6 -17
  8. package/dist/chunks/{steering-D4LUQ-av.mjs → steering-D7hWeMgE.mjs} +1 -1
  9. package/dist/chunks/{tail-BW030xz_.mjs → tail-CDNMZ-2E.mjs} +1 -1
  10. package/dist/gtd.bundle.mjs +5 -7
  11. package/dist/steering.mjs +1 -1
  12. package/dist/testkit.mjs +6 -8
  13. package/dist/workflow-kit.mjs +1 -1
  14. package/dist/workflows/cleanup.mjs +2 -2
  15. package/dist/workflows/feature.mjs +3 -3
  16. package/dist/workflows/fix.mjs +3 -3
  17. package/dist/workflows/review.mjs +14 -4
  18. package/dist/workflows/rollout.mjs +1 -1
  19. package/dist/workflows.mjs +18 -229
  20. package/package.json +1 -6
  21. package/src/install/ConfigScaffold.ts +1 -2
  22. package/src/install/Install.ts +4 -5
  23. package/src/steering/review.test.ts +6 -0
  24. package/src/steering/review.ts +4 -1
  25. package/src/testkit/steps.ts +5 -0
  26. package/src/workflows/index.ts +1 -2
  27. package/src/workflows/review/review-door.feature +38 -0
  28. package/src/workflows/review/review.ts +15 -3
  29. package/src/workflows/shared/lenses.ts +1 -5
  30. package/src/workflows/shared/options.ts +1 -21
  31. package/src/workflows/shared/review.ts +2 -19
  32. package/src/workflows/shared/skills.test.ts +0 -2
  33. package/src/workflows/shared/skills.ts +0 -3
  34. package/src/workflows/shared/text.ts +2 -5
  35. package/src/workflows/shared/vars.ts +0 -8
  36. package/dist/workflows/tests.mjs +0 -193
  37. package/src/workflows/tests/index.ts +0 -6
  38. package/src/workflows/tests/tests-options.feature +0 -52
  39. package/src/workflows/tests/tests.feature +0 -266
  40. package/src/workflows/tests/tests.test.ts +0 -51
  41. package/src/workflows/tests/tests.ts +0 -270
@@ -1,5 +1,5 @@
1
1
  import { accessFor, agent, answered, changesSince, check, codeThreads, defineWorkflow, displayPath, env, head, human, judge, mark, numeric, quote, read, refuse, scope, skillsFor, start, vars } from "../flows.mjs";
2
- import { d as ANSWER_FIX, f as ANSWER_LEAD, p as ANSWER_WONT_FIX, v as FREE_TEXT_PLACEHOLDER } from "./steering-D4LUQ-av.mjs";
2
+ import { d as ANSWER_FIX, f as ANSWER_LEAD, p as ANSWER_WONT_FIX, v as FREE_TEXT_PLACEHOLDER } from "./steering-D7hWeMgE.mjs";
3
3
  import { escalation as escalation$1, gate as gate$1, healthy as healthy$1, lensScopes, lensesOf, removedAssertions } from "../workflow-kit.mjs";
4
4
  import { c as String$, g as standardSchemaV1, h as optionalWith, l as Struct, n as Boolean$, s as Number$ } from "./Schema-C6fLlQzx.mjs";
5
5
  //#region src/workflows/shared/registry.ts
@@ -226,11 +226,6 @@ const testFileGlobs = [
226
226
  "**/__tests__/**"
227
227
  ];
228
228
  const defaultFlagRegistry = "src/flags/index.ts";
229
- /** The `tests` workflow's own process settings: where it looks for skipped tests, and how a skip reads. */
230
- const testsDefaults = {
231
- testFiles: testFileGlobs.join(", "),
232
- skipPattern: "^\\s*(?:(?:describe|context|suite|it|test|specify)\\.(?:skip|todo)\\b|x(?:describe|context|it|test|specify)\\s*\\(|(?:@\\S+\\s+)*@(?:skip|ignore)(?:\\s|$))"
233
- };
234
229
  /** Process settings. */
235
230
  const defaults = {
236
231
  reviewBase: "",
@@ -563,7 +558,7 @@ const composedReview = (base, report) => {
563
558
  return name;
564
559
  };
565
560
  const chunk = (title, body) => `## ${title}\n\n${body.trim()}`;
566
- const answerBoxes = ([fix, wontFix] = [ANSWER_FIX, ANSWER_WONT_FIX]) => `${ANSWER_LEAD}\n\n- [ ] ${fix}\n- [ ] ${wontFix}\n- [ ] ${FREE_TEXT_PLACEHOLDER}`;
561
+ const answerBoxes = `${ANSWER_LEAD}\n\n- [ ] ${ANSWER_FIX}\n- [ ] ${ANSWER_WONT_FIX}\n- [ ] ${FREE_TEXT_PLACEHOLDER}`;
567
562
  const conflicts = (report.standards?.undecided ?? []).map((c) => chunk(unique(conflictTitle(c)), conflictBody(c)));
568
563
  const added = report.standards?.added ?? [];
569
564
  const notes = report.notes.map((n) => ({
@@ -575,7 +570,7 @@ const composedReview = (base, report) => {
575
570
  ...report.nitFix === void 0 ? [] : [chunk("Fixed from your notes", `Your nits and fix-as-suggested notes were worked on in ${short(report.nitFix)}; the notes you answered are left out — check the diff.`)],
576
571
  ...weakened.length === 0 ? [] : [chunk("Weakened scenarios", `These scenarios lost an assertion the review base had:\n\n${weakened.join("\n")}`)],
577
572
  ...conflicts,
578
- ...notes.map((n) => chunk(n.title, `${n.unresolved === true ? `_The fixer left this unresolved._\n\n${unboxed(n.body)}` : n.unclear === true ? `_A fix turn removed this while renaming another finding — check whether it was fixed._\n\n${unboxed(n.body)}` : unboxed(n.body) || "_No detail given._"}\n\n${answerBoxes(n.answers)}`)),
573
+ ...notes.map((n) => chunk(n.title, `${n.unresolved === true ? `_The fixer left this unresolved._\n\n${unboxed(n.body)}` : n.unclear === true ? `_A fix turn removed this while renaming another finding — check whether it was fixed._\n\n${unboxed(n.body)}` : unboxed(n.body) || "_No detail given._"}\n\n${answerBoxes}`)),
579
574
  ...report.fixed.length === 0 ? [] : [chunk("Fixed automatically", report.fixed.map((f) => `- ${f.title} (${short(f.commit)})`).join("\n"))],
580
575
  ...added.length === 0 ? [] : [chunk("Standards added", `Learned from your answers and kept in \`${STANDARDS}\`:\n\n${added.map((s) => `- ${s}`).join("\n")}`)],
581
576
  ...report.noise.length === 0 ? [] : [chunk("Dropped as noise", report.noise.map((f) => `- ${f.title} (p=${f.p})`).join("\n"))]
@@ -1944,24 +1939,6 @@ const flagShipped = (flow, name) => defineWorkflow(standardSchemaV1(FlagOptions,
1944
1939
  base: void 0
1945
1940
  };
1946
1941
  });
1947
- const TestsOptions = Struct({
1948
- ...ShippedOptions.fields,
1949
- testFiles: setting,
1950
- skipPattern: setting
1951
- });
1952
- const testsShipped = (flow) => defineWorkflow(standardSchemaV1(TestsOptions, {
1953
- onExcessProperty: "error",
1954
- errors: "all"
1955
- }), ({ contextLimit, ...options }) => ({
1956
- flow: limited(flow, contextLimit),
1957
- defaults: over({
1958
- ...defaults,
1959
- ...testsDefaults
1960
- }, options),
1961
- envDefaults: over(envDefaults, options),
1962
- doors: { tests: {} },
1963
- base: void 0
1964
- }));
1965
1942
  //#endregion
1966
1943
  //#region src/workflows/shared/skills.ts
1967
1944
  const skills = (vars) => {
@@ -1977,8 +1954,6 @@ const skills = (vars) => {
1977
1954
  design: ["spec-driven-development", "planning-and-task-breakdown"],
1978
1955
  notes: ["incremental-implementation", "code-simplification"],
1979
1956
  feedback: ["test-driven-development", "incremental-implementation"],
1980
- tests: ["test-audit", "test-driven-development"],
1981
- "tests.health": ["debugging-and-error-recovery"],
1982
1957
  ...build,
1983
1958
  ...Object.fromEntries(Object.entries(build).map(([name, list]) => [`refactor.${name}`, list])),
1984
1959
  refactor: ["ponytail"],
@@ -2011,4 +1986,4 @@ const steering = {
2011
1986
  [REVIEW]: "review"
2012
1987
  };
2013
1988
  //#endregion
2014
- export { implementFixPrompt as $, planner as A, conflictBody as At, composedReview as B, flipProblems as Bt, awaitReview as C, unwindFailedMessage as Ct, fixNits as D, testFileGlobs as Dt, fixCheck as E, envDefaults as Et, buildReviewCollectingPrompt as F, parseStandards as Ft, designGateAnswerMessage as G, coverageQuestion as H, requireFlag as Ht, buildReviewTriageMessage as I, renderStandards as It, finisherSystem as J, designSystem as K, builderSystem as L, standardKey as Lt, reviewQuality as M, conflictTitle as Mt, reviewing as N, isConflictTitle as Nt, fixQuality as O, testsDefaults as Ot, agentWithSkills as P, oneLine as Pt, implementBuildingPrompt as Q, clearCriteriaMessage as R, flagMentions as Rt, answerReviewQuestions as S, uncoveredMessage as St, collecting as T, defaults as Tt, coveringPrompt as U, coverageMessage as V, registryEntry as Vt, criterionLine as W, handOffAwaitReviewMessage as X, fixReviewNotesPrompt as Y, idleMessage as Z, REFACTOR as _, reviewerSystem as _t, flagModeOn as a, qualityTriageMessage as at, REVIEW as b, slicingPrompt as bt, testsShipped as c, refactorDroppedRefusal as ct, gate as d, refactorRules as dt, naiveApplyFailure as et, guarded as f, reviewEditNotesCapture as ft, QUALITY as g, reviewNotesCapture as gt, HANDOFF as h, reviewGateBlockedMessage as ht, skills as i, qualityFindingsFile as it, reviewMissing as j, conflictFor as jt, fixRisks as k, STANDARDS as kt, baseline as l, refactorFixPrompt as lt, FEEDBACK as m, reviewFeedbackFixPrompt as mt, summary as n, normaliseCriteriaScript as nt, flagShipped as o, qualityUnresolvedMessage as ot, healthy as p, reviewEditsCapture as pt, designTriagePrompt as q, access as r, oversizedMessage as rt, shipped as s, refactorBuildingPrompt as st, steering as t, naivePassPrompt as tt, escalation as u, refactorNotePrompt as ut, REFACTOR_NOTE as v, seamByHandMessage as vt, coder as w, unwindFailure as wt, SLICES as x, startGateBlockedMessage as xt, REQUIREMENTS as y, seamSteerMessage as yt, clearCriteriaQuestion as z, flagReferences as zt };
1989
+ export { naiveApplyFailure as $, reviewMissing as A, conflictTitle as At, coverageMessage as B, requireFlag as Bt, coder as C, unwindFailure as Ct, fixQuality as D, STANDARDS as Dt, fixNits as E, testFileGlobs as Et, buildReviewTriageMessage as F, standardKey as Ft, designSystem as G, coveringPrompt as H, builderSystem as I, flagMentions as It, fixReviewNotesPrompt as J, designTriagePrompt as K, clearCriteriaMessage as L, flagReferences as Lt, reviewing as M, oneLine as Mt, agentWithSkills as N, parseStandards as Nt, fixRisks as O, conflictBody as Ot, buildReviewCollectingPrompt as P, renderStandards as Pt, implementFixPrompt as Q, clearCriteriaQuestion as R, flipProblems as Rt, awaitReview as S, unwindFailedMessage as St, fixCheck as T, envDefaults as Tt, criterionLine as U, coverageQuestion as V, designGateAnswerMessage as W, idleMessage as X, handOffAwaitReviewMessage as Y, implementBuildingPrompt as Z, REFACTOR_NOTE as _, seamByHandMessage as _t, flagModeOn as a, qualityUnresolvedMessage as at, SLICES as b, startGateBlockedMessage as bt, baseline as c, refactorFixPrompt as ct, guarded as d, reviewEditNotesCapture as dt, naivePassPrompt as et, healthy as f, reviewEditsCapture as ft, REFACTOR as g, reviewerSystem as gt, QUALITY as h, reviewNotesCapture as ht, skills as i, qualityTriageMessage as it, reviewQuality as j, isConflictTitle as jt, planner as k, conflictFor as kt, escalation as l, refactorNotePrompt as lt, HANDOFF as m, reviewGateBlockedMessage as mt, summary as n, oversizedMessage as nt, flagShipped as o, refactorBuildingPrompt as ot, FEEDBACK as p, reviewFeedbackFixPrompt as pt, finisherSystem as q, access as r, qualityFindingsFile as rt, shipped as s, refactorDroppedRefusal as st, steering as t, normaliseCriteriaScript as tt, gate as u, refactorRules as ut, REQUIREMENTS as v, seamSteerMessage as vt, collecting as w, defaults as wt, answerReviewQuestions as x, uncoveredMessage as xt, REVIEW as y, slicingPrompt as yt, composedReview as z, registryEntry as zt };
@@ -1,7 +1,7 @@
1
- import { answered, changesSince, head, judge, numeric, read, removeScript, requireRevert, restoreScript, run, showScript, vars, writeScript } from "../flows.mjs";
1
+ import { answered, changesSince, head, judge, numeric, read, requireRevert, restoreScript, run, showScript, vars, writeScript } from "../flows.mjs";
2
2
  import { removedAssertions, review } from "../workflow-kit.mjs";
3
- import { At as conflictBody, B as composedReview, C as awaitReview, D as fixNits, E as fixCheck, Ft as parseStandards, I as buildReviewTriageMessage, It as renderStandards, J as finisherSystem, Lt as standardKey, Mt as conflictTitle, Nt as isConflictTitle, P as agentWithSkills, Pt as oneLine, S as answerReviewQuestions, T as collecting, b as REVIEW, f as guarded, ft as reviewEditNotesCapture, g as QUALITY, gt as reviewNotesCapture, j as reviewMissing, jt as conflictFor, k as fixRisks, kt as STANDARDS, mt as reviewFeedbackFixPrompt, p as healthy, pt as reviewEditsCapture, w as coder, y as REQUIREMENTS } from "./reserved-ulcSkND6.mjs";
4
- import { i as isOptionalObject, n as closeReview, o as tail, s as NO_FINDINGS } from "./tail-BW030xz_.mjs";
3
+ import { A as reviewMissing, At as conflictTitle, Dt as STANDARDS, E as fixNits, F as buildReviewTriageMessage, Ft as standardKey, Mt as oneLine, Nt as parseStandards, O as fixRisks, Ot as conflictBody, Pt as renderStandards, S as awaitReview, T as fixCheck, d as guarded, dt as reviewEditNotesCapture, f as healthy, ft as reviewEditsCapture, h as QUALITY, ht as reviewNotesCapture, jt as isConflictTitle, kt as conflictFor, w as collecting, x as answerReviewQuestions, y as REVIEW, z as composedReview } from "./reserved-BENPy6IJ.mjs";
4
+ import { i as isOptionalObject, n as closeReview, o as tail, s as NO_FINDINGS } from "./tail-CDNMZ-2E.mjs";
5
5
  //#region src/workflows/shared/learn.ts
6
6
  const SUMMARY_MAX = 200;
7
7
  const BANNER = /^_(?:The fixer left this unresolved\.|A fix turn removed this while renaming another finding — check whether it was fixed\.|No detail given\.)_\s*/;
@@ -303,7 +303,7 @@ const composing = (base, report, carry, nitFix, answered = /* @__PURE__ */ new S
303
303
  * praise dropped.
304
304
  */
305
305
  const humanReview = (base, escalations = { rounds: 0 }, options = {}) => {
306
- const { guard, guardRests, fixAccess, rules, awaitMessage } = options;
306
+ const { guard, guardRests, fixAccess, rules } = options;
307
307
  const feedback = options.feedback ?? {
308
308
  file: ".gtd/REQUIREMENTS.md",
309
309
  collecting,
@@ -328,7 +328,7 @@ const humanReview = (base, escalations = { rounds: 0 }, options = {}) => {
328
328
  guardRests,
329
329
  rules
330
330
  }),
331
- awaitReview: (b) => awaitReview(b, awaitMessage?.(b)),
331
+ awaitReview,
332
332
  reviewMissing,
333
333
  collecting: feedback.collecting,
334
334
  triage: triage(severities),
@@ -388,17 +388,6 @@ const callForm = (first, second, [third, fourth, ...extra]) => {
388
388
  if (typeof second === "string") return legacyForm(first, second, third, fourth);
389
389
  if (typeof first === "string") return currentForm(first, second, third, fourth);
390
390
  };
391
- /** Build the concerns a review round collected into `.gtd/REQUIREMENTS.md`, then remove it. */
392
- const fixFeedback = async () => {
393
- await agentWithSkills("feedback.fixing", reviewFeedbackFixPrompt(), {
394
- label: "Fixing your review feedback",
395
- file: REQUIREMENTS,
396
- model: coder(),
397
- system: finisherSystem(),
398
- allowEmpty: true
399
- });
400
- await run("feedback.closing", removeScript([REQUIREMENTS]), { label: "Closing the feedback" });
401
- };
402
391
  /**
403
392
  * Undo the human's review-round code edits. A path changed since the human
404
393
  * left it is not overwritten; requireRevert names it instead.
@@ -416,4 +405,4 @@ const reUnwind = async (feedback) => {
416
405
  requireRevert(edited, base);
417
406
  };
418
407
  //#endregion
419
- export { reUnwind as a, isCode as i, fixFeedback as n, humanReview as r, buildTail as t };
408
+ export { reUnwind as i, humanReview as n, isCode as r, buildTail as t };
@@ -15901,7 +15901,7 @@ const reviewDescriptor = {
15901
15901
  openThreads: openThreadsOf
15902
15902
  };
15903
15903
  const pointerLabel = (f) => `${f.path}${f.line === void 0 ? "" : `#${f.line}${f.rangeEnd === void 0 ? "" : `-${f.rangeEnd}`}`}`;
15904
- const chunkNote = (chunk, prior) => chunk.description === (prior?.description ?? "") ? [] : [{
15904
+ const chunkNote = (chunk, prior) => chunk.description === (prior?.description ?? "") || prior === void 0 && chunk.answers !== void 0 ? [] : [{
15905
15905
  line: chunk.headingLine,
15906
15906
  note: {
15907
15907
  kind: "chunk",
@@ -1,6 +1,6 @@
1
1
  import { answered, head, judge, mark, numeric, read, refuse, removeScript, run, scope, sectionBodies, showScript, vars, writeScript } from "../flows.mjs";
2
2
  import { fixFindings, lensEntriesOf, lensOf, qualityLap as qualityLap$1, reviewToHandOff } from "../workflow-kit.mjs";
3
- import { C as awaitReview, E as fixCheck, M as reviewQuality, N as reviewing, O as fixQuality, X as handOffAwaitReviewMessage, at as qualityTriageMessage, b as REVIEW, f as guarded, g as QUALITY, it as qualityFindingsFile, j as reviewMissing, k as fixRisks, p as healthy, u as escalation } from "./reserved-ulcSkND6.mjs";
3
+ import { A as reviewMissing, D as fixQuality, M as reviewing, O as fixRisks, S as awaitReview, T as fixCheck, Y as handOffAwaitReviewMessage, d as guarded, f as healthy, h as QUALITY, it as qualityTriageMessage, j as reviewQuality, l as escalation, rt as qualityFindingsFile, y as REVIEW } from "./reserved-BENPy6IJ.mjs";
4
4
  //#region src/workflows/shared/lenses.ts
5
5
  const NO_FINDINGS = {
6
6
  notes: [],
@@ -21606,11 +21606,10 @@ rather than starting the review; \`gtd-door fix\` on a GREEN suite is a no-op
21606
21606
  straight back to \`idle\` — the exec'd \`gtd-build\` exits immediately on it.
21607
21607
  \`gtd doors\` lists the doors a repository offers (those of the workflows its
21608
21608
  config exports — the bundled \`fix\` and \`review [base]\`, plus the opt-in
21609
- \`rollout <flag>\` (turn a release flag default-on), \`cleanup <flag>\`
21610
- (remove it) and \`tests\` (revive skipped tests), which a config adds by
21611
- exporting \`rollout\` from \`@pmelab/gtd/workflows/rollout\`, \`cleanup\` from
21612
- \`@pmelab/gtd/workflows/cleanup\` and \`tests\` from
21613
- \`@pmelab/gtd/workflows/tests\` — plus any it declares). Refuses with
21609
+ \`rollout <flag>\` (turn a release flag default-on) and \`cleanup <flag>\`
21610
+ (remove it), which a config adds by exporting \`rollout\` from
21611
+ \`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
21612
+ \`@pmelab/gtd/workflows/cleanup\` — plus any it declares). Refuses with
21614
21613
  \`usage: gtd-door <name> [args...]\` on stderr and exit \`2\` when the name is
21615
21614
  missing — nothing was even attempted. Default path: \`~/.local/bin/gtd-door\`.
21616
21615
 
@@ -21723,8 +21722,7 @@ const CONFIG_SCAFFOLD = `// The workflows gtd runs here: gtd's shipped feature,
21723
21722
  // its own doors: \`gtd door review [base]\` and \`gtd door fix\`. Export \`rollout\`
21724
21723
  // from \`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
21725
21724
  // \`@pmelab/gtd/workflows/cleanup\` to add \`gtd door rollout <flag>\` and
21726
- // \`gtd door cleanup <flag>\`, and \`tests\` from \`@pmelab/gtd/workflows/tests\`
21727
- // to add \`gtd door tests\`.
21725
+ // \`gtd door cleanup <flag>\`.
21728
21726
  export {
21729
21727
  feature as default,
21730
21728
  feature,
package/dist/steering.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { C as parseFootnotes, D as headingSectionBodies, E as getParseCount, O as headingSections, S as openThreadFindings, T as parseThreadsWithFindings, _ as unansweredNotes, a as unansweredQuestions, b as FOOTNOTE_ACTION_TITLE, c as stripCodeThreads, d as ANSWER_FIX, f as ANSWER_LEAD, g as reviewRisks, h as reviewNotes, i as steeringFormatOrFreeForm, k as formatFinding, l as freeFormFormat, m as reviewDecisions, n as openThreads, o as viewOf, p as ANSWER_WONT_FIX, r as steeringFormatFor, s as parseCodeThreads, t as BUILT_IN_MODE_NAMES, u as applySteeringEdits, v as FREE_TEXT_PLACEHOLDER, w as parseThreads, x as THREAD_REPLY_ACTION_TITLE, y as isAnswered } from "./chunks/steering-D4LUQ-av.mjs";
1
+ import { C as parseFootnotes, D as headingSectionBodies, E as getParseCount, O as headingSections, S as openThreadFindings, T as parseThreadsWithFindings, _ as unansweredNotes, a as unansweredQuestions, b as FOOTNOTE_ACTION_TITLE, c as stripCodeThreads, d as ANSWER_FIX, f as ANSWER_LEAD, g as reviewRisks, h as reviewNotes, i as steeringFormatOrFreeForm, k as formatFinding, l as freeFormFormat, m as reviewDecisions, n as openThreads, o as viewOf, p as ANSWER_WONT_FIX, r as steeringFormatFor, s as parseCodeThreads, t as BUILT_IN_MODE_NAMES, u as applySteeringEdits, v as FREE_TEXT_PLACEHOLDER, w as parseThreads, x as THREAD_REPLY_ACTION_TITLE, y as isAnswered } from "./chunks/steering-D7hWeMgE.mjs";
2
2
  export { ANSWER_FIX, ANSWER_LEAD, ANSWER_WONT_FIX, BUILT_IN_MODE_NAMES, FOOTNOTE_ACTION_TITLE, FREE_TEXT_PLACEHOLDER, THREAD_REPLY_ACTION_TITLE, applySteeringEdits, formatFinding, freeFormFormat, getParseCount, headingSectionBodies, headingSections, isAnswered, openThreadFindings, openThreads, parseCodeThreads, parseFootnotes, parseThreads, parseThreadsWithFindings, reviewDecisions, reviewNotes, reviewRisks, steeringFormatFor, steeringFormatOrFreeForm, stripCodeThreads, unansweredNotes, unansweredQuestions, viewOf };
package/dist/testkit.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { answered, applyScript, checkScript, configProblems, configure, installContext, isFactoryWorkflow, moveScript, numeric, protocolMismatch, removeScript, restoreScript, revertScript, showScript, t as flows_exports, writeScript } from "./flows.mjs";
2
2
  import { A as beatKindOf, B as ACCESS_REFUSAL, C as renderLandPlain, D as renderBeatJson, E as beatDocument, O as statusOf, S as renderLandJson, T as renderBeatPlain, U as renderFormat, _ as selectPath, a as contextLimitFault, g as resolveSession, h as globMatches, j as demandOf, l as parseContextWindow, m as slicesDocument, o as contextShapeFault, p as renderSlicesJson, v as judgeJson, x as noopText, y as landFields } from "./chunks/wire-BJuZWR3C.mjs";
3
- import { D as headingSectionBodies, O as headingSections, T as parseThreadsWithFindings, a as unansweredQuestions, k as formatFinding, n as openThreads, r as steeringFormatFor, s as parseCodeThreads, t as BUILT_IN_MODE_NAMES } from "./chunks/steering-D4LUQ-av.mjs";
3
+ import { D as headingSectionBodies, O as headingSections, T as parseThreadsWithFindings, a as unansweredQuestions, k as formatFinding, n as openThreads, r as steeringFormatFor, s as parseCodeThreads, t as BUILT_IN_MODE_NAMES } from "./chunks/steering-D7hWeMgE.mjs";
4
4
  import { $ as logWarning, $i as BaseProto, $n as map$5, $r as make$19, $t as provide$1, A as catchIf, Ai as add$1, An as scopeMake, Ar as flatMap$3, At as suspend$5, B as flatMap$4, Bi as getOrElse, Bn as get$3, Br as sync$1, Bt as unsafeMakeLatch, C as all$1, Ci as toArray, Cn as isInterrupted, Cr as exitFail, Ct as sandbox, D as async, Di as GenericTag, Dn as squash, Dr as exitZipRight, Dt as scopedWith$1, E as asVoid$1, Ei as unsafeHead, En as reduceWithContext, Er as exitVoid, Et as scoped$4, F as ensuring$2, Fi as fromIterable, Fn as join$3, Fr as map$3, Ft as tryMap, G as forkIn, Gi as match$4, Gn as TypeId$10, Gr as whenEffect, Gt as zipLeft, H as fnUntraced, Hi as isNone, Hn as modify$1, Hr as uninterruptible, Ht as when, I as exit, Ii as splitAt, In as sequential, Ir as onInterrupt, It as tryPromise, J as ignore, Ji as isLeft, Jn as all, Jr as DeferredTypeId$1, Jt as spaced$1, K as forkScoped, Ki as none, Kn as Class, Kr as withFiberRuntime, Kt as zipRight$3, L as fail$5, Li as filter$1, Ln as bind, Lr as scopeClose, Lt as try_, M as die$2, Mi as getOption, Mn as _await$2, Mr as interruptAsFiber, Mt as tap, N as dieMessage, Ni as omit, Nn as inheritAll$1, Nr as interruptFiber, Nt as tapErrorCause, O as catchAll$1, Oi as Reference, On as ensuring$3, Or as fiberId, Ot as serviceOption, P as either, Pi as empty$5, Pn as interruptAllAs$1, Pr as interruptible$1, Pt as timeout, Q as isEffect, Qi as pipeArguments, Qn as isFailure, Qr as ids, Qt as mergeAll$2, R as failCause$4, Ri as flatMap$5, Rn as bindTo, Rr as succeed$4, Rt as uninterruptible$1, S as addFinalizer$1, Si as takeRight, Sn as isDieType, Sr as exitAs, St as runtime, T as as, Ti as unsafeGet, Tn as map$6, Tr as exitSucceed, Tt as scopeWith, U as forEach$2, Ui as isSome, Un as set$1, Ur as uninterruptibleMask$1, Ut as withFiberRuntime$1, V as flatten$4, Vi as getOrUndefined, Vn as make$16, Vr as tap$1, Vt as unsafeMakeSemaphore$1, W as forkDaemon, Wi as map$8, Wn as update$1, Wr as void_$2, Wt as zip$1, X as interruptible, Xi as match$2, Xn as fail$4, Xr as combine, Xt as tagged, Y as interrupt$4, Yi as left, Yn as die, Yr as empty$6, Yt as TaggedError$1, Z as intoDeferred, Zi as right, Zn as failCause$3, Zr as combineAll, Zt as fromEffect$5, _ as decodeSync, _i as of, _n as fail$3, _r as deferredIsDone, _t as raceWith, a as Literal, aa as constFalse, ai as size$2, an as updateContext$1, ar as zipRight$2, at as matchCause, b as acquireRelease, bi as reverse, bn as interrupt$3, br as deferredUnsafeDone, bt as runPromise, c as String$, ca as constVoid, ci as append$1, cn as Scope, cr as asyncInterrupt, ct as negate, d as Union, da as pipe, di as empty$4, dn as close, dr as deferredAwait, dt as orElse, ea as NodeInspectSymbol, ei as none$1, en as provideMerge$1, er as mapBoth, et as makeSemaphore, f as between, fi as filter, fn as extend, fr as deferredComplete, ft as orElseSucceed, gi as map$7, gn as die$1, gr as deferredInterruptWith, gt as race, hi as isEmpty$2, hn as NoSuchElementException, hr as deferredInterrupt, ht as provideService, i as Defect, ia as hasProperty, ii as has, in as unsafeRunPromiseExit, ir as zip$2, it as match$5, j as catchTag, ji as get$5, jn as scopeTag, jr as interrupt$2, jt as sync$2, k as catchAllCause, ki as Tag, kn as forEachConcurrentDiscard, kr as fiberRefLocally, kt as succeed$6, l as Struct, la as dual, li as appendAll, ln as addFinalizer, lr as catchAll, lt as onError, m as optional$1, mi as isChunk, mn as make$18, mr as deferredFailCause, mt as provide$2, n as Boolean$, na as toJSON, ni as make$17, nn as succeed$3, nr as succeed$5, nt as mapBoth$1, o as Never, oa as constTrue, oi as decode, on as forkIn$1, or as as$1, ot as matchCauseEffect, p as decodeUnknown, pi as fromIterable$1, pn as fork, pr as deferredFail, pt as promise, q as gen, qi as some, qn as spanTag, qr as zipRight$1, qt as zipWith, r as Cause, ra as equals, ri as set$2, rn as unsafeFork, rr as void_$3, rt as mapError, s as Number$, sa as constUndefined, si as isFinite, sn as unsafeMakeSemaphore, sr as asVoid, st as matchEffect, t as Array$, ta as format, ti as get$4, tn as scoped$3, tr as match$3, tt as map$4, u as TaggedError, ua as identity, ui as drop, un as addFinalizerExit, ur as currentContext$1, ut as orDie, v as encodeSync, vi as prepend, vn as failureOrCause, vr as deferredMake, vt as repeat, w as annotateLogs, wi as unsafeFromArray, wn as isInterruptedOnly, wr as exitFailCause, wt as scope, x as acquireUseRelease$2, xi as take$2, xn as interruptors, xr as deferredUnsafeMake, xt as runPromiseExit$1, y as _void, yi as reduce, yn as flipCauseOption, yr as deferredSucceed, yt as retry, z as fiberIdWith, zi as fromNullable, zn as sleep, zr as suspend$4, zt as uninterruptibleMask } from "./chunks/Schema-C6fLlQzx.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import * as Crypto from "node:crypto";
@@ -6643,11 +6643,10 @@ rather than starting the review; \`gtd-door fix\` on a GREEN suite is a no-op
6643
6643
  straight back to \`idle\` — the exec'd \`gtd-build\` exits immediately on it.
6644
6644
  \`gtd doors\` lists the doors a repository offers (those of the workflows its
6645
6645
  config exports — the bundled \`fix\` and \`review [base]\`, plus the opt-in
6646
- \`rollout <flag>\` (turn a release flag default-on), \`cleanup <flag>\`
6647
- (remove it) and \`tests\` (revive skipped tests), which a config adds by
6648
- exporting \`rollout\` from \`@pmelab/gtd/workflows/rollout\`, \`cleanup\` from
6649
- \`@pmelab/gtd/workflows/cleanup\` and \`tests\` from
6650
- \`@pmelab/gtd/workflows/tests\` — plus any it declares). Refuses with
6646
+ \`rollout <flag>\` (turn a release flag default-on) and \`cleanup <flag>\`
6647
+ (remove it), which a config adds by exporting \`rollout\` from
6648
+ \`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
6649
+ \`@pmelab/gtd/workflows/cleanup\` — plus any it declares). Refuses with
6651
6650
  \`usage: gtd-door <name> [args...]\` on stderr and exit \`2\` when the name is
6652
6651
  missing — nothing was even attempted. Default path: \`~/.local/bin/gtd-door\`.
6653
6652
 
@@ -6760,8 +6759,7 @@ const CONFIG_SCAFFOLD = `// The workflows gtd runs here: gtd's shipped feature,
6760
6759
  // its own doors: \`gtd door review [base]\` and \`gtd door fix\`. Export \`rollout\`
6761
6760
  // from \`@pmelab/gtd/workflows/rollout\` and \`cleanup\` from
6762
6761
  // \`@pmelab/gtd/workflows/cleanup\` to add \`gtd door rollout <flag>\` and
6763
- // \`gtd door cleanup <flag>\`, and \`tests\` from \`@pmelab/gtd/workflows/tests\`
6764
- // to add \`gtd door tests\`.
6762
+ // \`gtd door cleanup <flag>\`.
6765
6763
  export {
6766
6764
  feature as default,
6767
6765
  feature,
@@ -1,5 +1,5 @@
1
1
  import { changes, changesSince, hasThreadFor, head, mark, read, refuse, requireReplies, requireThreadsClosed, scope } from "./flows.mjs";
2
- import { _ as unansweredNotes, c as stripCodeThreads, g as reviewRisks, h as reviewNotes, m as reviewDecisions, w as parseThreads } from "./chunks/steering-D4LUQ-av.mjs";
2
+ import { _ as unansweredNotes, c as stripCodeThreads, g as reviewRisks, h as reviewNotes, m as reviewDecisions, w as parseThreads } from "./chunks/steering-D7hWeMgE.mjs";
3
3
  //#region src/workflow-kit/health.ts
4
4
  /** Hand a red suite that repeated attempts could not fix to a person, until `limit` rounds are spent. */
5
5
  const escalation = async (count, steps) => {
@@ -1,6 +1,6 @@
1
1
  import { agent, changes, glob, read, refuse, scope, start, vars } from "../flows.mjs";
2
- import { Et as envDefaults, Ht as requireFlag, Tt as defaults, Vt as registryEntry, i as skills, n as summary, o as flagShipped, r as access, t as steering, w as coder, zt as flagReferences } from "../chunks/reserved-ulcSkND6.mjs";
3
- import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-BW030xz_.mjs";
2
+ import { Bt as requireFlag, C as coder, Lt as flagReferences, Tt as envDefaults, i as skills, n as summary, o as flagShipped, r as access, t as steering, wt as defaults, zt as registryEntry } from "../chunks/reserved-BENPy6IJ.mjs";
3
+ import { a as refusePendingHandOff, r as handOffTail } from "../chunks/tail-CDNMZ-2E.mjs";
4
4
  //#region src/workflows/cleanup/cleanup.ts
5
5
  const removingPrompt = (name, registry) => `Clean up the release flag "${name}", which is default-on: delete its entry in ${registry}, and remove every \`GTD_FLAG_${name.toUpperCase()}\` check from the shipped sources. Keep the flag-on path; delete code only the off path reached, including tests that pin the off path.`;
6
6
  const cleanupFlow = async () => {
@@ -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-ulcSkND6.mjs";
4
- import { a as refusePendingHandOff, o as tail } from "../chunks/tail-BW030xz_.mjs";
5
- import { a as reUnwind, i as isCode$1, r as humanReview, t as buildTail } from "../chunks/review-Da2ndnB1.mjs";
3
+ import { $ as naiveApplyFailure, B as coverageMessage, C as coder, Ct as unwindFailure, E as fixNits, Et as testFileGlobs, G as designSystem, H as coveringPrompt, I as builderSystem, K as designTriagePrompt, L as clearCriteriaMessage, N as agentWithSkills, P as buildReviewCollectingPrompt, Q as implementFixPrompt, R as clearCriteriaQuestion, St as unwindFailedMessage, T as fixCheck, Tt as envDefaults, U as criterionLine, V as coverageQuestion, W as designGateAnswerMessage, X as idleMessage, Z as implementBuildingPrompt, _ as REFACTOR_NOTE, _t as seamByHandMessage, a as flagModeOn, at as qualityUnresolvedMessage, b as SLICES, bt as startGateBlockedMessage, ct as refactorFixPrompt, et as naivePassPrompt, f as healthy, g as REFACTOR, gt as reviewerSystem, h as QUALITY, i as skills, k as planner, lt as refactorNotePrompt, m as HANDOFF, n as summary, nt as oversizedMessage, ot as refactorBuildingPrompt, p as FEEDBACK, r as access, s as shipped, st as refactorDroppedRefusal, t as steering, tt as normaliseCriteriaScript, u as gate, ut as refactorRules, v as REQUIREMENTS, vt as seamSteerMessage, w as collecting, wt as defaults, x as answerReviewQuestions, xt as uncoveredMessage, yt as slicingPrompt } from "../chunks/reserved-BENPy6IJ.mjs";
4
+ import { a as refusePendingHandOff, o as tail } from "../chunks/tail-CDNMZ-2E.mjs";
5
+ import { i as reUnwind, n as humanReview, r as isCode$1, t as buildTail } from "../chunks/review-DcbgUwr7.mjs";
6
6
  import { posix } from "node:path";
7
7
  //#region src/workflows/shared/fences.ts
8
8
  const markFenced = (text) => {
@@ -1,7 +1,7 @@
1
1
  import { read, refuse, removeScript, run, scope, start } from "../flows.mjs";
2
- import { g as reviewRisks, h as reviewNotes } from "../chunks/steering-D4LUQ-av.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-ulcSkND6.mjs";
4
- import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-BW030xz_.mjs";
2
+ import { g as reviewRisks, h as reviewNotes } from "../chunks/steering-D7hWeMgE.mjs";
3
+ import { C as coder, J as fixReviewNotesPrompt, N as agentWithSkills, Tt as envDefaults, c as baseline, i as skills, n as summary, q as finisherSystem, r as access, s as shipped, t as steering, wt as defaults, y as REVIEW } from "../chunks/reserved-BENPy6IJ.mjs";
4
+ import { r as handOffTail, t as REVIEW_ORIG } from "../chunks/tail-CDNMZ-2E.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-ulcSkND6.mjs";
3
- import { a as refusePendingHandOff } from "../chunks/tail-BW030xz_.mjs";
4
- import { a as reUnwind, n as fixFeedback, t as buildTail } from "../chunks/review-Da2ndnB1.mjs";
1
+ import { read, refuse, removeScript, run, start } from "../flows.mjs";
2
+ import { C as coder, N as agentWithSkills, Tt as envDefaults, i as skills, mt as reviewGateBlockedMessage, n as summary, pt as reviewFeedbackFixPrompt, q as finisherSystem, r as access, s as shipped, t as steering, u as gate, v as REQUIREMENTS, wt as defaults } from "../chunks/reserved-BENPy6IJ.mjs";
3
+ import { a as refusePendingHandOff } from "../chunks/tail-CDNMZ-2E.mjs";
4
+ import { i as reUnwind, t as buildTail } from "../chunks/review-DcbgUwr7.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-ulcSkND6.mjs";
2
+ import { Bt as requireFlag, C as coder, It as flagMentions, Rt as flipProblems, Tt as envDefaults, i as skills, n as summary, o as flagShipped, p as FEEDBACK, r as access, t as steering, u as gate, wt as defaults } from "../chunks/reserved-BENPy6IJ.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.";