issue-697: Causal context-vector patch on #537 adapters#525
Open
superkaiba wants to merge 22 commits into
Open
issue-697: Causal context-vector patch on #537 adapters#525superkaiba wants to merge 22 commits into
superkaiba wants to merge 22 commits into
Conversation
…h framing) Resolve a contradiction the #694 r2 Codex code-reviewer surfaced as a Style/Consistency note: SKILL.md's Step 10 analysis branch (~line 6037-6038) said a finding-less kind:analysis task 'self-skips cleanly inside the agent' after reaching the Step 10b/10c/10c-bis batch, while the routing entry condition two paragraphs later (~line 6045-6047) said the same finding-less task 'enters NONE of the Step 10b/10c/10c-bis batch — proceed straight to Step 10d (unchanged)'. Pick the defense-in-depth framing (plan option (b)): the outer `## Results` entry condition is PRIMARY (finding-less analysis never enters this branch and routes straight to Step 10d); the in-agent skip is reframed as a redundant defense-in-depth BACKSTOP ("even if a finding-less analysis task somehow reached this branch it would self-skip cleanly inside the agent"), preserving the related-work-finder agent's documented self-protection without contradicting the entry condition. Location 2 unchanged. Effective routing behavior is preserved — pure prose alignment.
…om origin/issue-651)
Six TDD invariants (plan §TDD / Gate C1): self-patch identity (read+gen), non-identity KV-cache propagation, patch-slot audit, patch-at-position isolation, f_CV math (both poolings), no-effect-cell sentinel. Stub module raises NotImplementedError so tests collect + fail red.
The layer-output overwrite REPLACES layer_module.forward (not a forward hook) so the patched residual is what Transformers' hidden-states recorder captures into hidden_states[L+1] — a forward hook fires after the recorder wrapper, so it propagates downstream but is invisible to output_hidden_states (the T4 / read-test invariant). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y + analysis - issue697_dispatch.py: vendor/canary/sweep/analyze phases; PASS_UNIFIED smoke=sweep-with-one-cell; --n-gpus 4 default (ft-7b 4x A100-80); per-phase cell list all derives from the same --cells subset; [phase=...] + sentinel. - issue697_cell.py: per-(B,C,seed) cross-model CV patch read (capture + P-down/P-up + 4 controls on the 14x20 panel), per-cell slot audit, persists .pt (both poolings for marker/fact) + _E.json, per-cell HF upload. - issue697_canary.py: Gate C1 (cv_patch correctness) + Gate C2 (inherited #651 Gate 7a rsLoRA parity); smoke skips C2. - issue697_analysis.py: persona-clustered bootstrap f_CV + hero 2x4 grid. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…paper_palette_role - issue697_cell.py: marker arm's behavioral E DV is now the judge-free four-float-style TF slot read (log P(※) at the post-response slot under unpatched/P-up/P-down), NOT 4x free generation — the marker DV is a teacher-forced log-prob per the #537/#651 recipe + marker-leakage rule. Removes 32 marker cells from the free-gen cost surface. - issue697_analysis.py: paper_palette_role(role) returns a single hex string per role (was mis-called as a dict). The residual behavioral-E free-gen cost (em/syc/fact over the full panel) is surfaced via epm:compute-deviation for orchestrator descope; the v-space PRIMARY f_CV pipeline is in budget (16 GPU-h / 4h wall). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ge, wire full_span + use_cache, close concerns - cv_patch: make_cv_patch_hook accepts per-position distinct replacements (dict[int,Tensor] / position-aligned 2-D) — full_span scope (concern #3); context_span_positions helper; param rename replacement_vec -> replacements. - cell.py: full_span v-condition (FT c+ at every [0..patch_pos] position); E-gen descope to source-anchor + 4 closest bystanders (compute-deviation v2); per-behavior decode knobs (em sample temp=1.0 n=5 / syc+fact greedy max=512); --use-cache threaded; raw_completions split to canonical prefix + verify; _E_metadata.json under analysis_tensors/. - canary.py: writes canary_decision.json (use_cache_production_default); marginal-parity safety net flips to uncached. - dispatch.py: reads use_cache decision + threads --use-cache; device-count preflight assert (item 5c); analyze phase runs vendored Sonnet judge. - judge.py (NEW) + vendored i537_judging.py: off-pod CPU judge, Sonnet 4.5 for em/syc/fact (supersedes #537 Haiku pin), produces {cell}_judged.json. - tests: T7/T7b multi-position replacements, T8 use_cache=False threading, T9 per-behavior decode knobs (18/18 green). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e decision and gate_7a vendor issue697_canary.py + issue697_dispatch.py run as SCRIPTS (uv run python scripts/<name>.py) where sys.path[0]=scripts/ and the `scripts.` package import idiom does not resolve. Robustly import the vendored #651 gate_7a (script-mode/package-mode try/except) and inline the canary use_cache decision path constant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dge raw-text poller The vendored i537_judging.submit_judge_batch_raw carried a hand-rolled messages.batches.create + unbounded while-True poll, which workflow_lint --check-batch-judge-client FAILs (the deadline-less poller forbidden by #658/#663). Add a sanctioned RAW-TEXT sibling submit_and_poll_batch_raw to eval/batch_judge.py (same #663 shard + expires_at deadline bound as _submit_and_poll_batch, but collects verdict text verbatim instead of parsing to a score dict — the #537 pools have their own downstream parsers) and delegate to it. Pin with 3 regression tests (raw text verbatim, error sentinel mapping, deadline bound) using the existing _DeadlineSubmitClient. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pace/P-down verdict) Closes the four binding code-review BLOCKERs from the round-2 reconciler verdict, all 0-GPU analyze-side fixes (no retrain, no sweep re-run): - full-span-not-consumed-by-analyze: _per_question_f_cv now reads conditions["full_span"], analyze() aggregates its persona-clustered CI + the last-token-vs-full-span scope delta into f_cv_summary.json, and the hero v-space row plots the full_span comparison point (plan control #4). - e-subset-uses-euclidean-not-cosine: select_e_subset ranks bystanders by cosine distance 1-cos(c_p, c_anchor) (raw pairwise per persona-distance-metrics.md; descope marker v2 mandates closest-by-#651-cosine), docstrings updated, and the chosen metric is persisted in the per-cell manifest (e_subset_metric). - e-space-analysis-not-wired: analyze() loads {cell}_judged.json (em/syc/fact) + the marker _E_metadata.json TF marker-logp records, computes f_CV^E = (E_Pup - E0)/(E+ - E0) and its P-down analog, populates f_cv_e_ci / f_cv_e_down_ci + the hero E-row (placeholder only when judged data is genuinely absent). - pdown-verdict-crosscheck-not-wired: analyze() aggregates f_cv_down, bootstraps its CI (persona-clustered), and _verdict emits patch-inconsistent when the P-up and P-down CIs disagree (plan §6.3). Adds 4 regression pins to tests/test_cv_patch.py (one per concern_id), all fail pre-fix / pass post-fix. Full cv_patch suite 22/22; lint + format clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ose marker-e-space-mean-of-ratios Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…arker + upload resilience
- §4.0 cv_patch.patched_read gains read_layer (Option B): patch hook at
patch_layer (L=10), read v at hidden_states[read_layer+1] (L=14) so the patch
propagates 4 attention layers to the response-slot read (read_layer=None keeps
the legacy same-layer behavior for the canary self-patch null). Cell threads
patch_layer (L=10) through _build_conditions/_patched_reads + asserts
patch_layer < read_layer (the v3 read-inert class); donor captured at L_patch;
capture set {7,10,14,21}; --patch-layer arg (default 10).
- §6.1 _marker_logp_at_slot returns the four-float storage contract
{log_p, z_marker, z_eos, logZ} from the same forward (im_end id 151645);
marker E records persist all four per condition.
- §4.2 _upload_cell_artifacts: per-EXPECTED-file HfApi.file_exists (not a
~64K-file list_repo_files) + _hf_retry exponential backoff on transient
5xx/timeouts (HfHubHTTPError from huggingface_hub.utils); fail-loud on 4xx /
budget exhaustion / missing file. tests/test_issue697_cell_upload.py pins it.
- §4.4 R_base cache read: _load_rbase_cache (canonical HF -> local -> inline-gen
fallback) replaces per-cell R_base regeneration; --rbase-cache-dir arg.
- §11 cosmetics: cell --max-new-tokens default 1024.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…gate + continue-on-fail + #537 ctx-gating - §4.5 issue697_rbase.py: vLLM-batched greedy R_base over the 280-prompt panel, cached + uploaded to HF. spawn multiproc method (#628 fork-poison), use_tqdm=False (#613), chunked at EPM_VLLM_GREEDY_CHUNK_SIZE (#664) with per-chunk INFO logs; EngineCore reaped before the HF parity load (coexistence); vLLM-vs-HF greedy parity gate with HF-greedy fallback on material divergence. - §4.3 phase_sweep continue-on-cell-fail: budget ceil(N/16)=4; per-cell epm:cell-failed sentinel + terminal epm:cell-failed-summary + sweep_coverage.json (failed_tuples for analyze check 11b); raise above budget. - §7.1 inert-read gate: issue697_analysis.assert_not_read_inert (v5 abs(pdn)<1e-4 threshold — the v4 abs(pdn-1.0) was non-functional). phase_inert_read_assert (7.1a) MUST detect inertness on the v3-salvaged marker_sp_swe_seed42.pt before the sweep; assert_smoke_cell_not_inert (7.1b) requires the new smoke cell's .pt be NON-inert before a production sweep dispatches. - §6.5 #537 ctx-gating: load_537_ctx_gating + cell_ctx_gating_status join eval_results/issue_537 per_row_breadth; analyze restricts the behavioral-E mapping-changed verdict to #537-context-gated cells (WARN-not-fail when absent). - §Salvage: --seed-42-only -> the 64-cell production grid (4 beh x 16 ctx x seed 42); the 4 salvaged marker cells are RE-RUN (v3 v is read-inert), not skipped. - analysis: four-float marker back-compat read (_marker_logp_value reads the new dict or the salvaged single-float). 'all' phase order = vendor -> inert_read_assert -> rbase_prep -> sweep (canary C2/C1.2 REUSED). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…off-pod HF hydration, use_cache=False default B1 (smoke-non-inert-gate-not-enforced): add phase_smoke (one real-GPU cell -> §7.1b non-inert assert -> smoke_697b_pass.json + HF upload) BEFORE sweep in the 'all' ladder; phase_sweep now REFUSES the wave loop on len(cells)>1 until a smoke-pass artifact exists with matching git SHA + read layer + non_inert=true (_assert_smoke_pass_for_sweep). A 64-cell A100 sweep can no longer start without a verified non-inert L=10/L=14 read. Test: tests/test_issue697_dispatch_smoke_gate.py. B2 (analysis-hf-artifact-hydration-missing): phase_analyze hydrates per-cell .pt + _E_metadata + raw_completions from HF (_hydrate_analyze_artifacts, canonical list_repo_files+hf_hub_download, idempotent resume-skip, fail-loud when no .pt on HF) before the glob, so off-pod analyze on a fresh VM works. Test: tests/test_issue697_analysis_hydration.py. B3 (production-use-cache-default-true): flip --use-cache + _read_use_cache_decision defaults to False; fetch the 7B canary decision from HF (gates/ then salvaged), REJECT a non-7B (0.5B-smoke) provenance for the 7B sweep, delete the local 0.5B canary_decision.json. KV caching drops the patch (parity Δ=0.25) -> uncached default protects p_up/p_down E. Test: tests/test_issue697_use_cache_decision.py. Minor: other_ctx donor rotates per persona (idx+1)%N (no self-reference). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… data only)
Single-seed (seed=42) read against the canonical issue697_cv_patch/analysis_tensors/ HF
prefix at primary layer L=14, slot pooling for fact/marker, persona-clustered bootstrap
over 4480 = 280 x 16 cells.
Headline (n=16 contexts, seed 42, P-up arm):
- fact f_CV = 0.0007 [0.0006, 0.0009] (n=4480); full_span upper bound 0.096; null floor 0.0009;
verdict = patch-inconsistent (P-up/P-down CIs disjoint at sub-0.001 level);
- marker f_CV = 0.0498 [0.0454, 0.0548] (n=4480); full_span upper bound 0.174; null floor 0.079;
f_CV^E = 0.00033 [-0.0017, 0.0022] over 16 cells; verdict = mapping-changed.
Both behaviors say the L=14 context vector does NOT carry the finetuning shift; the
context-to-behavior mapping M does. For marker, last-token f_CV (0.050) is BELOW the
random-CV null floor (0.079), so the patch literally does less than noise. The full_span
upper bound puts the context-vector-mediated share at <= 17% (marker) / <= 10% (fact);
83-90% lives in M. The behavioral DV agrees for marker (f_CV^E ~= 0); fact's f_CV^E awaits
the off-pod Sonnet judge pass.
Caveats: single seed (seed=1042 leg unrun); em is 8/16, sycophancy is 0/16 (the JOB-3
re-dispatch closes both gaps); no F4 #537-ctx-gating restriction applied (no file yet).
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
…weeps)
The original FLEX_START sweep is going to be force-deleted by the 24h fence
with 40/64 cells complete on HF canonical and 24 still to run (8 em + 16
sycophancy). Without a skip-if-exists guard, ANY resume launch (orchestrator
re-drive, autonomous-session GCP→RunPod failover, or a manual rerun) would
re-run all 64 cells from scratch — wasting ~33h of GPU time.
This adds the same skip-if-exists pattern siblings use (issue664_dispatch's
_classify_cell_hub_state + _cell_done_anywhere): a single list_repo_files
call resolves which cells already have both canonical artifacts on HF
(issue697_cv_patch/analysis_tensors/{cell_id}.pt + _E_metadata.json), and
_filter_cells_already_on_hub drops them from the dispatched list. Default
ON; --no-skip-on-hub forces the full sweep.
A failed listing call (the 504 the paginated tree endpoint occasionally
throws on huge repos) is fail-soft → proceed with the full subset, since
the per-cell create_commit is itself idempotent (re-running a complete
cell rewrites the same files).
Verified via --dry-run --seed-42-only: 40/64 cells correctly skipped,
24 cells (8 em + 16 syc) dispatched. The dispatched 24 matches the
ground truth: 8 missing em (default, binst_em, fmt_json, fmt_code,
reph_polite, reph_imp, reph_casual, icl_k8) + 16 sycophancy.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
…ur-condition logp Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…result repro The patch/ tree's *_judged.json files (Claude-Sonnet-4.5-judged per-cell EM and taught-fact behavioral reads) were uncommitted. Commit the small JSONs (22 MB total) so the clean-result footer can SHA-pin them; the 9.5 GB .pt activation tensors stay on the HF data repo per upload policy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
superkaiba
marked this pull request as ready for review
June 30, 2026 08:25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes task #697.
Causal decomposition: does finetuning a behavior into a context shift the context vector (input) or the context→behavior mapping (function)?
Substrate: #537's already-trained behavior×context LoRA adapters (no new training).
Plan: tasks/planning/697/plans/plan.md (v2 after one revise round)