Eight load-bearing ADRs closing the loop from contemplation Phase 5 through a public showcase demo. Each one is small and evidence-bearing; together they sequence the next arc without duplicating existing substrate. - 0092 Reviewer Registry v1 — populates docs/reviewers.yaml schema; unblocks all reasoning-capable claims under ADR-0091. - 0093 Domain Pack Contract v1 Implementation — wires ADR-0091's five follow-up items (parser, dry-run validator, chain registry, eval lane refs, reviewer resolution) so manifest fields actually gate status. - 0094 Proposal Source Provenance — sealed ProposalSource type widening proposal schemas ahead of 0095. - 0095 Miner-Sourced Teaching Proposals — closes the contemplation loop: articulation_quality / contradiction_detection / frontier_compare miners emit PackMutationProposal candidates routed through the single reviewed teaching path; identity-pack defense at construction, not review; replay-equivalence pre-gate. - 0096 Fabrication-Control Eval Lane — first negative-control measure; three case classes (phantom endpoint, cross-pack non-bridge, sibling collapse) with frozen thresholds (fabrication_rate ≤ 0.01). - 0097 Mathematics-Logic Reasoning-Capable Ratification — first domain claim under ADR-0091; chain corpus + eval lanes already exist, this is the formal contract ratification. - 0098 Demo Composition Contract — DemoCommand protocol so demos can be composed without reimplementation; deterministic JSON, no global state mutation, declared output paths only. - 0099 Public Showcase Demo — composes four scenes (determinism / honest unknown / reviewed learning / multi-hop+trace) under 30s; pure composition enforced by grep gate; JSON byte-equality CI-pinned. Landing order: 0092 → 0094 → 0095 → 0093 → 0096 → 0097 → 0098 → 0099. Deliberately not included: curriculum compiler, formation course runner, calculator operators, response-mode taxonomy expansion, learning-scale 10k harness. Each is deferred with a documented reason.
125 lines
4.2 KiB
Markdown
125 lines
4.2 KiB
Markdown
# ADR-0094 — Proposal Source Provenance
|
|
|
|
**Status:** Proposed
|
|
**Date:** 2026-05-21
|
|
**Author:** CORE agents + reviewers
|
|
|
|
---
|
|
|
|
## Context
|
|
|
|
`teaching/proposals/proposals.jsonl` and the surrounding review flow
|
|
(`teaching/review.py`, `teaching/store.py`, ADR-0057) currently assume
|
|
proposals originate from a single source: an operator authoring through
|
|
the existing teaching CLI. The schema has no typed source field.
|
|
|
|
Two near-term ADRs widen this:
|
|
|
|
- ADR-0095 introduces miner-sourced proposals (contemplation Phase 5
|
|
loop closure).
|
|
- A future ADR will introduce curriculum-sourced proposals (deferred
|
|
per the rewrite blueprint).
|
|
|
|
Without a typed source field, downstream consumers (`teaching/review.py`,
|
|
capability ledger evidence rows, audit telemetry) will branch on string
|
|
prefixes informally. That is the same shape of mistake ADR-0067's
|
|
explicit `subject_pack_id` / `object_pack_id` fields prevented for
|
|
cross-pack chains.
|
|
|
|
---
|
|
|
|
## Decision
|
|
|
|
Introduce a sealed `ProposalSource` type widening
|
|
`PackMutationProposal` / `TeachingProposal` schemas. The widening is
|
|
schema-only; no runtime behavior changes under this ADR.
|
|
|
|
### Sealed type
|
|
|
|
```python
|
|
@dataclass(frozen=True, slots=True)
|
|
class ProposalSource:
|
|
kind: Literal["operator", "miner", "curriculum"]
|
|
source_id: str # "" for kind="operator"; miner_id or course_id otherwise
|
|
emitted_at_revision: str # git SHA at emission
|
|
|
|
def serialize(self) -> str:
|
|
# "operator", "miner:articulation_quality", "curriculum:math_logic_v1"
|
|
return self.kind if not self.source_id else f"{self.kind}:{self.source_id}"
|
|
```
|
|
|
|
### Schema migration
|
|
|
|
- New field on `PackMutationProposal` and `TeachingProposal`:
|
|
`source: ProposalSource`.
|
|
- Default for existing operator-authored proposals: `ProposalSource(kind="operator", source_id="", emitted_at_revision=<head>)`.
|
|
- Migration is one-shot at ADR landing: a deterministic rewriter walks
|
|
existing `proposals.jsonl` files, attaches the default operator
|
|
source, and rewrites in sorted order. Migration is a reviewed
|
|
proposal itself.
|
|
|
|
### Consumer rules
|
|
|
|
- `teaching/review.py` performs exhaustive match on `source.kind`. Any
|
|
new kind requires a new ADR adding a branch.
|
|
- Telemetry events (`chat/telemetry.py`) carry `source.serialize()` as
|
|
a string field. Redact-by-default already covers proposal content;
|
|
source is non-sensitive and emitted plainly.
|
|
- Capability ledger evidence rows (ADR-0091) include `source` in their
|
|
provenance trail.
|
|
|
|
### What this ADR does not do
|
|
|
|
- Does not introduce miner-sourced proposals (ADR-0095).
|
|
- Does not introduce curriculum-sourced proposals.
|
|
- Does not change review thresholds. Source affects audit, not gate.
|
|
|
|
---
|
|
|
|
## Invariant
|
|
|
|
`proposal_source_exhaustive_match` — every code path that branches on
|
|
`proposal.source.kind` uses Python `match` with explicit cases for each
|
|
sealed-type value; the type checker refuses a non-exhaustive match. A
|
|
proposal without `source` fails parsing.
|
|
|
|
---
|
|
|
|
## Lane
|
|
|
|
`evals/proposal_source_schema/` (new, small):
|
|
|
|
- positive: round-trip serialization for each `kind`
|
|
- negative: missing `source` field rejected at parse
|
|
- negative: unknown `kind` rejected at parse
|
|
- migration: existing `proposals.jsonl` rewritten deterministically;
|
|
two runs produce identical bytes
|
|
|
|
---
|
|
|
|
## Trust Boundary
|
|
|
|
`source_id` is a typed string but flows through user-adjacent surfaces
|
|
(telemetry, ledger reports). It is sanitized via
|
|
`core/_safe_display.safe_display` at all surface emission points,
|
|
matching the discipline established in ADR-0051. The migration rewriter
|
|
runs only when invoked explicitly; no implicit on-load mutation.
|
|
|
|
---
|
|
|
|
## Consequences
|
|
|
|
- ADR-0095 can introduce `kind="miner"` without secondary schema churn.
|
|
- A future curriculum ADR can introduce `kind="curriculum"` the same way.
|
|
- Existing operator review flow is unchanged; the new field is set to
|
|
its operator default on every existing proposal.
|
|
|
|
---
|
|
|
|
## PR Checklist
|
|
|
|
- Capability added: typed provenance schema for proposals.
|
|
- Invariant proved: `proposal_source_exhaustive_match`.
|
|
- Lane proving it: `evals/proposal_source_schema/`.
|
|
- Hidden normalization / stochastic fallback / approximate recall / unreviewed mutation: none. Migration is explicit and reviewed.
|
|
- Trust boundary: `source_id` sanitized at every surface; no implicit on-load rewrites.
|