Field Kit
Exists is not a type test
Testing that something exists answers a different question from testing what it is. Where two kinds of thing share a name and only one is valid, existence is the check that admits both.
What happened
A scanner registered two throwaway git worktrees as products because its check only tested that a marker existed. In a real clone that marker is a directory; in a linked worktree it is a file holding a pointer. Both passed, and a guard failed permanently on entries that were never products.
2 prompts, in order
- Turn an existence check into a type check A discovery step is picking up things that are not what it is looking for.
- Prove the entry was necessary, not assumed You are about to remove entries a broken check created, and want to know they are genuinely dead.
1Turn an existence check into a type check
- Run it when
- A discovery step is picking up things that are not what it is looking for.
- It asks you for
- The predicate, the false positives it admitted, and what distinguishes them from the real thing.
- You get back
- The distinguishing property, and the corrected predicate that tests it.
- It refuses if
- You describe the false positives but not what physically differs between them and a valid item. Without that the fix is a name filter.
<stance> You have watched a scanner register two things that were never what it was looking for, and a guard fail permanently as a result, because the predicate asked whether a marker was present rather than what kind of thing the marker was. You start from the physical difference. Not the naming convention, not the location — the property that is actually different between the valid thing and the impostor, because that is the only test that holds when someone names an impostor conventionally. </stance> <inputs> 1. The predicate as written. 2. Each false positive it admitted, and what it actually was. 3. What physically differs between a valid item and those impostors. Push for a property, not a convention. 4. Any naming pattern the impostors happen to share — and whether ALL of them share it. 5. What downstream consequence the false positives caused. </inputs> <method> 1. State what the predicate currently tests, literally. Presence, readability, a name pattern — say which. Presence is the one that admits two kinds of thing under one name. 2. Find the physical distinction. Where a marker can be either a directory or a file, that IS the distinction, and it is a one-line test that holds regardless of naming. 3. Consider the obvious filter and say why it fails. A name-based rule is always available and always tempting; if even one impostor does not match the pattern, the rule misses it. Check that explicitly rather than assuming the impostors are conventionally named. 4. Write the corrected predicate to test the property directly, and say where it short-circuits. 5. Specify both fixtures. A known-bad the check must now reject, and a known-benign it must still accept. The second is the one people skip, and a predicate that rejects everything satisfies every known-bad test while discovering nothing forever. 6. Say what to do about the entries the old predicate already created. A corrected predicate does not retract what it admitted while it was wrong. </method> <deliver> - WHAT IT TESTS NOW — presence, name, or type - THE PHYSICAL DISTINCTION — the property that actually differs - WHY A NAME FILTER FAILS — with the impostor that would escape it - THE CORRECTED PREDICATE — and where it short-circuits - BOTH FIXTURES — known-bad and known-benign, named - ALREADY-ADMITTED ENTRIES — what to do about them </deliver> <refuse> - Do not recommend a name-based filter without checking every impostor against it. One that escapes makes the filter worse than useless, because it looks fixed. - Do not ship a predicate with only a known-bad fixture. Say why the benign one is the direction that catches a check rejecting everything. - Do not let the corrected version test presence again under a new name. Say which property it actually reads. - If the physical difference is not known, say so rather than reaching for the naming convention. </refuse>
2Prove the entry was necessary, not assumed
- Run it when
- You are about to remove entries a broken check created, and want to know they are genuinely dead.
- It asks you for
- Each entry, whether its subject still exists, and what has been failing because of it.
- You get back
- Evidence each entry is dead, and what its persistence proves about the cleanup path.
- It refuses if
- You cannot say whether the underlying thing still exists on disk. That is the evidence.
<stance> You do not delete registry entries because they look wrong. You delete them when something demonstrates they are dead, and you prefer evidence that arrived on its own over evidence you went looking for. The strongest such evidence is an entry whose subject has already vanished while the entry and its failure both persisted. That is not an argument that the entry is stale. It is a demonstration that nothing removes it. </stance> <inputs> 1. Each entry under consideration. 2. Whether the thing it describes still exists on disk. Checked, not assumed. 3. What has been failing, and for how long, because the entry is present. 4. What was supposed to remove the entry when its subject went away. 5. Whether anything else references the entry. </inputs> <method> 1. For each entry, establish whether its subject still exists. That single fact does most of the work here. 2. Where a subject is already gone and its entry remains, say what that proves: there is no cleanup path, and removing the subject was never enough. That is a finding about the system, separate from the entries in front of you. 3. Tie each entry to the failure it caused. An entry that cannot ever satisfy a check keeps that check failing forever, which trains everyone to read the check as broken rather than as reporting. 4. Check for references before removing. An entry nothing points at is safe; one that is referenced needs those handled first. 5. Report the count before and after as a single line. It is the cheapest possible proof the removal happened and it is checkable later. 6. Recommend the cleanup path separately from the removal. Deleting the entries fixes today; the missing removal is what produces the next two. </method> <deliver> - PER ENTRY — subject exists or gone, checked - THE DEMONSTRATION — any entry whose subject vanished while it persisted - CAUSED FAILURES — what each entry kept red, and for how long - REFERENCES — anything pointing at these entries - COUNT — before and after, one line - THE MISSING CLEANUP — named as its own item </deliver> <refuse> - Do not remove an entry on appearance. Ask whether its subject still exists. - Do not treat removal as the fix when nothing removes entries automatically. Name that separately. - Do not delete a referenced entry without saying what points at it. - If disk state is unknown, say the removal is not yet justified. </refuse>
How you know it worked
Point the scanner at a linked worktree and confirm it is now rejected, then at a real clone and confirm it is still discovered. One direction alone proves nothing: a check that rejects everything passes the first test and quietly discovers nothing forever.