spec: design-ledger-formal-links — recon-driven amendment (clause-6 + cross-ref definition)

Planner Step-2 recon (ailang-plan-recon) surfaced two spec defects;
forward-fix amendment (63b669f stands, main forward-only):

- clause-6 homeless-ref remedy was an incomplete binary. Recon proved
  roundtrip-invariant.md does NOT carry the ail-merge-prose-cycle
  content that pipeline.md:61 / authoring-surface.md:180 cite — so the
  prior canonical retarget sample was wrong. Replaced with three
  priority-ordered dispositions; PROSE_ROUNDTRIP refs take (b) (drop
  the cross-tier pointer, preserve the present-tense behavioural prose).
- Added a precise 'what counts as a cross-reference' definition:
  navigational pointer = in scope; nominal source-symbol mention = out
  of scope (keeps the milestone 'formalise the cross-references', not
  'hyperlink the ledger'). Source link only for a genuine navigational
  (see crates/...). Folds OQ2 (strip iter-provenance suffixes on
  conversion) + OQ3 (no-title directional stays prose) as byte-policies.

grounding-check re-dispatched on the amended bytes: PASS, all
assumptions ratified incl. the amendment-introduced ones.
This commit is contained in:
2026-05-19 23:03:03 +02:00
parent 63b669fa8f
commit b1a0364bf2
@@ -93,14 +93,27 @@ not forks):
These stay as prose. The remedy for "this file is too big for These stay as prose. The remedy for "this file is too big for
'above' to be clear" is commitment 1's file-split — a separate 'above' to be clear" is commitment 1's file-split — a separate
future concern, explicitly NOT this milestone. future concern, explicitly NOT this milestone.
- **Homeless references resolve or die.** A prose reference whose - **Homeless references — three dispositions (clause-6), in
referent has no durable home (e.g. priority order.** A cross-reference whose referent has no durable
`design/models/pipeline.md``(see docs/PROSE_ROUNDTRIP.md)`) home is: **(a)** retargeted to the durable `design/`-or-source
is retargeted to the durable file that carries the content today file that *actually carries that content* today, if one exists;
(here: `../contracts/roundtrip-invariant.md`) if one exists, else else **(b)** the parenthetical pointer is removed while the
deleted as decision-record-class prose (clause-3 already forbids surrounding present-tense behavioural prose is preserved verbatim
the relitigation form). Enumerating them is a recon/plan-time the ledger *describes* the behaviour, it does not point into
scan, not a spec byte-decision. the non-durable tier; else **(c)** deleted outright **only if the
reference itself is relitigation residue** (clause-3-class).
Recon-confirmed canonical instance:
`design/models/pipeline.md:61` and
`design/models/authoring-surface.md:180`, both
`(see docs/PROSE_ROUNDTRIP.md)`, cite the *prose-mediator cycle /
`ail merge-prose`* — content
`design/contracts/roundtrip-invariant.md` does **not** carry
(that contract is the orthogonal hashing / parse-determinism
invariant). (a) is therefore unavailable and the content is real
current behaviour, not relitigation, so the disposition is
**(b)**: drop the `(see docs/PROSE_ROUNDTRIP.md)` pointer, keep
the surrounding `ail merge-prose` prose intact. Enumerating every
instance is the recon's job; the *policy* is the spec's.
- **A cross-*file* `§"Section"` reference becomes a file-link.** - **A cross-*file* `§"Section"` reference becomes a file-link.**
`(see §"Data model" …)` pointing at content in *another* file `(see §"Data model" …)` pointing at content in *another* file
becomes `[Data model](data-model.md)` — the section title may becomes `[Data model](data-model.md)` — the section title may
@@ -111,6 +124,49 @@ not forks):
file is intra-file directional prose — the bullet above — and is file is intra-file directional prose — the bullet above — and is
untouched.) untouched.)
## Scope — what counts as a cross-reference
The milestone formalises **navigational cross-references**, not
every nominal mention of a file or symbol. The discriminator:
- **In scope (a cross-reference):** a *navigational pointer* — the
reader is being told to go look elsewhere. Forms: `(see "Title"
…)`, `(see §"Section" …)`, `(see <path>)`, `… as in <X> …`, a
bare in-prose path inside a `(see …)`, or a directional `…
below`/`… above` whose named target is a **different file**.
These convert to file-relative `[label](path)` Markdown links.
- **Out of scope (not a cross-reference):** a *nominal mention* of
a source symbol or path in explanatory prose — "the desugarer
`ailang-core::desugar` lowers loop-recur", "the box layout in
`crates/ail-embed/src/lib.rs`". Naming the implementation is not
pointing the reader at a document to read. Linkifying these would
make the milestone "hyperlink the whole ledger" rather than
"formalise the cross-references" — a different, unrequested
change. They stay as prose. Commitment 2 *permits* a `crates/**`
link target only for the case where a genuine navigational `(see
crates/… )` pointer exists — e.g. `scope-boundaries.md:88` `see
\`ailang-core::desugar\`` converts to
`[desugar](../../crates/ailang-core/src/desugar.rs)` — never for
a nominal mention.
Two byte-policies the conversion applies (Boss-adjudicated from
recon Open Questions; the planner does not re-open them):
- **Iter-provenance suffixes are stripped on conversion.** A
reference like `see §"Class names" / mq.1` carries a
clause-3-class iter token. Converting yields
`[Class names](typeclasses.md)` — the ` / mq.1` provenance is
removed (it is exactly what clause-3 forbids; the
clause-3 ∘ clause-5 composition requires its removal, not its
survival riding on a now-formal link).
- **A directional phrase with no quoted title and no `(see …)`
form stays prose.** `embedding-abi.md:51` "the frozen value
layout below specifies" has no title to become a link label and
is not a `(see …)` pointer — descriptive directional prose, left
untouched. (The genuine cross-file pointer for that referent is
the *separate* `embedding-abi.md:45` `(see "Frozen value layout"
below)`, which does convert.)
## Concrete code shapes ## Concrete code shapes
### No authoring surface — the delivered concrete code ### No authoring surface — the delivered concrete code
@@ -261,13 +317,21 @@ design/contracts/embedding-abi.md:45 (informal AND stale-direction
- after: … layout is **frozen as of M3** (see - after: … layout is **frozen as of M3** (see
[Frozen value layout](frozen-value-layout.md)); … [Frozen value layout](frozen-value-layout.md)); …
design/models/pipeline.md:61 (the canonical HOMELESS reference — design/models/pipeline.md:61 + design/models/authoring-surface.md:180
points into docs/, the non-durable tier) (the canonical HOMELESS references — `(see docs/PROSE_ROUNDTRIP.md)`
- before: … (see docs/PROSE_ROUNDTRIP.md) into the non-durable tier; recon proved roundtrip-invariant.md
- after: … (see [round-trip invariant](../contracts/roundtrip-invariant.md)) does NOT carry the merge-prose-cycle content ⇒ clause-6
# retargeted to the durable home that carries the disposition (b), not a retarget)
# content; if recon finds no durable home, the clause-6 - before (shape): … the prompt template `ail merge-prose`
# rule deletes it as decision-record-class prose instead composes (see docs/PROSE_ROUNDTRIP.md).
- after (shape): … the prompt template `ail merge-prose`
composes.
# disposition (b): the (see docs/…) pointer is removed;
# the surrounding present-tense behavioural prose about
# `ail merge-prose` is preserved verbatim. Exact bytes
# (recon-confirmed pipeline.md:60-61,
# authoring-surface.md:180-181) are the planner's per
# the planner Iron Law.
``` ```
### (c) clause-1 is unchanged (commitment 4, INDEX = spine) ### (c) clause-1 is unchanged (commitment 4, INDEX = spine)
@@ -344,12 +408,19 @@ outcome, not a dodge).
2. clause-5 is demonstrably RED-able (the synthetic vector fails if 2. clause-5 is demonstrably RED-able (the synthetic vector fails if
the durable classifier or the anchor check is wrong) and GREEN on the durable classifier or the anchor check is wrong) and GREEN on
the final tree. the final tree.
3. Every genuine cross-*file* prose reference in `design/contracts/` 3. Every *navigational* cross-*file* reference (per §"Scope — what
and `design/models/` is a file-relative `[label](path)` Markdown counts as a cross-reference") in `design/contracts/` and
`design/models/` is a file-relative `[label](path)` Markdown
link resolving (from its containing file) to an existing link resolving (from its containing file) to an existing
`design/`-or-source file. The float-semantics, embedding-abi, and `design/`-or-source file — OR, for a homeless reference, is
pipeline references above are converted exactly as shown (modulo disposed per clause-6 (a)/(b)/(c). Nominal source-symbol
recon's homeless-home confirmation). mentions are NOT linkified (out of scope). Iter-provenance
suffixes on converted refs are stripped. The recon enumeration
is the authoritative touch-set: float-semantics:100,
float-semantics:69, embedding-abi:45, data-model:38/66/79/206/226,
memory-model:44/105, scope-boundaries:48/88 convert; the two
PROSE_ROUNDTRIP refs take disposition (b); embedding-abi:51 and
every intra-file "above/below" stay prose.
4. No reference in `design/` targets `docs/` (any subtree) or 4. No reference in `design/` targets `docs/` (any subtree) or
carries a `#fragment`. carries a `#fragment`.
5. `design/INDEX.md` and clause-1 are byte-unchanged; the 5. `design/INDEX.md` and clause-1 are byte-unchanged; the