contracting — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited contracting (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill produces anvil/contract.yml. Every criterion populates four verification-level slots (Exists, Substantive, Wired, Functional) as grammatical slots, not optional annotations. Counter-examples come from the global Ledger and are injected into the draft verbatim from each matching lesson's remediation.counter_example_text field. A contract that does not parse into all four levels on every criterion does not get saved.
Invoking the Anvil CLI: the CLI is shipped as cli/anvil.js inside the plugin directory. It is NOT on PATH. Every invocation in this skill uses node "$CLAUDE_PLUGIN_ROOT/cli/anvil.js" <subcommand> .... Treat $ANVIL as shorthand for that command prefix.
Auto-invoked by /start <intent>. Invoked by the orchestrator whenever a task stream lacks a confirmed anvil/contract.yml. Once a contract is confirmed, the skill is not re-invoked until the user /starts a new stream or explicitly edits the contract.
Steps 1, 2, 4, 5, 6 run in the orchestrator's main thread. Step 3 - the heavy drafting work - is dispatched to a fresh subagent. The orchestrator holds only the source_intent, the pattern tags, the Ledger query results, and eventually the written anvil/contract.yml file. It never holds the drafting reasoning or any intermediate YAML.
source_intent string and extract pattern tags (nouns and verbs that describe the surface the change touches). Keep the list of tags small (3 to 8 typical).node "$CLAUDE_PLUGIN_ROOT/cli/anvil.js" ledger query <pattern>. Collect the returned lessons as a single deduplicated array.agents/contract-drafter.md) using the Task tool. Pass in the briefing: the verbatim source_intent, the extracted pattern tags, the deduplicated Ledger results, and the repository path. The subagent drafts anvil/contract.yml with all four verification levels populated per criterion, injects any matched lessons as counter_examples, runs anvil contract --validate, and returns exactly one sentence. Do NOT draft the YAML inline in the orchestrator thread - the orchestrator's context stays clean so the loop can fit larger contracts and longer runs without window pressure.state.meta.contract_unconfirmed = true via cli/lib/io.js writeFileUtf8 atomic-rename once the contract-drafter returns successfully. If the agent returned an error instead of a contract, surface the error to the user and stop; do not present a half-drafted contract for confirmation.anvil/contract.yml from disk and present it to the user for one-shot binary confirmation using the Contract Confirmation Template below. This is one of only two human touchpoints in the entire Anvil loop; the summary MUST be readable by a non-coder. Do not paste raw YAML and do not ask "does this look right?" without the full template. Render the template as conversational Markdown in the chat, not inside a single fenced block that the user has to parse.accept, yes, or an unambiguous variant), save anvil/contract.yml (already on disk from step 3) and set state.meta.contract_unconfirmed = false via cli/lib/io.js writeFileUtf8 atomic-rename. On reject or on any non-affirmative reply, delete the draft and clear the flag; the user re-enters with a clearer prompt. The meta.contract_unconfirmed flag is the writer surface read by hooks/user-prompt-submit to route prompts to the contracting skill until the user has confirmed. No silent auto-pick. No list-of-N gate.Render exactly these sections, in this order, in the chat. Section headings are verbatim. Section bodies are populated from the draft contract. Keep every bullet to plain English; a non-coder must be able to read the summary top-to-bottom and decide accept/reject without opening any file.
#### What you asked for
Quote the user's intent verbatim in one block quote. No paraphrase. This is source_intent.
#### What I will build, in plain language
One or two sentences translating the contract goal into everyday language. No jargon. If jargon is unavoidable, define it inline in parentheses the first time it appears.
#### How we will know it worked
One bullet per criterion. Each bullet has this shape:
<test name> and it passes", or "the app receives <input> and returns <output>">.<inputs> -> <expected>, taken verbatim from the criterion's functional.inputs and functional.expected fields. If multiple inputs exist, show the two most distinct.If the contract has N criteria, this section has N bullets. Do not omit a criterion. Do not collapse two criteria into one bullet.
#### What I will NOT do
Bullet list of explicit out-of-scope items. Pull from the contract's invariants.public_api_unchanged, no_new_dependencies, and any scope bounds implied by the criteria. If the user's intent mentioned something that is NOT in any criterion, say so here: "You mentioned <X>; I did not include it because <reason>. Tell me to add it if you want it." This surfaces silent omissions (row 9 defeater).
#### Lessons from past runs
If counter_examples is non-empty, render each entry as:
If counter_examples is empty, write a single line: "No prior lessons matched; this is the first run for this pattern."
#### What happens if something fails
Verbatim. Users need to know the failure mode before they accept:
If any criterion fails, I will not mark the work done. I will capture the failure, write a lesson into the Ledger so future contracts inherit it, update this contract with the lesson as a counter-example, and retry up to <loop_cap> times. If it still fails after that, I will stop and hand the decision back to you. I never silently pass a failing criterion.
Replace <loop_cap> with the actual value from the plan when available, else use 3 (the default).
#### The rules I am locking in
Bullet list of invariants in plain language:
invariants.no_new_dependencies: true -> "I will not add any new third-party libraries."invariants.public_api_unchanged names symbols -> "The public surface stays the same: <sym1>, <sym2>, ..."invariants.coverage.new_code_minimum is set -> "New code will be covered by tests at >= <N>%."invariants.no_secret_patterns: true -> "No API keys or secrets will appear in any diff."If there are no invariants, write "No cross-cutting invariants. Each criterion stands on its own."
#### Your decision
End the summary with this exact block:
Accept this contract? Reply `accept` or `reject`.
>
- accept: I will save the contract and proceed to plan and execute it autonomously. The next time you will be asked anything is at /ship (PR review and merge). - reject: Nothing is saved. Tell me what to change - more detail, different scope, different success criteria - and I will redraft from scratch.Do not append any text after this block. Do not solicit free-form feedback. The gate is binary (Invariant 16).
Reject the following shortcuts:
If any of these conditions obtain, the draft is rejected:
contract-drafter agent. Inline drafting fills the main context window with intermediate reasoning and defeats the "orchestrator holds artifacts, not narration" invariant (failure-taxonomy row 16: Context-window collapse).functional.inputs is empty or placeholder text; the human has nothing concrete to confirm against.Before presenting the draft, run in order:
node "$CLAUDE_PLUGIN_ROOT/cli/anvil.js" contract --validate anvil/contract.yml exits 0.functional.inputs entry and a non-empty functional.expected value.node "$CLAUDE_PLUGIN_ROOT/cli/anvil.js" ledger query was run for each extracted pattern and the Counter-examples section reflects the top-five aggregate results, or the section is absent because no lessons matched.anvil/contract.yml's frontmatter version equal to 1.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.