Refine argument-taint roadmap: origin-guard works, propagator 1->0 is next bug

ober

a2a8aa260593bb873e76de8e72fd977288cb5826

diff --git a/HANDOFF_OPUS_4_8.md b/HANDOFF_OPUS_4_8.md
index 8e18d26..c438f37 100644
--- a/HANDOFF_OPUS_4_8.md
+++ b/HANDOFF_OPUS_4_8.md
@@ -225,16 +225,44 @@ languages, so closing them is the tip of the larger work:
    test5) which `field-source-taints-base-text?` won't anchor. THEN (3c)
    value-analysis (`.length`→numeric test4, `.compareTo`→numeric test10,
    string-concat test7).
-   ATTEMPTED + REVERTED (2026-06-02): a syntactic `source-token-in-sink-arg?`
-   (bare-identifier source appears as a token in the sink's argument) handled
-   `sink(wrap(x))` but is TOO SYNTACTIC — it ignores labels/requires, sanitizers,
-   and by-side-effect ordering, so it broke 7 smoke taint tests (the metavar
-   branch matched a `source($X)` argument; a propagated label-source's NAME `foo`
-   matched unrelated sinks; by-side-effect typestate sources reached every call).
-   LESSON: argument-taint must flow through the propagation graph — the call's
-   RESULT becomes a derived taint-state that respects labels/sanitizers — not a
-   text token match. A real subproject, deferred. The RECEIVER fix (3a) is
-   safe precisely because it is anchored on the source variable as the
+   ATTEMPTED + REVERTED TWICE (2026-06-02): a token-occurrence reach
+   (`source-token-in-sink-arg?`: source variable appears as a token in the sink's
+   argument / propagator RHS).
+   - v1 (purely syntactic) broke 7 smoke taint tests.
+   - v2 added the right discriminator — `original-bare-variable-source?` =
+     `(equal? origin finding)` (NOT propagated) AND `simple-identifier-text?`
+     (a bare variable) AND `(not side-effect?)`. This FIXED the labeled-propagator
+     case (a propagated label-source has origin/=finding, so its name `foo` no
+     longer spoofs unrelated sinks) and most others, and made `bad`
+     (`sink("a"+x)`) + numbers1 test7 reach. But TWO smoke cases still leak:
+     (i) `source($X)` produces a source-state whose finding is the metavar value
+     `user_input` (origin==finding, bare id) so `sink(user_input)` false-matches
+     — need to exclude metavar-bound sources (try `(null? (finding-metavars ...))`,
+     but verify the focus-param source survives it); (ii) by-side-effect typestate
+     creates a DERIVED state on `l` that isn't flagged side-effect, so `lock(l)`
+     re-reaches. Also, once args reach, booleans need their own value-analysis
+     (ok2/ok3 `Boolean.valueOf(x)` reach but aren't suppressed) — same chicken/egg
+     as numbers test8/9.
+   - v3 (cleanest so far) SPLIT sink vs propagator. The SINK-only reach
+     (`source-token-in-sink-arg?` in the two sink gates, origin-guarded) is
+     SMOKE-CLEAN (321/321) — the v2 "leaks" (i)/(ii) were RED HERRINGS from raw
+     `grep` trace-line noise; the real smoke breakers were all on the PROPAGATOR
+     path. Sink-only alone, handler-off: booleans1 now catches `bad` (18) but adds
+     FPs at ok2/ok3 (10/14, need boolean value-analysis); numbers1 still misses 40
+     (test7 is a propagator chain, not a sink arg). The PROPAGATOR clause
+     (`original-bare-variable-source?` token in the assignment RHS, in
+     `source-taints-binding?`) is what makes test7 reach AND completes numbers1
+     (test8/9 already suppressed by the numeric value-analysis 3c) — BUT it breaks
+     ONE smoke test, `Java query string taint with text fallback`, paradoxically
+     1→0 (adding an OR clause REDUCES findings: the legit `queryParams.get`→id→
+     query path disappears). That 1→0 is the real bug to chase next — likely a
+     self-taint / label-set or dedupe interaction when the propagated `id` also
+     token-matches its own RHS. NEXT: debug that 1→0 (scheme harness replicating
+     the smoke case is at /tmp/jqh.ss pattern); once fixed, sink+propagator
+     completes numbers1 handler-off. THEN boolean value-analysis for booleans1.
+   LESSON: the origin/side-effect/bare-id guard is the right discriminator;
+   sink-side is landable now, propagator-side needs the 1→0 fix. The RECEIVER fix
+   (3a) is safe precisely because it is anchored on the source variable as the
    expression's base, which a derived/label/arg occurrence can't spoof.
    The `test` rule-id group needs (2)+(3a/b/c) + best-fit-sink, getter/setter,
    lambda, jpa, FQN before its overfit clause retires. The same engine retires the