Contributing

Two distinct contribution paths — pick the one that matches where your pack will live.

Both kinds of pack use the same file layout and the same @femto/pack-schema validator. The sections below cover shipped-pack contribution first and then the org-local authoring walkthrough.

Pack layout

A pack lives under packs/<pack-id>/ with a kebab-case id matching ^[a-z][a-z0-9-]{0,62}[a-z0-9]$:

packs/multi-tenancy/
├── pack.json
├── kcs/
│   ├── row-level-security.md
│   └── tenant-scoping.md
└── tests/
    ├── rls-missing-force.md
    └── ...

KC structure

Every KC markdown file must contain these six sections in this order:

  1. ## Concept
  2. ## Invariants
  3. ## Mechanisms
  4. ## Common failures
  5. ## Diagnostic heuristics
  6. ## Citations

The schema enforces per-bullet citations: every claim bullet in the first five sections includes an inline markdown link, and every link URL parses. Link rot is checked weekly by a CI workflow separate from per-PR validation.

The diagnostic-heuristics section is the hardest to write and the one the probe leans on most. Expect it to accumulate slowly — “what an expert looks for when this is subtly wrong” is tacit knowledge, and the corresponding KCs will often ship with thinner heuristic content than declarative content. That’s expected and named; strengthening it over time is one of the highest-leverage PRs a pack can accept.

Test cases

The harness needs held-out ground truth to produce honest AUC / FPR / TPR. A test case is a markdown file with YAML frontmatter:

---
id: rls-missing-force
kcs_in_scope: [row-level-security]
kcs_touched: [row-level-security]
stratum: standard
expected_correctness: 0.9
---

# Scenario

...

A pack cannot be promoted from alpha to stable without a harness of a minimum size covering declarative, procedural, causal, and diagnostic probes — a canonical per-domain test-case specification, not a cherry-picked subset that aligns with the grader’s strengths. Before promotion, run a fidelity spot-check (real interactive sessions vs. harness measurements) and commit .harness/spot-check.md; the calibrate command warns if it’s missing.

PR checklist

Before opening a PR:

Running the harness locally

See docs/calibration.md for the full flow — claude setup-token, the three mandatory disclosure conditions (grader_invocation: "harness-delegated", reads_path: "synthetic_or_empty", delegation_failure_rate), and the alpha → stable promotion rules.

Review model

One maintainer reviews and merges. Review priorities:

  1. Citation quality — authoritative, current, URL-parseable.
  2. Invariants and common-failures for accuracy against the cited sources.
  3. Test-case coverage across declarative / procedural / causal / diagnostic.
  4. Diagnostic-heuristics content depth.

Merge latency scales with operator bandwidth. If PR volume outstrips review capacity, femto will adopt an OWASP-style domain-leader model rather than relax moderation.

Authoring an org-local pack

For compliance, internal policy, or proprietary-domain packs that you don’t want to (or can’t) merge upstream: author the pack in your own repo and femto will load it side-by-side with shipped packs.

The file layout is identical to a shipped pack, just rooted at .femto/packs/ instead of packs/:

<your-repo>/.femto/packs/org-hipaa-access/
├── pack.json
├── kcs/
│   ├── minimum-necessary-disclosure.md
│   └── audit-logging.md
└── tests/
    └── phi-in-debug-log.md

Shape requirements

Identical to shipped packs — the schema does not distinguish between them:

Authoritative sources for compliance KCs

The shipped-pack citation discipline (RFC / vendor doc / OWASP) still applies, but compliance-domain sources are thinner on the ground. Pragmatic substitutes:

Validation locally

bunx femto-validate-pack .femto/packs/org-hipaa-access

Calibration locally (optional)

The harness runs on any valid pack directory. For org-local calibration:

bunx femto-harness run .femto/packs/org-hipaa-access

Writes .harness/report.json inside the org-local pack. Publish internally — these numbers do not appear on the hosted Metrics page. That surface is operator-curated for shipped packs only, per the Gate 1 publish-commitment; org-local reliability is the adopter’s responsibility.

Loading and precedence

On session start, the MCP server walks shipped packs first ($CLAUDE_PLUGIN_ROOT/packs), then org-local packs ($PWD/.femto/packs). First match wins, so shipped packs shadow any org-local pack that reuses their id. Each loaded pack’s source appears in events.jsonl as pack.loaded with source: “shipped” | “org_local” — check the log if you’re unsure which version a session resolved to.

What not to do