A full re-audit of the Oshun monorepo, run the same day the 2026-07-16 architecture audit closed its reconciliation ledger. This pass has three jobs the first audit could not do:
- Verify the remediations actually hold in-tree today (guards wired, gates green, no regressions), not just in execution logs.
- Audit what the remediation itself created — new conventions (ratchets, registries, presets) have their own failure modes.
- 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,287package.json; 953Cargo.tomlunder 17 workspace roots; 83pyproject.toml(78 locks); 7,080 tsconfig files; 2,669 vitest configs; 102 workflows; 1.7 GB shared pack. - Census tools: every
project.json/package.jsonparsed with node (0 parse failures); exact-duplicate detection viagit ls-files -sindex SHAs (free, whole-repo, no sampling); workflow path filters glob-tested againstgit ls-fileswith 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 theci.ymlquality 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.ts12,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; thedeploy/*half (still "queued" in the prior ledger) has been absorbed (infra/compose,infra/vault-deploy,infra/k8s-deploy, per-domain trees), and thedeploy/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.logfiles, all inside the deliberateevidence/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 theV2/tools/*glob still present inpnpm-workspace.yamlline 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 oflibs/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 MBmain.js+ runtime/styles), committed 2026-01-10 during workspace init; nothing references it. Delete.types/— one file (global-jsx.d.ts); fold intoconfigs/or the consuming tsconfig.evaluation/— one file (human-gold/acquisition-registry.v1.json); fold intoevidence/or the owning domain.openapi/— 4 files including two timestamped.backup-*files tracked in git (openapi/lilith/openapi.yaml.backup-1760592604742,.schema-backup-1760592952186) plusdocs/domains/lilith/extras/stoplight/.spectral.yaml.backup. Delete the backups; then decide whether rootopenapi/merges into per-appapps/<domain>/*/openapi/(the dominant pattern — e.g.apps/yemaya/api/openapi/).tests/(28 files) vstesting/(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. Mergetests/intotesting/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. Aneith-spatial-mathmicro-crate inside the existing umbrella preserves the no-external-deps property while deduplicating.build.rsduplicated 11× (kalika eels/electronic-structure/…) and 7× (euterpe/kalika native crates).version.tsone-liners duplicated 13× (bellona) + 12× (isis) — generate from package.json at build, or accept and stop counting.apps/lilith/svc-*:types.ts(6× + 4×) andapp.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 adocs/conventions/note so they're allowed to diverge deliberately). openapi-contract-utils.tsidentical across bellona/hathor(+2 more); e2efixtures.tsin two 5× families;.storybook/test-runner.ts4×.
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) vsevent-bus(cross-domain bus) — names don't communicate the split;authvsauth-primitives;logging/metrics/tracingas three micro-libs besidebff-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 tolibs/tara/. - A
libs/shared/README.mdtaxonomy (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)#
- Fix the red registry gate: register
scope:testing(or retagtesting/prompt-injectionto an existing governance scope). One line + one tag edit. - Close the ratchet bypass: run
check-conventions-ratchet.mjs+check-registry.mjsas 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-protecttools/conventions/conventions-ratchet-baseline.jsonso baseline bumps require explicit review. - Guard the root: add a root-
*.mdallowlist tocheck-forbidden-paths.sh; move the five 07-15…07-17 reports plus ISIS_TODOS×2/ISIS_GAPS/V1_RESIDUAL_AUDIT intodocs/audits/(with redirects/pointers if tooling parses them). - Delete tracked junk:
openapi/*.backup-*,.spectral.yaml.backup,static/,crates/maya-terrain-deform/. Fourgit rmcommands.
P1 — finish what R-8/R-12 started (days)#
- R-8 slice 4: move
V2/tools,V5/toolsunderapps/; drop theV2/tools/*workspace glob; then the completion claim is true. - nx-cover apps/v4 + apps/v5: per-service
project.jsonwith scope tags, wrapping existing cargo/pnpm commands (v3/v6/v7 files are the template). - Tag the 33 untagged projects and extend
check-registry.mjsto assert scope-tag presence, not just validity. - 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. - Target-name vocabulary: document canonical names; add
type-check/fmt/test-cov/cargo-test/format-checktotargetDefaultswithcache:trueas a bridge; codemod renames domain-by-domain.
P2 — steady-state debt burn (weeks, incremental)#
- 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). - Catalog long-tail wave for the 97 multi-range deps (vitest first).
- README drift check for the generated fleet; fix
infra/README.md's stale table while there. - Dead workflow filter lines (G-1 table) — nine deletions.
libs/sharedcuration: taxonomy README, adjudicate events/event-bus + auth/auth-primitives, evicttara-live-class-booking.- Snapshot policy: single-platform Playwright baselines or LFS.
nx.json/CLAUDE.mdstale-root cleanup (C-3) andnx releasedry-run verification (C-5).- neith
math.rsmicro-crate + build.rs dedup inside the umbrellas; lilith svc scaffolding decision; arete↔demeter UI-kit decision.
P3 — owner-gated / long-term#
- History rewrite (existing runbook; owner-executed).
- F-5 eslint composition slices; C-4/C-5 tsconfig preset unification onto
configs/tsconfig/. - Coverage-threshold promotion domain-by-domain (I-1).
- iris taxonomy documentation or flattening decision (B-7); psyche umbrella project replacement (B-6).
- 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.