@pmelab/gtd 60.1.0 → 62.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 +16 -0
- package/dist/chunks/{testkit-BhTey1Do.mjs → testkit-XQeYCNMn.mjs} +1670 -1470
- package/dist/chunks/{wire-DZ8R1RU9.mjs → wire-CPNSm_9N.mjs} +27 -12
- package/dist/gtd.bundle.mjs +991 -627
- package/dist/gtd.core.mjs +117 -117
- package/dist/testkit/gherkin.mjs +1 -1
- package/dist/testkit.mjs +1 -1
- package/dist/wire.mjs +2 -2
- package/package.json +1 -1
- package/src/cli/Cli.ts +6 -1
- package/src/cli/History.test.ts +10 -1
- package/src/cli/Launch.test.ts +52 -0
- package/src/cli/Launch.ts +143 -0
- package/src/cli/Metrics.test.ts +10 -1
- package/src/cli/Program.test.ts +30 -20
- package/src/cli/Program.ts +4 -2
- package/src/cli/Strays.ts +3 -2
- package/src/cli/index.ts +1 -0
- package/src/edge/Edge.test.ts +79 -26
- package/src/edge/Edge.ts +178 -99
- package/src/emit/GitScript.ts +21 -3
- package/src/emit/index.ts +3 -0
- package/src/gherkin/messages.test.ts +1 -0
- package/src/gherkin/module-config.feature +1 -0
- package/src/gherkin/more-steps.feature +1 -0
- package/src/gherkin/testkit.feature +2 -1
- package/src/install/Install.ts +9 -2
- package/src/platform/PinFile.ts +61 -0
- package/src/platform/index.ts +1 -0
- package/src/replay/Format.test.ts +35 -8
- package/src/replay/Format.ts +7 -4
- package/src/replay/Replay.test.ts +54 -0
- package/src/replay/Replay.ts +61 -17
- package/src/replay/Trailers.test.ts +11 -48
- package/src/replay/Trailers.ts +36 -42
- package/src/replay/Tree.ts +11 -0
- package/src/replay/index.ts +3 -0
- package/src/step/LandStep.ts +1 -0
- package/src/step/RepoSnapshot.ts +2 -0
- package/src/step/planStart.test.ts +2 -3
- package/src/step/planStart.ts +1 -5
- package/src/step/planStep.test.ts +4 -4
- package/src/step/planStep.ts +10 -8
- package/src/testkit/TestRepo.test.ts +4 -1
- package/src/testkit/TestRepo.ts +3 -1
- package/src/twins/EmittedScriptRecognizer.ts +32 -1
- package/src/twins/GitTiers.ts +23 -0
- package/src/twins/InMemRepo.ts +14 -0
- package/src/twins/PinBeats.ts +33 -0
- package/src/twins/PinFile.test.ts +107 -0
- package/src/twins/PinFile.ts +12 -0
- package/src/twins/index.ts +2 -0
- package/src/wire/BeatDocument.ts +26 -5
- package/src/wire/Demand.ts +16 -6
- package/src/wire/constants.ts +3 -0
- package/src/wire/types.ts +4 -0
- package/src/workflow/fingerprint.ts +2 -2
- package/src/workflow/index.ts +2 -2
- package/src/workflow/load.ts +14 -1
- package/src/workflow/pin.ts +15 -7
package/src/wire/types.ts
CHANGED
|
@@ -10,6 +10,9 @@ export type StateName = string
|
|
|
10
10
|
/** The three content kinds a state can carry — exactly one per state. */
|
|
11
11
|
export type ContentKind = "script" | "prompt" | "message"
|
|
12
12
|
|
|
13
|
+
/** What a pin or unpin beat does to the pin; a driver may do it its own way instead of running the script. */
|
|
14
|
+
export type PinMark = "add" | "remove"
|
|
15
|
+
|
|
13
16
|
/** The name of a steering-file mode. Not a closed vocabulary: the valid set derives from the active definition (`BUILT_IN_MODES` plus whatever `modes:` declares). */
|
|
14
17
|
export type StateMode = string
|
|
15
18
|
|
|
@@ -51,4 +54,5 @@ export interface RenderedDemandSource {
|
|
|
51
54
|
readonly judge?: string
|
|
52
55
|
readonly skills?: readonly string[]
|
|
53
56
|
readonly access?: StepAccess
|
|
57
|
+
readonly pin?: PinMark
|
|
54
58
|
}
|
|
@@ -7,12 +7,12 @@ export type ConfigFingerprint = Readonly<Record<string, string>>
|
|
|
7
7
|
|
|
8
8
|
const HASH_LENGTH = 16
|
|
9
9
|
|
|
10
|
-
// A path
|
|
10
|
+
// A path with a control character is never recorded, so it can never
|
|
11
11
|
// reach a terminal from history.
|
|
12
12
|
// eslint-disable-next-line no-control-regex -- the control range IS the point
|
|
13
13
|
const CONTROL_CHARACTER = /[\x00-\x1f\x7f-\x9f]/
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const contentHash = (content: string | Buffer): string =>
|
|
16
16
|
createHash("sha256").update(content).digest("hex").slice(0, HASH_LENGTH)
|
|
17
17
|
|
|
18
18
|
const realOr = (path: string): string => {
|
package/src/workflow/index.ts
CHANGED
|
@@ -33,5 +33,5 @@ export {
|
|
|
33
33
|
type StateMode,
|
|
34
34
|
type StateName,
|
|
35
35
|
} from "./Workflow.js"
|
|
36
|
-
export {
|
|
37
|
-
export { EngineCore, pin, readPin } from "./pin.js"
|
|
36
|
+
export type { ConfigFingerprint } from "./fingerprint.js"
|
|
37
|
+
export { EngineCore, pin, pinHeader, PIN_FORMAT, readPin } from "./pin.js"
|
package/src/workflow/load.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { Host, Workspace, type WorkspaceOps } from "../platform/index.js"
|
|
|
17
17
|
import { compileConfig, type CompiledConfig } from "./compile.js"
|
|
18
18
|
import { SETTING_NAME_RULE, isSettingName } from "./vars.js"
|
|
19
19
|
import { ConfigDiscovery, WORKFLOW_MODULE, type WorkflowModule } from "./discovery.js"
|
|
20
|
-
import { configFingerprint, type ConfigFingerprint } from "./fingerprint.js"
|
|
20
|
+
import { changedConfigFiles, configFingerprint, type ConfigFingerprint } from "./fingerprint.js"
|
|
21
21
|
import { PIN_KEY } from "../install/index.js"
|
|
22
22
|
import {
|
|
23
23
|
dedupeDiagnostics,
|
|
@@ -50,6 +50,8 @@ export interface ConfigOperations {
|
|
|
50
50
|
readonly warnings: readonly Diagnostic[]
|
|
51
51
|
/** The content hash of every file `gtd.config.ts`'s evaluation touched — itself plus any relative import — by path relative to the root. */
|
|
52
52
|
readonly fingerprint: ConfigFingerprint
|
|
53
|
+
/** Inside a pin, the files it was bundled from that differ on disk now. */
|
|
54
|
+
readonly drift: readonly string[]
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
// Everything lives in `message` (not `GtdError.detail`) — `renderFailure`
|
|
@@ -204,6 +206,17 @@ export const load: Effect.Effect<
|
|
|
204
206
|
fingerprint:
|
|
205
207
|
pinned?.fingerprint ??
|
|
206
208
|
configFingerprint(loaded.file.dependencyFiles, host.root, module.read ?? readFromDisk),
|
|
209
|
+
drift:
|
|
210
|
+
pinned === undefined
|
|
211
|
+
? []
|
|
212
|
+
: changedConfigFiles(
|
|
213
|
+
pinned.fingerprint,
|
|
214
|
+
configFingerprint(
|
|
215
|
+
Object.keys(pinned.fingerprint).map((file) => resolvePath(host.root, file)),
|
|
216
|
+
host.root,
|
|
217
|
+
readFromDisk,
|
|
218
|
+
),
|
|
219
|
+
),
|
|
207
220
|
}
|
|
208
221
|
})
|
|
209
222
|
|
package/src/workflow/pin.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { ownPackage, pinnedWorkflowSource } from "./load.js"
|
|
|
7
7
|
import type { WorkflowModule } from "./discovery.js"
|
|
8
8
|
|
|
9
9
|
/** Bumped when a launcher could no longer run an older pin the same way. */
|
|
10
|
-
const PIN_FORMAT = 1
|
|
10
|
+
export const PIN_FORMAT = 1
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* The engine a pin carries, as ES module source. Live, the `gtd.core.mjs` the
|
|
@@ -57,16 +57,24 @@ export const pin = (
|
|
|
57
57
|
])
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
+
/** A pin's header line, read without unpacking it; undefined when the bytes are no pin. */
|
|
61
|
+
export const pinHeader = (
|
|
62
|
+
bytes: Uint8Array,
|
|
63
|
+
): { readonly format: number; readonly version: string } | undefined => {
|
|
64
|
+
const end = bytes.indexOf(0x0a)
|
|
65
|
+
const header =
|
|
66
|
+
end < 0 ? null : /^gtdpin (\d+) gtd (\S+)$/.exec(Buffer.from(bytes.subarray(0, end)).toString())
|
|
67
|
+
return header === null ? undefined : { format: Number(header[1]), version: header[2]! }
|
|
68
|
+
}
|
|
69
|
+
|
|
60
70
|
/** A pin's header and module source. */
|
|
61
71
|
export const readPin = (
|
|
62
72
|
bytes: Uint8Array,
|
|
63
73
|
): { readonly format: number; readonly version: string; readonly source: string } => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
if (end < 0 || header === null) throw new Error("not a gtd pin")
|
|
74
|
+
const header = pinHeader(bytes)
|
|
75
|
+
if (header === undefined) throw new Error("not a gtd pin")
|
|
67
76
|
return {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
source: gunzipSync(bytes.subarray(end + 1)).toString("utf8"),
|
|
77
|
+
...header,
|
|
78
|
+
source: gunzipSync(bytes.subarray(bytes.indexOf(0x0a) + 1)).toString("utf8"),
|
|
71
79
|
}
|
|
72
80
|
}
|