@pmelab/gtd 24.0.0 → 24.1.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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +31 -5
- package/claude/hooks/access.ts +1 -1
- package/dist/chunks/Schema-Dh-mkwkq.mjs +25353 -0
- package/dist/chunks/reserved-ejn-LVYO.mjs +1388 -0
- package/dist/chunks/rolldown-runtime-8H4AJuhK.mjs +14 -0
- package/dist/chunks/steering-D-PvRC5W.mjs +16296 -0
- package/dist/chunks/wire-DA7q2ikx.mjs +473 -0
- package/dist/flows.mjs +525 -0
- package/dist/gtd.bundle.mjs +43339 -55575
- package/dist/steering.mjs +2 -0
- package/dist/testkit.mjs +13006 -0
- package/dist/wire.mjs +2 -0
- package/dist/workflow-kit.mjs +352 -0
- package/dist/workflows/feature.mjs +315 -0
- package/dist/workflows/fix.mjs +40 -0
- package/dist/workflows/review.mjs +25 -0
- package/dist/workflows.mjs +8 -6
- package/package.json +69 -8
- package/src/cli/Cli.test.ts +1329 -0
- package/src/cli/Cli.ts +1348 -0
- package/src/cli/Program.test.ts +2262 -0
- package/src/cli/Program.ts +1331 -0
- package/src/cli/ToolCommands.ts +43 -0
- package/src/cli/index.ts +14 -0
- package/src/edge/Edge.test.ts +1016 -0
- package/src/edge/Edge.ts +1225 -0
- package/src/edge/index.ts +16 -0
- package/src/emit/Emit.test.ts +425 -0
- package/src/emit/Emit.ts +139 -0
- package/src/emit/GitScript.test.ts +260 -0
- package/src/emit/GitScript.ts +131 -0
- package/src/emit/ModeContradiction.test.ts +120 -0
- package/src/emit/ModeContradiction.ts +66 -0
- package/src/emit/OutcomeScript.test.ts +238 -0
- package/src/emit/OutcomeScript.ts +73 -0
- package/src/emit/SteeringMode.test.ts +274 -0
- package/src/emit/SteeringMode.ts +256 -0
- package/src/emit/index.ts +40 -0
- package/src/install/ConfigScaffold.ts +19 -0
- package/src/install/Install.test.ts +426 -0
- package/src/install/Install.ts +634 -0
- package/src/install/Version.ts +27 -0
- package/src/install/index.ts +3 -0
- package/src/platform/CommandRunner.ts +74 -0
- package/src/platform/Commentary.test.ts +126 -0
- package/src/platform/Commentary.ts +92 -0
- package/src/platform/Git.test.ts +50 -0
- package/src/platform/Git.ts +552 -0
- package/src/platform/Host.ts +42 -0
- package/src/platform/RetainedHistory.test.ts +65 -0
- package/src/platform/RetainedHistory.ts +34 -0
- package/src/platform/Workspace.test.ts +669 -0
- package/src/platform/Workspace.ts +631 -0
- package/src/platform/WorktreeState.test.ts +162 -0
- package/src/platform/WorktreeState.ts +50 -0
- package/src/platform/index.ts +22 -0
- package/src/replay/Access.test.ts +53 -0
- package/src/replay/Access.ts +46 -0
- package/src/replay/Format.test.ts +20 -0
- package/src/replay/Format.ts +14 -0
- package/src/replay/Replay.test.ts +887 -0
- package/src/replay/Replay.ts +669 -0
- package/src/replay/Trailers.test.ts +117 -0
- package/src/replay/Trailers.ts +213 -0
- package/src/replay/Tree.test.ts +25 -0
- package/src/replay/Tree.ts +45 -0
- package/src/replay/index.ts +11 -0
- package/src/steering/Blocks.fixture.ts +6 -0
- package/src/steering/Blocks.test.ts +167 -0
- package/src/steering/Blocks.ts +321 -0
- package/src/steering/CodeThreads.test.ts +127 -0
- package/src/steering/CodeThreads.ts +197 -0
- package/src/steering/Edits.test.ts +19 -0
- package/src/steering/Edits.ts +20 -0
- package/src/steering/Eol.test.ts +16 -0
- package/src/steering/Eol.ts +2 -0
- package/src/steering/FORMATS.md +58 -0
- package/src/steering/Footnotes.test.ts +977 -0
- package/src/steering/Footnotes.ts +661 -0
- package/src/steering/Inline.fixture.ts +7 -0
- package/src/steering/Inline.test.ts +227 -0
- package/src/steering/Inline.ts +195 -0
- package/src/steering/MarkdownTree.test.ts +247 -0
- package/src/steering/MarkdownTree.ts +260 -0
- package/src/steering/Outline.ts +19 -0
- package/src/steering/SteeringFormat.test.ts +91 -0
- package/src/steering/SteeringFormat.ts +267 -0
- package/src/steering/SteeringFormats.test.ts +163 -0
- package/src/steering/Threads.ts +163 -0
- package/src/steering/contract.test.ts +264 -0
- package/src/steering/fixtures/code-threads/cache.stripped.ts.txt +6 -0
- package/src/steering/fixtures/code-threads/cache.ts.md +15 -0
- package/src/steering/fixtures/free-form/notes.md +12 -0
- package/src/steering/fixtures/free-form/notes.read.json +42 -0
- package/src/steering/fixtures/qa/answered.md +23 -0
- package/src/steering/fixtures/qa/answered.read.json +119 -0
- package/src/steering/fixtures/qa/requirements.md +160 -0
- package/src/steering/fixtures/qa/requirements.read.json +475 -0
- package/src/steering/fixtures/review/review.md +76 -0
- package/src/steering/fixtures/review/review.read.json +237 -0
- package/src/steering/fixtures/review/ticked.md +23 -0
- package/src/steering/fixtures/review/ticked.read.json +99 -0
- package/src/steering/fixtures/review-notes/baseline.md +14 -0
- package/src/steering/fixtures/review-notes/noted.md +19 -0
- package/src/steering/freeform.test.ts +311 -0
- package/src/steering/freeform.ts +148 -0
- package/src/steering/index.test.ts +62 -0
- package/src/steering/index.ts +140 -0
- package/src/steering/qa.test.ts +2160 -0
- package/src/steering/qa.ts +1104 -0
- package/src/steering/review.test.ts +1829 -0
- package/src/steering/review.ts +1180 -0
- package/src/step/LandStep.ts +31 -0
- package/src/step/RepoSnapshot.ts +29 -0
- package/src/step/accessRefusal.test.ts +58 -0
- package/src/step/accessRefusal.ts +26 -0
- package/src/step/index.ts +5 -0
- package/src/step/planStart.test.ts +202 -0
- package/src/step/planStart.ts +167 -0
- package/src/step/planStep.test.ts +104 -0
- package/src/step/planStep.ts +89 -0
- package/src/step/snapshot.fixture.ts +28 -0
- package/src/testkit/EmittedScriptRecognizer.test.ts +639 -0
- package/src/testkit/EmittedScriptRecognizer.ts +642 -0
- package/src/testkit/FakeGitOperations.ts +95 -0
- package/src/testkit/GitTiers.test.ts +11 -0
- package/src/testkit/GitTiers.ts +1052 -0
- package/src/testkit/InMemRepo.ts +467 -0
- package/src/testkit/Layers.test.ts +58 -0
- package/src/testkit/Layers.ts +241 -0
- package/src/testkit/StrictGitOperations.ts +31 -0
- package/src/testkit/TestRepo.test.ts +119 -0
- package/src/testkit/TestRepo.ts +274 -0
- package/src/testkit/cliIo.ts +36 -0
- package/src/testkit/index.ts +9 -0
- package/src/testkit/steps.ts +177 -0
- package/src/testkit/testkit.feature +65 -0
- package/src/wire/BeatDocument.test.ts +419 -0
- package/src/wire/BeatDocument.ts +114 -0
- package/src/wire/BeatPlain.test.ts +113 -0
- package/src/wire/BeatPlain.ts +127 -0
- package/src/wire/BeatStatus.test.ts +59 -0
- package/src/wire/BeatStatus.ts +81 -0
- package/src/wire/Demand.test.ts +142 -0
- package/src/wire/Demand.ts +108 -0
- package/src/wire/ExitCodes.test.ts +21 -0
- package/src/wire/ExitCodes.ts +16 -0
- package/src/wire/Glob.ts +29 -0
- package/src/wire/Judge.ts +22 -0
- package/src/wire/Land.test.ts +120 -0
- package/src/wire/Land.ts +75 -0
- package/src/wire/Select.test.ts +148 -0
- package/src/wire/Select.ts +78 -0
- package/src/wire/Sessions.test.ts +59 -0
- package/src/wire/Sessions.ts +39 -0
- package/src/wire/WireSchema.test.ts +162 -0
- package/src/wire/constants.ts +22 -0
- package/src/wire/golden/1/beat-capture.json +34 -0
- package/src/wire/golden/1/beat-message.json +34 -0
- package/src/wire/golden/1/beat-prompt.json +44 -0
- package/src/wire/golden/1/beat-script.json +34 -0
- package/src/wire/golden/1/beat-stalled.json +34 -0
- package/src/wire/golden/1/judge.json +14 -0
- package/src/wire/golden/1/land-noop.json +10 -0
- package/src/wire/golden/1/land.json +10 -0
- package/src/wire/index.ts +12 -0
- package/src/wire/types.ts +46 -0
- package/src/workflow/Diagnostic.test.ts +93 -0
- package/src/workflow/Diagnostic.ts +54 -0
- package/src/workflow/SteeringFormats.test.ts +27 -0
- package/src/workflow/SteeringFormats.ts +6 -0
- package/src/workflow/Workflow.ts +77 -0
- package/src/workflow/compile.test.ts +53 -0
- package/src/workflow/compile.ts +56 -0
- package/src/workflow/discovery.ts +122 -0
- package/src/workflow/fingerprint.test.ts +52 -0
- package/src/workflow/fingerprint.ts +53 -0
- package/src/workflow/index.ts +33 -0
- package/src/workflow/load.test.ts +1017 -0
- package/src/workflow/load.ts +836 -0
- package/src/workflow/skills.test.ts +109 -0
- package/src/workflow/skills.ts +90 -0
- package/src/workflow/vars.ts +33 -0
- package/src/workflows/feature/feature.test.ts +27 -33
- package/src/workflows/feature/index.ts +10 -0
- package/src/workflows/fix/fix.feature +80 -0
- package/src/workflows/fix/fix.test.ts +58 -78
- package/src/workflows/fix/index.ts +6 -0
- package/src/workflows/index.ts +2 -10
- package/src/workflows/review/index.ts +6 -0
- package/src/workflows/review/review.test.ts +85 -29
- package/src/workflows/review/review.ts +3 -1
- package/src/workflows/shared/config.fixture.ts +12 -0
- package/src/workflows/shared/reserved.ts +11 -0
- package/src/workflows/shared/workflows.steps.ts +7 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nodes": [
|
|
3
|
+
{
|
|
4
|
+
"title": "Review note severity tiers (issue #270, T3b)",
|
|
5
|
+
"anchor": {
|
|
6
|
+
"kind": "paragraph",
|
|
7
|
+
"line": 0
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"title": "Sketch: `.gtd/TODO.md` said \"work on issue 270\". Issue #270: at the `review.triage` judge rest (T3, shipped), ask four narrow questions per human note — `security` (yes/no), `reversibility` (one-way/two-way), `blastRadius` (local/module/contract), `newConcept` (yes/no) — in the same commit, as more `Gtd-Judge:` trailers. Flow code, never the model, turns the answers into a tier: security yes or one-way → `critical`; contract or new concept → `should`; else `could`.",
|
|
12
|
+
"anchor": {
|
|
13
|
+
"kind": "paragraph",
|
|
14
|
+
"line": 2
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"title": "Concerns",
|
|
19
|
+
"anchor": {
|
|
20
|
+
"kind": "paragraph",
|
|
21
|
+
"line": 80
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"title": "1. Severity questions at the triage rest — PRODUCT",
|
|
26
|
+
"anchor": {
|
|
27
|
+
"kind": "paragraph",
|
|
28
|
+
"line": 82
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"title": "The `review.triage` rest asks the four severity questions per tiered note (which notes: open question above) alongside the T3 verdict, in one commit. Question wording follows the issue: one-way covers migrations, published API shapes, file formats, anything another system depends on by tomorrow; new concept is judged against the code, never a glossary file, and reusing or extending an existing concept is not new.",
|
|
33
|
+
"anchor": {
|
|
34
|
+
"kind": "paragraph",
|
|
35
|
+
"line": 84
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"title": "2. Tier derivation and guard rails — PRODUCT",
|
|
40
|
+
"anchor": {
|
|
41
|
+
"kind": "paragraph",
|
|
42
|
+
"line": 91
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"title": "Flow code derives the tier: security yes OR one-way → `critical`; contract OR new concept → `should`; else `could`. Deferring is the risky direction: an unanswered question, truncated evidence, or `p` below `reviewSeverityMinP` makes the note `critical`, never `could`. A human note starting with `!` is `critical` and gets no severity questions.",
|
|
47
|
+
"anchor": {
|
|
48
|
+
"kind": "paragraph",
|
|
49
|
+
"line": 93
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"title": "3. Routing by tier — PRODUCT",
|
|
54
|
+
"anchor": {
|
|
55
|
+
"kind": "paragraph",
|
|
56
|
+
"line": 99
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"title": "`critical` + `should` → `.gtd/REQUIREMENTS.md` this round, via the existing collecting turn. `could` → `.gtd/TODO.md` as a deferred package (lifecycle: open question above). Inside REQUIREMENTS.md: one-way doors first, then new concepts, then the rest in note order.",
|
|
61
|
+
"anchor": {
|
|
62
|
+
"kind": "paragraph",
|
|
63
|
+
"line": 101
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"title": "4. Sign-off block on criticals — PRODUCT",
|
|
68
|
+
"anchor": {
|
|
69
|
+
"kind": "paragraph",
|
|
70
|
+
"line": 106
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"title": "A round with an open critical cannot sign off (what counts as resolved: open question above).",
|
|
75
|
+
"anchor": {
|
|
76
|
+
"kind": "paragraph",
|
|
77
|
+
"line": 108
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"title": "5. `!` marker in the review format — TECHNICAL",
|
|
82
|
+
"anchor": {
|
|
83
|
+
"kind": "paragraph",
|
|
84
|
+
"line": 111
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"title": "`src/steering/review.ts` recognises the leading `!` on a human note and strips it from the text the folding turn sees.",
|
|
89
|
+
"anchor": {
|
|
90
|
+
"kind": "paragraph",
|
|
91
|
+
"line": 113
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"title": "6. New process setting `reviewSeverityMinP` — TECHNICAL",
|
|
96
|
+
"anchor": {
|
|
97
|
+
"kind": "paragraph",
|
|
98
|
+
"line": 116
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"title": "Default and fold-time recording per the answered questions below; outcomes stay re-foldable from the recorded trailers (T7, #272), never re-asked.",
|
|
103
|
+
"anchor": {
|
|
104
|
+
"kind": "paragraph",
|
|
105
|
+
"line": 118
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"title": "7. Acceptance — PRODUCT",
|
|
110
|
+
"anchor": {
|
|
111
|
+
"kind": "paragraph",
|
|
112
|
+
"line": 121
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"title": "A review with one one-way-door note, one new-concept note and six style notes produces REQUIREMENTS.md with two entries (one-way door first) and TODO.md with six, and sign-off stays blocked until the one-way door is resolved. Cucumber scenarios cover it; README and `docs/` reflect the `!` marker, the new setting and the deferral.",
|
|
117
|
+
"anchor": {
|
|
118
|
+
"kind": "paragraph",
|
|
119
|
+
"line": 123
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"title": "Which notes get a severity tier?",
|
|
124
|
+
"detail": "T3 already routes each note by verdict: `edit` → planning lap, `question` → answered in place, `nit` → one batched fix, `praise` → dropped. The tier can reroute only edits, or also pull questions and nits into a lap.",
|
|
125
|
+
"status": "open",
|
|
126
|
+
"answered": false,
|
|
127
|
+
"anchor": {
|
|
128
|
+
"kind": "question",
|
|
129
|
+
"index": 0
|
|
130
|
+
},
|
|
131
|
+
"body": [
|
|
132
|
+
{
|
|
133
|
+
"title": "T3 already routes each note by verdict: `edit` → planning lap, `question` → answered in place, `nit` → one batched fix, `praise` → dropped. The tier can reroute only edits, or also pull questions and nits into a lap.",
|
|
134
|
+
"anchor": {
|
|
135
|
+
"kind": "paragraph",
|
|
136
|
+
"line": 14
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
"children": [
|
|
141
|
+
{
|
|
142
|
+
"title": "Only `edit` notes are tiered",
|
|
143
|
+
"checked": false,
|
|
144
|
+
"anchor": {
|
|
145
|
+
"kind": "option",
|
|
146
|
+
"questionIndex": 0,
|
|
147
|
+
"index": 0
|
|
148
|
+
},
|
|
149
|
+
"body": [
|
|
150
|
+
{
|
|
151
|
+
"title": "critical/should edits → REQUIREMENTS.md now; could edits → TODO.md Questions, nits, praise route exactly as today; no severity asked for them A nit that renames a published API (one-way) is still fixed without a plan Done-when holds only if the six style notes are judged `edit`, not `nit`",
|
|
152
|
+
"anchor": {
|
|
153
|
+
"kind": "paragraph",
|
|
154
|
+
"line": 19
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"title": "Every note but praise is tiered; the tier only escalates",
|
|
161
|
+
"checked": false,
|
|
162
|
+
"anchor": {
|
|
163
|
+
"kind": "option",
|
|
164
|
+
"questionIndex": 0,
|
|
165
|
+
"index": 1
|
|
166
|
+
},
|
|
167
|
+
"body": [
|
|
168
|
+
{
|
|
169
|
+
"title": "A critical/should question or nit goes to REQUIREMENTS.md instead of its T3 route A could question is still answered, a could nit still fixed now; only could edits are deferred More judge questions per rest; a misjudged \"touches auth\" pulls a harmless nit into a full lap",
|
|
170
|
+
"anchor": {
|
|
171
|
+
"kind": "paragraph",
|
|
172
|
+
"line": 24
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"title": "Every note but praise is tiered; could also defers nits",
|
|
179
|
+
"checked": false,
|
|
180
|
+
"anchor": {
|
|
181
|
+
"kind": "option",
|
|
182
|
+
"questionIndex": 0,
|
|
183
|
+
"index": 2
|
|
184
|
+
},
|
|
185
|
+
"body": [
|
|
186
|
+
{
|
|
187
|
+
"title": "Same escalation as above, plus could nits go to TODO.md instead of being fixed The T3 nit route then only fires for nothing — effectively retired Matches the done-when literally whether style notes are judged edit or nit",
|
|
188
|
+
"anchor": {
|
|
189
|
+
"kind": "paragraph",
|
|
190
|
+
"line": 31
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"title": "",
|
|
197
|
+
"checked": false,
|
|
198
|
+
"anchor": {
|
|
199
|
+
"kind": "option",
|
|
200
|
+
"questionIndex": 0,
|
|
201
|
+
"index": 3
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"title": "What does \"a lap cannot sign off with an open critical\" enforce?",
|
|
208
|
+
"detail": "A critical note always goes to REQUIREMENTS.md, so the round it appears in already cannot sign off. The fork is whether the NEXT round checks that the critical was actually dealt with.",
|
|
209
|
+
"status": "open",
|
|
210
|
+
"answered": false,
|
|
211
|
+
"anchor": {
|
|
212
|
+
"kind": "question",
|
|
213
|
+
"index": 1
|
|
214
|
+
},
|
|
215
|
+
"body": [
|
|
216
|
+
{
|
|
217
|
+
"title": "A critical note always goes to REQUIREMENTS.md, so the round it appears in already cannot sign off. The fork is whether the NEXT round checks that the critical was actually dealt with.",
|
|
218
|
+
"anchor": {
|
|
219
|
+
"kind": "paragraph",
|
|
220
|
+
"line": 39
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
],
|
|
224
|
+
"children": [
|
|
225
|
+
{
|
|
226
|
+
"title": "Nothing extra: routing a critical into a lap is the block",
|
|
227
|
+
"checked": false,
|
|
228
|
+
"anchor": {
|
|
229
|
+
"kind": "option",
|
|
230
|
+
"questionIndex": 1,
|
|
231
|
+
"index": 0
|
|
232
|
+
},
|
|
233
|
+
"body": [
|
|
234
|
+
{
|
|
235
|
+
"title": "No new step, no new guard The next round signs off whenever the human signs off, even if the fix missed the point",
|
|
236
|
+
"anchor": {
|
|
237
|
+
"kind": "paragraph",
|
|
238
|
+
"line": 44
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"title": "Carry each critical into the next REVIEW.md as an item the human must tick",
|
|
245
|
+
"checked": false,
|
|
246
|
+
"anchor": {
|
|
247
|
+
"kind": "option",
|
|
248
|
+
"questionIndex": 1,
|
|
249
|
+
"index": 1
|
|
250
|
+
},
|
|
251
|
+
"body": [
|
|
252
|
+
{
|
|
253
|
+
"title": "The review gate refuses sign-off while any carried critical is unticked New visible ritual in REVIEW.md; the human, not a model, decides \"resolved\"",
|
|
254
|
+
"anchor": {
|
|
255
|
+
"kind": "paragraph",
|
|
256
|
+
"line": 48
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"title": "A judge asks \"is this critical resolved?\" per carried critical at sign-off",
|
|
263
|
+
"checked": false,
|
|
264
|
+
"anchor": {
|
|
265
|
+
"kind": "option",
|
|
266
|
+
"questionIndex": 1,
|
|
267
|
+
"index": 2
|
|
268
|
+
},
|
|
269
|
+
"body": [
|
|
270
|
+
{
|
|
271
|
+
"title": "One more judge rest per signing round Below-floor or unanswered keeps sign-off blocked, which can loop until the human edits again",
|
|
272
|
+
"anchor": {
|
|
273
|
+
"kind": "paragraph",
|
|
274
|
+
"line": 51
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"title": "",
|
|
281
|
+
"checked": false,
|
|
282
|
+
"anchor": {
|
|
283
|
+
"kind": "option",
|
|
284
|
+
"questionIndex": 1,
|
|
285
|
+
"index": 3
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
]
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"title": "What happens to deferred `could` notes in `.gtd/TODO.md`?",
|
|
292
|
+
"detail": "TODO.md is the human's sketch file at `idle`. A deferred note written there mid process gets committed onto the branch, and the next process's `unwind` only reverts what the human adds at `idle` — not what is already committed — so deferred notes do not reach the next triage on their own.",
|
|
293
|
+
"status": "open",
|
|
294
|
+
"answered": false,
|
|
295
|
+
"anchor": {
|
|
296
|
+
"kind": "question",
|
|
297
|
+
"index": 2
|
|
298
|
+
},
|
|
299
|
+
"body": [
|
|
300
|
+
{
|
|
301
|
+
"title": "TODO.md is the human's sketch file at `idle`. A deferred note written there mid process gets committed onto the branch, and the next process's `unwind` only reverts what the human adds at `idle` — not what is already committed — so deferred notes do not reach the next triage on their own.",
|
|
302
|
+
"anchor": {
|
|
303
|
+
"kind": "paragraph",
|
|
304
|
+
"line": 58
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"children": [
|
|
309
|
+
{
|
|
310
|
+
"title": "Append them to TODO.md and leave them committed; the human pulls them into a later process by hand",
|
|
311
|
+
"checked": false,
|
|
312
|
+
"anchor": {
|
|
313
|
+
"kind": "option",
|
|
314
|
+
"questionIndex": 2,
|
|
315
|
+
"index": 0
|
|
316
|
+
},
|
|
317
|
+
"body": [
|
|
318
|
+
{
|
|
319
|
+
"title": "Smallest build `.gtd/TODO.md` ships in the branch/PR unless the human deletes it Deferred items are only a reminder until a human re-types or re-touches them",
|
|
320
|
+
"anchor": {
|
|
321
|
+
"kind": "paragraph",
|
|
322
|
+
"line": 65
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"title": "Append them to TODO.md, and the next ordinary start treats a committed TODO.md as part of its sketch",
|
|
329
|
+
"checked": false,
|
|
330
|
+
"anchor": {
|
|
331
|
+
"kind": "option",
|
|
332
|
+
"questionIndex": 2,
|
|
333
|
+
"index": 1
|
|
334
|
+
},
|
|
335
|
+
"body": [
|
|
336
|
+
{
|
|
337
|
+
"title": "Deferred items become concerns of the next process automatically Changes what `unwind`/triage read for every ordinary start `.gtd/TODO.md` still sits in the branch until that next process",
|
|
338
|
+
"anchor": {
|
|
339
|
+
"kind": "paragraph",
|
|
340
|
+
"line": 70
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"title": "Do not commit them: hand them back at sign-off (message or summary), tree stays clean",
|
|
347
|
+
"checked": false,
|
|
348
|
+
"anchor": {
|
|
349
|
+
"kind": "option",
|
|
350
|
+
"questionIndex": 2,
|
|
351
|
+
"index": 2
|
|
352
|
+
},
|
|
353
|
+
"body": [
|
|
354
|
+
{
|
|
355
|
+
"title": "No `.gtd/` file leaks into the PR Deviates from the issue's \"TODO.md as a deferred package\"; nothing persists unless the human copies it",
|
|
356
|
+
"anchor": {
|
|
357
|
+
"kind": "paragraph",
|
|
358
|
+
"line": 75
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"title": "",
|
|
365
|
+
"checked": false,
|
|
366
|
+
"anchor": {
|
|
367
|
+
"kind": "option",
|
|
368
|
+
"questionIndex": 2,
|
|
369
|
+
"index": 3
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
]
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"title": "Where does the `!` go, and on which notes?",
|
|
376
|
+
"detail": "As the first character of the human's own note text, on any note kind — pointer note, footnote, chunk prose — stripped before folding; prefixing the pointer path itself would break the pointer parse, and one rule for all kinds is easier to remember.",
|
|
377
|
+
"status": "answered",
|
|
378
|
+
"answered": false,
|
|
379
|
+
"anchor": {
|
|
380
|
+
"kind": "question",
|
|
381
|
+
"index": 3
|
|
382
|
+
},
|
|
383
|
+
"body": [
|
|
384
|
+
{
|
|
385
|
+
"title": "As the first character of the human's own note text, on any note kind — pointer note, footnote, chunk prose — stripped before folding; prefixing the pointer path itself would break the pointer parse, and one rule for all kinds is easier to remember.",
|
|
386
|
+
"anchor": {
|
|
387
|
+
"kind": "paragraph",
|
|
388
|
+
"line": 133
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
"children": []
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"title": "Does a REQUIREMENTS.md entry show its tier?",
|
|
396
|
+
"detail": "Yes: each folded note names its tier and the answer that earned it (\"critical: one-way door\", \"critical: forced by `!`\", \"critical: judge unsure\"); the issue rejects a single score for being unauditable, so the reason must be visible.",
|
|
397
|
+
"status": "answered",
|
|
398
|
+
"answered": false,
|
|
399
|
+
"anchor": {
|
|
400
|
+
"kind": "question",
|
|
401
|
+
"index": 4
|
|
402
|
+
},
|
|
403
|
+
"body": [
|
|
404
|
+
{
|
|
405
|
+
"title": "Yes: each folded note names its tier and the answer that earned it (\"critical: one-way door\", \"critical: forced by `!`\", \"critical: judge unsure\"); the issue rejects a single score for being unauditable, so the reason must be visible.",
|
|
406
|
+
"anchor": {
|
|
407
|
+
"kind": "paragraph",
|
|
408
|
+
"line": 140
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
],
|
|
412
|
+
"children": []
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"title": "What order do concerns take inside REQUIREMENTS.md?",
|
|
416
|
+
"detail": "One-way doors, then new concepts, then every other critical/should note in document order — the issue fixes the first two; document order is the existing tie-break.",
|
|
417
|
+
"status": "answered",
|
|
418
|
+
"answered": false,
|
|
419
|
+
"anchor": {
|
|
420
|
+
"kind": "question",
|
|
421
|
+
"index": 5
|
|
422
|
+
},
|
|
423
|
+
"body": [
|
|
424
|
+
{
|
|
425
|
+
"title": "One-way doors, then new concepts, then every other critical/should note in document order — the issue fixes the first two; document order is the existing tie-break.",
|
|
426
|
+
"anchor": {
|
|
427
|
+
"kind": "paragraph",
|
|
428
|
+
"line": 146
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
],
|
|
432
|
+
"children": []
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
"title": "What is `reviewSeverityMinP`'s default, and what does a blank value do?",
|
|
436
|
+
"detail": "`0.7`, one floor for all four questions, matching `reviewNoteActionable` and `judgeIdenticalMinP`; a blank value makes every tiered note `critical`, the same fail-safe a blank `reviewNoteActionable` gives (every note an `edit`).",
|
|
437
|
+
"status": "answered",
|
|
438
|
+
"answered": false,
|
|
439
|
+
"anchor": {
|
|
440
|
+
"kind": "question",
|
|
441
|
+
"index": 6
|
|
442
|
+
},
|
|
443
|
+
"body": [
|
|
444
|
+
{
|
|
445
|
+
"title": "`0.7`, one floor for all four questions, matching `reviewNoteActionable` and `judgeIdenticalMinP`; a blank value makes every tiered note `critical`, the same fail-safe a blank `reviewNoteActionable` gives (every note an `edit`).",
|
|
446
|
+
"anchor": {
|
|
447
|
+
"kind": "paragraph",
|
|
448
|
+
"line": 152
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
],
|
|
452
|
+
"children": []
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"title": "What happens without a configured judge?",
|
|
456
|
+
"detail": "Same as T3: the rest surfaces to the driver, which answers the extra questions like the verdict; no separate fallback.",
|
|
457
|
+
"status": "answered",
|
|
458
|
+
"answered": false,
|
|
459
|
+
"anchor": {
|
|
460
|
+
"kind": "question",
|
|
461
|
+
"index": 7
|
|
462
|
+
},
|
|
463
|
+
"body": [
|
|
464
|
+
{
|
|
465
|
+
"title": "Same as T3: the rest surfaces to the driver, which answers the extra questions like the verdict; no separate fallback.",
|
|
466
|
+
"anchor": {
|
|
467
|
+
"kind": "paragraph",
|
|
468
|
+
"line": 158
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
],
|
|
472
|
+
"children": []
|
|
473
|
+
}
|
|
474
|
+
]
|
|
475
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Review: 0ef1c31
|
|
2
|
+
|
|
3
|
+
<!-- base: 8d5defb41ddbf4ec3927018eecf09a893653a028 -->
|
|
4
|
+
|
|
5
|
+
**This round closes the reverse gap from the last review: a commit footer under
|
|
6
|
+
a title with no `!` now fails. It also anchors the title's `!` match and states
|
|
7
|
+
the both-or-neither rule in both agent prompts.** No new risk found.
|
|
8
|
+
`tests/tooling/commits.test.ts` passes locally: **31/31**.
|
|
9
|
+
|
|
10
|
+
## PR check: both-or-neither for title and footer
|
|
11
|
+
|
|
12
|
+
**The title check now runs both ways.** A `!` title with no footer fails, as
|
|
13
|
+
before. **A footer with no `!` title now fails too.** The `!` match is a regex
|
|
14
|
+
anchored at the type prefix, so **a `!:` later in the title no longer counts as
|
|
15
|
+
breaking**.
|
|
16
|
+
|
|
17
|
+
- [ ] ./.github/workflows/commits.yml#36-46 — one
|
|
18
|
+
`git log --no-merges --format=%B` over the range sets `carries`. The old
|
|
19
|
+
per-commit loop is gone. `bang` is the bash version of
|
|
20
|
+
`commitlint.config.mjs`'s `bangHeader` (`\w` spelled `[A-Za-z0-9_]`). The
|
|
21
|
+
step uses GitHub's default shell, `bash -e` without pipefail, so `grep -q`
|
|
22
|
+
closing the pipe early cannot flip `carries` off. **If anyone adds
|
|
23
|
+
`shell: bash` (which turns on pipefail), a SIGPIPE from `git log` can
|
|
24
|
+
silently drop a found footer.**
|
|
25
|
+
- [ ] ./tests/tooling/commits.test.ts#52-59 — `check` now wraps `checkTitle`
|
|
26
|
+
with the fixed title `"feat: a title"`. `checkTitle` no longer adds a
|
|
27
|
+
`feat: fine` commit when given no messages, so callers pass their own.
|
|
28
|
+
- [ ] ./tests/tooling/commits.test.ts#62-66 — the passing case includes a footer
|
|
29
|
+
commit, so its title gains `!`. Without it the new reverse rule fails the
|
|
30
|
+
case.
|
|
31
|
+
- [ ] ./tests/tooling/commits.test.ts#118-132 — existing cases are adapted: the
|
|
32
|
+
title case now supplies its own commit, and the footer commit moves first
|
|
33
|
+
in the list. Neither changes what the case asserts.
|
|
34
|
+
- [ ] ./tests/tooling/commits.test.ts#140-150 — two new cases: a footer under a
|
|
35
|
+
plain title fails with "title has no", and `` `!:` `` in the middle of a
|
|
36
|
+
title passes.
|
|
37
|
+
|
|
38
|
+
## Convention doc
|
|
39
|
+
|
|
40
|
+
**`docs/commits.md` states the reverse rule and that the 72-char limit applies
|
|
41
|
+
before GitHub's ` (#N)` suffix.**
|
|
42
|
+
|
|
43
|
+
- [ ] ./docs/commits.md#10-20 — prose only. The pinned string
|
|
44
|
+
`at most 72 characters` is unchanged, so the doc-pin test still matches.
|
|
45
|
+
|
|
46
|
+
## Agent prompts state the rule
|
|
47
|
+
|
|
48
|
+
**Both closing-message prompts now require `!` and
|
|
49
|
+
`BREAKING CHANGE: <how to migrate>` together, and list the type set.** A new
|
|
50
|
+
test pins this.
|
|
51
|
+
|
|
52
|
+
- [ ] ./src/workflows/text.ts#867-878 — this replaces the old "`!` alone is not
|
|
53
|
+
enough" note with "both or neither". It adds a subject-format bullet with
|
|
54
|
+
the 9 types and the 72-char limit.
|
|
55
|
+
- [ ] ./claude/hooks/ship.ts#64-67 — squash prompt: a `!` subject needs the
|
|
56
|
+
footer.
|
|
57
|
+
- [ ] ./claude/hooks/ship.ts#301-304 — PR prompt: a `!` title needs the footer
|
|
58
|
+
line in the description. Line 304 now goes past the prompt's line width
|
|
59
|
+
(cosmetic only).
|
|
60
|
+
- [ ] ./tests/tooling/commits.test.ts#161-170 — pins both prompt files to the
|
|
61
|
+
config's `type-enum` and the literal footer placeholder. **The type check
|
|
62
|
+
is weak: `toContain("ci")` / `"fix"` / `"test"` matches anywhere in large
|
|
63
|
+
files, so dropping a type from the prompt prose would not fail it.** Only
|
|
64
|
+
the footer string check has real power.
|
|
65
|
+
|
|
66
|
+
## Release bump cases and cache inputs
|
|
67
|
+
|
|
68
|
+
**More semantic-release cases, including a real GitHub squash body. The tooling
|
|
69
|
+
task cache now also keys on `package-lock.json`.**
|
|
70
|
+
|
|
71
|
+
- [ ] ./tests/tooling/commits.test.ts#238-240 — `fix` → patch, `docs` → no
|
|
72
|
+
release, and a `(#12)` squash with a `* feat!:` body footer → 2.0.0. This
|
|
73
|
+
proves the footer cuts a major from inside the squash body.
|
|
74
|
+
- [ ] ./turbo.json#86-88 — adds `package-lock.json` to the inputs, so a
|
|
75
|
+
commitlint or semantic-release version bump no longer reuses a stale
|
|
76
|
+
cached pass.
|