Skip to content

0.5.1 — safety and diagnostics, from first real-project use - #1

Merged
emmepi86 merged 2 commits into
mainfrom
feat/0.5.1-safety-and-diagnostics
Jul 28, 2026
Merged

0.5.1 — safety and diagnostics, from first real-project use#1
emmepi86 merged 2 commits into
mainfrom
feat/0.5.1-safety-and-diagnostics

Conversation

@emmepi86

Copy link
Copy Markdown
Owner

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.md per descrivere solo il nuovo arrivato e lasciava orfane le note già presenti — un vault formalmente valido e semanticamente falso.

Il manifest guadagna schema_version: 2 e l'identità del registro:

{
  "schema_version": 2,
  "register": { "prefix": "RES", "source": "FINDINGS.md" }
}

e lo split rifiuta fail-closed:

ERROR: vault already belongs to prefix RES
cannot split prefix CQR into the same vault
use a separate --out directory

--adopt-vault è la via esplicita. Il merge multi-registro resta un'operazione deliberata, non un effetto collaterale di due split. I manifest v1 continuano a essere compresi.

2. Gli identificatori sono accettati come sono scritti

Un registro con ### F1 non produceva niente, perché il pattern pretendeva il trattino. Ora è opzionale e l'id è preservato: F1 resta F1. 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-4 splitta 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.

No findings matched in audit.md.

Expected:
  heading level: 2-6
  identifier:    F-<number> or F<number>

First headings found:
  ### F1 — Negazioni e correzioni diventano diagnosi attive
  ### F2 — Collasso dei fenotipi rari

più --inspect per l'elenco completo degli stili presenti.

4. Le note che non collegano nulla vengono nominate, con la causa

notes_with_matches: 10 comprimeva 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.

UNLINKED NOTES

CQR-3
  reason: no symbol identifiers found

CQR-8
  reason: only ambiguous symbols found

--report-unlinked li elenca, --require-linked fa fallire la CI, e l'output JSON porta unlinked_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.md lasciava 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.cancel resta forte anche dove cancel è ovunque.

Verifica

77 test, tutti verdi (14 preesistenti + 63 nuovi). Provato end-to-end sui registri reali che avevano fallito: quello con ### F1 ora 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.

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
emmepi86 marked this pull request as ready for review July 28, 2026 20:59
@emmepi86
emmepi86 merged commit ef87526 into main Jul 28, 2026
2 checks passed
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.

2 participants