Skip to content

ReferenceCheck.ts finds 223 missing references in the shipped payload, has no invoker, and its orphan detection inspects one file #1541

Description

@tzioup

ReferenceCheck.ts finds 223 missing references in the shipped payload, has no invoker, and its orphan detection inspects one file

Structured for machine parsing: claims are atomic, each carries the command that verifies it. Every command runs against a fresh clone of this repo — none depend on my machine, my install, or my configuration. Reproduction at the bottom.

Summary

LIFEOS/TOOLS/ReferenceCheck.ts is a full-surface reference validator. Run unmodified against the shipped payload it reports 223 missing references in 231ms. Nothing invokes it — no hook, no command, no CI job. Its orphan mode reports 0 on every run because the check inspects exactly one file out of 1,324.

This is the same shape as #1539: the diagnostic exists, it is correct, and nothing asks it anything.

Claims and verification

$PAYLOAD below means the release payload staged in the shape it ships as. ReferenceCheck resolves its root as $HOME/.claude, so:

git clone --depth 1 https://github.com/danielmiessler/LifeOS && cd LifeOS
mkdir -p /tmp/rc && cp -R LifeOS/install /tmp/rc/.claude

B1 — the shipped payload contains 223 missing references.

cd /tmp/rc/.claude/LIFEOS/TOOLS && HOME=/tmp/rc bun ReferenceCheck.ts --quiet | tail -1
# ReferenceCheck: 1174 files, 1558 refs, 223 missing, 0 stale, 0 orphan — 231ms

B2 — roughly half are legitimate; the rest are not. Classification of the 223:

Class Count Defect?
Runtime-created state and logs (MEMORY/STATE, OBSERVABILITY, DATA, LEARNING, RESEARCH) 90 No — created on first use
USER/ tree 28 No — populated at interview
References to private skills not in the release 35 Yes
References to dated MEMORY/WORK/<slug>/ISA.md artifacts 13 Yes
Other 57 Mixed
grep -cE 'skills/_[A-Z]' /tmp/out.txt        # 35
grep -cE 'MEMORY/WORK/' /tmp/out.txt         # 13
grep -cE 'MEMORY/(STATE|OBSERVABILITY|DATA|LEARNING|RESEARCH)/' /tmp/out.txt   # 90
grep -cE 'USER/' /tmp/out.txt                # 28

(where /tmp/out.txt is the lines from B1)

The 35 resolve to seven private skills: _HOMESECURITY, _INCIDENT_RESPONSE, _LIFEOS, _NETWORK, _ULWORK, _WRITING, _X.

This is why the check cannot gate as-is. ~118 of 223 are expected. A gate on the raw count would be more than half false positives, and a gate that cries wolf gets disabled. An ignore-list for runtime-created paths is a prerequisite for making this blocking — noted in the PR.

B3 — nothing invokes ReferenceCheck.

grep -rl 'ReferenceCheck' --include='*.json' --include='*.sh' --include='*.yml' --include='*.ts' LifeOS/install | grep -v 'ReferenceCheck.ts'
# LifeOS/install/LIFEOS/TOOLS/IntegrityCheck.ts   (itself never invoked — see B6)

B4 — orphan detection inspects one file. ReferenceCheck.ts:616:

const isLifeosTopMd = /^LifeOS\/[^/]+\.md$/.test(rel);
if (!isLifeosTopMd) continue;

Two independent faults:

Case. The directory is LIFEOS/. Paths resolve as LIFEOS/LIFEOS_SYSTEM_PROMPT.md, which fails ^LifeOS/. Likely unfollowed from the PAI→LifeOS rename.

ls /tmp/rc/.claude | grep -x 'LifeOS' ; echo "exit $?"   # no match

Scope. Corrected to ^LIFEOS/, the pattern still matches only top-level .md:

ls /tmp/rc/.claude/LIFEOS/*.md | wc -l   # 1
find /tmp/rc/.claude -type f \( -name '*.md' -o -name '*.ts' \) | wc -l   # 1324

Maximum possible coverage is 1 file of 1,324, and that one file is referenced — so the check reports 0 whether or not the case is fixed. I verified this: patching only the case leaves the count at 0.

B5 — I tried the obvious fix and it isn't sufficient. Widening scope to LIFEOS/TOOLS/*.ts yields 102 orphans, but many are user-facing CLI tools that are supposed to be unreferenced (they're run by hand). The orphan class needs a definition distinguishing "nothing invokes this" from "a human invokes this," which is a design question rather than a one-line change. I'm reporting this rather than proposing a patch, because the naive version would be correctly rejected.

Two entries in that 102 are genuine and load-bearing: IntegrityCheck.ts and ReferenceCheck.ts itself.

B6 — IntegrityCheck.ts orchestrates this tool and is itself uninvoked. It shells ReferenceCheck.ts --json --stale --orphans (line 118) and documents /ic as its entry point. The payload ships no such command:

ls LifeOS/install/commands/
# context-search.md  cs.md  pu.md

The SessionEnd hook hooks/IntegrityCheck.hook.ts shares its name but never references it — it imports TranscriptParser and shells BudgetCheck.ts.

Because orphan mode returns 0, IntegrityCheck.ts would consume that as a pass if it ever ran. That makes the current state a false-negative generator on the class rather than merely an absent check.

B7 — Actions is configured; nothing validates the shipped tree.

ls .github/workflows/
# claude-code-review.yml  claude.yml

claude.yml triggers on issue_comment, issues, pull_request_review, pull_request_review_comment. claude-code-review.yml triggers on pull_request. Both are anthropics/claude-code-action. Neither runs on push, release, or tag, and neither runs the validator.

Why this is worth a gate rather than a fix

The individual references matter less than the fact that nothing checks them. Three majors shipped in the ten weeks to July (v5.0.0 → v6.0.0 → v7.0.0), so a fix to any specific reference in 7.1.1 is obsolete before it lands. A check that runs against whatever ships next is not.

The cost of the current state falls on the project rather than on users individually: a defect discovered only after install is patched locally, which makes that user's instance diverge from the release, which makes their subsequent bug reports unreproducible — removing from the diagnostic pool exactly the people motivated enough to investigate. LifeOS's proposition is deterministic, spec-governed behaviour; unvalidated releases produce a population of individually-repaired installs, which is the opposite.

PR

#1542 adds a report-only workflow: stage LifeOS/install as $HOME/.claude, run ReferenceCheck.ts --quiet, print the summary line to the job summary. No source change, continue-on-error, does not gate. It exists to make the number visible on every PR touching the payload.

Flipping it to blocking needs the ignore-list from B2 first. Happy to do that as a follow-up if you want it.

Reproduction

git clone --depth 1 https://github.com/danielmiessler/LifeOS && cd LifeOS
mkdir -p /tmp/rc && cp -R LifeOS/install /tmp/rc/.claude
cd /tmp/rc/.claude/LIFEOS/TOOLS && HOME=/tmp/rc bun ReferenceCheck.ts --quiet | tail -1

Scope

Verified against a fresh clone at 4e33cc8. All claims are properties of the repo tree. My own install reports 316 rather than 223 because it contains my files as well; the 223 figure is payload-only and is the one that reproduces for anyone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions