Install
$ agentstack add skill-nicolasapr-contract-tree-change-with-contracts ✓ 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
Change With Contracts
The procedure for changing code in a repo that has a contract tree. It keeps you oriented with cheap reads and turns any boundary change into a deliberate, visible decision.
Hard rule: this skill NEVER cascades on its own. When a change would alter a module's boundary, you present the blast radius and let the user choose preserve-vs-cascade. No boundary-affecting code is touched before that choice.
If the repo has no .contract-tree/ yet, run map-modules first (at least for the area you're touching), then return here.
The six steps
1. Locate
Read .contract-tree/tree.md. Find the module(s) where the task lives. Open only those CONTRACT.md files — read their purpose, io, invariants, and entrypoints. Do not scan the whole tree.
2. Classify the change
Read io.input as the module's precondition, io.output as its postcondition, and each invariant as a boundary guarantee (Design by Contract). Then classify into three — see [../contract-tree/references/principles.md](../contract-tree/references/principles.md) for the compatibility rule and taxonomy:
- Internal (SemVer PATCH) — internals only; precondition, postcondition, and every
invariant stay true. → Implement freely. On finish, re-check invariants; update CONTRACT.md only if something it declares actually changed. No cascade.
- Additive (SemVer MINOR) — the contract changes but stays backward compatible: it
weakens the precondition (accepts more), strengthens the postcondition (guarantees more), or adds a new optional output/entrypoint. Existing consumers still work. → Update the CONTRACT.md; no cascade. This is also the target of a "preserve".
- Breaking (SemVer MAJOR) — it strengthens the precondition (demands more of
callers), weakens the postcondition (guarantees less), removes/renames required I/O, or breaks a declared invariant. → Go to step 3.
When unsure whether a change is additive or breaking, treat it as breaking and compute the radius; a false alarm is cheap, a missed break is not.
3. Compute the blast radius
Follow references/blast-radius.md: from tree.md, follow → edges transitively from the changed module to collect all downstream modules, then open each one's CONTRACT.md to see how it consumes the changing output. Note which are genuinely affected and how.
4. Present the radius and let the user decide
Show the user: what boundary changes, which downstream modules are affected, and their concrete use points. Then offer the two paths explicitly:
- Preserve — find an additive path to the same goal so the provider evolves
without consumers jumping in lockstep (consumer-driven evolution): add a new field/overload instead of changing an existing one, introduce an extension point, adapt at the edge, or deprecate-before-removing. The radius collapses to zero downstream work.
- Cascade — accept the breaking change and propagate it through the affected downstream
modules.
When you present the radius, note how each downstream module is coupled to the changing output (its connascence — a renamed field is weak; a relied-on meaning like "meters" or a positional/algorithmic dependency is strong). Stronger coupling means a costlier cascade and a stronger reason to preserve.
Stop and wait for the user's choice. Do not touch boundary-affecting code before it.
5. Execute the chosen path
- Preserve — implement the boundary-safe alternative in the module. Downstream
is untouched.
- Cascade — change the root module, then each affected downstream module **in
graph order** (upstream before downstream), updating each module's CONTRACT.md as its boundary changes.
6. Close
Update every CONTRACT.md whose boundary changed, and regenerate the affected part of .contract-tree/tree.md if the dependency graph changed. An updated contract is part of "done" — leaving it stale is a bug, because the next task trusts it.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: nicolasapr
- Source: nicolasapr/contract-tree
- License: MIT
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.