@pmelab/gtd 7.0.0 → 7.1.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/README.md +4 -2
- package/dist/gtd.bundle.mjs +731 -188
- package/docs/cli.md +41 -47
- package/docs/configuration.md +65 -0
- package/docs/upgrading.md +8 -2
- package/package.json +1 -1
- package/schema.json +180 -0
package/docs/cli.md
CHANGED
|
@@ -32,14 +32,15 @@ Commands:
|
|
|
32
32
|
validate Format and validate the steering file the resolved rest
|
|
33
33
|
declares, with its mode's commands (its file:/mode:);
|
|
34
34
|
exits non-zero with the findings when it is invalid
|
|
35
|
-
mermaid Print the active workflow's shape as Mermaid
|
|
36
|
-
stateDiagram-v2 source (no mutation)
|
|
37
35
|
lsp Start the LSP server for .gtd/ steering files (stdio)
|
|
36
|
+
visualize Serve an interactive diagram of the active workflow locally
|
|
38
37
|
version Print version and exit
|
|
39
38
|
help Print this help and exit
|
|
40
39
|
|
|
41
40
|
Options:
|
|
42
41
|
--json Output structured JSON instead of plain text
|
|
42
|
+
--port=<n> (gtd visualize only) port to serve on (default: a free port)
|
|
43
|
+
--no-open (gtd visualize only) do not open the browser
|
|
43
44
|
--cost=<n> (gtd step only) record the invocation's token cost
|
|
44
45
|
--model=<name> (gtd step only, with --cost) tag that cost's model
|
|
45
46
|
--version, -v Print version and exit
|
|
@@ -394,46 +395,6 @@ agent or human:
|
|
|
394
395
|
|
|
395
396
|
`gtd validate` takes no arguments.
|
|
396
397
|
|
|
397
|
-
## `gtd mermaid`
|
|
398
|
-
|
|
399
|
-
Pure emitter of the active workflow's **shape** — not the resolved rest — as
|
|
400
|
-
Mermaid [`stateDiagram-v2`](https://mermaid.js.org/syntax/stateDiagram.html)
|
|
401
|
-
source (see `src/Mermaid.ts`): one node per declared state, the `[*] -->`
|
|
402
|
-
initial-state marker, one edge per declared `on` row labeled with its raw
|
|
403
|
-
pattern string (same declaration order the engine itself evaluates), a `--> [*]`
|
|
404
|
-
edge for every commit state (final, no outgoing edges — see
|
|
405
|
-
[STATES.md §8](../STATES.md#8-the-squash-lifecycle)), and one `note right of`
|
|
406
|
-
per rest naming its actor, content kind, and retry cap (e.g.
|
|
407
|
-
`agent · prompt · retry 3→escalate`). No git, no HEAD resolution, no template
|
|
408
|
-
rendering — purely a function of the compiled `WorkflowDefinition`, so its
|
|
409
|
-
output is identical regardless of the current process/branch state.
|
|
410
|
-
|
|
411
|
-
```
|
|
412
|
-
$ gtd mermaid
|
|
413
|
-
stateDiagram-v2
|
|
414
|
-
state "idle" as idle
|
|
415
|
-
state "planning" as planning
|
|
416
|
-
...
|
|
417
|
-
[*] --> idle
|
|
418
|
-
idle --> planning : * **
|
|
419
|
-
...
|
|
420
|
-
note right of idle : human · message
|
|
421
|
-
...
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
Pipe it straight into a `.md`/`.mmd` file, a GitHub issue/PR description, or any
|
|
425
|
-
Mermaid-aware renderer (GitHub, GitLab, VS Code, Obsidian, the
|
|
426
|
-
[Mermaid Live Editor](https://mermaid.live)) to get a diagram of a custom
|
|
427
|
-
`.gtdrc` `workflow:` with no hand-maintained docs required.
|
|
428
|
-
|
|
429
|
-
State names are aliased to Mermaid-safe identifiers (non-word characters fold to
|
|
430
|
-
`_`; a digit-led name gets an `s_` prefix) via a `state "<name>" as <alias>`
|
|
431
|
-
declaration up front, so a hyphenated name like `plan-review` still displays
|
|
432
|
-
with its exact declared spelling. Rejects `--json` (exit 1,
|
|
433
|
-
`gtd mermaid does not accept --json`) — there is no structured shape to emit
|
|
434
|
-
beyond the Mermaid source itself — and takes no arguments (extra positional args
|
|
435
|
-
are rejected).
|
|
436
|
-
|
|
437
398
|
## `gtd lsp`
|
|
438
399
|
|
|
439
400
|
Starts an LSP server over stdio for `.gtd/` steering files — document symbols
|
|
@@ -469,6 +430,39 @@ extra positional arguments — it's a long-running server, not a state command.
|
|
|
469
430
|
Runs until the client disconnects (the LSP `exit` notification), then exits
|
|
470
431
|
cleanly.
|
|
471
432
|
|
|
433
|
+
## `gtd visualize [--port=<n>] [--no-open] [--json]`
|
|
434
|
+
|
|
435
|
+
Serve an interactive diagram of the ACTIVE workflow on a local web server: the
|
|
436
|
+
main flow as a graph (one box per sub-machine), and a click-through inspector
|
|
437
|
+
with each state's actor, content kind, model/memory, steering file+mode, retry,
|
|
438
|
+
flags, and outgoing/incoming edges. This is the replacement for the removed
|
|
439
|
+
`gtd mermaid` — a live viewer instead of a static diagram dump.
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
$ gtd visualize
|
|
443
|
+
gtd visualize running at http://127.0.0.1:53017 — Ctrl-C to stop
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
The server serves two routes: `/` (the self-contained HTML page) and
|
|
447
|
+
`/workflow.json` (the model the page renders). It runs until interrupted
|
|
448
|
+
(Ctrl-C), then closes cleanly. Options (orthogonal, `gtd visualize` only):
|
|
449
|
+
|
|
450
|
+
- `--port=<n>` (or `--port <n>`) — serve on a specific port (0–65535); the
|
|
451
|
+
default is a free ephemeral port, printed on start.
|
|
452
|
+
- `--no-open` — do not open the default browser (the URL is always printed).
|
|
453
|
+
- `--json` — print the workflow model to stdout and exit WITHOUT starting a
|
|
454
|
+
server. The model is `{ states, initial, groups, vars }`; each state carries
|
|
455
|
+
its `actor`/`kind`/`model`/`memory`/`file`/`mode`/`retry`/`flags`, its `on`
|
|
456
|
+
edges, its computed `incoming` edges, and its sub-machine `group`. `groups`
|
|
457
|
+
lists each sub-machine invocation and the concrete states it produced.
|
|
458
|
+
|
|
459
|
+
Dispatched before the repository-root guard and the config-reading path's review
|
|
460
|
+
window — it reads the active workflow (the built-in default when none is
|
|
461
|
+
configured) but touches no git/HEAD/review-window state. The diagram is rendered
|
|
462
|
+
with Mermaid loaded from a CDN, so the graph needs network access the first time
|
|
463
|
+
a browser loads the page; the inspector works offline regardless. Rejects
|
|
464
|
+
unknown options and unexpected positional arguments.
|
|
465
|
+
|
|
472
466
|
## Error envelope
|
|
473
467
|
|
|
474
468
|
Every command, in `--json` mode, reports a failure as a machine-readable
|
|
@@ -496,8 +490,8 @@ the plain-text one.
|
|
|
496
490
|
green run, and the check's `"C"` pattern never fires. Gitignore every path
|
|
497
491
|
your scripts write before wiring gtd into a repo.
|
|
498
492
|
- **Repository root invocation.** Every state subcommand (`step`/`review`/
|
|
499
|
-
`next`/`status
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
`
|
|
503
|
-
|
|
493
|
+
`next`/`status`) must run from the git repository root — the workflow, pending
|
|
494
|
+
changes, and process history are resolved against the process cwd.
|
|
495
|
+
`--help`/`--version` (and the `help`/`version` subcommands), `lsp`, and
|
|
496
|
+
`visualize` skip this guard entirely (`visualize` still reads the `.gtdrc`
|
|
497
|
+
workflow, but needs no git state).
|
package/docs/configuration.md
CHANGED
|
@@ -588,6 +588,71 @@ done:
|
|
|
588
588
|
command), and gtd never interprets the number's unit (tokens, cents, whatever
|
|
589
589
|
the driver records) or the model name — it only records, sums, and groups them.
|
|
590
590
|
|
|
591
|
+
## Sub-machines (`submachines:` / `use:`)
|
|
592
|
+
|
|
593
|
+
Two OPTIONAL top-level keys let you factor repeated or complex clusters of
|
|
594
|
+
states into reusable **sub-machines** that are expanded into ordinary concrete
|
|
595
|
+
states at load time (see [STATES.md §13](../STATES.md) and
|
|
596
|
+
`src/Submachines.ts`). They add NO runtime behavior — the engine only ever sees
|
|
597
|
+
the expanded states — so a workflow authored with them is exactly a workflow
|
|
598
|
+
written flat.
|
|
599
|
+
|
|
600
|
+
```yaml
|
|
601
|
+
workflow:
|
|
602
|
+
submachines:
|
|
603
|
+
gate: # authored once
|
|
604
|
+
params: [onGreen] # names referenced as `$onGreen` below
|
|
605
|
+
states:
|
|
606
|
+
check:
|
|
607
|
+
actor: check
|
|
608
|
+
script: <%~ it.vars.testCommand %>
|
|
609
|
+
on:
|
|
610
|
+
"A .gtd/FEEDBACK.md": blocked # a local state -> renamed by `as:`
|
|
611
|
+
"C": "$onGreen" # a param -> bound by `with:`
|
|
612
|
+
blocked:
|
|
613
|
+
actor: human
|
|
614
|
+
file: <%= it.vars.feedbackFile %>
|
|
615
|
+
message: "fix the baseline"
|
|
616
|
+
on: { "* **": check }
|
|
617
|
+
use:
|
|
618
|
+
- submachine: gate
|
|
619
|
+
as: { check: start-check, blocked: start-blocked } # local -> concrete (omit for identity)
|
|
620
|
+
with: { onGreen: planning } # bind each `$param`
|
|
621
|
+
set: { check: { reviewEntry: true } } # optional extra fields on a renamed state
|
|
622
|
+
states:
|
|
623
|
+
idle:
|
|
624
|
+
{ actor: human, initial: true, message: "…", on: { "* **": start-check } }
|
|
625
|
+
planning: { actor: agent, prompt: "…", on: { "* **": start-check } }
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
Rules:
|
|
629
|
+
|
|
630
|
+
- **`submachines: { <name>: { params, states } }`** — `states` are ordinary
|
|
631
|
+
state definitions, except an `on`/`retry.otherwise` target or any whole field
|
|
632
|
+
value may be a `$param` placeholder.
|
|
633
|
+
- **`use:`** is an ordered list. Each entry names a `submachine:` and may set:
|
|
634
|
+
- **`as:`** — a `local -> concreteName` rename map. Omit it (or a given local)
|
|
635
|
+
for identity. Alias to the names a flat workflow would use to keep history
|
|
636
|
+
and `git log` unchanged.
|
|
637
|
+
- **`with:`** — bindings for the sub-machine's `$param`s.
|
|
638
|
+
- **`set:`** — extra fields merged onto a renamed state (e.g. `reviewEntry`).
|
|
639
|
+
- **Substitution is WHOLE-VALUE only.** `$name` resolves only when it is the
|
|
640
|
+
entire value of a field or target — never a substring — so bash `$x`/`${x}`
|
|
641
|
+
and Eta `<%= it.vars.x %>` inside content are untouched. Pass per-instance
|
|
642
|
+
text (a whole message/prompt/`describe`) as a whole `$name` binding.
|
|
643
|
+
- A target naming one of the sub-machine's own locals is rewritten via `as:`;
|
|
644
|
+
any other target passes through verbatim (a concrete top-level state). `on`
|
|
645
|
+
PATTERN keys are never substituted.
|
|
646
|
+
- Expansion strips `submachines:`/`use:`; the merged `states` are then compiled
|
|
647
|
+
and `validateDefinition`'d normally. Unknown sub-machine, unbound `$param`,
|
|
648
|
+
and generated-name collisions are load-time errors, aggregated with the rest.
|
|
649
|
+
|
|
650
|
+
`gtd init` scaffolds the EXPANDED flat config, so a fresh project never sees
|
|
651
|
+
`submachines:`/`use:` unless it adds them itself. The bundled template is
|
|
652
|
+
authored with them (dedup: `assertGreen`/`makeGreen`/`qaLoop`; comprehension:
|
|
653
|
+
`planLoop`/`humanReview`/`specGate`/`packageLoop`) and its golden test pins that
|
|
654
|
+
expansion is byte-identical to the flat form.
|
|
655
|
+
|
|
591
656
|
## Variables
|
|
592
657
|
|
|
593
658
|
Every template — `script`/`prompt`/`message`/`commit`, and `model`/`memory`/
|
package/docs/upgrading.md
CHANGED
|
@@ -80,8 +80,14 @@ upgrading.
|
|
|
80
80
|
existing review/feedback machinery unmodified — see
|
|
81
81
|
[STATES.md §11](../STATES.md#11-the-review-checkout-window) and
|
|
82
82
|
[CLI reference](cli.md#gtd-review-commitish---json). The current command
|
|
83
|
-
surface is `init` / `step` / `next` / `status` / `validate` / `
|
|
84
|
-
`
|
|
83
|
+
surface is `init` / `step` / `next` / `status` / `validate` / `review` /
|
|
84
|
+
`lsp`.
|
|
85
|
+
|
|
86
|
+
- **`gtd mermaid` → `gtd visualize`.** The static Mermaid emitter has been
|
|
87
|
+
replaced by `gtd visualize`, which serves an interactive diagram of the active
|
|
88
|
+
workflow (main flow, sub-machines, per-state details) on a local web server —
|
|
89
|
+
see [CLI reference](cli.md#gtd-visualize---portn---no-open---json). Both are
|
|
90
|
+
read-only views of the active workflow; nothing in the machine changes.
|
|
85
91
|
|
|
86
92
|
- **`gtd format <file>`, and the bundled prettier with it.** gtd no longer
|
|
87
93
|
formats anything on its own: a steering-file mode declares its own `format:`
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -36,6 +36,182 @@
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
+
"submachines": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"description": "Optional reusable sub-machines, invoked by `use:` and expanded into concrete states at load time (see src/Submachines.ts).",
|
|
42
|
+
"additionalProperties": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"description": "A reusable, parameterized cluster of states, expanded at load time by each `use:` invocation into concrete states (see src/Submachines.ts). Purely a source-authoring convenience — the engine only ever sees the expanded states.",
|
|
45
|
+
"additionalProperties": false,
|
|
46
|
+
"required": ["states"],
|
|
47
|
+
"properties": {
|
|
48
|
+
"params": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"description": "Parameter names. A `$name` token used as a whole field value or `on`/`retry.otherwise` target is replaced by the invocation's `with:` binding."
|
|
54
|
+
},
|
|
55
|
+
"states": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"description": "The sub-machine's local states. `on`/`retry.otherwise` targets naming another local are rewritten via `as:`; a `$name` value is bound from `with:`.",
|
|
58
|
+
"minProperties": 1,
|
|
59
|
+
"additionalProperties": {
|
|
60
|
+
"type": "object",
|
|
61
|
+
"description": "One workflow state. Declare exactly one content kind (script/prompt/message/commit). A commit state is final: no actor, no on.",
|
|
62
|
+
"additionalProperties": false,
|
|
63
|
+
"properties": {
|
|
64
|
+
"actor": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"description": "Who acts at this state. Required on every non-commit state; forbidden on a commit state."
|
|
67
|
+
},
|
|
68
|
+
"script": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"description": "Content kind: a shell script (Eta template). The loop driver executes it verbatim via bash, then steps this state's actor."
|
|
71
|
+
},
|
|
72
|
+
"prompt": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"description": "Content kind: an agent prompt (Eta template), emitted by `gtd next`."
|
|
75
|
+
},
|
|
76
|
+
"message": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "Content kind: a human-facing message (Eta template), emitted by `gtd next`."
|
|
79
|
+
},
|
|
80
|
+
"commit": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"description": "Content kind: entering this state ends the process by squashing it into one commit with this message (Eta template). Final — no actor, no on."
|
|
83
|
+
},
|
|
84
|
+
"on": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"description": "Ordered map of change pattern -> target state. Patterns: \"C\" (clean tree) or \"<A|M|D|*> <glob>\" over the pending diff; first declared match wins. Every target must name a defined state, and every non-initial state must be reachable through these edges (or a retry.otherwise). A value is either the target state name (string) or a { to, describe } object whose describe is a human-readable sentence templates can surface as it.edges (e.g. in a human gate's message).",
|
|
87
|
+
"additionalProperties": {
|
|
88
|
+
"oneOf": [
|
|
89
|
+
{
|
|
90
|
+
"type": "string",
|
|
91
|
+
"description": "The target state name."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"type": "object",
|
|
95
|
+
"additionalProperties": false,
|
|
96
|
+
"required": ["to"],
|
|
97
|
+
"properties": {
|
|
98
|
+
"to": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"description": "The target state name."
|
|
101
|
+
},
|
|
102
|
+
"describe": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"description": "Human-readable sentence describing where this change routes; surfaced verbatim (never Eta-rendered) to templates as it.edges[].describe."
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"initial": {
|
|
112
|
+
"type": "boolean",
|
|
113
|
+
"description": "Exactly one state in the workflow must declare initial: true (and it must not be a commit state)."
|
|
114
|
+
},
|
|
115
|
+
"retry": {
|
|
116
|
+
"type": "object",
|
|
117
|
+
"description": "Redirect transitions INTO this state once it has been entered `max` times in the current process.",
|
|
118
|
+
"additionalProperties": false,
|
|
119
|
+
"required": ["max", "otherwise"],
|
|
120
|
+
"properties": {
|
|
121
|
+
"max": {
|
|
122
|
+
"type": "integer",
|
|
123
|
+
"minimum": 0,
|
|
124
|
+
"description": "Entries allowed this process before redirecting."
|
|
125
|
+
},
|
|
126
|
+
"otherwise": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Defined state to redirect to once over the cap."
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"model": {
|
|
133
|
+
"type": "string",
|
|
134
|
+
"description": "Opaque harness hint passed through `gtd next --json`/`gtd status --json` (e.g. \"smart\"). Never interpreted by gtd. Forbidden on a commit state."
|
|
135
|
+
},
|
|
136
|
+
"memory": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"description": "Opaque memory-scope label passed through `gtd next --json`/`gtd status --json` (e.g. \"plan\"). A memory-aware driver retains an agent's memory across consecutive agent turns sharing this label and starts fresh when it changes. Never interpreted by gtd. Forbidden on a commit state."
|
|
139
|
+
},
|
|
140
|
+
"file": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"description": "The state's steering file: an Eta template naming the file a human/editor should look at while the machine rests here. Forbidden on a commit state."
|
|
143
|
+
},
|
|
144
|
+
"mode": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"description": "The steering file's format: the name of a built-in mode (qa/review, validated in-process by gtd) or of a `modes:` entry. gtd formats and validates the file with that mode before capturing a turn out of this state, and the LSP dispatches live diagnostics on the built-in names. Requires a sibling `file:`. Forbidden on a commit state."
|
|
147
|
+
},
|
|
148
|
+
"reviewWindow": {
|
|
149
|
+
"type": "boolean",
|
|
150
|
+
"description": "When true, gtd opens a review checkout window while the machine rests here — HEAD/index are rewound to the review base so the whole base..HEAD diff surfaces as uncommitted changes in the editor. Forbidden on a commit state."
|
|
151
|
+
},
|
|
152
|
+
"reviewBase": {
|
|
153
|
+
"type": "boolean",
|
|
154
|
+
"description": "Marks the state whose most-recent in-process commit anchors the review window's diff base; absent any, the base is the process start. Forbidden on a commit state."
|
|
155
|
+
},
|
|
156
|
+
"reviewEntry": {
|
|
157
|
+
"type": "boolean",
|
|
158
|
+
"description": "Marks the (at most one) state `gtd review <commitish>` enters to start a brand new process reviewing <commitish>..HEAD. Forbidden on a commit state and on the initial state."
|
|
159
|
+
},
|
|
160
|
+
"fixEntry": {
|
|
161
|
+
"type": "boolean",
|
|
162
|
+
"description": "Marks the (at most one) state `gtd fix` enters to start a brand new process that goes straight into repairing the current failing tests. Forbidden on a commit state and on the initial state."
|
|
163
|
+
},
|
|
164
|
+
"requireProgress": {
|
|
165
|
+
"type": "boolean",
|
|
166
|
+
"description": "When true, a step at this state is refused if its only pending change is deleting the state's own `file:` — a work-free turn that discards its input without addressing it. A `NOTHING ACTIONABLE` sentinel file is exempt (a legitimately non-actionable round makes no code change). Requires a `file:`. Forbidden on a commit state."
|
|
167
|
+
},
|
|
168
|
+
"answerGate": {
|
|
169
|
+
"type": "boolean",
|
|
170
|
+
"description": "When true, a step at this state is refused unless every open question in its qa-mode `file:` is answered — exactly one checkbox ticked per question. Requires a `file:` and `mode: qa`. Forbidden on a commit state."
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"use": {
|
|
179
|
+
"type": "array",
|
|
180
|
+
"description": "Sub-machine invocations. Each clones a `submachines:` entry into concrete states: `as:` renames its locals (identity when omitted), `with:` binds its `$param`s, `set:` adds extra per-instance state fields.",
|
|
181
|
+
"items": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"additionalProperties": false,
|
|
184
|
+
"required": ["submachine"],
|
|
185
|
+
"properties": {
|
|
186
|
+
"submachine": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"description": "Name of a declared sub-machine."
|
|
189
|
+
},
|
|
190
|
+
"name": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"description": "Optional label for this instance (inert to expansion; used by tooling like `gtd visualize` to name the group). Defaults to the sub-machine name."
|
|
193
|
+
},
|
|
194
|
+
"as": {
|
|
195
|
+
"type": "object",
|
|
196
|
+
"description": "Rename map: local state name -> concrete state name (identity when omitted).",
|
|
197
|
+
"additionalProperties": {
|
|
198
|
+
"type": "string"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"with": {
|
|
202
|
+
"type": "object",
|
|
203
|
+
"description": "Bindings for the sub-machine's `$param`s."
|
|
204
|
+
},
|
|
205
|
+
"set": {
|
|
206
|
+
"type": "object",
|
|
207
|
+
"description": "Extra fields merged onto a renamed local state, keyed by local name.",
|
|
208
|
+
"additionalProperties": {
|
|
209
|
+
"type": "object"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
39
215
|
"states": {
|
|
40
216
|
"type": "object",
|
|
41
217
|
"description": "The workflow's named states. At least one; exactly one with initial: true.",
|
|
@@ -148,6 +324,10 @@
|
|
|
148
324
|
"requireProgress": {
|
|
149
325
|
"type": "boolean",
|
|
150
326
|
"description": "When true, a step at this state is refused if its only pending change is deleting the state's own `file:` — a work-free turn that discards its input without addressing it. A `NOTHING ACTIONABLE` sentinel file is exempt (a legitimately non-actionable round makes no code change). Requires a `file:`. Forbidden on a commit state."
|
|
327
|
+
},
|
|
328
|
+
"answerGate": {
|
|
329
|
+
"type": "boolean",
|
|
330
|
+
"description": "When true, a step at this state is refused unless every open question in its qa-mode `file:` is answered — exactly one checkbox ticked per question. Requires a `file:` and `mode: qa`. Forbidden on a commit state."
|
|
151
331
|
}
|
|
152
332
|
}
|
|
153
333
|
}
|