@pmelab/gtd 12.5.0 → 14.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.
@@ -0,0 +1,128 @@
1
+ import {
2
+ changes,
3
+ head,
4
+ human,
5
+ refuse,
6
+ requireRevert,
7
+ restoreScript,
8
+ revertScript,
9
+ run,
10
+ start,
11
+ type EntryBase,
12
+ type FlowArgs,
13
+ type Summary,
14
+ } from "../flows/index.js"
15
+ import { baseline, gate } from "./health.js"
16
+ import { packages } from "./packages.js"
17
+ import { architecturePass, design } from "./planning.js"
18
+ import { buildTail, type ReviewOutcome } from "./review.js"
19
+ import { ARCHITECTURE, FEEDBACK, REQUIREMENTS, REVIEW } from "./steps.js"
20
+ import * as t from "./text.js"
21
+
22
+ // gtd's built-in default workflow. Any change to the tree starts a process:
23
+ // `idle` → `unwind` reverts the sketch (its intent survives in history) → a
24
+ // green-baseline gate → design, architecture and one package per concern →
25
+ // the quality lap → human review, which signs off (the episode ends back at
26
+ // `idle`) or sends a full re-plan lap. `--entry fix-precheck`, `--entry
27
+ // review-gate.check --var reviewBase=<commitish>` and `--entry
28
+ // start-gate.check` enter the same flow further in.
29
+ //
30
+ // Every part is exported for other workflows to compose; see the modules
31
+ // re-exported below.
32
+
33
+ export { defaults } from "./vars.js"
34
+ export * from "./steps.js"
35
+ export * from "./health.js"
36
+ export * from "./planning.js"
37
+ export * from "./packages.js"
38
+ export * from "./review.js"
39
+
40
+ /** Revert the sketch that started the process out of the working tree; its intent survives in history. */
41
+ export const unwind = (): Promise<void> => {
42
+ const commit = head()
43
+ return run("unwind", revertScript(commit, FEEDBACK, t.unwindFailure(commit)), {
44
+ label: "Unwinding your input",
45
+ })
46
+ }
47
+
48
+ /**
49
+ * Undo the human's review-round code edits. A path changed since the human
50
+ * left it is not overwritten; requireRevert names it instead.
51
+ */
52
+ export const reUnwind = async (
53
+ feedback: Extract<ReviewOutcome, { verdict: "feedback" }>,
54
+ ): Promise<void> => {
55
+ const { base, edited } = feedback
56
+ const restore = edited.filter((c) => c.status !== "added").map((c) => c.path)
57
+ const remove = edited.filter((c) => c.status === "added").map((c) => c.path)
58
+ await run("re-unwind", restoreScript(base, { restore, remove }), {
59
+ label: "Re-unwinding your review edit",
60
+ file: REVIEW,
61
+ base,
62
+ })
63
+ requireRevert(edited, base)
64
+ }
65
+
66
+ /** Plan, build and review until a review round signs off; feedback re-plans from scratch. */
67
+ export const planAndBuild = async (firstBase: string): Promise<void> => {
68
+ let base = firstBase
69
+ for (;;) {
70
+ await design(base)
71
+ await architecturePass()
72
+ await packages()
73
+ const outcome = await buildTail(false, base)
74
+ if (outcome.verdict === "signoff") return
75
+ await reUnwind(outcome)
76
+ base = outcome.base
77
+ }
78
+ }
79
+
80
+ /** After a tail that skipped planning: stop on sign-off, re-plan on feedback. */
81
+ export const afterTail = async (outcome: ReviewOutcome): Promise<void> => {
82
+ if (outcome.verdict === "signoff") return
83
+ await reUnwind(outcome)
84
+ await planAndBuild(outcome.base)
85
+ }
86
+
87
+ /** An ordinary start: wait at `idle`, unwind the sketch, check the baseline, then plan and build. */
88
+ export const ordinaryStart = async (): Promise<void> => {
89
+ await human("idle", { message: t.idleMessage(), label: "Idle", file: ".gtd/TODO.md" })
90
+ await unwind()
91
+ if (changes(FEEDBACK).some((c) => c.status !== "deleted")) {
92
+ await human("unwind-failed", {
93
+ message: t.unwindFailedMessage(),
94
+ label: "Could not unwind your input",
95
+ file: FEEDBACK,
96
+ })
97
+ }
98
+ await gate("start-gate", t.startGateBlockedMessage())
99
+ await planAndBuild(start())
100
+ }
101
+
102
+ const ENTRIES = ["fix-precheck", "review-gate.check", "start-gate.check"]
103
+
104
+ export default async function unified({ entry }: FlowArgs): Promise<void> {
105
+ if (entry === undefined) return ordinaryStart()
106
+ if (entry === "fix-precheck") {
107
+ if (await baseline("fix-precheck")) return
108
+ return afterTail(await buildTail(true, start()))
109
+ }
110
+ if (entry === "review-gate.check") {
111
+ await gate("review-gate", t.reviewGateBlockedMessage())
112
+ return afterTail(await buildTail(false, start()))
113
+ }
114
+ if (entry === "start-gate.check") {
115
+ await gate("start-gate", t.startGateBlockedMessage())
116
+ return planAndBuild(start())
117
+ }
118
+ refuse(
119
+ `"${entry}" is not an enterable state — enterable states:\n${ENTRIES.map((name) => ` ${name}`).join("\n")}`,
120
+ )
121
+ }
122
+
123
+ export const summary: Summary = t.summaryPrompt
124
+
125
+ export const steering = { [REQUIREMENTS]: "qa", [ARCHITECTURE]: "qa", [REVIEW]: "review" }
126
+
127
+ export const base: EntryBase = (entry, vars) =>
128
+ entry === "review-gate.check" ? (vars.reviewBase ?? "") : undefined
@@ -0,0 +1,23 @@
1
+ // The bundled workflow's variable defaults. `.gtdrc` `vars:`, `--var` and
2
+ // `GTD_<NAME>` override any of them.
3
+ export const defaults: Readonly<Record<string, string>> = {
4
+ testCommand: "npm test",
5
+ plannerModel: "smart",
6
+ coderModel: "base",
7
+ reviewBase: "",
8
+ judgeBudgetBytes: "32768",
9
+ judgeIdenticalMinP: "0.7",
10
+ specPreJudge: "0.9",
11
+ reviewNoteActionable: "0.7",
12
+ architectureSkipMinP: "0.85",
13
+ triageSkills: "spec-driven-development, planning-and-task-breakdown",
14
+ architectureSkills: "api-and-interface-design, documentation-and-adrs",
15
+ decomposeSkills: "incremental-implementation, planning-and-task-breakdown",
16
+ buildSkills: "test-driven-development, incremental-implementation",
17
+ fixSkills: "debugging-and-error-recovery",
18
+ reviewFixSkills: "incremental-implementation, code-simplification",
19
+ reviewSkills: "code-review-and-quality",
20
+ specReviewSkills: "code-review-and-quality, spec-driven-development",
21
+ escalateSkills: "debugging-and-error-recovery",
22
+ qualityReviews: "owasp-security, code-simplification",
23
+ }