@pmelab/gtd 59.0.0 → 59.0.1
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 +5 -5
- package/dist/chunks/{testkit-CMBAAyRK.mjs → testkit-07Z_ENch.mjs} +431 -446
- package/dist/chunks/{wire-C12dahrH.mjs → wire-BTUhRGXj.mjs} +1 -1
- package/dist/flows.mjs +1 -1
- package/dist/gtd.bundle.mjs +410 -440
- package/dist/testkit/gherkin.mjs +145 -65
- package/dist/testkit.mjs +1 -1
- package/dist/wire.mjs +1 -1
- package/package.json +1 -1
- package/skills/authoring/SKILL.md +3 -2
- package/src/cli/Cli.test.ts +133 -52
- package/src/cli/Cli.ts +384 -461
- package/src/cli/Help.test.ts +47 -0
- package/src/cli/Help.ts +70 -0
- package/src/cli/Program.test.ts +67 -4
- package/src/cli/Program.ts +65 -18
- package/src/edge/Edge.ts +1 -1
- package/src/emit/Emit.test.ts +1 -1
- package/src/emit/Emit.ts +1 -1
- package/src/flows/factory.ts +3 -1
- package/src/gherkin/index.ts +135 -71
- package/src/gherkin/messages.test.ts +90 -0
- package/src/gherkin/messages.ts +84 -0
- package/src/testkit/TestRepo.test.ts +47 -2
- package/src/testkit/TestRepo.ts +51 -6
- package/src/twins/EmittedScriptRecognizer.ts +5 -8
- package/src/wire/Land.ts +1 -1
- package/src/workflow/load.ts +6 -6
- package/src/workflow/skills.test.ts +5 -5
- package/src/workflow/skills.ts +1 -1
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
softResetTo,
|
|
17
17
|
updateRef,
|
|
18
18
|
binaryGuard,
|
|
19
|
-
DID_NOT_RUN_COMMENT,
|
|
20
19
|
failurePromptWrapper,
|
|
21
20
|
fileExistsGuard,
|
|
22
21
|
PRESENTATION_FAILURE_WARNING,
|
|
@@ -552,13 +551,11 @@ const recognizeGtdUncheck = (repo: InMemRepo, block: string): BlockOutcome | und
|
|
|
552
551
|
}
|
|
553
552
|
|
|
554
553
|
/**
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
* script, so recognizing it as a no-op (like the retry-helper function
|
|
558
|
-
* definition) keeps the `@inmem` tier green.
|
|
554
|
+
* A block of nothing but comments is a no-op in `sh` too — `combinedScript`'s
|
|
555
|
+
* leading `DID_NOT_RUN_COMMENT`, and the list of paths a start commits.
|
|
559
556
|
*/
|
|
560
|
-
const
|
|
561
|
-
block
|
|
557
|
+
const recognizeCommentBlock = (block: string): BlockOutcome | undefined =>
|
|
558
|
+
block.split("\n").every((line) => line.startsWith("#")) ? { kind: "noop" } : undefined
|
|
562
559
|
|
|
563
560
|
/** `combinedScript`'s optional half. Reports `noop` whatever the inner result, mirroring bash's `( … ) || <warning>`. Exception: under `git: false` any unrecognized inner block fails the outer script (git or not), so the in-memory twin knowingly diverges from `sh` rather than run git unseen. */
|
|
564
561
|
const PRESENTATION_FAILURE_TEXT = `${extractQuotedTokens(PRESENTATION_FAILURE_WARNING)[0]!.replace(/\\n$/, "")}\n`
|
|
@@ -695,7 +692,7 @@ const recognizersFor = (
|
|
|
695
692
|
git: boolean,
|
|
696
693
|
): ReadonlyArray<(block: string) => BlockOutcome | undefined> => [
|
|
697
694
|
(block) => recognizeSetFlags(block),
|
|
698
|
-
(block) =>
|
|
695
|
+
(block) => recognizeCommentBlock(block),
|
|
699
696
|
(block) => recognizePrecondition(repo, block),
|
|
700
697
|
(block) => recognizeFileExistsGuard(repo, block),
|
|
701
698
|
(block) => recognizeBinaryGuard(commands, block),
|
package/src/wire/Land.ts
CHANGED
|
@@ -71,5 +71,5 @@ export const landProseText = (subject: string): string => renderFormat(FMT_LAND_
|
|
|
71
71
|
*/
|
|
72
72
|
export const renderLandPlain = (fields: LandFields, command = "land"): string =>
|
|
73
73
|
fields.subject !== null
|
|
74
|
-
? `${landProseText(fields.subject).trimEnd()}\n(
|
|
74
|
+
? `${landProseText(fields.subject).trimEnd()}\n(to land it: s=$(gtd ${command} --json=script) && sh -c "$s")\n`
|
|
75
75
|
: noopText(fields.state)
|
package/src/workflow/load.ts
CHANGED
|
@@ -50,7 +50,7 @@ export interface ConfigOperations {
|
|
|
50
50
|
// prints `message` verbatim and would print a duplicated `detail` twice.
|
|
51
51
|
const configError = (diagnostics: readonly Diagnostic[]): GtdError =>
|
|
52
52
|
new GtdError(
|
|
53
|
-
`gtd config:\n${diagnostics
|
|
53
|
+
`gtd: config:\n${diagnostics
|
|
54
54
|
.filter((d) => d.severity === "error")
|
|
55
55
|
.map((d) => ` - ${formatDiagnostic(d)}`)
|
|
56
56
|
.join("\n")}`,
|
|
@@ -84,7 +84,7 @@ export const refuseLegacyRc: Effect.Effect<void, GtdError, Host | ConfigDiscover
|
|
|
84
84
|
return yield* Effect.fail(
|
|
85
85
|
new GtdError(
|
|
86
86
|
[
|
|
87
|
-
"gtd config:",
|
|
87
|
+
"gtd: config:",
|
|
88
88
|
...found.map((file) => ` - ${file}: no longer read — delete it`),
|
|
89
89
|
" gtd 23 removed the .gtdrc files; move each key they set:",
|
|
90
90
|
" vars → an option of the workflow factory in gtd.config.ts, or its `defaults` export",
|
|
@@ -129,7 +129,7 @@ export const load: Effect.Effect<
|
|
|
129
129
|
try: () => loadWorkflows(module, shipped),
|
|
130
130
|
catch: (e) =>
|
|
131
131
|
new GtdError(
|
|
132
|
-
`gtd config:\n - ${module.filepath}: ${e instanceof Error ? e.message : String(e)}`,
|
|
132
|
+
`gtd: config:\n - ${module.filepath}: ${e instanceof Error ? e.message : String(e)}`,
|
|
133
133
|
),
|
|
134
134
|
})
|
|
135
135
|
const compiled = loaded.config
|
|
@@ -885,7 +885,7 @@ const replayToFirstStep = (
|
|
|
885
885
|
outcome.kind === "failed" || outcome.kind === "refused"
|
|
886
886
|
? outcome.message.replace(/^gtd: /, "")
|
|
887
887
|
: "the default entry must begin at a step — that step is where a finished process waits"
|
|
888
|
-
return Effect.fail(new GtdError(`gtd config:\n - ${loaded.file.origin}: ${problem}`))
|
|
888
|
+
return Effect.fail(new GtdError(`gtd: config:\n - ${loaded.file.origin}: ${problem}`))
|
|
889
889
|
},
|
|
890
890
|
)
|
|
891
891
|
|
|
@@ -912,7 +912,7 @@ const firstStep = (
|
|
|
912
912
|
if (reads.length > 0) {
|
|
913
913
|
return yield* Effect.fail(
|
|
914
914
|
new GtdError(
|
|
915
|
-
`gtd config:\n - ${loaded.file.origin}: the flow's first step on an ordinary start reads ${reads.join(" and ")} — that step is where a finished process waits, so it must not depend on a setting`,
|
|
915
|
+
`gtd: config:\n - ${loaded.file.origin}: the flow's first step on an ordinary start reads ${reads.join(" and ")} — that step is where a finished process waits, so it must not depend on a setting`,
|
|
916
916
|
),
|
|
917
917
|
)
|
|
918
918
|
}
|
|
@@ -923,7 +923,7 @@ const firstStep = (
|
|
|
923
923
|
if (atHead === name) return name
|
|
924
924
|
return yield* Effect.fail(
|
|
925
925
|
new GtdError(
|
|
926
|
-
`gtd config:\n - ${loaded.file.origin}: the flow's first step on an ordinary start depends on the repository's files ("${name}" without them, "${atHead}" at HEAD) — that step is where a finished process waits, so it must not change as files do`,
|
|
926
|
+
`gtd: config:\n - ${loaded.file.origin}: the flow's first step on an ordinary start depends on the repository's files ("${name}" without them, "${atHead}" at HEAD) — that step is where a finished process waits, so it must not change as files do`,
|
|
927
927
|
),
|
|
928
928
|
)
|
|
929
929
|
})
|
|
@@ -17,24 +17,24 @@ describe("resolveScopeSkills", () => {
|
|
|
17
17
|
const message = await failure(() => {
|
|
18
18
|
throw new Error("boom")
|
|
19
19
|
})
|
|
20
|
-
expect(message).toContain(`gtd config:\n - ${FILE}: boom`)
|
|
20
|
+
expect(message).toContain(`gtd: config:\n - ${FILE}: boom`)
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
it("rejects a non-object return", async () => {
|
|
24
24
|
expect(await failure(() => ["a"])).toContain(
|
|
25
|
-
`gtd config:\n - ${FILE}: skills export must return an object of scope -> skill names`,
|
|
25
|
+
`gtd: config:\n - ${FILE}: skills export must return an object of scope -> skill names`,
|
|
26
26
|
)
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
it("rejects a non-array value", async () => {
|
|
30
30
|
expect(await failure(() => ({ a: "x" }))).toContain(
|
|
31
|
-
`gtd config:\n - ${FILE}: skills export: "a" must be an array of skill names`,
|
|
31
|
+
`gtd: config:\n - ${FILE}: skills export: "a" must be an array of skill names`,
|
|
32
32
|
)
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
it("rejects a non-string entry", async () => {
|
|
36
36
|
expect(await failure(() => ({ a: ["x", 1] }))).toContain(
|
|
37
|
-
`gtd config:\n - ${FILE}: skills export: "a" must be an array of skill names`,
|
|
37
|
+
`gtd: config:\n - ${FILE}: skills export: "a" must be an array of skill names`,
|
|
38
38
|
)
|
|
39
39
|
})
|
|
40
40
|
|
|
@@ -80,7 +80,7 @@ describe("resolveScopeAccess", () => {
|
|
|
80
80
|
|
|
81
81
|
it("rejects a malformed export with the file", async () => {
|
|
82
82
|
expect(message(await run({ access: () => ["a"] }))).toContain(
|
|
83
|
-
`gtd config:\n - ${FILE}: access export must return an object`,
|
|
83
|
+
`gtd: config:\n - ${FILE}: access export must return an object`,
|
|
84
84
|
)
|
|
85
85
|
expect(message(await run({ access: () => ({ a: { write: "x" } }) }))).toContain(
|
|
86
86
|
`${FILE}: access export: "a": access.write must be an array`,
|
package/src/workflow/skills.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Diagnostic } from "./Diagnostic.js"
|
|
|
7
7
|
import { failOnErrors } from "./load.js"
|
|
8
8
|
|
|
9
9
|
const fail = (origin: string, message: string): GtdError =>
|
|
10
|
-
new GtdError(`gtd config:\n - ${origin}: ${message}`)
|
|
10
|
+
new GtdError(`gtd: config:\n - ${origin}: ${message}`)
|
|
11
11
|
|
|
12
12
|
const checkShape = (value: unknown): Record<string, readonly string[]> => {
|
|
13
13
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|