slm-training issues: verified-scope-solver (SLM-57/59) + LDI0-01 contract (SLM-114)#322
Conversation
Specify the guarantee boundary separating prefix legality from support (participation in a bounded, fully verified completion) for the Verified Scope Solving & Hybrid Realization project. Spec-only: no solver code, dependency, experiment, or checkpoint; decode behavior is unchanged until a later VSS issue enables new flags. - docs/design/verified-scope-solver.md: term definitions, SUPPORTED / UNSUPPORTED / UNKNOWN semantics (UNKNOWN never removes a candidate), a deterministic bounded-enumeration reference backend (no SMT/Z3) plus an optional future backend protocol, certificate replay and the deduction-vs-decision transitions with every destructive step citing an exact proof/replay, capsule SCC boundaries, late realization, a relationship-to-existing-code table, and an end-to-end partial-coverage live-UNKNOWN example. - research-lineage.md: VSS0 research anchors (DeepCoder, CEGIS, egg / e-graphs, EDLM, TreeDiff, LDT) with the existing Faithful/Adapted/ Surrogate/Adjacent fidelity vocabulary; none tagged Faithful (spec-only). - README.md: register the new doc in the design-doc navigation index. Verified: python -m scripts.repo_policy ok, check-changed selects no tests (docs-only), git diff --check clean, all relative links resolve. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MeD6nTTabPQhva7pXtTMNj
VSS0-03: add the model-independent solver state used by exact closure, certified search, capsule solving, and later learned guidance, per the contract in docs/design/verified-scope-solver.md (VSS0-01 / SLM-57). New package src/slm_training/dsl/solver/ (Torch-free, stdlib-only core): - state.py: frozen, JSON-safe HoleId, SolverBounds, SupportVerdict, DomainValue, HoleDomain, FiniteDomainState. Order-insensitive SHA-256 fingerprint over hard state/config only (excludes decision_level, parent_fingerprint, and by construction logits/scores/timestamps/PIDs/ caches). Monotone refine() (rejects added values / unknown holes), with_decision() lineage, multi-hole meet(), domain() lookup, summary metrics, deterministic to_dict/from_dict. FiniteDomainProjection seam. - adapters.py: completion_forest_state() projects a CompletionForest into one prefix-keyed hole carrying full CompletionPath.token_ids + kind and the coverage guarantee in metadata (empty -> bottom; singleton -> structurally solved for that projection only). Lazy-loaded via package __getattr__ so importing the package pulls in no compiler/torch machinery. tests/test_dsl/test_solver_state.py (28 tests) covers order-insensitive fingerprints, hard-state/version sensitivity, JSON round-trip stability, bottom/solved semantics, monotone refinement + expansion rejection, meet intersection + mismatched-identity rejection, decision lineage, the empty/singleton/multi-path/forced-suffix/partial-coverage adapter fixtures, and a subprocess-verified Torch-free import. No model or ship claim: a model-independent data structure plus a projection adapter the default decode path does not invoke. No checkpoint, experiment, or eval. Exact closure, proof certificates, capsule solving, and learned guidance remain later VSS issues. Verified: pytest tests/test_dsl/test_solver_state.py tests/test_models/test_compiler_decode.py -q (63 passed); ruff clean; python -m scripts.repo_policy ok; git diff --check clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (11)
📝 WalkthroughWalkthroughThe change adds LDI decision-event contracts, objective-support admission, bounded diagnostics, causal constrained-trace capture and replay, removable TwoTower low-rank adapters, related fixtures and tests, plus design-document updates for LDI and verified-scope solver status. ChangesLDI evidence and admission
Causal decision capture
Removable TwoTower adapters
Verified-scope solver documentation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
LDI0-01: add nine verified prior-art works to local-decision-sources.json (LoRA, AdaLoRA, PCGrad/Gradient Surgery, MGDA/MTL-as-MOO, PICARD, Grammar-Aligned Decoding, Min-p sampling, DeepSeekMath/GRPO, TAB-PO). Metadata (title, authors, date) verified against arXiv. All are labeled implementation_status "Adjacent" — none is reimplemented — and carry category, local_decision_takeaway, repo_relevance, and limitations. source_scope honestly records that 25 works came from the original ChatGPT share and 9 were added by LDI0-01. Strengthen test_local_decision_source_manifest_is_complete to assert the new counts (42 rows / 34 papers), unique source_ids and URIs, presence of the required provenance metadata fields, and the Adapted/Adjacent status vocabulary (nothing claimed Faithful). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
LDI0-01: make the local-decision architecture and evidence boundaries canonical in the repo. - Add a "Separation of concerns" section encoding the invariants: evidence / objective / actuator / experiment / promotion are separately owned; constraint shadows certify legality only (never preference labels without same-state counterfactual verification); adapters (LoRA/DoRA/PiSSA/TwoTower delta/ReFT/SAE) are actuator choices, not event schemas; hard grammar/compiler constraints stay deployed; new experiments draw unique E-IDs from allocation (none reserved). Name the real owners (local_decisions.py, local_train.py, trace_store.py, run_quality_matrix.py + autoresearch) and forbid a second orchestration/training stack. Name DecisionEventV2 / action-table evidence as the first new contract. - Add "Measured falsification chain and current blocker": summarize E249-E289 and record the E284 blocker (stable state support is necessary but not sufficient for the objective because independently judged legal alternatives yield different bad-token sets at the same state). - Refresh the stale V10 status (E248/E249 measured; E250-E254 unrun) and the source audit (34 works; nine Adjacent additions mapped to clusters). - Add a dated Measured-status note: docs/inventory only, no model or ship claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
LDI0-01: - research-lineage.md: update the "Exact-state local decision preference" entry from the stale "Proposed/unrun V10 rows E248-E254" to the measured V10 status (E248/E249 measured, E249 rejected, E250-E254 unrun), point at the full 34-paper audit, and label the nine new prior-art works (LoRA/AdaLoRA, PCGrad/MGDA, PICARD/GAD/Min-p, GRPO, TAB-PO) Adjacent -- inventoried, not reimplemented. - quality-experiment-matrix.md: add an "LDI (local decision interventions) index" that points runnable work at the existing V10 section, forbids a second trainer, and registers the LDI0 namespace with no claimed matrix rows and no reserved E-IDs (future rows draw unique E-IDs from allocation). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Records the reviewed commit, source-inventory before/after (33->42 rows, 25->34 papers), duplicate/alternate-URL handling, the nine Adjacent additions with verified arXiv metadata, the documents updated, and an explicit no-code/no-model-quality/no-ship honesty statement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…(SLM-114 follow-on / LDI0-02) Introduces src/slm_training/harnesses/preference/decision_events_v2.py, the V2 contract that separates a model DECISION STATE from per-action verifier EVIDENCE and from a materialized OBJECTIVE VIEW — the fix for the E284 blocker (stable grammar-state support does not imply objective/action-partition support). - DecisionStateV2: canonical state_id over exact model state + immutable runtime identities only (no labels, rollouts, or candidate order), so two label samples of one state share a state_id and evidence reordering/augmentation never changes it. Generalizes V1's twotower-only shape to twotower + causal. - ActionOutcomeV2: append-only per-candidate evidence; preserves the complete ordered G0-G12 gate vector verbatim (validated, never set-collapsed). Merge dedups by content identity, not array order. - ObjectiveView + materializers: materialize_pareto (trainable) and materialize_constraint_shadow (trainable=False, so semantic trainers cannot consume legality-only evidence). - migrate_v1_event: one-way, evidence-honest V1->V2 migration (partial evidence marked incomplete; no fabricated rollout/verifier vectors). - Atomic JSONL writer + a manifest that separately, order-independently fingerprints states / evidence / views. tests/test_harnesses/preference/test_decision_events_v2.py (16 tests): state-id order-independence and per-field sensitivity, tampered-id rejection, complete- G0-G12 enforcement, append-only dedup, materializer trainability + foreign-state rejection, honest V1 migration, and order-independent manifest fingerprints. V1 suite unchanged (27 passed with test_local_decisions.py). ruff + repo_policy clean. Scope: this is the core schema/materializer/migration foundation. The remaining materializer views (thresholded scalar, single-best/worst, set-valued) and the Markdown/CSV renderers from the issue remain follow-on work; no model, checkpoint, training, or quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…emo (SLM-116) Finishes the objective-view materializer set required by LDI0-02 and adds the design memo evidence artifact. - materialize_thresholded: threshold one scalar reward metric, gated by an evidence-confidence floor (low-confidence/no-reward actions stay ambiguous). - materialize_single_best_worst: single-best good / single-worst bad control. - materialize_set_valued: good/bad partitions from verifier verdicts (all G-gates pass => good). All three are trainable; constraint_shadow remains non-trainable. - Add _action_summary so materializers aggregate multiple append-only rollout rows per action instead of double-classifying. - docs/design/iter-ldi0-02-decision-events-v2-20260717.md: worked fixture-corpus walk-through (one state, two actions, two materializers producing different views, stable state fingerprint vs changing objective fingerprint) with an explicit no-training/no-ship honesty statement and named follow-ons. Tests: 20 in test_decision_events_v2.py (adds thresholded/single-best-worst/ set-valued views + idempotent migration); V1 suite unchanged (31 passed with test_local_decisions.py). ruff + repo_policy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Adds the V2 objective-support coverage gate that fixes the E284 blocker: a corpus can pass state-support (good-only signature) yet fail objective support because the sampled bad-action set changes the FTPO gradient. - objective_view_signature: keys on materializer id/config hash + the good/bad partition (unlike the state-support signature, which excludes negatives). - objective_view_support: held-out objective-view coverage (the V2 analogue of decision_signature_support) — covered/uncovered/passed by split. - admit_semantic_corpus: fail-closed admission that refuses non-trainable (constraint_shadow) views, materializer mismatches, and corpora lacking train support for any held-out objective signature; each refusal names what is missing. 4 tests (24 total in test_decision_events_v2.py): the E284 pattern (passes state support, fails objective support), covered-passes, constraint-shadow refusal, materializer-mismatch refusal. ruff + repo_policy clean. Scope: Part A (admission) core, torch-free. Part B (the bounded two-tier runtime diagnostic with a cumulative-wall-budget deadline + fake-clock tests) and the trainer-entry wiring + memo are the next commits. No model, checkpoint, training, or quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…/ LDI0-03 Part B core) Implements the runtime-budget mechanism that makes the objective-geometry diagnostic bounded, fixing the E285/E286 failure mode (a profile that ran past the envelope and produced invalid evidence). - DiagnosticBudget: cumulative wall budget, default and hard-capped at 5 minutes. - Deadline: one monotonic deadline shared across stages (read through the module `time` ref so a fake clock can be injected). - run_bounded_stages: runs named stages under the shared deadline; on expiry returns status "expired" with result=None (no partial result is ever presented as a diagnostic result) and per-stage telemetry showing what ran before the stop. - not_authorized_report: refuses an unauthorized full-parameter Tier-2 request (status "not_authorized", no result) instead of replaying the invalid E285 full-parameter profile. - write_diagnostic_report: atomic mkstemp + fsync + os.replace JSON write. 5 tests (deterministic fake clock): 5-minute cap, completed run, deadline expiry produces no result and runs no further stage, not_authorized has no result, atomic write. ruff + repo_policy clean. Scope: the bounded-runner core. Remaining for LDI0-03: the Tier-1 logit-space and Tier-2 adapter-subspace diagnostic content that runs on this runner, the train_local_from_paths admission wiring, and the design memo. No model, checkpoint, training, or quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…SLM-117) Documents the objective-support admission gate and bounded-diagnostic runner landed for LDI0-03, compares V1 state-support / V1 objective-signature / V2 objective-view support, and marks E285 and E286 as invalid historical evidence (ran past the five-minute envelope with no report). Notes the remaining Tier-1/ Tier-2 diagnostic content and train_local_from_paths admission wiring as follow-on. No training, checkpoint, model-quality, or ship claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…DI0-03) Wires the E284 fix into the semantic trainer so a non-admitted corpus is refused before the first optimizer step (and before the checkpoint is even loaded), mirroring the existing constraint_shadow refusal. - local_decisions.objective_signature_support: held-out coverage of the OBJECTIVE signature (decision_signature, good + bad) — the analogue of the good-only decision_signature_support. A corpus can pass state support yet fail here. - train_local_from_paths gains require_objective_support; when set it computes objective-signature coverage on the loaded events and raises, naming the uncovered held-out signatures, before TwoTowerModel.from_checkpoint. 2 tests: the E284 pattern (state support passes, objective support fails) and the trainer refusing an objective-unsupported corpus (the refusal fires before the missing checkpoint is reached). 13 passed in test_local_decisions.py; ruff + repo_policy clean. Remaining for LDI0-03: the Tier-1/Tier-2 diagnostic content on the bounded runner. No training run, checkpoint, or model-quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…7 / LDI0-03) Complete the bounded-diagnostic content on run_bounded_stages: - tier1_objective_geometry: read-only geometry over already-materialized objective views (getattr on good/bad action ids, decoupled from decision_events_v2). Reports per-corpus objective-contradiction count (an action scored good by one view and bad by another — the logit-space shadow of the E284 conflict) and the mean pairwise Jaccard overlap of per-state good-action sets. Computes no gradient, trains nothing. - tier2_subspace_gradients: refuses an empty/None (full-parameter) request as not_authorized rather than replaying the invalid E285 full-parameter profile; for an explicit adapter subset it records a bounded plan only, with the gradient computation deferred to a model stage this module never runs. Both run under the shared cumulative five-minute DiagnosticBudget, so an expired run still yields result: None. Adds fake-clock tests for the Tier-1 contradiction/agreement/deadline paths and the Tier-2 refuse/plan paths, and updates the LDI0-03 memo to reflect what landed vs. the remaining V2 admit_semantic_corpus CLI wiring. No training, checkpoint, or model-quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…19 / LDI1-01) Instrument the causal OpenUI plug-in so every supervised decision is recoverable from exact prefix token ids and model logits, not decoded strings, and emit DecisionEventV2 evidence compatible with the shared preference harness (SLM-116). - models/causal_trace.py (torch-free core): capture_raw_steps drives a greedy constrained decode through injected forward_logits/allowed_ids callables, so the raw pre-mask argmax and the constrained selection come from the same logits and a constraint_shadow (illegal raw winner overridden by a legal selection) is exact. Returns policy-retained RawStepObservations, the full generated sequence, and an honest stop_reason. Bounded selection policies (every / constraint_shadow_only / margin_threshold / sampled_positions / named_roles) never change what is emitted. - Emission: emit_causal_decision maps observations onto causal DecisionStateV2 with the exact integer prefix as context_ids; base+adapter identity is folded into policy_checkpoint_sha (no dedicated adapter field), so adapter on/off yields distinct state identities. A shadow yields a legality-only ActionOutcomeV2 and a non-trainable materialize_constraint_shadow view that admit_semantic_corpus refuses. - Persistence: CausalTraceWriter appends to the shared TraceStore (kind=causal_decision, no second format) with a reproducible manifest; load_causal_decision_states fails closed on a checkpoint/tokenizer mismatch before returning any state. - Plug-in: generate_constrained_traced stores context_ids as the full prefix so model(context_ids).logits[:, -1, :] replays exactly; replay_causal_action applies a forced action to the exact prefix and returns a pre-judge GeneratedOutcome for the counterfactual owner (no judge here). generate_constrained (trace-off) is unchanged. Tests: torch-free capture/emission/persistence/fail-closed/policy suite; a torch suite for the real forward through the loop, stored-logit replay within tolerance, greedy equivalence, reproducible forced replay, and adapter identity; and a committed fixture-grade trace (exact prefix replay, raw/legal telemetry, one non-admittable constraint shadow, one forced legal counterfactual outcome). Adds no FTPO trainer, no judge, no matrix run, no training, and no model-quality or ship claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
The causal-capture fixture test asserted that a fixed program validated against the OpenUI catalog. That passed under the lenient lark backend used locally but failed CI, where the strict lang_core backend rejects "Text" as not-in-catalog. The component catalog is environment/pack-dependent, so asserting catalog-validity in a committed fixture is both fragile and an overreach. Set the forced-outcome fixture's canonical_program to null — which is exactly what a strict-backend replay yields for a non-catalog program — and assert only backend-independent honesty properties (forced action id, finish reason, no judge label). Update the fixture README and LDI1-01 memo to state that canonicalization is deferred to the strict validator rather than claimed here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
There was a problem hiding this comment.
Actionable comments posted: 20
🧹 Nitpick comments (1)
tests/test_harnesses/preference/test_decision_events_v2.py (1)
124-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover every field contributing to
state_id.Despite the test name, several identity fields are omitted, including tokenizer/decode hashes, abstract role, canvas/context IDs, generation step, architecture, and group. Parameterize the field mutations so future hash regressions cannot pass unnoticed.
As per coding guidelines, “Non-trivial logic must leave one runnable check behind.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_harnesses/preference/test_decision_events_v2.py` around lines 124 - 131, Expand test_state_id_changes_for_every_hard_state_field to cover every field used by _state().state_id, including tokenizer and decode hashes, abstract role, canvas/context IDs, generation step, architecture, and group. Parameterize the field mutations so each change is asserted against the base state_id, preserving the existing checks and leaving a runnable regression check for every identity field.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/design/iter-ldi0-02-decision-events-v2-20260717.md`:
- Around line 34-35: Update the recorded test count from 20 to 24 in both
references in the decision-events walkthrough, including the additional
occurrence around the later referenced section. Do not change the test suite or
surrounding documentation.
In `@docs/design/verified-scope-solver.md`:
- Around line 3-9: Update the document’s status section to remove the stale
claim that no solver code exists or that the project is specification-only.
Describe VSS0-01 as the contract and identify VSS0-03 as the implemented subset,
while preserving accurate statements about unchanged checkpoints, decode
behavior, and feature-gated rollout.
In `@src/slm_training/dsl/solver/adapters.py`:
- Around line 63-82: Update the projection flow around prefix, completion-path,
pack, and constraint-version inputs to validate their types explicitly at the
trust boundary instead of coercing them with int() or str(). Reject booleans,
strings, floats, and other invalid token values; preserve validated token values
unchanged for prefix and path construction, and validate pack_id and
constraint_version before using them in problem identity/state fields.
- Around line 34-38: Update _prefix_fingerprint to return the complete SHA-256
digest instead of truncating it to the first 16 hexadecimal characters, while
preserving the existing normalized ID serialization and hashing behavior.
In `@src/slm_training/dsl/solver/state.py`:
- Around line 136-143: Update HoleId.from_dict and the other solver-state
deserializers to fail closed at the JSON boundary: validate mapping, container,
and scalar types before constructing objects, access required fields directly,
and reject missing or null required domains. Remove str()/int() coercions and
data.get(...) or () fallbacks so dataclass validators receive original values
and malformed payloads cannot become valid empty or solved states.
- Around line 98-130: Remove ordering generation from the HoleId dataclass by
dropping order=True, while preserving dataclass immutability and all existing
fields, validation, and canonical_key behavior. Callers should use canonical_key
for sorting and lookup instead of generated comparisons.
- Around line 561-570: Update _merge_metadata to detect metadata conflicts using
canonical JSON representations rather than Python equality, so values such as 1
and 1.0 are treated distinctly. When representations match, retain a
deterministic value independent of operand order, ensuring left.meet(right) and
right.meet(left) produce identical metadata and fingerprints.
- Around line 53-64: Update _is_json_scalar to accept floats only when they are
finite, while continuing to allow None, strings, integers, and booleans. Use the
standard floating-point finiteness check so NaN and positive or negative
infinity are rejected before _canonical_json serializes or fingerprints state.
In `@src/slm_training/harnesses/preference/decision_events_v2.py`:
- Around line 754-770: Update objective_view_signature to include the existing
state-support identity in its hashed payload alongside materializer
configuration and good/bad action IDs. Reuse the established state-support
signature helper or symbol rather than reconstructing state identity, while
preserving the objective partition fields and truncation behavior.
- Around line 415-418: Update the outcome validation loops around the shown
state_id checks, including the corresponding logic near the second occurrence,
to reject any outcome whose action_id is not in state.legal_action_ids or whose
legal flag is false. Perform this validation before semantic materialization and
before adding action IDs to observed, while preserving the existing state
ownership validation.
- Around line 321-322: Update _normalize_reward_vector to validate reward
vectors at the input boundary before materialization: require each entry to
match the expected metric identity, reject missing metrics, and reject duplicate
metrics instead of allowing row.get(name, 0.0) to fabricate zero scores.
Preserve valid vectors’ normalized tuple output and ensure malformed inputs fail
before any consumer processes them.
- Around line 413-421: Update the shared _action_summary aggregation to collect
and flatten all underlying reward vectors per action, then compute one overall
average rather than averaging batch means or retaining the last batch. Replace
the local by_action/Pareto aggregation and other materializer-specific logic
with this canonical summary, preserving state validation and observed-action
tracking across every caller.
- Around line 773-781: Validate min_train_support at the start of
objective_view_support and require it to be a positive integer, rejecting zero,
negative values, and non-integer inputs before processing items. Preserve the
existing coverage behavior for valid thresholds.
- Around line 284-308: Update ActionOutcomeV2.from_dict to validate the
serialized version against the supported V2 schema version before
reconstruction, rejecting unsupported values. Validate that legal is an actual
boolean rather than coercing arbitrary inputs with bool(), and preserve the
existing field parsing for valid records.
In `@src/slm_training/models/causal_lm_openui.py`:
- Around line 278-300: The policy identity currently hashes compatibility
metadata and LoRA parameter names rather than actual weights. Update
active_adapter_identity and the capture_identity fingerprint path to use a
stable digest of the active base and adapter checkpoint/artifact tensors, so any
weight mutation changes policy_checkpoint_sha while preserving empty-adapter
behavior. Add a regression test that mutates an existing LoRA tensor without
renaming it and verifies the captured identity changes.
- Around line 383-390: In the causal replay method surrounding state.context_ids
validation, validate that forced_action_id belongs to state.legal_action_ids
before running the model or constructing base_prefix. Reject non-members with
the method’s existing input-validation error behavior, while preserving the
current flow for legal forced actions.
- Around line 385-411: Update replay output construction in the flow containing
forward_logits and capture_raw_steps so raw_text decodes the full generated
suffix already present in state.context_ids, starting at the decision position,
followed by forced_action_id and the continuation tokens. Preserve the existing
prompt prefix exclusion and add a regression covering a state with
decision_position greater than zero to verify earlier generated tokens remain in
the materialized program.
In `@src/slm_training/models/causal_trace.py`:
- Around line 532-539: Update the state-loading loop around
DecisionStateV2.from_dict to validate the deserialized state’s checkpoint and
tokenizer hashes against expected_checkpoint_sha and expected_tokenizer_sha, in
addition to the existing row-level checks. Reject mismatches before appending
the state to states, preserving the current ValueError behavior.
- Around line 276-286: Update the logits handling in the causal-trace decoding
flow to validate every value from forward_logits(prefix) is finite before any
selection, softmax, or evidence persistence. Raise CausalTraceError for
non-finite logits, while preserving the existing empty-vector and legal-token
validation behavior.
In `@tests/test_dsl/test_solver_state.py`:
- Around line 388-392: Update the subprocess.run call in the Torch-free import
test to use a short timeout, and catch subprocess.TimeoutExpired so the test
fails explicitly with useful timeout details instead of hanging indefinitely.
Preserve the existing return-code and TORCH_FREE_OK assertions for successful
completion.
---
Nitpick comments:
In `@tests/test_harnesses/preference/test_decision_events_v2.py`:
- Around line 124-131: Expand test_state_id_changes_for_every_hard_state_field
to cover every field used by _state().state_id, including tokenizer and decode
hashes, abstract role, canvas/context IDs, generation step, architecture, and
group. Parameterize the field mutations so each change is asserted against the
base state_id, preserving the existing checks and leaving a runnable regression
check for every identity field.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 601ee29f-7fdf-4580-abf8-20283616b8e1
📒 Files selected for processing (31)
README.mddocs/design/iter-ldi0-01-20260717.mddocs/design/iter-ldi0-02-decision-events-v2-20260717.mddocs/design/iter-ldi0-03-objective-support-admission-20260718.mddocs/design/iter-ldi1-01-causal-capture-20260718.mddocs/design/local-decision-interventions.mddocs/design/quality-experiment-matrix.mddocs/design/research-lineage.mddocs/design/verified-scope-solver.mdsrc/slm_training/dsl/solver/__init__.pysrc/slm_training/dsl/solver/adapters.pysrc/slm_training/dsl/solver/state.pysrc/slm_training/harnesses/preference/decision_diagnostics.pysrc/slm_training/harnesses/preference/decision_events_v2.pysrc/slm_training/harnesses/preference/local_decisions.pysrc/slm_training/harnesses/preference/local_train.pysrc/slm_training/models/causal_lm_openui.pysrc/slm_training/models/causal_trace.pysrc/slm_training/resources/autoresearch/local-decision-sources.jsontests/test_autoresearch/test_harness.pytests/test_dsl/test_solver_state.pytests/test_harnesses/preference/test_decision_diagnostics.pytests/test_harnesses/preference/test_decision_events_v2.pytests/test_harnesses/preference/test_local_decisions.pytests/test_models/fixtures/ldi1/README.mdtests/test_models/fixtures/ldi1/causal_trace_manifest.jsontests/test_models/fixtures/ldi1/forced_counterfactual_outcome.jsontests/test_models/fixtures/ldi1/traces.jsonltests/test_models/test_causal_trace.pytests/test_models/test_causal_trace_fixture.pytests/test_models/test_causal_trace_plugin.py
| if not isinstance(forest, CompletionForest): | ||
| raise ValueError(f"completion_forest_state requires a CompletionForest, got {type(forest).__name__}") | ||
| prefix = tuple(int(token) for token in prefix_ids) | ||
| fingerprint = _prefix_fingerprint(prefix) | ||
| hole_id = HoleId(namespace=_NAMESPACE, path=(len(prefix), fingerprint), kind="next_action") | ||
| values = tuple( | ||
| DomainValue( | ||
| tag=_TOKEN_PATH_TAG, | ||
| token_ids=tuple(int(token) for token in path.token_ids), | ||
| kind=path.kind, | ||
| ) | ||
| for path in forest.paths | ||
| ) | ||
| hole = HoleDomain(hole_id=hole_id, values=values, metadata=(("coverage", str(forest.coverage)),)) | ||
| return FiniteDomainState( | ||
| problem_id=f"{_NAMESPACE}:{fingerprint}", | ||
| pack_id=str(pack_id), | ||
| constraint_version=str(constraint_version), | ||
| bounds=bounds, | ||
| holes=(hole,), |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Validate projection inputs instead of coercing them.
int() aliases values such as True, "1", and 1.9 to the same token, while str() accepts invalid pack/version identifiers. This bypasses the stricter state validators and can assign malformed compiler inputs a valid state identity.
Pass values through unchanged after explicit type checks, including every prefix and completion-path token.
As per coding guidelines, “Always perform input validation at trust boundaries.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/slm_training/dsl/solver/adapters.py` around lines 63 - 82, Update the
projection flow around prefix, completion-path, pack, and constraint-version
inputs to validate their types explicitly at the trust boundary instead of
coercing them with int() or str(). Reject booleans, strings, floats, and other
invalid token values; preserve validated token values unchanged for prefix and
path construction, and validate pack_id and constraint_version before using them
in problem identity/state fields.
Source: Coding guidelines
…low-up) Address correctness/validation findings from PR review on the already-landed SLM-59/116/119 code: - causal replay (causal_lm_openui): reject a forced action that is not legal for the stored state, and keep the tokens generated before the decision (context_ids[prompt_len:]) so a decision_position > 0 replay materializes the full program rather than a truncated one. active_adapter_identity now digests adapter tensor *values*, so a weight mutation changes policy_checkpoint_sha. - causal_trace: reject non-finite logits before selection/persistence; validate the deserialized state identity against the requested checkpoint/tokenizer, not only the row envelope. - decision_events_v2: ActionOutcomeV2.from_dict validates schema version and rejects non-boolean legal; objective_view_support requires a positive min_train_support. - solver state: reject non-finite floats from JSON-safe state (allow_nan=False + finite check), drop HoleId's unusable generated ordering (paths mix str/int; use canonical_key), and make _merge_metadata commutative via canonical JSON. - solver adapters: keep the full SHA-256 prefix digest (no 64-bit truncation). - tests: bound the torch-free import subprocess with a timeout; add regression tests for the replay suffix, illegal forced action, and adapter-weight identity change. - docs: correct the decision-events test count (24) and the verified-scope-solver status (state schema + adapter implemented, decode integration not). Regression tests + full solver/preference/models suites stay green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
… part 1) The self-contained, repository-owned adapter primitive (no Hugging Face PEFT): - models/adapters/spec.py: TwoTowerAdapterSpec, a torch-free frozen, versioned, validated config that round-trips through to_dict/from_dict (rejects unknown fields) so it can persist in an adapter_config.json and through CLI/config. - models/adapters/low_rank.py: LowRankAdapter, a pure-torch wrapper for a frozen nn.Linear implementing y = W x + (alpha/rank) * B(A(dropout(x))) with B zero-initialized (fresh adapter is bit-identical to the parent), enable/disable, adapter_parameters, and a one-way merged_linear() on a copy that never mutates the parent or the removable adapter. Torch-free spec tests and torch-gated wrapper tests cover zero-init identity, disable-restore, gradients only on A/B, dtype/device + batched dims, merge parity without base mutation, and validation. TwoTower model integration (attach/save/load/ merge APIs, adapter-only trainable_parameters, checkpoint allow-list) follows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
… (review) Matching state_id alone let an outcome with an arbitrary action_id, or legal=False, become a trainable good/bad label. Add a shared _require_semantic_outcome guard (state ownership + legal flag + membership in the state's legal action set) and call it in materialize_pareto and the shared _action_summary, so every semantic materializer fails closed before an illegal action is preferred. The legality-only constraint_shadow diagnostic is unchanged (it emits no good/bad labels). Adds a regression test for the illegal and out-of-domain cases; updates the memo test count. Full preference suite green (25 tests in the V2 suite). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
_normalize_reward_vector (the ActionOutcomeV2 construction boundary) now rejects a non-empty reward vector with missing or duplicate metrics, so a downstream mean can no longer fabricate a 0.0 for absent evidence. Empty reward vectors (migrated / legality-only outcomes) remain valid. Adds a regression test; preference suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…2-01, part 2) Attach/resolve the low-rank adapter onto the denoiser and expose adapter-only training: - models/adapters/twotower_adapter.py: deterministic target resolution mapping spec target-module names (attn_q/k/v/out, cross_attn_*, mlp_in/out) onto the denoiser block linears, with fail-closed errors for unknown targets, non-linear matches, and out-of-range layers; attaches LowRankAdapter wrappers in place under a forked RNG so attachment never shifts the training RNG stream. The context tower is never adapted. - TwoTowerModel: attach_adapter (base-fingerprint fail-closed + freeze every non-adapter parameter so the existing trainable_parameters() naturally yields only adapter tensors), enable/disable_adapter, adapter_parameters, has_adapter, and active_adapter_identity (content digest of adapter tensors). Tests cover fresh-adapter output identity at every site, disable-restore after weight change, gradients only on adapter tensors, deterministic resolution + actionable errors, base-fingerprint mismatch, no-RNG-shift, and adapter-only trainable_parameters. Existing twotower suite unchanged. Save/load/merge, the checkpoint allow-list, config/CLI round-trip, and the wiring memo follow. No training run, no quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…art 3) merge_adapter_copy folds each denoiser LowRankAdapter into a plain nn.Linear on a deepcopy, so the merged model carries no active wrappers and trains as an ordinary full model, while this model and its removable adapter are left untouched (merge is one-way on a copy). Tests cover merged-vs-enabled parity at an adapted site, the original staying adapter-bearing, and the no-adapter error. Adds the LDI2-01 wiring memo recording what landed (spec, LowRankAdapter, deterministic attachment, adapter-only training, merge) and the honest remaining scope (save/load directory, checkpoint allow-list, config/CLI round-trip, artifact_identity distinction). No training run, no promoted checkpoint, no quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
…LDI2-01, part 4) save_adapter writes the removable adapter to its own directory — adapter_config.json (the spec), adapter_model.pt (only the lora tensors, not the base checkpoint), and adapter_manifest.json (module map, parameter names/shapes, trainable parameter count, adapter bytes, and base/tokenizer identity). load_adapter fails closed before copying any tensor when the tokenizer identity or base compatibility fingerprint does not match this model, then attaches, loads the tensors, and sets requires_grad per `trainable`. Tests cover the save→load round trip (a fresh same-seed model reproduces the adapted logits) and the fail-closed base-fingerprint mismatch. Existing twotower suite unchanged; the base .pt checkpoint path is untouched. The checkpoint allow-list and config/CLI round-trip remain the documented follow-on. No training run, no quality claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
… subtlety Record that save_adapter/load_adapter (fail-closed removable adapter directory) landed, and correct the remaining-scope note: attaching an adapter renames the wrapped base weight key (q_proj.weight -> q_proj.base.weight), so the base-.pt checkpoint interplay is a wrapper-stripping design task, not a one-line adapter-key allow-list. Doc only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Add concise docstrings to the public methods/properties of the new LDI modules that lacked them — the spec's scaling/to_dict/from_dict, the low-rank adapter's construction/enable/disable/forward surface, the two non-obvious target-resolution helpers, and the causal-trace observation/capture/writer/outcome API. Docstrings only; no behavior change (all affected tests unchanged and green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/slm_training/models/adapters/low_rank.py`:
- Around line 28-42: Update LowRankAdapter.__init__ to validate alpha as finite
and positive, and dropout as finite and non-negative, before assigning scaling
or constructing dropout. Reject invalid values with ValueError, while preserving
valid zero-dropout behavior and existing rank validation.
In `@src/slm_training/models/adapters/spec.py`:
- Around line 40-78: Validate schema_version in AdapterSpec.__post_init__ by
requiring it to equal the supported ADAPTER_SCHEMA_VERSION. Raise a clear
ValueError for any unsupported version so from_dict() cannot interpret future
schemas as the current format.
In `@src/slm_training/models/adapters/twotower_adapter.py`:
- Around line 76-99: Update the adapter target-resolution flow around the
existing block traversal to either resolve the output head when
spec.include_output_head is true or explicitly reject that configuration with a
clear ValueError. Ensure the option never silently has no effect, while
preserving current denoiser-layer resolution behavior.
- Around line 115-120: Update the RNG context around LowRankAdapter construction
in the adapter attachment loop to include the target linear layer’s CUDA device
when applicable, while preserving CPU behavior. Use the device associated with
linear to populate fork_rng(devices=...), ensuring lora_A initialization does
not advance the external CUDA generator.
In `@src/slm_training/models/twotower.py`:
- Around line 1002-1016: Update the adapter-loading flow around
self.attach_adapter and torch.load to fully load and validate the artifact
before mutating the model: verify the exact tensor key set, shapes, manifest
module map, and parameter identities, including both missing and unexpected
entries. Only after all validation succeeds should attach_adapter run, tensors
be copied, and trainability flags be updated; preserve atomic behavior by
leaving the model unchanged when loading or validation fails.
- Around line 872-876: Update the adapter attachment validation near
compatibility_fingerprint() in src/slm_training/models/twotower.py (lines
872-876) to compare base_checkpoint_sha with the model’s loaded base-checkpoint
identity and fail on mismatch. Revise
docs/design/iter-ldi2-01-twotower-adapter-20260718.md (lines 47-52) to avoid
claiming fail-closed base identity until this check is implemented. Add a test
in tests/test_models/test_twotower_adapter.py (lines 173-184) covering identical
architectures with different checkpoints and asserting attachment is rejected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 535f7611-a9bb-4d2f-b852-10535951d79d
📒 Files selected for processing (23)
docs/design/iter-ldi0-02-decision-events-v2-20260717.mddocs/design/iter-ldi1-01-causal-capture-20260718.mddocs/design/iter-ldi2-01-twotower-adapter-20260718.mddocs/design/verified-scope-solver.mdsrc/slm_training/dsl/solver/adapters.pysrc/slm_training/dsl/solver/state.pysrc/slm_training/harnesses/preference/decision_events_v2.pysrc/slm_training/models/adapters/__init__.pysrc/slm_training/models/adapters/low_rank.pysrc/slm_training/models/adapters/spec.pysrc/slm_training/models/adapters/twotower_adapter.pysrc/slm_training/models/causal_lm_openui.pysrc/slm_training/models/causal_trace.pysrc/slm_training/models/twotower.pytests/test_dsl/test_solver_state.pytests/test_harnesses/preference/test_decision_events_v2.pytests/test_models/fixtures/ldi1/README.mdtests/test_models/fixtures/ldi1/forced_counterfactual_outcome.jsontests/test_models/test_adapter_spec.pytests/test_models/test_causal_trace_fixture.pytests/test_models/test_causal_trace_plugin.pytests/test_models/test_low_rank_adapter.pytests/test_models/test_twotower_adapter.py
🚧 Files skipped from review as they are similar to previous changes (11)
- tests/test_models/fixtures/ldi1/forced_counterfactual_outcome.json
- docs/design/iter-ldi1-01-causal-capture-20260718.md
- tests/test_models/fixtures/ldi1/README.md
- tests/test_models/test_causal_trace_fixture.py
- docs/design/iter-ldi0-02-decision-events-v2-20260717.md
- src/slm_training/models/causal_lm_openui.py
- docs/design/verified-scope-solver.md
- src/slm_training/dsl/solver/state.py
- src/slm_training/harnesses/preference/decision_events_v2.py
- tests/test_harnesses/preference/test_decision_events_v2.py
- src/slm_training/models/causal_trace.py
| expected = getattr(spec, "base_compatibility_fingerprint", "") | ||
| if expected and expected != self.compatibility_fingerprint(): | ||
| raise ValueError( | ||
| "adapter base compatibility fingerprint does not match this model" | ||
| ) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Enforce exact base-checkpoint identity across runtime, documentation, and tests.
The adapter stores base_checkpoint_sha, but attachment only checks a shape/configuration fingerprint.
src/slm_training/models/twotower.py#L872-L876: compare the adapter SHA against the model’s loaded base-checkpoint identity.docs/design/iter-ldi2-01-twotower-adapter-20260718.md#L47-L52: avoid claiming fail-closed base identity until that check exists.tests/test_models/test_twotower_adapter.py#L173-L184: add an identical-architecture, different-checkpoint mismatch test.
📍 Affects 3 files
src/slm_training/models/twotower.py#L872-L876(this comment)docs/design/iter-ldi2-01-twotower-adapter-20260718.md#L47-L52tests/test_models/test_twotower_adapter.py#L173-L184
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/slm_training/models/twotower.py` around lines 872 - 876, Update the
adapter attachment validation near compatibility_fingerprint() in
src/slm_training/models/twotower.py (lines 872-876) to compare
base_checkpoint_sha with the model’s loaded base-checkpoint identity and fail on
mismatch. Revise docs/design/iter-ldi2-01-twotower-adapter-20260718.md (lines
47-52) to avoid claiming fail-closed base identity until this check is
implemented. Add a test in tests/test_models/test_twotower_adapter.py (lines
173-184) covering identical architectures with different checkpoints and
asserting attachment is rejected.
Address CodeRabbit findings on the removable low-rank adapter: - low_rank: validate alpha (finite, positive) and dropout (finite, in [0,1)) in the wrapper constructor, so direct construction — which bypasses TwoTowerAdapterSpec — cannot silently produce an invalid adapter (poisoned scaling / dropout degrading to Identity). - spec: reject an unsupported schema_version in __post_init__ so a newer schema can never be reinterpreted as V1 through from_dict(). - twotower_adapter: fail closed on include_output_head=True (the output head is not a resolvable target, so the flag would otherwise silently have no effect); include the target CUDA device in the RNG fork so attachment never advances the external CUDA generator. - twotower.load_adapter: validate the whole artifact against its manifest (tokenizer + base fingerprint agreement, exact tensor key set, shapes) before mutating the model, and check the key set in both directions, so a mismatched or truncated adapter leaves the model unchanged instead of half-attached. - Document that base_checkpoint_sha is provenance only (attachment is gated on architecture fingerprint + tokenizer_sha, which do not tell two checkpoints of the same shape apart); exact base-checkpoint enforcement is deferred with the checkpoint-identity work. Regression tests added for each fail-closed path. Full tests/test_models suite green (172 passed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Resolve conflicts against main's checkpoint + decode-invariance advance: - local-decision-sources.json / test_autoresearch: take main's canonical data+test pair (both branches landed the same SLM-114 source expansion: 34 works / 42 rows; main's test additionally verifies the 9 arxiv IDs). - verified-scope-solver.md: keep this branch's version — it documents the torch-free solver state/adapter implementation this PR actually ships (main's doc was the earlier spec-only stub). - research-lineage.md, local-decision-interventions.md: take main's canonical, further-advanced LDI synthesis (same conclusions; richer E248-E286 ledger). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Second re-merge to catch up to main's fast-moving tip. Only conflict was docs/design/verified-scope-solver.md — both branches appended a dated "Measured status" note (main's VSS0-02/SLM-58 explain-seam note, this branch's VSS0-03/SLM-59 solver-impl note); kept both in numeric order. Main's choice_tokenizer / compiler_draft / compiler_decode changes auto-merged. Focused tests green (80 passed), repo_policy ok. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
The fleet independently shipped SLM-59 (Torch-free finite-domain support lattice) to main via #321/#326. This branch had its own SLM-59 implementation, now redundant. Per "do not reimplement what already exists," resolve the add/add collision by taking main's canonical dsl/solver/ (state.py, adapters.py, __init__.py) and test_solver_state.py verbatim, dropping this branch's duplicate. #322 collapses to its unique, solver-independent LDI contribution (DecisionEventV2 + diagnostics, causal capture, removable adapter). Verified: main's solver test + all LDI suites pass together (141), repo_policy ok. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Rolling integration branch for autonomously-worked
slm-trainingLinear issues (developed on the designated branchclaude/slm-training-issues-d8l0baper the environment's branch policy). Contents so far:SLM-57 (VSS0-01) — verified-scope-solver contract
docs/design/verified-scope-solver.md+ research-lineage anchors (the settled dependency SLM-59 builds on).SLM-59 (VSS0-03) — Torch-free finite-domain support lattice
New
src/slm_training/dsl/solver/(state.py,adapters.py,__init__.py):HoleId,SolverBounds,SupportVerdict,DomainValue,HoleDomain,FiniteDomainState. Order-insensitive SHA-256fingerprintoverhard state/config only (excludes decision lineage, logits, scores, timestamps).
Monotone
refine(),with_decision()lineage, multi-holemeet(),summary(),deterministic
to_dict/from_dict.completion_forest_state()adapter(empty → bottom; singleton → structurally-solved-for-projection-only). Lazy-loaded
so importing the package stays Torch-free.
tests/test_dsl/test_solver_state.py(28 tests) incl. a subprocess-verifiedTorch-free import.
SLM-114 (LDI0-01) — local-decision evidence contract
local-decision-sources.json: nine verified prior-art works added (LoRA, AdaLoRA,PCGrad, MGDA, PICARD, Grammar-Aligned Decoding, Min-p, DeepSeekMath/GRPO, TAB-PO),
all
Adjacent(inventoried, not reimplemented); metadata verified against arXiv.local-decision-interventions.md: separation-of-concerns invariants, owners +no-second-stack rule, the E249–E284 falsification chain and current blocker,
DecisionEventV2first-contract note, dated Measured-status note.research-lineage.mdrefresh +quality-experiment-matrix.mdLDI0 index (noclaimed rows, no reserved E-IDs).
tests/test_autoresearch/test_harness.py: updated counts + stronger assertions.Testing
pytest tests/test_dsl/test_solver_state.py tests/test_models/test_compiler_decode.py -q→ 63 passed.pytest tests/test_autoresearch/test_harness.py tests/test_autoresearch/test_lattice_recursive_sources.py -q→ 44 passed.ruff checkclean on touched Python;python -m scripts.repo_policyok;git diff --checkclean.Notes
data structure + adapter not on the default decode path; SLM-114 is documentation +
a source inventory. No checkpoint, experiment, or eval.
tests/test_dsl/tests/test_harnesses/model_buildsuites (e.g. tokenizer vocab-size drift) reproduce on
mainwithout these changes.🤖 Generated with Claude Code
https://claude.ai/code/session_01U5Fy8PnMTV54p675y9T3B8
Summary by CodeRabbit