--- name: semctx-semantic description: >- Carry intent, invariants, decisions, evidence and unknowns through a non-trivial change using the semctx semantic layer. Use when starting substantial work: open or select a change contract, pull a bounded semantic slice, then keep the contract honest as you edit — verify impact, compose the change verdict, run the recommended tests, and record proofs/unknowns. Never conclude on a BLOCK. --- # Working a change with the semctx semantic layer This is the focused Plane B workflow. Use `semctx-control` when the task also needs repository impact, L0-L6 tracing, migration planning, or the shared Codex/Claude completion contract. The semantic layer is **authored truth** (Plane B) that sits beside the deterministic repository graph (Plane A). It answers *"which intention, invariants, decisions, evidence and unknowns must survive while I change this system?"* — it does **not** find files for a task (that is grep/BM25/ embeddings; see ADR 0005). Everything is deterministic and works with no LLM; you make it better. Pass the absolute project root as `repositoryRoot` on every MCP call. The server rejects missing or relative roots so a plugin-cache working directory can never become the implicit target. ## The loop (non-trivial change) 1. **Check semantic integrity.** Call `semctx_semantic_check` and preserve every canonical reason code. Do not continue into a write loop with an invalid/mismatched pointer, obsolete active contract, or stale verification baseline. 2. **Open or select a change contract.** - `semctx_change_open` with `{ id: "change.", statement, preserves: [...], serves: [...], requires: [...], unknowns: [...] }`. It becomes the active change (provenance `agent`). - `preserves` are the invariants this change must not break; `requires` are the proofs you will owe; `unknowns` are the open questions you must not silently drop. 3. **Pull a bounded semantic slice.** `semctx_semantic_slice { changeId }` (or `symbolRef` / `claimRef`). Read the capsule: Intentions, Invariants, Decisions, Linked symbols/claims, Evidence obtained, Open unknowns, **Forbidden / safety constraints**, Next expected proofs. It is bounded and every line points to a source — treat anything absent as **unknown**, not as false. 4. **Edit the code.** 5. **Analyse impact.** Call `semctx_verify_change` (Plane A: impacted symbols/contracts/invariants, recommended tests, PASS/WARN/BLOCK). This is unchanged and still first-class. 6. **Compose the change verdict.** Call `semctx_change_verify { changeId }`. It reuses the impact report verbatim and folds in the contract: - **VERIFIED** — all preserved invariants proved/untouched, all required evidence proved, no open blocking unknown, no stale link. - **PARTIAL** — open non-critical unknowns or unproven required evidence; nothing blocking. - **BLOCKED** — an underlying BLOCK, a critical preserved invariant touched without a test, a contradicted invariant, or (per config) a superseded decision in use. - **STALE** — a repository link no longer resolves (the model drifted from the code) — re-link before trusting the verdict. 7. **Run the recommended tests** from the impact report. They must pass. 8. **Record progress.** When you actually obtain a proof (you ran the test and it passed), update the evidence node's status to `tested` / `runtime_verified`. Before resolving an unknown, ensure its authored node declares `proved_by` to that proven evidence; then use `semctx_change_update { id, resolveUnknowns: [...] }`. 9. **Close through proof.** `semctx_change_close { id }` reruns composed verification and derives `verified` only from a VERIFIED result. Generic updates cannot assert that lifecycle. ## Rules - **Never conclude "done" on a BLOCKED verdict.** Resolve the finding (add the test / fix the change) or the user explicitly disables the rule in `.semctx/config.json`. - **On PARTIAL, say exactly what remains unproven** — list the pending evidence and open unknowns. PARTIAL is honest, not finished. - **On STALE, re-link before trusting anything** — a stale link means the declared coupling drifted. - **Never invent a relation, a proof or an invariant.** Only cite what the slice / reports show. If the model does not declare it, it is an open unknown. - **Keep the two planes distinct.** A structural fact ("X calls Y") is Plane A; an intention ("X must never happen twice") is Plane B. Do not launder one into the other. ## Handoff before compaction Before a context compaction or handing the work to a fresh agent, call `semctx_handoff` (optionally with a `note`). It captures the active change, touched invariants, obtained/pending proofs, open unknowns and next validations into `.semctx/working/`. On resume, call `semctx_resume` to rehydrate a short, stable capsule. These are explicit tools — do not rely on any implicit compaction hook. ## Local equivalents (no MCP) Prefer the plugin-bundled CLI (`dist/semctx.js`, same release as MCP). Claude Code substitutes the plugin root into this skill at load time, so the path below is already absolute; if it still reads as a literal `${…}` placeholder, use a global `semctx` on PATH instead (same version: `semctx --version`), or report that no shell CLI is available. `CLAUDE_PLUGIN_ROOT` is never exported to your terminal — do not rely on the shell to expand it. ``` bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" semantic init # scaffold .semctx/semantic/ (versioned) bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" semantic check --json # integrity + lifecycle reason codes bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" change open change. --preserves --unknown bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" semantic slice --change change. --format agent bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" verify diff --base origin/main # Plane A impact bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" change verify change. --base origin/main # composed verdict bun "${CLAUDE_PLUGIN_ROOT}/dist/semctx.js" semantic handoff # / semctx semantic resume semctx semantic check --json # global fallback ```