Skip to content

docs(rich): freeze Phase-B semantic contract candidate (#669) - #685

Merged
jnhu76 merged 2 commits into
masterfrom
docs/669-rich-semantic-contract-phase-b
Oct 2, 2026
Merged

jnhu76 merged 2 commits into
masterfrom
docs/669-rich-semantic-contract-phase-b

Conversation

@jnhu76

@jnhu76 jnhu76 commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

Phase-B authority pass for #669 (Rich Protocol / Backend Contract Freeze): turn the candidate Phase-B decisions into repository-level authority so independent review can accept them and Phase C gets a stable oracle.

Documentation-only. No production code, no tests, no schema changes. The known B-F01 closure bug remains deliberately unfixed.

Authority structure

What is frozen (candidate)

  • Single Rich V1 authority = closed grammar + normalization/equivalence + CONTENT_LIMITS + declared editor→canonical mapping policy.
  • Canonicalization invariants RC-01..RC-04, including the load-bearing closure property: successful canonicalization must produce a value the same semantic system accepts (schema + limits + idempotence + safe read/replay).
  • Typed read trust: empty / plain / legacy_plain (provenance-gated) / rich_valid / rich_noncanonical / unsupported_version / corrupt, with CORRUPT_PERSISTED_RICH != EMPTY_DOCUMENT.
  • Verbatim submit freeze (submit must not re-normalize/repair/reinterpret an accepted value).
  • Grading/result frozen parity; capability downgrade obligations (new commitment vs accepted obligation, per ADR-022); canonical replay identity semantics; mutable-attempt replay guarantee; export raw-vs-projection separation; inert/bounded rendering obligations.

Explicitly NOT frozen

Receipt physical storage / SHA implementation / DB schema & index; B-F01 repair mechanism (split vs reject left for Phase C/D after adversarial evidence); Phase-C generator design; offline protocol; admission protocol; capability resolver implementation; Math UX; exact export DTO field names.

B-F01 disposition

KNOWN · NOT FIXED · USED AS PHASE-B COUNTEREXAMPLE (motivating RC-03) · PHASE-C/D FOLLOW-UP.

Review rounds

  • Round 1 @ 344c1473: verdict CHANGE_REQUIRED — blockers F1 (post-merge status self-contradiction) and F2 (plain vs legacy_plain read-trust conflation).
  • F1/F2 corrections @ be035c6d (docs-only follow-up):
    • F1: status header and §19 lead-in now state the post-merge normative status ("normative, adopted by ADR-019 Phase-B amendment"); candidate/review state lives only in this PR body.
    • F2: §7 splits plain / legacy_plain into distinct read states with the provenance rule — plain follows from slot answer mode (never typeof value === "string"), legacy_plain requires explicit source/mode provenance, and an unexplained string where Rich is authoritative classifies as corrupt, so candidate restore / reload / recovery / STALE_VERSION adoption / grading-result rendering / export cannot bypass the typed-read boundary.
  • Awaiting focused re-review of F1/F2 only.

Checks

  • pnpm format:check — PASS
  • pnpm verify:static — PASS (format/lint/lint:arch/lint:db-config/lint:db-journal/lint:env-contract/lint:eslint/typecheck/openapi:check; recursive-reference exporter warnings are pre-existing)
  • git diff --check — PASS
  • Follow-up be035c6d (docs-only): pre-push gate re-ran lint:arch / typecheck / openapi:check — PASS (same pre-existing exporter warnings); pnpm format:check re-run — PASS

Scope audit

git diff --stat vs master: 4 files, +539/−6, all under docs/. No apps/ or packages/ changes.

Handoff

PHASE_B_AUTHORITY_CANDIDATE = F1_F2_CORRECTED_AWAITING_FOCUSED_RE_REVIEW
PHASE_B                     = STILL_NOT_ACCEPTED
READY_FOR_PHASE_C           = NO

Refs #669, #673. Does not close #669.

@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 57cfcbd6-3b17-4e8a-b392-c46fe8432cb5

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

jnhu76 commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

Independent Phase-B authority review @ 344c1473

Verdict: CHANGE_REQUIRED before Phase-B acceptance.

The architecture direction is sound and scope is disciplined (docs-only, B-F01 deliberately unfixed, replay semantics separated from receipt mechanism), but two authority-level ambiguities should be corrected before this can become the Phase-C oracle.

F1 — authority status is self-contradictory after merge

rich-content-semantic-contract.md says Status: Phase-B authority candidate awaiting independent review, while the same change marks ADR-019 as ACCEPTED, amended (2026-10-02) and both indexes say the new document is adopted authority.

If merged as-is, the normative document will permanently claim it is still a candidate awaiting review while its adoption record says it is accepted.

Required correction: repository text should describe the post-merge state. The PR body may carry candidate / awaiting review; the normative document should say it is normative/adopted by ADR-019 (or equivalent wording that remains true after merge).

F2 — read-trust contract still conflates Plain with legacy-Plain-in-Rich

§7 currently has one row: plain / explicitly sourced legacy plain, with the explanation that a plain string or legacy plain answer means Rich authority is not invoked.

These are materially different cases:

  1. Plain slot/mode — ordinary Plain value; Rich semantics genuinely do not apply.
  2. Legacy plain value inside a Rich-associated frozen slot/source — valid only when provenance explicitly establishes the legacy case. It must be classified by the shared Rich read-trust resolver; an arbitrary string under frozen Rich mode must not become valid merely because typeof value === "string".

Required correction: split these states (e.g. plain and legacy_plain) or state the provenance rule equivalently. Make explicit that legacy_plain requires source/mode evidence, while an unexplained string where Rich is authoritative is corrupt / unsupported according to the chosen taxonomy. This prevents candidate restore / STALE adoption / export from bypassing the typed-read boundary Phase B is freezing.

Everything else reviewed

  • RC-03 closure correctly captures B-F01 without prescribing the repair.
  • CONTENT_LIMITS vs preflight ownership is appropriately separated.
  • Submit is verbatim freeze; no second canonicalizer is introduced.
  • Grading/result consume one frozen content authority.
  • ADR-022 new-commitment vs accepted-obligation semantics are preserved.
  • Replay freezes canonical identity + mutable-attempt no-silent-eviction semantics, while SHA/SQL/index/migration remain out of Rich authority.
  • Export and rendering freeze obligations without prematurely fixing DTO/mechanism.
  • No ADR-023 is needed.

CI note at review time: Static checks are green; Build was still running. No production/test changes were found.

PHASE_B_AUTHORITY_CANDIDATE = CHANGE_REQUIRED
PHASE_B                     = NOT_ACCEPTED
READY_FOR_PHASE_C           = NO
BLOCKERS                    = F1, F2

After F1/F2 are corrected, this should be a focused re-review rather than another broad audit.

F1 (PR #685 review): the normative document described itself as a
candidate awaiting independent review while ADR-019 and both indexes
record it as adopted; repository text now states the post-merge status
(header + §19 lead-in).

F2 (PR #685 review): §7 merged plain and explicitly sourced legacy
plain into one read state. They are now distinct states: plain follows
from the slot's answer mode, legacy_plain requires explicit source /
mode provenance, and an unexplained string where Rich is authoritative
classifies as corrupt, so candidate restore / STALE adoption / export
cannot bypass the typed-read trust boundary.
@jnhu76

jnhu76 commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

F1/F2 corrections landed in be035c6d (docs-only follow-up, +18/−8, touches only rich-content-semantic-contract.md):

F1 — post-merge status. The status header now states the post-merge truth: Status: **normative**, adopted by ADR-019 (Phase-B amendment, 2026-10-02). The §19 lead-in Before acceptance… (same pre-merge process language) is now This contract must continue to satisfy:. Candidate / review state now lives only in the PR body (Review rounds + Handoff blocks updated).

F2 — read-trust split. §7 now carries separate plain and legacy_plain rows plus explicit classification rules:

  • plain follows from the slot's answer mode — never inferred from typeof value === "string" alone;
  • legacy_plain requires explicit source / mode provenance establishing the value was written by the legacy plain protocol for that slot;
  • a plain string where Rich is authoritative, without that provenance, classifies as corrupt (inconsistent stored shape) and must not be adopted as a valid plain answer by candidate restore, reload, recovery, STALE_VERSION adoption, grading / result rendering, or export.

§19-F already enumerated legacy as a distinct state; the §7 table now matches it.

Checks for be035c6d: pnpm format:check PASS · git diff --check PASS · pre-push gate (lint:arch / typecheck / openapi:check) PASS with the same pre-existing exporter warnings. No other files touched.

Ready for the focused re-review (F1/F2 only).

jnhu76 commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

Focused re-review — F1/F2 @ be035c6d

Verdict: PASS for the authority corrections. No new blocker found in 344c1473..be035c6d.

Scope was intentionally limited to the follow-up commit only.

F1 — PASS

The normative document now describes the durable post-merge state: Status: normative, adopted by ADR-019 (Phase-B amendment, 2026-10-02). The §19 lead-in is likewise timeless (This contract must continue to satisfy:). Candidate/review workflow state remains in the PR body, not in normative repository text.

This removes the previous self-contradiction between the architecture document, ADR-019, and the indexes.

F2 — PASS

§7 now gives plain and legacy_plain distinct trust semantics:

  • plain follows from the slot's Plain answer mode and is explicitly not inferred from typeof value === "string";
  • legacy_plain requires explicit source/mode provenance showing that the value was written under the legacy plain protocol for that Rich-associated slot/source;
  • an unexplained string where Rich is authoritative is corrupt, and candidate restore/reload/recovery/STALE_VERSION adoption/grading-result rendering/export may not treat it as a valid plain answer.

That is the missing provenance rule from the first review and closes the C4 typed-read bypass ambiguity.

Scope / regression check

The follow-up commit changes exactly one file, docs/architecture/rich-content-semantic-contract.md, with +18/−8. No receipt mechanism, B-F01 repair, production code, test code, ADR authority, capability semantics, or other Phase-B decisions were changed.

F1                              = CLOSED
F2                              = CLOSED
NEW_AUTHORITY_BLOCKERS          = NONE
PHASE_B_AUTHORITY_CONTENT       = PASS
PR_685_CONTENT_REVIEW           = PASS

At review time the exact-head CI matrix for be035c6d is still running, so this is not a claim that all required CI is green yet. Once the required exact-head checks pass, I consider PR #685 ready to merge. The actual Phase-B acceptance point should be the merged authority SHA recorded in #669; only then set PHASE_B = PASS / READY_FOR_PHASE_C = YES and start the frozen-oracle Phase C campaign.

@jnhu76
jnhu76 merged commit 6c50ebf into master Oct 2, 2026
11 checks passed
@jnhu76
jnhu76 deleted the docs/669-rich-semantic-contract-phase-b branch October 2, 2026 10:32
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.

[Umbrella][Rich Subjective] Protocol/backend closure → candidate editor UX → adversarial proof

1 participant