Skip to content

docs: lock buyer-facing auto backend to fail-closed Rust - #945

Closed
cursor[bot] wants to merge 9 commits into
mainfrom
cursor/bc-4ace8e61-25c0-4757-9d00-18631c0d61d6-c3a0
Closed

docs: lock buyer-facing auto backend to fail-closed Rust#945
cursor[bot] wants to merge 9 commits into
mainfrom
cursor/bc-4ace8e61-25c0-4757-9d00-18631c0d61d6-c3a0

Conversation

@cursor

@cursor cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Scope

Keep the executable Claude runtime-contract from #833, and close the remaining buyer-facing #621 defect: README and commercial-readiness still told a purchaser that backend="auto" transparently falls back to NumPy, which is the opposite of shipped resolve_backend("auto") behavior.

This branch includes the #833 CLAUDE.md TOML contract and extends the lock to customer-facing install/sales copy plus the PRD/TRD/ADR-0002 summaries that still called automatic resolution a transparent fallback.

Prefer this PR over #833. Do not merge #833 in parallel.

What a purchaser should do

  1. Install a wheel or editable build that compiles fast_mlsirm._core.
  2. Keep FitConfig(backend="auto") for production; it fails closed if the Rust core is missing.
  3. Pass backend="numpy" only when you want the explicit reference/parity path.

Machine-readable contract (unchanged)

[runtime_contract]
requires_python = ">=3.12"
auto_backend = "rust_required"
numpy_role = "reference_parity_only"

Verification

Focused contract tests in tests/test_claude_runtime_contract.py passed locally (7 tests), including README, commercial-readiness, PRD, TRD, and ADR-0002 stale-claim locks. No runtime, formula, estimator, or dependency changes.

Advances #621.

Open in Web View Automation 

seonghobae and others added 9 commits August 14, 2026 10:13
Keep the Claude runtime-contract TOML, and stop README, commercial
readiness, PRD, TRD, and ADR-0002 from advertising a silent NumPy
fallback for backend=auto. Purchasers should install the compiled
Rust core or pass explicit backend=numpy for parity testing.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@cursor
cursor Bot requested a review from seonghobae August 16, 2026 16:23
@seonghobae
seonghobae marked this pull request as ready for review August 16, 2026 16:24
@cursor

cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@seonghobae
seonghobae enabled auto-merge (squash) August 16, 2026 16:33

@cursor cursor Bot 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.

Verdict: REQUEST_CHANGES (posted as COMMENT; GitHub rejects REQUEST_CHANGES on cursor[bot] PRs)

The Install rewrite, CLAUDE.md TOML contract, commercial Supported Product Surface, and the PRD/TRD/ADR-0002 auto sentences match shipped resolve_backend("auto"). Prefer this PR over #833. Do not merge #833 in parallel.

This branch does not close the buyer-facing defect it claims to close. A purchaser can still be told that auto falls back to NumPy — in the same README this PR edited, in fast-mlsirm fit --help, in the public FitConfig comments, and in commercial Operational Notes. The new tests lock exact phrases and stay green through all of that. They never import resolve_backend.

Shipped policy on this head:

  • python/fast_mlsirm/backend.py: auto"rust" when fast_mlsirm._core imports; otherwise RuntimeError("compiled Rust core is required for automatic backend resolution"). Explicit numpy never inspects the core.
  • FitConfig.backend default is "auto".
  • CLI --backend default is auto.
  • Behavioral lock already exists in tests/test_backend.py.

No security, formula, estimator, or dependency issues.

Blocking leftovers (same defect class)

  1. README.md CLI section (lines 378–381) — Install now says fail-closed; the later CLI examples still say fit --backend auto “falls back to NumPy otherwise.” Buyer confusion in the primary install doc.
  2. python/fast_mlsirm/cli.py --help — still says default: auto = Rust core when available, numpy reference fallback. That is the purchaser-visible contract for fast-mlsirm fit.
  3. python/fast_mlsirm/config.py FitConfig.backend comment — still says "auto" “transparently falls back to the pure-numpy reference implementation otherwise.”
  4. docs/commercial_readiness.md Operational Notes — still says “Installed wheels can use the NumPy backend by default,” which contradicts the new Supported Product Surface and README (“installed wheels ship the compiled core”).
  5. tests/test_claude_runtime_contract.py — phrase locks, not a shipped-policy bind. _STALE_AUTO_NUMPY_FALLBACK is the old Install sentence only. It does not catch “falls back to NumPy otherwise”, CLI help, FitConfig comments, or commercial Operational Notes. test_claude_machine_runtime_contract_matches_shipped_policy never imports resolve_backend.

Residual product gap (not introduced here)

Auto fail-closed errors do not tell the next action. Doctoring correctly wants a stable, non-reflective error, but a purchaser is not told to install a wheel/_core or pass backend="numpy" / --backend numpy.

Next action

A successor on this run’s branch will lock the leftover README/CLI/FitConfig/commercial surfaces, bind the contract tests to resolve_backend, and add a stable next-action suffix on the auto fail-closed error. Treat that successor as the landing vehicle. Reviewer seonghobae is already requested. Do not self-approve.

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

assert _STALE_AUTO_NUMPY_FALLBACK not in normalized
assert _STALE_PARITY_AND_FALLBACK not in normalized
assert "fails closed when that extension is unavailable" in normalized
assert "Automatic resolution never silently selects NumPy" in normalized

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.

This README lock only forbids the old Install sentence. The same file still says fit --backend auto “falls back to NumPy otherwise” around lines 378–381. A purchaser who follows the CLI examples gets the opposite of shipped resolve_backend("auto"). Scan that later CLI section (or the whole README) for the leftover claim.

project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))
guidance = (ROOT / "CLAUDE.md").read_text(encoding="utf-8")

assert _runtime_contract(guidance) == {

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.

test_claude_machine_runtime_contract_matches_shipped_policy compares CLAUDE.md TOML to hardcoded rust_required / reference_parity_only. It never imports resolve_backend. The executable fail-closed bind already lives in tests/test_backend.py; this lock should call or document that shipped function so a docs-only rewrite cannot drift from runtime policy.


assert _STALE_NUMPY_DEFAULT not in readiness
assert "Rust/PyO3 backend as the default `auto` runtime path" in readiness
assert "Explicit NumPy reference backend for parity testing only" in readiness

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.

This assertion locks the Supported Product Surface rewrite and misses Operational Notes: “Installed wheels can use the NumPy backend by default.” That leftover still tells a sales reviewer the opposite of “installed wheels ship the compiled core.” Include that sentence in the stale-claim scan.

Comment thread README.md
`backend="numpy"` to force the pure-Python reference (used for parity testing).
The default runtime backend is `"auto"`. It uses the compiled Rust core
(`fast_mlsirm._core`) and fails closed when that extension is unavailable.
Automatic resolution never silently selects NumPy. Source and editable installs

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.

Install copy is now correct. The CLI section later in this same file still says fit --backend auto uses Rust when available and falls back to NumPy otherwise. Until that paragraph is rewritten, this PR does not close the buyer-facing #621 defect.

- Rust/PyO3 backend as the default `auto` runtime path through
`fast_mlsirm._core`. `auto` fails closed when the compiled core is
unavailable.
- Explicit NumPy reference backend for parity testing only.

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.

Supported Product Surface is now correct. Operational Notes still say installed wheels can use NumPy by default. A sales reviewer who reads past the surface list still gets the old ownership story.

@seonghobae seonghobae closed this Aug 16, 2026
auto-merge was automatically disabled August 16, 2026 16:38

Pull request was closed

Copy link
Copy Markdown
Contributor

Superseded by #946 after a fresh exact-head comparison. #946 is a strict descendant of this head (ahead 2 / behind 0, merge base = this exact head), retains the executable CLAUDE/runtime and buyer-facing Rust-required auto contract, and closes additional stale surfaces in README CLI guidance, fit --help, public FitConfig comments, commercial Operational Notes, and the package-owned auto error path. This PR was closed before its enabled auto-merge could integrate the incomplete predecessor contract.

seonghobae added a commit that referenced this pull request Aug 25, 2026
…faces (#951)

* test(docs): pin Claude runtime support contract

* docs: align Claude guidance with fail-closed runtime

* test(docs): normalize Markdown wrapping in runtime contract

* test(docs): reject marginal fallback claim

* revert: keep runtime guidance lane scoped

* test(docs): require machine-readable runtime contract

* docs: publish machine-readable runtime contract

* test(config): expose integer callback trust gap

* fix(config): reject caller-controlled integer coercion

* test(config): cover bounded integer trust controls

* docs(changelog): record config integer boundary hardening

* docs(doctoring): record config integer trust boundary

* fix(config): validate simulation and fit controls at construction

Strix VULN-0001 failed the current head because MLS2PLMConfig and
FitConfig could be constructed with values that bypass memory-safety
bounds until a later explicit validate() call. Run the existing
validators from __post_init__ so invalid objects cannot exist, and keep
validate() public and idempotent.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* fix(config): store trusted integers and harden seed controls

Write admitted NumPy integers back as built-in ints so n_items and
seed + restart cannot wrap, and reject untrusted seed/verbose values
before construction returns.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* docs: lock buyer-facing auto backend to fail-closed Rust

Keep the Claude runtime-contract TOML, and stop README, commercial
readiness, PRD, TRD, and ADR-0002 from advertising a silent NumPy
fallback for backend=auto. Purchasers should install the compiled
Rust core or pass explicit backend=numpy for parity testing.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* fix: lock leftover auto-backend surfaces to fail-closed Rust

Close the buyer-facing leftovers that #945 missed: README CLI examples,
fit --help, FitConfig comments, commercial Operational Notes, and the
auto fail-closed error now name the next action. Contract tests bind to
resolve_backend and scan those surfaces.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* test: tolerate wrapped fit --help and reference/parity wording

The auto-unavailable message uses "reference/parity" as policy language,
not a filesystem path. fit --help wraps the next-action clause, so the
lock now compares whitespace-normalized help text.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* fix: lock leftover demo and acceptance auto surfaces to Rust

Buyer demo copy, README layout, sales --check-import help, and
release-acceptance still treated Rust as optional or accepted NumPy
as an automatic fit outcome. Fail those surfaces closed and lock them.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* test(sales): expose automatic backend authority gap

* test(sales): defer backend authority to owning PR

* test(backend): cover unloadable Rust core

* fix(backend): fail closed before untrusted controls and loader errors

* test(backend): enforce callback-safe controls

* docs(backend): record loader and control hardening

* docs(backend): unify loader and selector trust boundary

* test(config): align resource-limit regressions with constructor validation

* test(config): keep bifactor objective fixture valid

* fix(test): match auto-fit Rust authority error text

The merge with main kept the pre-helper regex from #865 after
_require_auto_fit_resolved_to_rust started raising
"fit auto backend must resolve to rust".

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* fix(diagnostics): trust fold counts before budget products

dimensionality_diagnostics still multiplied untrusted NumPy k_folds
and added untrusted seed offsets, so uint8(32)*32 wrapped past the
fit-budget cap and uint8(250)+6 wrapped to 0. Store built-in ints
the same way seed/verbose already do.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* test(config): use raw regex literals in compatibility checks

* fix(diagnostics): trust fit-diagnostic integer controls

fit_diagnostics still coerced parameter_count with int() and left
m2_q_* untrusted, so a hostile __index__ object could execute during
AIC/BIC arithmetic. Marshal those controls through _trusted_integer
the same way seed/verbose already do.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

* test(backend): document import failure fixture

* test(backend): lock reference guidance contract

* fix(adr): preserve accepted backend decision

* fix(docs): distinguish CLI and Python reference paths

* fix(cli): point NumPy parity users to --reference

* test(runtime): align fail-closed reference contract

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
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