One rule replaces Q44's two: every absolute path literal in the subject that
resolves inside the live data root is relocated to the same relative path inside
the per-invocation sandbox, on the parsed node's own span, wherever in the module
it sits and whatever the constant holding it is called. Q44's HELM_HOME =
assignment rewrite is subsumed, not removed; the SNAPSHOT_PATH rewrite (Q39/Q43's
mechanism) is kept. Q39's literal refusal is retired for this class and its reason
printed where the refusal stood -- the refusal's own text said the rewrite "cannot
redirect a path that is not the module constant the rule keys on", which is the
statement Q45 makes false.
Gate 2bbca218871bc5613e1fe3c4d3a84fe2e6da05ffc526e51b2865a8c8ad00ee5e (105,477 B /
1,942 lines) against Q44's 18580c102ddb1c3f (94,819 / 1,731); diff = 426 lines =
2 file headers + 7 hunk headers + 284 added + 73 removed + 60 context, sums exactly;
1,731 + 284 - 73 = 1,942. Collector byte-identical to Q44's 4e45021d80395d3f
(measured by sha256 comparison, not asserted).
Green pair 5 consecutive: rc 0, 13,312 B stdout each, 169 passed / 0 failed,
VERDICT: ALL GATES PASS. 169 = 166 + 3, unchanged from Q44 -- two new Q45 checks
plus Q44's held-directory check carried verbatim and still labelled Q44.
The five Q39 negatives still refused under both gates (all ten rc 2, live delta 0).
n5 is the class change: Q44 refuses it (stdout 0 B), Q45 admits it and lets its legs
run (stdout 575 B), still rc 2 with live delta 0.
Discriminator on a scratch protected root, rule (3) disarmed, two subjects (a
differently-named root constant; the held directory built at call time from a
literal, with HELD_DIR left in place as a decoy) x three variants (redirect armed /
disarmed / the Q44 gate blind):
armed rc 0, 169/0, the only held write in the run's own sandbox, protected delta 0
disarmed rc 1, 165/4, the held write in the protected root, protected NONZERO
q44blind rc 0, 169/0, VERDICT: ALL GATES PASS, and the held write in the protected root
Prevention separated from detection by measurement, on both shapes.
INCIDENT, disclosed in full: the first discriminator run wrote the LIVE held
directory. The subject's root literal was /root/.helm while the variant's own live
root was the scratch protected root, so the literal sat outside the gate's live
root, was never in the redirect's inventory, and the copy the legs ran still named
live. Restored byte-exact from /root/crucible/q43z/backup/held.bak by
restore_held.py, verified against the recorded digest 5b6d70716153c3f4 (120 B,
mtime_ns 1791478687099553071). ctime_ns moved to 1791846636217687791 -- the trace
of the restore, which a restore cannot undo. Three mechanical fixes followed in
this tree: make_subjects.py retargets the root literal with an asserted count;
run_negatives.py's guard() refuses any discriminator subject whose code names the
live data root (it fired during this build); abort_if_live_moved() stops the whole
run the moment a live object moves.
Four instrument defects of mine, each caught by its own measurement: the span list
visited each AST node once per ancestor (ast.walk nested inside _q39_iter_nodes),
which produced Path('<sandbox>'le/<sandbox>'le/<sandbox>'le/<sandbox>') on the
HELM_HOME line; the subject header swap stripped the original docstring's opening
triple quote; make_subjects.py's truthiness and its HELM_HOME expectation; and the
q44blind variant's PIN block reading the wrong environment variable.
Two defects in others' code, found here and not fixed here: the Q44 gate accesses
_q39_tree.body with no None guard (unexercised, so reported rather than repaired);
and Q39's _q39_live_literals list appends once per ancestor yielded, so one literal
site printed 12 times (deduped for display where Q45 reads it; Q39's list unchanged).
Live state delta 0 on all 21 rows: snapshot 14,039 B / aa842b0fd88037f8 /
mtime_ns 1791479579475780303 / ctime_ns 1791789490146606356; held pin 120 B /
5b6d70716153c3f4 / mtime_ns 1791478687099553071 / ctime_ns 1791846636217687791
(that ctime is the restore trace). Deployed /root/.helm/bin/ untouched
(ee0b36a82f23fcf3 / 7ed1bca8f9da624f / 5c67473d89283c3d). Nothing deployed, no cp,
decisions/ and inbox/ untouched, no another-party file edited, no secret.
22 KiB
Q45 — the redirect keys on the resolved value, not on a name
Screen. Every claim below carries a path, a hash, a URL, or a command with its output, or the word
unverified. Nothing secret is printed here or in the files this record lands. The long strings are paths, check names, refusal messages, sha256 digests and one URL.
1. What this item was, and what closed it
Q44's redirect keys on the literal line HELM_HOME =
(re.match(r"\s*HELM_HOME\s*=", _l)), so a subject that composes its live paths
from a differently-named root, or builds them at call time from a literal,
is outside the substitution entirely. Q45 replaces that rule with one that keys on
the resolved value:
every absolute path literal in the subject that resolves inside the live data root is relocated to the same relative path inside the per-invocation sandbox, wherever in the module it sits, and whatever the constant holding it is called.
Q44's explicit HELM_HOME = assignment rewrite is subsumed, not removed: that
line carries the literal, so the literal rule rewrites it, and every constant
composed from it follows by construction. The explicit SNAPSHOT_PATH = rewrite
(Q39/Q43's mechanism) is kept, because it is what reaches a subject with no live
literal at all.
The class is closed by construction for both of the shapes Q45 names, measured on a scratch protected root with rule (3) disarmed. §6 is the discriminator.
| artifact | bytes | lines | sha256 |
|---|---|---|---|
gate helm-selftest.py |
105,477 | 1,942 | 2bbca218871bc5613e1fe3c4d3a84fe2e6da05ffc526e51b2865a8c8ad00ee5e |
| Q44 gate (comparator) | 94,819 | 1,731 | 18580c102ddb1c3f3bd92681402f98ef02f75ee8601c72224c508f9121573c79 |
subject helm-collect.py |
29,954 | 720 | 4e45021d80395d3f03fc58d7e99610e3c1c0d2fcf9c85f1db50b16cfd2043c6c |
harness out/Q45-NEGATIVES.json |
88,622 | 1,483 | 3b317c56191f4a9961dc6c8d82bc5fadec563c5040374fba7a280c072afd223c |
figures out/Q45-FIGURES.json |
— | — | 5be33be4d0156a28dd74bdfd9c17ca708dce9813067ab8e7fbf7ec3b904c434d |
The subject collector is byte-identical to Q44's — measured, not asserted
(collector_identical_to_q44: true in out/Q45-FIGURES.json, by comparing the
two files' sha256). Every change in this item is in the gate.
diff -u Q44 gate → Q45 gate = 426 lines = 2 file headers + 7 hunk headers +
284 added + 73 removed + 60 context, and the decomposition sums to the total
(sums: true). 1,731 + 284 − 73 = 1,942 exactly. Rule for the decomposition,
printed because reply 28 was returned against Q44 for getting it wrong: added =
lines starting + minus the +++ header; removed = - minus ---; the
remainder is @@ hunks plus context.
Scratch tree /root/crucible/q45/. Nothing deployed, no cp into
/root/.helm/bin/, no production path touched, decisions/ and inbox/
untouched, no another-party file edited, no secret printed.
2. The mechanism
Two functions, both defined before the Q39 scan that feeds them, because the scan's result becomes the redirect's inventory.
_q45_live_root = _q39_live_resolved.parent.parent # /root/.helm
def _q45_rel(_lit):
"""<lit> rebased onto the live data root, or None if it sits outside it."""
# normpath, not resolve(): the literals are already absolute and normalised,
# and resolve() would follow a symlink out of the comparison.
_q45_constants(_tree) visits every string Constant exactly once, skipping
bare string statements (docstrings) — the same exclusion that keeps the deployed
collector's prose, which names the live path in a comment, out of the scan.
_q45_rewrite(_src_text, _target_root, _snapshot_dest=None) returns
(text, report):
- every
SNAPSHOT_PATH =line is rewritten to_snapshot_destwhen one is given (Q39/Q43's mechanism, unchanged); - every absolute literal resolving inside the live root is rewritten to the same
relative path under
_target_root, on the parsed node's own span (lineno/col_offset/end_col_offset), so the edit is anchored on the AST rather than on a text search and a literal that also occurs inside a docstring is left alone.
The report carries the inventory, the span count, and the spans left uncovered with the reason, so the gate prints what it did instead of asserting that it did it.
What one rule covers. On the deployed collector the inventory is one literal,
/root/.helm at line 29, one span relocated:
HELM_HOME = Path("/root/.helm") -> HELM_HOME = Path('<sandbox>')
SNAPSHOT_PATH = HELM_HOME / "data" / … -> follows (composed)
HELD_DIR = HELM_HOME / "data" / "held" -> follows (composed)
_STACK_ROOT = Path("<root>") takes the same rewrite as HELM_HOME =, and
Path("<root>") / "data" / "held" inside a function body takes the same
rewrite on the literal it shares with the module constant.
Q39's literal refusal is retired for this class, and its reason is printed
where the refusal stood. The refusal's own text said the rewrite "cannot
redirect a path that is not the module constant the rule keys on" — that is
exactly the statement Q45 makes false. The literals become the redirect's
inventory and the subject is admitted. What the redirect does not cover is a
root resolved at runtime from __file__, an environment variable or argv, where
there is no literal to rewrite; that class is caught by the module-constant check
(§4, check 2), by the per-leg watch and by rule (3). The refusal is re-pointed,
not deleted.
The probe copy carries the redirect too. Before Q45 the probe's rewrite
touched only SNAPSHOT_PATH, so a subject whose destination was a literal ran
the probe against the live path; Q39's literal scan refused such a subject at
admission, which is why that hole was never measured. The redirect makes the
probe safe on the class, which is what retires the refusal.
3. The green pair
Five consecutive invocations, HELM_COLLECTOR=/root/crucible/q45/helm-collect.py python3 /root/crucible/q45/helm-selftest.py, run from /root/crucible/q45/:
| run | rc | stdout | verdict | seconds | sha256 of the log |
|---|---|---|---|---|---|
| green-1 | 0 | 13,312 B | 169 passed, 0 failed / ALL GATES PASS |
12.20 | c02adfda1704eea0… |
| green-2 | 0 | 13,312 B | same | 12.10 | 10972472d772db66… |
| green-3 | 0 | 13,312 B | same | 12.20 | 51b42c964868bed8… |
| green-4 | 0 | 13,312 B | same | 12.10 | 389a04e41d2fd1fd… |
| green-5 | 0 | 13,312 B | same | 12.33 | deef0ded4a09ac77… |
169 = 166 + 3, unchanged from Q44's count. The three Q44 slots are now two
Q45 checks plus Q44's held-directory check carried verbatim and still labelled
Q44, so a reader can see which check is new and which is carried.
The Q45: foot line, green run 1:
Q45: 1 live-data-root literal(s) in the inventory (/root/.helm@line 29),
1 literal span(s) relocated into the sandbox
/root/crucible/q45/helm-legs-<…>, 0 left in the copy, 0 uncovered;
the copy's path-valued module constants: HELD_DIR=<sandbox>/data/held,
HELM_HOME=<sandbox>, PROFILES_DIR=/root/.hermes/profiles,
SNAPSHOT_PATH=<sandbox>/data/snapshot.json,
STANDUP_DIR=/root/troupe-standup/checkins,
TIMMY_REPO=/root/timmy-talking-turd
(6 of 13 module constants are paths; the non-path ones -- the redaction table,
the roster, the schema string -- are not printed, because a gate log is not the
place for them); the live held directory /root/.helm/data/held holds 1 file(s),
unchanged (sha, mtime_ns and ctime_ns compared)
PROFILES_DIR, STANDUP_DIR and TIMMY_REPO are deliberately not relocated:
they are outside the live data root, so they are not in the inventory, and the
redirect does not touch what it does not protect.
4. The two Q45 checks
Check 1 — every live-data-root literal in the subject is relocated in the copy the legs run. Condition: the residual (the copy re-parsed) is empty and nothing is uncovered. The inventory size is printed on every path, because the check is vacuous for a subject carrying no live literal at all and a vacuous pass must be visible rather than silent — the Q34 lesson.
Check 2 — no module-level constant of the copy resolves inside the live data
root. Measured by a subprocess that imports the copy and prints every
module-level name's value; the gate fails on any that resolves inside the live
root. This is the behavioural half and it is what catches a root the literal rule
could not rewrite (composed at runtime from __file__, an environment variable or
argv). It is a value, not a source marker.
Q44's check 3 — the live held directory is unchanged by every leg in the run,
censused on bytes, sha256, mtime_ns and ctime_ns before any leg and again at
the foot — is carried verbatim, label included. ctime is in the census because
it is the stamp a restore cannot undo (Q43's discriminator).
5. The five Q39 negatives, still refused
Each fixture run under both gates, HELM_COLLECTOR=<fixture>:
| fixture | Q45 gate | Q44 gate | live delta (Q45) |
|---|---|---|---|
n1-incident-shape |
rc 2, stdout 0 B | rc 2, stdout 0 B | 0 |
n2-traceback |
rc 2, stdout 0 B | rc 2, stdout 0 B | 0 |
n3-decoy |
rc 2, stdout 0 B | rc 2, stdout 0 B | 0 |
n4-comment-only |
rc 2, stdout 0 B | rc 2, stdout 0 B | 0 |
n5-live-literal |
rc 2, stdout 575 B | rc 2, stdout 0 B | 0 |
n5 is the class change, and it is the point of the item. Q39 refused it
(Q39 REFUSAL: the subject collector … names the live destination as an absolute literal … No leg is executed.). Q45 admits it, relocates the literal, and
lets its legs run — the Q39 NOTE now reads 1 distinct site(s). Q39 REFUSED this class; Q45 redirects it, so the literal(s) become the redirect's inventory and the subject is admitted. Its rc is still 2 and its live delta still 0, so
admitting the class costs nothing measurable; the 575 B of stdout is the legs
running where before nothing ran.
Q39's admission machinery is otherwise untouched: the behavioural probe, the per-leg watch and rule (3) all still fire, and n1–n4 are refused exactly as before.
6. The discriminator
Two subjects, both the real collector with exactly one thing changed, built
by make_subjects.py:
| subject | change | bytes / lines | sha256 |
|---|---|---|---|
subjects/collector-altroot.py |
HELM_HOME → _STACK_ROOT, whole word, 3 → 0 occurrences |
30,833 / 736 | fc51eb0986e5b25e139df75ba2d7478be24fa8518b33ae4df31995aaee5a43a6 |
subjects/collector-calltime.py |
pin_stackchain() composes its held directory at call time from a literal; the HELD_DIR constant stays, still composed from HELM_HOME, and is a decoy nothing on the write path reads |
31,021 / 741 | aa1d73d112cf1674f4a1550cae7c40a3986c0cfb4f47149b88ef7c2114b3681b |
A synthetic fixture cannot be the gate's subject — the suite exercises the collector's whole interface, and a fixture that stubs it measures the stub. That was tried first and is logged in §8.
Three variants per subject, built by make_variants.py:
| variant | gate | rule (3) | redirect target | watch |
|---|---|---|---|---|
armed |
Q45 | disarmed | the per-invocation sandbox | armed |
disarmed |
Q45 | disarmed | the protected root | disarmed |
q44-blindspot |
Q44 | disarmed | n/a (Q44's own) | disarmed |
The watch is disarmed in the last two on purpose: a detect-and-restore watch
restores the very write the discriminator measures, which is how a measurement
ends up proving nothing. The measurement is the harness's own before/after census
on (bytes, sha256, mtime_ns, ctime_ns).
All six rows, protected = the scratch root, censused around every invocation:
| row | rc | passed | held write lands in | protected held | live / live held |
|---|---|---|---|---|---|
q45-armed-collector-altroot |
0 | 169 passed, 0 failed |
<sandbox>/data/held/… |
0 | 0 / 0 |
q45-armed-collector-calltime |
0 | 169 passed, 0 failed |
<sandbox>/data/held/… |
0 | 0 / 0 |
q45-disarmed-collector-altroot |
1 | 165 passed, 4 failed |
<protected>/data/held/… |
NONZERO | 0 / 0 |
q45-disarmed-collector-calltime |
1 | 165 passed, 4 failed |
<protected>/data/held/… |
NONZERO | 0 / 0 |
q45-q44blind-collector-altroot |
1 | 167 passed, 2 failed |
<protected>/data/held/… |
NONZERO | 0 / 0 |
q45-q44blind-collector-calltime |
0 | 169 passed, 0 failed |
<protected>/data/held/… |
NONZERO | 0 / 0 |
The Q45-PIN: / Q44-PIN: line in each row is where "the write landed" is read
from, and both readings are on one line rather than two runs:
q45-armed-collector-altroot Q45-PIN: rc=0 … pinned e40308e573d046d7… ->
/root/crucible/q45/variants/helm-legs-oountx_s/data/held/stackchain-home.html.sha256
… sandbox held=120 B / sha256 676fede2c29a381a… / mtime_ns 1791847039674987167
… protected held=114 B / sha256 b58d2d0eb9f45862b… / mtime_ns 1791478687000000000
q45-disarmed-collector-altroot Q45-PIN: rc=0 … pinned e40308e573d046d7… ->
/root/crucible/q45/protected/data/held/stackchain-home.html.sha256
… sandbox held=absent; protected held=120 B / sha256 9b65871d6d8b44dd…
/ mtime_ns 1791847054218188403 / ctime_ns 1791847054222188733
Prevention separated from detection by measurement, on both shapes. Armed, the
run is green (169 passed, 0 failed, VERDICT: ALL GATES PASS) and the only held
write in the process tree is inside the run's own sandbox, with the protected root
delta 0 on all four census fields. Disarmed, the same shape lands in the protected
root with a nonzero mtime_ns and ctime_ns.
The sharpest row is q45-q44blind-collector-calltime: rc 0, 169 passed, 0 failed, VERDICT: ALL GATES PASS, and the held write lands in the protected
root. The pre-Q45 gate reports green while the class writes outside the sandbox.
That is the blind spot Q45 closes, stated by the gate's own verdict rather than by
argument.
The two disarmed rows fail 4 checks and the two q44blind rows fail 2 and 0
respectively; those reds are the expected measurement of a disabled or absent
mechanism, not defects. In q44blind-collector-calltime nothing fails at all,
which is the finding.
Live state, delta 0 on all 21 rows. Snapshot 14,039 B / sha256
aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d / mtime_ns
1791479579475780303 / ctime_ns 1791789490146606356, before and after every
invocation (live_delta != 0: none, live_held_delta != 0: none). The live root
is never named by any subject or variant — run_negatives.py's guard() refuses
one that does, and it fired during this build (§8).
7. Limits, stated rather than buried
- The redirect keys on literals, so a root with no literal is not covered.
HELM_HOME = Path(__file__).resolve().parent, or any root read from an environment variable or argv, has nothing to relocate. Check 2 catches the consequence (a module constant resolving inside the live root fails the run), the per-leg watch catches an actual write after the fact, and rule (3) catches a leg that names the live path in argv. Prevention for that class is not claimed. - The
q44blindvariant disarms Q39's literal refusal, rule (3) and the watch together, so its rows are not a statement about the shipped Q44 gate — they are a statement about Q44's redirect on a class it cannot see, with the three other guards moved out of the way. The shipped Q44 gate refuses the class outright (§5,q44-neg-n5-live-literal: rc 2, stdout 0 B). - Check 1 is vacuous for a subject with no live literal. The inventory size is printed on every path so the vacuity is visible. No subject this gate runs is in that class, and the record does not claim a rate for subjects it has not seen.
- The redirect relocates, it does not sanitise. A subject that writes to a path derived from a relocated literal writes inside the sandbox, which is the intent; the sandbox is removed at exit and 0 paths were left behind by any green run.
- Byte counts, hashes and timings are dated readings (2026-10-12, ~23:00Z).
The
Q45-PIN:line's pin digeste40308e5…is the current live Stackchain body's normalised digest, which is a property of the remote page, not of this run. - Not exercised: the timeout branch in
_q45_rewrite's caller, and a multi-line path literal (recorded asuncoveredwith a reason rather than silently skipped). No path literal in any subject this gate runs spans lines.
8. This run's own defects, logged first
The incident: the first discriminator run wrote the LIVE held directory. Restored byte-exact; disclosed in full.
The subject's root literal was /root/.helm, while the variant's own live root
was the scratch protected root. So the literal sat outside the gate's live
root, was never in the redirect's inventory, and the copy the legs ran still
named live. All six discriminator rows in that run re-wrote
/root/.helm/data/held/stackchain-home.html.sha256 (live_held_delta: NONZERO on
every row); the live snapshot was untouched (live_delta: 0 on every row).
Restored by restore_held.py from /root/crucible/q43z/backup/held.bak, which
carries the exact original line. The restore is verified, not trusted: the
backup's 120 bytes hash to 5b6d70716153c3f4bd82045d5d71edf88f793a240ce1275c3dfca5759d0ee297,
which is the digest every prior tick recorded, and the script refuses to restore
if it does not match. Post-restore: 120 B / 5b6d7071… / mtime_ns
1791478687099553071, VERDICT: RESTORED BYTE-EXACT. ctime_ns moved to
1791846636217687791 — the trace of the restore, which a restore cannot undo
(Q43's discriminator). The bytes, size and mtime are exact; the inode's change
time is not recoverable.
Three mechanical fixes followed, all in this tree:
make_subjects.pyretargets the root literal to the scratch protected root, asserting the occurrence count before and after. This is not part of the class under test — it is the discipline Q43/Q44 already carry ("on a scratch protected path, never the live one"), which this run skipped.run_negatives.py'sguard()refuses any discriminator subject whose code names the live data root, using the same walk the redirect uses (string Constants outside bare string statements), so a subject's docstring may discuss the live root in prose without tripping it. It fired during this build and stopped the run.run_negatives.py'sabort_if_live_moved()stops the whole run the moment a live object moves, restoring the held pin from the backup first. Restoring alone is not enough — the run that caused it keeps going and causes it again.
The guard deliberately does not apply to the five negative-control fixtures,
whose whole purpose is to name the live path; what is under test there is that the
gate refuses them, and the backstop is the measured refusal plus
abort_if_live_moved.
Four instrument defects, each found by its own measurement:
- The span list visited each AST node once per ancestor.
_q39_iter_nodesyields a node and its children, so nestingast.walkinside it reaches aConstantonce per ancestor — harmless for a dict (Q39 dedupes withsetdefault), fatal for a span list. The first rewrite producedPath('<sandbox>'le/<sandbox>'le/<sandbox>'le/<sandbox>')on theHELM_HOMEline. Fixed with_q45_constants, a single-pass walk, used by both the inventory and the span list. - The subject header swap stripped the original's first line to make room,
and that line is the opening
"""of the module docstring — so the docstring body came back unterminated, the closing"""opened a new string, and everything after it (an em-dash) was read as code. Fixed by prepending. make_subjects.py's truthiness and expectation were both wrong (ok &= bool(...)on aPosixPath;HELM_HOMEexpected 1 where the call-time subject keeps all 3). Both caught by the builder's own assertions.- The
q44blindvariant's PIN block readQ45_PROTECTED_ROOTwhile the harness passesQ44_PROTECTED_ROOT, so it died with aKeyErrorafter the report block and never printed where the write landed — the one row whose own evidence was missing.
One defect in the pre-Q45 gate, found here and not fixed here: the Q44 gate
accesses _q39_tree.body with no None guard, so a subject that does not parse
crashes it with AttributeError: 'NoneType' object has no attribute 'body'
instead of refusing. My Q45 gate guards the same access
(_q45_copy_tree.body if _q45_copy_tree is not None else []). No subject in this
run fails to parse, so the defect is unexercised and is reported rather than
repaired — Q44's gate is not mine to edit silently.
One cosmetic defect in Q39's scan, fixed where Q45 reads it: Q39's
_q39_live_literals list appends once per ancestor yielded (the shape in defect
1), so the same literal site was printed 12 times for one site. Q39 got away with
it because the list only fed a refusal message; Q45 turns it into a printed
inventory, so it is deduped for display and the count is the distinct site
count. Q39's own list is unchanged.
9. What this changes for the adoption ask
The §4 pair is now collector 4e45021d80395d3f… + gate
2bbca218871bc561… (superseding Q44's 18580c102ddb1c3f…). Q40's finding is
unchanged and is the reason the cp matters: the deployed gate 7ed1bca8… reads
HELM_COLLECTOR zero times (grep -c HELM_COLLECTOR /root/.helm/bin/helm-selftest.py → 0), so it has no subject-selection path at
all and none of Q31–Q45's protection is in production until the pair lands.
Q7, measured: after this item the Helm lane's executable set is empty again. Q9 waits on the checksum handover, Q13 and Q19 on Alexander, Q42 is zephyrus-sparkborn's, and the adoption is the same human call. No new item opened. The one follow-on this run would name if the lane re-opens: check 2 catches a root the literal rule cannot rewrite, but only after the copy is built — resolving every path the subject declares at runtime, rather than every literal it declares statically, is the stronger form and is not built.
— Merlin