@pmelab/gtd 58.2.0 → 59.0.1

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 (150) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +120 -395
  3. package/dist/chunks/{Schema-B3o6eRNU.mjs → testkit-07Z_ENch.mjs} +13503 -3460
  4. package/dist/chunks/{wire-C12dahrH.mjs → wire-BTUhRGXj.mjs} +1 -1
  5. package/dist/flows.mjs +1 -1
  6. package/dist/gtd.bundle.mjs +484 -497
  7. package/dist/testkit/gherkin.mjs +145 -65
  8. package/dist/testkit.mjs +1 -1
  9. package/dist/wire.mjs +1 -1
  10. package/package.json +3 -42
  11. package/skills/authoring/SKILL.md +34 -27
  12. package/src/cli/Cli.test.ts +148 -71
  13. package/src/cli/Cli.ts +384 -463
  14. package/src/cli/Help.test.ts +47 -0
  15. package/src/cli/Help.ts +70 -0
  16. package/src/cli/Program.test.ts +127 -33
  17. package/src/cli/Program.ts +70 -25
  18. package/src/edge/Edge.ts +4 -4
  19. package/src/emit/Emit.test.ts +1 -1
  20. package/src/emit/Emit.ts +1 -1
  21. package/src/flags/index.test.ts +0 -13
  22. package/src/flags/index.ts +1 -3
  23. package/src/flows/factory.ts +3 -1
  24. package/src/gherkin/index.ts +135 -71
  25. package/src/gherkin/messages.test.ts +90 -0
  26. package/src/gherkin/messages.ts +84 -0
  27. package/src/install/Install.test.ts +14 -11
  28. package/src/install/Install.ts +38 -15
  29. package/src/install/index.ts +1 -2
  30. package/src/replay/Replay.test.ts +1 -1
  31. package/src/replay/index.ts +1 -1
  32. package/src/step/planStart.ts +6 -1
  33. package/src/testkit/TestRepo.test.ts +47 -2
  34. package/src/testkit/TestRepo.ts +51 -6
  35. package/src/twins/EmittedScriptRecognizer.ts +5 -8
  36. package/src/twins/FlowScripts.ts +1 -1
  37. package/src/wire/Land.ts +1 -1
  38. package/src/workflow/index.ts +1 -0
  39. package/src/workflow/load.test.ts +138 -113
  40. package/src/workflow/load.ts +7 -7
  41. package/src/workflow/skills.test.ts +5 -5
  42. package/src/workflow/skills.ts +1 -1
  43. package/src/workflow/vars.test.ts +30 -3
  44. package/src/workflow/vars.ts +34 -2
  45. package/src/workflow-kit/index.ts +1 -1
  46. package/dist/chunks/reserved-lMYCaapY.mjs +0 -1990
  47. package/dist/chunks/review-Bfaror38.mjs +0 -427
  48. package/dist/chunks/tail-Bd7L940p.mjs +0 -355
  49. package/dist/chunks/testkit-JDtpNKyi.mjs +0 -10410
  50. package/dist/workflows/cleanup.mjs +0 -36
  51. package/dist/workflows/feature.mjs +0 -1018
  52. package/dist/workflows/fix.mjs +0 -41
  53. package/dist/workflows/review.mjs +0 -45
  54. package/dist/workflows/rollout.mjs +0 -48
  55. package/dist/workflows.mjs +0 -40651
  56. package/src/install/ConfigScaffold.ts +0 -22
  57. package/src/workflows/cleanup/cleanup-path.feature +0 -94
  58. package/src/workflows/cleanup/cleanup.feature +0 -315
  59. package/src/workflows/cleanup/cleanup.test.ts +0 -276
  60. package/src/workflows/cleanup/cleanup.ts +0 -52
  61. package/src/workflows/cleanup/index.ts +0 -6
  62. package/src/workflows/feature/acceptance-criteria-tier.feature +0 -25
  63. package/src/workflows/feature/acceptance-criteria.feature +0 -389
  64. package/src/workflows/feature/criteria-coverage.feature +0 -102
  65. package/src/workflows/feature/criteria.test.ts +0 -147
  66. package/src/workflows/feature/criteria.ts +0 -267
  67. package/src/workflows/feature/fast-path.feature +0 -93
  68. package/src/workflows/feature/feature.test.ts +0 -338
  69. package/src/workflows/feature/feature.ts +0 -156
  70. package/src/workflows/feature/green.ts +0 -19
  71. package/src/workflows/feature/index.ts +0 -18
  72. package/src/workflows/feature/lens-models.feature +0 -69
  73. package/src/workflows/feature/lens-review.feature +0 -566
  74. package/src/workflows/feature/naive-acceptance.feature +0 -147
  75. package/src/workflows/feature/naive-test.feature +0 -263
  76. package/src/workflows/feature/one-step-land.feature +0 -93
  77. package/src/workflows/feature/planning.ts +0 -41
  78. package/src/workflows/feature/refactor-absorbs.feature +0 -131
  79. package/src/workflows/feature/refactor-first.feature +0 -158
  80. package/src/workflows/feature/refactor-lens-models.feature +0 -79
  81. package/src/workflows/feature/refactor-rebuild.feature +0 -273
  82. package/src/workflows/feature/refactor-review.feature +0 -1528
  83. package/src/workflows/feature/refactor.test.ts +0 -1220
  84. package/src/workflows/feature/refactor.ts +0 -368
  85. package/src/workflows/feature/release-flag.feature +0 -167
  86. package/src/workflows/feature/release-flag.test.ts +0 -49
  87. package/src/workflows/feature/release-flag.ts +0 -46
  88. package/src/workflows/feature/review-gate.feature +0 -241
  89. package/src/workflows/feature/reviewer-walkthrough.feature +0 -142
  90. package/src/workflows/feature/risk-tier.feature +0 -351
  91. package/src/workflows/feature/seam-rejection.feature +0 -146
  92. package/src/workflows/feature/seam.feature +0 -297
  93. package/src/workflows/feature/seam.test.ts +0 -527
  94. package/src/workflows/feature/seam.ts +0 -426
  95. package/src/workflows/feature/standards.feature +0 -354
  96. package/src/workflows/feature/steps.test.ts +0 -65
  97. package/src/workflows/feature/steps.ts +0 -45
  98. package/src/workflows/feature/tier-pin.feature +0 -66
  99. package/src/workflows/feature/tier.test.ts +0 -166
  100. package/src/workflows/feature/tier.ts +0 -56
  101. package/src/workflows/fix/fix-lens-origin.feature +0 -114
  102. package/src/workflows/fix/fix-quality.feature +0 -212
  103. package/src/workflows/fix/fix.feature +0 -79
  104. package/src/workflows/fix/fix.test.ts +0 -74
  105. package/src/workflows/fix/fix.ts +0 -52
  106. package/src/workflows/fix/index.ts +0 -6
  107. package/src/workflows/index.ts +0 -47
  108. package/src/workflows/review/index.ts +0 -6
  109. package/src/workflows/review/review-door.feature +0 -199
  110. package/src/workflows/review/review.test.ts +0 -27
  111. package/src/workflows/review/review.ts +0 -60
  112. package/src/workflows/rollout/index.ts +0 -6
  113. package/src/workflows/rollout/rollout.feature +0 -510
  114. package/src/workflows/rollout/rollout.test.ts +0 -263
  115. package/src/workflows/rollout/rollout.ts +0 -82
  116. package/src/workflows/shared/__fixtures__/feature-collecting-prompt.txt +0 -98
  117. package/src/workflows/shared/access.test.ts +0 -62
  118. package/src/workflows/shared/access.ts +0 -24
  119. package/src/workflows/shared/config.fixture.ts +0 -12
  120. package/src/workflows/shared/fences.ts +0 -24
  121. package/src/workflows/shared/health.test.ts +0 -148
  122. package/src/workflows/shared/health.ts +0 -191
  123. package/src/workflows/shared/learn.test.ts +0 -140
  124. package/src/workflows/shared/learn.ts +0 -201
  125. package/src/workflows/shared/lenses.test.ts +0 -39
  126. package/src/workflows/shared/lenses.ts +0 -294
  127. package/src/workflows/shared/options.test.ts +0 -157
  128. package/src/workflows/shared/options.ts +0 -92
  129. package/src/workflows/shared/progress.feature +0 -124
  130. package/src/workflows/shared/prose.ts +0 -263
  131. package/src/workflows/shared/recheck.feature +0 -60
  132. package/src/workflows/shared/registry.test.ts +0 -345
  133. package/src/workflows/shared/registry.ts +0 -183
  134. package/src/workflows/shared/reserved.ts +0 -11
  135. package/src/workflows/shared/review.test.ts +0 -1062
  136. package/src/workflows/shared/review.ts +0 -446
  137. package/src/workflows/shared/skills.test.ts +0 -121
  138. package/src/workflows/shared/skills.ts +0 -49
  139. package/src/workflows/shared/standards.test.ts +0 -90
  140. package/src/workflows/shared/standards.ts +0 -156
  141. package/src/workflows/shared/steps.test.ts +0 -219
  142. package/src/workflows/shared/steps.ts +0 -201
  143. package/src/workflows/shared/tail.test.ts +0 -454
  144. package/src/workflows/shared/tail.ts +0 -264
  145. package/src/workflows/shared/text.fixture.ts +0 -128
  146. package/src/workflows/shared/text.test.ts +0 -1430
  147. package/src/workflows/shared/text.ts +0 -1700
  148. package/src/workflows/shared/threads.test.ts +0 -129
  149. package/src/workflows/shared/vars.ts +0 -47
  150. package/src/workflows/shared/workflows.steps.ts +0 -54
@@ -1,129 +0,0 @@
1
- import { afterEach, describe, expect, it } from "vitest"
2
- import {
3
- hasThreadFor,
4
- installContext,
5
- requireReplies,
6
- requireThreadsClosed,
7
- type CodeThreadInfo,
8
- type ThreadInfo,
9
- } from "../../flows/index.js"
10
-
11
- const withThreads = (
12
- list: readonly ThreadInfo[],
13
- run: () => void,
14
- code: readonly CodeThreadInfo[] = [],
15
- ): void => {
16
- installContext({
17
- refuse: (message: string): never => {
18
- throw new Error(message)
19
- },
20
- read: () => "doc",
21
- threads: () => list,
22
- codeThreads: () => code,
23
- } as never)
24
- run()
25
- }
26
-
27
- afterEach(() => installContext(undefined))
28
-
29
- const open: ThreadInfo = { name: "a", line: 3, waitingOn: "human", faults: [] }
30
- const asked: ThreadInfo = { name: "b", line: 9, waitingOn: "agent", faults: [] }
31
- const faulty: ThreadInfo = {
32
- ...asked,
33
- name: "c",
34
- line: 14,
35
- faults: ['Footnote thread "[^c]": two consecutive "H:" entries — entries must alternate'],
36
- }
37
-
38
- describe("requireThreadsClosed", () => {
39
- it("refuses while any thread waits on the human, naming each", () => {
40
- withThreads([open, asked, { name: "c", line: 12, waitingOn: "human", faults: [] }], () => {
41
- expect(() => requireThreadsClosed("f.md")).toThrow(/f\.md:3: \[\^a\][\s\S]*f\.md:12: \[\^c\]/)
42
- expect(() => requireThreadsClosed("f.md")).toThrow(/reply with a conclusion, or delete/)
43
- })
44
- })
45
-
46
- it("passes with no open thread", () => {
47
- withThreads([asked], () => expect(() => requireThreadsClosed("f.md")).not.toThrow())
48
- })
49
-
50
- it("refuses a thread with a syntax fault even when it waits on the agent", () => {
51
- withThreads([faulty], () => {
52
- expect(() => requireThreadsClosed("f.md")).toThrow(/f\.md:14: \[\^c\][\s\S]*two consecutive/)
53
- })
54
- })
55
- })
56
-
57
- describe("requireReplies", () => {
58
- it("refuses while any thread waits on the agent, naming each", () => {
59
- withThreads([open, asked], () => {
60
- expect(() => requireReplies("f.md")).toThrow(/f\.md:9: \[\^b\]/)
61
- })
62
- })
63
-
64
- it("passes when every thread has the agent's reply", () => {
65
- withThreads([open], () => expect(() => requireReplies("f.md")).not.toThrow())
66
- })
67
-
68
- it("refuses a thread with a syntax fault even when it waits on the human", () => {
69
- withThreads([{ ...faulty, waitingOn: "human" }], () => {
70
- expect(() => requireReplies("f.md")).toThrow(/f\.md:14: \[\^c\][\s\S]*two consecutive/)
71
- })
72
- })
73
- })
74
-
75
- const codeOpen: CodeThreadInfo = {
76
- path: "src/a.ts",
77
- line: 7,
78
- waitingOn: "human",
79
- first: "why?",
80
- faults: [],
81
- }
82
- const codeAsked: CodeThreadInfo = { ...codeOpen, line: 20, waitingOn: "agent", first: "how?" }
83
- const codeFaulty: CodeThreadInfo = {
84
- ...codeOpen,
85
- line: 30,
86
- first: "x",
87
- faults: ['Code thread at src/a.ts:30: two consecutive "H:" entries'],
88
- }
89
-
90
- describe("code threads at the gates", () => {
91
- it("an open code thread refuses landing, naming path:line and first entry", () => {
92
- withThreads(
93
- [],
94
- () => expect(() => requireThreadsClosed("f.md")).toThrow(/src\/a\.ts:7: why\?/),
95
- [codeOpen, codeAsked],
96
- )
97
- })
98
-
99
- it("a code thread waiting on the agent does not refuse landing", () => {
100
- withThreads([], () => expect(() => requireThreadsClosed("f.md")).not.toThrow(), [codeAsked])
101
- })
102
-
103
- it("a code thread waiting on the agent refuses an agent turn, naming path:line", () => {
104
- withThreads(
105
- [],
106
- () => {
107
- expect(() => requireReplies("f.md")).toThrow(/src\/a\.ts:20: how\?/)
108
- expect(() => requireReplies("f.md")).toThrow(/one "A:" comment line/)
109
- },
110
- [codeOpen, codeAsked],
111
- )
112
- })
113
-
114
- it("a fault refuses both ways", () => {
115
- withThreads([], () => expect(() => requireThreadsClosed("f.md")).toThrow(/src\/a\.ts:30/), [
116
- codeFaulty,
117
- ])
118
- withThreads([], () => expect(() => requireReplies("f.md")).toThrow(/two consecutive/), [
119
- codeFaulty,
120
- ])
121
- })
122
-
123
- it("hasThreadFor combines footnote and code threads", () => {
124
- withThreads([], () => expect(hasThreadFor("agent", "f.md")).toBe(true), [codeAsked])
125
- withThreads([asked], () => expect(hasThreadFor("agent", "f.md")).toBe(true))
126
- withThreads([open], () => expect(hasThreadFor("agent", "f.md")).toBe(false), [codeOpen])
127
- withThreads([open], () => expect(hasThreadFor("human")).toBe(false))
128
- })
129
- })
@@ -1,47 +0,0 @@
1
- // The bundled workflow's settings, in two kinds. A process setting changes
2
- // which step comes next, so it is pinned for the whole process at its start;
3
- // an environment setting only changes how a step runs on this machine, so it
4
- // is read live on every invocation. A factory option, `--var` (process
5
- // settings only) and `GTD_<NAME>` override either.
6
-
7
- /** The refactor guard's fixed list, and `seamAllow`'s default minus `.gtd/**`. */
8
- export const testFileGlobs: readonly string[] = [
9
- "**/*.test.*",
10
- "**/*.spec.*",
11
- "**/*.feature",
12
- "**/tests/**",
13
- "**/test/**",
14
- "**/__tests__/**",
15
- ]
16
-
17
- export const defaultFlagRegistry = "src/flags/index.ts"
18
-
19
- /** Process settings. */
20
- export const defaults: Readonly<Record<string, string>> = {
21
- reviewBase: "",
22
- judgeBudgetBytes: "32768",
23
- judgeIdenticalMinP: "0.7",
24
- reviewNoteActionable: "0.7",
25
- reviewSeverityMinP: "0.7",
26
- qualityTriageMinP: "0.7",
27
- // How sure the judge must be that an answer at the review gate is a reusable standard.
28
- standardMinP: "0.8",
29
- refactorFlagPattern: "\\bGTD_FLAG_\\w+",
30
- seamAllow: [...testFileGlobs, ".gtd/**"].join(", "),
31
- // A person tries every green naive pass at `seam.try` before anything builds on it.
32
- naiveTest: "false",
33
- // GTD_FLAG_RISK_TIER, recorded at process start; only "1" is on.
34
- flag_risk_tier: "0",
35
- // Decides the turn count: one `build.quality.<lens>` scope per entry, each
36
- // keyed in `./skills.ts`.
37
- qualityReviews:
38
- "correctness, owasp-security, ponytail-review, test-audit, conventions, spec-challenge, criteria-coverage",
39
- refactorQualityReviews: "correctness, ponytail-review, conventions",
40
- }
41
-
42
- /** Environment settings. */
43
- export const envDefaults: Readonly<Record<string, string>> = {
44
- testCommand: "npm test",
45
- plannerModel: "smart",
46
- coderModel: "base",
47
- }
@@ -1,54 +0,0 @@
1
- import { After, Given, Then } from "quickpickle"
2
- import { CONFIG_SCAFFOLD } from "../../install/index.js"
3
- import assert from "node:assert"
4
- import type { TestkitWorld } from "../../testkit/index.js"
5
-
6
- Given("the shipped workflows, as gtd install scaffolds them", (world: TestkitWorld) => {
7
- world.configure(CONFIG_SCAFFOLD)
8
- })
9
-
10
- // Ambient, not explicit: the repository's own env is fixed when it is created,
11
- // and only a real environment variable can change between two steps of one process.
12
- const restores: (() => void)[] = []
13
-
14
- Given(
15
- "the ambient environment variable {string} is {string}",
16
- (_: TestkitWorld, name: string, value: string) => {
17
- const before = process.env[name]
18
- restores.push(() => {
19
- if (before === undefined) delete process.env[name]
20
- else process.env[name] = before
21
- })
22
- process.env[name] = value
23
- },
24
- )
25
-
26
- After(() => {
27
- while (restores.length > 0) restores.pop()!()
28
- })
29
-
30
- Then("the last commit body contains {string}", (world: TestkitWorld, text: string) => {
31
- const message = world.repo().messages().at(-1) ?? ""
32
- assert.ok(message.includes(text), message)
33
- })
34
-
35
- Then(
36
- "the commit {string} has a body containing {string}",
37
- (world: TestkitWorld, subject: string, text: string) => {
38
- // Every commit with the subject, so a repeated step is not judged by its first match.
39
- const matching = world
40
- .repo()
41
- .messages()
42
- .filter((m) => m.split("\n")[0] === subject)
43
- assert.ok(matching.length > 0, `no commit "${subject}"`)
44
- for (const message of matching) assert.ok(message.includes(text), message)
45
- },
46
- )
47
-
48
- Then("no commit body contains {string}", (world: TestkitWorld, text: string) => {
49
- const hit = world
50
- .repo()
51
- .messages()
52
- .find((m) => m.includes(text))
53
- assert.ok(hit === undefined, `a commit body contains "${text}":\n${hit}`)
54
- })