@pmelab/gtd 58.1.0 → 59.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 (142) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +115 -390
  3. package/dist/chunks/{Schema-B3o6eRNU.mjs → testkit-CMBAAyRK.mjs} +13409 -3351
  4. package/dist/gtd.bundle.mjs +76 -59
  5. package/dist/testkit/gherkin.mjs +30 -2
  6. package/dist/testkit.mjs +1 -1
  7. package/package.json +3 -42
  8. package/skills/authoring/SKILL.md +31 -25
  9. package/src/cli/Cli.test.ts +15 -19
  10. package/src/cli/Cli.ts +2 -4
  11. package/src/cli/Program.test.ts +60 -29
  12. package/src/cli/Program.ts +5 -7
  13. package/src/edge/Edge.ts +3 -3
  14. package/src/flags/index.test.ts +0 -13
  15. package/src/flags/index.ts +1 -3
  16. package/src/gherkin/git-control.feature +78 -0
  17. package/src/gherkin/index.ts +35 -1
  18. package/src/install/Install.test.ts +14 -11
  19. package/src/install/Install.ts +38 -15
  20. package/src/install/index.ts +1 -2
  21. package/src/replay/Replay.test.ts +1 -1
  22. package/src/replay/index.ts +1 -1
  23. package/src/step/planStart.ts +6 -1
  24. package/src/testkit/TestRepo.test.ts +118 -2
  25. package/src/testkit/TestRepo.ts +57 -6
  26. package/src/testkit/index.ts +1 -0
  27. package/src/twins/EmittedScriptRecognizer.ts +12 -14
  28. package/src/twins/FlowScripts.ts +10 -9
  29. package/src/twins/InMemRepo.ts +26 -1
  30. package/src/twins/Layers.ts +12 -1
  31. package/src/twins/index.ts +6 -1
  32. package/src/workflow/index.ts +1 -0
  33. package/src/workflow/load.test.ts +138 -113
  34. package/src/workflow/load.ts +1 -1
  35. package/src/workflow/vars.test.ts +30 -3
  36. package/src/workflow/vars.ts +34 -2
  37. package/src/workflow-kit/index.ts +1 -1
  38. package/dist/chunks/reserved-lMYCaapY.mjs +0 -1990
  39. package/dist/chunks/review-Bfaror38.mjs +0 -427
  40. package/dist/chunks/tail-Bd7L940p.mjs +0 -355
  41. package/dist/chunks/testkit-D1-auYau.mjs +0 -10362
  42. package/dist/workflows/cleanup.mjs +0 -36
  43. package/dist/workflows/feature.mjs +0 -1018
  44. package/dist/workflows/fix.mjs +0 -41
  45. package/dist/workflows/review.mjs +0 -45
  46. package/dist/workflows/rollout.mjs +0 -48
  47. package/dist/workflows.mjs +0 -40651
  48. package/src/install/ConfigScaffold.ts +0 -22
  49. package/src/workflows/cleanup/cleanup-path.feature +0 -94
  50. package/src/workflows/cleanup/cleanup.feature +0 -315
  51. package/src/workflows/cleanup/cleanup.test.ts +0 -276
  52. package/src/workflows/cleanup/cleanup.ts +0 -52
  53. package/src/workflows/cleanup/index.ts +0 -6
  54. package/src/workflows/feature/acceptance-criteria-tier.feature +0 -25
  55. package/src/workflows/feature/acceptance-criteria.feature +0 -389
  56. package/src/workflows/feature/criteria-coverage.feature +0 -102
  57. package/src/workflows/feature/criteria.test.ts +0 -147
  58. package/src/workflows/feature/criteria.ts +0 -267
  59. package/src/workflows/feature/fast-path.feature +0 -93
  60. package/src/workflows/feature/feature.test.ts +0 -338
  61. package/src/workflows/feature/feature.ts +0 -156
  62. package/src/workflows/feature/green.ts +0 -19
  63. package/src/workflows/feature/index.ts +0 -18
  64. package/src/workflows/feature/lens-models.feature +0 -69
  65. package/src/workflows/feature/lens-review.feature +0 -566
  66. package/src/workflows/feature/naive-acceptance.feature +0 -147
  67. package/src/workflows/feature/naive-test.feature +0 -263
  68. package/src/workflows/feature/one-step-land.feature +0 -93
  69. package/src/workflows/feature/planning.ts +0 -41
  70. package/src/workflows/feature/refactor-absorbs.feature +0 -131
  71. package/src/workflows/feature/refactor-first.feature +0 -158
  72. package/src/workflows/feature/refactor-lens-models.feature +0 -79
  73. package/src/workflows/feature/refactor-rebuild.feature +0 -273
  74. package/src/workflows/feature/refactor-review.feature +0 -1528
  75. package/src/workflows/feature/refactor.test.ts +0 -1220
  76. package/src/workflows/feature/refactor.ts +0 -368
  77. package/src/workflows/feature/release-flag.feature +0 -167
  78. package/src/workflows/feature/release-flag.test.ts +0 -49
  79. package/src/workflows/feature/release-flag.ts +0 -46
  80. package/src/workflows/feature/review-gate.feature +0 -241
  81. package/src/workflows/feature/reviewer-walkthrough.feature +0 -142
  82. package/src/workflows/feature/risk-tier.feature +0 -351
  83. package/src/workflows/feature/seam-rejection.feature +0 -146
  84. package/src/workflows/feature/seam.feature +0 -297
  85. package/src/workflows/feature/seam.test.ts +0 -527
  86. package/src/workflows/feature/seam.ts +0 -426
  87. package/src/workflows/feature/standards.feature +0 -354
  88. package/src/workflows/feature/steps.test.ts +0 -65
  89. package/src/workflows/feature/steps.ts +0 -45
  90. package/src/workflows/feature/tier-pin.feature +0 -66
  91. package/src/workflows/feature/tier.test.ts +0 -166
  92. package/src/workflows/feature/tier.ts +0 -56
  93. package/src/workflows/fix/fix-lens-origin.feature +0 -114
  94. package/src/workflows/fix/fix-quality.feature +0 -212
  95. package/src/workflows/fix/fix.feature +0 -79
  96. package/src/workflows/fix/fix.test.ts +0 -74
  97. package/src/workflows/fix/fix.ts +0 -52
  98. package/src/workflows/fix/index.ts +0 -6
  99. package/src/workflows/index.ts +0 -47
  100. package/src/workflows/review/index.ts +0 -6
  101. package/src/workflows/review/review-door.feature +0 -199
  102. package/src/workflows/review/review.test.ts +0 -27
  103. package/src/workflows/review/review.ts +0 -60
  104. package/src/workflows/rollout/index.ts +0 -6
  105. package/src/workflows/rollout/rollout.feature +0 -510
  106. package/src/workflows/rollout/rollout.test.ts +0 -263
  107. package/src/workflows/rollout/rollout.ts +0 -82
  108. package/src/workflows/shared/__fixtures__/feature-collecting-prompt.txt +0 -98
  109. package/src/workflows/shared/access.test.ts +0 -62
  110. package/src/workflows/shared/access.ts +0 -24
  111. package/src/workflows/shared/config.fixture.ts +0 -12
  112. package/src/workflows/shared/fences.ts +0 -24
  113. package/src/workflows/shared/health.test.ts +0 -148
  114. package/src/workflows/shared/health.ts +0 -191
  115. package/src/workflows/shared/learn.test.ts +0 -140
  116. package/src/workflows/shared/learn.ts +0 -201
  117. package/src/workflows/shared/lenses.test.ts +0 -39
  118. package/src/workflows/shared/lenses.ts +0 -294
  119. package/src/workflows/shared/options.test.ts +0 -157
  120. package/src/workflows/shared/options.ts +0 -92
  121. package/src/workflows/shared/progress.feature +0 -124
  122. package/src/workflows/shared/prose.ts +0 -263
  123. package/src/workflows/shared/recheck.feature +0 -60
  124. package/src/workflows/shared/registry.test.ts +0 -345
  125. package/src/workflows/shared/registry.ts +0 -183
  126. package/src/workflows/shared/reserved.ts +0 -11
  127. package/src/workflows/shared/review.test.ts +0 -1062
  128. package/src/workflows/shared/review.ts +0 -446
  129. package/src/workflows/shared/skills.test.ts +0 -121
  130. package/src/workflows/shared/skills.ts +0 -49
  131. package/src/workflows/shared/standards.test.ts +0 -90
  132. package/src/workflows/shared/standards.ts +0 -156
  133. package/src/workflows/shared/steps.test.ts +0 -219
  134. package/src/workflows/shared/steps.ts +0 -201
  135. package/src/workflows/shared/tail.test.ts +0 -454
  136. package/src/workflows/shared/tail.ts +0 -264
  137. package/src/workflows/shared/text.fixture.ts +0 -128
  138. package/src/workflows/shared/text.test.ts +0 -1430
  139. package/src/workflows/shared/text.ts +0 -1700
  140. package/src/workflows/shared/threads.test.ts +0 -129
  141. package/src/workflows/shared/vars.ts +0 -47
  142. 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
- })