ADR-0005 · prompt-lock.json semantics: committed, fail-only-on-check, three hard errors + one warning
Status: Accepted
Committed to git
prompt-lock.json is committed, not gitignored. The analogy to package-lock.json is intentional: it pins the manifest content hashes for reproducible codegen across teammates and CI. A gitignored lockfile would mean every engineer has their own hashes, and the "teammate edits the manifest, CI catches it" story collapses.
Fail-only-on-check at runtime
The internal pull() utility does not throw when the lockfile is stale or missing. Runtime remains permissive. The integrity gate is promptregistry check (and its --tsc variant). This keeps the runtime lean and makes the check command load-bearing.
What counts as drift
promptregistry check evaluates four conditions per Pin:
- Hash drift (hard error): The remote manifest content hash differs from the lockfile hash. This is the silent-shipping bug the lockfile exists to catch — someone edited the manifest without bumping the version.
- Stale generated file (hard error): A generated
.tsheader hash differs from the lockfile hash. Codegen wasn't re-run after a manifest update. - Missing pin (hard error): A generated file's Pin has no corresponding entry in the lockfile. The lockfile is incomplete or hand-edited.
- Orphaned lockfile entry (warning, non-blocking): The lockfile has an entry for a Pin that no generated file references. Housekeeping noise, not a failure.
Considered options
- Gitignored lockfile. Rejected — defeats cross-team reproducibility.
- Fail-on-pull at runtime. Rejected — runtime should not depend on build artifacts for correctness; the check command is the explicit gate.
- Treat orphaned entries as hard errors. Rejected — they are harmless dead weight; failing CI on housekeeping creates noise.
Consequences
- CI must run
promptregistry check(orpromptregistry check --tsc) as a mandatory step. - The check result includes a
warningsarray so the check command can surface orphaned entries without failing the exit code. - The README ships
"typecheck": "promptregistry check && tsc --noEmit"as the canonical build script.