Skip to content

Consumer migration §5 steps 2–5: harvest config, un-vendor ruff, de-pin, ogar-emit consumer path#71

Merged
AdaWorldAPI merged 5 commits into
mainfrom
claude/odoo-rs-transcode-lf8ya5
Jul 5, 2026
Merged

Consumer migration §5 steps 2–5: harvest config, un-vendor ruff, de-pin, ogar-emit consumer path#71
AdaWorldAPI merged 5 commits into
mainfrom
claude/odoo-rs-transcode-lf8ya5

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Executes the open steps of .claude/handovers/2026-07-05-ogar-v3-consumer-migration-plan.md §5 (steps 2–5 now [DONE] in the plan itself):

  • Step 2 — .claude/harvest/ (4102eb0): the ORM→AR back-projection training wheel as data — 15 rules (7 direct / 6 guess / 2 weak), every one validation = "unmeasured", doctrines (config-is-data, measure-don't-claim) in the README + TOML meta. Direct DSL rules suppress their name-pattern guess fallbacks; the unique_index guess is flagged "make ruff smarter" (no backing harvest yet), not faked here.
  • Step 3 — un-vendor (a561b41, ea8fcf7): vendor/AdaWorldAPI-ruff deleted; ruff_openproject promoted to crates/ with crate-local fixtures; the vendor's ahead-deltas were upstreamed to ruff first (strict-superset audit), so nothing was lost. The extract_triples_produces_locked_shape test goes green for the first time since the vendor era — every fact mechanically grounded (schema-stratum column, IfMod-fix raise, compute-linkage emitted_by).
  • De-pin sweep (9222d9b): operator ruling — no rev pins; all AdaWorldAPI deps float on the convergence branch, single-source verified (cargo tree -i one git source for both ruff_spo_triplet and ogar_vocab; includes the op-surreal-ast ogar-vocab flip that the gate itself demanded).
  • Steps 4–5 — the ogar-emit consumer path (5092688): feature-gated module ogar_consumercompile_op::<P>emit_surreal_via_ogarrender_surreal_via_ogar, accessor-thin, zero op-local transpiler logic, ogar-emitter deliberately deferred (V3-triple emitter; the DDL path is ogar-adapter-surrealql). Includes the OP↔Redmine convergence pin (same concept via class_id accessors, diverging APP_PREFIX) and fixture-driven emit tests on rails_mini. Native projection path untouched (default-features run proves it) until step 6's gated retirements.

Tests: default features 10 lib + 7 integration (native path unchanged); --features ogar-emit 13 lib + 2 consumer integration + 7 rails_fixture, all green; ruff_openproject 4/4 + 3/3; op-canon 24 + 8 doctests; workspace check clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01D9qw3LYDprZi4uts2m57iq


Generated by Claude Code

claude added 5 commits July 5, 2026 10:11
§5 step 2 of the OGAR V3 consumer-migration plan
(.claude/handovers/2026-07-05-ogar-v3-consumer-migration-plan.md) — the
additive, zero-risk first step. Stands up .claude/harvest/ as the ONE
training wheel op-nexgen owns: the ORM→AR back-projection, promoted from
the buried D-AR-3.5 vendor patch to explicit resolver config (data).

Files:
- README.md — what the directory is (the one training wheel), the
  data-not-code doctrine, the measure-don't-claim oracle discipline, the
  rules-file schema, and the §4-vs-schema.rs discrepancy log.
- orm-ar-backprojection.toml — 15 [[rule]] rows (7 direct / 6 guess /
  2 weak).

Rules sourced from plan §4 + the vendored D-AR-3.5 harvest
(vendor/AdaWorldAPI-ruff/crates/ruff_ruby_spo/src/schema.rs):
- §4 table rows → typed_column (row1), null_false_presence (row2),
  foreign_key_name (row3), polymorphic_pair (row4), unique_index (row5),
  habtm_join_table (row6), counter_cache (row7), and the §4 row8
  lft/rgt|parent_id split into nested_set + adjacency_tree.
- schema.rs rules the §4 table omits → explicit_column (t.column form),
  implicit_pk + id_false_suppresses_pk (PK defaults), timestamps_pair,
  and the DIRECT DSL association extraction references_belongs_to +
  references_polymorphic (higher-confidence than §4's name-pattern guess).
All 15 rules are validation="unmeasured" pending the AR-oracle pass; no
rule ships as coverage until the 90/10 oracle diff confirms it.

op-codegen-residual is untouched: its RESIDUAL_MANIFEST is output-side
three-buckets data (a different concern) whose migration is a later step
(§5 step 6); the README records where it lives.

Doctrines restated: config is data — where data is insufficient, make
ruff smarter (spec it, don't fake it here); measure, don't claim — every
guess is validated against the AR oracle, no shipped coverage unmeasured.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D9qw3LYDprZi4uts2m57iq
…amed rev (consumer-migration §5 step 3)

The vendor fork's entire ahead-delta (D-AR-3.5 schema stratum, Ruby
method-visibility filtering, extract_tree_with DO-arm harvest,
Predicate::ColumnNotNull + Model.inherits/Field.not_null) landed
upstream as AdaWorldAPI/ruff 8d6c31b (strict-superset audit + 66/66 +
47/47 green there), so the vendored ruff_spo_triplet/ruff_ruby_spo retire
in favor of rev-pinned git deps — the same pin ritual this repo
already runs for OGAR. ruff_openproject (OP-local curation, never an
upstream crate) relocates to crates/ as a workspace member with its
fixtures made crate-local; ruff_python_dto_check (standalone, no
manifest) relocates unmodified. The workspace exclude for the vendor
mirror goes away with the mirror.

Per the vendored-tree fuse doctrine (OGAR EPIPHANIES
E-VENDOR-DELTA-IS-THE-TRAINING-WHEEL): a vendored tree gets a drift
fuse or a deletion date — this is the deletion date. Drift protection
is now the rev pin + the lock-pin bump ritual.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D9qw3LYDprZi4uts2m57iq
Absorbs the e84e1c0 IfMod pin bump and moves to c514b96, which adds
the compute-linkage pass (schema field + compute def => emitted_by,
Inferred-grade). ruff_openproject gains the additive schema-aware
entry points (extract_graph_with_schema / extract_triples_with_schema)
and the locked-shape test now exercises the honest path: fields from
the schema stratum (fixture gains a db/migrate/tables/ baseline —
work_packages.rb with the total_hours column, plus time_entries.rb
for symmetry with the app/models fixture), raises from the IfMod fix,
emitted_by from the linkage pass — extract_triples_produces_locked_shape
green for the first time since the vendor era documented it as drift.
op-codegen-pipeline steady.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D9qw3LYDprZi4uts2m57iq
… ruling — no rev pins)

Operator ruling: rev pins on AdaWorldAPI-internal git deps are retired —
"they're out of desperation to lock what hadn't converged in transpiler
sink-in yet." Drift protection is the fuse tests, not pins.

- ruff_openproject, op-codegen-pipeline: ruff_ruby_spo / ruff_spo_triplet
  flip from `rev = "c514b96d38d764bb16ac070fb2fdbd13477f41bc"` to
  `branch = "claude/odoo-rs-transcode-lf8ya5"`.
- op-canon, op-codegen-projection, op-surreal-ast: ogar-vocab /
  ogar-class-view / ogar-render-askama flip from `branch = "main"` to the
  same convergence branch, so every OGAR dep in the workspace resolves to
  one git source (op-surreal-ast wasn't named in the original sweep but
  its ogar-vocab dep at branch=main produced a second, ambiguous source —
  flipped it too to restore single-source coherence).
- lance-graph-contract stays on `branch = "main"` everywhere (already
  floating, never rev-pinned).

Flips to `branch = "main"` once the convergence branches merge.
Cargo.lock still locks a concrete rev for reproducibility.

Verified: cargo tree -i ruff_spo_triplet / -i ogar-vocab each resolve to
exactly one git source. cargo test -p ruff_openproject (3 lib + 4
integration), -p op-canon (24 lib + 8 doctest), -p op-codegen-projection
(34 lib), -p op-codegen-pipeline (10 lib + 7 integration) all green.
cargo check --workspace clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D9qw3LYDprZi4uts2m57iq
…> OGAR lift/mint -> adapter emit (§5 steps 4-5)

Adds the ogar-emit consumer path alongside (not replacing) the native
ruff -> op-surreal-ast -> SurrealQL path: source -> ruff -> OGAR
lift/mint -> Class -> ogar-adapter-surrealql::emit_surrealql_ddl.

- op-codegen-pipeline/Cargo.toml: optional deps ogar-vocab,
  ogar-from-ruff, ogar-adapter-surrealql (all on the convergence
  branch, single-source with the rest of the workspace's OGAR deps;
  ogar-adapter-surrealql pulled with default features only — its
  surrealdb-parser feature stays off). New `ogar-emit` feature gates
  the new module so the native path's dependency graph is untouched
  by default.
- New `op_codegen_pipeline::ogar_consumer` module (feature-gated):
  `compile_op::<P>` (thin wrapper over
  `ogar_from_ruff::mint::compile_graph_ruby`), `emit_surreal_via_ogar`,
  `render_surreal_via_ogar` (full extract -> filter -> emit chain), and
  `render_classid_of::<P>` (accessor-only classid composition via
  `ogar_vocab::app::render_classid_for`). Unit tests pin the
  OpenProject/Redmine convergence (WorkPackage/Issue, TimeEntry,
  Project all converge with distinct APP_PREFIXes) and
  `render_classid_of::<OpenProjectPort>("WorkPackage") ==
  Some(0x0102_0001)`.
- New tests/ogar_consumer_fixture.rs (gated on the `ogar-emit`
  feature): drives the shared `tests/fixtures/rails_mini/` fixture
  through the OGAR path, asserting DEFINE TABLE for WorkPackage +
  TimeEntry, no AdhocThing, and typed schema-stratum fields (`subject`
  required `string`, `done_ratio` optional `int`) — line-presence
  assertions, deliberately not byte-golden against the native path's
  different emit shape.
- Updated the ogar-v3 consumer migration plan (§5 steps 4-5) to
  [DONE] / [DONE — additive], noting ogar-emitter was deliberately
  deferred (targets V3 triples, not this step's DDL need) and that
  full test-porting off the native path (step 6, retiring
  op-surreal-ast) remains open.

Verified: cargo test -p op-codegen-pipeline (default features: 10 lib
+ 7 integration, native path untouched) and --features ogar-emit (13
lib + 2 new integration + 7 rails_fixture, all green). cargo tree -p
op-codegen-pipeline --features ogar-emit -i ruff_spo_triplet resolves
to one git source. cargo check --workspace --features
op-codegen-pipeline/ogar-emit clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D9qw3LYDprZi4uts2m57iq

@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 1 potential issue.

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 5092688. Configure here.

pub fn render_surreal_via_ogar(rails_root: &Path) -> String {
let (mut graph, _report) = ruff_ruby_spo::extract_app_with_schema(rails_root, crate::NAMESPACE);
crate::filter_to_core(&mut graph);
emit_surreal_via_ogar(&graph)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

OGAR path drops pre-filter FK knowledge

Medium Severity

The render_surreal_via_ogar function filters the ModelGraph with filter_to_core before OGAR processing. This prematurely discards knowledge of non-core models. The native pipeline retains all model names to correctly resolve foreign key record<Target> types. Consequently, the OGAR path may generate SurrealQL DDL with mis-typed foreign key columns compared to the production pipeline.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5092688. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 509268807c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +64 to +65
crate::filter_to_core(&mut graph);
emit_surreal_via_ogar(&graph)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve non-core targets before OGAR emission

When the ogar-emit path is run on a real OpenProject checkout, this filters the ModelGraph before compiling/emitting OGAR classes. The native path in this crate keeps a pre-filter target snapshot specifically because core models can point at non-core targets such as assigned_to -> Principal; after this filter, those target classes are unavailable for stub/table emission, so the OGAR DDL can contain relationships to classes that were removed from the emitted class set. Compile from the full graph or carry/synthesize target stubs before emitting the filtered core surface.

Useful? React with 👍 / 👎.

Comment thread Cargo.toml
# normally; they bypass workspace-member discovery.
exclude = [
"vendor/AdaWorldAPI-ruff",
"crates/ruff_openproject",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wire the moved dto-check tests into Cargo

This commit relocates the ruff_python_dto_check SQLX source and tests under crates/ruff_python_dto_check, but the workspace member list only adds crates/ruff_openproject, and there is no crates/ruff_python_dto_check/Cargo.toml in the tree. Cargo ignores directories without a manifest/member, so the moved tests under crates/ruff_python_dto_check/tests are never discovered and cargo test -p ruff_python_dto_check cannot exercise the SQLX target. Add a manifest/workspace member or keep these files out of crates/ as non-build fixtures.

Useful? React with 👍 / 👎.

@AdaWorldAPI AdaWorldAPI closed this Jul 5, 2026
@AdaWorldAPI AdaWorldAPI reopened this Jul 5, 2026
@AdaWorldAPI AdaWorldAPI merged commit abb23f3 into main Jul 5, 2026
1 check passed
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