inject-spec-first¶
Provenance¶
- Source:
.spec/spexcode/spec-cli/sessions/injected-context/inject-spec-first/spec.md - Source SHA-256:
2e90bad574a40875c8e0bbca430d83de506a3f7f57e6cb8d4cf8b2f2886918a3
inject-spec-first¶
raw source¶
The standing contract already tells an agent to read a file's governing spec before understanding its code
([[core]]), but a standing instruction is easy to scroll past. Catch the first READ whose target actually has
a code: governor. An uncovered file has no contract to read, so allowing it must leave the gate armed for a
later governed read. Firing once on the first actionable boundary lands when it counts; firing on every read
would become noise.
expanded spec¶
A PreToolUse hook (spec-first.sh) runs behind the same manifest and dispatcher on every harness. Native
hook shims deliver PreToolUse broadly; they do not own product filtering. The shell face of the
[[harness-adapter]] supplies one semantic read matcher: Claude's Read payload and Codex's read-shaped Bash
payload reduce to the same file path, while mutations, unrelated tools, and unresolvable commands reduce to
nothing. spec-first.sh contains no harness branch.
The path is then resolved through the authoritative spec graph (spex internal spec-governors, a stable
machine projection of the same ownership resolver as spex spec owner). Only a real code: governor is
actionable; uncovered and related-only files are ungoverned. The session sentinel (spec-checked,
a sibling of session.json under [[runtime]]) therefore has exactly one transition:
- armed + irrelevant/unresolvable/ungoverned event -> armed, allow silently;
- armed + governed read -> spent, block once, naming the actual governor and requiring its relevant parent, siblings, and children before retrying;
- spent + any later event -> spent, allow silently.
The blocking text is rendered by the shared HookPromptCatalog through spex internal hook-prompt, with the
actual path and resolved governor passed as data. The shell owns event detection and sentinel state; the registry
owns the model-facing words. Thus the public prompt catalog and the live block cannot drift apart, while the common
silent path stays pure shell.
This file governance is independent of the session record's governed bit. Dashboard-launched and
self-launched agents both get the gate, and a self-launched session's store directory is created only when a
governed read actually spends it. A read performed through a command shape the adapter cannot resolve passes
without changing state: the hook is a precise reminder, while the Stop gate remains the enforcer. Its
edit-time twin [[inject-spec-of-file]] keeps governance visible during mutations.