# locks/ — dependency closure locks (packet-level)

Both validator stacks are pinned as a full transitive closure with hashes so a standalone
consumer can reproduce the exact conformance environment.

**Path independence**: all packet scripts resolve the packet root from their own location
(or the `PACKET_ROOT` env override) and never hardcode machine paths — to verify a copied
or mutated packet, run the COPY's own scripts.

## node/ — ajv stack

- `package.json` / `package-lock.json` (lockfileVersion 3), pinned `ajv@8.20.0`.
- Transitive closure (all with sha512 integrity):
  fast-deep-equal@3.1.3, fast-uri@3.1.8, json-schema-traverse@1.0.0, require-from-string@2.0.2.
- Setup + reproduce (verified from a fresh directory):
  ```
  mkdir verify && cd verify
  cp <packet>/locks/node/package.json <packet>/locks/node/package-lock.json .
  npm ci
  # node scripts resolve 'ajv' from AJV_WORKSPACE (not from their own location):
  AJV_WORKSPACE="$PWD" node <packet>/build/check_compile.mjs
  AJV_WORKSPACE="$PWD" node <packet>/schema-corpus/run_schema_corpus.mjs
  ```
  If `AJV_WORKSPACE` is unset or the dependency is missing, the scripts fail closed with
  an explicit diagnostic (exit 2) instead of a raw module-resolution error.

## python/ — jsonschema stack

- `requirements.in`: `jsonschema==4.26.0`.
- `requirements.lock`: generated by
  `uv pip compile requirements.in --generate-hashes --python-version 3.12 -o requirements.lock`.
- Closure: jsonschema==4.26.0 (wheel sha256 `d489f152…` = matches the frozen PINS), attrs==26.1.0,
  jsonschema-specifications==2025.9.1, referencing==0.37.0, rpds-py==2026.9.1,
  typing-extensions==4.16.0 (marker: python < 3.13).
- Reproduce (uv-native; `pip install --require-hashes` is NOT compatible with uv's
  marker-annotated output):
  ```
  uv venv verify --python 3.12
  uv pip sync <packet>/locks/python/requirements.lock --python verify/Scripts/python.exe
  verify/Scripts/python.exe <packet>/build/check_compile.py
  ```

## Findings recorded during lock verification

1. **Marker dependency dropped by default-target compile**: compiling without an
   explicit `--python-version` omitted `typing-extensions`; on Python 3.12 the
   jsonschema import then fails inside `referencing.typing`
   (`TypeVar(default=...)` is 3.13+). The lock MUST be generated with an explicit
   python-version target. (Caught by fresh-environment verification.)
2. **Node ESM resolution**: `import "ajv"` inside a script resolves relative to the
   SCRIPT's location, so running a packet script from an npm-ci workspace used to fail;
   the scripts now resolve dependencies via `createRequire(AJV_WORKSPACE)` instead.
3. **Install path**: `uv pip sync` is the canonical installer for the python lock.

## Fresh-environment verification (rev3, 2026-10-13)

Fresh `uv venv` + `uv pip sync` and fresh `npm ci` were run, then the full packet
suites were executed against the locked environments (commands above):

| suite | result |
|---|---|
| build/check_compile.py | PY_COMPILE: ALL OK (23 files) |
| build/check_compile.mjs (via AJV_WORKSPACE) | AJV_COMPILE: ALL OK (23 files) |
| schema-corpus (both sides, exact stable codes) | cases=99 fails=0 ALL_PASS |
| corpus/ (c14n, loader-gated) | cases: 58 fails: 0 | RESULT: ALL_PASS |
| evidence/pattern_samples | 40/40 ALL_PASS (both sides, exact stable codes) |
| evidence/meta_smoke | ALL PASS |
| build/packet_lint.py | PACKET_LINT: PASS |
| build/lint_mutation_check.py | MUTATION_SUITE: ALL KILLED (25 sabotages + chain + baselines) |
| build/check_readonly_replay.py | READONLY_REPLAY: PASS (tree bit-identical incl. caches) |
| regeneration chain (meta->schemas->manifest->index->lint->compile) | OK, byte-stable |
