Problem or motivation
Refresh is purely hash-driven: if the source hash matches, the snapshot is reused; otherwise full rebuild. This conflates four different change types into one "something changed" signal. Structure drift in authoring surfaces (heading structure, table layout, relation blocks) causes parser drift even when semantics haven't changed. snapshotNeedsRebuild() in runtime.ts only checks for missing description/metadata fields — it does not classify the nature of the change.
Proposed solution
1. Declared machine-facing indexing view
Create a stable semantic spine artifact (e.g., indexing-view.json) containing the machine-facing contract: pattern IDs with canonical title/status/type/normativity/part/cluster, alias set with successor/deprecation pointers, anchor map, explicit relation edges, route-bearing metadata, and snapshot edition identity. On refresh, diff this view first before deciding whether a full rebuild is needed.
2. Classify source changes into four families
| Change family |
Description |
Indexer action |
| Viewing change |
Same semantic spine, different wording/order/examples |
Mostly ignore — rebuild artifacts but expect identical indexing view |
| Slot/base explicitness change |
Implicit metadata made explicit |
Strengthen constructor signature, no semantic change |
| Editioned semantic change |
Meaning actually changed |
Mint new edition, retarget references explicitly |
| Described-entity retargeting |
Object of talk changed |
Not a refresh — treat as a retargeting event |
3. Refresh sentinels
Post-rebuild checks: ID continuity, alias coverage, anchor continuity, route closure, no dangling references, no hidden semantic owner changes. Report in build-audit.json.
Affected area
src/runtime/ (compiler & query engine)
Alternatives considered
Keeping hash-only refresh is simpler but does not protect against editorial drift — a whitespace-only rewrite triggers a full rebuild, while a silent semantic change gets the same treatment as a typo fix.
Additional context
- Current refresh logic:
src/runtime/runtime.ts lines 62–115
- Current compatibility check:
snapshotNeedsRebuild() lines 313+
FPF grounding:
- G.11 (Telemetry-Driven Refresh & Decay Orchestrator, Stable): Directly governs refresh triggers, decay detection, and edition-aware reruns. The proposed four-family change classification implements G.11's concern of knowing what kind of change triggers refresh.
- B.3.4 (Evidence Decay & Epistemic Debt, Stable): Hash-only refresh creates epistemic debt (B.3.4:2) — it cannot distinguish a cosmetic edit from a semantic change, so trust in the compiled index silently decays. The proposed sentinels implement B.3.4's freshness model.
- A.6.3 (U.EpistemicViewing, Stable): The indexing view is a describedEntity-preserving projection (a "view") of the compiled state — this is exactly what A.6.3 defines. The view adds no new semantics; it projects existing compiled artifacts into a stable machine-facing contract.
Note: Previous version cited A.6.S (SignatureEngineeringPair) and E.20 (Draft). A.6.S is about boundary signature engineering, not internal indexing views — replaced with A.6.3 (EpistemicViewing). E.20 is Draft status and its scope (mechanism introduction) doesn't match — removed.
Measurable impact
| Metric |
Before |
After (target) |
How to measure |
| Stable indexing view artifact exists |
No |
Yes (indexing-view.json emitted) |
ls .runtime/fpf-index/indexing-view.json |
| Change families classified in build audit |
0 |
4 (viewing, slot/base, editioned, retargeting) |
grep -c 'change_family' .runtime/fpf-index/build-audit.json |
| Refresh sentinel checks in build audit |
0 |
≥5 (ID continuity, alias coverage, anchor continuity, route closure, dangling refs) |
`grep -Ec 'sentinel |
| Unnecessary full rebuilds on whitespace-only edits |
triggers rebuild |
no rebuild (hash match on indexing view) |
Edit whitespace in FPF-spec.md, run bun run cli -- refresh, check build-audit.json for rebuilt: false |
Problem or motivation
Refresh is purely hash-driven: if the source hash matches, the snapshot is reused; otherwise full rebuild. This conflates four different change types into one "something changed" signal. Structure drift in authoring surfaces (heading structure, table layout, relation blocks) causes parser drift even when semantics haven't changed.
snapshotNeedsRebuild()inruntime.tsonly checks for missing description/metadata fields — it does not classify the nature of the change.Proposed solution
1. Declared machine-facing indexing view
Create a stable semantic spine artifact (e.g.,
indexing-view.json) containing the machine-facing contract: pattern IDs with canonical title/status/type/normativity/part/cluster, alias set with successor/deprecation pointers, anchor map, explicit relation edges, route-bearing metadata, and snapshot edition identity. On refresh, diff this view first before deciding whether a full rebuild is needed.2. Classify source changes into four families
3. Refresh sentinels
Post-rebuild checks: ID continuity, alias coverage, anchor continuity, route closure, no dangling references, no hidden semantic owner changes. Report in
build-audit.json.Affected area
src/runtime/ (compiler & query engine)
Alternatives considered
Keeping hash-only refresh is simpler but does not protect against editorial drift — a whitespace-only rewrite triggers a full rebuild, while a silent semantic change gets the same treatment as a typo fix.
Additional context
src/runtime/runtime.tslines 62–115snapshotNeedsRebuild()lines 313+FPF grounding:
Note: Previous version cited A.6.S (SignatureEngineeringPair) and E.20 (Draft). A.6.S is about boundary signature engineering, not internal indexing views — replaced with A.6.3 (EpistemicViewing). E.20 is Draft status and its scope (mechanism introduction) doesn't match — removed.
Measurable impact
indexing-view.jsonemitted)ls .runtime/fpf-index/indexing-view.jsongrep -c 'change_family' .runtime/fpf-index/build-audit.jsonFPF-spec.md, runbun run cli -- refresh, checkbuild-audit.jsonforrebuilt: false