docs(phase-3): fold in the proving consumer's review of the split table
Their answer crossed with the draft rather than responding to it, so the two readings of the same validator are independent. They agree on every substantive point -- four required keys, three reserved basenames, summary as the only nullable key, the index structure, the closed sets -- and on the column assignments. That is corroboration, not confirmation bias, and it is worth more than either reading alone. Four refinements folded in: - Emission order is an ordered prefix followed by remaining keys SORTED, not just an ordered list. This is the commons D1 outcome and it is what keeps regeneration byte-identical; normalising key order any other way breaks their BUNDLE_HASH_REGISTRY gate, which is why D1 mattered. - Values may be a non-empty LIST of strings, not only scalars. Same block -list shape Door C already refuses to round-trip, which is why imported concepts are written verbatim -- a scalars-only parser would destroy their Release pages, and a scalars-only profile would reject them. - Non-required allowlisted keys are validated against closed sets WHEN PRESENT, not required to be present. - Internal-link resolution generalises only because path_policy owns the layer layout; noted on the gate row as their caveat, accepted. Gate 5's row now distinguishes the Guard COLUMN (functionality that is the guard's and is never reimplemented) from the call SITE (theirs, in their acquisition stage) -- the one place our wording and theirs differed.
This commit is contained in:
parent
678f9b2b07
commit
08ca68fee2
1 changed files with 30 additions and 7 deletions
|
|
@ -1,9 +1,17 @@
|
|||
# Phase 3 split table — the proving consumer's 25 gates
|
||||
|
||||
Status: **draft, awaiting review.** Phase 3's plan requires this mapping before
|
||||
any porting, reviewed with the operator and with the proving consumer
|
||||
(`claude-code-llm-wiki`). Nothing here is implemented yet, and nothing in the
|
||||
consumer's repository is modified by this repository.
|
||||
Status: **drafted and independently corroborated; operator review outstanding.**
|
||||
Phase 3's plan requires this mapping before any porting. Nothing here is
|
||||
implemented yet, and nothing in the consumer's repository is modified by this
|
||||
repository.
|
||||
|
||||
The proving consumer (`claude-code-llm-wiki`) answered the same questions from
|
||||
their own code on 2026-07-25, crossing with this draft rather than responding
|
||||
to it. Two independent readings of the same source agreed on every substantive
|
||||
point: four required keys, three reserved basenames, `summary` as the only
|
||||
nullable key, the index structure, and the closed sets. Their answer added four
|
||||
refinements, each folded in below and marked. Their column assignments match
|
||||
this table's, with one wording difference resolved in gate 5's row.
|
||||
|
||||
Read from the consumer's working tree on 2026-07-25:
|
||||
`tools/wiki_ingest/validate.py` and `tools/wiki_ingest/bundle.py` at commit
|
||||
|
|
@ -28,7 +36,7 @@ that remains true, and a gate added there after this date is not in this table.
|
|||
| 2 | `INGEST_CHANGELOG_PARSE` | ERROR | Consumer | Source-format parsing for one specific upstream. |
|
||||
| 3 | `INGEST_EXPECTED_SET` | ALERT | Consumer | npm/changelog reconciliation against known deltas. |
|
||||
| 4 | `INGEST_DOCS_CORPUS_SANITY` | ERROR | Consumer | Corpus size/shape thresholds for one named corpus. Its second half — "a concept must not derive from the changelog page" — is a layer-provenance rule expressed as a URL test; see open question Q3. |
|
||||
| 5 | `INGEST_INPUT_INJECTION_SCAN` | WARN (ERROR when verbatim) | Guard | Carrier scan plus semantic lexicon on fetched input. The disposition-aware escalation is Consumer policy over a Guard verdict; see open question Q1. |
|
||||
| 5 | `INGEST_INPUT_INJECTION_SCAN` | WARN (ERROR when verbatim) | Guard | Carrier scan plus semantic lexicon on fetched input. Guard *column* means the functionality is the guard's and is never reimplemented — not that the call site moves here. The consumer keeps the call, as they state, since it sits in their acquisition stage. The disposition-aware escalation is Consumer policy over a Guard verdict; see Q1. |
|
||||
|
||||
## Stage B — LLM-output contract
|
||||
|
||||
|
|
@ -51,7 +59,7 @@ that remains true, and a gate added there after this date is not in this table.
|
|||
| 15 | `BUNDLE_RESERVED_FILES` | ERROR | Profile | `log.md` required-absent; `index.md` structure. Three reserved basenames, not two — see "What STRICT_V1 must express". |
|
||||
| 16 | `BUNDLE_YAML_STRICT` | ERROR | Profile | Key allowlist, required keys, and the StrictYAML scalar subset. |
|
||||
| 17 | `BUNDLE_LAYER_PATH_TYPE` | ERROR | Profile | Path prefix ⇄ `layer` ⇄ `source_tier` ⇄ `type` agreement. |
|
||||
| 18 | `BUNDLE_LINKS_INTERNAL` | ERROR | Profile | Every relative cross-link resolves inside the bundle. |
|
||||
| 18 | `BUNDLE_LINKS_INTERNAL` | ERROR | Profile | Every relative cross-link resolves inside the bundle. Consumer's caveat, accepted: link resolution assumes their layer layout, so it generalises only because `path_policy` owns the layout too. |
|
||||
| 19 | `BUNDLE_LINKS_EXTERNAL` | WARN (never blocks) | Consumer | Liveness polling; needs network state this library does not collect. |
|
||||
| 20 | `BUNDLE_URL_ALLOWLIST` | ERROR | mixed | Decomposed below. |
|
||||
| 21 | `BUNDLE_INDEX_COMPLETE` | ERROR | Profile | Per-directory index exactness plus root-index metadata keys. |
|
||||
|
|
@ -104,7 +112,10 @@ corrected in the same commit.
|
|||
*allowlist* that doubles as canonical emission order — `type`, `title`,
|
||||
`description`, `timestamp`, `layer`, `source_tier`, `source_url`,
|
||||
`source_sha`, `version`, `date`, `summary`. So `frontmatter_schema` needs
|
||||
three fields, not one: required, allowlisted, and ordered.
|
||||
three fields, not one: required, allowlisted, and ordered. The non-required
|
||||
keys are validated against closed sets **when present**, not required to be
|
||||
present — a profile that requires all of them rejects pages the consumer
|
||||
ships today.
|
||||
2. **Three reserved basenames, not two.** `index.md`, `log.md`, and
|
||||
`README.md`. README is bundle documentation, reserved like `index.md`: it
|
||||
carries no frontmatter, is skipped by the per-document gates, is never
|
||||
|
|
@ -118,8 +129,20 @@ Beyond the frontmatter set, `BundleProfile` must carry:
|
|||
- **Type policy:** closed enum, four values.
|
||||
- **Nullable keys:** `summary` alone may be `null` — the single deliberate
|
||||
escape from strings-only frontmatter.
|
||||
- **Value shapes:** a string scalar, **or a non-empty list of strings**. This
|
||||
is the same block-list shape Door C already refuses to round-trip through
|
||||
this library's line-oriented parser, which is why an imported concept is
|
||||
written verbatim. A profile that assumes scalars-only rejects the consumer's
|
||||
own `Release` pages, and a parser that assumes scalars-only would silently
|
||||
destroy them.
|
||||
- **Key-name grammar:** `^[a-z_]+$`.
|
||||
- **Scalar encoding:** the StrictYAML subset (JSON-double-quoted scalars), so
|
||||
a regeneration over the same data is byte-identical.
|
||||
- **Emission order — carry this over intact:** the ordered prefix above,
|
||||
followed by any remaining keys **sorted**. This is the door-A model settled
|
||||
by commons decision D1, and it is what makes regeneration byte-identical.
|
||||
A profile that normalises key order any other way breaks the consumer's
|
||||
`BUNDLE_HASH_REGISTRY` gate, which is what made that decision matter.
|
||||
- **Layer/path policy:** `concepts/` ⇄ layer `concepts`, source_tier
|
||||
`official-docs`, any type except `Release`; `releases/` ⇄ layer `releases`,
|
||||
source_tier `changelog-derived`, type `Release` exactly. Their constants
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue