@pmelab/gtd 52.1.0 → 53.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 +91 -129
- package/claude/hooks/drive.ts +0 -3
- package/claude/hooks/register.tsx +3 -68
- package/claude/hooks/ship.ts +85 -1595
- package/dist/chunks/{reserved-DxB5CROj.mjs → reserved-CQ7amcKG.mjs} +45 -132
- package/dist/chunks/{review-CKMSdvgW.mjs → review-CNgN_V8T.mjs} +2 -2
- package/dist/chunks/{tail-QZc7Uz2U.mjs → tail-JZ9PAOwp.mjs} +2 -14
- package/dist/chunks/{wire-BJuZWR3C.mjs → wire-C12dahrH.mjs} +2 -130
- package/dist/flows.mjs +1 -16
- package/dist/gtd.bundle.mjs +476 -982
- package/dist/testkit.mjs +58 -417
- package/dist/wire.mjs +2 -2
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +112 -363
- package/dist/workflows/fix.mjs +2 -2
- package/dist/workflows/review.mjs +3 -3
- package/dist/workflows/rollout.mjs +1 -1
- package/dist/workflows.mjs +311 -674
- package/package.json +1 -1
- package/src/cli/Cli.test.ts +1 -86
- package/src/cli/Cli.ts +13 -133
- package/src/cli/Metrics.test.ts +21 -31
- package/src/cli/Metrics.ts +25 -36
- package/src/cli/Program.test.ts +1 -35
- package/src/cli/Program.ts +5 -64
- package/src/cli/ToolCommands.ts +0 -3
- package/src/edge/Edge.test.ts +20 -322
- package/src/edge/Edge.ts +10 -181
- package/src/edge/index.ts +0 -1
- package/src/flows/runtime.test.ts +0 -27
- package/src/flows/runtime.ts +1 -49
- package/src/install/Install.ts +15 -24
- package/src/replay/Replay.test.ts +0 -169
- package/src/replay/Replay.ts +4 -93
- package/src/replay/index.ts +0 -1
- package/src/testkit/Layers.ts +0 -1
- package/src/wire/BeatDocument.ts +2 -12
- package/src/wire/BeatStatus.ts +0 -3
- package/src/wire/WireSchema.test.ts +0 -18
- package/src/wire/index.ts +0 -2
- package/src/wire/types.ts +0 -7
- package/src/workflow/Workflow.ts +1 -9
- package/src/workflows/feature/criteria.test.ts +1 -14
- package/src/workflows/feature/criteria.ts +6 -38
- package/src/workflows/feature/feature.ts +34 -118
- package/src/workflows/feature/hands-on-skip.feature +2 -70
- package/src/workflows/feature/index.ts +0 -1
- package/src/workflows/feature/one-step-land.feature +0 -4
- package/src/workflows/feature/prototype-rounds.feature +1 -1
- package/src/workflows/feature/prototype.feature +3 -3
- package/src/workflows/feature/prototype.ts +18 -29
- package/src/workflows/feature/refactor-absorbs.feature +3 -8
- package/src/workflows/feature/refactor-first.feature +0 -5
- package/src/workflows/feature/refactor-rebuild.feature +0 -6
- package/src/workflows/feature/refactor-review.feature +11 -11
- package/src/workflows/feature/refactor.ts +30 -64
- package/src/workflows/feature/review-gate.feature +1 -1
- package/src/workflows/feature/seam-rejection.feature +0 -4
- package/src/workflows/feature/seam.test.ts +7 -26
- package/src/workflows/feature/seam.ts +52 -165
- package/src/workflows/index.ts +0 -1
- package/src/workflows/shared/lenses.ts +0 -13
- package/src/workflows/shared/options.test.ts +2 -11
- package/src/workflows/shared/options.ts +4 -21
- package/src/workflows/shared/review.test.ts +3 -3
- package/src/workflows/shared/steps.ts +0 -2
- package/src/workflows/shared/text.test.ts +10 -80
- package/src/workflows/shared/text.ts +35 -211
- package/src/workflows/shared/vars.ts +2 -8
- package/src/workflows/shared/workflows.steps.ts +0 -13
- package/claude/hooks/context.ts +0 -66
- package/src/replay/Slices.test.ts +0 -73
- package/src/replay/Slices.ts +0 -45
- package/src/wire/ContextLimit.fixture.ts +0 -30
- package/src/wire/ContextLimit.test.ts +0 -96
- package/src/wire/ContextLimit.ts +0 -169
- package/src/wire/Slices.ts +0 -25
- package/src/wire/golden/1/slices.json +0 -11
- package/src/workflows/feature/context-limit.feature +0 -37
- package/src/workflows/feature/continuation-cap.feature +0 -69
- package/src/workflows/feature/continuation-rebuild.feature +0 -92
- package/src/workflows/feature/continuation-slices.feature +0 -68
- package/src/workflows/feature/continuation.feature +0 -209
- package/src/workflows/feature/slice-findings.feature +0 -256
- package/src/workflows/feature/slicing-cap.feature +0 -23
- package/src/workflows/feature/slicing.feature +0 -297
- package/src/workflows/feature/slicing.test.ts +0 -49
- package/src/workflows/feature/slicing.ts +0 -105
- package/src/workflows/shared/continuation.ts +0 -92
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Feature: a refactor that carried the whole feature still gets a quality lap over all of it
|
|
4
4
|
|
|
5
5
|
With GTD_FLAG_RISK_TIER off, a refactor-first
|
|
6
|
-
refactor can land everything the requirements ask for. The feature
|
|
6
|
+
refactor can land everything the requirements ask for. The feature's
|
|
7
7
|
implement turn then has only the naive pass's acceptance tests to carry
|
|
8
|
-
over, and with no code but tests changed since the refactor the feature
|
|
9
|
-
|
|
8
|
+
over, and with no code but tests changed since the refactor the feature's
|
|
9
|
+
quality lap covers the whole change, refactor included.
|
|
10
10
|
|
|
11
11
|
Background:
|
|
12
12
|
Given the shipped workflows, as gtd install scaffolds them
|
|
@@ -132,8 +132,3 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
|
|
|
132
132
|
gtd(check): implement.closing → build.quality.correctness.reviewing
|
|
133
133
|
gtd(agent): build.quality.correctness.reviewing → build.review.reviewing
|
|
134
134
|
"""
|
|
135
|
-
And the output lines of gtd "slices" start with:
|
|
136
|
-
"""
|
|
137
|
-
refactor
|
|
138
|
-
feature
|
|
139
|
-
"""
|
|
@@ -160,9 +160,4 @@ Feature: a refactor-first judgment walks one fixed path to the review gate
|
|
|
160
160
|
And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
|
|
161
161
|
And the commit "gtd(judge): seam.judge → seam.note" has a body containing "\"answer\":\"refactor-first\""
|
|
162
162
|
And no commit body contains "Gtd-Approved:"
|
|
163
|
-
And the output lines of gtd "slices" start with:
|
|
164
|
-
"""
|
|
165
|
-
refactor
|
|
166
|
-
feature
|
|
167
|
-
"""
|
|
168
163
|
And no commit body contains "Gtd-Workflow:"
|
|
@@ -197,7 +197,6 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
|
|
|
197
197
|
Then the process rests at "implement.building"
|
|
198
198
|
And "src/calc.ts" contains "op(a, b, 1)"
|
|
199
199
|
And "src/calc.ts" does not contain "subtract"
|
|
200
|
-
And the output of gtd "slices" contains "refactor "
|
|
201
200
|
|
|
202
201
|
Scenario: the rebuild lands only once it carries the naive pass's acceptance tests, green
|
|
203
202
|
Given step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
@@ -285,8 +284,3 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
|
|
|
285
284
|
gtd(check): implement.health.check → implement.closing
|
|
286
285
|
gtd(check): implement.closing → build.review.reviewing
|
|
287
286
|
"""
|
|
288
|
-
And the output lines of gtd "slices" start with:
|
|
289
|
-
"""
|
|
290
|
-
refactor
|
|
291
|
-
feature
|
|
292
|
-
"""
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
@inmem
|
|
2
|
-
Feature: the refactor
|
|
2
|
+
Feature: the refactor is reviewed on its own before the feature is implemented
|
|
3
3
|
|
|
4
4
|
After a refactor-first judgment the refactor is built, quality-lapped and
|
|
5
|
-
reviewed
|
|
6
|
-
the feature
|
|
5
|
+
reviewed on its own. Review edits re-run the refactor, never the design;
|
|
6
|
+
the feature that follows is quality-lapped from the refactor's
|
|
7
7
|
sign-off, then reviewed. The flags are pinned so the per-flag test runs never move it off
|
|
8
8
|
its path.
|
|
9
9
|
|
|
@@ -614,7 +614,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
614
614
|
And ".gtd/REFACTOR.md" does not exist
|
|
615
615
|
And ".gtd/REVIEW.md" contains "A: add and subtract differ only by sign."
|
|
616
616
|
|
|
617
|
-
Scenario: a no-change landing after the in-gate reply signs off and the feature
|
|
617
|
+
Scenario: a no-change landing after the in-gate reply signs off and the feature follows
|
|
618
618
|
Given step "implement.building" writes "src/calc.ts" with:
|
|
619
619
|
"""
|
|
620
620
|
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
@@ -697,7 +697,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
697
697
|
Then the process rests at "build.review.reviewing"
|
|
698
698
|
And "src/calc.ts" contains "subtract"
|
|
699
699
|
|
|
700
|
-
Scenario: a praise-only one-shot footnote signs off and the feature
|
|
700
|
+
Scenario: a praise-only one-shot footnote signs off and the feature follows
|
|
701
701
|
Given step "implement.building" writes "src/calc.ts" with:
|
|
702
702
|
"""
|
|
703
703
|
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
@@ -979,7 +979,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
979
979
|
Then driving the process is refused with "refactor-feedback"
|
|
980
980
|
And driving the process is refused with "hand-edited src/calc.ts"
|
|
981
981
|
|
|
982
|
-
Scenario: a praise note and a concluded thread on a settled round sign off and the feature
|
|
982
|
+
Scenario: a praise note and a concluded thread on a settled round sign off and the feature follows
|
|
983
983
|
Given step "implement.building" writes "src/calc.ts" with:
|
|
984
984
|
"""
|
|
985
985
|
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
@@ -1066,7 +1066,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1066
1066
|
Then the process rests at "build.review.reviewing"
|
|
1067
1067
|
And "src/calc.ts" contains "subtract"
|
|
1068
1068
|
|
|
1069
|
-
Scenario: a praise-only refactor review still signs off and the feature
|
|
1069
|
+
Scenario: a praise-only refactor review still signs off and the feature follows
|
|
1070
1070
|
Given step "implement.building" writes "src/calc.ts" with:
|
|
1071
1071
|
"""
|
|
1072
1072
|
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
@@ -1099,7 +1099,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1099
1099
|
Then the process rests at "build.review.reviewing"
|
|
1100
1100
|
And "src/calc.ts" contains "subtract"
|
|
1101
1101
|
|
|
1102
|
-
Scenario: a nit fix in the refactor
|
|
1102
|
+
Scenario: a nit fix in the refactor that changes a non-stray is refused, though a glob stray widens the write access
|
|
1103
1103
|
Given step "seam.naive" writes "src/*.ts" with:
|
|
1104
1104
|
"""
|
|
1105
1105
|
export const literalGlobName = 2
|
|
@@ -1130,7 +1130,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1130
1130
|
When gtd lands
|
|
1131
1131
|
Then driving the process is refused with "refactor-scope"
|
|
1132
1132
|
|
|
1133
|
-
Scenario: the nit-fix turn in the refactor
|
|
1133
|
+
Scenario: the nit-fix turn in the refactor may write the strays and .gtd/** only
|
|
1134
1134
|
Given step "seam.naive" writes "src/*.ts" with:
|
|
1135
1135
|
"""
|
|
1136
1136
|
export const literalGlobName = 2
|
|
@@ -1185,7 +1185,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1185
1185
|
"""
|
|
1186
1186
|
And no commit body contains "refactor.build.review.composing"
|
|
1187
1187
|
|
|
1188
|
-
Rule: with a quality lens on both
|
|
1188
|
+
Rule: with a quality lens on both the refactor and the feature
|
|
1189
1189
|
|
|
1190
1190
|
Background:
|
|
1191
1191
|
Given an environment variable "GTD_REFACTORQUALITYREVIEWS" set to "correctness"
|
|
@@ -1275,7 +1275,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1275
1275
|
"""
|
|
1276
1276
|
And step "refactor.build.review.closing" runs its script
|
|
1277
1277
|
|
|
1278
|
-
Scenario:
|
|
1278
|
+
Scenario: the refactor's and the feature's quality laps each review from their own base
|
|
1279
1279
|
When the process is driven
|
|
1280
1280
|
Then the process rests at "refactor.build.quality.correctness.reviewing"
|
|
1281
1281
|
And the resting step's content contains the hash of the commit "gtd(agent): seam.note → refactor.deriving"
|
|
@@ -15,9 +15,8 @@ import {
|
|
|
15
15
|
} from "../../flows/index.js"
|
|
16
16
|
import { lensEntriesOf } from "../../workflow-kit/index.js"
|
|
17
17
|
import { markFenced } from "../shared/fences.js"
|
|
18
|
-
import { continuing, phase, type Phase } from "../shared/continuation.js"
|
|
19
18
|
import { healthy, type Guard } from "../shared/health.js"
|
|
20
|
-
import { coder, FEEDBACK,
|
|
19
|
+
import { coder, FEEDBACK, REFACTOR } from "../shared/steps.js"
|
|
21
20
|
import * as t from "../shared/text.js"
|
|
22
21
|
import { defaults, testFileGlobs } from "../shared/vars.js"
|
|
23
22
|
import { buildTail, reUnwind, type FeedbackTarget } from "../shared/review.js"
|
|
@@ -264,12 +263,7 @@ const guardOf =
|
|
|
264
263
|
}
|
|
265
264
|
|
|
266
265
|
/** Derive, build, check and close one refactor lap; `feedback` is the collected review text of the lap before. */
|
|
267
|
-
const refactorLap = async (
|
|
268
|
-
p: Plan,
|
|
269
|
-
guard: Guard,
|
|
270
|
-
refactor: Phase,
|
|
271
|
-
feedback?: string,
|
|
272
|
-
): Promise<void> => {
|
|
266
|
+
const refactorLap = async (p: Plan, guard: Guard, feedback?: string): Promise<void> => {
|
|
273
267
|
const { pattern, strays, reference, note } = p
|
|
274
268
|
await run(
|
|
275
269
|
"deriving",
|
|
@@ -282,59 +276,32 @@ const refactorLap = async (
|
|
|
282
276
|
]),
|
|
283
277
|
{ label: "Deriving the refactor package", file: REFACTOR_PACKAGE },
|
|
284
278
|
)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// The building turns' own changes only: a fix turn reaching a path is not the refactor reaching it.
|
|
312
|
-
for (const c of changes()) reached.add(c.path)
|
|
313
|
-
await healthy(
|
|
314
|
-
async () => {
|
|
315
|
-
await t.agentWithSkills("fix.suite.fixing", t.refactorFixPrompt(strays, pattern), {
|
|
316
|
-
label: "Fixing the check",
|
|
317
|
-
file: FEEDBACK,
|
|
318
|
-
model: coder(),
|
|
319
|
-
system: t.builderSystem(),
|
|
320
|
-
})
|
|
321
|
-
guard()
|
|
322
|
-
},
|
|
323
|
-
{ describeGuard: guard, rules: t.refactorRules(strays, pattern) },
|
|
324
|
-
)
|
|
325
|
-
if (left === undefined) return { result: undefined }
|
|
326
|
-
return {
|
|
327
|
-
result: undefined,
|
|
328
|
-
handoff: {
|
|
329
|
-
snapshot,
|
|
330
|
-
note: left.trim(),
|
|
331
|
-
open: strays.filter((path) => !reached.has(path)),
|
|
332
|
-
},
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
await run("closing", removeScript([REFACTOR_PACKAGE, HANDOFF]), {
|
|
336
|
-
label: "Closing out the refactor",
|
|
337
|
-
})
|
|
279
|
+
await t.agentWithSkills(
|
|
280
|
+
"building",
|
|
281
|
+
t.refactorBuildingPrompt({
|
|
282
|
+
pkg: REFACTOR_PACKAGE,
|
|
283
|
+
strays,
|
|
284
|
+
pattern,
|
|
285
|
+
reference,
|
|
286
|
+
feedback: feedback !== undefined,
|
|
287
|
+
note: note !== undefined,
|
|
288
|
+
}),
|
|
289
|
+
{ label: "Refactoring", model: coder(), system: t.builderSystem() },
|
|
290
|
+
)
|
|
291
|
+
guard()
|
|
292
|
+
await healthy(
|
|
293
|
+
async () => {
|
|
294
|
+
await t.agentWithSkills("fix.suite.fixing", t.refactorFixPrompt(strays, pattern), {
|
|
295
|
+
label: "Fixing the check",
|
|
296
|
+
file: FEEDBACK,
|
|
297
|
+
model: coder(),
|
|
298
|
+
system: t.builderSystem(),
|
|
299
|
+
})
|
|
300
|
+
guard()
|
|
301
|
+
},
|
|
302
|
+
{ describeGuard: guard, rules: t.refactorRules(strays, pattern) },
|
|
303
|
+
)
|
|
304
|
+
await run("closing", removeScript([REFACTOR_PACKAGE]), { label: "Closing out the refactor" })
|
|
338
305
|
}
|
|
339
306
|
|
|
340
307
|
const strayAccess = (strays: readonly string[]) => ({
|
|
@@ -348,7 +315,7 @@ export const refactorFirst = async (
|
|
|
348
315
|
const p = plan(shape, options)
|
|
349
316
|
if (p === undefined) return false
|
|
350
317
|
return scope({ name: "refactor", access: strayAccess(p.strays) }, async () => {
|
|
351
|
-
await refactorLap(p, guardOf(p, head())
|
|
318
|
+
await refactorLap(p, guardOf(p, head()))
|
|
352
319
|
return true
|
|
353
320
|
})
|
|
354
321
|
}
|
|
@@ -375,10 +342,9 @@ export const reviewedRefactor = async (
|
|
|
375
342
|
"gtd land: refactor-feedback: the review feedback changed files but wrote no .gtd/REFACTOR.md — a refactor cannot act on it; revert the change, or `gtd abandon` and restart",
|
|
376
343
|
dropped: t.refactorDroppedRefusal,
|
|
377
344
|
}
|
|
378
|
-
const refactor = phase("refactor")
|
|
379
345
|
let collected: string | undefined
|
|
380
346
|
for (;;) {
|
|
381
|
-
await refactorLap(p, guard,
|
|
347
|
+
await refactorLap(p, guard, collected)
|
|
382
348
|
// A person's edit at an escalation rest is never refused, as in the lap.
|
|
383
349
|
const outcome = await buildTail(entry, {
|
|
384
350
|
green: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@inmem
|
|
2
2
|
Feature: a feature process ends at the human review
|
|
3
3
|
|
|
4
|
-
After the
|
|
4
|
+
After the quality lap the process rests at the review gate,
|
|
5
5
|
`.gtd/REVIEW.md`. A sign-off ends the process. A note asking for a change in
|
|
6
6
|
behaviour starts a feedback lap — design, then implement with no new naive
|
|
7
7
|
pass or seam judge, the hands-on test, the quality lap — and the review
|
|
@@ -136,8 +136,4 @@ Feature: rejected naive passes walk one fixed path through the steer gate to the
|
|
|
136
136
|
And the commit "gtd(judge): seam.judge → seam.steer" has a body containing "\"answer\":\"reject\""
|
|
137
137
|
And the commit "gtd(judge): seam.judge → implement.applying" has a body containing "\"answer\":\"land\""
|
|
138
138
|
And no commit body contains "Gtd-Approved:"
|
|
139
|
-
And the output lines of gtd "slices" start with:
|
|
140
|
-
"""
|
|
141
|
-
feature
|
|
142
|
-
"""
|
|
143
139
|
And no commit body contains "Gtd-Workflow:"
|
|
@@ -311,9 +311,6 @@ const reviewDoc = [
|
|
|
311
311
|
|
|
312
312
|
interface Seamed {
|
|
313
313
|
readonly names: string[]
|
|
314
|
-
readonly slices: string[]
|
|
315
|
-
/** Slice names entered, with the steps seen while inside each. */
|
|
316
|
-
readonly inside: Record<string, string[]>
|
|
317
314
|
readonly outcome: SeamOutcome | Error
|
|
318
315
|
}
|
|
319
316
|
|
|
@@ -327,10 +324,7 @@ const driveSeam = async (
|
|
|
327
324
|
let red = false
|
|
328
325
|
let redsLeft = reds
|
|
329
326
|
const names: string[] = []
|
|
330
|
-
const slices: string[] = []
|
|
331
|
-
const inside: Record<string, string[]> = {}
|
|
332
327
|
const stack: string[] = []
|
|
333
|
-
const open: string[] = []
|
|
334
328
|
const files = new Map<string, string>([["src/a.ts", "a"]])
|
|
335
329
|
let current = "c0"
|
|
336
330
|
const effects: Record<string, () => void> = {
|
|
@@ -351,12 +345,6 @@ const driveSeam = async (
|
|
|
351
345
|
},
|
|
352
346
|
pushScope: (scope: { name?: string }) => void stack.push(scope.name ?? ""),
|
|
353
347
|
popScope: () => void stack.pop(),
|
|
354
|
-
enterSlice: (name: string) => {
|
|
355
|
-
slices.push(name)
|
|
356
|
-
open.push(name)
|
|
357
|
-
inside[name] = []
|
|
358
|
-
},
|
|
359
|
-
leaveSlice: () => void open.pop(),
|
|
360
348
|
read: (path: string) => files.get(path),
|
|
361
349
|
head: () => current,
|
|
362
350
|
kept: () => tip(stray),
|
|
@@ -372,7 +360,6 @@ const driveSeam = async (
|
|
|
372
360
|
}
|
|
373
361
|
if (full === "seam.clear") files.delete(".gtd/FEEDBACK.md")
|
|
374
362
|
names.push(full)
|
|
375
|
-
for (const name of open) inside[name]!.push(full)
|
|
376
363
|
effects[request.name]?.()
|
|
377
364
|
if (request.kind === "judge")
|
|
378
365
|
return Promise.resolve({ answers: { shape: { answer, p: 0.9 } }, truncated: [] })
|
|
@@ -385,14 +372,13 @@ const driveSeam = async (
|
|
|
385
372
|
} catch (error) {
|
|
386
373
|
outcome = error as Error
|
|
387
374
|
}
|
|
388
|
-
return { names,
|
|
375
|
+
return { names, outcome }
|
|
389
376
|
}
|
|
390
377
|
|
|
391
378
|
describe("seamBuild", () => {
|
|
392
|
-
it("land resolves the kept tip to land, with the caller's base
|
|
379
|
+
it("land resolves the kept tip to land, with the caller's base", async () => {
|
|
393
380
|
const h = await driveSeam("land")
|
|
394
381
|
expect(h.outcome).toEqual({ reference: "abc", base: "c-base", land: true })
|
|
395
|
-
expect(h.slices).toEqual([])
|
|
396
382
|
expect(h.names).toEqual(["seam.naive", "seam.check", "seam.judge"])
|
|
397
383
|
})
|
|
398
384
|
|
|
@@ -432,7 +418,7 @@ describe("seamBuild", () => {
|
|
|
432
418
|
expect(h.outcome).toEqual({ reference: "abc", base: "c-base", land: true })
|
|
433
419
|
})
|
|
434
420
|
|
|
435
|
-
it("refactor-first runs the reviewed refactor
|
|
421
|
+
it("refactor-first runs the reviewed refactor right after the note and resolves HEAD after it", async () => {
|
|
436
422
|
const h = await driveSeam("refactor-first")
|
|
437
423
|
expect(h.outcome).toEqual({
|
|
438
424
|
reference: "abc",
|
|
@@ -440,16 +426,14 @@ describe("seamBuild", () => {
|
|
|
440
426
|
refactored: true,
|
|
441
427
|
rebuild: { note: "Seam: a shared op", acceptance: { hash: "abc", tests: [], ids: [] } },
|
|
442
428
|
})
|
|
443
|
-
expect(h.slices).toEqual(["refactor"])
|
|
444
429
|
expect(h.names.indexOf("seam.note")).toBe(h.names.indexOf("seam.judge") + 1)
|
|
445
|
-
expect(h.
|
|
446
|
-
expect(h.
|
|
447
|
-
expect(h.inside.refactor).toContain("refactor.build.review.closing")
|
|
430
|
+
expect(h.names.indexOf("refactor.deriving")).toBe(h.names.indexOf("seam.note") + 1)
|
|
431
|
+
expect(h.names).toContain("refactor.build.review.closing")
|
|
448
432
|
expect(h.names.some((n) => n.includes("approve"))).toBe(false)
|
|
449
433
|
expect(h.names.some((n) => n.startsWith("implement"))).toBe(false)
|
|
450
434
|
})
|
|
451
435
|
|
|
452
|
-
it("refactor-first with only test-file strays resolves the caller's base with no
|
|
436
|
+
it("refactor-first with only test-file strays resolves the caller's base with no refactor and no by-hand", async () => {
|
|
453
437
|
const h = await driveSeam("refactor-first", change("src/a.test.ts", "modified"), {
|
|
454
438
|
seamAllow: ".gtd/**",
|
|
455
439
|
})
|
|
@@ -458,7 +442,6 @@ describe("seamBuild", () => {
|
|
|
458
442
|
base: "c-base",
|
|
459
443
|
rebuild: { acceptance: { hash: "abc", tests: [], ids: [] } },
|
|
460
444
|
})
|
|
461
|
-
expect(h.slices).toEqual([])
|
|
462
445
|
expect(h.names).not.toContain("seam.by-hand")
|
|
463
446
|
expect(h.names.some((n) => n.startsWith("refactor"))).toBe(false)
|
|
464
447
|
})
|
|
@@ -469,18 +452,16 @@ describe("seamBuild", () => {
|
|
|
469
452
|
{ path: "src/a.test.ts", status: "modified", before: undefined, after: "b" },
|
|
470
453
|
{ seamAllow: ".gtd/**" },
|
|
471
454
|
)
|
|
472
|
-
expect(h.slices).toEqual([])
|
|
473
455
|
expect(h.names).toContain("seam.by-hand")
|
|
474
456
|
})
|
|
475
457
|
|
|
476
|
-
it("rests unreadable strays at seam.by-hand and
|
|
458
|
+
it("rests unreadable strays at seam.by-hand and runs no refactor", async () => {
|
|
477
459
|
const h = await driveSeam("refactor-first", {
|
|
478
460
|
path: "src/a.ts",
|
|
479
461
|
status: "modified",
|
|
480
462
|
before: undefined,
|
|
481
463
|
after: "b",
|
|
482
464
|
})
|
|
483
|
-
expect(h.slices).toEqual([])
|
|
484
465
|
expect(h.names).toContain("seam.by-hand")
|
|
485
466
|
expect(h.outcome).toEqual({
|
|
486
467
|
reference: "abc",
|