* test(#3866): pin that verify:pre must dispatch every hook kind verify-work.md's verify_pre_hooks step dispatches only `kind == "gate"`, so getWiredKinds reports verify:pre -> {gate} and gen-capability-registry rejects any capability declaring a step or contribution there. The verify lane is therefore closed to capabilities that want to contribute to what UAT covers rather than refuse to let it start. Failing-first: the step, contribution, and exact-kind-set rows are RED; the pre-existing gate row is a green regression pin so the new arms cannot orphan the arm verify:pre already had. Refs #3866 * feat(#3866): dispatch step and contribution hooks at verify:pre verify_pre_hooks dispatched `kind == "gate"` only, so getWiredKinds reported verify:pre -> {gate} and gen-capability-registry's validateHooksWired rejected any capability declaring a step or contribution there. A capability could refuse to let UAT start; it could not contribute to what UAT covers. Add contribution and step arms mirroring execute:wave:post, deferring to references/loop-hook-dispatch.md and carrying its ref.command in-context validation guard ahead of any shell-use prose. A verify:pre step is advisory: it never blocks the start of UAT and an erroring step is routed by its own onError. The gate arm and its check guard are untouched. Give extract_tests an additive consumption seam for the artefacts those steps declare via the existing steps[].produces field -- no new registry field, no new ordering, no invented filename. Manifest-supplied artefact names are validated in-context against an allowlist and resolved only inside PHASE_DIR. With no producing step the derivation is unchanged, pinned by test rather than asserted in prose. Review findings folded in: the artefact-name allowlist (isolated adversarial pass), the artefact-shape contract and the seam-inertness tests (spec axis), and the reference/how-to split so one constraint has one source of truth (standards axis). Closes #3866 * chore(#3866): backfill changeset PR number --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -119,6 +119,33 @@ Choose the hook kind that matches the behaviour:
|
||||
|
||||
Declare file artefact flow with `produces` and `consumes`. The registry uses those arrays to order hooks and to reject unsatisfied dependencies.
|
||||
|
||||
### Check the point dispatches your kind
|
||||
|
||||
A point having a call site does not mean it dispatches every kind. Each host workflow decides, per
|
||||
point, which kinds its dispatch text handles — the wire-on-demand model — and the registry build
|
||||
enforces the result: `gen-capability-registry.cjs` scans the host workflows with `getWiredKinds()`
|
||||
and rejects a manifest that declares a kind the point does not dispatch. You find out at
|
||||
`npm run gen:capability-registry`, not at runtime:
|
||||
|
||||
```
|
||||
capability "demo" steps[0].point "ship:pre" registers a step hook, but the host call site's
|
||||
dispatch text never covers `kind == "step"` (it covers: gate). A hand-rolled single-kind consumer
|
||||
silently never dispatches the other kinds — dispatch every registered kind per
|
||||
gsd-core/references/loop-hook-dispatch.md.
|
||||
```
|
||||
|
||||
That error is the answer, not a bug to route around. Either pick a point that dispatches your kind,
|
||||
express the behaviour as a kind the point does dispatch, or open an issue to wire the arm — that
|
||||
last route is what [#3866](https://github.com/open-gsd/gsd-core/issues/3866) did for `verify:pre`,
|
||||
which dispatched only `gate` and so let a capability refuse to let UAT start but never contribute
|
||||
to what UAT covers.
|
||||
|
||||
For which kinds a given point dispatches, and the `verify:pre` step / `produces` semantics, see
|
||||
[Valid `point` values](../reference/capability-manifest.md#valid-point-values) — that table is the
|
||||
single source of truth. One operational note it does not carry: a `verify:pre` `produces` name
|
||||
whose artefact is absent at UAT time is reported and skipped, so a step that was inactive, skipped,
|
||||
or failed never drops a deliverable and never blocks UAT.
|
||||
|
||||
## Ship skills — and know what you are shipping
|
||||
|
||||
A skill your Capability declares is not an inert asset. Its `SKILL.md` body is copied **verbatim** into the user's runtime skills directory at install, where it becomes an agent-invocable instruction file. GSD does **not** scan it: there is no content inspection of any kind, at install or at any later point. What you write is what reaches the agent.
|
||||
|
||||
Reference in New Issue
Block a user