@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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +115 -390
- package/dist/chunks/{Schema-B3o6eRNU.mjs → testkit-CMBAAyRK.mjs} +13409 -3351
- package/dist/gtd.bundle.mjs +76 -59
- package/dist/testkit/gherkin.mjs +30 -2
- package/dist/testkit.mjs +1 -1
- package/package.json +3 -42
- package/skills/authoring/SKILL.md +31 -25
- package/src/cli/Cli.test.ts +15 -19
- package/src/cli/Cli.ts +2 -4
- package/src/cli/Program.test.ts +60 -29
- package/src/cli/Program.ts +5 -7
- package/src/edge/Edge.ts +3 -3
- package/src/flags/index.test.ts +0 -13
- package/src/flags/index.ts +1 -3
- package/src/gherkin/git-control.feature +78 -0
- package/src/gherkin/index.ts +35 -1
- package/src/install/Install.test.ts +14 -11
- package/src/install/Install.ts +38 -15
- package/src/install/index.ts +1 -2
- package/src/replay/Replay.test.ts +1 -1
- package/src/replay/index.ts +1 -1
- package/src/step/planStart.ts +6 -1
- package/src/testkit/TestRepo.test.ts +118 -2
- package/src/testkit/TestRepo.ts +57 -6
- package/src/testkit/index.ts +1 -0
- package/src/twins/EmittedScriptRecognizer.ts +12 -14
- package/src/twins/FlowScripts.ts +10 -9
- package/src/twins/InMemRepo.ts +26 -1
- package/src/twins/Layers.ts +12 -1
- package/src/twins/index.ts +6 -1
- package/src/workflow/index.ts +1 -0
- package/src/workflow/load.test.ts +138 -113
- package/src/workflow/load.ts +1 -1
- package/src/workflow/vars.test.ts +30 -3
- package/src/workflow/vars.ts +34 -2
- package/src/workflow-kit/index.ts +1 -1
- package/dist/chunks/reserved-lMYCaapY.mjs +0 -1990
- package/dist/chunks/review-Bfaror38.mjs +0 -427
- package/dist/chunks/tail-Bd7L940p.mjs +0 -355
- package/dist/chunks/testkit-D1-auYau.mjs +0 -10362
- package/dist/workflows/cleanup.mjs +0 -36
- package/dist/workflows/feature.mjs +0 -1018
- package/dist/workflows/fix.mjs +0 -41
- package/dist/workflows/review.mjs +0 -45
- package/dist/workflows/rollout.mjs +0 -48
- package/dist/workflows.mjs +0 -40651
- package/src/install/ConfigScaffold.ts +0 -22
- package/src/workflows/cleanup/cleanup-path.feature +0 -94
- package/src/workflows/cleanup/cleanup.feature +0 -315
- package/src/workflows/cleanup/cleanup.test.ts +0 -276
- package/src/workflows/cleanup/cleanup.ts +0 -52
- package/src/workflows/cleanup/index.ts +0 -6
- package/src/workflows/feature/acceptance-criteria-tier.feature +0 -25
- package/src/workflows/feature/acceptance-criteria.feature +0 -389
- package/src/workflows/feature/criteria-coverage.feature +0 -102
- package/src/workflows/feature/criteria.test.ts +0 -147
- package/src/workflows/feature/criteria.ts +0 -267
- package/src/workflows/feature/fast-path.feature +0 -93
- package/src/workflows/feature/feature.test.ts +0 -338
- package/src/workflows/feature/feature.ts +0 -156
- package/src/workflows/feature/green.ts +0 -19
- package/src/workflows/feature/index.ts +0 -18
- package/src/workflows/feature/lens-models.feature +0 -69
- package/src/workflows/feature/lens-review.feature +0 -566
- package/src/workflows/feature/naive-acceptance.feature +0 -147
- package/src/workflows/feature/naive-test.feature +0 -263
- package/src/workflows/feature/one-step-land.feature +0 -93
- package/src/workflows/feature/planning.ts +0 -41
- package/src/workflows/feature/refactor-absorbs.feature +0 -131
- package/src/workflows/feature/refactor-first.feature +0 -158
- package/src/workflows/feature/refactor-lens-models.feature +0 -79
- package/src/workflows/feature/refactor-rebuild.feature +0 -273
- package/src/workflows/feature/refactor-review.feature +0 -1528
- package/src/workflows/feature/refactor.test.ts +0 -1220
- package/src/workflows/feature/refactor.ts +0 -368
- package/src/workflows/feature/release-flag.feature +0 -167
- package/src/workflows/feature/release-flag.test.ts +0 -49
- package/src/workflows/feature/release-flag.ts +0 -46
- package/src/workflows/feature/review-gate.feature +0 -241
- package/src/workflows/feature/reviewer-walkthrough.feature +0 -142
- package/src/workflows/feature/risk-tier.feature +0 -351
- package/src/workflows/feature/seam-rejection.feature +0 -146
- package/src/workflows/feature/seam.feature +0 -297
- package/src/workflows/feature/seam.test.ts +0 -527
- package/src/workflows/feature/seam.ts +0 -426
- package/src/workflows/feature/standards.feature +0 -354
- package/src/workflows/feature/steps.test.ts +0 -65
- package/src/workflows/feature/steps.ts +0 -45
- package/src/workflows/feature/tier-pin.feature +0 -66
- package/src/workflows/feature/tier.test.ts +0 -166
- package/src/workflows/feature/tier.ts +0 -56
- package/src/workflows/fix/fix-lens-origin.feature +0 -114
- package/src/workflows/fix/fix-quality.feature +0 -212
- package/src/workflows/fix/fix.feature +0 -79
- package/src/workflows/fix/fix.test.ts +0 -74
- package/src/workflows/fix/fix.ts +0 -52
- package/src/workflows/fix/index.ts +0 -6
- package/src/workflows/index.ts +0 -47
- package/src/workflows/review/index.ts +0 -6
- package/src/workflows/review/review-door.feature +0 -199
- package/src/workflows/review/review.test.ts +0 -27
- package/src/workflows/review/review.ts +0 -60
- package/src/workflows/rollout/index.ts +0 -6
- package/src/workflows/rollout/rollout.feature +0 -510
- package/src/workflows/rollout/rollout.test.ts +0 -263
- package/src/workflows/rollout/rollout.ts +0 -82
- package/src/workflows/shared/__fixtures__/feature-collecting-prompt.txt +0 -98
- package/src/workflows/shared/access.test.ts +0 -62
- package/src/workflows/shared/access.ts +0 -24
- package/src/workflows/shared/config.fixture.ts +0 -12
- package/src/workflows/shared/fences.ts +0 -24
- package/src/workflows/shared/health.test.ts +0 -148
- package/src/workflows/shared/health.ts +0 -191
- package/src/workflows/shared/learn.test.ts +0 -140
- package/src/workflows/shared/learn.ts +0 -201
- package/src/workflows/shared/lenses.test.ts +0 -39
- package/src/workflows/shared/lenses.ts +0 -294
- package/src/workflows/shared/options.test.ts +0 -157
- package/src/workflows/shared/options.ts +0 -92
- package/src/workflows/shared/progress.feature +0 -124
- package/src/workflows/shared/prose.ts +0 -263
- package/src/workflows/shared/recheck.feature +0 -60
- package/src/workflows/shared/registry.test.ts +0 -345
- package/src/workflows/shared/registry.ts +0 -183
- package/src/workflows/shared/reserved.ts +0 -11
- package/src/workflows/shared/review.test.ts +0 -1062
- package/src/workflows/shared/review.ts +0 -446
- package/src/workflows/shared/skills.test.ts +0 -121
- package/src/workflows/shared/skills.ts +0 -49
- package/src/workflows/shared/standards.test.ts +0 -90
- package/src/workflows/shared/standards.ts +0 -156
- package/src/workflows/shared/steps.test.ts +0 -219
- package/src/workflows/shared/steps.ts +0 -201
- package/src/workflows/shared/tail.test.ts +0 -454
- package/src/workflows/shared/tail.ts +0 -264
- package/src/workflows/shared/text.fixture.ts +0 -128
- package/src/workflows/shared/text.test.ts +0 -1430
- package/src/workflows/shared/text.ts +0 -1700
- package/src/workflows/shared/threads.test.ts +0 -129
- package/src/workflows/shared/vars.ts +0 -47
- package/src/workflows/shared/workflows.steps.ts +0 -54
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
@inmem
|
|
2
|
-
Feature: a fix loop still making progress at the cap gets one extra turn
|
|
3
|
-
|
|
4
|
-
`healthy` escalates once three fix turns are spent. When `health.judge`
|
|
5
|
-
calls that round progress — still red, but closer to green — with at least
|
|
6
|
-
`judgeIdenticalMinP` confidence, one more fix runs first, once per run of
|
|
7
|
-
fixes. The round after it escalates without asking the judge. Any other
|
|
8
|
-
verdict escalates at the cap as before.
|
|
9
|
-
|
|
10
|
-
Background:
|
|
11
|
-
Given a gtd config with:
|
|
12
|
-
"""
|
|
13
|
-
import { healthy } from "@pmelab/gtd/workflows"
|
|
14
|
-
import { agent } from "@pmelab/gtd/flows"
|
|
15
|
-
|
|
16
|
-
export const defaults = { judgeIdenticalMinP: "0.7" }
|
|
17
|
-
export const held = async () => {
|
|
18
|
-
await agent("first", "go")
|
|
19
|
-
await healthy(() => agent("fix", "go"))
|
|
20
|
-
}
|
|
21
|
-
export default held
|
|
22
|
-
"""
|
|
23
|
-
And step "first" writes "src/a.ts" with:
|
|
24
|
-
"""
|
|
25
|
-
export const a = 1
|
|
26
|
-
"""
|
|
27
|
-
And step "health.check" writes ".gtd/FEEDBACK.md" with:
|
|
28
|
-
"""
|
|
29
|
-
tests failing
|
|
30
|
-
"""
|
|
31
|
-
And step "fix" deletes ".gtd/FEEDBACK.md"
|
|
32
|
-
And step "health.recheck" writes ".gtd/FEEDBACK.md" with:
|
|
33
|
-
"""
|
|
34
|
-
tests still failing
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
Scenario: progress at the cap buys exactly one extra fix turn
|
|
38
|
-
Given judge step "health.judge" answers:
|
|
39
|
-
"""
|
|
40
|
-
[{"id":"verdict","answer":"progress","p":0.9}]
|
|
41
|
-
"""
|
|
42
|
-
When gtd starts workflow "held"
|
|
43
|
-
And the process is driven
|
|
44
|
-
Then the process rests at "health.describe"
|
|
45
|
-
And the commit subjects end with:
|
|
46
|
-
"""
|
|
47
|
-
gtd(agent): first → health.check
|
|
48
|
-
gtd(check): health.check → fix
|
|
49
|
-
gtd(agent): fix → health.check
|
|
50
|
-
gtd(check): health.check → health.judge
|
|
51
|
-
gtd(judge): health.judge → fix
|
|
52
|
-
gtd(agent): fix → health.check
|
|
53
|
-
gtd(check): health.check → health.judge
|
|
54
|
-
gtd(judge): health.judge → fix
|
|
55
|
-
gtd(agent): fix → health.check
|
|
56
|
-
gtd(check): health.check → health.judge
|
|
57
|
-
gtd(judge): health.judge → fix
|
|
58
|
-
gtd(agent): fix → health.check
|
|
59
|
-
gtd(check): health.check → health.recheck
|
|
60
|
-
gtd(check): health.recheck → health.describe
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
Scenario Outline: <verdict> at <p> escalates at the cap without an extra turn
|
|
64
|
-
Given judge step "health.judge" answers:
|
|
65
|
-
"""
|
|
66
|
-
[{"id":"verdict","answer":"<verdict>","p":<p>}]
|
|
67
|
-
"""
|
|
68
|
-
When gtd starts workflow "held"
|
|
69
|
-
And the process is driven
|
|
70
|
-
Then the process rests at "health.describe"
|
|
71
|
-
And the commit subjects end with:
|
|
72
|
-
"""
|
|
73
|
-
gtd(agent): first → health.check
|
|
74
|
-
gtd(check): health.check → fix
|
|
75
|
-
gtd(agent): fix → health.check
|
|
76
|
-
gtd(check): health.check → health.judge
|
|
77
|
-
gtd(judge): health.judge → fix
|
|
78
|
-
gtd(agent): fix → health.check
|
|
79
|
-
gtd(check): health.check → health.judge
|
|
80
|
-
gtd(judge): health.judge → fix
|
|
81
|
-
gtd(agent): fix → health.check
|
|
82
|
-
gtd(check): health.check → health.judge
|
|
83
|
-
gtd(judge): health.judge → health.recheck
|
|
84
|
-
gtd(check): health.recheck → health.describe
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
Examples:
|
|
88
|
-
| verdict | p |
|
|
89
|
-
| new-failure | 0.9 |
|
|
90
|
-
| progress | 0.5 |
|
|
91
|
-
|
|
92
|
-
Scenario: a person's escalation stop starts a new run of fixes with its own extra turn
|
|
93
|
-
Given judge step "health.judge" answers:
|
|
94
|
-
"""
|
|
95
|
-
[{"id":"verdict","answer":"progress","p":0.9}]
|
|
96
|
-
"""
|
|
97
|
-
And step "health.describe" writes ".gtd/ESCALATION.md" with:
|
|
98
|
-
"""
|
|
99
|
-
try something else
|
|
100
|
-
"""
|
|
101
|
-
And step "health.stop" writes "NOTES.md" with:
|
|
102
|
-
"""
|
|
103
|
-
narrowed
|
|
104
|
-
"""
|
|
105
|
-
When gtd starts workflow "held"
|
|
106
|
-
And the process is driven
|
|
107
|
-
Then the process rests at "health.exhausted"
|
|
108
|
-
And the commit subjects end with:
|
|
109
|
-
"""
|
|
110
|
-
gtd(agent): health.describe → health.stop
|
|
111
|
-
gtd(human): health.stop → fix
|
|
112
|
-
gtd(agent): fix → health.check
|
|
113
|
-
gtd(check): health.check → health.judge
|
|
114
|
-
gtd(judge): health.judge → fix
|
|
115
|
-
gtd(agent): fix → health.check
|
|
116
|
-
gtd(check): health.check → health.judge
|
|
117
|
-
gtd(judge): health.judge → fix
|
|
118
|
-
gtd(agent): fix → health.check
|
|
119
|
-
gtd(check): health.check → health.judge
|
|
120
|
-
gtd(judge): health.judge → fix
|
|
121
|
-
gtd(agent): fix → health.check
|
|
122
|
-
gtd(check): health.check → health.recheck
|
|
123
|
-
gtd(check): health.recheck → health.exhausted
|
|
124
|
-
"""
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
// Prose the bundled workflow's prompts share: its voice, its personas and
|
|
2
|
-
// the rules several steps repeat. A workflow that wants different words
|
|
3
|
-
// writes its own prompts.
|
|
4
|
-
|
|
5
|
-
export const skillsPreamble = `- Load whatever's listed here that your harness actually has installed,
|
|
6
|
-
skip anything it doesn't — silently, never stopping or asking about a
|
|
7
|
-
missing one: {skills}
|
|
8
|
-
- A loaded skill offers technique, never authority: this state's own file
|
|
9
|
-
format and its own completion condition are the final word over
|
|
10
|
-
anything a skill's instructions say, regardless of which one this
|
|
11
|
-
prompt states first
|
|
12
|
-
- Never let a loaded skill turn this turn interactive — answer nothing,
|
|
13
|
-
ask nothing; this runs unattended, with no one at a keyboard`
|
|
14
|
-
|
|
15
|
-
/** One bullet per restricted side; empty when neither is. An empty glob list reads "nothing". */
|
|
16
|
-
export const accessPreamble = (access: {
|
|
17
|
-
readonly read: readonly string[] | null
|
|
18
|
-
readonly write: readonly string[] | null
|
|
19
|
-
}): string => {
|
|
20
|
-
const globs = (list: readonly string[]): string =>
|
|
21
|
-
list.length === 0 ? "nothing" : list.join(", ")
|
|
22
|
-
return [
|
|
23
|
-
...(access.read === null ? [] : [`- This turn may read only: ${globs(access.read)}`]),
|
|
24
|
-
...(access.write === null
|
|
25
|
-
? []
|
|
26
|
-
: [
|
|
27
|
-
`- This turn may write only: ${globs(access.write)} — anything else is refused when the turn lands`,
|
|
28
|
-
]),
|
|
29
|
-
].join("\n")
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const styleBlock = `- A deliverable, not a chat reply — size follows the work; cut padding
|
|
33
|
-
- Lead with the answer; never circle back to restate it
|
|
34
|
-
- Flat, commanding sentences — commit to the claim, never hedge
|
|
35
|
-
- Everyday words; define an unavoidable term in five words or fewer, on
|
|
36
|
-
first use
|
|
37
|
-
- Bold carries the load: bold the claim, not the sentence around it —
|
|
38
|
-
the bold text alone must yield the full point and every risk
|
|
39
|
-
- **Never trim a risk, a number, a threshold, or a scoped condition to
|
|
40
|
-
save space — this outranks every other rule here**
|
|
41
|
-
- Ship the artifact bare — no lead-in, no sign-off
|
|
42
|
-
- Compressing is not dropping: three load-bearing parts ship as three,
|
|
43
|
-
each shorter, never as two
|
|
44
|
-
- One idea per block; break when the idea shifts
|
|
45
|
-
- Flag risk in one blunt line, never hedged prose; never narrate — do it`
|
|
46
|
-
|
|
47
|
-
export const styleFormatContract = `- Machine-read: its format contract outranks every style rule above —
|
|
48
|
-
keep every \`##\`/\`###\` heading, checkbox row, and marker line exactly
|
|
49
|
-
as specified. Never renumber or rename a heading; a parser reads
|
|
50
|
-
these literally and a violation refuses the turn
|
|
51
|
-
- Voice rules above govern only the prose between these elements`
|
|
52
|
-
|
|
53
|
-
export const agentConduct = `- You have shell and file tools — bash, read, write, edit — use them
|
|
54
|
-
without asking first; this runs unattended, no one grants permission
|
|
55
|
-
- Investigate with real commands rather than assuming a file's, a
|
|
56
|
-
commit's, or a decision's status — then act on what you find
|
|
57
|
-
- No injected status block — no cwd, no branch, no history, no tree
|
|
58
|
-
state — orient yourself first with \`git status\`, \`git log\`, \`ls\`
|
|
59
|
-
- The turn's message names a commit, a range, or a file to go inspect
|
|
60
|
-
yourself — never a diff or summary inlined into the conversation
|
|
61
|
-
- Across turns one conversation may span, work from what you already
|
|
62
|
-
read and settled, unless told this is a fresh, cold pass
|
|
63
|
-
- Your turn ends when you return, and nothing you leave running survives
|
|
64
|
-
it in any useful way — never detach or background work you intend to
|
|
65
|
-
act on, never end a turn planning to "check back": no later turn
|
|
66
|
-
inherits your intent. Run it in the foreground and wait, however long
|
|
67
|
-
it takes. If it genuinely cannot finish inside one turn, write down
|
|
68
|
-
where it stands and what to resume, so the tree carries the state`
|
|
69
|
-
|
|
70
|
-
export const designPersona = `You are the product-facing planning voice in gtd's build pipeline: turn
|
|
71
|
-
a raw sketch — a hand-edit, a scratch note, or both — into an ordered,
|
|
72
|
-
classified list of concerns, and hold the running product conversation
|
|
73
|
-
with the human it depends on. You are read by that human — write
|
|
74
|
-
plainly — not by a parser, except where a state says otherwise.`
|
|
75
|
-
|
|
76
|
-
export const reviewerPersona = `You are the independent reviewing mind in gtd's build pipeline —
|
|
77
|
-
deliberately separate from whoever wrote the code, with no attachment
|
|
78
|
-
to it. Write a structured review document grouping a diff into
|
|
79
|
-
chunks; classify a round of the human's feedback as actionable or
|
|
80
|
-
just approving; answer the human's questions inline in the review;
|
|
81
|
-
and, when asked, fix the small nits the human flagged and the risks
|
|
82
|
-
you marked yourself, each in one batch.
|
|
83
|
-
Beyond that you never fix or build anything yourself.`
|
|
84
|
-
|
|
85
|
-
export const builderPersona = `You are the TDD implementer in gtd's build pipeline: build the
|
|
86
|
-
task in front of you end to end, tests first, and come back to fix
|
|
87
|
-
things when redirected — a failing check, or reviewer feedback. Stay
|
|
88
|
-
strictly inside that task; never touch code outside it. Treat feedback as the
|
|
89
|
-
diagnosis to act on; discard it, with reason, only when simply wrong.`
|
|
90
|
-
|
|
91
|
-
export const finisherPersona = `You are the closing identity in gtd's build pipeline — the last coder
|
|
92
|
-
before it closes. Fix a late-breaking failing check after sign-off,
|
|
93
|
-
focused and minimal. Every turn lands its own commit — nothing here
|
|
94
|
-
gets squashed away.`
|
|
95
|
-
|
|
96
|
-
export const escalationPersona = `You are the diagnosing voice in gtd's build pipeline, called in once a
|
|
97
|
-
check has stayed red past repeated fix attempts. Read the failing
|
|
98
|
-
output, the previous round's, and the code those attempts touched, then
|
|
99
|
-
write down what is failing, why the earlier attempts didn't resolve it,
|
|
100
|
-
and concrete approaches worth trying next. Never fix the code yourself —
|
|
101
|
-
naming the problem precisely enough for the next fix turn is the whole
|
|
102
|
-
job.`
|
|
103
|
-
|
|
104
|
-
export const stateFileRules = `- You are an autonomous coding agent
|
|
105
|
-
- This workflow's own state files are its private scratchpad, never
|
|
106
|
-
project code or documentation`
|
|
107
|
-
|
|
108
|
-
export const questionBar = `- The goal is shared understanding, not a quota or an empty section: a
|
|
109
|
-
question exists to close a gap between what the human wants and
|
|
110
|
-
what the agent is about to build. Ask whenever that gap is open —
|
|
111
|
-
even when the point looks cheap to undo, settled-looking, or
|
|
112
|
-
narrow. This goal outranks what follows; the conditions below are
|
|
113
|
-
signals a gap is real, strong evidence to ask, never permission
|
|
114
|
-
withheld
|
|
115
|
-
- Before writing \`## Open Questions\`, walk every concern you grouped and
|
|
116
|
-
collect every point above the bar into that ONE section — a question
|
|
117
|
-
held back for a later lap is a bug. One lap is the target; a second is
|
|
118
|
-
the exception
|
|
119
|
-
- Raise first, narrow second: only once every concern above the bar is
|
|
120
|
-
raised into \`## Open Questions\`, walk that same set once more and
|
|
121
|
-
answer the ones a confident default settles, moving each into
|
|
122
|
-
\`## Answered Questions\` with its answer. This pass narrows what's
|
|
123
|
-
already raised — it is never license to raise less, and skipping the
|
|
124
|
-
raise to answer straight through is the same bug as holding a
|
|
125
|
-
question back for a later lap
|
|
126
|
-
- Treat each of these as strong evidence a gap is real: it's a genuine
|
|
127
|
-
fork with divergent outcomes (user-visible for product, materially
|
|
128
|
-
different builds for technical); the diff and history don't already
|
|
129
|
-
settle it (treat an explicit \`.gtd/TODO.md\` directive, a committed
|
|
130
|
-
hand-edit, or — on a loop-back lap — the human's own review-round
|
|
131
|
-
edit/note as settled); or it would be expensive to undo once
|
|
132
|
-
code is written
|
|
133
|
-
- Where no gap in shared understanding exists, decide it yourself:
|
|
134
|
-
record it under \`## Answered Questions\` as
|
|
135
|
-
\`### <the point phrased as a question>\`
|
|
136
|
-
plus a one-line rationale in prose, no checkboxes. That heading
|
|
137
|
-
always comes last, after every other \`##\` section
|
|
138
|
-
- Above the bar, write it under \`## Open Questions\` — always the first
|
|
139
|
-
\`##\` section — as \`### <question>\` plus a body plus a checkbox list.
|
|
140
|
-
The count of concrete options is your call, taken from how many
|
|
141
|
-
genuinely distinct answers the fork has — never padded to a fixed
|
|
142
|
-
number. A floor still applies: at least two real options plus the
|
|
143
|
-
free-text slot, or the question is not a fork
|
|
144
|
-
- The heading is followed by one or two lines of body naming the fork
|
|
145
|
-
and what actually differs, THEN the option list. The body frames the
|
|
146
|
-
fork; each option's own content carries that option's impacts — they
|
|
147
|
-
never repeat each other. A body that lists the options back is
|
|
148
|
-
padding, and an option line that restates the fork is padding too
|
|
149
|
-
- Each option is one short line plus its own impacts nested under it as
|
|
150
|
-
a bullet list: one to four bullets, free-form — what it costs, what
|
|
151
|
-
it buys, how it differs from the others. Write the dimensions this
|
|
152
|
-
fork actually has and skip the ones it does not; no \`Costs:\`/\`Buys:\`/
|
|
153
|
-
\`Differs:\` labels, no fixed bullet count. The free-text slot is last,
|
|
154
|
-
mandatory, identified by position rather than by label:
|
|
155
|
-
|
|
156
|
-
### <the question>
|
|
157
|
-
|
|
158
|
-
<one or two lines: what the fork is, what actually differs>
|
|
159
|
-
|
|
160
|
-
- [ ] <first option — a short line>
|
|
161
|
-
- <impact>
|
|
162
|
-
- <impact>
|
|
163
|
-
- [ ] <second option — a short line>
|
|
164
|
-
- <impact>
|
|
165
|
-
- [ ] <third option — a short line>
|
|
166
|
-
- <impact>
|
|
167
|
-
- <impact>
|
|
168
|
-
- <impact>
|
|
169
|
-
- [ ] _your answer_
|
|
170
|
-
|
|
171
|
-
- Never tick a box yourself — the human ticks exactly one per question`
|
|
172
|
-
|
|
173
|
-
export const questionBarReturn = `- This lap continues the same goal as the first: close the gap
|
|
174
|
-
between what the human wants and what gets built. Folding in
|
|
175
|
-
answers and deciding what's left is that same goal continued, not
|
|
176
|
-
a different job
|
|
177
|
-
- The human answered — a ticked box, a free-text answer in place of
|
|
178
|
-
\`_your answer_\`, a deleted question, or a deleted \`## Open Questions\`
|
|
179
|
-
section are all answers. Fold each resolved answer into its concern's
|
|
180
|
-
prose, then move the question into \`## Answered Questions\` as
|
|
181
|
-
\`### <question>\` with the resolved answer in plain prose — no
|
|
182
|
-
checkboxes
|
|
183
|
-
- \`## Answered Questions\` is always the last \`##\` section — a moved
|
|
184
|
-
question lands there, never wherever \`## Open Questions\` used to sit
|
|
185
|
-
- Never re-raise a deleted question. A settled \`## Answered Questions\`
|
|
186
|
-
entry stays settled, except one carrying a human footnote on its
|
|
187
|
-
\`### \` heading: that is the only entry that may change. Fold the note
|
|
188
|
-
in, then either rewrite the recorded answer in place (still under
|
|
189
|
-
\`## Answered Questions\`) or, when the note leaves the point genuinely
|
|
190
|
-
open, move it back to \`## Open Questions\` as a fresh fork with
|
|
191
|
-
options and the \`_your answer_\` slot. A note that only asks a
|
|
192
|
-
question follows the footnote rule: one \`- A:\` reply, answer unchanged
|
|
193
|
-
- An answer may earn a follow-up: if it opens a genuinely new fork above
|
|
194
|
-
the bar — one the answer itself created — raise it as a fresh \`##
|
|
195
|
-
Open Questions\` entry on this same lap. Never restate a question
|
|
196
|
-
already asked, and never treat this as licence to re-open a question
|
|
197
|
-
already settled under \`## Answered Questions\` that carries no
|
|
198
|
-
footnote on its heading
|
|
199
|
-
- Recognise a silent lap from \`## Open Questions\` still present with
|
|
200
|
-
nothing ticked and nothing else changed — the human's way of saying
|
|
201
|
-
the gap is already closed. That lap ends the questions, whatever the
|
|
202
|
-
goal says: decide every remaining question yourself, move each to
|
|
203
|
-
\`## Answered Questions\` with a one-line rationale, raise nothing new,
|
|
204
|
-
and leave no \`## Open Questions\` section behind`
|
|
205
|
-
|
|
206
|
-
export const fixFeedbackPrompt = `- The only state file this turn writes is \`.gtd/FEEDBACK.md\` — no other
|
|
207
|
-
files for notes or output
|
|
208
|
-
- Read \`.gtd/FEEDBACK.md\` (the failing test output) and fix the code so
|
|
209
|
-
the suite passes
|
|
210
|
-
- When \`.gtd/ESCALATION.md\` is present, it is a human-reviewed analysis
|
|
211
|
-
of why earlier attempts failed — read it and treat it as the primary
|
|
212
|
-
instruction for this turn. Never edit or delete it yourself, even once
|
|
213
|
-
you believe you've resolved it: only a genuinely green check retires
|
|
214
|
-
it, so an attempt that turns out to be wrong still leaves the next
|
|
215
|
-
turn's instruction in place. Its absence is the ordinary case: an
|
|
216
|
-
unremarkable red round with nothing to escalate yet
|
|
217
|
-
- Delete \`.gtd/FEEDBACK.md\` either way — once the suite passes, or once
|
|
218
|
-
you have established the feedback was wrong; leaving it in place is
|
|
219
|
-
never the right end state, the next check writes its own`
|
|
220
|
-
|
|
221
|
-
export const footnoteRules = `- Leave a footnote anywhere: mark the exact spot with \`[^name]\` (any
|
|
222
|
-
name, no whitespace or \`]\`), then define it below as \`[^name]:
|
|
223
|
-
explain what you mean\` — indent continuation lines by 4 spaces or
|
|
224
|
-
more. (A newly seeded definition starts with an empty body — a
|
|
225
|
-
definition whose body is still empty or whitespace-only is flagged
|
|
226
|
-
as unfilled, so write your own words there; words left under-indented
|
|
227
|
-
are flagged separately, naming the indent as the fix)
|
|
228
|
-
- A footnote is a comment on that exact spot — the hunk, line, or
|
|
229
|
-
paragraph it marks — never a whole-file remark
|
|
230
|
-
- \`name\` is yours to pick; only a definition's name must be unique in
|
|
231
|
-
this document — the same name may mark more than one spot
|
|
232
|
-
- To start a conversation, open the definition with a list: \`[^name]:\`
|
|
233
|
-
then an indented \`- H: <your question>\`. The agent answers with
|
|
234
|
-
\`- A: <reply>\`. Reply with a new \`- H:\` entry to continue; to
|
|
235
|
-
close the thread, reply with a conclusion (the agent folds it in and
|
|
236
|
-
deletes the thread) or delete the thread yourself. Entries alternate
|
|
237
|
-
\`H:\`/\`A:\` and the agent never starts a thread
|
|
238
|
-
- While a thread's last entry is the agent's, it is open and moving on
|
|
239
|
-
is refused: reply with a conclusion, or delete it
|
|
240
|
-
- The same conversation works as \`// H: <question>\` comment lines in a
|
|
241
|
-
file changed in this process (\`#\`, \`--\` or \`;\` by language); the phone UI does not show them,
|
|
242
|
-
and \`gtd check --open-threads\` lists the open ones`
|
|
243
|
-
|
|
244
|
-
export const footnoteAnchor = `- A footnote (\`[^name]\` plus its \`[^name]:\` definition) is a comment on
|
|
245
|
-
its exact anchor — fold it in as a mandatory concern described
|
|
246
|
-
against that anchor's hunk or paragraph, never flattened into a
|
|
247
|
-
whole-file remark
|
|
248
|
-
`
|
|
249
|
-
|
|
250
|
-
export const footnoteFoldIn = `${footnoteAnchor}- A one-shot footnote needs no reply: fold it in and DELETE it in this
|
|
251
|
-
same turn — marker and definition together. Never re-read a footnote
|
|
252
|
-
already acted on. A one-shot footnote that asks a question becomes a
|
|
253
|
-
thread instead: rewrite its definition as \`- H: <its body>\` then
|
|
254
|
-
\`- A: <your reply>\`, keeping the marker
|
|
255
|
-
- A thread is a definition whose body is a list of \`- H:\`/\`- A:\`
|
|
256
|
-
entries. Handle each by its last entry:
|
|
257
|
-
- last is \`- H:\` and asks something — reply with exactly one
|
|
258
|
-
\`- A: <reply>\` entry and change nothing else for it
|
|
259
|
-
- last concludes or advises — fold it in like a one-shot footnote,
|
|
260
|
-
then delete marker and definition
|
|
261
|
-
- last is \`- A:\` — it waits on the human; leave it alone
|
|
262
|
-
- Never start a thread yourself, and never leave a thread whose last
|
|
263
|
-
entry is \`- H:\` — a turn that does is refused`
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
@inmem
|
|
2
|
-
Feature: a red check is re-run once before it reaches a person
|
|
3
|
-
|
|
4
|
-
Before the fix loop escalates, `healthy` re-runs the suite as
|
|
5
|
-
`health.recheck`. Green there ends the loop as if the check had passed, and
|
|
6
|
-
the re-check's landing records `Gtd-Mark: flaky=health.check`. Red again
|
|
7
|
-
escalates as before.
|
|
8
|
-
|
|
9
|
-
Background:
|
|
10
|
-
Given a gtd config with:
|
|
11
|
-
"""
|
|
12
|
-
import { healthy } from "@pmelab/gtd/workflows"
|
|
13
|
-
import { agent, human } from "@pmelab/gtd/flows"
|
|
14
|
-
|
|
15
|
-
export const held = async () => {
|
|
16
|
-
await agent("first", "go")
|
|
17
|
-
await healthy(() => agent("fix", "go"))
|
|
18
|
-
await human("done")
|
|
19
|
-
}
|
|
20
|
-
export default held
|
|
21
|
-
"""
|
|
22
|
-
And step "first" writes "src/a.ts" with:
|
|
23
|
-
"""
|
|
24
|
-
export const a = 1
|
|
25
|
-
"""
|
|
26
|
-
And step "health.check" writes ".gtd/FEEDBACK.md" with:
|
|
27
|
-
"""
|
|
28
|
-
1 test failing
|
|
29
|
-
"""
|
|
30
|
-
And step "fix" deletes ".gtd/FEEDBACK.md"
|
|
31
|
-
And judge step "health.judge" answers:
|
|
32
|
-
"""
|
|
33
|
-
[{"id":"verdict","answer":"progress","p":0.9}]
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
Scenario: a re-check that passes ends the loop without a person, recorded as flaky
|
|
37
|
-
Given step "health.recheck" deletes ".gtd/FEEDBACK.md"
|
|
38
|
-
When gtd starts workflow "held"
|
|
39
|
-
And the process is driven
|
|
40
|
-
Then the process rests at "done"
|
|
41
|
-
And the commit subjects end with:
|
|
42
|
-
"""
|
|
43
|
-
gtd(agent): fix → health.check
|
|
44
|
-
gtd(check): health.check → health.judge
|
|
45
|
-
gtd(judge): health.judge → health.recheck
|
|
46
|
-
gtd(check): health.recheck → done
|
|
47
|
-
"""
|
|
48
|
-
And the last commit body contains "Gtd-Mark: flaky=health.check"
|
|
49
|
-
And ".gtd/FEEDBACK.md" does not exist
|
|
50
|
-
|
|
51
|
-
Scenario: a re-check that stays red escalates, with nothing recorded as flaky
|
|
52
|
-
Given step "health.recheck" writes ".gtd/FEEDBACK.md" with:
|
|
53
|
-
"""
|
|
54
|
-
1 test still failing
|
|
55
|
-
"""
|
|
56
|
-
When gtd starts workflow "held"
|
|
57
|
-
And the process is driven
|
|
58
|
-
Then the process rests at "health.describe"
|
|
59
|
-
And the last commit subject is "gtd(check): health.recheck → health.describe"
|
|
60
|
-
And no commit body contains "Gtd-Mark: flaky="
|