Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8de7bc8
Add bounded verified-scope-solver architecture contract (SLM-57)
claude Jul 17, 2026
302cd67
Implement Torch-free finite-domain support lattice (SLM-59)
claude Jul 17, 2026
a81e8f0
Extend local-decision source inventory with required prior art (SLM-114)
claude Jul 17, 2026
b78ade8
Recommit local-decision-interventions as the LDI0 contract (SLM-114)
claude Jul 17, 2026
7361cab
Refresh LDI lineage and register the LDI matrix index (SLM-114)
claude Jul 17, 2026
cbdcfed
Add LDI0-01 design iteration memo (SLM-114)
claude Jul 17, 2026
e7fad0b
Add DecisionEventV2 core: state/action-evidence/objective-view model …
claude Jul 17, 2026
b8dbd1e
Complete DecisionEventV2 materializers and add the LDI0-02 evidence m…
claude Jul 17, 2026
81645d1
Add objective-support admission gate (SLM-117 / LDI0-03 Part A)
claude Jul 17, 2026
4712d12
Add bounded diagnostic runner with cumulative wall deadline (SLM-117 …
claude Jul 18, 2026
6e40a31
Add LDI0-03 memo: objective-support admission + bounded diagnostics (…
claude Jul 18, 2026
3c04e80
Enforce objective-support admission at the trainer entry (SLM-117 / L…
claude Jul 18, 2026
1d8bb40
Add Tier-1 objective-geometry and Tier-2 subspace diagnostics (SLM-11…
claude Jul 18, 2026
ff1417e
Capture exact causal decision states and legal-action evidence (SLM-1…
claude Jul 18, 2026
778550b
Make the LDI1-01 forced-outcome fixture backend-independent (SLM-119)
claude Jul 18, 2026
c666f73
Harden trust-boundary validation across the LDI/solver PR (review fol…
claude Jul 18, 2026
8956906
Add the removable low-rank adapter backend module (SLM-123 / LDI2-01,…
claude Jul 18, 2026
c08c160
Reject illegal/out-of-domain outcomes before semantic materialization…
claude Jul 18, 2026
cee01e8
Validate reward vectors carry exactly the expected metrics (review)
claude Jul 18, 2026
cb47f1b
Integrate the removable low-rank adapter into TwoTower (SLM-123 / LDI…
claude Jul 18, 2026
c1c0c9c
Add one-way adapter merge + LDI2-01 wiring memo (SLM-123 / LDI2-01, p…
claude Jul 18, 2026
6b93b84
Add removable adapter save/load with fail-closed identity (SLM-123 / …
claude Jul 18, 2026
1ddfddc
Update LDI2-01 memo: save/load landed; note the checkpoint key-rename…
claude Jul 18, 2026
4fd2fdf
Document the public adapter + causal-trace API surface
claude Jul 18, 2026
6984beb
Harden adapter trust boundaries per review (SLM-123 / LDI2-01)
claude Jul 18, 2026
21d1f5e
Merge origin/main into claude/slm-training-issues-d8l0ba
claude Jul 18, 2026
7f233c0
Merge origin/main (776c701) into claude/slm-training-issues-d8l0ba
claude Jul 18, 2026
dd533b0
Merge origin/main (5572e01): adopt main's canonical SLM-59 solver
claude Jul 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions docs/design/iter-ldi0-01-20260717.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# LDI0-01 — local-decision evidence contract recommit

Date: 2026-07-17
Status: **documentation and source-inventory change only; no code, no checkpoint,
no model-quality or ship claim.**

## Scope

LDI0-01 makes the local-decision-interventions research synthesis and architectural
boundaries canonical in the repository so future agents do not rebuild a parallel
harness, rerun the falsified E249–E284 experiments as if open, or treat a local
metric gain as promotion evidence. No event-schema or trainer code, adapter,
checkpoint, or model-card quality update is included.

Reviewed commit: `c7cb099` (main at review time).

## Source inventory: before / after

| | Before | After |
| --- | --- | --- |
| Academic works | 25 | 34 |
| Implementation / doc sources | 8 | 8 |
| Total rows | 33 | 42 |

Nine works were added (all `implementation_status = Adjacent`, none reimplemented),
with title / authors / date verified against arXiv:

| Work | arXiv | Category | Relationship |
| --- | --- | --- | --- |
| LoRA | 2106.09685 | adapter_actuator | Adjacent |
| AdaLoRA | 2303.10512 | adapter_actuator | Adjacent |
| PCGrad (Gradient Surgery) | 2001.06782 | multi_objective_balance | Adjacent |
| MGDA (MTL as MOO) | 1810.04650 | multi_objective_balance | Adjacent |
| PICARD | 2109.05093 | constrained_decoding | Adjacent |
| Grammar-Aligned Decoding | 2405.21047 | constrained_decoding | Adjacent |
| Min-p sampling | 2407.01082 | constrained_decoding | Adjacent |
| DeepSeekMath / GRPO | 2402.03300 | verifiable_training | Adjacent |
| TAB-PO | 2603.00025 | local_preference | Adjacent |

## Duplicate / alternate-URL handling

- Each new `uri` is a fresh arXiv `abs` URL, checked against the existing 33 rows;
none collides. The adapter family already present (DoRA, PiSSA, MoLoRA, PermDoRA,
and the PEFT LoRA doc row) is distinct from the LoRA / AdaLoRA papers, and
DeepSeekMath / GRPO (2402.03300) is distinct from DeepSeek-R1 (2501.12948).
- No new paper duplicates an existing work under an alternate URL; the repo
convention keeps arXiv as `uri` and any secondary link in `metadata.alternate_urls`.
- `test_local_decision_source_manifest_is_complete` asserts unique `source_id` and
unique `uri` across all 42 rows, required provenance metadata on every row, and the
`{Adapted, Adjacent}` status vocabulary (nothing claimed Faithful).

## Documents updated

- `src/slm_training/resources/autoresearch/local-decision-sources.json` — nine rows
plus an honest `source_scope`.
- `docs/design/local-decision-interventions.md` — separation-of-concerns invariants,
owners plus the no-second-stack rule, the E249–E284 falsification chain and current
blocker, the `DecisionEventV2` first-contract note, and a dated Measured-status note.
- `docs/design/research-lineage.md` — refreshed local-decision entry; new works
labeled Adjacent.
- `docs/design/quality-experiment-matrix.md` — an LDI0 index (no claimed rows, no
reserved E-IDs).
- `tests/test_autoresearch/test_harness.py` — updated counts and stronger assertions.

## Honesty statement

No model or ship claim. This iteration is documentation and a source inventory. The
E249–E284 chain remains the authoritative measured record; the current blocker —
stable grammar-state support is necessary but not sufficient for the objective — is
recorded, not resolved. `python -m scripts.repo_policy` passes and the focused
source-manifest test is green.
82 changes: 82 additions & 0 deletions docs/design/iter-ldi0-02-decision-events-v2-20260717.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# LDI0-02 — DecisionEventV2 (state / action-evidence / objective-view)

Date: 2026-07-17
Status: **schema + materializers + V1 migration, with tests; no event mining,
no trainer change, no checkpoint, and no model-quality or ship claim.**

## What and why

`DecisionEventV2` (`src/slm_training/harnesses/preference/decision_events_v2.py`)
replaces V1's frozen `good_token_ids` / `bad_token_ids` payload as the *primary*
semantic corpus contract with a three-part model that separates concerns V1
conflated — the fix for the E284 blocker (*stable grammar-state support does not
imply objective/action-partition support*):

* **`DecisionStateV2`** — the exact, replayable model decision state plus immutable
runtime identities. Its `state_id` is a canonical `content_sha` over state and
identity **only** (never labels, rollout outcomes, or candidate order), and
generalizes V1's TwoTower-only `canvas_ids`+`position` shape to `twotower` and
`causal` (prefix) tracks.
* **`ActionOutcomeV2`** — append-only, per-candidate verifier evidence. The complete
ordered **G0–G12** gate vector is preserved verbatim (validated, never
set-collapsed). Merge deduplicates by content identity, not array order.
* **`ObjectiveView`** — a pure, versioned materialization of one state's action
table. Five materializers: `pareto`, `thresholded`, `single_best_worst`,
`set_valued` (all `trainable=True`), and `constraint_shadow`
(`trainable=False` — a semantic trainer must refuse legality-only evidence).

`migrate_v1_event` performs a one-way, deterministic, idempotent V1→V2 migration
that marks partial evidence **incomplete** and never fabricates rollout/verifier
vectors. V1 corpora and their loaders are untouched.

## Fixture-corpus demonstration

The executable version of this walk-through is
`tests/test_harnesses/preference/test_decision_events_v2.py` (26 tests). One exact
state with two independently-observed actions:

1. **One exact state** — a `DecisionStateV2` for a `component` decision with
`legal_action_ids = (4, 9, 10)`. Its `state_id` is fixed by the state/identity
fields; constructing it twice yields the same id
(`test_two_label_samples_of_one_state_share_one_state_id`), and it is unchanged
by how action evidence is later ordered or augmented
(`test_state_id_is_independent_of_action_evidence_order_and_augmentation`).
2. **Multiple independently replayed actions** — action `4` observed with reward
`0.9`, action `9` with reward `0.1`, each carrying its own complete G0–G12
vector; a re-observation of identical evidence collapses under the append-only
merge, new evidence appends
(`test_append_only_merge_dedups_by_content_not_order`).
3. **Two materializers, different views from the same evidence** — `pareto` labels
`good={4}`, `bad={9}`, `unobserved={10}` and is trainable; `constraint_shadow`
labels `good={}`, `bad={}`, `ambiguous={4,9}` and is **not** trainable
(`test_pareto_view_is_trainable_and_partitions_actions`,
`test_constraint_shadow_view_is_not_trainable`).
4. **Stable state fingerprint, changing objective fingerprint** — the manifest
(`decision_state_manifest`) fingerprints states, action evidence, and objective
views separately and order-independently
(`test_manifest_fingerprints_are_separate_and_order_independent`): re-ordering
the evidence rows leaves the outcome fingerprint unchanged, while the state,
outcome, and view fingerprints differ from one another.

## Validation (fail-closed)

Enforced and tested: unknown record fields rejected; a tampered `state_id`
rejected; `split` must derive from `group_id`; a TwoTower state requires
`canvas_ids`, a causal state requires `context_ids`; every present verifier vector
must carry the complete ordered G0–G12 gate set with valid statuses; objective-view
partitions must be disjoint; a materializer rejects an outcome whose `state_id`
does not match the state; atomic, duplicate-safe JSONL writes.

## Honest scope / caveats

- **No model or ship claim.** This is a corpus/record schema plus pure
materializers and a migration. No event is mined, no trainer consumes V2 yet, no
checkpoint or eval is produced.
- **Named independent-judge rationale** beyond the G11 gate status, and a
full model-driven **logit-replay** integration fixture (versus the schema-level
causal/TwoTower state construction covered here), are the honest follow-ons; the
state records already carry the prefix/canvas + policy/tokenizer/decode/verifier
identities required to replay.
- Verified with `pytest tests/test_harnesses/preference/test_decision_events_v2.py`
(20) and `tests/test_harnesses/preference/test_local_decisions.py` (V1 unchanged,
11); `ruff` and `python -m scripts.repo_policy` clean.
96 changes: 96 additions & 0 deletions docs/design/iter-ldi0-03-objective-support-admission-20260718.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# LDI0-03 — objective-support admission and bounded diagnostics

Date: 2026-07-18
Status: **objective-support admission gate, bounded-diagnostic runner, the Tier-1
objective-geometry pass, the Tier-2 refuse-full-parameter interface, and a V1
objective-signature trainer-entry refusal all landed with tests. The V2
`admit_semantic_corpus` CLI wiring (`--require-admission` / `--materializer`) remains
follow-on. No training, checkpoint, model-quality, or ship claim.**

## Why this exists

E283 repaired every held-out grammar-**state** support signature, yet E284 still
found **35 held-out objective conflicts**: the FTPO objective depends on the
sampled bad-action set, which is *not* part of the state-support signature, so a
corpus can pass state support while its objective (action-partition) support is
deficient. E285 and E286 then tried a more exact profile but blew the experiment
envelope and produced **invalid evidence**:

- **E285** — no cumulative wall-clock deadline; ran past 25 minutes, operator-stopped,
**no report** → invalid evidence.
- **E286** — chunked batched vector-Jacobian products; killed at 283.62 s by the
five-minute envelope, **no report**; the implementation was removed rather than
retained on a fast unit test.

Both are marked invalid historical evidence here; no metric, comparison, or training
decision may be inferred from them.

## Support criteria compared

| Criterion | Keys on | Catches E284? |
| --- | --- | --- |
| V1 state support (`decision_support_signature`) | decision kind + legal tokens + **good** tokens | No — excludes the sampled negatives |
| V1 objective signature (`decision_signature`) | + **bad** tokens | Diagnoses it, but not wired as an admission gate |
| **V2 objective-view support** (`objective_view_support`, this issue) | materializer id/config hash + **good/bad** partition, split-aware | **Yes** — held-out objective signatures without train support fail admission |

The V2 gate is the fix: `admit_semantic_corpus` fails closed before training when a
corpus (a) contains a non-trainable view (e.g. the `constraint_shadow` diagnostic),
(b) carries a materializer that does not match the requested objective, or (c) lacks
train support for any held-out objective signature — naming what is missing so
support can be repaired (never by copying held-out programs).

## Bounded runtime (the E285/E286 fix)

`decision_diagnostics.run_bounded_stages` runs diagnostic stages under one cumulative
`DiagnosticBudget` (default and hard cap five minutes), read through a `time`
reference so a deterministic fake clock drives the tests. On expiry the run is
`expired` with **`result: None`** — no partial result is ever presented as a
diagnostic result — and a full-parameter Tier-2 request is refused as
`not_authorized` rather than replaying the invalid E285 full-parameter profile.
`write_diagnostic_report` persists reports atomically (mkstemp + fsync + os.replace).

## Landed in this iteration

- `src/slm_training/harnesses/preference/decision_events_v2.py`:
`objective_view_signature`, `objective_view_support`, `admit_semantic_corpus`.
- `src/slm_training/harnesses/preference/decision_diagnostics.py`: `DiagnosticBudget`,
`Deadline`, `run_bounded_stages`, `not_authorized_report`, `write_diagnostic_report`,
and — on that bounded runner — `tier1_objective_geometry` and
`tier2_subspace_gradients`.
- `tier1_objective_geometry` reads already-materialized objective views (`getattr` on
`good_action_ids` / `bad_action_ids`, so it stays decoupled from
`decision_events_v2`) and reports, per corpus, the count of states with an
objective **contradiction** (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 the per-state good-action sets. It computes no gradient and 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.
- A V1 objective-signature pre-flight refusal now guards `train_local_from_paths`
(`require_objective_support=True`): `objective_signature_support` (keyed on the
good+bad `decision_signature`) fails the entry before the checkpoint is loaded when
a held-out objective signature lacks train support — the E284 blocker.
- Tests: the E284 pattern (passes state support, fails objective support),
constraint-shadow and materializer-mismatch refusals
(`tests/test_harnesses/preference/test_decision_events_v2.py`), the deterministic
fake-clock deadline / no-result-on-expiry / not-authorized cases plus the Tier-1
contradiction/agreement and Tier-2 refuse/plan cases
(`tests/test_harnesses/preference/test_decision_diagnostics.py`), and the trainer
objective-support refusal (`tests/test_harnesses/preference/test_local_decisions.py`).
`ruff` and `python -m scripts.repo_policy` clean.

## Honest remaining scope

- Wiring the **V2** `admit_semantic_corpus` gate into `train_local_from_paths` (and a
`--require-admission` / `--materializer` CLI flag) so the semantic trainer refuses a
non-admitted corpus — a materializer mismatch or a non-trainable view — before the
first optimizer step, mirroring the existing `constraint_shadow` refusal. The V1
objective-signature refusal already landed here covers the sampled-negative (E284)
case; the V2 gate additionally covers materializer identity.
- The Tier-2 gradient computation itself (the deferred model stage) and the richer
Tier-1 logit-space content (parent legal-space good/bad mass and margins, dominance
under raw vs unit-normalized scaling, held-out signature distances) that build on the
bounded runner landed here.
- These are the next commits. This iteration adds no token/component special cases,
runs no training, and makes no model-quality claim.
Loading
Loading