Skip to content

fix(odoo-spo): read selection_add + merge across classes (codex #530 follow-up)#532

Merged
AdaWorldAPI merged 1 commit into
mainfrom
claude/odoo-spo-selection-add
Jun 18, 2026
Merged

fix(odoo-spo): read selection_add + merge across classes (codex #530 follow-up)#532
AdaWorldAPI merged 1 commit into
mainfrom
claude/odoo-spo-selection-add

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Summary

Follow-up to #530 — the selection_add fix for the codex P2 review landed on the branch after #530's merge snapshot was taken, so it's cherry-picked here.

The finding (codex, valid)

Odoo addons extend an existing Selection field's value domain via _inherit + fields.Selection(selection_add=[('reviewed','Reviewed')]) without redeclaring the base list. _extract_selection_values only read the base selection= arg, so the emitted selection_value set was incomplete — a downstream ASSERT $value IN [...] would reject records in legal extension-added states.

Fix

  1. _extract_selection_values now reads both the base list (positional arg 0 or selection=) and selection_add=, unioning base-first with order-preserving dedup (factored into _selection_tuple_keys).
  2. _scan_file binding now merges keys per (model, field) instead of last-write-wins — the base declaration and the selection_add extension live in different classes, so the field's value set must accumulate across scans.

Tests (53 → 57)

  • selection_add kwarg alone → added keys
  • base + selection_add → union, base first
  • selection_add dedups against base
  • cross-class merge: base state in the _name class + selection_add=[('reviewed', …)] in an _inherit class → accumulated [draft, posted, reviewed]

python3 -m unittest tests.test_spo_enrich57/57 OK.

Pure Extracted-leg breadth fix; the Core-first framing from #530 (typed Core is the authoritative home for selection_value) is unchanged.

Odoo addons extend an existing Selection field's domain via
`_inherit` + `fields.Selection(selection_add=[('reviewed','Reviewed')])`
WITHOUT redeclaring the base list. `_extract_selection_values` only read
the base `selection=` arg, so the emitted `selection_value` set was
incomplete and a downstream `ASSERT $value IN [...]` would reject records
in legal extension-added states.

Two fixes:

1. `_extract_selection_values` now reads BOTH the base list (positional
   arg 0 or `selection=`) AND `selection_add=`, unioning base-first with
   order-preserving dedup (factored into `_selection_tuple_keys`).

2. `_scan_file` binding MERGES selection keys per (model, field) instead
   of last-write-wins — the base declaration and the `selection_add`
   extension live in DIFFERENT classes, so the field's value set must
   accumulate across scans, not overwrite.

Tests (53 -> 57):
  - selection_add kwarg alone -> added keys
  - base + selection_add -> union, base first
  - selection_add dedups against base
  - cross-class merge: base in _name class + selection_add in _inherit
    class -> accumulated [draft, posted, reviewed]

  python3 -m unittest tests.test_spo_enrich : 57/57 OK
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@AdaWorldAPI, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 44 minutes and 44 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f7a2cb7-a41e-4069-ba07-094e5cef1503

📥 Commits

Reviewing files that changed from the base of the PR and between c581b54 and a4b161a.

📒 Files selected for processing (2)
  • tools/odoo-blueprint-extractor/odoo_blueprint_extractor/spo_enrich.py
  • tools/odoo-blueprint-extractor/tests/test_spo_enrich.py

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

❤️ Share

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

@AdaWorldAPI AdaWorldAPI merged commit eb85028 into main Jun 18, 2026
1 check passed

@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: a4b161aac8

ℹ️ 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".

seen.add(key)
out.append(key)
_selection_tuple_keys(base, out, seen)
_selection_tuple_keys(add, out, seen)

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 Avoid closing domains from selection_add alone

This now treats selection_add as enough to return a non-empty value list even when the base selection was dynamic or a bare constant, which this helper intentionally cannot resolve. In a common inherited-field case like a base state = fields.Selection(STATES) plus state = fields.Selection(selection_add=[('reviewed', ...)]), the scan records only reviewed; enrich then emits a closed selection_value set with just the extension key, so downstream ASSERT generation rejects the original legal base states. Please keep selection_add as a pending extension and only emit a closed domain once a static base list is known.

Useful? React with 👍 / 👎.

# live in DIFFERENT classes, so a given (model, field)
# accumulates across scans (codex #530). Order-preserving,
# de-duplicated union.
acc = selections.setdefault((mu, field_name), [])

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 Do not union full selection redeclarations

This merge is applied to every fields.Selection declaration, not just selection_add extensions. When an _inherit class redeclares the whole field with selection=[...] to replace or reorder the domain, stale keys from the earlier definition remain in the accumulated set, so the generated selection_value facts allow values the final Odoo field no longer accepts. The scan needs to distinguish additive selection_add values from a full base selection redeclaration and overwrite/reset for the latter.

Useful? React with 👍 / 👎.

AdaWorldAPI pushed a commit that referenced this pull request Jun 18, 2026
…ce/extend/poison + mro rustfmt

Two codex P2 findings on merged #532 were real semantic bugs (live in main),
both producing a WRONG `ASSERT $value IN [...]` — the silent-data-rejection
class that matters for faithful DDL — plus a rustfmt miss on merged #533.

# #532 finding 1 — selection_add must not close a dynamic domain

A `Selection(selection_add=[('x','X')])` extension onto a base that is
DYNAMIC (`Selection(STATE_CONST)` / `selection='_compute_x'`) was emitting
`['x']` as if it were the complete closed set, so the projected
`ASSERT $value IN ['x']` would reject every legal base value.

# #532 finding 2 — full redeclarations must replace, not union

The cross-class merge unioned EVERY `fields.Selection` declaration, so an
`_inherit` class that REDECLARES the whole field with `selection=[...]`
(replace/reorder) left stale keys from the earlier definition in the set.

# The correct three-way semantics

`_extract_selection(call) -> (base_dynamic, base_keys, add_keys)`:
  - static `selection=`  → REPLACE (a redeclaration drops earlier keys)
  - `selection_add=`     → EXTEND  (unions across classes)
  - provided-but-dynamic → POISON  (sentinel `None`; never closed; sticky)

A closed `ASSERT IN` is emitted only when the whole domain is statically
known. Poison is recorded as `None` in the `selections` map and skipped at
emission (`selection_skip_open_domain` stat).

# #533 — mro.rs rustfmt

`mro.rs` landed un-`cargo fmt`'d (codex flagged the diff). Reformatted;
7/7 mro tests still pass.

# Tests

  python3 -m unittest tests.test_spo_enrich : 61/61 (was 57)
    + test_dynamic_base_plus_add_stays_poisoned   (finding 1)
    + test_full_redeclaration_replaces_not_unions (finding 2)
    + test_open_domain_none_emits_nothing
    + rewrote extraction tests for the (dynamic, base, add) contract
  cargo test -p lance-graph-ontology --lib mro : 7/7
  rustfmt --check mro.rs : clean

EPIPHANIES: E-ODOO-SELECTION-REPLACE-EXTEND-POISON.
AdaWorldAPI added a commit that referenced this pull request Jun 18, 2026
fix(odoo): codex review on #532/#533 — selection replace/extend/poison + mro rustfmt
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