packstruct docs

packstruct audit-conformance

The linter checks pack manifests (section 2 + section 1 of the SPEC). The conformance harness checks the other half: whether a loader honors the spec. That makes the implements: packstruct@1 pin verifiable instead of honorary.

npx packstruct audit-conformance . --loader "node bin/load-packs.js {packs}"
npx packstruct audit-conformance . --loader "node bin/load-packs.js {packs}" --json
                                    # { schema, mode: 'audit', repo, cases, honored, violations }

How it works

The CLI ships verdict-claiming fixture cases (bundled in the npm package under conformance/cases/): one clean bundle, one bundle per SPEC section 5 refusal norm (schemaVersion, kebab-case name, name/dir match, missing entry, empty description, non-dotted version), and a name-collision pair. For each case the harness:

  1. materializes the bundle into a fresh scratch root under the system temp dir;
  2. {packs} in the loader template becomes that bundle root (shell-quoted for you), and the host’s own loader command runs over it;
  3. grades verdict, nothing else: a conforming loader exits 0 on the clean bundle, and exits non-zero AND names the pack on every violation bundle (SPEC section 5 says refusals are nameable - the harness matches pack identity, never refusal jargon, since wording stays host-owned).

Any other outcome is an audit violation naming the case:

npx packstruct audit-conformance: 5/8 case(s) honored by the loader over .
  AUDIT schema-version [audit-refuse]: loader exit 0 (loader accepted) on case "schema-version" - the spec verdict is refuse
  AUDIT clean [audit-accept]: loader exit 1 on case "clean" - the spec verdict is accept

Exit ladder is the same as lint: 0 all cases honored, 1 any case failed (list above), 2 usage error (missing --loader, no {packs} placeholder).

What it deliberately does not check

The harness refuses to grade host cargo beyond the SPEC’s promises: it never judges refusal wording, never evaluates the loader’s output format, and never runs loader code itself - the host command runs in a shell the host owns. If your loader needs more wiring than a one-line command template, wrap it in a shim script and point --loader at that.

Receipt

The house rule (receipt ships in the same commit): packstruct’s own CLI is the first audited loader - npm test runs the 8 bundled cases through node bin/cli.mjs lint {packs} and asserts 8/8 honored, plus both failure directions (a loader that accepts everything fails 7 cases; a loader that refuses without naming the pack fails all 8).