0.5.1 — safety and diagnostics, from first real-project use - #1
Merged
Conversation
Found by running tracelink against a clinical codebase rather than by review. Each of these was defensible behaviour that left the user with no way forward. A vault now belongs to one register. Splitting a second one into it rewrote INDEX.md to describe only the newcomer and orphaned the notes already there — formally valid, semantically false. The manifest gains `schema_version: 2` and a `register` identity, and split refuses a different prefix or a different source file. `--adopt-vault` is the explicit way through; merging stays a deliberate operation rather than a side effect of running split twice. v1 manifests are still understood. Identifiers are accepted as written. A register whose findings read `### F1` produced nothing, because the pattern required a hyphen. It is now optional and the id is PRESERVED — `F1` stays `F1`. Rewriting a human identifier to suit the tool is a cost paid by every reader of the register, forever, to save one regex. Prefixes containing hyphens work too, so `P1-CQR-4` splits and sorts. Failure says what it found. "No headings matched" named the pattern it wanted and nothing else; answering "then what IS in this file?" meant reading the source. It now prints the first headings and the identifier styles present, with `--inspect` for the full list. Notes that link nothing are named, with the cause. `notes_with_matches: 10` compressed three different problems into one number: a finding written only in prose, candidates filtered as too common, and symbols that were only ambiguous call for three different fixes. `--report-unlinked` lists them, `--require-linked` fails CI on them, and the JSON output carries `unlinked_notes`. Ambiguous references stay visible. Withholding the link is right — guessing between two definitions is worse than abstaining — but dropping the reference from CODE-INDEX.md left silence exactly where the answer was two answers. They now get their own section with the referencing notes and every candidate. README documents the editorial contract: linking is lexical, so explicit identifiers and qualified names produce strong links and prose does not. 77 tests.
emmepi86
marked this pull request as ready for review
July 28, 2026 20:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tutto quanto segue viene dall'uso reale su un codebase clinico, non da review: cinque casi in cui tracelink ha fatto qualcosa di difendibile e inutile per chi lo stava usando.
1. Un vault appartiene a un registro
Splittare un secondo registro nello stesso vault riscriveva
INDEX.mdper descrivere solo il nuovo arrivato e lasciava orfane le note già presenti — un vault formalmente valido e semanticamente falso.Il manifest guadagna
schema_version: 2e l'identità del registro:{ "schema_version": 2, "register": { "prefix": "RES", "source": "FINDINGS.md" } }e lo split rifiuta fail-closed:
--adopt-vaultè la via esplicita. Il merge multi-registro resta un'operazione deliberata, non un effetto collaterale di duesplit. I manifest v1 continuano a essere compresi.2. Gli identificatori sono accettati come sono scritti
Un registro con
### F1non produceva niente, perché il pattern pretendeva il trattino. Ora è opzionale e l'id è preservato:F1restaF1. Riscrivere un identificatore umano per comodità del tool è un costo pagato da ogni lettore del registro, per sempre, per risparmiare una regex.Funzionano anche i prefissi con trattini, quindi
P1-CQR-4splitta e ordina correttamente.3. Il fallimento dice cosa ha trovato
Prima nominava il pattern che voleva e basta; rispondere a «e allora cosa c'è in questo file?» richiedeva leggere il sorgente.
più
--inspectper l'elenco completo degli stili presenti.4. Le note che non collegano nulla vengono nominate, con la causa
notes_with_matches: 10comprimeva tre problemi diversi in un numero solo. Una finding scritta in prosa, candidati filtrati perché troppo comuni e simboli solo ambigui richiedono tre correzioni diverse.--report-unlinkedli elenca,--require-linkedfa fallire la CI, e l'output JSON portaunlinked_notes.5. I riferimenti ambigui restano visibili
Trattenere il link è giusto — indovinare fra due definizioni è peggio che astenersi — ma toglierlo del tutto da
CODE-INDEX.mdlasciava silenzio esattamente dove la risposta era due risposte. Ora hanno una sezione propria con le note che li citano e tutti i candidati.README
Documentato il contratto editoriale: il linking è lessicale, quindi identificatori espliciti e qualified name producono link forti e la prosa no.
watchdog.cancelresta forte anche dovecancelè ovunque.Verifica
77 test, tutti verdi (14 preesistenti + 63 nuovi). Provato end-to-end sui registri reali che avevano fallito: quello con
### F1ora produce le 5 note, e il vault multi-registro viene rifiutato invece di corrompersi.Fuori scope, per 0.6.0 come da piano:
.tracelink.toml,init,doctor,context, policy configurabile per i common symbols, JSON stabile ovunque.