Skip to content

Commit 8fd2eb3

Browse files
derek73claude
andcommitted
Say what the forced insertion is worth, in numbers that were measured
Third pass at this comment, and the first two both overstated the same half from samples too small to carry the claim. What it said and what measurement says: * "the conversion from sampled to fired is 100%" -- it is about four in five (350 of 450 aligned examples over 24 randomized runs of 250). The conclusion it supported was right and is kept; the number is gone, replaced by the decline paths, which are all the stage deciding: a FAMILY_COMMA opts the stage out, or an earlier script-written token takes the surname site -- a bare drawn surname ('김 김민준'), a hangul post-nominal, or a Han token under a policy that activated HAN. That last group is what the rewrite deleted and this restores; a Latin word never takes the site (zero occurrences in 1082 aligned examples), so the note that only Latin blocks it named the one blocker that does not bite. * "13-19 [per] 250" alignment, "0-4 times" in the name, "one entry among ~30", "0-5 per run" for the peel -- measured 5.5% of draws over 20000, a couple per 250, a pool of median size 23, and 0-7 peels per randomized run. Ranges taken from a handful of runs are dropped or widened. * "roughly eight times what it was" -- follows from no measurement I can reproduce; dropped for the fire counts themselves. Leads instead with the one figure that cannot rot: instrument _split under the committed derandomize=True seed and origin/master counts zero surname splits against two peels, this tree 23 against one. One command, same answer every time. Adds what the change does NOT buy, which is the honest headline: this layer asserts totality and span-exactness only, so every behavioral mutant in the stage passes here before and after and is killed by tests/v2/pipeline/test_script_segment.py. The one defect class it can catch is span arithmetic in _split, and the peel already reached that path -- writing `base + end` as `base + end + 1`, origin/master finds it in 8 runs of 10 at a median 1561 shrink calls and 14.6 seconds, this tree in 10 of 10 at 346 calls and 3.6 seconds. And two costs that went unmentioned: the insertion drops the stage's i-is-None early return under a live configuration from 1.3% of examples to 0.1% (it survives where a drawn quote pair carries the token into a nickname), and an insertion at the end can suppress a peel, since the peel site is the last non-post-nominal token. Correction to this branch's first commit message, which is pushed and not being amended: it gave the pre-change baseline as "0-2" where the comment said 0, 1, 1, 2, 2, 4. Neither is the range -- 36 randomized runs of 250 give 0-9. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 007c6b6 commit 8fd2eb3

1 file changed

Lines changed: 78 additions & 37 deletions

File tree

tests/v2/test_properties.py

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ def test_particle_fork_is_never_double_reported(text: str) -> None:
201201
# in the same drawn `surnames`, 0.8% of draws, so the fork fires
202202
# roughly once in 900 examples (42 over 36000 measured) and the
203203
# committed 250-example seed does not reach it at all; a randomized
204-
# run is what sees it. The Han rows ride along for script_orders,
205-
# and are not inert here either -- `_policies` draws segment_scripts
204+
# run is what sees it. The Han rows ride along for script_orders, and
205+
# are not inert here either -- `_policies` draws segment_scripts
206206
# freely, so HAN is activated in 37.7% of drawn policies (measured
207207
# over 20000 draws), and an activated Han token STANDING EARLIER takes
208208
# the surname site: "欧阳 김민준" does not split, where "김민준 欧阳"
@@ -345,42 +345,83 @@ def _names_using(draw: st.DrawFn, lexicon: Lexicon,
345345
# mixed-script token the surname half correctly declines, and for
346346
# the peel it is the one shape that reaches an ASCII tail at all --
347347
# the stage bails on a wholly-ASCII original, so the non-Latin stem
348-
# is what admits '민준jr'. Both fires observed under drawn lexicons
349-
# are of exactly that shape.
348+
# is what admits '민준jr'. Every peel fire observed under a drawn
349+
# lexicon is of exactly that shape -- the committed run's is
350+
# '민준de'.
351+
# What the forced insertion below is worth, in the one number that
352+
# cannot rot: instrument _split under this test's committed
353+
# derandomize=True seed -- peel and surname split are told apart by
354+
# its tail_tag argument -- and origin/master's version of this
355+
# strategy counts ZERO surname splits against two peels, while this
356+
# one counts 23 against one. That figure is reproducible by anyone
357+
# in one command and moves only when these strategies do.
350358
# Being in the POOL is not the same as being in the NAME, and for
351-
# the surname half that gap was the whole story. Measured with the
352-
# token merely offered: over 250 examples the lexicon and policy
353-
# agree often enough (13-19 runs of 250) but the token is drawn into
354-
# the name only 0-4 times, because it is one entry among ~30 and a
355-
# name takes 1-8 pieces. Every time it IS drawn the split fires --
356-
# the conversion from sampled to fired is 100% -- so the shortfall
357-
# was sampling, never the stage. Hence the forced insertion below
358-
# rather than a wider pool.
359-
# An earlier version of this comment called the surname half
360-
# "structurally inert, not luck" on the strength of a single
361-
# derandomize=True run reporting zero. That run is one sample, and
362-
# repeating it cannot disagree with itself; randomized runs give
363-
# 0, 1, 1, 2, 2, 4. The structural part is real but narrower than
364-
# claimed: `w + "민준"` on a NON-hangul surname is a mixed-script
365-
# token whose effective_script is None, so those candidates can
366-
# never be a site whatever the policy says. Only a drawn hangul
367-
# surname makes a usable one, which is what `activatable` selects.
368-
# With the insertion the surname half measures 0, 2, 5, 6, 6, 7, 9,
369-
# 9, 10, 12, 15, 19 over twelve randomized runs of 250 -- roughly
370-
# eight times what it was, and NOT a guarantee. It cannot be one:
371-
# the insertion only fires when the drawn lexicon carries a hangul
372-
# surname AND the drawn policy activates hangul, which is about 14
373-
# draws in 250, and a run that draws few can still reach zero. What
374-
# changed is that alignment now converts to a fire every time
375-
# instead of one time in five.
376-
# The peel still rides on sampling alone (0-5 per run): it is
377-
# saturated by case rows and stage tests, so a second forced piece
378-
# was not worth the distribution shift. The mechanism generalizes
379-
# if that ever changes.
380-
# Re-measure rather than trusting these numbers: derandomize=True
381-
# is set on the test, so repeating THAT run returns the same count
382-
# forever and cannot disagree with itself. Drive these strategies
383-
# under derandomize=False to see the spread.
359+
# the surname half that gap was the whole story. Two things must
360+
# coincide before the shape is legal at all -- a HANGUL surname
361+
# drawn AND a policy that activates hangul, together 5.5% of draws
362+
# over 20000 -- and the token then has to win a place in a 1-8
363+
# piece name against a pool of median size 23. Merely offered, it
364+
# reached the name a couple of times per 250. The shortfall was
365+
# sampling, never the stage.
366+
# What that buys is COVERAGE, not detection, and the two are worth
367+
# separating because the first is the easier to oversell. This
368+
# layer asserts totality and span-exactness only, so every
369+
# BEHAVIORAL mutant in the stage -- the site's last-token scan,
370+
# shortest-first, the whole-token guard, the activation gate, the
371+
# post-nominal decline, the prefix cap, the segment remap -- passes
372+
# here with the insertion and without it, and is killed by
373+
# tests/v2/pipeline/test_script_segment.py instead. The one defect
374+
# class this layer CAN catch is span arithmetic inside _split, and
375+
# the peel already reached that path. Writing `base + end` as
376+
# `base + end + 1` and giving each tree ten randomized runs of 250:
377+
# origin/master finds it in 8 runs of 10, at a median 1561 shrink
378+
# calls and 14.6 seconds; this tree finds it in 10 of 10, at 346
379+
# calls and 3.6 seconds, and shrinks to '김민준 김' where master
380+
# shrinks to the peel's '민준van'. st.integers shrinks the
381+
# insertion index toward 0, which walks the token into the position
382+
# likeliest to fire instead of away from it.
383+
# Alignment is still not a guarantee: with the token forced in the
384+
# split fires in about four aligned examples in five (350 of 450,
385+
# over 24 randomized runs of 250). Every decline is the stage
386+
# deciding, not waste. A FAMILY_COMMA opts the stage out whole -- a
387+
# ',' piece is in the pool. Otherwise an EARLIER script-written
388+
# token takes the surname site: a bare drawn surname ('김 김민준'
389+
# leaves 김민준 unsplit -- the whole-token guard), a drawn hangul
390+
# post-nominal (the leading post-nominal decline), or a Han token
391+
# under a policy that activated HAN. A LATIN word never takes it --
392+
# 'John 김민준' still splits, zero occurrences in 1082 aligned
393+
# examples -- which is why the insertion index is drawn rather than
394+
# pinned to 0.
395+
# Two earlier versions of this comment overstated this half from
396+
# small samples -- one calling it "structurally inert, not luck" on
397+
# a single derandomize=True run reporting zero, one putting the
398+
# conversion above at 100%. So: a derandomize=True run is one
399+
# sample and cannot disagree with itself, and every randomized
400+
# figure quoted here was taken under derandomize=False instead,
401+
# which is how to re-measure them. The structural claim is real but
402+
# narrower than it was made: `w + "민준"` on a NON-hangul surname is
403+
# a mixed-script token whose effective_script is None, so those
404+
# candidates can never be a site whatever the policy says. Only a
405+
# drawn hangul surname makes a usable one, which is what
406+
# `activatable` selects.
407+
# Two shapes the insertion costs, both small, neither zero. It is
408+
# unconditional once lexicon and policy align, so the stage's
409+
# i-is-None early return under a LIVE configuration fell from 1.3%
410+
# of examples to 0.1%: it survives only where a drawn quote pair
411+
# carries the token off into a nickname, leaving segments[0] with
412+
# nothing in an activated script ("prof ' Smith 남민준 '"). And the
413+
# inserted token can SUPPRESS a peel, the peel site being the last
414+
# non-post-nominal token and this token being no post-nominal:
415+
# '김민준씨 김민준' leaves 씨 glued where '김민준 김민준씨' peels
416+
# it.
417+
# The peel gets no forced piece of its own -- it is saturated by
418+
# case rows and stage tests, so a second one was not worth the
419+
# distribution shift -- and its count here is a lottery either way
420+
# (0-7 per randomized run of 250). On net the insertion nudges it
421+
# UP, by a route worth knowing: a hangul token makes the original
422+
# non-ASCII, which lifts the stage's ASCII bail off Latin tails
423+
# that are otherwise unreachable -- under honorific_tails={'a'},
424+
# 'John la' does not peel and '김민준 la' does.
384425
# sorted for the same reason `vocab` above is: frozenset iteration
385426
# order is not stable across runs, and an unsorted pool shifts
386427
# every index sampled_from draws -- which would defeat

0 commit comments

Comments
 (0)