agentleFS
maksutovicmaksutovic/joycraft/.github/skills/joycraft-harden/SKILL.md

joycraft-harden

Skill15 starsChanged 52 days agoMITView on GitHub

Invoked by tune, optimize, or session-end to convert eligible boundary prose into machine-checked deny patterns — not a user entry point.

  • Commits and pushes

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 3 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Read the project's boundary file (AGENTS.md, or wherever the ALWAYS/ASK FIRST/NEVER rules live), .claude/settings.json permissions.deny, …

    line 16
  2. Distinctive:

    Semantic downgrade guard: ASK FIRST rules are not NEVER rules.

    line 35
  3. Very specific:

    Already covered: if a rule already matches an existing deny pattern, label it verified and just stamp provenance if the boundary-file line …

    line 45
  4. Very specific:

    Do not write to deny-patterns.txt or settings.json until the human has explicitly approved the diff shown in Step 3.

    line 59
  5. Very specific:

    Never auto-apply. Every write to settings.json or deny-patterns.txt requires the Step 4 approval gate.

    line 88
  6. Distinctive:

    Leave ineligible rules as prose, labeled ineligible.

    line 90
  7. Distinctive:

    Never silently convert ASK FIRST into a hard deny — flag the downgrade.

    line 91

≈ “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

At skill entry, run node docs/.joycraft/check.mjs check --json --session <session-id> once, reusing JOYCRAFT_SESSION_ID if supplied or one ID chosen for this conversation. If the checker is missing or fails, continue the requested skill quietly without retrying setup. Offer updates only for display: true; current, postponed, off, and unknown stay quiet. If automaticUpdate is present, finish this skill, then run its exact command once from the project root: the candidate must verify every safety gate before applying. Other updates require approval. After an offer or automatic attempt, record it with node docs/.joycraft/check.mjs acknowledge <available-version> --session <session-id>. Apply updates only at this workflow boundary; after success, reinvoke the skill or restart the session to load changed instructions.

Harden (Prose Boundaries → Machine Checks)

You are converting eligible ALWAYS/ASK FIRST/NEVER boundary prose into machine-checked form. Prose is a rule the model merely hopes to follow; a deny pattern or hook enforces it. Harden is convert-what-exists — it never interviews from scratch (that's joycraft-lockdown).

Step 1: Read the current state

Read the project's boundary file (AGENTS.md, or wherever the ALWAYS/ASK FIRST/NEVER rules live), .claude/settings.json permissions.deny, and .claude/hooks/joycraft/deny-patterns.txt. These are the only two enforcement surfaces you target. Both are installed by Joycraft's safeguard machinery (npx joycraft@latest init) — you append to the files it produces, you never rewrite the hook script itself, and you never add a new hook framework.

Step 2: Classify each ALWAYS/ASK FIRST/NEVER rule

For every rule, decide eligible or ineligible:

  • Eligible — the rule can be stated as a command regex or file-path pattern with near-zero false positives (e.g. "never push to main/master" → an anchored git push regex).
  • Ineligible — the rule is semantic/judgment-dependent (e.g. "keep dependencies minimal", "changes affect all users"). Leave it as prose and label it ineligible in your run summary. When in doubt, ineligible — judgment stays with the model.

Semantic downgrade guard: ASK FIRST rules are not NEVER rules. Converting an ASK FIRST rule into a hard deny silently removes the "ask" step. If you propose converting an ASK FIRST rule to a deny pattern, flag the downgrade explicitly in the proposal — don't let it pass as a routine conversion.

Anchoring: a regex that would false-positive a legitimate command (e.g. blocking git push origin main also blocking git push origin main-docs) is not safely expressible — anchor with word boundaries (\bmain\b, \bmaster\b) or reclassify ineligible.

Already covered: if a rule already matches an existing deny pattern, label it verified and just stamp provenance if the boundary-file line is missing it — don't duplicate the pattern.

Step 3: Propose exact diffs — PROTOCOL

Show the exact diff for each eligible rule before touching anything:

  • The literal line(s) added to .claude/hooks/joycraft/deny-patterns.txt.
  • The literal string(s) added to .claude/settings.json permissions.deny (create the array if absent; never disturb permissions.allow or the hooks config).

Step 4: Apply only on explicit human approval — PROTOCOL, never auto-apply

Do not write to deny-patterns.txt or settings.json until the human has explicitly approved the diff shown in Step 3. If the human rejects a proposed conversion, the rule stays prose — record the rejection in the harden run summary and move on; do not re-propose it in the same run.

Step 5: Stamp inline provenance — PROTOCOL

For every rule you convert (or verify as already covered), stamp its AGENTS.md line with an inline HTML comment, exactly this format:

<!-- origin: <failure|source> <date>, probation: <model> -->

<failure|source> is either the failure that motivated the rule or the source that established it (a decision, a brief, an incident). <date> is the stamp date. <model> is the current model name — this is what later goes on probation when the model changes. The comment is inline on the rule's own line, invisible in rendered Markdown — no sidecar table.

Step 6: Report

Summarize: rules converted (with the diff applied), rules verified (already covered, now provenance-stamped), rules left ineligible (with why), and any rejections.

Constraints

  • Target only permissions.deny and deny-patterns.txt — never the hook script itself, never docs/templates/, never a new hook framework.
  • Never auto-apply. Every write to settings.json or deny-patterns.txt requires the Step 4 approval gate.
  • Leave ineligible rules as prose, labeled ineligible.
  • Never silently convert ASK FIRST into a hard deny — flag the downgrade.
  • Probation review (a rule's probation: model no longer matches the current model) is surfaced by joycraft-tune, not decided here — harden never auto-retires a rule.

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.