You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Drafted by an AI agent from an operator-confirmed interview (run 20260908-home-d1).
Parent
Parent: #4004. Refs #3858, which implements ranking signals computable from existing snapshot data. That issue makes the component notice more; this one makes it remember. They are complementary and neither substitutes for the other: signals rank what to look at, the catalog records what looking at it concluded.
Covers four confirmed decisions together — record shape, catalog scope, investigation procedure, and what happens when the owner is still unknown — because they are one artifact and one pass.
Problem
The component investigates and then forgets.
On this run, deciding that .sbx-denybin (104 bytes, four stub ssh/scp batch files) was removable took a nine-source investigation: User PATH, Machine PATH, the claude-remote-control scheduled-task action, .claude.json, .codex\config.toml, .claude, the chezmoi source, and the sandbox checkout. That reasoning exists only in a report in the operator's data directory. The next run re-derives it from nothing, or does not.
Worse are the entries kept because the investigation ran out of road, with no way to record that it did:
.cache\verifier-scratch — 173 KB, contains a .git, newest file 2026-09-02, no config anywhere references it. Owner unknown, so kept.
.cache\performance-harness — 87 bytes, same shape. Owner unknown, so kept.
ansel — empty, created 2026-09-01, zero provenance anywhere on the machine. Name-only, so kept.
Each of those will be re-investigated, reach the same dead end, and be kept again, every run, forever. The operator knows the answer for at least one of them and was never asked in a form the component could retain.
What to build
One artifact under the plugin data root: catalog.json plus a rendered CATALOG.md.
Record shape
One record per catalogued entry:
path
identity — device, inode, kind
owner
provenance — a narrative of 2-4 sentences
evidence — a list, each item carrying its source: a file path, a command, or a URL
disposition
tier
size
first_seen_run, last_seen_run, last_verified
source — engine or human
How a record is used
The scan annotates a matching entry with prior_disposition.
The report leads with new or changed entries; unchanged ones get one line each. This is the point of the artifact: a re-run of a catalogued home directory should be short.
Identity or descendant-set change invalidates a record. A moved inode or a changed child set means the thing being described is not the thing that was described.
A record is a hint, never authorization. The same rule the component already applies to filename hints. A catalogued remove disposition does not shorten the approval ceremony, does not skip a preview, and does not survive a failed revalidation.
Catalog scope
Catalogue:
every immediate child of the target,
every hinted or empty entry at any depth,
every entry flagged out of place — no protected reason, no recognizable app or config convention.
Deeper entries catalogue at owner level: one record per owning tool or product, not one per file.
The operator's constraint, verbatim: "Nothing that looks out of place is skipped." An out-of-place entry is investigated, catalogued, and inventoried with enough context to justify its disposition, whatever that disposition turns out to be. "Small", "empty", and "probably fine" are not reasons to skip; they are findings to record.
Investigation procedure
The skill ships a required local procedure, run per catalogued entry:
manifests and READMEs
config file contents
Get-Command (or the platform equivalent)
running processes
scheduled tasks
PATH, both user and machine
installed programs
git remotes and status
dotfile and settings references
Escalation to /discovery:research is presence-gated and permitted only when the local procedure finds no owner. /discovery:explore applies only to repository strays.
Unknowns
The report ends with one question per entry whose owner is still unknown after the local procedure and any escalation.
The operator's answer is written into the catalog as human-sourced provenance (source: human) and is not asked again while identity holds. Until answered, the entry's disposition stays keep.
Design constraints
The catalog records conclusions and their evidence; it never records an approval.
An entry with source: human provenance is not re-investigated by the local procedure while its identity is unchanged, but it is still re-verified for identity.
Unknown must remain visibly unknown. An entry no investigation resolved reads as unresolved, not as low-priority — the failure mode this whole artifact exists to prevent is a dead end quietly aging into an assumption.
The rendered CATALOG.md is for the operator to read without running anything.
Acceptance criteria
catalog.json and a rendered CATALOG.md are written under the plugin data root, with the record shape above.
A scan annotates matching entries with prior_disposition, and the report leads with new or changed entries while giving unchanged ones one line each.
A change to an entry's identity or descendant set invalidates its record, demonstrated by a test.
A catalogued disposition never shortens or skips any approval, preview, or revalidation step, demonstrated by a test.
Catalog scope covers every immediate child, every hinted or empty entry at any depth, and every out-of-place entry; deeper entries are catalogued at owner level.
The local investigation procedure ships in the skill, is required per catalogued entry, and its sources are enumerated.
/discovery:research is invoked only when the local procedure finds no owner, and only when present.
The report ends with one question per still-unknown-owner entry; an operator answer is persisted with source: human and is not re-asked while identity holds.
An entry with an unanswered question keeps disposition keep.
scripts/affected-tests.sh --run selects and passes the suites mapped to the changed files.
Drafted by an AI agent from an operator-confirmed interview (run
20260908-home-d1).Parent
Parent: #4004. Refs #3858, which implements ranking signals computable from existing snapshot data. That issue makes the component notice more; this one makes it remember. They are complementary and neither substitutes for the other: signals rank what to look at, the catalog records what looking at it concluded.
Covers four confirmed decisions together — record shape, catalog scope, investigation procedure, and what happens when the owner is still unknown — because they are one artifact and one pass.
Problem
The component investigates and then forgets.
On this run, deciding that
.sbx-denybin(104 bytes, four stubssh/scpbatch files) was removable took a nine-source investigation: User PATH, Machine PATH, theclaude-remote-controlscheduled-task action,.claude.json,.codex\config.toml,.claude, the chezmoi source, and the sandbox checkout. That reasoning exists only in a report in the operator's data directory. The next run re-derives it from nothing, or does not.Worse are the entries kept because the investigation ran out of road, with no way to record that it did:
.cache\verifier-scratch— 173 KB, contains a.git, newest file 2026-09-02, no config anywhere references it. Owner unknown, so kept..cache\performance-harness— 87 bytes, same shape. Owner unknown, so kept.ansel— empty, created 2026-09-01, zero provenance anywhere on the machine. Name-only, so kept.Each of those will be re-investigated, reach the same dead end, and be kept again, every run, forever. The operator knows the answer for at least one of them and was never asked in a form the component could retain.
What to build
One artifact under the plugin data root:
catalog.jsonplus a renderedCATALOG.md.Record shape
One record per catalogued entry:
pathidentity— device, inode, kindownerprovenance— a narrative of 2-4 sentencesevidence— a list, each item carrying its source: a file path, a command, or a URLdispositiontiersizefirst_seen_run,last_seen_run,last_verifiedsource—engineorhumanHow a record is used
prior_disposition.removedisposition does not shorten the approval ceremony, does not skip a preview, and does not survive a failed revalidation.Catalog scope
Catalogue:
Deeper entries catalogue at owner level: one record per owning tool or product, not one per file.
The operator's constraint, verbatim: "Nothing that looks out of place is skipped." An out-of-place entry is investigated, catalogued, and inventoried with enough context to justify its disposition, whatever that disposition turns out to be. "Small", "empty", and "probably fine" are not reasons to skip; they are findings to record.
Investigation procedure
The skill ships a required local procedure, run per catalogued entry:
Get-Command(or the platform equivalent)Escalation to
/discovery:researchis presence-gated and permitted only when the local procedure finds no owner./discovery:exploreapplies only to repository strays.Unknowns
The report ends with one question per entry whose owner is still unknown after the local procedure and any escalation.
The operator's answer is written into the catalog as human-sourced provenance (
source: human) and is not asked again while identity holds. Until answered, the entry's disposition stayskeep.Design constraints
source: humanprovenance is not re-investigated by the local procedure while its identity is unchanged, but it is still re-verified for identity.CATALOG.mdis for the operator to read without running anything.Acceptance criteria
catalog.jsonand a renderedCATALOG.mdare written under the plugin data root, with the record shape above.prior_disposition, and the report leads with new or changed entries while giving unchanged ones one line each./discovery:researchis invoked only when the local procedure finds no owner, and only when present.source: humanand is not re-asked while identity holds.keep.scripts/affected-tests.sh --runselects and passes the suites mapped to the changed files.Out of scope