Skip to content

V3 criticals: five proofs + WoA 1:1 parity (D-PARITY-PROBE-WOA-1) + PG-facet adapter#158

Merged
AdaWorldAPI merged 22 commits into
mainfrom
claude/v3-criticals-woa-parity
Jul 6, 2026
Merged

V3 criticals: five proofs + WoA 1:1 parity (D-PARITY-PROBE-WOA-1) + PG-facet adapter#158
AdaWorldAPI merged 22 commits into
mainfrom
claude/v3-criticals-woa-parity

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

What

The five documented "criticals" of the OGAR V3 transpiler substrate, each turned from an [H]-hypothesis into an executable proof, plus the WoA 1:1 reality-check. Rebased on #157 (recipe-codebook Phase 1). 22 commits, 42/42 test suites green.

Multi-agent build: Opus plan/review/IR-sign-off, Sonnet grind under fixed specs; every finding adversarially re-verified before merge.

The five criticals — now proven

Layer Proof
behavior ActionDef carries reads/writes/calls facts from ruff #38 (IR-surface signed off vs OGAR-AS-IR §3; reads=inferred, writes=authoritative). D-BEHAVIOR-ACTION-EDGES.
render Falsifier #2 GREEN, dual-target: identical ClassView×FieldMask projection → askama (Rust) and jinja (Python) yield the identical field set at mask=45. Loud-fail guard replaces the silent >64-field drop. D-FIELDMASK-LOUD-FAIL.
membrane lift_ogit_entity: OGIT-TTL → controller-DTO with expected wire-names (DocumentInfoRecord fixture; vocab/ogar.ttl is owl:Class meta-vocab, deliberately unrecognised). D-MEMBRANE-TTL-DTO.
execution lifted Action → NativeCommandExecutor punched through end-to-end; falsifier #3 gap (kanban/tombstone needs ractor runtime) documented. cognition: StepDomain exhaustive-match breaks LOUD at compile-time when the ERP arm lands. D-EXEC-ONE-ACTION.
fieldmask widening Shipped separately as lance-graph #651 (merged): WideFieldMask, backward-compatible, canonical form + repr-independent Eq/Hash (a P0 equality footgun found & fixed pre-merge).

The reality check — WoA substrate vs WoA, 1:1

D-PARITY-PROBE-WOA-1: WoA TimesheetActivity → SQLAlchemy harvest → OGAR lift → emit_python → structural diff vs original. classes 1/1, columns typed 3/3, nullability 3/3, associations 1/1, py_compile + instantiate green. classid 0x0103_0003 via the WOA_ALIASES convergence pin to BILLABLE_WORK_ENTRY (SPEC's "unaliased bootstrap" assumption refuted and pinned by test; bootstrap is literal 0). Honest drift listed: emit_python doesn't yet render options.required.

Full harvest parked under .claude/harvest/woa-rs/ (139 models, 1961 attributes, 107/107 associations resolved, 6 aliased): the sink-in substrate for woa-rs, with PARKED.md relocation steps (OSM #152 precedent). Released in WoA at .claude/harvest/woa-sinkin-substrate/ (branch claude/woa-repo-backup-update-qb1enp).

SPEC-0 — the three #156 correctness findings, fixed (red-before-green)

Mainline extract_app* now routes through extract_app_with_schema; FK-dedup honours explicit foreign_key:; attribute-dup guard prevents invalid codegen. D-156-CORRECTNESS-FIXES.

SPEC-7 — Python persistence groundwork (ruling b)

New ogar-adapter-postgres-ddl: facet table (classid + 12 axis-indexed SMALLINT), DDL generated from the ClassView. Role split baked into the docs: PG = transactional system-of-record, lance-graph = zero-copy read hot-path, moka PG-side only (never before lance — it would break zero-copy). check_parity drift-fuse skeleton (outbox/dual-write/CDC = named follow-ups). D-PY-PERSIST-PG-FACET.

Depends on / sequencing

Follow-ups (named in ledger, not silently dropped)

FieldMask consolidation (project_total_schema_fields), emit_python required-rendering, dual-write outbox + CDC, Part-A SQLAlchemy frontend already on the ruff PR, falsifier #3 ractor runtime, F17/F1 measurement gates.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Cg8DSUz1U4AvKqXiy9Xx2f

claude added 22 commits July 6, 2026 14:43
Add lift_ogit_entity: lowers an OGIT entity TTL plus its attribute TTLs
into the canonical Class (controller-DTO wire shape), matching
attributes by localized name. Pins wire names via
tests/membrane_probe.rs against the real OGIT NTO
DocumentInfoRecord fixture (documentNumber/Type/PartId/Version).

Corrects the mission's vocab/ogar.ttl pointer: that file is owl:Class
meta-vocab which the rdfs:Class walker (ttl::detect_kind) does not
parse; the OGIT NTO corpus is the real fixture family for this probe.

Makes ttl::local_name_from_curie pub(crate) so the new pipeline helper
can localize curie-form attribute references to wire names.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r skeleton (SPEC-7)

Realizes Ruling (b, refined): PostgreSQL = transactional System-of-Record
(writes/GoBD/ACID); lance-graph = read-optimized hot-path, never sole
booking store; moka cache PG-side only, never in front of lance-graph
(zero-copy guardrail encoded in module docs).

New sibling crate ogar-adapter-postgres-ddl (precedent:
ogar-adapter-clickhouse-ddl), emit-only (no DB driver, no network):

- emit_postgres_ddl(&[Class]) -> per-class CREATE TABLE, typed + nullable
  from the schema stratum (options.required == Some(true) -> NOT NULL).
- emit_facet_table_ddl(table_name) -> the V3 facet table: classid +
  12 axis-indexable payload columns (p0..p11 SMALLINT), one B-tree index
  per column. Verified against ruff_spo_address::Facet (16 B total =
  4 B classid + 6 tiers x 2 B is_a/part_of rank == 12 payload bytes),
  confirming the 12-column layout without guessing a 16-slot variant.
- parity::check_parity(sink_in, legacy) -> ParityReport, the drift-fuse
  skeleton for the legacy-parity revival mode (COUNT_FUSE pattern);
  documents (does not build) the transactional-outbox dual-write runtime.

Both TimesheetActivity-tied tests (woa_timesheet_activity_ddl_roundtrips_field_set,
woa_timesheet_activity_sink_in_matches_hand_legacy) use a Class fixture
hand-transcribed directly from WoA/models.py:1746 (read-only source) as a
documented stand-in: SPEC-5's real CompiledClass lift output lives on an
unmerged sibling branch (claude/v3c-woa-parity) not present here.

cargo test -p ogar-adapter-postgres-ddl: 10 passed.
cargo test --workspace: all green, nothing regressed.
cargo clippy -p ogar-adapter-postgres-ddl --all-targets --all-features -D warnings: clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ndExecutor)

Add tests/lifted_action_dispatch.rs: a ruff_spo_triplet::Model method is
lifted via ogar_from_ruff::lift_actions into an ActionDef, then dispatched
through the reference NativeCommandExecutor -- the executable half of
Falsifier #3 ("lifted action -> ActionHandler -> result"). The header
documents the remaining gap precisely: the kanban transition + Lance
tombstone half needs the lance-graph ractor runtime, not present in this
repo.

ogar-from-ruff is added as a dev-dependency (execution probe only, not a
runtime dependency of this crate).

Also includes a trivial cargo-fmt-only fixup to membrane_probe.rs
(SPEC-3 commit, no semantic change).

SPEC-4 part (ii) (cognition typ-test, ActionDef -> UnifiedStep) is left
OFFEN: the spec designates crates/ogar-class-view/tests/cognition_step_mapping.rs
as its home (that crate already deps lance-graph-contract), but this
grind's authorized file scope is limited to ogar-from-schema/**  and
ogar-action-handler/** only -- ogar-class-view is out of scope. Reported
in the mission handoff rather than worked around.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d-trip (SPEC-2)

Three deliverables from SPEC-2 (fieldmask + render dual-target), OGAR side
only (FieldMask widening in lance-graph-contract is a separate PR):

(i) Pin test documenting today's silent drop of fields beyond the 64-bit
    FieldMask ceiling: FieldMask::with(n) for n >= MAX_FIELDS is a no-op,
    and the FULL sentinel still bypasses per-bit gating (emits overflow
    fields too). Pinned against the `field_present` primitive directly,
    since (ii) below makes the same input via `render_class_with_methods`
    loud-fail instead of returning Ok with a silent drop (see deviation
    note in the final report).

(ii) Loud-fail guard: `render_class_with_methods` now returns
     `Result<String, RenderError>`. A class with more fields than a single
     u64 FieldMask can address, under a non-FULL mask, returns
     `RenderError::TooManyFieldsForMask` instead of silently dropping
     fields 64+. FULL and <=64-field classes are unaffected (Ok). Swept
     the one in-workspace call site (examples/render_osm.rs `.expect`,
     compiles unchanged since RenderError: Debug).

(iii) Falsifier #2, dual-target: one (fields, mask) fixture
      (tests/fixtures/mask_roundtrip.json) drives both the askama (Rust)
      and jinja2 (Python) engines; both yield the identical field-name set.
      New tests/mask_dual_target.rs (Rust) + tests/jinja/render_mask.py.j2
      + tests/jinja/test_mask_roundtrip.py (Python, run via
      `uv run --with jinja2`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three CONFIRMED PR #156 findings, each closed with a red-before-green
regression test:

(a) ogar-from-rails::extract_app / extract_app_with routed through the
    schema-blind ruff_ruby_spo::extract_app_with, so the physical
    db/migrate/tables/*.rb column stratum never reached the shipped API
    (project_rails_fields had nothing to project; the "18/18" parity only
    held on a direct lift_model call with a hand-built fields vector). Now
    routes through ruff_ruby_spo::extract_app_with_schema. Guarded by a
    compile-level pin (extract_app_uses_schema_aware_symbol, non-ignored)
    and a real-corpus #[ignore]d test documenting the wiring.

(b) is_fk_shadowed_by_association only matched the <name>_id naming
    convention, ignoring an association's explicit foreign_key: option, so
    `belongs_to :author, foreign_key: "user_id"` double-projected
    user_id (scalar) and author (association). Now checks the explicit
    foreign_key first, falling back to the naming convention.

(c) project_rails_fields pushed every physical column unconditionally,
    so a model with both `attribute :foo, :string` (AR-DSL) and a
    physical foo column duplicated Class.attributes. Now skips a
    physical column whose name already matches a lifted attribute,
    keeping the AR-DSL declaration as the single authoritative entry.

Drive-by: ogar-class-view/Cargo.toml's stale "68 promoted canonical
concepts" doc corrected to 79 (the enforced ogar-vocab COUNT_FUSE).

cargo test -p ogar-from-ruff / -p ogar-from-rails / -p ogar-class-view
all green. Fixes (b) and (c) verified red-before-fix by stashing each
hunk individually and re-running the paired regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Type-level test that ogar_vocab::ActionDef lowers onto lance-graph-contract's
UnifiedStep orchestration shape. Confirmed against the pinned source
(lance-graph 598f8727, orchestration.rs) that UnifiedStep/StepStatus are
plain public structs/enums (not #[non_exhaustive]), so the full mapping is
built directly via struct literal rather than downgraded to the documented-gap
variant. StepDomain's variant set matches RECON R5 exactly (Crew/Ladybug/N8n/
LanceGraph/Ndarray/Smb/Medcare/Kanban) with no ERP/controller arm yet; an
exhaustive match pins that seam so a silent variant addition fails to compile.

No new dependency: ogar-class-view already deps lance-graph-contract and
ogar-vocab.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…IT-2)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… 1/2)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…delGraph

Part B: new ogar-from-ruff::sqlalchemy module — project_sqlalchemy_fields
(Rails-style total-nullability wiring + FK-dedup + SPEC-0(c) attribute-dup
guard), lift_model_sqlalchemy/lift_model_graph_sqlalchemy (stamp
Language::Python via the SQLAlchemy projection, not the Odoo one), plus
mint::compile_graph_sqlalchemy<P: PortSpec>. Implemented as a new module
file + a single `mod sqlalchemy;` line in lib.rs (WS-G-D merge constraint:
lib.rs is being edited concurrently by another agent) rather than SPEC-5's
preferred shared project_total_schema_fields helper threaded through
lib.rs — documented as a named, reported trade-off in the module docs.

Part C: crates/ogar-from-ruff/tests/woa_parity_probe.rs — a synthetic
ModelGraph transcribed verbatim from the real, read-only WoA
TimesheetActivity (models.py:1746-1753) lifts through
compile_graph_sqlalchemy::<WoaPort> and emits via emit_python to a
structurally 1:1 @DataClass: 3/3 columns typed, 3/3 nullability, 1/1
association (FK timesheet_id deduped to the timesheet BelongsTo), 0/0
action names (schema-only v0). Prints the D-PARITY-PROBE-WP-1-style N/N
metric with an explicit drift list.

Named SPEC-5 deviation (verified against ogar-vocab/src/ports.rs and
RECON.md R8, not invented): WOA_ALIASES already pins "TimesheetActivity"
to BILLABLE_WORK_ENTRY as a deliberate planner/ERP convergence concept, so
compile_graph_sqlalchemy::<WoaPort> yields facet classid 0x0103_0003 (the
convergence pin firing correctly), not the bootstrap 0x0000_0003 SPEC-5
assumed. A second, independent inaccuracy in the same passage: even a
genuinely unmapped WoA model resolves to the literal bootstrap 0
(classid_for_node never composes the app prefix on a None lookup), not a
composed 0x0000_0003. Both are pinned by dedicated tests in mint.rs rather
than silently "fixed" to match the spec's expectation.

Part D: the emitted @DataClass py-compiles and instantiates
(tests/py/instantiate_check.py), proving the Python mirror of
CompiledClass is real, usable Python, not just syntactically valid text.

cargo test -p ogar-from-ruff: 59 + 3 passed. cargo test --workspace: all
green, zero regressions. cargo clippy -p ogar-from-ruff --all-targets
--all-features -- -D warnings: clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rface signed off gegen OGAR-AS-IR §3

Wire ruff's real behavior facts (ruff_spo_triplet::Function.reads/writes/
calls) onto ogar_vocab::ActionDef as first-class effect annotations, making
behavior part of the compile-time substrate (Operator §3) without fabricating
reactive @api.depends semantics from a plain method read (kausal stays None).

IR-surface sign-off (WS-V, Opus) against docs/OGAR-AS-IR.md §3 six tests:
- Test 2 (effect annotations first-class): PASSES HEAD-ON. reads/writes/calls
  are exactly the "what it reads / what it writes / what side effects" the
  test mandates; ActionDef previously violated it.
- Tests 1/3/4/5/6: NEUTRAL. No hidden state, no target-dialect creep, no
  back-end/optimizer semantics touched; the facts ride the Core IR node
  (ActionDef), not the classid/address (doctrine: behavior is a property of
  what the id resolves to, never the address).

Additive + non-breaking: ActionDef derives Default and is #[non_exhaustive];
its only construction path is ActionDef::new(..) + ..Default::default(), so
the three new Vec<String> fields default to empty at every site. Workspace
sweep confirms no exhaustive-match site breaks.

Honest scoping: name-level only (value/body/params not captured by today's
frontend); body_source/on_enter/params lowering remains SPEC-1(ii), a
documented ruff_spo_triplet::Function extension follow-up.

Tests: cargo test -p ogar-vocab (96) + -p ogar-from-ruff (58, incl. 3 new:
lift_actions_carries_read_write_call_effect_facts,
lift_actions_empty_facts_stay_empty_not_none,
lift_actions_identity_predicate_object_unchanged) + cargo test --workspace
(419 passed / 0 failed). clippy -D warnings clean on both patched crates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ippy-1.95-Doc-Lints in Beispielen

Die sqlalchemy.rs-Kopie von is_fk_shadowed_by_association bekommt die
SPEC-0(b)-Semantik (explizites foreign_key zuerst, dann <name>_id-Konvention) —
sonst waere die #156-Bug-Klasse im SQLAlchemy-Arm wieder eingefuehrt worden.
Lockstep-Kommentar + Konsolidierungs-Follow-up dokumentiert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…E-WOA-1, E8-adjacent entries

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-parity

Ledger-Konflikte append-only aufgelöst (beide Eintrags-Sets erhalten).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

# Conflicts:
#	.claude/board/EPIPHANIES.md
#	docs/DISCOVERY-MAP.md
…o → WoaPort (parked for woa-rs)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@AdaWorldAPI AdaWorldAPI merged commit 318b46f into main Jul 6, 2026
2 checks passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b2ff812. Configure here.

name.to_string()
} else {
format!("\"{}\"", name.replace('"', "\"\""))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reserved table name unquoted

High Severity

quote_pg_ident incorrectly identifies names like User as safe bare identifiers. This causes emit_postgres_ddl to generate unquoted table names. Since PostgreSQL folds unquoted names to lowercase and user is a reserved keyword, applying the generated DDL can fail or mis-bind tables, impacting schemas like WoA.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b2ff812. Configure here.

field: legacy_attr.name.clone(),
sink_in: sink_in_attr.options.required,
legacy: legacy_attr.options.required,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Parity nullability tri-state mismatch

Medium Severity

The check_parity function incorrectly flags nullability drift when options.required is None in one class and Some(false) in another. These values are semantically equivalent for nullable columns and produce identical DDL, leading to false positives in the parity report.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b2ff812. Configure here.

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.

2 participants