agentleFS
metacircu1armetacircu1ar/hive_skills/skills/input-contract-hardening/SKILL.md

input-contract-hardening

Skill4 starsChanged 2 months agoMITView on GitHub

Make every caller-input boundary enforce its contract before side effects, with precise, private-safe, actionable diagnostics that agree across surfaces. Boundaries include CLI arguments, options and globals; files, pipes and stdin; configuration; socket/RPC/HTTP requests; MCP and tool arguments; and command lines generated by other tools. Use for a focused validation-and-diagnostics pass on a diff, command family, service, or repository, with in-place hardening or read-only proposals. Not a general security audit, error-logging review, or redesign of domain rules.

The file

Show its rules and text

We split this skill into the rules it gives an agent

17 rules. About 0 are common, 16 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈16

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use the host's skill invocation mechanism or provide this file and the same arguments directly.

    line 21
  2. Very specific:

    read-only: Treat the reviewed repository as immutable.

    line 47
  3. Distinctive:

    Use fewer workers when useful work or capacity is limited, and disclose the reduction.

    line 70
  4. Distinctive:

    If delegation is unavailable, prohibited, or fails, finish the affected work yourself.

    line 71
  5. Distinctive:

    Wait for assigned results before synthesis.

    line 73
  6. Distinctive:

    Read applicable repository instructions and reuse the project's existing validators, error types, renderers, and conventions.

    line 98
  7. Distinctive:

    Only explicit caller input is the caller's fault.

    line 109
  8. Distinctive:

    Never blame a caller for something they did not supply, and never let an explicit bad value fall back to an inherited or default one.

    line 121
  9. Distinctive:

    Use or establish one typed input-error shape across all surfaces:

    line 129
  10. Distinctive:

    Status and streams: use a distinct exit status for input errors (for example 2) versus operational failures (for example 1).

    line 144
  11. Distinctive:

    Check pure input before any side effect, and never move a check across an authority boundary:

    line 165
  12. Distinctive:

    Before side effects: run syntax, type, range, relationship, and applicability checks before reading payload files, touching state or …

    line 168
  13. Distinctive:

    Do not reorder authority: keep idempotent replay, request-ID conflict detection, authorization, ownership, lifecycle, and capacity checks …

    line 173
  14. Distinctive:

    Deterministic precedence: when several problems exist, the reported one must not depend on JSON key order, flag order, or hash ordering.

    line 177
  15. Distinctive:

    Read once: read a selected file or config once into a bounded, owned value and carry it to execution.

    line 181
  16. Distinctive:

    Cheap before expensive: run metadata checks such as path existence before loading large models or constructing clients, so trivial mistakes …

    line 188
  17. Distinctive:

    Every external caller and generated invocation exercised after tightening.

    line 258

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Input contract hardening

Find every place where caller-supplied input crosses into the program, and make each boundary enforce its declared contract. Each rejection should name exactly what was wrong, what is expected, and a complete working example, without echoing private values. Apply valid fixes in place by default, or return proposals in read-only mode. The goal is that no caller mistake is silently ignored, guessed around, or reported as an operational failure, and no operational failure is blamed on the caller.

Invocation

/input-contract-hardening [--finders N] [--verifiers M] [--delivery-mode in-place|read-only] [--comment] [<target>]

Use the host's skill invocation mechanism or provide this file and the same arguments directly. With no target, review the current diff. A target may be a pull-request number, branch, commit range, command family, or file/directory path. A path selects that code for review even if unchanged; use . for a repository-wide pass.

--finders and --verifiers are non-negative integer worker counts, each defaulting to 0, excluding the invoking agent. --delivery-mode defaults to in-place. Invalid counts or modes require a corrected invocation before proceeding; do not guess or silently fall back to editing. Counts change delegation, not coverage or model settings. An explicit no-edit instruction selects read-only even without the flag.

Example activations

/input-contract-hardening
/input-contract-hardening --finders 3 --verifiers 2
/input-contract-hardening --delivery-mode read-only src/cli/
/input-contract-hardening --delivery-mode read-only .
/input-contract-hardening --delivery-mode read-only --comment 123

Delivery and worker policy

  • in-place: Complete the review, then apply confirmed, in-scope fixes yourself and verify the resulting changes with checks appropriate to their risk.
  • read-only: Treat the reviewed repository as immutable. Inspect code and available evidence without editing or creating files, applying patches, staging, or running builds, tests, formatters, or generators. Return proposed changes as prose or code snippets and describe checks for someone else to run. Do not write a report or patch file into the repository.

Neither mode authorizes commits or pushes. Posting PR comments requires --comment; in read-only mode it permits publishing proposals, not changing code.

Launch no subagents by default. With zero workers, perform all finding, verification, and coverage checks yourself. Do not infer delegation permission from task size or available tools. Positive counts permit at most N finder workers and M verifier workers, subject to the enclosing workflow's restrictions:

  • Reuse the requested pools across surfaces and findings; do not launch extra gap-check, fixer, or reporting agents. Cover all review angles regardless of worker count.
  • Workers inspect and return findings only. They must not edit files, post comments, spawn agents, or recursively invoke review skills. A verifier worker must not verify its own findings. Local verification is not independent agent verification.
  • Pass each worker the absolute repository path, exact scope, task requirements, relevant context paths, applicable instructions, delivery mode, assigned surfaces, and expected output. The read-only restrictions apply to every worker too.
  • Use fewer workers when useful work or capacity is limited, and disclose the reduction. If delegation is unavailable, prohibited, or fails, finish the affected work yourself.

Wait for assigned results before synthesis. The invoking agent owns final coverage, deduplication, judgment, delivery, and any authorized comments.

1. Inventory every input boundary

Resolve the requested scope using non-mutating inspection. For the default diff, inspect branch changes against the upstream or agreed base together with staged, unstaged, and relevant untracked source files. If the base cannot be established, state that limitation. If the scope is empty, say so rather than claiming it passed.

Build an inventory of every surface through which a caller can influence behavior, and for each one record its parser, its consumers, and its documented contract:

  • CLI positional arguments, options, global options, subcommands, environment variables read as configuration, and default values.
  • User-selected files, directories, symlinks, pipes, FIFOs, /dev/fd paths, stdin, configuration files, and assets referenced from configuration.
  • Socket, RPC, HTTP, and job-queue request envelopes, including nested operation fields, identifiers, cursors, pagination, and replay or request IDs.
  • Tool-call arguments for MCP or agent-hosted tools, including advertised schemas, descriptions, and examples.
  • Command lines and requests that other code generates: installers, setup wizards, service units, test harnesses, acceptance drivers, and wrappers around this program. These are callers too, and tightening a contract can break them.

Read applicable repository instructions and reuse the project's existing validators, error types, renderers, and conventions. Do not assume a framework, language, or parser library. Treat schemas, types, and help text as claims to verify against the runtime code that actually accepts or rejects input. A schema is not enforcement.

For a diff, follow dependencies far enough to establish ordering and consumers, but report defects introduced or re-exposed by the change, or failures to meet explicit task obligations. For a path or command-family pass, existing defects in scope count.

2. Classify each value's origin before choosing its error

Only explicit caller input is the caller's fault. For every value at a failing check, determine whether it came from:

  • an explicit caller argument or field, including an explicitly typed value that equals the default;
  • an omitted value replaced by a default;
  • inherited or derived state, such as a parent record, a branch source, a role, configuration, a saved selection, or a stored record;
  • the environment or a dependency at run time.

Errors on explicit caller input are input errors. Errors on defaults, inherited, configured, or stored values are operational or configuration errors, or corruption. Never blame a caller for something they did not supply, and never let an explicit bad value fall back to an inherited or default one. Keep "omitted" distinct from "explicit null" distinct from "explicit default" wherever the contract or the parser can tell them apart. Do not guess origin from error codes or message text; carry provenance from where the value entered.

3. Enforce one diagnostic contract

Use or establish one typed input-error shape across all surfaces:

  • code: a stable category such as missing, invalid value, out of range, conflicting, unknown, invalid path, or invalid identifier.
  • field: the exact location in the caller's own vocabulary. That means the actual CLI flag or positional name for a CLI, and a JSON pointer such as /arguments/timeout or /operation/request/kind for a wire or tool call. For an unknown key, identify the containing object, never the caller's key text.
  • expected: the accepted form, bounds, and relationships, stated from trusted static metadata.
  • examples: at least one complete, valid invocation or call for the command actually used, which must itself parse.

Rendering rules:

  • Status and streams: use a distinct exit status for input errors (for example 2) versus operational failures (for example 1). Put structured output on stdout and a short human diagnostic on stderr. Keep existing unsuccessful-outcome semantics.
  • Never echo received values in wire or structured output: secrets, paths, URLs, payloads, identifiers, prompts, unknown tokens. Echo on local stderr only for fields explicitly declared public, such as bounded numbers or enums, and escape and bound anything printed.
  • Keep native causes private but attached, so logs and debugging retain the original parser or operating-system error. A wrapper must not replace the primary cause, and a cleanup failure must not hide the original error.
  • Transport typed errors intact across processes and protocols. Decode them strictly: complete metadata or none, no partial, positional, or duplicate-key shapes. Map a peer's field to local flags only through a trusted, per-command table. An impossible or wrong-command pointer is a protocol failure, not a caller error.
  • Follow the protocol's own rules. For example, MCP tool-argument failures are tool results with isError: true, while malformed requests or unknown tools are protocol errors. A diagnostic hidden in a field that clients drop does not help.

4. Place each check deliberately

Check pure input before any side effect, and never move a check across an authority boundary:

  • Before side effects: run syntax, type, range, relationship, and applicability checks before reading payload files, touching state or configuration, acquiring locks, opening sockets, starting providers or services, downloading, or mutating anything. A rejected command must leave the system byte-for-byte unchanged and must not create restart-suppression or other bookkeeping records.
  • Do not reorder authority: keep idempotent replay, request-ID conflict detection, authorization, ownership, lifecycle, and capacity checks where they are. Semantic checks that depend on authorized state stay after authorization. Moving validation ahead of replay can break safe retries of already-accepted requests.
  • Deterministic precedence: when several problems exist, the reported one must not depend on JSON key order, flag order, or hash ordering. Prefer this order: shape, then missing required fields, then unknown keys, then values in a fixed field order.
  • Read once: read a selected file or config once into a bounded, owned value and carry it to execution. Re-reading after a pause, download, or lock acquisition lets a replaced file change what is applied. Revalidate state after waits, not the caller's input.
  • Recheck under locks: compare the exact snapshot used for a decision under the final lock. A change observed there is a concurrent operational event, not a newly discovered caller error.
  • Cheap before expensive: run metadata checks such as path existence before loading large models or constructing clients, so trivial mistakes fail fast.

5. Hunt the defect classes that hide at boundaries

Actively look for each of these; they rarely announce themselves:

  • Silent fallbacks. A malformed optional value is treated as absent: a filter is dropped and the result looks empty, a bad path is replaced by an inherited default, or a wrong-typed mode quietly becomes the default mode.
  • Ignored or inapplicable options. A flag accepted by the parser but unused by the selected command, or meaningful only with another flag. This includes global options inherited by every subcommand, and explicitly supplied defaults.
  • Lenient decoders. Positional arrays accepted where objects are documented, duplicate keys silently collapsed, unit variants not rejecting unknown fields, or null accepted where the schema says required (and the reverse).
  • Schema drift. Advertised required fields, bounds, enums, or nullability that differ from what the runtime accepts, and examples in help or docs that no longer parse.
  • Blocking and special files. Pipes, FIFOs, devices, sockets, or directories supplied where a regular file is expected, which can block forever before any bounded read begins. Open non-blocking and inspect the opened descriptor. A one-shot pipe must not be consumed twice by separate stages or processes.
  • Unbounded reads and limits. Size checks after full reads, limits applied after UTF-8 decoding so an oversized input reports an encoding error instead of a size error, missing byte bounds on strings and identifiers, and integer overflow or silent capping instead of rejection.
  • Inconsistent classification. The same caller mistake reported as an input error by one command or surface and as an operational error by another.
  • Path hazards. Symlinks, non-UTF-8 paths, canonical paths that differ from the selected spelling, and paths resolved against the working directory when they should be relative to the file that references them (or the reverse).
  • Liveness assumptions. A probe result used as proof of ownership or absence. For example, a refused connection does not prove a socket is stale; a live listener with a full backlog can refuse.

6. Keep surfaces consistent

  • One shared pure validator per rule, used by the CLI, wire decoders, tool adapters, and programmatic constructors. A programmatic API must not bypass the relationships that the CLI parser enforces.
  • One registry of trusted field metadata, expected forms, and examples, feeding error messages, help text, tool descriptions, and schemas, with tests that every advertised example parses and every property is described.
  • Tightening a contract updates every caller in the same change. Find generated command lines in installers, setup flows, services, harnesses, and acceptance drivers; give each command only the options it consumes; prove representative generated invocations still parse.
  • Unless project policy says otherwise, do not add compatibility aliases or fallback readers for old malformed input. State intentional contract changes explicitly.

7. Prove it with evidence

Static reading finds candidates; tests must pin behavior. Require, as applicable:

  • Boundary tables for each field: missing, wrong type, empty, minimum, maximum, one past each bound, byte-versus-character limits, control characters, null versus absent, unknown keys, and conflicting or dependent combinations.
  • Privacy assertions: a canary secret, path, or payload never appears in structured output or wire errors, and native causes remain attached for debugging.
  • Ordering and no-side-effect proofs from actual process runs: invalid input against an absent or poisoned root, a sentinel socket or listener that must not be contacted, a held-open stdin that must not be read, and unchanged state, records, and files afterwards.
  • Red-then-green regressions for races, hangs, and protocol misbehavior. Run hanging cases in a bounded child process so the old behavior is proven without wedging the suite.
  • Unfiltered full test suites whenever shared parsing, error, transport, or emission code changes. Check the logs for zero filtered tests; a passing filtered subset can hide stale expectations elsewhere.
  • Every external caller and generated invocation exercised after tightening. Platform-specific code paths must actually build and run on their platform.
  • Golden or snapshot fixtures change only deliberately: re-record narrowly, inspect the diff, and rerun normally. Never regenerate broadly to make failures disappear.

8. Verify, deliver, and report

Deduplicate findings and check each against actual code, actively looking for counterevidence such as an earlier validator, a documented intentional fallback, or an enforced schema. Use the verifier pool if requested; otherwise check locally. Classify each candidate:

  • CONFIRMED: a concrete input reaches a wrong outcome: it is accepted, ignored, misattributed, leaks private data, causes a side effect, or hangs.
  • PLAUSIBLE: the mechanism is supported, but a runtime or configuration condition is unresolved; name the missing evidence.
  • REFUTED: existing handling is sufficient.

Omit refuted candidates. Return distinct confirmed and plausible findings ranked by severity as a JSON array. Each finding has file, line, summary, surface, failure_scenario (the concrete input and the wrong outcome), verdict, proposed_change, and validation_plan; optionally include suggested_code. If no findings survive, return [] with a separate coverage and limitations note.

In in-place mode, work in bounded slices, one command family or surface at a time. For larger changes, write a short plan (contract, ordering, callers, evidence), then implement, and verify each slice before the next. Apply only confirmed fixes, preserve intended behavior and user changes, and report what changed and which checks actually ran. Never represent a proposed test as executed.

In read-only mode, return actionable proposals without applying them. State that no files changed and that proposed changes and validation steps were not executed.

In either mode, briefly identify the inventoried surfaces, the traced callers, the excluded or unverified paths, and any reduced delegation. Do not generate a separate ledger or report artifact unless requested.

With --comment and a GitHub PR target, post findings through an available integration or CLI. Distinguish proposals from local fixes; include a code suggestion only when it fully fixes the issue. If the target is not a PR or posting is unavailable, return findings and explain why no comments were posted.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.