Skip to content

Feat/d83 jw fact table reachability - #329

Merged
evkir merged 4 commits into
mainfrom
feat/d83-jw-fact-table-reachability
Oct 29, 2026
Merged

evkir merged 4 commits into
mainfrom
feat/d83-jw-fact-table-reachability

Conversation

@evkir

@evkir evkir commented Oct 29, 2026

Copy link
Copy Markdown
Owner

Four commits.

  1. The licence argument counted registry entries, not repositories: 64
    servers publish out of 60 repositories. Fixed in four texts, and a test
    now recomputes the count and holds every spelled figure to it.
  2. scripts/probe_fact_table_reachability.py asks which repositories behind
    the table still answer, using the probe target selection already uses.
  3. The page now dates the commits it names and says the table is a record
    of that day. Guard reads the date off the fixture's filename.
  4. detector_eval bound blind to two different things in one function;
    renamed, and the module declared in [tool.mypy] files. Priced at +0
    crossers / -1 reached before the fact and moving both by that.

Measured today: all 60 repositories answered.

What this changes

How it was measured

Checklist

  • ruff format --check cyberai/ tests/ and ruff check cyberai/ tests/ pass
  • pytest -W ignore::DeprecationWarning -m "not slow and not smoke" passes
  • New behaviour is covered by a test that fails without the change
  • I have read CLA.md and I hereby sign the CLA

evkir added 4 commits October 29, 2026 10:03
…rgument

Four texts put the prose corpus at sixty-four. That is the number of
servers the committed table holds; a licence belongs to a repository, and
the sixty-four servers publish out of sixty repositories -- one owner
carries six of them, and a renamed account appears twice over one tree.
Nothing recomputed either figure, so the four agreed with each other and
with nothing on disk.

The page itself said sixty-four servers and was right; it is left alone.

A test now recomputes the count from the rows and reads every spelled
figure out of each text, failing on a count that drifts in either
direction and on a text that stops naming one at all. A mutant that
deleted the count rather than changing it survived the first form of that
assertion, which is why absence fails too.
…answer

Every row of the committed table names a repository and a commit, and
invites a reader to fetch the text at that commit and compare the digest.
The commits were the heads of those checkouts on the day the corpus was
read. Other people's repositories move, and nothing has asked since
whether a reader following the table today arrives anywhere.

The probe is the one the scanner's own target selection already uses, so
the three states printed here are the states that decide whether a target
is audited at all, not a second opinion written beside them. It asks each
distinct repository once: sixty questions rather than one per row, which
is the same dedup key selection uses and the reason the two agree on what
counts as one repository.

What it measures is weaker than what the table promises. A repository that
answers is not a promise that the commit still resolves -- a rewritten
history answers here and would fail a fetch. A repository that does not
answer is proof that it cannot.

The tests substitute the probe everywhere: one that reached the network
would measure other people's uptime and fail on a train.
… have moved

The page invited a reader to fetch each text at the commit named beside it
and compare the digest. The commits were heads on the day the corpus was
read, and the only place that day appeared was inside the fixture's
filename: a path, not a claim about time. A reader arriving a year later
had nothing on the page telling them the addresses had aged.

The page now says which day, says the table is a record of that day rather
than a description of the repositories now, and points at the probe. What
the digest promises is narrowed in the same breath: it still says whether
you read what we read, and says nothing about whether anything is there to
read.

The guard reads the date off the fixture's name rather than holding a
constant of its own, so renaming the table to a new collection date and
leaving the page behind fails. It finds the clause by what it asserts
rather than by the date it carries -- the date appears on the page twice,
once inside the path, and a search for it alone lands on a sentence that
names a file and claims nothing about when its rows were read.

Measured before writing this: all sixty repositories answered. That number
is not on the page. It came from the network and nothing in the tree can
hold it to anything, which is the same reason the claim here is about the
date rather than about what is still reachable.
…and declare the module

One function bound the name blind twice: once in the per-row loop to a
predicate about a single subclass, and once near the end to the list of
subclass names nothing was ever flagged in. Nothing about the run depended
on it -- the second binding simply replaced the first -- but a reader meets
one name carrying two meanings, and mypy holds the list to the type of the
predicate: two errors, on the assignment and on the join.

Renaming both to is_blind and blind_names left the module clean, which is
what the drift report then demanded: a module that reports nothing under
the gate's own flags has to be declared or explained, and this one had
neither. Priced before the fact by scripts/scope_price.py at 0 errors, +0
crossers and -1 reached, and moving both counters by exactly that: 16
reaching 24 became 16 reaching 23.

The scope page was further behind than this change. It claimed 117 of 175
modules while saying the gated pair beside it were 115 and 173, and said
114 modules were in the scope two paragraphs later. Only the ratio is
gated, so the other three drifted in silence. All of them now read what the
checker resolves.

Measured: with the module declared, restoring the collision turns mypy red
and leaves every test in tests/unit/test_detector_eval_cli.py green. That
is the shape of what was wrong -- a defect only the type checker could see,
in a file the type checker was not asked about.
@codecov

codecov Bot commented Oct 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@evkir
evkir merged commit 6d2764d into main Oct 29, 2026
10 checks passed
@evkir
evkir deleted the feat/d83-jw-fact-table-reachability branch October 29, 2026 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant