@pmelab/gtd 65.0.0 → 66.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 +3 -2
- package/claude/hooks/drive.ts +10 -1
- package/claude/hooks/git.ts +2 -2
- package/claude/hooks/pr.ts +80 -20
- package/claude/hooks/register.tsx +19 -4
- package/dist/chunks/{flows-DGs0W3HI.mjs → flows-CmQplvh1.mjs} +134 -40
- package/dist/chunks/{steering-DEh_MS40.mjs → steering-CMrePUiY.mjs} +115 -17
- package/dist/chunks/{testkit-CgrLmpdJ.mjs → testkit-BJhAAVGt.mjs} +179 -34
- package/dist/chunks/{wire-BNS8ciNu.mjs → wire-xTbzFc26.mjs} +7 -3
- package/dist/flows.mjs +1 -1
- package/dist/gtd.bundle.mjs +430 -100
- package/dist/gtd.core.mjs +147 -134
- package/dist/steering.mjs +1 -1
- package/dist/testkit/gherkin.mjs +1 -1
- package/dist/testkit.mjs +2 -2
- package/dist/web/main.css +1 -1
- package/dist/web/main.js +185 -18
- package/dist/wire.mjs +1 -1
- package/dist/workflow-kit.mjs +9 -3
- package/package.json +1 -1
- package/src/cli/Cli.ts +1 -1
- package/src/cli/Program.ts +18 -2
- package/src/edge/Edge.ts +93 -11
- package/src/flows/helpers.ts +36 -18
- package/src/flows/index.test.ts +3 -0
- package/src/flows/index.ts +5 -0
- package/src/flows/runtime.ts +123 -16
- package/src/install/Install.ts +9 -2
- package/src/platform/Git.test.ts +7 -11
- package/src/platform/NodeSync.ts +2 -0
- package/src/platform/SyncIo.ts +2 -0
- package/src/platform/Workspace.test.ts +37 -0
- package/src/platform/Workspace.ts +36 -0
- package/src/replay/Replay.ts +33 -1
- package/src/replay/Trailers.ts +3 -0
- package/src/replay/Tree.ts +5 -0
- package/src/steering/FORMATS.md +3 -1
- package/src/steering/SteeringFormat.ts +13 -0
- package/src/steering/fixtures/review/sectioned.md +1 -1
- package/src/steering/fixtures/review/sectioned.read.json +0 -1
- package/src/steering/index.ts +1 -0
- package/src/steering/review.test.ts +181 -5
- package/src/steering/review.ts +160 -18
- package/src/step/RepoSnapshot.ts +4 -0
- package/src/step/planStep.ts +6 -6
- package/src/twins/EmittedScriptRecognizer.ts +1 -1
- package/src/twins/InMemRepo.ts +24 -3
- package/src/twins/Layers.ts +1 -0
- package/src/twins/SyncIo.test.ts +19 -4
- package/src/twins/SyncIo.ts +13 -1
- package/src/wire/BeatDocument.test.ts +15 -0
- package/src/wire/BeatDocument.ts +8 -2
- package/src/wire/Demand.ts +4 -2
- package/src/wire/golden/1/beat-capture.json +1 -0
- package/src/wire/golden/1/beat-message.json +1 -0
- package/src/wire/golden/1/beat-prompt.json +1 -0
- package/src/wire/golden/1/beat-script.json +1 -0
- package/src/wire/golden/1/beat-stalled.json +1 -0
- package/src/workflow/Workflow.ts +2 -0
- package/src/workflow-kit/index.test.ts +1 -0
- package/src/workflow-kit/index.ts +1 -0
- package/src/workflow-kit/scenarios.ts +8 -0
package/src/wire/BeatDocument.ts
CHANGED
|
@@ -33,6 +33,7 @@ const dispatchFieldsOf = (
|
|
|
33
33
|
): {
|
|
34
34
|
readonly session: DemandSession | undefined
|
|
35
35
|
readonly validate: string | undefined
|
|
36
|
+
readonly fresh: string | null
|
|
36
37
|
readonly skills: readonly string[] | undefined
|
|
37
38
|
readonly access: StepAccess | undefined
|
|
38
39
|
readonly pin: PinMark | undefined
|
|
@@ -40,6 +41,7 @@ const dispatchFieldsOf = (
|
|
|
40
41
|
const none = {
|
|
41
42
|
session: undefined,
|
|
42
43
|
validate: undefined,
|
|
44
|
+
fresh: null,
|
|
43
45
|
skills: undefined,
|
|
44
46
|
access: undefined,
|
|
45
47
|
pin: undefined,
|
|
@@ -50,6 +52,7 @@ const dispatchFieldsOf = (
|
|
|
50
52
|
...none,
|
|
51
53
|
session: demand.session,
|
|
52
54
|
validate: demand.validate,
|
|
55
|
+
fresh: demand.fresh,
|
|
53
56
|
skills: demand.skills,
|
|
54
57
|
access: demand.access,
|
|
55
58
|
}
|
|
@@ -75,6 +78,8 @@ export interface BeatDocument {
|
|
|
75
78
|
readonly model: string | undefined
|
|
76
79
|
readonly system: string | undefined
|
|
77
80
|
readonly validate: string | undefined
|
|
81
|
+
/** A validator retry with `session.resume`: the original prompt plus the correction, for a driver that starts a new session. `null` otherwise. */
|
|
82
|
+
readonly fresh: string | null
|
|
78
83
|
/** On a pin or unpin beat only: what its script does to `.gtd/process.gtdpin`. */
|
|
79
84
|
readonly pin: PinMark | undefined
|
|
80
85
|
readonly log: string
|
|
@@ -96,13 +101,13 @@ export interface BeatDocument {
|
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
/**
|
|
99
|
-
* Flatten a `Demand` plus its `BeatStatus` into the single
|
|
104
|
+
* Flatten a `Demand` plus its `BeatStatus` into the single 27-key document
|
|
100
105
|
* `gtd next --json` emits — the ONLY place the two are joined. `cost`/
|
|
101
106
|
* `costByModel` are omitted together, exactly when no cost was recorded
|
|
102
107
|
* (`cost <= 0`).
|
|
103
108
|
*/
|
|
104
109
|
export const beatDocument = (demand: Demand, status: BeatStatus): BeatDocument => {
|
|
105
|
-
const { session, validate, skills, access, pin } = dispatchFieldsOf(demand)
|
|
110
|
+
const { session, validate, fresh, skills, access, pin } = dispatchFieldsOf(demand)
|
|
106
111
|
const hasCost = status.cost > 0
|
|
107
112
|
return {
|
|
108
113
|
schema: WIRE_SCHEMA,
|
|
@@ -114,6 +119,7 @@ export const beatDocument = (demand: Demand, status: BeatStatus): BeatDocument =
|
|
|
114
119
|
model: status.model,
|
|
115
120
|
system: status.system,
|
|
116
121
|
validate,
|
|
122
|
+
fresh,
|
|
117
123
|
pin,
|
|
118
124
|
log: status.log,
|
|
119
125
|
state: status.state,
|
package/src/wire/Demand.ts
CHANGED
|
@@ -96,6 +96,7 @@ export type Demand =
|
|
|
96
96
|
readonly content: string
|
|
97
97
|
readonly session: DemandSession | undefined
|
|
98
98
|
readonly validate: string | undefined
|
|
99
|
+
readonly fresh: string | null
|
|
99
100
|
readonly skills: readonly string[] | undefined
|
|
100
101
|
readonly access: StepAccess
|
|
101
102
|
}
|
|
@@ -115,8 +116,9 @@ export const demandOf = (input: {
|
|
|
115
116
|
readonly kind: BeatKind
|
|
116
117
|
readonly session?: DemandSession
|
|
117
118
|
readonly validate?: string
|
|
119
|
+
readonly fresh?: string | null
|
|
118
120
|
}): Demand => {
|
|
119
|
-
const { rendered, kind, session, validate } = input
|
|
121
|
+
const { rendered, kind, session, validate, fresh = null } = input
|
|
120
122
|
const content =
|
|
121
123
|
kind === "stalled"
|
|
122
124
|
? stallDiagnosis(rendered.state, rendered.actor, rendered.failure, rendered.blocked)
|
|
@@ -124,7 +126,7 @@ export const demandOf = (input: {
|
|
|
124
126
|
const skills =
|
|
125
127
|
rendered.skills !== undefined && rendered.skills.length > 0 ? rendered.skills : undefined
|
|
126
128
|
const access = rendered.access ?? { read: null, write: null }
|
|
127
|
-
if (kind === "prompt") return { kind, content, session, validate, skills, access }
|
|
129
|
+
if (kind === "prompt") return { kind, content, session, validate, fresh, skills, access }
|
|
128
130
|
if (kind === "script" && rendered.pin !== undefined) return { kind, content, pin: rendered.pin }
|
|
129
131
|
return { kind, content }
|
|
130
132
|
}
|
package/src/workflow/Workflow.ts
CHANGED
|
@@ -42,6 +42,8 @@ export interface StepDef {
|
|
|
42
42
|
readonly requireRevert?: boolean
|
|
43
43
|
readonly allowEmpty?: boolean
|
|
44
44
|
readonly keep?: boolean
|
|
45
|
+
/** A validator retry: the step's original prompt, `content` being the correction. */
|
|
46
|
+
readonly original?: string
|
|
45
47
|
readonly onFail?: "rest"
|
|
46
48
|
readonly acceptClean?: boolean
|
|
47
49
|
readonly approve?: boolean
|
|
@@ -68,3 +68,11 @@ export const removedAssertions = (changes: readonly Change[]): readonly RemovedA
|
|
|
68
68
|
return { path: c.path, lines }
|
|
69
69
|
})
|
|
70
70
|
.filter((r) => r.lines.length > 0)
|
|
71
|
+
|
|
72
|
+
/** Validator form of `removedAssertions`: lists each lost line by path and scenario, or `undefined` when none. */
|
|
73
|
+
export const assertionErrors = (changes: readonly Change[]): string | undefined => {
|
|
74
|
+
const lost = removedAssertions(changes)
|
|
75
|
+
if (lost.length === 0) return undefined
|
|
76
|
+
const lines = lost.flatMap((r) => r.lines.map((a) => ` - ${r.path}: ${a.scenario}: ${a.line}`))
|
|
77
|
+
return `Restore the assertions these .feature files lost:\n${lines.join("\n")}`
|
|
78
|
+
}
|