# Monorepo Deep Audit — 2026-07-18 (Second Pass)

A full re-audit of the Oshun monorepo, run the same day the
[2026-07-16 architecture audit](MONOREPO_ARCHITECTURE_AUDIT_2026-07-16.md)
closed its reconciliation ledger. This pass has three jobs the first audit could
not do:

1. **Verify the remediations actually hold in-tree today** (guards wired, gates
   green, no regressions), not just in execution logs.
2. **Audit what the remediation itself created** — new conventions (ratchets,
   registries, presets) have their own failure modes.
3. **Go one level more granular** — per-project target/executor census,
   index-SHA duplicate census, workflow filter glob-testing, foundation-lib
   adoption counts — places the first audit sampled.

Every number below was measured directly on this tree (branch `oshun-v1-nisaba`,
head `5d7ed35d4b`) on 2026-07-18. No number is carried forward from the previous
report.

---

## 1. Executive summary

**The 2026-07-16 remediation held.** Forbidden-path guard green, conventions
ratchet green at exact baselines, services→apps and R-8 path rewiring left zero
stale references in workflows, express is down to one dormant package,
Rust/Python lock coverage held, file naming is 99.8 % kebab-case. The repo is in
materially better shape than it was two days ago.

**But the audit machinery has three cracks, and the taxonomy has regrown
weeds:**

| #   | Severity | Finding                                                                                                                                                                                    |
| --- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1   | **P0**   | The domains registry gate (`check-registry.mjs`) is **red on this branch today**: `testing/prompt-injection` uses unregistered `scope:testing`.                                            |
| 2   | **P0**   | The conventions ratchet has an institutionalized bypass: 4× "grandfather pre-ratchet files merged from main" commits raised the `.test.ts` baseline 12,602 → 12,699.                       |
| 3   | **P0**   | Root markdown landfill regrew within 48 h of the cleanup: 5 dated audit/TODO files (07-15…07-17) at root; nothing enforces the `docs/audits/` convention.                                  |
| 4   | **P1**   | Two zero-consumer foundation libs (`@oshun/resilience`, `@oshun/collections`) while the ratchet grandfathers 23 local CircuitBreakers + 128 local `sleep()`s with no burn-down.            |
| 5   | **P1**   | `apps/v4` and `apps/v5` (arrived via R-8) contain **zero** `project.json` — invisible to the nx graph, recreating the "hollow apps" class H-6 fixed.                                       |
| 6   | **P1**   | R-8 residue: `V2/tools/esports` is a live nx project under a `V2/tools/*` workspace glob; `V5/tools/` holds 137 code files — "product roots keep ue/docs/ops only" is not yet true.        |
| 7   | **P1**   | Target-name drift across 3,445 projects: `typecheck`/`type-check`/`typecheck:ts`, `fmt`×422 vs `format`×30, `test-integration` AND `test:integration` — ~550 check-style targets uncached. |
| 8   | **P2**   | 240 exact-duplicate source clusters (309 redundant copies), incl. a 270-line `math.rs` duplicated 10× across neith crates and pairwise-duplicated React components (arete↔demeter).        |
| 9   | **P2**   | 97 npm deps hard-pinned at conflicting ranges (vitest at 11 distinct ranges); catalog adherence 66 %.                                                                                      |
| 10  | **P2**   | 3,445 generated READMEs with no CI drift check; `infra/README.md` already stale (documents `deploy/*` as live after its absorption).                                                       |

The deep pattern behind findings 1–4: **the remediation built enforcement
machinery, but parallel sessions route around it**. Gates that only run on this
branch's PRs don't bind the five other worktrees pushing to main; baselines that
can be bumped in a `chore:` merge commit aren't ratchets, they're counters. The
highest-leverage work now is not more cleanup — it's making the existing
machinery binding at the merge point.

---

## 2. Methodology

- **Scale**: 129,219 tracked files; 3,445 nx projects (3,445 `project.json`);
  3,287 `package.json`; 953 `Cargo.toml` under 17 workspace roots; 83
  `pyproject.toml` (78 locks); 7,080 tsconfig files; 2,669 vitest configs; 102
  workflows; 1.7 GB shared pack.
- **Census tools**: every `project.json`/`package.json` parsed with node (0
  parse failures); exact-duplicate detection via `git ls-files -s` index SHAs
  (free, whole-repo, no sampling); workflow path filters glob-tested against
  `git ls-files` with GitHub's `*`-does-not-cross-`/` semantics; guards
  (`check-forbidden-paths.sh`, `check-conventions-ratchet.mjs`,
  `check-registry.mjs`) executed live.
- **Parallelism**: main-loop only (session-limit discipline); no agent fan-out.
- Findings are lettered by dimension (A hygiene, B structure, C build, D deps, E
  DRY, F conventions, G CI, H architecture, I testing/docs, J deferrals) and
  numbered within.

---

## 3. What held (verification of the 2026-07-16 remediation)

Checked directly, all green today:

- `scripts/check-forbidden-paths.sh` — passes; wired in the `ci.yml` quality
  job; correctly guards `.build/`, backups, build-info, generated HTML, and the
  six retired roots (`deploy/`, `infrastructure/`, `platform/`, `systems/`,
  `DOMAINS/`, `tara/`).
- `tools/conventions/check-conventions-ratchet.mjs` — passes; all 7 families
  exactly at baseline (pino 29, pg 17, ioredis 26, process.env 1302,
  CircuitBreaker 23, sleep 128, `.test.ts` 12,699 — but see A-2 on how that last
  baseline moved).
- **services→apps (B-5/R-9)** and **R-8 (V5/V2/V4)** — zero workflow path
  filters reference any moved tree; `apps/{concordia,psyche,metis}` live.
- **R-6 infra unification is now COMPLETE** — one `infra/` root; the `deploy/*`
  half (still "queued" in the prior ledger) has been absorbed (`infra/compose`,
  `infra/vault-deploy`, `infra/k8s-deploy`, per-domain trees), and the `deploy/`
  root is resurrection-guarded.
- **D-3 framework policy** — express: 1 package (a docs extras fixture), fastify
  96, hono 52, Nest 16 frozen, koa 0.
- **D-5/D-6** — 953 Cargo.toml under 17 workspace roots; Python 78/83 locks.
- **F kebab naming** — 29,144 kebab vs 64 camelCase source files in `libs/`.
- **No tracked junk** — zero `__pycache__`/`.pyc`/`.DS_Store`; only 8 `.log`
  files, all inside the deliberate `evidence/` bundle.
- Largest tracked blob is `pnpm-lock.yaml` (4.7 MB) — the history-rewrite-sized
  artifacts are gone from the tip.

---

## 4. Findings

### A. Repo & git hygiene

**A-1 (P0) Root landfill regrew within 48 hours.** Five dated audit/TODO
documents were added at the repo root _after_ the A-5 cleanup established
`docs/audits/` as the home for reports:

| File                                                   | Lines | Added      |
| ------------------------------------------------------ | ----- | ---------- |
| `V1_V9_AUTONOMOUS_CONTENT_SOTA_AUDIT_2026-07-15.md`    | 2,182 | 2026-07-15 |
| `V1_V9_AUTONOMOUS_CONTENT_SOTA_GAP_CLOSURE_TODOS...md` | 2,051 | 2026-07-15 |
| `V1_V9_SOTA_AUDIT_REVIEW_2026-07-15.md`                | 334   | 2026-07-15 |
| `DOCS_CENTER_PAGE_AUDIT_2026-07-16.md`                 | 919   | 2026-07-16 |
| `HATHOR_YEMAYA_IDEATION_SOTA_TODOS_2026-07-17.md`      | 751   | 2026-07-17 |

Plus pre-existing root strays never adjudicated: `ISIS_TODOS.md` (523),
`ISIS_TODOS_2.md` (3,215), `ISIS_GAPS/` (9 files), and
`V1_RESIDUAL_AUDIT_2026-06-11/` (13 files). The convention exists; nothing
enforces it. **Recommendation**: extend `check-forbidden-paths.sh` with a root
`*.md` allowlist (the ~14 legitimately root-level, tooling-parsed files: README,
CLAUDE, AGENTS, ARCHITECTURE, DOMAINS, SECURITY, etc.). New reports then fail CI
at the root and pass in `docs/audits/`.

**A-2 (P0) The ratchet has an institutionalized bypass.** Four commits titled
`chore(ci): grandfather pre-ratchet files merged from main` appear in recent
history; the `.test.ts` baseline moved 12,602 → 12,695 → 12,699. The mechanism:
parallel sessions on other branches (without the ratchet, or predating it) add
`.test.ts` files / raw imports; when main is merged into this branch, the gate
goes red _here_, and the merge session "fixes" it by raising the baseline. Each
individual bump is defensible; collectively they mean **the ratchet binds only
authors on this branch** — exactly the population that already follows the
convention. **Recommendation** (pick one, in preference order): (1) run the
ratchet as a required check on the main branch itself (push-time), so the
violation fails where it's introduced; (2) make baseline files
CODEOWNERS-protected so bumps need explicit review; (3) at minimum, have the
grandfathering commit _rename_ incoming `.test.ts` files instead of counting
them.

_Live evidence, same day_: while this audit was being committed, a merge from
main brought in two new `.test.ts` files
(`apps/oshun/bff/src/data-deletion/saved-claim-passage-eraser.test.ts`,
`.../nisaba/state-durability.integration.test.ts`) and turned the gate red
(12,701 vs 12,699), forcing the fifth bump in the sequence. Why the rename fix
(option 3) was not applied at merge time, verified rather than assumed: the
files' exact paths are pinned in the `evidence/v1-v9/V1-002.md` execution ledger
(a machine-adjacent record), the owning app's local corpus is 845× `.test.ts` vs
7× `.spec.ts`, and the files belong to another session's in-flight work — a
merge commit must not rewrite them. (A subtlety checked en route:
`apps/oshun/bff/vitest.config.ts` declares `include: ['src/**/*.test.ts']`,
which _looks_ like it would orphan `.spec.ts` tests — but vitest's `mergeConfig`
concatenates it with the base config's `{test,spec}` globs, so both suffixes run
and the local line is merely redundant. Config-reading alone would have gotten
this wrong; `vitest list` settled it.) This confirms the recommendation ordering
above: only option 1 — running the ratchet where files are _authored_ — actually
stops the erosion; merge-time enforcement structurally cannot.

**A-3 (P2) Playwright visual snapshots are tracked for two platforms.**
`apps/oshun/web/e2e/visual-regression-pages.spec.ts-snapshots/` carries ~2 MB
PNGs in `-darwin` _and_ `-linux` variants for dozens of pages. Binary snapshot
pairs are the single biggest recurring blob class at the tip.
**Recommendation**: pick the CI platform (linux) as the only committed baseline
and gate darwin runs behind `--update-snapshots` locally, or move snapshots to
LFS (95 LFS patterns already exist; only 23 objects use them).

**A-4 (P3) Pack size.** 1.7 GB shared across worktrees; the measured rewrite
(runbook `HISTORY_REWRITE_RUNBOOK_2026-07-18.md`) would yield ~889 MB. Remains
owner-gated — correctly so.

**A-5 (P3) Root script count**: 132 (was 128 at D-4 close). Watch, don't act.

### B. Folder structure & taxonomy

**B-1 (P1) R-8 is "complete" but V-root code remains.** The decision record
states "Product roots keep ue/docs/ops only." Measured today, outside `ue/`:

- `V2/tools/esports` — a **live nx project** (`@v2/esports-tools`, 8 TS sources)
  reached via the `V2/tools/*` glob still present in `pnpm-workspace.yaml` line
  88;
- `V5/tools/` — **137 code files** (198 total: missions, vehicles, xr,
  workshop-moderator, vtuber-companion, …);
- `V2/tools/validate-v2-docs.py`; `V4/.ci/{run-gate,changed-gates}.mjs` (the
  latter two are gate infrastructure and legitimately "ops").

The three staged moves covered `{services,web,scripts}`; `tools/` was never in
scope. **Recommendation**: a fourth R-8 change: `V2/tools`, `V5/tools` →
`apps/v<n>/tools-*` (or `libs/v<n>/…` for the library-shaped ones), delete the
`V2/tools/*` workspace glob, and only then update the decision record's
completion claim.

**B-2 (P1) `apps/v4` and `apps/v5` are nx-invisible.** Zero `project.json` under
either tree (only `package.json`/`Cargo.toml`), while siblings v3/v6/v7/v8/v10
have per-service nx projects. Consequences: `nx affected` cannot schedule them,
the boundary/tag system cannot constrain them, and their verification runs only
through per-product script fleets. This recreates the "hollow apps" class the
prior audit's H-6 pass eliminated — introduced this time by the R-8 move itself.
**Recommendation**: per-service `project.json` with `scope:v4`/`scope:v5` tags
wrapping the existing cargo/pnpm commands (the v3/v6/v7 files are the template).

**B-3 (P0) The domains registry gate is red.**
`node tools/domains/check-registry.mjs` fails today:
`scope tag "scope:testing" is used by projects but not registered` — from
`testing/prompt-injection/project.json`. Whoever added the prompt-injection
harness tagged it with a scope the registry doesn't know. Two distinct fixes,
both needed: register (or retag to an existing governance scope) **and** note
that this proves the gate isn't running where that project landed (see A-2's
pattern).

**B-4 (P2) Flat-app naming breaches.** `apps/euterpe-studio-web` (should be
`apps/euterpe/studio-web`; the euterpe domain exists in libs and the app even
has its own nested `node_modules`) and `apps/neith-vault` (→
`apps/neith/vault`). `apps/infra` is a third oddity: infrastructure services
(gpu-dispatcher, runpod-metrics) under a pseudo-domain named identically to the
root IaC tree `infra/` — rename to a real owner domain or
`apps/platform-services/`.

**B-5 (P2) Root directory dregs** (each small, all confusing):

- `crates/maya-terrain-deform/` — an **orphan duplicate** of
  `libs/maya/engine-core/crates/maya-terrain-deform` (only the Cargo.toml is
  tracked; `src/` exists untracked on disk; the engine-core workspace references
  its own internal copy). Delete.
- `static/` — a compiled webpack bundle (2.2 MB `main.js` + runtime/styles),
  committed 2026-01-10 during workspace init; nothing references it. Delete.
- `types/` — one file (`global-jsx.d.ts`); fold into `configs/` or the consuming
  tsconfig.
- `evaluation/` — one file (`human-gold/acquisition-registry.v1.json`); fold
  into `evidence/` or the owning domain.
- `openapi/` — 4 files including **two timestamped `.backup-*` files tracked in
  git** (`openapi/lilith/openapi.yaml.backup-1760592604742`,
  `.schema-backup-1760592952186`) plus
  `docs/domains/lilith/extras/stoplight/.spectral.yaml.backup`. Delete the
  backups; then decide whether root `openapi/` merges into per-app
  `apps/<domain>/*/openapi/` (the dominant pattern — e.g.
  `apps/yemaya/api/openapi/`).
- `tests/` (28 files) vs `testing/` (296 files) — two root test trees with no
  README stating the split. `testing/` = per-domain harnesses (bellona
  remote-control, prompt-injection, e2e page objects); `tests/` = cross-domain
  integration flows. Merge `tests/` into `testing/integration/` or document the
  rule.

**B-6 (P2) Nested/overlapping project roots.** `libs/psyche/project.json`
(`psyche-platform`) declares `sourceRoot: libs/psyche` — overlapping all 134
child projects — plus a 40-entry hand-maintained `implicitDependencies` list.
Any file change in any psyche lib invalidates psyche-platform's cache and the
list drifts silently. Same pattern smaller:
`libs/iris/agents/computer-use/native/` contains a child project at
`native/ts/`. **Recommendation**: replace domain-level umbrella projects with an
nx `run-many --projects=tag:scope:psyche` alias; if the umbrella must stay,
generate `implicitDependencies` from the registry.

**B-7 (P3) Depth and taxonomy variance in libs/.** 2,693 projects at the
canonical `libs/<domain>/<lib>` depth; 237 at depth 4; 92 at depth 5–6 — iris
alone has 154+ deep projects under a three-level taxonomy
(`accessibility/visual/alternatives`) no other domain uses. Not worth a mass
move; worth a written rule for _new_ libs ("depth 3 unless the domain has an
approved taxonomy README").

**B-8 (P3) V3 root doc landfill.** 53 SCREAMING_CASE validation `.md` files sit
loose at `V3/` root (alongside the same-purpose `V3/validation/` and `V3/docs/`
dirs). Fold into `V3/docs/validation/`.

### C. Build system & Nx

**C-1 (P1) Target-name drift, quantified.** Across 3,445 projects / 12,600+
targets:

| Concept    | Variants found                                                          |
| ---------- | ----------------------------------------------------------------------- |
| typecheck  | `typecheck` 1,265 · `type-check` 48 · `typecheck:ts` 33                 |
| format     | `fmt` 422 · `format` 30 · `format-check` 13                             |
| int. tests | `test:integration` 10 · `test-integration` 8 (both live simultaneously) |
| coverage   | `test-cov` 24                                                           |
| cargo      | `cargo-test` 17 (beside `test` wrapping cargo elsewhere)                |

`nx.json` `targetDefaults`/`cacheableOperations` cover only the 6 canonical
names, so **1,521 variant-named targets are uncached**, ~550 of them check-style
(fmt/type-check/test-cov/cargo-test/format-check) that would benefit directly.
**Recommendation**: publish the canonical target vocabulary in
`docs/conventions/`, add the five variant names to `targetDefaults` with
`cache: true` as a bridge, then codemod the renames domain-by-domain (the
392-launcher normalization from the grind session is the template).

**C-2 (P1) 7,173 `nx:run-commands` targets** remain the dominant executor (vs
2,056 `@nx/eslint:lint`, 1,846 `@nx/vite:test`, 1,429 `@nx/js:tsc`). This is the
standing R-14 debt; every standardization slice (presets, launchers, target
names) shrinks it. Also: two vitest executors coexist — `@nx/vite:test` (1,846)
and `@nx/vitest:test` (33); converge the 33.

**C-3 (P2) `nx.json` staleness.** The eslint plugin excludes
`["lilith/**", "yemaya/**", "apps/**"]` — the first two roots no longer exist
(retired in R-7/R-9). `CLAUDE.md`'s "Project Structure" line likewise still
lists root `lilith/`, `yemaya/`. Both are five-minute fixes that end real
confusion (this audit initially went looking for those roots).

**C-4 (P2) Two tsconfig preset families.** Root `tsconfig.{app,lib,spec}.json`
(nx-classic) AND `configs/tsconfig/{base,library,node,service}.json` (83
adopters). Meanwhile 2,655 tsconfigs extend `tsconfig.base.json` directly with
hand-rolled options. Pick `configs/tsconfig/` as canonical (it matches the
`configs/vitest/`, `configs/eslint/` pattern), fold the root trio into it, and
grow adoption with the same hash-class method used for vitest.

**C-5 (P2) `nx release` glob likely inert.**
`release.projects: ["libs/*", "apps/*"]` — depth-2 path globs against project
roots that live at depth 3+. If `nx release` is expected to version anything
beyond the four depth-2 projects (`libs/{contracts,openapi,proto,psyche}`),
verify `nx release --dry-run` enumerates what ADR-0073 intends.

**C-6 (P3)** 14 projects have zero targets; `configs/` mixes tooling presets
with `configs/nous/training/*.json` experiment data (relocate to the nous
domain).

### D. Dependency management

**D-1 (P1) Hard-pin drift.** 13,376 dependency entries: 66 % `catalog:`, 25 %
`workspace:`, **1,207 hard pins**, of which **97 packages are pinned at multiple
conflicting ranges**. Worst: vitest at **11 distinct ranges** (`^1.0.0` →
`^3.2.4`), jose ×5, @fastify/websocket ×4 (`^8`…`^11`), date-fns (`^2`/`^3`),
uuid (`^9`/`^10`), ajv, semver, dompurify, nodemailer…. **Recommendation**: a
catalog long-tail wave — for each multi-range dep, add the canonical version to
the catalog and codemod `"dep": "<range>"` → `"dep": "catalog:"`; 354 catalog
entries exist, the mechanism is proven.

**D-2 (P3) Renovate** covers docker digests + npm patch grouping; add a rule
targeting `pnpm-workspace.yaml` catalog entries (or verify `config:recommended`
already bumps them) so the catalog doesn't fossilize.

**D-3 (P3) Python manifests**: 78/83 locks (5 documented never-resolvable) —
held; 14 legacy `requirements.txt` remain for eventual pyproject conversion.

### E. DRY — whole-repo exact-duplicate census (index SHAs)

Method: group every tracked blob by its index SHA — zero-cost, no sampling,
exact-match only (near-duplicates are strictly additional).

**E-1 (P2) Config duplication = the next preset slices, precomputed.** 524
duplicate clusters among non-test code; the top clusters are ALL
`vitest.config.ts` — the 12 largest hash classes alone cover ≈887 files (268× +
195× + 70× + 53× + 47× + 44× + 43× + 38× + 36× + 32× + 31× + 30×). With
760/2,669 configs already one-line preset re-exports, slice 3 of the R-14 dedup
can be generated mechanically from this census.

**E-2 (P2) Real source duplication: 240 clusters, 309 redundant copies.**
Notable families:

- `libs/neith/spatial-*`: a **270-line f64 linear-algebra module (`math.rs`)
  duplicated 10×** across crates. The header says "dependency-free" deliberately
  — but ten copies of Vec3/quaternion math drift independently. A
  `neith-spatial-math` micro-crate inside the existing umbrella preserves the
  no-external-deps property while deduplicating.
- `build.rs` duplicated 11× (kalika eels/electronic-structure/…) and 7×
  (euterpe/kalika native crates).
- `version.ts` one-liners duplicated 13× (bellona) + 12× (isis) — generate from
  package.json at build, or accept and stop counting.
- `apps/lilith/svc-*`: `types.ts` (6× + 4×) and `app.ts` (3×) — service scaffold
  clones; extract to a lilith service-kit or leave, but record the decision.
- **arete ↔ demeter web apps share pairwise-identical components**
  (`ProtectedRoute.tsx`, `PageHeader.tsx`, `Input.tsx`, test setup) — a
  cross-domain UI-kit candidate (or template lineage worth a `docs/conventions/`
  note so they're allowed to diverge deliberately).
- `openapi-contract-utils.ts` identical across bellona/hathor(+2 more); e2e
  `fixtures.ts` in two 5× families; `.storybook/test-runner.ts` 4×.

**E-3** Ratcheted families (pino/pg/ioredis/env/CircuitBreaker/sleep) hold at
exact baselines — see A-2 for the caveat on _how_ they hold.

### F. Conventions

**F-1 (P2) History is 40 % merge commits.** 16 of the last 40 commits are
`Merge remote-tracking branch 'origin/main'` (across at least three active
session branches). Conventional-commit discipline is otherwise clean (0
non-merge violations in the sample). The two-line push protocol (branch + main)
times N parallel worktrees is the cause. Worth an explicit owner decision:
either accept merge noise as the cost of the workflow, or move to short-lived
branches + a single fast-forward main.

**F-2 (P2) 3,445 READMEs, no drift gate.** The F-3 generator
(`tools/docs/generate-lib-readmes.mjs`) produced 2,466 of them from registry +
package descriptions, but no CI job re-runs it in `--check` mode. Package
descriptions will change; READMEs will lie. Add a drift check beside the
registry check in the quality job.

**F-3 (P3) eslint monolith**: 1,579 lines (one lilith carve-out landed in
`configs/eslint/`). The F-5 composition plan remains valid; continue slices with
the `--print-config` byte-identical proof method.

### G. CI/CD

102 workflows; 64 use the shared composite setup action; 26 have schedules (the
two nightly COST-disabled ones documented). The services→apps and R-8 rewiring
left **zero** stale references to moved trees — the glob-test method works.
Remaining drift, found by glob-testing every `paths:` filter:

**G-1 (P2) Nine genuinely dead filter lines** (filters that can never match a
tracked file — the workflow still fires via its other, live filters):

| Workflow                     | Dead filter                                      | Why                                                 |
| ---------------------------- | ------------------------------------------------ | --------------------------------------------------- |
| `tara-ci.yml`                | `tara/**`                                        | root retired (R-7)                                  |
| `sophia-phase6.yml`          | `libs/oshun/sophia-client/**`                    | no such lib (libs/oshun has `evidence-sophia`)      |
| `vdocs-reader-ui.yml`        | `vdocs-index.html`, `vdocs-search-index.js`      | untracked generated files — push filters can't fire |
| `v2-multiplatform-build.yml` | `rust-toolchain.toml`                            | not at root                                         |
| `capability-truth-drift.yml` | `evidence/placements/**`, `evidence/releases/**` | trees don't exist (only `evidence/v1-v9/`)          |
| `codeql.yml`                 | `**.jsx`                                         | zero tracked .jsx                                   |

Delete the lines (or create the anticipated `evidence/` trees if
capability-truth expects them soon). Cheap, and it keeps the glob-test method's
signal clean for the next audit.

### H. Architecture

**H-1 (P1) Foundation libs: build ≠ adoption.** Import census (path-alias aware,
both quote styles):

| Lib                  | External importers |
| -------------------- | ------------------ |
| `@oshun/math`        | **1,982**          |
| `@oshun/config`      | 24                 |
| `@oshun/http-client` | 29                 |
| `@oshun/events`      | 15                 |
| `@oshun/bff-kit`     | 13                 |
| `@oshun/ids`         | 7                  |
| `@oshun/collections` | **0**              |
| `@oshun/resilience`  | **0**              |

`@oshun/resilience` (backoff/circuit-breaker/retry/sleep, built 2026-07-16 as
the DRY-wave landing zone) has **zero consumers**, while the ratchet
grandfathers 23 local CircuitBreaker classes and 128 local `sleep()` defs
forever. The math lib proves adoption works when a wave drives it.
**Recommendation**: either run one adoption wave (the 128 sleeps are mechanical;
each adoption lowers the baseline, making the ratchet monotonically tighter) or
delete the zero-consumer libs — an unused foundation lib is negative value: it's
the thing the next duplicate-writer is blamed for not using.

**H-2 (P1) 33 projects have no `scope:` tag** (aphrodite chat/devices/payment,
six veritas apps, aja distributed-workers, …) — the boundary rules cannot see
them. The registry check catches _unknown_ scopes but not _absent_ ones; add an
absent-scope assertion to `check-registry.mjs` and tag the 33.

**H-3 (P2) `libs/shared` needs a curation pass** (59 libs):

- Overlap pairs with near-identical mandates: `events` (typed in-process
  emitter) vs `event-bus` (cross-domain bus) — names don't communicate the
  split; `auth` vs `auth-primitives`; `logging`/`metrics`/`tracing` as three
  micro-libs beside `bff-kit`'s own tracing.
- **Domain code in shared**: `libs/shared/tara-live-class-booking` (488-line
  feature lib whose only consumer is an oshun-web e2e spec) — move to
  `libs/tara/`.
- A `libs/shared/README.md` taxonomy (what earns "shared", the overlap-pair
  adjudications) would prevent regrowth; the DEPRECATIONS.md pattern already
  exists for the exits.

**H-4 (P3)** `infra/` post-consolidation duplicate pairs need a second-pass
merge or a README note: `k8s` + `k8s-deploy`, `vault` + `vault-deploy` +
`neith-vault`, `terraform` + `terraform-v1`. And `infra/README.md`'s live-trees
table still lists `deploy/{…}` as a live tree — stale the day after the
absorption. Fix the table now; merge the pairs when each owner window allows.

### I. Testing & docs

**I-1 (P2) Coverage thresholds are enforced in <5 % of projects.** Of 2,669
vitest configs, ~121 enforce thresholds (70 via the
`node-lib-coverage-thresholds` preset, ~81 hand-rolled). The isis
coverage-formulas gate covers its domain; everywhere else, coverage reporting
exists but nothing fails. **Recommendation**: make
`node-lib-coverage-thresholds` the default preset for _new_ libs (generator
default), and promote domains to it one at a time — do not attempt a repo-wide
threshold flag-day.

**I-2 (P3)** Suffix split frozen at 11,570 `.spec.ts` / 10,191 `.test.ts` — as
designed, but see A-2: the freeze only binds where the ratchet runs.

**I-3 (P3) docs/ taxonomy stragglers**: `docs/kalika/`, `docs/oshun/` sit beside
the `docs/domains/<domain>/` pattern that every other domain follows — fold in.

### J. Deferral scorecard (from the 2026-07-16 ledger, verified in-tree)

| Deferral                    | Status today                                                                                      |
| --------------------------- | ------------------------------------------------------------------------------------------------- |
| R-6 deploy/\* half          | **DONE** since ledger (one `infra/` root) — but README stale + duplicate pairs (H-4)              |
| R-8 V5/V2/V4 convergence    | **DONE** with zero-flip proofs — residue: V2/tools, V5/tools (B-1); apps/v4+v5 nx-invisible (B-2) |
| History rewrite             | Owner-gated, runbook current, pack 1.7 GB → ~889 MB measured                                      |
| F-5 eslint split            | 1 slice (lilith); 1,579-line monolith remains                                                     |
| C-5 tsconfig presets        | 83 adopters; two competing preset families now exist (C-4)                                        |
| R-14 target standardization | vitest presets 28 % (760/2,669); 7,173 run-commands; target-name drift measured (C-1)             |
| R-13b generator collapse    | contract ×14 family = documented refusal (stands); scripts/ holds 2,764 code files per-domain     |
| A-6 LFS tail                | 95 patterns in .gitattributes, 23 LFS objects — landed                                            |

---

## 5. Prioritized recommendations

### P0 — make the machinery binding (hours, not days)

1. **Fix the red registry gate**: register `scope:testing` (or retag
   `testing/prompt-injection` to an existing governance scope). One line + one
   tag edit.
2. **Close the ratchet bypass**: run `check-conventions-ratchet.mjs` +
   `check-registry.mjs` as required checks on main pushes (they already run in
   ci.yml quality — confirm that job is required on every branch and on main),
   and CODEOWNERS-protect `tools/conventions/conventions-ratchet-baseline.json`
   so baseline bumps require explicit review.
3. **Guard the root**: add a root-`*.md` allowlist to
   `check-forbidden-paths.sh`; move the five 07-15…07-17 reports plus
   ISIS_TODOS×2/ISIS_GAPS/V1_RESIDUAL_AUDIT into `docs/audits/` (with
   redirects/pointers if tooling parses them).
4. **Delete tracked junk**: `openapi/*.backup-*`, `.spectral.yaml.backup`,
   `static/`, `crates/maya-terrain-deform/`. Four `git rm` commands.

### P1 — finish what R-8/R-12 started (days)

5. **R-8 slice 4**: move `V2/tools`, `V5/tools` under `apps/`; drop the
   `V2/tools/*` workspace glob; then the completion claim is true.
6. **nx-cover apps/v4 + apps/v5**: per-service `project.json` with scope tags,
   wrapping existing cargo/pnpm commands (v3/v6/v7 files are the template).
7. **Tag the 33 untagged projects** and extend `check-registry.mjs` to assert
   scope-tag presence, not just validity.
8. **Resilience adoption wave OR deletion**: 128 grandfathered `sleep()`s are a
   mechanical codemod onto `@oshun/resilience`; each adoption lowers the ratchet
   baseline. If nobody will drive it, delete the zero-consumer libs and record
   the refusal — an unadopted foundation lib is worse than none.
9. **Target-name vocabulary**: document canonical names; add
   `type-check`/`fmt`/`test-cov`/`cargo-test`/`format-check` to `targetDefaults`
   with `cache:true` as a bridge; codemod renames domain-by-domain.

### P2 — steady-state debt burn (weeks, incremental)

10. **Vitest preset slice 3** from the SHA census (≈887 files in 12 hash classes
    are literally identical — the conversion is `sed`-shaped and
    byte-equivalence-provable).
11. **Catalog long-tail wave** for the 97 multi-range deps (vitest first).
12. **README drift check** for the generated fleet; fix `infra/README.md`'s
    stale table while there.
13. **Dead workflow filter lines** (G-1 table) — nine deletions.
14. **`libs/shared` curation**: taxonomy README, adjudicate events/event-bus +
    auth/auth-primitives, evict `tara-live-class-booking`.
15. **Snapshot policy**: single-platform Playwright baselines or LFS.
16. **`nx.json`/`CLAUDE.md` stale-root cleanup** (C-3) and `nx release` dry-run
    verification (C-5).
17. **neith `math.rs` micro-crate** + build.rs dedup inside the umbrellas;
    lilith svc scaffolding decision; arete↔demeter UI-kit decision.

### P3 — owner-gated / long-term

18. History rewrite (existing runbook; owner-executed).
19. F-5 eslint composition slices; C-4/C-5 tsconfig preset unification onto
    `configs/tsconfig/`.
20. Coverage-threshold promotion domain-by-domain (I-1).
21. iris taxonomy documentation or flattening decision (B-7); psyche umbrella
    project replacement (B-6).
22. Merge-noise policy decision (F-1).

---

## 6. Appendix — raw measurements (2026-07-18)

```
tracked files                129,219
nx projects (project.json)     3,445   (33 missing scope tags; 14 no targets)
package.json                   3,287
dep entries                   13,376   (catalog 8,771 / workspace 3,398 / hard 1,207)
multi-range hard-pinned deps      97
Cargo.toml                       953   (17 workspace roots)
pyproject/locks                83/78
tsconfig files                 7,080   (configs/tsconfig adopters: 83)
vitest configs                 2,669   (preset re-exports: 760)
vitest coverage-threshold cfgs  ~121
workflows                        102   (composite action: 64; scheduled: 26)
eslint.config.js lines         1,579
executors: run-commands 7,173 · eslint 2,056 · vite:test 1,846 · js:tsc 1,429
            esbuild 156 · vitest:test 33 · js:node 34 · next 3
target names: test 3,400 · lint 3,286 · build 3,109 · typecheck 1,265
            fmt 422 · type-check 48 · typecheck:ts 33 · test-cov 24
exact-dup clusters (code, non-test)       524  (2,442 redundant copies)
exact-dup clusters (source, non-config)   240  (309 redundant copies)
.spec.ts 11,570 · .test.ts 10,191
kebab vs camel src files (libs)  29,144 : 64
LFS: 95 patterns / 23 objects
git pack (shared)              1.7 GB
ratchet: pino 29 · pg 17 · ioredis 26 · env 1,302 · CB 23 · sleep 128 ·
         .test.ts baseline 12,699 (was 12,602 at ledger close; 4 grandfather bumps)
foundation-lib importers: math 1,982 · http-client 29 · config 24 · events 15 ·
         bff-kit 13 · ids 7 · collections 0 · resilience 0
```

**Method note for the next audit**: the index-SHA duplicate census and the
workflow-filter glob test are cheap enough to run every time; both are pure
read-only one-liners over `git ls-files` and caught real drift this pass.

---

## 7. Resolution ledger (later 2026-07-18)

Every finding adjudicated the same day: **done** (executed + verified),
**corrected** (the finding's premise was wrong — the correction is the
resolution), or **declined/backlog** (explicit decision with the reason
recorded). Each row landed as its own pushed commit (branch + main).

| Finding                                                     | Resolution                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 / B-3 registry gate red                                   | **Done** — `testing` registered as a cross-domain harness governance scope; gate green                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| 2 / A-2 ratchet bypass                                      | **Done, structurally** — `--staged` authoring-time mode (60 ms) wired into pre-commit; test-suffix baseline converted count→file-set (closes the +1/−1 hole, names offenders); merges during this very session confirmed the mechanism (later main merges arrived already `.spec.ts`)                                                                                                                                                                                                                                                                                                                                                                                               |
| 3 / A-1 root landfill                                       | **Done, partially corrected** — the "landfill" is largely the documented active-planning convention (docs/domains/README.md); guard added: root `*.md` outside the core allowlist + declared ledger list fails CI; stale `V1_RESIDUAL_AUDIT_2026-06-11/` retired to docs/audits with refs fixed (plus two pre-existing broken links)                                                                                                                                                                                                                                                                                                                                                |
| 4 / H-1 zero-consumer foundation libs                       | **Done** — adoption waves executed: 120 sleep/delay defs → @oshun/resilience (clamp semantics aligned, 23/23), 8 chunk clones → @oshun/collections; ratchet local-sleep-def 128→8 (4 domain-typed + 4 boundary-blocked refusals — contracts stays dependency-pure); 71 package.json gain explicit deps                                                                                                                                                                                                                                                                                                                                                                              |
| 5 / B-2 apps/v4+v5 nx-invisible                             | **Done, corrected** — TS packages were pnpm-inferred all along; real gaps closed: 25 project.json (3 cargo crates truly invisible + tags/cached-inputs for 22), v4/v5 named inputs, v4 scope registered; smoke green                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| 6 / B-1 R-8 residue                                         | **Done** — slice 4: V2/tools/esports → apps/v2/esports-tools (glob dropped, 7/7 + tsc green); V5/tools **corrected** as ops (the V5 gate fleet — stays); en route repaired 54 DOMAINS-stale + 125 V2-path-stale checkers, 23 stale docs, 12 brittle phrase assertions, and the slice-2-broken grpc vitest alias                                                                                                                                                                                                                                                                                                                                                                     |
| 7 / C-1 C-2 target drift                                    | **Done (bridge) + doc** — canonical vocabulary in docs/conventions/nx-target-names.md; variant names cache-bridged in targetDefaults; 33 @nx/vitest:test → @nx/vite:test; full renames = R-14 follow-up by design                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 8 / E-2 source duplication                                  | **Done where real** — 9× neith spatial math.rs → re-export of neith-spatial-core::math (2,430 lines deleted, cargo+tests green); **corrected**: build.rs copies are per-crate cargo idiom, version.ts one-liners are per-package data; lilith svc scaffolds + arete↔demeter UI kit = owner product decisions (backlog)                                                                                                                                                                                                                                                                                                                                                              |
| 9 / D-1 dep drift                                           | **Done (safe subset)** — 218 pins → catalog (26 intersecting + 51 same-major consolidations); hard pins 1,207→991, multi-range 97→**44**; the 44 are cross-major migrations (vitest ^1/^2→^3 etc.) = real upgrade backlog, not config cleanup                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| 10 / F-2 readme drift + H-4 infra README                    | **Done** — generator `--check` (coverage invariant) wired in ci.yml; infra/README rewritten to the one-root reality incl. the vault-deploy/k8s-deploy same-name-different-origin note                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| A-3 snapshots                                               | **Done via LFS** (single-platform pruning rejected: darwin baselines serve the owner's local runs) — 66 PNGs → LFS pointers, workflow checkout lfs:true                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| A-4 pack/history rewrite                                    | Owner-gated as before (runbook current)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| C-3/C-4 nx.json staleness                                   | **Done** — phantom excludes dropped; CLAUDE.md structure rewritten                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| C-5 nx release scope                                        | **Verified working-as-documented** (ADR-0073 deliberate depth-2 interface scope; dry-run enumerates it; first release needs `--first-release`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| C-6 zero-target projects                                    | **Corrected** — all 14 carry full package-script-inferred targets                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| E-1 vitest preset tail                                      | **Done (slice 3) + corrected** — the census's big classes were the converted re-exports themselves; of the real 99 hand-rolled classes, top 3 non-domain classes (106 files) converted with zero-flip proof (3/988/79); themis's 31-file class already routes through a domain factory (left; that IS dedup)                                                                                                                                                                                                                                                                                                                                                                        |
| G-1 dead filters                                            | **Done** — nine lines deleted, six workflows YAML-verified                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| H-2 untagged projects                                       | **Done** — 33 legacy domain-tagged projects gain scope tags; absent-scope assertion added to the registry gate                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| H-3 shared curation                                         | **Done** — curation rule + adjudicated near-name pairs in libs/shared/README (events/event-bus, auth/auth-primitives, obs trio = deliberate); tara-live-class-booking → libs/tara as @tara/live-class-booking (audit's "sole consumer" claim corrected: real web/mobile consumers, all rewired)                                                                                                                                                                                                                                                                                                                                                                                     |
| I-1 coverage thresholds                                     | **Started as designed** — thresholds preset is now the generator default for new libs; domain-by-domain promotion remains owner-paced                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| I-2 suffix split                                            | Held by the new authoring-time gate; iris generator's `.test.ts` template renamed `.spec.ts` (it would have tripped the gate)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| I-3 docs stragglers                                         | **Declined with reason** — docs/oshun is machine-wired (stub-scan allowlist path); docs/kalika move = churn without consumer benefit; both recorded                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| B-5 root dirs                                               | **Done** (crates/ orphan, static/, backups deleted; openapi backups purged); `types/`+`evaluation/` single-file dirs left (tracked, cheap, no consumer risk today)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| B-6 tests/ vs testing/                                      | **Done via documentation** — tests/README.md states the split rule                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| B-7 depth variance                                          | **Done via rule** — placement-depth convention documented; existing deep taxonomies grandfathered                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| B-8 V3 root docs                                            | **Declined with evidence** — all 52 files externally referenced (workflows/checkers/docs); product-root placement, not repo-root landfill                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| B-4 flat apps                                               | **Done (second pass, same day)** — the deploy-window gating was already dissolved by the owner's prelaunch confirmation, so both renames executed: `apps/euterpe-studio-web` → `apps/euterpe/studio-web` and `apps/neith-vault` → `apps/neith/vault` (workspace globs, project.json depths, tsconfig extends, source-of-truth registry mapping, env-baseline paths, docs all rewired; source-of-truth verifier + registry + ratchet green; nx resolves both at the new roots; the neith android gradlew relative path, broken at HEAD, now resolves at the new depth). `apps/infra` stays: it is a real platform-services home and renaming it is a naming-taste call for the owner |
| B-6(psyche/iris nesting), F-1 merge noise, F-3 eslint split | **Owner-gated/backlog with reasons**: psyche umbrella + iris taxonomy = domain-owner design decisions (depth rule now prevents new cases); merge-noise is a workflow-policy decision only the owner can make; eslint composition continues on the proven `--print-config` slice method                                                                                                                                                                                                                                                                                                                                                                                              |

**Pre-existing reds surfaced (not introduced) and left visible**:
`check-v2-service-observability` (≈40 former V2/services packages lack
@oshun/metrics|tracing — red before R-8 too, was scanning an empty glob at
HEAD); 3 grpc-services commentary-seam contract failures (suite could not even
load at HEAD); 2 aje/sdk SHA-256 KAT failures; svc-user-preferences jest-types
baseline drift. Each is product-owner work now visible instead of silent.
