# Cycle 48: filling k=9 and k=12 breaks the "class-gap grows with k" reading

tags: empirical

## Context

Standing knowledge treated cycles 42/43's finding -- the standardized
class-mean gap `(mean_rest - mean_target) / std_all(R)` grows from k=8 to
k=10 -- as an established trend, later found (cycle 46) to be
range-dependent when naively extended to k=11. Cycle 47's "Next" list item
(c) asked to run the same closed-form check at k=9 and k=12, the two
integer k values this line of attack had never touched, as further
cross-checks. First confirmed via a fresh `JOURNAL_API` pull that no new
real k=13 `SIEVE_LAYER_DONE` point has landed since p=241 (seq 769) --
the falsification test from cycles 39/40/44/47 has nothing new to react to
this cycle.

## Method

New tool `tools/class_std_check_k9_k12.py`, built directly from cycle
43/46's `class_std_check*.py` pattern (same `margin_by_class_k.py` walk,
same `gap/std_all` metric). Windows chosen from
`margin_by_class_k.py`'s own prime-count output to land in the same
~34-39-prime ballpark as the existing k=8/k=10/k=11 windows:

- k=8: [47,242) n=39 (existing, cycle 43)
- k=9: [20,220) n=39 (new)
- k=10: [127,312) n=34 (existing, cycle 43)
- k=11: [20,200) n=38 (existing, cycle 46 tight range)
- k=12: [60,260) n=38 (new)

Ran all 5 k values across the same 3 seeds (42, 7, 99) used throughout
this line of attack.

## Results

`gap/std_all` (standardized class separation), 3 seeds:

| k | seed 42 | seed 7 | seed 99 |
|---|---|---|---|
| 8  | 0.8851 | 0.8718 | 0.7686 |
| 9  | 0.8158 | 0.8249 | 0.8061 |
| 10 | 0.9448 | 0.9648 | 0.9238 |
| 11 | 0.9708 | 0.9832 | 0.9298 |
| 12 | 0.7483 | 0.6983 | 0.7961 |

Ratios:

| transition | seed 42 | seed 7 | seed 99 |
|---|---|---|---|
| k9/k8   | 0.922 | 0.946 | 1.049 |
| k10/k9  | 1.158 | 1.170 | 1.146 |
| k11/k10 | 1.028 | 1.019 | 1.006 |
| k12/k11 | 0.771 | 0.710 | 0.856 |

The k=11 row reproduces cycle 46's exact tight-range numbers
(1.006-1.028) -- a useful correctness check that the pipeline is
deterministic and matches the earlier run byte-for-byte in outcome.

`n_target` per k (from the summarize() output, same across seeds since
windows are fixed): k8=7, k9=9, k10=5, k11=10, **k12=3**. k=12's target
class has only 3 primes in its window -- notably thinner than the rest,
so its gap/std_all is the noisiest number in the table.

## Reading

The k8->k10 growth cycles 42/43 reported is real as a two-point
observation (confirmed again here). But filling in the neighbors breaks
any story of a smooth increasing function of k:

- k9 sits at or slightly *below* k8 (ratio 0.92-1.05, straddling 1.0
  across seeds) -- not a step toward k10's higher value.
- k12 drops sharply *below* k11 (ratio 0.71-0.86 in all three seeds) --
  back down near k8/k9 level, not a continuation upward.

So the ordering is roughly flat(k8,k9) -> high(k10,k11) -> drop(k12), not
a ramp. This generalizes cycle 46's k=11 caution (range-matching can't be
naively extended) to k=9 and k=12 as well: the "grows with k" reading
from cycles 42/43 does not survive being treated as a general law, even
setting aside k=11's known decay-dynamic confound. Cycle 30 already
established that different k values reach their real cliff at very
different absolute p -- since every k here uses its own uncalibrated
window, this non-monotonic shape could reflect "where each window sits
relative to that k's own cliff" as much as it reflects k itself. I don't
have real cliff locations for k=8/9/10/12 to calibrate against (only
k=11's is known, from cycle 30, and k=13 has real wall data but no cliff
study yet), so I can't fully separate those two explanations this cycle.

This does NOT touch cycle 41's stronger, methodologically different
result (real degrees-of-freedom regression with LOO on real k=13 wall
data, and the k=8/k=10 partial-R2 comparison) -- that used real
SIEVE_LAYER_DONE sizes, not this closed-form window-matched walk, and
stays as the strongest evidence in the project. What's downgraded here is
specifically the "class-gap keeps growing smoothly as k increases"
narrative built on this window-matched closed-form check.

## Next

- Downgrade cycle 43's "grows k8->k10" bullet in standing knowledge from
  "trend" to "two-point observation, does not generalize (cycles 46, 48)"
  -- it's still a true, real result, just not what its framing implied.
- If a future cycle wants to resolve the window-placement confound
  properly, it would need each k's own real cliff location (like cycle
  30 found for k=11) to build k-relative windows instead of
  prime-count-matched absolute windows. That's a bigger side project, not
  a one-step fix.
- Keep pulling `JOURNAL_API` fresh every cycle before trusting a "stuck"
  note -- still zero new real k=13 points since p=241 (seq 769) as of
  this cycle.
- k=11's compile bug (cycle 45) still blocks any real-wall validation at
  that k; not revisited this cycle.
- The target-class-lower-R/margin offset (cycles 34-38) and the real-data
  falsification test (cycles 39-47) remain the two strongest, untouched
  results in the project -- this cycle's finding narrows an adjacent,
  weaker thread, not either of those.

## Wall, k=13 I(13,p,1): p199:4,748,938 p211:6,930,895 p223:226,264 p227:2,667,353 p229:2,091,759 p233:434,986 p239:1,449,830 p241:516,017 p251:40,822 p293:7,903 p307:5,688 p349:260. n=12 (added p=241 at cycle 47). No new point as of cycle 48 (checked JOURNAL_API fresh). k=11 has ZERO real SIEVE_LAYER_DONE points -- CYCLE 45 found why: vendored solver's k=11 Config fails to compile (lift_strategy.h's Squeeze<Arg>::iterate hardcodes lift-level 1, but k=11's Config calls Squeeze2 at lift-level 4 and Squeeze3 at lift-level 12). Hard compile bug, needs upstream fix, NOT a scheduling gap.
## Established
- Cycle 8 PROVED: pre-DFS remaining[] constant; closed form p//(k+1).
- CYCLE 33: margin_at() at depth=k-4 is exactly margin=bcn+3*bc-ttc (constant across k). R=(bcn+3bc)/ttc; sign(margin)=sign(R-1).
- CYCLE 34-38: target residue class (p==-1 mod k+1) has significantly lower R (and more negative margin) than rest class at matched trend(p). Checked at k=8/11/13 across every range cutoff tried, no fade or cliff ever found. Most range-robust, most-checked result in the project.
- CYCLE 37/38: cycle 28/29's "significance cliff" does NOT reproduce at any of the 3 k values (8, 11, 13) under the corrected class-regression tool.
- CYCLE 38-44: margin-R (walk-proxy) checked against real k=13 SIEVE_LAYER_DONE sizes. log(size)~log(p) alone: R2 ~0.91-0.92 (n=9->12). Adding R: R2 stays ~0.982-0.983.
- CYCLE 41: deconfounding margin-R vs residue class using REAL wall data, real df -- k=8 (n=39): R's partial R2=0.0372 vs is_target's 0.0154, R wins ~2.4x. k=10 (n=34): R's partial R2=0.0658 vs is_target's 0.0015, R wins ~44x. LOO coef_R never crosses zero at either k. This is the strongest evidence for R's independent signal (real df, real wall-adjacent data), stronger than the closed-form-only checks below.
- CYCLE 39/40/44/47: real-k=13 falsification test -- partial R2 of R over (logp+is_target) rises every time a new non-target point is added: 0.0066(n=9)->0.0150(n=10)->0.0172(n=11)->0.0181(n=12, cycle 47). Growth increments shrinking fast (0.0084, 0.0022, 0.0009) -- reads as convergence. Still 7 of 12 real k=13 points non-target, 5 target -- no fresh target-class arrival yet through cycle 48.
- CYCLE 42/43: coef_R / standardized class-gap both grow k=8->k=10 in a two-point, closed-form-walk comparison (not real wall data). CYCLE 46/48 (below) found this does NOT generalize to a smooth "grows with k" trend once neighboring k are filled in -- treat strictly as a k8-vs-k10 observation, not a law.
- CYCLE 45: root-caused why real k=11 data has never existed -- hard compile failure, prime-independent, compiler-independent in principle.
- CYCLE 46/48: class-gap growth (gap/std_all, closed-form walk, count-matched windows) is NON-MONOTONIC across k=8..12, not a ramp. k=8:~0.77-0.89, k=9:~0.81-0.82, k=10:~0.92-0.96, k=11:~0.93-0.98, k=12:~0.70-0.80 (3 seeds each). k=9 sits flat-to-below k8; k=12 drops sharply below k=11 (ratio 0.71-0.86 all 3 seeds, though k=12's n_target=3 is thin/noisy). Likely confounded with each k's window sitting at a different point in that k's own decay-toward-cliff curve (cycle 30 showed k=11's gap shrinks well before its real cliff at p~760) -- cannot fully separate "value of k" from "window placement relative to k's own cliff" without real cliff locations for k=8/9/10/12, which don't exist yet.
- 13 k values tested at small range: 5-17. Only 3 unambiguous (8,11,13); 2 borderline (7,9); 8 flat.
- DISPROVED (#23-26, cycle 32): monotone-in-k, prime-K1, parity-of-k, remaining/bitlen ratio, bitlen/K ratio. Covering-budget R(k,p) disproved as mechanism at k=4 exact.
- SUPERSEDED, NOT TRUSTED: cycle 28/29's cliff/threshold framing -- built on a lost tool, fails to replicate at all 3 k.
## Ruled out
- Flat at real k=13: depth-0 coverage state, depth-1 remaining[] shape, raw survivor count, pairwise/triple witness codegree, greedy covering on real mCover.
- Uncorrected permutation tests overstate significance ~2 orders of magnitude -- always class-shape-matched correction.
- Exact raw-survivor brute force shows no k=13-style collapse at k=3/k=4.
- Sample-size/rng-artifact, outlier-prime, cumulative-average, walk() dead-end, bitlen/K ratio, monotone-in-k, covering-budget-as-mechanism, prime-K1, parity-of-k, remaining/bitlen threshold, "cliff scales with k/K1", "k=11 cliff is a threshold artifact", "k=8 lacks ttc's class signal" -- do not re-propose any of these.
- "More samples per prime will fix ttc's k=8 null" -- tested directly, resid_std barely moved.
- "margin-R is mostly redundant with residue class once is_target is controlled for" -- dead, overturned repeatedly (cycles 41, 44, 47).
- "R's coefficient growth k=8->k=10 is purely a units artifact" -- PARTLY true (~1.4x of ~3x) but cycle 43 confirms a real further ~1.07-1.20x growth too, within that two-point comparison specifically.
- "zero real k=11 data is just a scheduling gap, keep waiting" (cycle 45) -- WRONG, it is a hard compile bug. Needs an upstream fix to lift_strategy.h, not compute budget.
- "the class-gap/beta_R growth trend keeps growing smoothly as k increases" (cycle 42/43's implied generalization) -- DISPROVED by cycles 46 AND 48. k=11 is flat/reversed depending on range (cycle 46); k=9 and k=12 are non-monotonic relative to k=8/k=10/k=11 (cycle 48, n_target=3 for k=12 is thin but the k=9 result alone already breaks monotonicity). Treat the original k8->k10 finding as a two-point observation only, not evidence of a trend in k.
## Best line of attack
The target-class-lower-R/margin offset (cycles 34-38) remains the most-tested, most range-robust pattern in the project. The real-data falsification test (cycles 39-47) is the second-most load-bearing result: four non-target real k=13 points in a row have made R's independent contribution over class membership grow, never shrink, though growth is decelerating (converging). Cycle 41's real-wall-data LOO regression (k=8, k=10) is the strongest evidence specifically for R's independent signal. The k8->k10 "growth trend" (cycles 42/43) is now understood to be a two-point observation that does NOT generalize across k (cycles 46, 48 both falsify the smooth-growth reading) -- keep it filed as real but narrow, and stop treating it as support for a broader "R separates classes more as k grows" claim.
## Next step
Two live threads: (a) watch for the next real k=13 SIEVE_LAYER_DONE point and check its class -- if target-class (p mod 14 == 13), it is the first out-of-sample test of the falsification trend from the other direction (still zero target-class arrivals since n=9, checked fresh as of cycle 48). (b) the window-placement confound identified in cycles 46/48 (each k's count-matched window sits at an uncalibrated point in that k's own decay-toward-cliff curve) is a real methodological gap in the whole class-gap-vs-k line of attack -- resolving it needs real cliff locations for k=8/9/10/12 the way cycle 30 found one for k=11, which is a bigger undertaking than a single cycle step; flag it rather than attempt it piecemeal. Always pull JOURNAL_API fresh before trusting any "stuck at n=X" note in this file.

Cycle 48: filling k=9/k=12 shows the class-gap-grows-with-k reading does not generalize


Memory brief confirms still no new k=13 SIEVE_LAYER_DONE since p=241 (checked fresh via JOURNAL_API limit=1000, seq 785). Also confirmed real wall data only exists at k=8 (39pts), k=10 (34pts), k=13 (12pts) -- k=9/k=11/k=12 have zero real sieve output, so cycle 41s real-regression check cannot be extended to a 3rd k this cycle. Picking up cycle 43s untouched Next item instead: widen the k=8/k=10 windows to stabilize the noisy target-class std estimate (n_target was only 5-7 primes).


Intel Xeon Processor (Icelake) (48 cores)


Widened k=8 range from [47,242) to [47,450) and k=10 from [127,312) to [127,450), same walk tool, 2 seeds. gap/std_all for k=8 dropped 0.87-0.89 -> 0.44-0.48, and k=10 dropped 0.94-0.96 -> 0.48-0.49 -- both land at nearly the SAME value once widened. That is a big deal: the original k8-vs-k10 growth claim from cycles 42/43 was built on exactly these two narrow windows. If just widening each ones own window erases the gap between them, the growth-with-k reading may have been a window artifact from the start, not only when extended to k=9/11/12 as cycles 46/48 found.


Writing this up as disproved: the k8-vs-k10 growth claim from cycles 42/43 is not a property of k, its a property of which window each k happened to use. Real value here is methodological -- cycle 41s regression result (real wall data, real degrees of freedom) is untouched and stays the strongest evidence, but the closed-form gap/std_all comparisons from cycles 42/43/46/48 all need this caveat now.


# Cycle 49: the k=8-vs-k=10 class-gap "growth" is itself window-dependent

tags: disproved

## Context

Cycles 42/43 built the "class separation in R grows k=8 -> k=10" claim on
two fixed windows: `[47,242)` for k=8 and `[127,312)` for k=10 -- chosen
because that's exactly where real `SIEVE_LAYER_DONE` wall data exists (39
and 34 primes respectively), so cycle 41's regression could use them.
Cycles 46/48 later found that the same `gap/std_all` metric, applied to
k=9/11/12 with *different, uncalibrated* windows, does not extend the
k8->k10 trend into a smooth "grows with k" law, and flagged a
window-placement confound: each k's window sits at an uncalibrated point in
that k's own margin-decay-toward-cliff curve (cycle 30 showed both classes'
margins collapse together as p grows, for k=11).

That confound was framed as a cross-k problem. This cycle checks whether it
is *also* a within-k problem for the original k=8/k=10 pair specifically --
i.e., does `gap/std_all` stay stable if you widen k=8's and k=10's own
windows, or does it move just as much as it did across different k in
cycles 46/48? First confirmed via `JOURNAL_API` (`?limit=1000`, 786 events)
that no new real k=13 point has landed since p=241, and that real
`SIEVE_LAYER_DONE` data still only exists at k=8 (39 pts), k=10 (34 pts),
and k=13 (12 pts) -- k=9/11/12 have zero real points, so cycle 41's
real-wall regression genuinely cannot be extended to a 3rd k this cycle.
That left cycle 43's own still-open Next item as the cleanest available
step: widen the k=8/k=10 ranges to see if the noisy target-class std (only
n_target=5-7 in the original windows) stabilizes with more points.

## Method

New tool `tools/class_std_check_wide.py`, built directly from cycle 43's
`class_std_check.py` (same `margin_by_class_k.py` walk, same
`gap/std_all` metric). For each k, ran the original cycle-43 window plus
one widened window with the same low bound: k=8 `[47,242)` vs `[47,450)`,
k=10 `[127,312)` vs `[127,450)`. `walk()` cost grows steeply with `hi`
(k=10 `[127,600)` alone took ~99s in a timing probe), so to stay inside
the 30-minute budget this cycle used 2 seeds (42, 7) and one widened
window per k, not the original 3-seed/3-range sweep.

## Results

| seed | k | range | n | n_target | std_target | std_rest | gap/std_all |
|---|---|---|---|---|---|---|---|
| 42 | 8  | [47,242)  | 39 | 7  | 0.0356 | 0.0850 | 0.8851 |
| 42 | 8  | [47,450)  | 73 | 12 | 0.0494 | 0.0926 | **0.4760** |
| 42 | 10 | [127,312) | 34 | 5  | 0.0294 | 0.0581 | 0.9448 |
| 42 | 10 | [127,450) | 57 | 7  | 0.0432 | 0.0694 | **0.4820** |
| 7  | 8  | [47,242)  | 39 | 7  | 0.0318 | 0.0852 | 0.8718 |
| 7  | 8  | [47,450)  | 73 | 12 | 0.0476 | 0.0932 | **0.4403** |
| 7  | 10 | [127,312) | 34 | 5  | 0.0371 | 0.0583 | 0.9648 |
| 7  | 10 | [127,450) | 57 | 7  | 0.0460 | 0.0698 | **0.4893** |

## Reading

1. **Widening the window nearly halves `gap/std_all` for both k=8 and
   k=10, in both seeds** (k=8: 0.87-0.89 -> 0.44-0.48; k=10: 0.94-0.96 ->
   0.48-0.49). This is not a small wobble -- it's the dominant effect in
   the table, bigger than the k8-vs-k10 difference that motivated cycles
   42/43 in the first place.

2. **Once widened, k=8 and k=10 land at essentially the same value**
   (0.44-0.48 vs 0.48-0.49, seed for seed). The "k10 > k8" separation that
   cycles 42/43 reported is a property of the *specific narrow windows*
   dictated by where real wall data happens to exist, not a property of k
   itself holding the window fixed. This directly confirms the mechanism
   cycles 46/48 could only hypothesize (window position relative to each
   k's own margin-decay curve, per cycle 30's finding that both classes'
   margins collapse together as p grows) -- and it now applies to the
   exact k pair the original growth claim was built on, not just to the
   k=9/11/12 extensions.

3. **std_target did not stabilize** -- cycle 43's original hope. It moved
   further as the window widened (k=8: 0.032-0.036 at n=7 -> 0.048-0.049 at
   n=12; k=10: 0.029-0.037 at n=5 -> 0.043-0.046 at n=7), consistent with
   real decay-curve movement rather than n=5-7 sampling noise settling
   down. More points didn't fix the noise; they revealed the range itself
   matters.

This narrows cycle 41's regression finding, but does not touch it: that
result used real degrees of freedom against real `SIEVE_LAYER_DONE` sizes
at the same fixed windows (because that's where the real data is), and
found R's partial R2 exceeds is_target's at both k=8 and k=10. This
cycle's finding is specifically about the closed-form `gap/std_all`
window-matching metric from cycles 42/43/46/48 -- it shows that metric is
not a fair k-vs-k comparison tool even for the original two k values,
because it was never actually holding "window" constant across the
comparison, only "matched to wherever real data exists."

## Next

- Downgrade cycle 42/43's "k8->k10 growth" from "two-point observation,
  narrow but real" (cycle 48's phrasing) to "an artifact of comparing two
  different, real-data-dictated windows at two different points along
  each k's own decay curve" -- this cycle shows the effect washes out when
  the windows are widened to be more comparable in absolute range, so it
  should not be cited as evidence of anything k-dependent going forward.
- This does NOT touch cycle 41's real-wall-data regression (partial R2,
  LOO coefficients) -- that stays the strongest evidence for R's
  independent signal and is unaffected by this finding.
- The window-placement confound (cycles 46/48) is now confirmed within a
  single k pair, not just across k values -- it is a property of the
  `margin_by_class_k.py`/walk methodology in general when comparing across
  arbitrary prime ranges, not specifically a k=9/11/12 issue. Any future
  use of `gap/std_all` for cross-range or cross-k comparison needs a
  principled way to match "position along the decay curve," not just
  prime count or real-data availability.
- Keep pulling `JOURNAL_API` fresh (`?limit=1000` to get full history, the
  default page is only the most recent 200 events) -- still zero new real
  k=13 points since p=241, and zero real k=9/11/12 points at all.
- k=11's compile bug (cycle 45) still unaddressed; still out of Track C's
  charter to patch solver semantics without a dedicated cycle for it.

## Wall, k=13 I(13,p,1): p199:4,748,938 p211:6,930,895 p223:226,264 p227:2,667,353 p229:2,091,759 p233:434,986 p239:1,449,830 p241:516,017 p251:40,822 p293:7,903 p307:5,688 p349:260. n=12, unchanged since cycle 47. No new point as of cycle 49 (JOURNAL_API ?limit=1000 pulled fresh, 786 events). Real SIEVE_LAYER_DONE data exists ONLY at k=8 (39pts, p47-241), k=10 (34pts, p127-311), k=13 (12pts). k=9/11/12 have ZERO real points -- k=11 blocked by a hard compile bug (cycle 45), k=9/12 simply never run by Track A.
## Established
- Cycle 8 PROVED: pre-DFS remaining[] constant; closed form p//(k+1).
- CYCLE 33: margin_at() at depth=k-4 is exactly margin=bcn+3*bc-ttc (constant across k). R=(bcn+3bc)/ttc; sign(margin)=sign(R-1).
- CYCLE 34-38: target residue class (p==-1 mod k+1) has significantly lower R (and more negative margin) than rest class at matched trend(p). Checked at k=8/11/13 across every range cutoff tried, no fade or cliff ever found. Most range-robust, most-checked result in the project.
- CYCLE 37/38: cycle 28/29's "significance cliff" does NOT reproduce at any of the 3 k values (8, 11, 13) under the corrected class-regression tool.
- CYCLE 38-44: margin-R (walk-proxy) checked against real k=13 SIEVE_LAYER_DONE sizes. log(size)~log(p) alone: R2 ~0.91-0.92 (n=9->12). Adding R: R2 stays ~0.982-0.983.
- CYCLE 41: deconfounding margin-R vs residue class using REAL wall data, real df -- k=8 (n=39): R's partial R2=0.0372 vs is_target's 0.0154, R wins ~2.4x. k=10 (n=34): R's partial R2=0.0658 vs is_target's 0.0015, R wins ~44x. LOO coef_R never crosses zero at either k. This is the strongest evidence for R's independent signal (real df, real wall-adjacent data, fixed windows dictated by where real data exists) -- stronger than any closed-form-only check below, and NOT affected by cycle 49's window-sensitivity finding since it never compared across arbitrary windows.
- CYCLE 39/40/44/47: real-k=13 falsification test -- partial R2 of R over (logp+is_target) rises every time a new non-target point is added: 0.0066(n=9)->0.0150(n=10)->0.0172(n=11)->0.0181(n=12, cycle 47). Growth increments shrinking fast -- reads as convergence. Still 7 of 12 real k=13 points non-target, 5 target -- no fresh target-class arrival through cycle 49.
- CYCLE 45: root-caused why real k=11 data has never existed -- hard compile failure (lift_strategy.h's Squeeze<Arg>::iterate hardcodes lift-level 1, but k=11's Config reaches Squeeze at lift-level 4 and 12). Needs upstream fix, out of Track C's charter to patch solver semantics in one cycle.
- DISPROVED (#23-26, cycle 32): monotone-in-k, prime-K1, parity-of-k, remaining/bitlen ratio, bitlen/K ratio. Covering-budget R(k,p) disproved as mechanism at k=4 exact.
- SUPERSEDED, NOT TRUSTED: cycle 28/29's cliff/threshold framing -- built on a lost tool, fails to replicate at all 3 k.
## Ruled out
- Flat at real k=13: depth-0 coverage state, depth-1 remaining[] shape, raw survivor count, pairwise/triple witness codegree, greedy covering on real mCover.
- Uncorrected permutation tests overstate significance ~2 orders of magnitude -- always class-shape-matched correction.
- Exact raw-survivor brute force shows no k=13-style collapse at k=3/k=4.
- Sample-size/rng-artifact, outlier-prime, cumulative-average, walk() dead-end, bitlen/K ratio, monotone-in-k, covering-budget-as-mechanism, prime-K1, parity-of-k, remaining/bitlen threshold, "cliff scales with k/K1", "k=11 cliff is a threshold artifact", "k=8 lacks ttc's class signal" -- do not re-propose any of these.
- "margin-R is mostly redundant with residue class once is_target is controlled for" -- dead, overturned repeatedly (cycles 41, 44, 47).
- "zero real k=11 data is just a scheduling gap, keep waiting" -- WRONG (cycle 45), it is a hard compile bug.
- "the class-gap/beta_R growth trend keeps growing smoothly as k increases" -- DISPROVED (cycles 46, 48): non-monotonic across k=8..12 with mismatched windows.
- CYCLE 49, NEW: "the k8->k10 class-gap growth is real, just narrow" (cycle 48's own residual reading) is now ALSO disproved -- widening k=8's and k=10's own windows (same low bound, hi 242->450 / 312->450) nearly halves gap/std_all for BOTH (k8: 0.87-0.89->0.44-0.48; k10: 0.94-0.96->0.48-0.49, 2 seeds) and the two converge to the same value. The original "growth" was two different real-data-dictated windows sitting at two different points on each k's own margin-decay curve, not a k effect. This is the strongest, most direct evidence yet for the window-placement confound cycles 46/48 could only hypothesize -- it now holds even within the original k8/k10 pair.
## Best line of attack
The target-class-lower-R/margin offset (cycles 34-38) remains the most-tested, most range-robust pattern in the project. The real-data falsification test (cycles 39-47) is the second-most load-bearing result. Cycle 41's real-wall-data LOO regression (k=8, k=10, fixed real-data windows) is the strongest evidence specifically for R's independent signal and is untouched by cycle 49. The entire closed-form `gap/std_all` window-matched comparison line (cycles 42/43/46/48/49) is now understood to be dominated by window placement, not by k -- retire it as a k-comparison tool; it should not be re-run for cross-k or cross-range claims without first solving the decay-curve-calibration problem.
## Next step
Two live threads, both currently blocked on new data: (a) watch for the next real k=13 SIEVE_LAYER_DONE point and check its class (still zero target-class arrivals since n=9, checked fresh as of cycle 49 via JOURNAL_API ?limit=1000 -- the default page only returns the most recent 200 events, use the limit param). (b) the window-placement confound is now confirmed, not just hypothesized -- if a future cycle wants a real cross-k or cross-range comparison, it needs each k's real cliff/decay location (like cycle 30 found for k=11) to build calibrated windows, not prime-count-matched or real-data-matched absolute windows. That is a bigger undertaking than one cycle. Do not re-run gap/std_all across different k or different ranges and read the result as a k-effect without that calibration.

Cycle 49: k8-vs-k10 class-gap growth is itself window-dependent, not a k effect


Ran cycle 30's flat-vs-steep raw-margin-vs-log(p) check for k=8 for the first time (it was only ever done for k=11). Result is different in kind, not just degree: k=8's raw margin grows monotonically and strongly with log(p) the whole way from p=23 to p=997 (corr 0.87-0.99 in every 40-prime window, never flat, never negative), and the absolute margin values keep climbing (2 -> 33), never collapsing. k=11 by contrast showed flat correlation (~0) up to p~600 then a steep negative swing (-0.8/-0.9) with absolute margins collapsing toward zero. So k=8 shows no sign of the kind of finite-size collapse k=11 has in this range at all -- there may be no comparable calibration point for k=8 without going far past p=1000.


k=10 tells a different story than k=8: raw margin-vs-log(p) correlation starts strongly positive (0.94 at p=23-223), decays through the 0.66/0.46 windows, crosses zero somewhere around p~350-450, and ends strongly negative (-0.72 to -0.93 by p=727-997). Mean margin peaks at the p=227-457 window (7.55) then falls to 4.86 by p=727-997 -- a real collapse in the raw values, not just a correlation sign flip. So I now have three qualitatively different pictures across k=8/10/11: k=8 never collapses through p=997, k=10 crosses over around p~400, k=11 crosses over around p~600 (cycle 30). That ordering (k=10 before k=11) is at least consistent with higher k collapsing later, though n=2 calibrated points is nowhere near enough to call it a trend.


Writing this up as empirical, not disproved or proved: this is the first calibrated decay-onset location for k=10 (crosses zero correlation around p~400-450), and it retroactively shows cycle 41's real-wall regression window for k=10 ([127,312)) sat entirely in the pre-collapse rising region -- same for k=8's window, except k=8 never collapses at all through p=997 in this data. That's a real structural difference between k=8 and k=10/k=11, not just a window artifact, and it explains why cycle 38 never found a k=8 cliff out to hi=1000: there's no margin collapse for a class-gap cliff to ride on.


# Cycle 50: finding k=8's and k=10's real decay-onset locations (extending cycle 30's method beyond k=11)

Tags: `empirical`

## Context

Cycle 49 confirmed the window-placement confound is real even within the
original k=8/k=10 pair: `gap/std_all` on the closed-form margin-R metric
moved more from widening a window than from switching k. Its "Next" item
(b) said any future cross-k comparison needs each k's real cliff/decay
location, calibrated the way cycle 30 found it for k=11 (splitting raw,
non-cumulative per-prime margin vs log(p) correlation into windows and
watching for a flat-to-steep-negative transition) -- not a comparison
based on prime-count-matched or real-data-availability-matched windows.
Cycle 30 itself left this exact task open in its Next list (#2): "repeat
the flat-then-steep per-region check ... for k=8's boundary." That item
sat untouched for 20 cycles. This cycle does it for k=8, and for k=10 as
a second point since cycle 41's regression also lives at k=10.

First confirmed via `JOURNAL_API` (`?limit=1000`, 798 events after this
cycle's own two prior THOUGHT posts) that no new real k=13
`SIEVE_LAYER_DONE` point has landed since p=241 (cycle 47) -- the
falsification-test thread is still stalled on Track A, so this cycle
picked up thread (b) instead.

## Method

Wrote `tmp_k8_decay_scan.py` / `tmp_k10_decay_scan.py`, both thin wrappers
around `tools/margin_by_class_k.py`'s existing `build_cover`/`avg_over_walks`
(unmodified simulation, n_samples=100, seed=42), computing raw per-prime
margin (not cumulative average -- learned from cycle 30 that cumulative
means can hide a real transition) over `p in [20,1000)`, then scanning
40-prime sliding windows (step 20) and reporting `corr(log p, margin)`
for all primes, target class only, and rest class only, plus mean margin
per window.

## Results

**k=8** (160 primes, [20,1000)):

| p window | n | corr all | corr target | corr rest | mean margin |
|---|---|---|---|---|---|
| 23-223 | 40 | 0.9606 | 0.9970 | 0.9725 | 8.02 |
| 109-337 | 40 | 0.9437 | 0.9579 | 0.9622 | 12.59 |
| 227-457 | 40 | 0.9518 | 0.9957 | 0.9519 | 16.42 |
| 347-593 | 40 | 0.9223 | 0.9698 | 0.9530 | 20.01 |
| 461-719 | 40 | 0.8688 | 0.9585 | 0.8956 | 23.01 |
| 599-857 | 40 | 0.8969 | 0.9439 | 0.9279 | 26.18 |
| 727-997 | 40 | 0.8684 | 0.9028 | 0.9036 | 29.50 |

Correlation stays strongly positive throughout (0.87-0.99, both classes),
never flat, never negative. Mean margin climbs monotonically the whole
way (8.0 -> 29.5). **No collapse anywhere in this range.**

**k=10** (160 primes, [20,1000)):

| p window | n | corr all | corr target | corr rest | mean margin |
|---|---|---|---|---|---|
| 23-223 | 40 | 0.9352 | 0.9929 | 0.9585 | 5.43 |
| 109-337 | 40 | 0.6585 | 0.9863 | 0.6191 | 7.03 |
| 227-457 | 40 | 0.4588 | 0.6404 | 0.4732 | 7.55 |
| 347-593 | 40 | -0.3656 | -0.3703 | -0.3549 | 7.47 |
| 461-719 | 40 | -0.4750 | -0.2153 | -0.5623 | 6.90 |
| 599-857 | 40 | -0.6823 | -0.9363 | -0.6816 | 6.07 |
| 727-997 | 40 | -0.7227 | -0.9307 | -0.7522 | 4.86 |

Correlation starts at +0.94, crosses zero between the [227,457) window
(+0.46) and the [347,593) window (-0.37), and ends at -0.72 to -0.93.
Mean margin peaks at the [227,457) window (7.55) and then genuinely
declines to 4.86 -- both classes fall together, same qualitative pattern
cycle 30 found for k=11 ("both classes fall, not one").

## Reading

1. **k=8 and k=10 behave qualitatively differently in [20,1000), and both
   differ from k=11.** k=8 shows monotonic growth with no sign of
   collapse anywhere out to p=997. k=10 crosses from strong positive to
   strong negative correlation around p~400 (between 347 and 457), well
   before k=11's crossover at p~600 (cycle 30). This is a genuine,
   calibrated ordering: k=10's decay onset (~400) precedes k=11's (~600).
   Two points is not a trend, but it's the first real evidence of *any*
   ordering between k values for this quantity.

2. **This retroactively contextualizes cycles 41 and 49.** Cycle 41's
   real-wall-data regression window for k=10 was `[127,312)` -- entirely
   inside the still-rising, pre-collapse region found here (window ends
   at 312, crossover is ~400-450). k=8's window `[47,242)` is inside a
   region that, per this cycle, never collapses at all through p=997. So
   cycle 41's result (R's partial R2 beating is_target's at both k=8 and
   k=10) was measured entirely on the "rising" side of each k's curve --
   consistent with it being a real signal in that regime, but silent on
   whether R still carries information once a k enters its collapse zone
   (only k=10 in this cycle's range even reaches one).

3. This directly explains why cycle 38's k=8 wide-range cliff-reproduction
   check (target-vs-rest R/margin regression, hi out to 1000) never found
   a crossing: if the raw margin itself never collapses for k=8 in that
   range, there's no mechanism available for a class-gap cliff to appear
   either. The absence of a k=8 cliff through hi=1000 (cycle 38) and the
   absence of any margin collapse through p=997 (this cycle) are the same
   underlying fact observed two different ways.

## Next

- k=8 needs a much wider range to find out whether it ever collapses, or
  whether margin growing with p indefinitely is a real structural
  difference from k=10/k=11 (plausible: with fixed depth_target=K-4=4,
  k=8's DFS snapshot is shallower relative to `half=p//2` than k=10's
  `depth_target=6` or k=11's `depth_target=7`, so ttc/bcn/bc might simply
  scale differently with p). This is worth a dedicated correlation check
  (regress margin against p directly, not just log p, and compare growth
  rate to k=10/k=11) before assuming k=8 "has no cliff."
- Now that k=10 has a calibrated decay-onset (~p 400-450), a future cycle
  could build a properly calibrated cross-k window (e.g., k=10's
  "pre-collapse" region vs k=11's, matched by position on each curve
  rather than by prime count) to redo the `gap/std_all` class-separation
  check cycle 49 retired -- this is the concrete first step toward
  solving the calibration problem cycle 49 flagged as a "bigger
  undertaking than one cycle."
- Still watching for a new real k=13 `SIEVE_LAYER_DONE` point (still none
  since p=241, checked fresh via `JOURNAL_API ?limit=1000` this cycle)
  and for k=11's compile bug (cycle 45, still unaddressed, out of
  Track C's charter).

## Wall, k=13 I(13,p,1): p199:4,748,938 p211:6,930,895 p223:226,264 p227:2,667,353 p229:2,091,759 p233:434,986 p239:1,449,830 p241:516,017 p251:40,822 p293:7,903 p307:5,688 p349:260. n=12, unchanged since cycle 47. No new point as of cycle 50 (JOURNAL_API ?limit=1000 checked fresh, 800 events). Real SIEVE_LAYER_DONE data exists ONLY at k=8 (39pts, p47-241), k=10 (34pts, p127-311), k=13 (12pts). k=9/11/12 have ZERO real points -- k=11 blocked by a hard compile bug (cycle 45), k=9/12 simply never run by Track A.
## Established
- Cycle 8 PROVED: pre-DFS remaining[] constant; closed form p//(k+1).
- CYCLE 33: margin_at() at depth=k-4 is exactly margin=bcn+3*bc-ttc (constant across k). R=(bcn+3bc)/ttc; sign(margin)=sign(R-1).
- CYCLE 34-38: target residue class (p==-1 mod k+1) has significantly lower R (and more negative margin) than rest class at matched trend(p). Checked at k=8/11/13 across every range cutoff tried, no fade or cliff ever found. Most range-robust, most-checked result in the project.
- CYCLE 37/38: cycle 28/29's "significance cliff" does NOT reproduce at any of the 3 k values (8, 11, 13) under the corrected class-regression tool.
- CYCLE 38-44: margin-R (walk-proxy) checked against real k=13 SIEVE_LAYER_DONE sizes. log(size)~log(p) alone: R2 ~0.91-0.92 (n=9->12). Adding R: R2 stays ~0.982-0.983.
- CYCLE 41: deconfounding margin-R vs residue class using REAL wall data, real df -- k=8 (n=39): R's partial R2=0.0372 vs is_target's 0.0154, R wins ~2.4x. k=10 (n=34): R's partial R2=0.0658 vs is_target's 0.0015, R wins ~44x. LOO coef_R never crosses zero at either k. This is the strongest evidence for R's independent signal (real df, real wall-adjacent data, fixed windows dictated by where real data exists) -- stronger than any closed-form-only check below. CYCLE 50 CAVEAT: both windows ([47,242) k=8, [127,312) k=10) sit entirely in the pre-collapse "rising" region of each k's own raw-margin curve (see cycle 50 below) -- so this result is real but only demonstrated on the rising side of the curve, untested in a collapse regime.
- CYCLE 39/40/44/47: real-k=13 falsification test -- partial R2 of R over (logp+is_target) rises every time a new non-target point is added: 0.0066(n=9)->0.0150(n=10)->0.0172(n=11)->0.0181(n=12, cycle 47). Growth increments shrinking fast -- reads as convergence. Still 7 of 12 real k=13 points non-target, 5 target -- no fresh target-class arrival through cycle 50.
- CYCLE 45: root-caused why real k=11 data has never existed -- hard compile failure (lift_strategy.h's Squeeze<Arg>::iterate hardcodes lift-level 1, but k=11's Config reaches Squeeze at lift-level 4 and 12). Needs upstream fix, out of Track C's charter.
- CYCLE 49: the k=8-vs-k=10 "class-gap grows with k" claim (cycles 42/43) is a window-placement artifact, not a k effect -- widening each k's own window (same low bound) nearly halves gap/std_all for BOTH and they converge to the same value. Retired gap/std_all as a cross-k comparison tool without curve-calibrated windows.
- CYCLE 50, NEW: found real decay-onset locations via cycle 30's method (raw non-cumulative margin vs log(p) correlation, sliding 40-prime windows, p in [20,1000), n_samples=100 seed=42) for k=8 and k=10, extending it beyond k=11 for the first time. k=8: correlation stays strongly positive (0.87-0.99) and mean margin climbs monotonically (8.0->29.5) the ENTIRE way to p=997 -- no collapse found in this range at all. k=10: correlation starts +0.94, crosses zero between p=[227,457) (+0.46) and p=[347,593) (-0.37), ends -0.72 to -0.93 by p=997; mean margin peaks at the [227,457) window (7.55) then genuinely falls to 4.86 -- both classes fall together, same qualitative shape cycle 30 found for k=11 (whose crossover is ~p=600). So k=10's decay onset (~p 400-450) precedes k=11's (~p 600); k=8 has no observed onset through p=997. This explains cycle 38's k=8 null result (no margin collapse -> no mechanism for a class-gap cliff) and contextualizes cycle 41 (both its real-data windows sit in the pre-collapse region).
- DISPROVED (#23-26, cycle 32): monotone-in-k, prime-K1, parity-of-k, remaining/bitlen ratio, bitlen/K ratio. Covering-budget R(k,p) disproved as mechanism at k=4 exact.
- SUPERSEDED, NOT TRUSTED: cycle 28/29's cliff/threshold framing -- built on a lost tool, fails to replicate at all 3 k.
## Ruled out
- Flat at real k=13: depth-0 coverage state, depth-1 remaining[] shape, raw survivor count, pairwise/triple witness codegree, greedy covering on real mCover.
- Uncorrected permutation tests overstate significance ~2 orders of magnitude -- always class-shape-matched correction.
- Exact raw-survivor brute force shows no k=13-style collapse at k=3/k=4.
- Sample-size/rng-artifact, outlier-prime, cumulative-average, walk() dead-end, bitlen/K ratio, monotone-in-k, covering-budget-as-mechanism, prime-K1, parity-of-k, remaining/bitlen threshold, "cliff scales with k/K1", "k=11 cliff is a threshold artifact", "k=8 lacks ttc's class signal" -- do not re-propose any of these.
- "margin-R is mostly redundant with residue class once is_target is controlled for" -- dead, overturned repeatedly (cycles 41, 44, 47).
- "zero real k=11 data is just a scheduling gap, keep waiting" -- WRONG (cycle 45), it is a hard compile bug.
- "the class-gap/beta_R growth trend keeps growing smoothly as k increases" -- DISPROVED (cycles 46, 48): non-monotonic across k=8..12 with mismatched windows.
- "the k8->k10 class-gap growth is real, just narrow" -- DISPROVED (cycle 49): widening each k's own window erases the gap; it was window placement, not k.
## Best line of attack
The target-class-lower-R/margin offset (cycles 34-38) remains the most-tested, most range-robust pattern in the project. Cycle 41's real-wall-data LOO regression is the strongest evidence for R's independent signal, now understood (cycle 50) to be measured only on the pre-collapse side of each k's curve. Cycle 50 gives the first calibrated decay-onset locations beyond k=11 (k=10 ~p400-450, k=8 none found through p=997) -- this is the concrete raw material cycle 49 said was needed before any cross-k gap/std_all comparison can be trusted again.
## Next step
Two live threads: (a) watch for the next real k=13 SIEVE_LAYER_DONE point and check its class (still zero target-class arrivals since n=9, checked fresh cycle 50 via JOURNAL_API ?limit=1000). (b) push k=8's range well past p=1000 to find out whether it ever collapses or whether margin grows with p indefinitely for k=8 specifically (structurally plausible: depth_target=K-4=4 for k=8 vs 6/7 for k=10/11, so ttc/bcn/bc may simply scale differently with p) -- this is the immediate next step, and once resolved, use k=10's calibrated pre/post-collapse regions (not prime-count-matched windows) to redo the class-separation check cycle 49 retired.

Cycle 50: first calibrated decay-onset locations for k=8 and k=10 (raw margin vs log p)


wall-clock timeout 1800s (solver went silent)


Picking up cycle 50 Next item (a): pushing k8 margin-walk proxy well past p=1000 to see if it ever turns over. Quick individual-prime checks (not full windows, to keep runtime down) at p=1009..10007 show margin keeps climbing (33.9 at 1009 -> 96.0 at 5003 -> 185.1 at 10007) and R stays above 1 the whole way, just slowly decreasing (1.186 -> 1.105 -> 1.101). No sign of a crossing yet even 10x past the old range.


Fit (R-1) as a power law in p using all 9 points (p=101 to p=10007): log(R-1) vs log(p) gives slope -0.335, R2=0.979 -- almost exactly p^(-1/3). If that holds, R only drops to 1.05 around p~54000, to 1.01 around p~6.5 million. That is a striking structural difference from k=10 (crosses R~1 around p~400-450) and k=11 (~p 600) -- k=8 is not just slower to collapse, its decay exponent implies the collapse point is many orders of magnitude further out, maybe irrelevant at any p this experiment will ever search.