Skip to content

feat(v3): T-Substrate-AnthropicSchemaMirror — provider-domain type mirror for Messages signature - #1261

Merged
briansrls merged 46 commits into
mainfrom
session/sharp-raven-604
Apr 30, 2026
Merged

briansrls merged 46 commits into
mainfrom
session/sharp-raven-604

Conversation

@briansrls

@briansrls briansrls commented Apr 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

T-Substrate-AnthropicSchemaMirror — v3 typed mirror of provider-domain schema types reachable from dsl/extdeps/llm/anthropic.dag's operation Messages signature.

Scope discipline:

  • Schema mirror only. Type authority for the provider-domain types reachable from the Messages signature; no data rows, no fn declarations.
  • Callable declaration precursor follows. fn anthropic_messages and any Operation row land in the next substrate slice that consumes these types — outside this PR.
  • Grounding PR-β (feat(grounding): T-Ground services.dag PR-β — anthropic_operations Phase 1 pilot #1252) remains paused. This PR alone does not unblock Grounding; PR-β consumes the callable from the follow-on, which in turn consumes these types.
  • No service-parser ingestion. v3's parser does not handle the v2 service { operation { transport rest { … } } } block; pulling anthropic.dag wholesale into BOOTSTRAP_FIXTURE_PATH_KEYS would lower the service block as ValueBody::Unparsed. This file is a v3-shaped typed twin, not a parse-import.
  • No test-only bridge. The mirror is real substrate type authority loaded by Dag::new(); the integration test consumes the production accessor surface.

Adds:

  • src/v3/std/anthropic_schema.dag — type authority only. Mirrors:
    • AnthropicChatMessage (UserMessage / AssistantMessage discriminator)
    • AnthropicUserContentBlock (UserTextBlock / UserToolResultBlock)
    • AnthropicAssistantContentBlock (AssistantTextBlock / AssistantToolUseBlock)
    • AnthropicStopReason (closed Anthropic API enum, all 7 variants)
    • AnthropicMessages200TextBlock / AnthropicMessages200Usage / AnthropicMessages200Body
  • src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs — 9 ratchets pinning v3 mirror against dsl/extdeps/llm/anthropic.dag. Each ratchet (a) walks the mirrored type's connective in the bootstrap and asserts the expected field/variant label set, then (b) extracts the matching type <name> block from the v2 source and asserts every expected label is present in that block — coupling the expected set to the v2 source itself, not just to constants in the test. Plus a textual optionality ratchet on is_error: Bool? and stop_sequence: String?.

Out of scope (deferred)

  • AnthropicErrorShape — covers the 4xx/5xx response slot only; not on the typed return reach for fn anthropic_messages -> AnthropicMessages200Body. Lands with the response/wire lockstep lane (Grounding's PR-β scope).
  • AnthropicModel, AnthropicModelSpec, AnthropicToolDefinition, AnthropicApiVersion, SystemPrompt, CacheControl, ThinkingMode, ThinkingConfig — outside the Messages operation's direct signature reach.
  • fn anthropic_messages and any Operation data row — next substrate precursor.

Why a v3 typed twin (rather than ingesting anthropic.dag directly)

Per the prior #1246 STOP+PING: pulling dsl/extdeps/llm/anthropic.dag wholesale into BOOTSTRAP_FIXTURE_PATH_KEYS would lower the v2 service { … } block as ValueBody::Unparsed (v3's parser does not handle that DSL today). This file is the typed twin authored on the v3 surface — same staged-fixture discipline as MethodTemplateContract (#1195) and services.dag PR-α (#1246).

Dissolution trigger

When v3 grows a service-DSL parse/load surface that ingests dsl/extdeps/llm/*.dag with full structural fidelity, this twin retires — the v2 source becomes the only authority and this file collapses. Tracked dissolution per modeling-discipline (feedback_parallel_representation_debt).

Local verification commands

cargo run -p v3-compiler --features bootstrap-regen-fresh --bin regen_bootstrap
cargo run -p v3-compiler --features bootstrap-regen-fresh --bin regen_bootstrap -- --verify
cargo test -p v3-compiler refresh_handwritten_parse_snapshot_manifest -- --ignored
cargo test -p v3-compiler --test integration anthropic_schema_lockstep
cargo test -p v3-compiler --test integration parse_stage4_prep::handwritten_parse_snapshot_matches_manifest
cargo test -p v3-compiler --test integration sg0_census

Test plan

  • Lockstep ratchets pass (9/9 local).
  • Bootstrap regen + manifest refresh committed.
  • SG-0 census entry added for the new hand-authored test file.
  • CI green once flipped to ready.

🤖 Generated with Claude Code

…ages signature

- src/v3/std/anthropic_schema.dag: type-authority-only mirror of provider-domain
  types reachable from operation Messages signature in
  dsl/extdeps/llm/anthropic.dag (AnthropicChatMessage + content block variants,
  AnthropicStopReason, AnthropicMessages200{TextBlock,Usage,Body}).
- AnthropicErrorShape deferred (4xx/5xx response slot only; not on the typed
  return reach for fn anthropic_messages -> AnthropicMessages200Body).
- src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:
  8 ratchets pinning v3 mirror against v2 source (variant labels, field labels,
  type-name presence in v2). Discipline mirrors method_registry_test.rs.
- Type authority only — no fn anthropic_messages, no Operation rows. Those
  are the next substrate precursor that consumes these types.
@briansrls briansrls changed the title sharp-raven-604 feat(v3): T-Substrate-AnthropicSchemaMirror — provider-domain type mirror for Messages signature Apr 30, 2026
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 1e08a24e · Trigger: schedule
  • Comparison: origin/main @ 86961089 ... review/pr-1261-1e08a24e @ 1e08a24e
  • Thinking: 23s wall

This is a clean substrate addition: typed mirror dag file + bidirectional lockstep ratchet test + regenerated bootstrap. Dissolution trigger documented (v3 service-DSL parser). Type-authority-only with a test asserting no value bodies leak. Set-equality (not subset) on both sides plus per-variant payload + optionality coverage — the ratchet fails closed in both directions.

Verdict: APPROVE — narrow, well-scoped substrate mirror with a fail-closed lockstep test against the v2 authority and a named, bounded dissolution trigger. No INVARIANTS / modeling-discipline / CODING / TESTING violations observed in the diff.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-thinking
  • Commit: 1e08a24e · Trigger: manual
  • Comparison: main @ 86961089 ... session/sharp-raven-604 @ 1e08a24e
  • Conversation: View conversation

1. Story of the diff

This PR introduces a narrow v3 .dag type mirror for the Anthropic Messages signature rather than importing the existing v2 dsl/extdeps/llm/anthropic.dag wholesale. The new src/v3/std/anthropic_schema.dag explicitly scopes itself to the operation input/output type reach, omits service/operation rows, and names the mirror as a temporary typed twin until v3 can structurally ingest the extdeps service DSL (src/v3/std/anthropic_schema.dag:6-36). The generated bootstrap files are regenerated to include these declarations, the parse corpus manifest is updated for the new .dag, and a new integration ratchet compares the v3 mirror against the v2 source for mirrored type presence, field/variant labels, payload shape, and optionality (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:5-23, src/v3/compiler/tests/integration.rs:40-41).

The load-bearing mechanism is the lockstep test: it treats the v2 file as the source authority and walks the generated v3 bootstrap declarations. That is the right direction for this staged bridge, but the current ratchet does not compare field type targets, so a core part of the “type mirror” can drift while tests stay green.

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Finding — BLOCKING. This diff adds substrate-level provider-domain types under src/v3/std/anthropic_schema.dag, and the file correctly states that this is a temporary twin with a dissolution trigger (src/v3/std/anthropic_schema.dag:33-36). However, the bridge’s drift ratchet only compares field/variant labels and optionality: records reduce v2 to labels at src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:314-316, and variants reduce v3/v2 payloads to (field_label, optional) at src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:271-278 and src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:372-390. That means content: List<AnthropicMessages200TextBlock> could become content: String, or input_tokens: Int could become String, without the lockstep test failing as long as the label and ? bit stay the same. For a substrate type mirror, field type identity is part of the modeled fact, not an implementation detail.

  1. INVARIANTS.md + modeling-discipline.md.

Finding — BLOCKING. Boundary Discipline / single-authority metadata is only partially enforced. The PR says the v2 file is the authority source (src/v3/std/anthropic_schema.dag:6-15) and that the new test pins mirrored names/labels/variants against it (src/v3/std/anthropic_schema.dag:28-31), but the actual assertions only establish label-set equality and optionality (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:317-347, src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:375-406). The missing type-shape comparison leaves two independently editable authorities for a field’s carrier type.

  1. CODING.md.

Compliant. The new Rust test code stays in free-function/data style: helpers such as conj_field_labels, v2_record_fields, v2_disj_variants, and assert_record_lockstep are pure projections/assertions over explicit inputs rather than hidden state or object methods (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:33-78, src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:84-269, src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:312-419).

  1. TESTING.md.

Finding — BLOCKING. The new tests are behavior-targeted and wired into the integration suite (src/v3/compiler/tests/integration.rs:40-41), but the central behavior claim is under-tested: “lockstep” for a type mirror must include field type expressions, not only field names and optionality. The record path collects v2_labels from (label, optional) only (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:315-316), while the variant-payload path collects v2_set / v3_set from labels only (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:372-383) and then checks optionality only (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:384-406). This allows semantic type drift to escape the ratchet.

  1. LOCKED DESIGN DECISIONS.

Compliant. The PR does not appear to alter a locked thesis/design decision directly; where it introduces a staged mirror, it names the current v3 service-DSL parse/load limitation and scopes the bridge to the Anthropic Messages signature reach (src/v3/std/anthropic_schema.dag:6-26).

  1. TRACKED vs UNTRACKED DEBT.

Compliant. The staged mirror has documentation, bounds, and a named dissolution trigger: it is type-authority only for this slice (src/v3/std/anthropic_schema.dag:13-15), bounded to types reachable from operation Messages input/output (src/v3/std/anthropic_schema.dag:17-26), and retires when v3 can ingest dsl/extdeps/llm/*.dag structurally (src/v3/std/anthropic_schema.dag:33-36). The hand-authored test is also registered in the SG0 census (src/v3/compiler/tests/integration/sg0_census_test.rs:232).

3. Verdict

REQUEST_CHANGES. The modeling direction is good and the debt is well bounded, but the lockstep ratchet does not yet protect the actual type carriers of the new substrate mirror. Add comparison of v2 field type expressions against v3 resolved field type shapes, including nested List<T> and T?, or explicitly narrow the mirror’s contract so it is not claiming type lockstep.

…t payloads)

OpenAI-Pro REQUEST_CHANGES on PR #1261 (sha 1e08a24): label + optionality
weren't enough to catch field type drift — content: List<X> could become
content: String while tests stayed green.

Adds:
- v3_canonical_ty(dag, ty): walks declarations to produce a canonical
  type-expression string. Named decls (String, Bool, AnthropicStopReason,
  AnthropicMessages200TextBlock, …) canonicalize as their surface name
  even though their underlying connective unfolds to Instantiation
  (e.g. String = FreeMonoid<Int>). Anonymous Instantiation sites
  (List<X>, Map<K, V>) and Cardinality(AtMostOne, T) get unfolded.
- normalize_ty_text(raw): strips trailing '?' and compresses internal
  whitespace so v2 source text matches v3 canonical form.
- v2_record_fields and parse_v2_brace_body_fields now return
  (label, normalized_ty_text, is_optional); v3_variant_payload_fields
  returns (label, canonical_ty, is_optional).
- assert_record_lockstep and assert_disj_lockstep added type-expression
  equality assertions in addition to label-set equality and optionality.
  Optionality is checked separately, so the type comparison strips
  the trailing '?' on both sides and compares inner-element forms only.

Coverage: every mirrored field across AnthropicChatMessage,
AnthropicUserContentBlock (incl. UserToolResultBlock.content/tool_use_id),
AnthropicAssistantContentBlock (incl. AssistantToolUseBlock.input: Json),
AnthropicMessages200TextBlock, AnthropicMessages200Usage (input_tokens: Int),
and AnthropicMessages200Body (content: List<...>, stop_sequence: String?)
now fails closed if v2 carrier type changes.
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: ee78939a · Trigger: schedule
  • Comparison: origin/main @ 86961089 ... review/pr-1261-ee78939a @ ee78939a
  • Thinking: 137s wall

Findings

Verdict: REQUEST_CHANGES. The schema mirror itself is documented with a bounded dissolution trigger, but the committed lockstep test fails in a fresh checkout, so the PR cannot land as-is.

@briansrls

Copy link
Copy Markdown
Contributor Author

Already fixed on current head. The reviewer was running against ee78939a9 (an intermediate commit during the type-expression-equality landing where v3 canonicalization was unfolding String to FreeMonoid<Int> and Int to Int64); commit b41143fe4 (current HEAD) corrects v3_canonical_ty to prefer the declaration's surface name when present:

fn v3_canonical_ty(dag: &Dag, ty: DeclarationId) -> String {
    let decl = dag.declaration(ty);
    if let Some(name) = decl.name.as_deref() {
        return name.to_string();
    }
    // anonymous Instantiation / Cardinality fallback below…
}

A named declaration (String, Bool, AnthropicStopReason, AnthropicMessages200TextBlock, …) canonicalizes as its surface name even though its underlying connective unfolds to Instantiation (e.g. String = FreeMonoid<Int>); only anonymous use-site instantiations (List<X>, Map<K, V>, T? cardinality carriers) get unfolded. v2 addresses these by name, v3 mirror does too.

Verified locally on b41143fe4:

running 8 tests
test anthropic_schema_lockstep_test::anthropic_assistant_content_block_lockstep ... ok
test anthropic_schema_lockstep_test::anthropic_chat_message_lockstep ... ok
test anthropic_schema_lockstep_test::anthropic_messages_200_body_lockstep ... ok
test anthropic_schema_lockstep_test::anthropic_messages_200_text_block_lockstep ... ok
test anthropic_schema_lockstep_test::anthropic_messages_200_usage_lockstep ... ok
test anthropic_schema_lockstep_test::anthropic_schema_authors_no_data_rows ... ok
test anthropic_schema_lockstep_test::anthropic_stop_reason_lockstep ... ok
test anthropic_schema_lockstep_test::anthropic_user_content_block_lockstep ... ok
test result: ok. 8 passed; 0 failed

Clippy clean. CI is rerunning on b41143fe4.

— sent from sharp-raven-604

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-thinking
  • Commit: 365e57f6 · Trigger: manual
  • Comparison: main @ bb40a384 ... session/sharp-raven-604 @ 365e57f6
  • Conversation: View conversation

1. Story of the diff

This PR stages a v3 provider-domain type mirror for the Anthropic Messages signature because v3 cannot yet ingest the existing v2 dsl/extdeps/llm/anthropic.dag service block structurally. The new src/v3/std/anthropic_schema.dag is deliberately scoped to the types reachable from the operation Messages input/output signature, explicitly omits out-of-reach provider types, and declares itself “type authority only” until a later operation-row/callable precursor consumes it (src/v3/std/anthropic_schema.dag:6-25, :27-35).

The safety mechanism is the new anthropic_schema_lockstep_test.rs, which treats the v2 file as the source authority and compares the v3 bootstrap’s mirrored declarations for field sets, variant sets, optionality, and canonical type expressions (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:5-23, :413-531). The PR wires that ratchet into the integration suite, adds the new .dag file to the parse corpus manifest, updates the SG-0 census allowlist for the new hand-authored test file, and regenerates bootstrap artifacts.

2. Invariant categories

  1. LAYER MODEL — Compliant. This touches v3 std/substrate-adjacent modeling, but not core Dag/Behavior structure; the mirror names its v2 authority, limits scope to the Messages signature, and makes the temporary duplication explicit with a dissolution trigger: “when v3 grows a service-DSL parse/load surface… this twin retires” (src/v3/std/anthropic_schema.dag:6-35).
  2. INVARIANTS.md + modeling-discipline.md — Compliant. Boundary discipline / single authority is handled by the lockstep ratchet rather than an unguarded parallel representation: the test asserts set equality between v2 and v3, optionality parity, and type-expression parity (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:10-18, :413-531). Coproduct discipline is also addressed: each new provider-domain coproduct is annotated as terminal with source rationale, e.g. AnthropicChatMessage and AnthropicStopReason (src/v3/std/anthropic_schema.dag:37-45, :66-78).
  3. CODING.md — Compliant. The Rust test helper code is data + free functions over explicit inputs (&Dag, type names, declaration IDs), not hidden state or object-style mutation; examples include conj_field_labels(dag, name), v3_field_is_optional(dag, owner, field), and assert_record_lockstep(type_name) (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:33-78, :413-465).
  4. TESTING.md — Compliant. The diff adds a focused integration ratchet for exactly the boundary this PR creates: v2 authority text versus v3 bootstrap mirror. It is behavior/contract-driven rather than snapshotting generated output: field/variant set equality, optionality, payload-shape parity, and “no data rows” are each asserted directly (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:413-531, :582-601). The integration registration is present (src/v3/compiler/tests/integration.rs:37-42).
  5. LOCKED DESIGN DECISIONS — N/A. I do not see this PR altering a locked design surface; it references existing staged-fixture/service-DSL gaps as justification, but does not change the locked substrate reflection or external realization contracts.
  6. TRACKED vs UNTRACKED DEBT — Compliant. The mirror is a tracked bridge: documentation names the authority source, the bounds, and a checkable dissolution trigger (src/v3/std/anthropic_schema.dag:6-35). The new hand-authored Rust test is also accounted for in the SG-0 census allowlist (src/v3/compiler/tests/integration/sg0_census_test.rs:229-234).

3. Verdict

APPROVE. The PR introduces a temporary v3 mirror, but it is bounded, source-anchored, ratcheted against the v2 authority, and carries an explicit dissolution trigger. I did not find a changed line that violates the substrate/modeling, coding, testing, locked-design, or tracked-debt rules.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: 365e57f6 · Trigger: schedule
  • Comparison: origin/main @ bb40a384 ... review/pr-1261-365e57f6 @ 365e57f6
  • Thinking: 57s wall

Findings: None. I read the rubric files from the pinned *-context/ paths and reviewed git diff origin/main...HEAD with focus on the hand-authored surface (src/v3/std/anthropic_schema.dag, anthropic_schema_lockstep_test.rs, integration.rs, manifest line, sg0_census_test.rs entry). The large bootstrap_generated*.rs churn is mechanical regen from the new std module.

Against that slice:

  • INVARIANTS / modeling discipline: The mirror is explicitly type-only, scoped to the Messages signature reach, names v2 authority (dsl/extdeps/llm/anthropic.dag) and a named dissolution trigger (retire when v3 can load v2 service DSL with full fidelity). Sum/record shapes carry 🟢 TERMINAL rationale tied to the v2 source — satisfies the “ledger / terminal vs scaffold” expectation for new coproducts on the modeled side. No second competing authority without the lockstep ratchet.

  • CODING.md: Data + free functions in the test module; panics/unwrap live in test code where the doc allows it.

  • TESTING.md: Integration-style lockstep is appropriate for the interface (“v3 mirror stays set-equal to v2 for these types”), analogous to other corpus/authority tests; corpus manifest update matches the parse-corpus pattern.

The span.file == "src/v3/std/anthropic_schema.dag" filter in anthropic_schema_authors_no_data_rows matches an existing pattern (e.g. services_carrier_shape_test.rs for services.dag) and is not a new class of concern introduced only here.

Verdict: APPROVE — The diff is focused, fail-closed at the ratchet (set equality, optionality, no data rows), and aligns with documented bridge + sunset discipline. I do not see a concrete rubric violation tied to a changed line.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review metadata

  • Provider / model: codex / unknown
  • Commit: 365e57f6 · Trigger: schedule
  • Thinking: 266s wall

Non-blocking — Strengths

  • src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs The lockstep test checks field sets, variant sets, payload fields, optionality, and canonical type expressions, so the mirror has a useful fail-closed drift ratchet once the cited v2 authority exists.

Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)

  • src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs The type-only ratchet at line 558 only rejects value_body rows, so a future fn in anthropic_schema.dag would lower as an Arrow with value_body None and bypass the guard; extend it in the T-Substrate-AnthropicSchemaMirror follow-up lane if deferred.

⚠️ Prior blocking comments 3167442700 and 3167442703 remain unresolved; I found no new blocking concerns beyond them.

…ard)

Codex non-blocking improvement on PR #1261: prior anthropic_schema_authors_no_data_rows
test rejected only declarations with value_body: Some(...), so a future
fn anthropic_messages would lower as TypeConnective::Arrow with
value_body: None and bypass the guard. Renamed to ..._or_fns and
extended the filter to also reject TypeConnective::Arrow declarations
authored in src/v3/std/anthropic_schema.dag.
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-thinking
  • Commit: 6613e080 · Trigger: manual
  • Comparison: main @ bb40a384 ... session/sharp-raven-604 @ 6613e080
  • Conversation: View conversation

1. Story of the diff

This PR stages a v3 provider-domain mirror for the Anthropic Messages signature rather than trying to ingest the v2 service { operation ... } source directly. The new src/v3/std/anthropic_schema.dag explicitly names dsl/extdeps/llm/anthropic.dag as the authority, limits scope to the input/output types reachable from operation Messages, and defers callable/operation rows to a later slice while this PR remains type-authority only (src/v3/std/anthropic_schema.dag:6-26). The actual mirror adds closed provider-domain coproducts for chat/content/stop reasons plus response records for the 200 body (src/v3/std/anthropic_schema.dag:43-116).

The key guardrail is the new integration ratchet: it extracts v2 type blocks from the v2 authority text and compares them against the full v3 bootstrap declarations for field/variant set equality, optionality, and canonical type expressions (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:5-23, :413-530). It also asserts the new .dag file stays type-only by rejecting any lowered data row or fn declaration from that file (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:582-610). The rest is wiring: the test module is registered, the parse corpus manifest includes the new .dag, the SG0 census accounts for the new hand-authored test, and generated bootstraps are refreshed.

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Compliant — this does touch Dag-visible substrate/domain types under src/v3/std, but it keeps them as declared types only: the file states “type authority only” and defers fn anthropic_messages plus Operation data rows to a later consuming precursor (src/v3/std/anthropic_schema.dag:13-15). The model also names its upstream authority and bounds scope to the signature-reachable types (src/v3/std/anthropic_schema.dag:6-26).

  1. INVARIANTS.md + modeling-discipline.md.

Compliant — boundary discipline / single authority is handled as a tracked mirror rather than silent parallel authority: the file names the v2 authority, adds a lockstep ratchet, and names the dissolution trigger when v3 can ingest dsl/extdeps/llm/*.dag structurally (src/v3/std/anthropic_schema.dag:28-36). Illegal states are also pushed into type shape: AnthropicChatMessage separates user vs assistant content blocks structurally rather than permitting a shared free-form content payload (src/v3/std/anthropic_schema.dag:38-45).

  1. CODING.md.

Compliant — the new Rust test is data + pure helper functions over explicit inputs: helpers take &Dag / type names and return structured projections (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:33-78, :93-126), with no hidden global state beyond a compile-time include_str! of the named authority (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:29). Panics are confined to test assertions / ratchet failures, not production library paths.

  1. TESTING.md.

Compliant — the PR adds behavior-driven lockstep tests at the right level for a bootstrap-visible mirrored schema: set equality, optionality, type-expression equality, and type-only enforcement are explicit test claims (src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:10-17, :418-463, :472-530, :582-610). The integration layer is justified because the contract being pinned is “v3 full bootstrap reflects this .dag mirror in lockstep with the v2 authority,” not a narrow helper function.

  1. LOCKED DESIGN DECISIONS.

N/A — the diff references the known service-DSL parse/load gap and future service ingestion path, but does not edit or contradict a locked design document. The divergence is explicitly scoped as a temporary typed twin until service DSL ingestion exists (src/v3/std/anthropic_schema.dag:6-15, :33-36).

  1. TRACKED vs UNTRACKED DEBT.

Compliant — the mirror is a temporary parallel representation, but it has all three bridge properties: documentation of why it exists (src/v3/std/anthropic_schema.dag:6-15), bounded scope (src/v3/std/anthropic_schema.dag:17-26), and a named dissolution trigger (src/v3/std/anthropic_schema.dag:33-36). The new hand-authored Rust ratchet is also accounted for in the SG0 census (src/v3/compiler/tests/integration/sg0_census_test.rs:229-233).

3. Verdict

APPROVE

The PR introduces a substrate-visible mirror, but it is narrowly scoped, structurally typed, ratcheted against its named authority, and explicitly marked as dissolving once v3 can ingest the upstream service DSL directly. I did not find a diff-local invariant violation that would justify blocking or comments.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: 6613e080 · Trigger: schedule
  • Comparison: origin/main @ bb40a384 ... review/pr-1261-6613e080 @ 6613e080
  • Thinking: 125s wall

Verdict: APPROVE

The diff is narrowly scoped: a documented v3 provider-domain mirror, generated bootstrap updates, and a lockstep ratchet against the v2 authority. I found no concrete violations of the pinned invariants or testing/coding guidance. The temporary duplicate authority is documented, bounded, tested bidirectionally, and has a named dissolution trigger.

Verification run: cargo test -p v3-compiler anthropic_schema_lockstep --test integration passed all 8 targeted tests.

@briansrls
briansrls merged commit ad016c5 into main Apr 30, 2026
4 checks passed
@briansrls
briansrls deleted the session/sharp-raven-604 branch April 30, 2026 12:38
briansrls added a commit that referenced this pull request Apr 30, 2026
Service-operation callable declaration precursor for the Anthropic
Messages REST operation, the substrate slice Grounding PR-β #1252 is
waiting on per parent #1130 dispatch.

Adds:
- src/v3/std/anthropic_messages.dag: top-level fn anthropic_messages
  with honest signature consuming v3.std.anthropic_schema mirror types
  (#1261). Returns AnthropicMessages200Body. host body lowers as
  ArrowBody::Unparsed (no producerless realization carrier minted).
- src/v3/compiler/tests/integration/anthropic_messages_callable_test.rs:
  5 ratchets — Arrow shape, parameter type list matches v2 source via
  v3 mirror, return type is AnthropicMessages200Body, callable is
  acceptable as Operation.callable.decl target, no Operation/data rows
  leak (those are PR-β scope).

Two intentional simplifications vs v2 (documented in file header):
- max_tokens: Int (v2 'Int = 4096'); v3 has no parameter defaults so
  the default is a caller-side fold, not a v3 contract change.
- Return is the 200 body only; AnthropicErrorShape is PR-β response/
  wire lockstep concern.

Out of scope: anthropic_operations: List<Operation> data row, sibling
binding/realization data rows. Grounding owns those.
briansrls added a commit that referenced this pull request Apr 30, 2026
…es declaration (#1266)

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* regen bootstrap after std.effects import path fix

* WIP: sharp-raven-604

* chore: apply cargo fmt

* WIP: sharp-raven-604

* regen bootstrap + refresh parse manifest after merge

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* PR-α: wrap Operation.callable in CallableRef (typed wrapper, mirrors MethodRef)

* chore: apply cargo fmt

* doc: align test comments with CallableRef wrapper (cosmetic)

* regen bootstrap after merge main

* T-Substrate-AnthropicSchemaMirror: v3 typed mirror for Anthropic Messages signature

- src/v3/std/anthropic_schema.dag: type-authority-only mirror of provider-domain
  types reachable from operation Messages signature in
  dsl/extdeps/llm/anthropic.dag (AnthropicChatMessage + content block variants,
  AnthropicStopReason, AnthropicMessages200{TextBlock,Usage,Body}).
- AnthropicErrorShape deferred (4xx/5xx response slot only; not on the typed
  return reach for fn anthropic_messages -> AnthropicMessages200Body).
- src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:
  8 ratchets pinning v3 mirror against v2 source (variant labels, field labels,
  type-name presence in v2). Discipline mirrors method_registry_test.rs.
- Type authority only — no fn anthropic_messages, no Operation rows. Those
  are the next substrate precursor that consumes these types.

* WIP: sharp-raven-604

* chore: apply cargo fmt

* anthropic_schema lockstep: couple expected labels to v2 source + optionality

Manager review on PR #1261: the prior lockstep tests asserted v3 labels
against hard-coded constants and only checked v2 type-name presence. They
would NOT catch v2 source drift on field/variant labels themselves.

This commit:
- Extracts the v2 type-block text via v2_type_block(name).
- assert_lockstep_record / assert_lockstep_disj now verify each expected
  label appears literally in the v2 block, fail-closed on either-side drift.
- New anthropic_optional_fields_remain_optional_in_v2_source asserts the
  '?' suffix on is_error: Bool? and stop_sequence: String? in the v2
  source, with comment explaining structural inspection of v3 optionality
  is deferred to the operation-row precursor (per manager guidance).

* anthropic_schema lockstep: bidirectional set equality + structural optionality

OpenAI-Pro REQUEST_CHANGES on PR #1261: prior ratchet only checked v3 set
== expected and expected ⊆ v2. v2 additions silently passed; v3 optionality
was text-only on the v2 side, not structurally checked on v3.

Strengthened:
- v2_record_fields(name) parses the v2 type block and extracts (label,
  is_optional) tuples directly from the source. v2_disj_variants(name)
  extracts variant labels (including from inline 'A | B | C' and
  multi-line '= Foo {} | Bar {}' shapes).
- assert_record_lockstep / assert_disj_lockstep assert SET EQUALITY
  between v2-extracted set and v3 bootstrap set (BTreeSet diff in the
  failure message names v3-only and v2-only labels).
- Optionality is structural on v3: v3_field_is_optional walks the field
  declaration's TypeConnective and matches Cardinality(AtMostOne, _).
  Each v2 'T?' field must lower optional; each v2 'T' field must NOT.
- New test anthropic_user_content_block_user_tool_result_block_optionality
  reaches the variant payload Conj for UserToolResultBlock and asserts
  is_error: Bool? lowers as Cardinality(AtMostOne, Bool) on the
  inner declaration (variant payloads aren't reached by the
  record-level ratchet).

* chore: apply cargo fmt

* fix clippy: use char array in split (manual char comparison lint)

* WIP: sharp-raven-604

* anthropic_schema lockstep: per-variant payload field+optionality coverage

OpenAI-Pro REQUEST_CHANGES on PR #1261: assert_disj_lockstep compared
only variant labels, leaving variant payload field labels and
optionality unguarded — UserToolResultBlock.content / tool_use_id and
AssistantToolUseBlock.id / name / input could drift between v2 and v3
while the test passed.

This commit:
- v2_disj_variants now returns (label, Option<Vec<(field_label,
  is_optional)>>), parsing variant payload bodies via the same logic
  v2_record_fields uses (extracted as parse_v2_brace_body_fields).
- v3_variant_payload_fields walks the v3 variant target's Conj
  declaration and projects (label, Cardinality(AtMostOne, _)?) tuples.
- assert_disj_lockstep extends to per-variant payload set equality and
  optionality: bare-on-bare passes; record-on-record requires set
  equality + optionality match; mismatched (one-side bare,
  other-side payload) fails closed.
- Drops the redundant special-case is_error optionality test — now
  subsumed by structural per-variant payload coverage on
  AnthropicUserContentBlock.

* chore: apply cargo fmt

* WIP: sharp-raven-604

* chore: apply cargo fmt

* WIP: sharp-raven-604

* anthropic_schema lockstep: type-expression equality (records + variant payloads)

OpenAI-Pro REQUEST_CHANGES on PR #1261 (sha 1e08a24): label + optionality
weren't enough to catch field type drift — content: List<X> could become
content: String while tests stayed green.

Adds:
- v3_canonical_ty(dag, ty): walks declarations to produce a canonical
  type-expression string. Named decls (String, Bool, AnthropicStopReason,
  AnthropicMessages200TextBlock, …) canonicalize as their surface name
  even though their underlying connective unfolds to Instantiation
  (e.g. String = FreeMonoid<Int>). Anonymous Instantiation sites
  (List<X>, Map<K, V>) and Cardinality(AtMostOne, T) get unfolded.
- normalize_ty_text(raw): strips trailing '?' and compresses internal
  whitespace so v2 source text matches v3 canonical form.
- v2_record_fields and parse_v2_brace_body_fields now return
  (label, normalized_ty_text, is_optional); v3_variant_payload_fields
  returns (label, canonical_ty, is_optional).
- assert_record_lockstep and assert_disj_lockstep added type-expression
  equality assertions in addition to label-set equality and optionality.
  Optionality is checked separately, so the type comparison strips
  the trailing '?' on both sides and compares inner-element forms only.

Coverage: every mirrored field across AnthropicChatMessage,
AnthropicUserContentBlock (incl. UserToolResultBlock.content/tool_use_id),
AnthropicAssistantContentBlock (incl. AssistantToolUseBlock.input: Json),
AnthropicMessages200TextBlock, AnthropicMessages200Usage (input_tokens: Int),
and AnthropicMessages200Body (content: List<...>, stop_sequence: String?)
now fails closed if v2 carrier type changes.

* anthropic_schema lockstep: also reject Arrow declarations (fn leak guard)

Codex non-blocking improvement on PR #1261: prior anthropic_schema_authors_no_data_rows
test rejected only declarations with value_body: Some(...), so a future
fn anthropic_messages would lower as TypeConnective::Arrow with
value_body: None and bypass the guard. Renamed to ..._or_fns and
extended the filter to also reject TypeConnective::Arrow declarations
authored in src/v3/std/anthropic_schema.dag.

* chore: apply cargo fmt

* T-Substrate-AnthropicMessagesCallable: fn anthropic_messages declaration

Service-operation callable declaration precursor for the Anthropic
Messages REST operation, the substrate slice Grounding PR-β #1252 is
waiting on per parent #1130 dispatch.

Adds:
- src/v3/std/anthropic_messages.dag: top-level fn anthropic_messages
  with honest signature consuming v3.std.anthropic_schema mirror types
  (#1261). Returns AnthropicMessages200Body. host body lowers as
  ArrowBody::Unparsed (no producerless realization carrier minted).
- src/v3/compiler/tests/integration/anthropic_messages_callable_test.rs:
  5 ratchets — Arrow shape, parameter type list matches v2 source via
  v3 mirror, return type is AnthropicMessages200Body, callable is
  acceptable as Operation.callable.decl target, no Operation/data rows
  leak (those are PR-β scope).

Two intentional simplifications vs v2 (documented in file header):
- max_tokens: Int (v2 'Int = 4096'); v3 has no parameter defaults so
  the default is a caller-side fold, not a v3 contract change.
- Return is the 200 body only; AnthropicErrorShape is PR-β response/
  wire lockstep concern.

Out of scope: anthropic_operations: List<Operation> data row, sibling
binding/realization data rows. Grounding owns those.

* chore: apply cargo fmt

* chore: restore comment/test adjacency in SG-0 census (cosmetic)

Reviewer (claude opus 4.7) non-blocking exploratory observation on PR
#1266: the alphabetical insertion of anthropic_messages_callable_test.rs
and anthropic_schema_lockstep_test.rs split the PB Tier-2 #1014 comment
block from the test it describes. Moving the comment two lines down
restores adjacency. No behavior change.

* anthropic_messages: pin Unparsed body + correct file header prose

OpenAI-Pro REQUEST_CHANGES on PR #1266: the file header claimed 'host
anthropic_messages' lowers to ArrowBody::ExternalRealization, but the
generated substrate has ArrowBody::Unparsed(span). Prose did not match
the substrate fact, and no test pinned the body class so a silent
rewrite was invisible.

Fixes:
- File header rewritten to honestly describe the actual lowered state:
  body remains Unparsed because the pipeline-stage post-processing
  patch in bootstrap.rs:256 is pipeline-specific and does not fire
  for service-operation callables. The patch is intentionally not
  added (would require a producerless CompilerHostRealization-style
  data row, the parallel surface the #1130 dispatch rejects).
- New ratchet anthropic_messages_body_is_unparsed pins
  ArrowBody::Unparsed; a silent rewrite to ExternalRealization /
  UserDefined / Pending / NoBody fails closed.
- File header explicitly bounds the unparsed-body state to the same
  dissolution trigger as the schema mirror.

* regen bootstrap: re-sync byte spans after anthropic_messages.dag header rewrite
briansrls added a commit that referenced this pull request Apr 30, 2026
…ase 1 (rebase against #1246/#1261/#1266)

Resume per manager dispatch (#1133 inbox 4353064310). Substrate cascade
chain CLOSED: #1246 services + Operation/RestEndpointBinding,
#1261 Anthropic schema mirror, #1266 anthropic_messages callable.

Changes from queue-ahead draft:
- Operation row: drop name field (per #1246 — Operation has no
  parallel display-name); add callable: { decl: anthropic_messages }
  (per #1266 callable-decl precursor).
- Import std.effects (not v3.std.effects); add v3.std.anthropic_messages
  + v3.std.services { CallableRef } imports.
- Test: pivot from name-based uniqueness to callable.decl uniqueness;
  pilot-row lookup resolves through callable.decl == anthropic_messages.
- Variant-label resolution via parent Disj.variants helper (codex
  feedback re P2 single-authority).

Two structural-honesty deferrals documented as separate receipts in
the file header (per #1133 inbox 4353159066 — keep distinct):
  §1 INPUT-FIELDS POPULATION — parser-grammar gap; nested
     Map<String, X> literals don't parse in record-field positions.
     Even empty `{}` fails the Map type check (parses as record).
     Whole pilot row deferred; empty list lands as scaffolding.
     Substrate-tracked Phase 1.5+ slice (#1130 comment 4353153545).
  §2 v2 PARAMETER DEFAULTS — InputField.default carrier deferred;
     v2's max_tokens: Int = 4096 not represented. Substrate-tracked
     Phase 1.5+ slice (#1130 comment 4352585286).

messages_pilot_present test #[ignore]'d with re-arm instructions;
list-shape + uniqueness + ParamToken→inputs boundary checks land
(vacuous on empty list but wired for Phase 1.5 row population).

Pre-merge gate: regen clean; integration tests 3 passed + 1 ignored;
parse-corpus manifest refreshed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 30, 2026
…ase 1 pilot (#1252)

* feat(grounding): T-Ground services.dag PR-β — anthropic_operations Phase 1 pilot (DRAFT, gated on #1246)

Queue-ahead authoring per manager dispatch (#1133 inbox 4349607248) for
T-Ground services.dag PR-β. Mirrors the #1195 MethodTemplateContract
Phase 1 pattern: typed v3 fixture row + bootstrap_fixture_authority
extension + lockstep test.

This PR is DRAFT until Substrate's PR-α (#1246; sharp-raven-604) lands
the `Operation` / `RestEndpointBinding` / `InputField` type
declarations at src/v3/std/services.dag. Authored against the
proposed shape from #1246 diff inspection.

Files:
- src/v3/std/anthropic_operations.dag — single Messages operation row
  (POST /v1/messages with 6 input fields), lockstep with v2 source of
  truth at dsl/extdeps/llm/anthropic.dag:182-198. Home in src/v3/std/
  per #1187 audit lesson.
- src/v3/std/extdeps_bootstrap_fixtures.dag — extends
  BootstrapFixtureSet + bootstrap_fixture_authority with anthropic_operations.
- src/v3/compiler/src/bootstrap.rs — extends BOOTSTRAP_FIXTURE_PATH_KEYS.
- src/v3/compiler/tests/integration/anthropic_operations_test.rs +
  integration.rs mod entry — three load-bearing checks (lowers as List;
  names unique; Messages pilot present with expected POST /v1/messages
  endpoint + input-field key set per anthropic.dag:183-189).

Pre-merge gate (per #1195 regression-class lesson): workspace-exclude +
v2-compiler-tests + lane2-cost-test all pass before flipping ready.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: apply cargo fmt

* test(grounding): wire ParamToken.name → Operation.inputs boundary check (vacuous on Messages)

Per codex non-blocking finding on PR #1252: header claimed the
ParamToken.name resolution check is wired, but no actual assertion
existed. Adds anthropic_operations_param_tokens_resolve_to_input_keys
which walks every row's path tokens and asserts each ParamToken's
name is a present key in the operation's input map.

Vacuous on the Phase 1 Messages pilot (/v1/messages is pure literal
segments), but rows with path variables inherit the discipline by
construction. Header text tightened to make the structural-wired vs
runtime-active distinction explicit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(grounding): correct import path v3.std.effects → std.effects in anthropic_operations.dag

Per codex non-blocking finding on PR #1252: the live staged effects
authority at src/v3/std/effects.dag declares 'module std.effects', not
'v3.std.effects'. My queue-ahead import path was wrong; fixed before
M2 module scoping starts consuming import paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(grounding): add anthropic_operations_test.rs to SG-0 hand-authored census

Per codex BLOCKING on PR #1252: the new hand-authored Rust integration
file at src/v3/compiler/tests/integration/anthropic_operations_test.rs
must be tracked in the SG-0 hand-authored census ratchet. Entry added
in alphabetical position with comment naming the gating chain
(#1252 → Substrate schema-mirror → callable-decl precursor).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(grounding): assert UrlPathToken constructor is LiteralToken before text check

Per codex non-blocking finding on PR #1252: the Messages path-token
walker matched any FieldValue::Variant with .. ignoring constructor —
a ParamToken { name: "v1" } could satisfy the text assertion. Tightened
to assert the variant name is LiteralToken before extracting text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: wise-tern-480

* WIP: wise-tern-480

* chore: apply cargo fmt

* feat(grounding): T-Ground services.dag PR-β — anthropic_operations Phase 1 (rebase against #1246/#1261/#1266)

Resume per manager dispatch (#1133 inbox 4353064310). Substrate cascade
chain CLOSED: #1246 services + Operation/RestEndpointBinding,
#1261 Anthropic schema mirror, #1266 anthropic_messages callable.

Changes from queue-ahead draft:
- Operation row: drop name field (per #1246 — Operation has no
  parallel display-name); add callable: { decl: anthropic_messages }
  (per #1266 callable-decl precursor).
- Import std.effects (not v3.std.effects); add v3.std.anthropic_messages
  + v3.std.services { CallableRef } imports.
- Test: pivot from name-based uniqueness to callable.decl uniqueness;
  pilot-row lookup resolves through callable.decl == anthropic_messages.
- Variant-label resolution via parent Disj.variants helper (codex
  feedback re P2 single-authority).

Two structural-honesty deferrals documented as separate receipts in
the file header (per #1133 inbox 4353159066 — keep distinct):
  §1 INPUT-FIELDS POPULATION — parser-grammar gap; nested
     Map<String, X> literals don't parse in record-field positions.
     Even empty `{}` fails the Map type check (parses as record).
     Whole pilot row deferred; empty list lands as scaffolding.
     Substrate-tracked Phase 1.5+ slice (#1130 comment 4353153545).
  §2 v2 PARAMETER DEFAULTS — InputField.default carrier deferred;
     v2's max_tokens: Int = 4096 not represented. Substrate-tracked
     Phase 1.5+ slice (#1130 comment 4352585286).

messages_pilot_present test #[ignore]'d with re-arm instructions;
list-shape + uniqueness + ParamToken→inputs boundary checks land
(vacuous on empty list but wired for Phase 1.5 row population).

Pre-merge gate: regen clean; integration tests 3 passed + 1 ignored;
parse-corpus manifest refreshed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 1, 2026
…edicate + runner (#1314)

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* regen bootstrap after std.effects import path fix

* WIP: sharp-raven-604

* chore: apply cargo fmt

* WIP: sharp-raven-604

* regen bootstrap + refresh parse manifest after merge

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* PR-α: wrap Operation.callable in CallableRef (typed wrapper, mirrors MethodRef)

* chore: apply cargo fmt

* doc: align test comments with CallableRef wrapper (cosmetic)

* regen bootstrap after merge main

* T-Substrate-AnthropicSchemaMirror: v3 typed mirror for Anthropic Messages signature

- src/v3/std/anthropic_schema.dag: type-authority-only mirror of provider-domain
  types reachable from operation Messages signature in
  dsl/extdeps/llm/anthropic.dag (AnthropicChatMessage + content block variants,
  AnthropicStopReason, AnthropicMessages200{TextBlock,Usage,Body}).
- AnthropicErrorShape deferred (4xx/5xx response slot only; not on the typed
  return reach for fn anthropic_messages -> AnthropicMessages200Body).
- src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:
  8 ratchets pinning v3 mirror against v2 source (variant labels, field labels,
  type-name presence in v2). Discipline mirrors method_registry_test.rs.
- Type authority only — no fn anthropic_messages, no Operation rows. Those
  are the next substrate precursor that consumes these types.

* WIP: sharp-raven-604

* chore: apply cargo fmt

* anthropic_schema lockstep: couple expected labels to v2 source + optionality

Manager review on PR #1261: the prior lockstep tests asserted v3 labels
against hard-coded constants and only checked v2 type-name presence. They
would NOT catch v2 source drift on field/variant labels themselves.

This commit:
- Extracts the v2 type-block text via v2_type_block(name).
- assert_lockstep_record / assert_lockstep_disj now verify each expected
  label appears literally in the v2 block, fail-closed on either-side drift.
- New anthropic_optional_fields_remain_optional_in_v2_source asserts the
  '?' suffix on is_error: Bool? and stop_sequence: String? in the v2
  source, with comment explaining structural inspection of v3 optionality
  is deferred to the operation-row precursor (per manager guidance).

* anthropic_schema lockstep: bidirectional set equality + structural optionality

OpenAI-Pro REQUEST_CHANGES on PR #1261: prior ratchet only checked v3 set
== expected and expected ⊆ v2. v2 additions silently passed; v3 optionality
was text-only on the v2 side, not structurally checked on v3.

Strengthened:
- v2_record_fields(name) parses the v2 type block and extracts (label,
  is_optional) tuples directly from the source. v2_disj_variants(name)
  extracts variant labels (including from inline 'A | B | C' and
  multi-line '= Foo {} | Bar {}' shapes).
- assert_record_lockstep / assert_disj_lockstep assert SET EQUALITY
  between v2-extracted set and v3 bootstrap set (BTreeSet diff in the
  failure message names v3-only and v2-only labels).
- Optionality is structural on v3: v3_field_is_optional walks the field
  declaration's TypeConnective and matches Cardinality(AtMostOne, _).
  Each v2 'T?' field must lower optional; each v2 'T' field must NOT.
- New test anthropic_user_content_block_user_tool_result_block_optionality
  reaches the variant payload Conj for UserToolResultBlock and asserts
  is_error: Bool? lowers as Cardinality(AtMostOne, Bool) on the
  inner declaration (variant payloads aren't reached by the
  record-level ratchet).

* chore: apply cargo fmt

* fix clippy: use char array in split (manual char comparison lint)

* WIP: sharp-raven-604

* anthropic_schema lockstep: per-variant payload field+optionality coverage

OpenAI-Pro REQUEST_CHANGES on PR #1261: assert_disj_lockstep compared
only variant labels, leaving variant payload field labels and
optionality unguarded — UserToolResultBlock.content / tool_use_id and
AssistantToolUseBlock.id / name / input could drift between v2 and v3
while the test passed.

This commit:
- v2_disj_variants now returns (label, Option<Vec<(field_label,
  is_optional)>>), parsing variant payload bodies via the same logic
  v2_record_fields uses (extracted as parse_v2_brace_body_fields).
- v3_variant_payload_fields walks the v3 variant target's Conj
  declaration and projects (label, Cardinality(AtMostOne, _)?) tuples.
- assert_disj_lockstep extends to per-variant payload set equality and
  optionality: bare-on-bare passes; record-on-record requires set
  equality + optionality match; mismatched (one-side bare,
  other-side payload) fails closed.
- Drops the redundant special-case is_error optionality test — now
  subsumed by structural per-variant payload coverage on
  AnthropicUserContentBlock.

* chore: apply cargo fmt

* WIP: sharp-raven-604

* chore: apply cargo fmt

* WIP: sharp-raven-604

* anthropic_schema lockstep: type-expression equality (records + variant payloads)

OpenAI-Pro REQUEST_CHANGES on PR #1261 (sha 1e08a24): label + optionality
weren't enough to catch field type drift — content: List<X> could become
content: String while tests stayed green.

Adds:
- v3_canonical_ty(dag, ty): walks declarations to produce a canonical
  type-expression string. Named decls (String, Bool, AnthropicStopReason,
  AnthropicMessages200TextBlock, …) canonicalize as their surface name
  even though their underlying connective unfolds to Instantiation
  (e.g. String = FreeMonoid<Int>). Anonymous Instantiation sites
  (List<X>, Map<K, V>) and Cardinality(AtMostOne, T) get unfolded.
- normalize_ty_text(raw): strips trailing '?' and compresses internal
  whitespace so v2 source text matches v3 canonical form.
- v2_record_fields and parse_v2_brace_body_fields now return
  (label, normalized_ty_text, is_optional); v3_variant_payload_fields
  returns (label, canonical_ty, is_optional).
- assert_record_lockstep and assert_disj_lockstep added type-expression
  equality assertions in addition to label-set equality and optionality.
  Optionality is checked separately, so the type comparison strips
  the trailing '?' on both sides and compares inner-element forms only.

Coverage: every mirrored field across AnthropicChatMessage,
AnthropicUserContentBlock (incl. UserToolResultBlock.content/tool_use_id),
AnthropicAssistantContentBlock (incl. AssistantToolUseBlock.input: Json),
AnthropicMessages200TextBlock, AnthropicMessages200Usage (input_tokens: Int),
and AnthropicMessages200Body (content: List<...>, stop_sequence: String?)
now fails closed if v2 carrier type changes.

* anthropic_schema lockstep: also reject Arrow declarations (fn leak guard)

Codex non-blocking improvement on PR #1261: prior anthropic_schema_authors_no_data_rows
test rejected only declarations with value_body: Some(...), so a future
fn anthropic_messages would lower as TypeConnective::Arrow with
value_body: None and bypass the guard. Renamed to ..._or_fns and
extended the filter to also reject TypeConnective::Arrow declarations
authored in src/v3/std/anthropic_schema.dag.

* chore: apply cargo fmt

* T-Substrate-AnthropicMessagesCallable: fn anthropic_messages declaration

Service-operation callable declaration precursor for the Anthropic
Messages REST operation, the substrate slice Grounding PR-β #1252 is
waiting on per parent #1130 dispatch.

Adds:
- src/v3/std/anthropic_messages.dag: top-level fn anthropic_messages
  with honest signature consuming v3.std.anthropic_schema mirror types
  (#1261). Returns AnthropicMessages200Body. host body lowers as
  ArrowBody::Unparsed (no producerless realization carrier minted).
- src/v3/compiler/tests/integration/anthropic_messages_callable_test.rs:
  5 ratchets — Arrow shape, parameter type list matches v2 source via
  v3 mirror, return type is AnthropicMessages200Body, callable is
  acceptable as Operation.callable.decl target, no Operation/data rows
  leak (those are PR-β scope).

Two intentional simplifications vs v2 (documented in file header):
- max_tokens: Int (v2 'Int = 4096'); v3 has no parameter defaults so
  the default is a caller-side fold, not a v3 contract change.
- Return is the 200 body only; AnthropicErrorShape is PR-β response/
  wire lockstep concern.

Out of scope: anthropic_operations: List<Operation> data row, sibling
binding/realization data rows. Grounding owns those.

* chore: apply cargo fmt

* chore: restore comment/test adjacency in SG-0 census (cosmetic)

Reviewer (claude opus 4.7) non-blocking exploratory observation on PR
#1266: the alphabetical insertion of anthropic_messages_callable_test.rs
and anthropic_schema_lockstep_test.rs split the PB Tier-2 #1014 comment
block from the test it describes. Moving the comment two lines down
restores adjacency. No behavior change.

* anthropic_messages: pin Unparsed body + correct file header prose

OpenAI-Pro REQUEST_CHANGES on PR #1266: the file header claimed 'host
anthropic_messages' lowers to ArrowBody::ExternalRealization, but the
generated substrate has ArrowBody::Unparsed(span). Prose did not match
the substrate fact, and no test pinned the body class so a silent
rewrite was invisible.

Fixes:
- File header rewritten to honestly describe the actual lowered state:
  body remains Unparsed because the pipeline-stage post-processing
  patch in bootstrap.rs:256 is pipeline-specific and does not fire
  for service-operation callables. The patch is intentionally not
  added (would require a producerless CompilerHostRealization-style
  data row, the parallel surface the #1130 dispatch rejects).
- New ratchet anthropic_messages_body_is_unparsed pins
  ArrowBody::Unparsed; a silent rewrite to ExternalRealization /
  UserDefined / Pending / NoBody fails closed.
- File header explicitly bounds the unparsed-body state to the same
  dissolution trigger as the schema mirror.

* regen bootstrap: re-sync byte spans after anthropic_messages.dag header rewrite

* T-Verification-BridgeLedger: substrate carrier for bridge-retirement ledger

Adds:
- src/v3/std/bridge_ledger.dag: substrate authority for the bridge-
  retirement ledger Verification's BridgeLedgerZero TestClaim folds.
  - BridgeStatus = Retired | Open (closed two-variant coproduct;
    structural partition, no stringly status).
  - BridgeLedgerRow { name, owner, status, authority } per dispatch
    contract.
  - data bridge_ledger: List<BridgeLedgerRow> = [...] populates the
    five canonical bridge rows from docs/r3-structure.md:79-83.
  - Per-row status rationale documented in file header: source-span-
    file-participation Open, mark-bootstrap-secret-nominal-opacity
    Retired, canonical-lens-name-dispatch Retired, include-str-side-
    channels Open, exact-string-patching-residual Open.
- src/v3/compiler/tests/integration/bridge_ledger_carrier_test.rs:
  6 ratchets — BridgeLedgerRow field set, BridgeStatus closed two-
  variant coproduct, bridge_ledger lowers as List<BridgeLedgerRow>,
  five canonical names in document order, name uniqueness, status
  field resolves structurally to a BridgeStatus constructor (not a
  string).
- bootstrap regen + parse manifest refresh + integration mod entry +
  SG-0 census entry.

Single substrate authority — no parallel Rust Vec, no test-side
ledger table. Verification's BridgeLedgerZero fold is out of scope
for this PR per dispatch.

* regen bootstrap + manifest after merging origin/main

* T-Verification-BridgeLedger: predicate variant + runner branch (Director scope extension)

Per parent #1130 dispatch (#4356094666) extending #1314: substrate
authority for BridgeLedgerZero gate, not just the carrier.

Adds:
- src/v3/std/verification.dag: TestPredicate variant
  BridgeLedgerZero { ledger: DeclarationRef }. Single payload field
  preserves typed-edge discipline; structural identity, not stringly
  ledger reference.
- src/v3/compiler/src/test_runner.rs: eval_bridge_ledger_zero branch.
  Resolves the ledger DeclarationRef, walks ValueBody::List rows,
  reads each row's status Variant, partitions by structural
  comparison against BridgeStatus::Retired's variant id (not by
  name). Returns Pass iff every row is Retired; Fail names the
  open rows in declaration order.
- src/v3/compiler/tests/integration/bridge_ledger_carrier_test.rs:
  Two new tests:
  - bridge_ledger_zero_predicate_carries_only_ledger_declaration_ref:
    pins the variant's payload set to {ledger} and asserts ledger's
    type is DeclarationRef from v3.spec.v3_l1.
  - bridge_ledger_zero_runner_fails_with_named_open_rows_at_head:
    compiles a TestClaim referencing the ledger via DeclarationRef
    and runs it through TestRunner. At HEAD with three Open rows
    (source_span_file_participation, include_str_side_channels,
    exact_string_patching_residual), expects Fail with all three
    named and the two Retired rows excluded. Re-arms as Pass once
    all five flip to Retired.
- bootstrap regen + parse manifest refresh.

8/8 tests pass; clippy clean. Verification's #1310 can now author the
.dag TestClaim consuming this predicate.

* chore: apply cargo fmt

* doc: bridge_ledger comment cites correct canonical-lens ratchet test (cosmetic)

Reviewer (cursor) NON-BLOCKING finding on PR #1314: per-row rationale for
bridge_canonical_lens_name_dispatch_retired cited
bridge_lower_helpers_patch_zero_residual_test (lower-helper exact-string
patch lane) instead of the canonical-lens-name-dispatch ratchet at
canonical_lens_bridge_ratchet_test.rs. Comment text only; bootstrap +
manifest re-synced for the byte-span shift.

* WIP: sharp-raven-604

* eval_bridge_ledger_zero: enforce canonical ledger identity (single-authority)

Codex REQUEST_CHANGES on PR #1314: the previous type-check accepted any
List<BridgeLedgerRow> declaration, so a sibling list could become a
parallel ledger authority and pass the gate independently of the
canonical bridge_ledger. INVARIANTS P2 / single-authority violation.

Adds:
- Canonical-identity check before the type-check guard: the resolved
  ledger DeclarationId must match dag.declaration_by_name('bridge_ledger').id.
  Sibling List<BridgeLedgerRow> declarations fail closed with a
  diagnostic naming the canonical authority. Type-check stays as
  defense-in-depth (catches a future carrier-shape drift).
- New test bridge_ledger_zero_runner_fails_closed_on_sibling_canonical_
  shape_ledger: compiles a sibling 'data sibling_ledger:
  List<BridgeLedgerRow> = []' and asserts BridgeLedgerZero fails
  closed because the declaration identity isn't the canonical one
  (even though the type IS compatible).
- Existing wrong-type test updated: identity check fires first for
  any non-canonical ledger, so the assertion now expects the
  canonical-identity diagnostic.

* chore: apply cargo fmt

* WIP: sharp-raven-604

* BridgeLedgerZero: tighten payload typing, per-row authority pointers, fail-closed name field

Codex BLOCKING(3) on PR #1314 sha b5f7dd5:

1. Authority document: external doc anchor was generic. Made
   bridge_ledger.dag the explicit substrate authority for rows; per-row
   'authority' field now points at the concrete ratchet (test, PR, or
   gating doc-anchor) that establishes that row's status, not a generic
   taxonomy heading. Status flips from Open to Retired are gated on the
   named ratchet reaching zero residual:
   - source_span_file_participation -> ROADMAP.md#lens-fold-file-path-semantics
   - mark_bootstrap_secret_nominal_opacity -> PR #937
   - canonical_lens_name_dispatch -> canonical_lens_bridge_ratchet_test.rs
   - include_str_side_channels -> PR #1171
   - exact_string_patching_residual -> bridge_lower_helpers_patch_zero_residual_test.rs

2. Predicate schema typing: TestPredicate::BridgeLedgerZero.ledger now
   typed as BridgeLedgerRef (typed wrapper { decl: DeclarationRef }),
   mirror of MethodRef / CallableRef. Adds bridge_ledger.dag::BridgeLedgerRef
   with the same #1175 substrate-gap dissolution trigger. Runner unwraps
   the record at the predicate boundary.

3. Runner row validation: missing or non-String name field now fails
   closed instead of using a placeholder, even before status partition.
   Defensive at the claim boundary, complementing the carrier ratchet
   that already guards bridge_ledger.dag's substrate-side shape.

10/10 tests pass on the new payload shape: predicate-shape ratchet
updated to require BridgeLedgerRef wrapper (not bare DeclarationRef);
runner tests use BridgeLedgerZero { ledger: { decl: <ref> } } literal
construction; sibling-canonical-shape and wrong-type negative tests
still fire fail-closed.

* verification ratchet: include BridgeLedgerZero variant after main rebase

m1_5_verification_test::bootstrap_loads_verification_authority_types
expected variant list still ended at SubstrateResearchDeferredClaim;
appended ('BridgeLedgerZero', vec!['ledger']) to match the live
bootstrap. Bootstrap+manifest re-synced from the post-merge regen.
10/10 bridge_ledger_carrier tests + 1/1 verification ratchet pass.

* doc: align eval_bridge_ledger_zero rustdoc with BridgeLedgerRef payload (cosmetic)

Reviewer (cursor) NON-BLOCKING on PR #1314: rustdoc on
eval_bridge_ledger_zero still described the predicate as
{ ledger: DeclarationRef } even though the substrate surface (and the
implementation) now requires the BridgeLedgerRef { decl: DeclarationRef }
wrapper. INVARIANTS 'documentation describes live state' alignment.
Comment-only; no behavior change; .rs file edit so no bootstrap regen
needed.

* bridge_ledger tests: derive row set + open/retired partition from live ledger (single-authority)

Codex BLOCKING on PR #1314: CANONICAL_BRIDGES + expected_open/retired
arrays copied the ledger row set and status partition into Rust,
creating exactly the test-side parallel table bridge_ledger.dag rules
out (single-authority / M7).

- Removed the CANONICAL_BRIDGES const and the
  bridge_ledger_carries_canonical_five_names_in_doc_order test (the
  test re-asserted ledger content from a hardcoded copy; row content
  authority lives only in bridge_ledger.dag).
- bridge_ledger_lowers_as_list_with_at_least_one_row replaces the
  earlier exact-five-rows assertion: pins the structural shape
  (List value_body, every entry a Record, non-empty) without
  duplicating the row count.
- bridge_ledger_zero_runner_fails_with_named_open_rows_at_head no
  longer hardcodes expected_open_rows / expected_retired_rows. It
  reads the live ledger from the bootstrap, partitions by structural
  comparison against BridgeStatus::Retired's variant id, and asserts:
  every Open row's name appears in the failure diagnostic and every
  Retired row's name does not. Re-arms automatically as upstream rows
  flip status — the test does not need an update each time.

9/9 tests pass; clippy clean. The only authority for ledger row
content is now src/v3/std/bridge_ledger.dag.

* bridge_ledger: repoint umbrella row authority at open-scope prose, not closed sub-slice ratchet

OpenAI-Pro REQUEST_CHANGES on PR #1314: the
bridge_exact_string_patching_residual_retired row's authority pointed
at bridge_lower_helpers_patch_zero_residual_test.rs, the receipt for
the RETIRED lower-helper sub-slice (#1014). The row stays Open because
*other* exact-string patching classes remain outside that receipt's
scope, so the closed-slice test was misleading as the row's authority.

Repointed authority at docs/r3-structure.md:83 — the prose row where
the umbrella's open-scope framing ('Other exact-string patching classes
... keep their own dissolution triggers') is defined. Each 'other class'
has its own trigger; the umbrella row retires when those triggers all
fire. Per-row inline comment in bridge_ledger.dag explains the
distinction.

* WIP: sharp-raven-604

* regen bootstrap + manifest after main rebase (clean conflicts)
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.

1 participant