* enhance(#4095): checkpoint:decision auto-selection is opt-in via auto_select Auto-mode used to auto-select a checkpoint:decision's first <option> unconditionally, making a decision checkpoint's safety depend on option presentation order rather than an authored choice. Add an optional auto_select="<option-id>" attribute on the <task> tag: absent, auto-mode now escalates to a human exactly like gate="blocking-human" does; present, it names the option auto-mode selects; naming an id with no matching <option id> is a hard structural-validation error at plan-parse time rather than a silent fallback to the first option. gate="blocking-human" continues to win over everything, unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(#4095): anchor auto_select/id attribute regexes past hyphenated decoys An isolated adversarial review of the auto_select work found that both new attribute regexes used \b as their left anchor, which is a word boundary, not a "start of attribute name" boundary. A decoy attribute ending in the same word (e.g. data-id="...") sitting before the real id="..." on the same <option> tag matched first, silently corrupting the extracted option id. Anchor on (?:^|\s) instead so only the real attribute name can match. Adds a regression test reproducing the exact decoy-attribute shape, plus a Unicode option-id test from the same review pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test(#4095): register auto-select-attribute.test.cjs in the docs-guard lane lint-docs-guard-registration failed: the new test reads docs/reference/ plan-md.md but was not registered, so a future edit to that doc could silently desync from the test without the guard catching it on the PR that changed the doc. Registered alongside its direct precedents (precondition-element.test.cjs, reversibility-tagging.test.cjs), which read the same file for the same reason. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(#4095): fit the decision bullet under execute-phase.md's frozen byte ceiling The remote gsd-test run caught what local checks missed: execute-phase.md carries a frozen ADR-857 Phase-6 byte ceiling (93600) with only 36 bytes of headroom before this change, and the original checkpoint:decision wording pushed it to 93772 (over the ceiling). Cascaded into failures in phase6-capstone-conformance, execute-phase-completion-reconciliation, claude-orchestration, and the compact-content drift-report test. Also caught: tests/package-legitimacy-gate.test.cjs anchors a "decision is conditional, not unconditional" safety check on the literal phrase "first option" in the decision bullet — which #4095 deliberately removes, since there is no more unconditional first-option pick. The test was asserting an assumption this change intentionally makes obsolete; re-anchored on tokens that still identify the bullet ('decision', 'auto-spawn') without weakening what the test actually verifies (the bullet must still carry a blocking-human carve-out). Also fixed a word-order mismatch between my own new test's regex and the actual doc text it was asserting against (tests/auto-select-attribute.test.cjs). Regenerated the compact-content benchmark baseline (tests/fixtures/compact-content-benchmark-baseline.json) to match the new byte counts. Emitted-Drift-Ack-Growth: gsd-executor.md — +7 bytes (49138 -> 49145), from the auto_select carve-out added to the checkpoint:decision auto-mode bullet; already trimmed once to fit the 49152 hard cap. Emitted-Drift-Ack-Growth: execute-phase.md — +12 bytes (93564 -> 93576), from the same carve-out in the orchestrator's decision bullet; kept 24 bytes under the frozen 93600 ADR-857 ceiling after two rounds of trimming for clarity vs. margin. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * chore(#4095): backfill changeset PR number Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: sim <sim@local> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -244,6 +244,40 @@ Full taxonomy, emission rules, and anti-patterns (chiefly: rating everything `on
|
||||
|
||||
---
|
||||
|
||||
## Auto-select
|
||||
|
||||
`auto_select` is an **optional** attribute on a `<task type="checkpoint:decision">` element (issue #4095). It names the `id` of the `<option>` that auto-mode (`workflow._auto_chain_active` / `workflow.auto_advance`) should select when the checkpoint is reached unattended.
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:decision" gate="blocking" auto_select="nextauth">
|
||||
<decision>Select authentication provider</decision>
|
||||
<options>
|
||||
<option id="supabase"><name>Supabase Auth</name></option>
|
||||
<option id="clerk"><name>Clerk</name></option>
|
||||
<option id="nextauth"><name>NextAuth.js</name></option>
|
||||
</options>
|
||||
<resume-signal>Select: supabase, clerk, or nextauth</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Semantics:**
|
||||
|
||||
| `auto_select` | Auto-mode behavior |
|
||||
|---|---|
|
||||
| Absent | Escalates to a human — same treatment as `gate="blocking-human"`. Auto-mode does not guess an answer from option order. |
|
||||
| Names a real `<option id="…">` | Selects that option and logs `⚡ Auto-selected: [option id]`, then continues. |
|
||||
| Names an id that does not match any `<option id="…">` | `verify plan-structure` fails at plan-parse time. Never a silent fallback to the first option. |
|
||||
|
||||
`gate="blocking-human"` continues to win over everything, unchanged — it stops for a human in every mode regardless of `auto_select`.
|
||||
|
||||
**Why:** before this attribute existed, auto-mode always picked the first `<option>`, and the planner convention of front-loading the recommended choice meant the safety of every decision checkpoint depended on presentation order — a detail no plan author was told was load-bearing. `auto_select` makes the unattended answer an authored decision instead of a byproduct of layout.
|
||||
|
||||
**Optional and back-compat for the structural validator:** a plan that omits `auto_select` on every `checkpoint:decision` task still passes `verify plan-structure` — the validator only rejects a *declared* `auto_select` that doesn't match any option id. What changes is auto-mode's *runtime* behavior (escalate instead of guessing), not plan-structure validity.
|
||||
|
||||
Full behavioral reference: `gsd-core/references/checkpoints.md` → `checkpoint:decision`.
|
||||
|
||||
---
|
||||
|
||||
## Task types
|
||||
|
||||
| Type | Use | Autonomy |
|
||||
@@ -251,7 +285,7 @@ Full taxonomy, emission rules, and anti-patterns (chiefly: rating everything `on
|
||||
| `auto` | Everything the executor can do independently. | Fully autonomous. |
|
||||
| `tracer` | The leading thin end-to-end slice a plan starts with by default (tracer-first) — production-quality, wired through every layer, with a real end-to-end `<verify>`. | Fully autonomous; after committing, the executor runs the tracer's `<verify>` as an early integration gate. A tracer carrying `gate="blocking-human"` STOPs for a human in every mode, auto included. Otherwise autonomous runs halt on failure before expansion, and interactive runs honor `workflow.human_verify_mode` (#3299): under the `end-of-phase` default a `<verify>` carrying only `<automated>` is re-run and, on success, expansion continues with **no** checkpoint (failure still halts); under `mid-flight`, or when the tracer carries `<human-check>`, a `checkpoint:human-verify` is presented. Full precedence chain: `gsd-core/references/checkpoints.md` → "Tracer feedback gate". |
|
||||
| `checkpoint:human-verify` | Visual or functional verification that requires a human to look at a running UI or service. | Pauses execution; presents to the developer; resumes on approval. |
|
||||
| `checkpoint:decision` | Implementation choices that arose during execution and require the developer's input. | Pauses execution; presents options; resumes on selection. |
|
||||
| `checkpoint:decision` | Implementation choices that arose during execution and require the developer's input. | Pauses execution; presents options; resumes on selection. In auto-mode, an `auto_select="<option-id>"` attribute lets the plan name the unattended answer — see [Auto-select](#auto-select). |
|
||||
| `checkpoint:human-action` | Truly unavoidable manual steps (account creation, hardware interaction). Used sparingly. | Pauses execution; resumes on confirmation. |
|
||||
|
||||
Plans that contain any checkpoint task must set `autonomous: false` in frontmatter.
|
||||
|
||||
Reference in New Issue
Block a user