Install
$ agentstack add skill-hdkhosravian-loop-contract-skill-loop-contract ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Loop Contract
What this skill produces
Given a raw need, this skill has two responses, one front-door. It first triages (step 0): when an existing skill/plugin/agent already fits, it routes — names that capability and offers to run it. Only when nothing fits does it design, and for a long autonomous job the design is a contract — which, for a DONE job, it then executes rather than handing back as a document. Routing lives in references/triage-routing.md; the rest of this document is the contract — the harder, higher-stakes response.
A contract is the spine of a run — the mission, oracle, phases and budget, written down before the work so the run is disciplined instead of improvised.
In both modes you write it and then execute it yourself (§5) — the document guides the work, it does not replace it. The one exception is an explicit request for a contract to run elsewhere. Either way it must be precise enough that an agent with no memory of this conversation can execute it correctly and stop at the right moment.
When the response is a KNOWN contract, never start doing the described job. If the request is "audit PR #128", you do not audit PR #128 while writing the contract — you write the contract that makes auditing it reliable. If you catch yourself opening the repo to "check something first", stop; you are doing the job instead of designing it.
The prohibition is temporal, not modal. It means: do not start the job while the contract is still unwritten. Once the file exists, execute it — in either mode (§5). Forgetting this is the other failure, and the more common one in practice:
- routing may invoke a fitting capability, after the user confirms;
- contract execution, KNOWN or DONE — you write the contract and then carry it out, until the
named DELIVERABLE exists. Refusing to act there is not discipline, it is the "handed back a document" bug.
This rule binds the designer's hands, not the contract's voice. You abstain from the work; the contract you hand off must compel the executor to do it. For a DONE job (implement, fix, migrate, produce an artifact) the contract commands the executor to change the world and defines completion as that change existing and passing its oracle — never as a report describing it. What comes back from that session is the job's deliverable, not a description of it: working code for an implementation job, every issue fixed and verified for a remediation job, the finished artifact for a plan or design, a verdict + evidence only for an audit. The contract is the run's spec; it is never the run's output.
Always deliver as a file, then present it. A contract pasted as chat text gets mangled and, worse, teaches the user to paste it as a chat message — which is exactly what §Delivery warns against.
Why a contract beats a prompt
Three failure modes kill long agentic jobs. Every section of the contract exists to defeat one:
- "Looks done." Without an external oracle, an agent optimizes for the appearance of completion.
→ §0 mission + §2 evidence standard + a real verifier.
- Context death. Two separate effects, often wrongly merged: re-sending the history each turn makes
cost grow with the square of the turn count, while attention spread over a growing window makes quality degrade well before the window fills. → §4 token policy + the ledger on disk.
- Drift and stall. Around turn 20 the agent is solving something adjacent, or re-running the
same command forever. → §1 termination + §6 stall behaviour + mission recitation.
State the relevant one to the user in a sentence when you deliver. It is why the contract is long.
What belongs to the model, and what belongs to a script
This is the division the whole skill rests on, and getting it backwards produces confident nonsense:
| | belongs to | why | |---|---|---| | Comprehension — reading a roadmap, spec, issue list or PR and working out what is actually being asked; what a task means; whether an item is one thing or three | the model | it is semantic. A regex over someone else's prose finds the conventions its author anticipated and silently misses everything else. | | Verification — did the check run, did it exit 0, is every scoped item accounted for, does the cited path exist, do the counts reconcile | a script | it must be ungameable and repeatable. A model asked to grade its own work will pass it. |
So: the model reads and decides; the script confirms the result. Never the reverse.
The deterministic-before-expensive cascade is about verification — "does this symbol exist, is it called, does this test pass" is a grep and should never cost a model call. It is not about comprehension: "what does this roadmap ask for" is not a grep, and forcing it into one is how a 42-task job becomes 35 tasks with seven silently dropped.
Concretely, when enumerating scope: read the source and list the items yourself. Use a pattern script only as a recall net afterwards — run it, diff its hits against your list, and investigate anything it caught that you missed. Its count is a cross-check, never the authority; a zero or a wildly inflated count means its patterns do not match this project, which is the normal case.
Sweep more than one source for that recall net, because each catches what the others drop: the host's own task list, markdown checkboxes in tracked files (rg -n '^\s*[-*] \[ \]'), open issues (gh issue list), TODO/FIXME comments, and any tracker the project uses. Anything they surface that your reading missed is either a scope item or a deliberate exclusion — decide which, out loud. Two independent sources agreeing on a count is the cheapest confirmation you did not under-enumerate.
Beyond the single run
The steps below design one run. Three loop-eng concerns wrap around it — trajectory observability, pass^k repeatability, and Loop 4 hill-climbing (the contract improving across runs via a retro and ratified decisions). See references/outer-loops.md; the concrete hooks are metrics.jsonl and retro.md in §2, the repeatability note in §1, and §8 of the template. This is the compounding edge the doc calls Loop 4 — most skills stop at the single run.
Workflow
0a. Is this a continuation? Look before you triage.
When the message is short and continuation-shaped — "continue", "keep going", "carry on", "what's left?", "is it done?", "finish it" — do not triage it as a new need and do not ask the user which job they mean. Look on disk first:
cat .claude/loops/INDEX.md 2>/dev/null || ls -d .claude/loops/*/ 2>/dev/null
Loops live in .claude/loops//, and INDEX.md says which are in flight. (Also check the project's Claude memory for a paused-loop note, and fall back to rg --files -g 'scope.jsonl' for a spine left somewhere else by an older run.)
If exactly one is unfinished, that is the job. Run python /scripts/fold_ledger.py --scope /scope.jsonl --ledger /ledger.jsonl --verdicts /verdicts.jsonl --out /dev/null --mode --remaining — its output is the worklist — and carry straight on from the first unfinished item. Do not re-freeze scope, do not re-do finished items, do not summarise the contract back.
If several turn up, name them in one line and ask which. If none does, it is a new need — triage it.
The user should never have to type a flag or a file path. Every --scope, --remaining, --oracle-cmd in this skill is yours to run, not theirs to remember; "continue" is a complete instruction and must work as one.
0. Triage the need — route, else design
Run this first when handed a rough need rather than an explicit job. Loop engineering sets the order: a response is only as good as the verifier that checks it, so fix the oracle before choosing a path, then take the cheapest response a verifier can still check.
- Oracle first. "How will the user know this need is met, without asking a human?" (see
references/oracle-catalog.md). The oracle filters candidates and becomes the success test of the path you pick. Can't name one? Say so — an unverifiable need is a checkpointed collaboration, not an autonomous loop. 1b. Split a bundle first. If the message carries several distinct needs — bugs and features and a perf complaint and an open question — they have different intents and different oracles. List them, give each its own intent/oracle/path, and ask the one question worth asking: which to do now, in what order. Under "don't ask", order them yourself (safety → reported defects → measurable work → open questions → speculative ideas), say the order, and proceed. Never freeze a speculative idea into scope without confirmation. Details in references/triage-routing.md §2a.
- **Classify the need — shape and intent** (per need, if you split).
- Shape — one-shot task · long-running job · question/advice · novel build. Shape sizes the loop;
domain (finance/software/AI…) only sharpens matching.
- Intent — DONE or KNOWN, the decisive axis. Ask: *"if the run returns a perfect report and
changed nothing, is the user happy?" Yes → KNOWN (audit, review, research — the report is* the deliverable; documenting is doing). No → DONE (implement, fix-all, investigate-then-fix, produce-artifact — the changed world is the deliverable; a report is at most a receipt). Intent is orthogonal to size: a long DONE job gets a DONE-shaped contract, never an audit one.
- Route before you design — cheap before expensive. The same instinct that runs the deterministic
sweep before the expensive panel, one level up: reusing something that already exists is the cheap move, bespoke design is the dear one. Survey the live inventory in context — the skills listing, agent types, plugin/MCP tools — and rank each on purpose-match, verifiability (is its output checkable against the oracle?), and cost-fit (the execution-protocol net-token test). A capability you cannot verify against the oracle is a weak fit however on-topic it reads — that false-fit is routing's silent-success failure.
- Decide (full rubric in
references/triage-routing.md):
- strong fit → recommend it, then offer to run (confirm before anything irreversible, §1 APPROVAL);
- DONE job that fits one session → just do it, under the same discipline: write the failing
check first, make the change, re-run it, report the exit code. A contract here is pure overhead and, worse, hands back a document instead of the work;
- long job, no single fit → write a contract (steps 1–5 below — the design branch), and **name its
mode in §0**: KNOWN (deliverable = verdict + evidence) or DONE (deliverable = the change or artifact, gated by an achievement oracle);
- trivial one-shot → do it inline (see Sizing guidance in
references/contract-template.md); - repeats on a schedule ("every week", "keep checking", "monitor…", or one of the standard jobs
— audit · testgaps · deps · optimize · reconcile · docdrift · dataquality · benchmark) → build it as a normal contract, then add the recurrence per references/recurring-jobs.md: fixed oracle, comparable ledger, and a report of what changed rather than the same findings each run;
- novel / no fit → sketch a bespoke solution: components, its oracle, the first step.
- Recommend, then offer to run. Emit a mini-contract — need · deliverable · mode · oracle · path ·
one-line why · first action · the run-offer — and stop there; triage is a decision, not a deliverable. Never auto-run a routed capability without the user's word. The do it row is exempt: for a DONE job you already have the ask — do the work, then report it.
Bounded like any loop: survey once, rank, decide. If nothing clears the bar, stop routing and design — don't re-score in circles.
1. Classify the job and find the oracle
(The contract branch of §0 — for a long-running job with no single existing capability. If triage already fixed the oracle, carry it forward rather than re-deriving it.)
Do this before writing a single line of the contract. The oracle determines everything else.
First carry the intent forward from triage — DONE or KNOWN — because it decides what the oracle must check:
- KNOWN → the oracle checks the verdict's trustworthiness: every row verdicted, evidence as
path:line plus an executed check.
- DONE → the oracle is an achievement oracle: a check that fails on the unchanged world
and can only be turned green by actually doing the work — a repro/acceptance test written and observed red first (go test ./..., cargo test, pytest, dbt test — whatever this project uses), a detector currently returning N>0 required to return 0, a reconciliation that must tie to zero, or (non-code) a component checklist whose items are concretely absent today. A document cannot flip a red check green: that is what makes completion unsatisfiable by documentation. Never retrofit it afterwards.
A multi-item job gets loop engineering per item, not once for the batch. "Implement the remaining tasks", "fix all the issues", "work through the findings" is not one job with one oracle — it is N jobs, and one oracle for all of them is satisfied by doing one of them. So:
- Freeze the scope first — you enumerate it, then check the count against the source. Read the
roadmap, issue list or spec and list every task into scope.jsonl yourself; do not delegate the reading to a pattern script, which finds only the conventions it anticipates. Then establish the expected count independently: the number the user stated ("42 tasks" → 42, it outranks your enumeration), or a recount of the source (rg -c, gh issue list | jq length, wc -l) when the source has a countable structure — a checkbox list does, ADR prose does not, and forcing a grep onto prose gives a confidently wrong number. Where nothing is countable, re-read the source in a second pass and reconcile the two enumerations. If you are short of the expected count, stop and resolve the difference before working — those are the items you are about to silently not do. Pass what you have to the gate (--scope, --expect-scope-count, --scope-count-cmd where a recount is meaningful).
- Choose serial or parallel yourself — parallel when items touch disjoint files and share no
state, serial when they interact. State which and why; do not ask.
- Per item: red → change → green → record. Write the check for this item and watch it fail,
make the change, re-run it and the suite, append fix/fix_verdict/proof_cmd before moving on.
- Each item needs its own proof. One test cited for twenty rows is rejected by the gate — that
pattern is the signature of work that was not done.
- Never stop at the first hard item. Two genuinely different attempts, then BLOCKED with a reason,
then keep going. The run ends when the scope is exhausted, not when something is difficult.
Doing one item well and reporting as though the job is done is the failure this exists to prevent, and it is indistinguishable from success unless the scope was frozen first.
Never tell the user a job is complete without showing the gate's exit line. Everything above is a check the gate performs, and the gate only performs it if you run it — so a "done" claim with no GATE PASSED — N rows folded beside it is exactly the unverified claim this skill exists to eliminate. Report the command and its observed exit status verbatim. If you did not run it, you do not know.
Checkpoint inside long phases; compute the remainder, never recall it. A 40-item job has no phase boundary between item 1 and item 40, so the BUDGET check never fires an
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: hdkhosravian
- Source: hdkhosravian/loop-contract-skill
- License: MIT
- Homepage: https://github.com/hdkhosravian/loop-contract-skill/blob/main/docs/LOOP-ENGINEERING.md
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.