Skip to content

Feat/ts optimizer package - #8872

Open
scottweaver wants to merge 1005 commits into
QwikDev:mainfrom
scottweaver:feat/ts-optimizer-package
Open

Feat/ts optimizer package#8872
scottweaver wants to merge 1005 commits into
QwikDev:mainfrom
scottweaver:feat/ts-optimizer-package

Conversation

@scottweaver

Copy link
Copy Markdown

This set of changes sees the experimental Typescript optimizer from https://github.com/thejackshelton/TS-Optimizer to a Qwik sub-package project.

scottweaver and others added 30 commits June 1, 2026 10:32
…QwikDev#186)

* parity(OSS-410): JSX dev-info uses source-relative lineNumber/columnNumber

Production correctness fix. JSX dev-info `lineNumber:` / `columnNumber:`
emitted under Inline strategy + default-strategy segment-file paths were
body-relative (computed from a wrapped parser input) instead of source-
relative (relative to the original module file). SWC emits source-relative
positions for the same fixtures.

Two call sites parse a wrapped body before walking JSX:
  - `rewrite/inline-body.ts`     — `const __body__ = ` + body
  - `segment-codegen.ts`         — `(` + body + `)`

Without conversion the JSX walker's `lineStarts` came from the wrapper,
not the source. Threaded an opt-in `sourcePosition` on `devOptions` that
carries the original source string + body's byte offset + wrapper prefix
length. `getDevSourceSuffix` builds `lineStarts` from the original source
and converts each `nodeStart` via
  `bodyOriginOffset + (nodeStart - wrapperPrefixLen)`
before line/column lookup. Parent-rewrite path (which already passes the
original module source as the walker's `source`) is unchanged — it omits
`sourcePosition` and the legacy fast-path runs.

Convergence baseline preserved (203/212). The 3 dev-info-emitting
fixtures using these paths (`root_level_self_referential_qrl_inline`,
`example_dev_mode_inlined`, `example_dev_mode`) continue to pass via the
compareAst lineNumber/columnNumber normalizer — the snap test harness
feeds an extra leading newline (deliberate compensation in
`snapshot-parser.ts:167` for the SWC 1-indexed-BytePos vs TS 0-indexed
offset impedance on `lo:`/`hi:`), which shifts our snap output by +1 line
from SWC's. Filing a follow-up to unify the impedance (snap parser strip
2 `\n`s + lo emission +1) so the normalizer can be removed cleanly.

Capture-induced body mutation (`injectCapturesUnpacking` prepending
`const X = _captures[N];` to the body) is also out of scope here; the
documented regression tests use no-capture bodies. The mutation-aware
fix would need position tracking through the unpacking step.

6 focused regression tests at `tests/optimizer/oss-410-dev-info-line-
number.test.ts` exercise the new behavior via direct `transformModule`
calls (bypassing the snap harness):
  - Inline strategy: source-relative on single-line + multi-line bodies
  - Default strategy: source-relative on segment files
  - Column on first body line uses absolute source column
  - Non-dev mode emits no dev-info
  - Multiple JSX siblings each get distinct source-relative positions

Baselines: convergence 203/212 unchanged, full suite 952/980 (+6 new
tests from this PR).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-410): drop nested ternaries in devOptionsForCall builders

Replace `devOptions ? sourceAvail ? {...} : devOptions : undefined`
nested-ternary form with `let` + procedural `if` guard at both call
sites (`rewrite/inline-body.ts`, `segment-codegen.ts`). Nested ternaries
are hard to read; the `if`-block reads top-to-bottom.

Type-alignment side change: `InlineSegmentJsxOptions.devOptions` and
`SegmentJsxOptions.devOptions` were typed as the narrow `{ relPath:
string }` literal — the ternary form coerced through structural
widening, the `let` form preserves the variable's inferred type. Widened
both fields to the canonical `DevSuffixOptions` (from `transform/jsx.ts`)
so the spread `{ ...devOptionsForCall, sourcePosition: ... }` is the
canonical shape end-to-end. No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(CBP): add "No nested ternaries" rule to CODING_BEST_PRACTICES.md

Captures the convention enforced in the previous commit's refactor:
at most one `?:` per expression; multi-condition branching uses `let`
+ procedural `if` block. Uses the OSS-410 `devOptionsForCall` builder
as the worked example since that's what motivated the rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-445 next (QwikDev#187)

OSS-410 (JSX dev-info source-relative positions) shipped. Surface-only
fix per ticket scope — convergence 203/212 unchanged; full suite 946 →
952 (+6 new regression tests). Pivoted mid-PR: nested-ternary
`devOptionsForCall` builder refactored to procedural `let` + `if` form
after user review; new CBP rule "No nested ternaries" added under
`## Functions` + saved as `feedback_no_nested_ternaries` memory.

Follow-up filed: OSS-445 — refactor `transformAllJsx` (14 positional
args) via `JsxTransformContext` + new `TransformAllJsxOptions`. Closes
the loop on OSS-374/375/376/377's parameter-reduction sweep. STATE.md's
previous "queue closed" claim was wrong by one function.

OPTIMIZER.md audit: no update needed — type-internal change (new
opt-in `DevInfoSourcePosition` + `DevSuffixOptions` types only).
+37-line drift on `transformAllJsx` cite under the 50-line threshold;
deferred to a separate doc-only refresh PR.

Main head: 6eeed30.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kDev#188)

## What changed

`transformAllJsx` (`src/optimizer/transform/jsx.ts:793`) reduced from
14 positional args to 2 via the established `JsxTransformContext` /
options split pattern. New exported types:

- `TransformAllJsxInput` — the 4 required inputs (source, s, program,
  importedNames) that the orchestrator can't sensibly default.
- `TransformAllJsxOptions` — the 10 configurable knobs (skipRanges,
  devOptions, keyCounterStart, enableSignals=true default, qpOverrides,
  qrlsWithCaptures, paramNames, relPath, sharedSignalHoister,
  precomputedScopeBindings).

All 3 production call sites (`rewrite/index.ts`, `rewrite/inline-body.ts`,
`segment-codegen.ts`) and 3 test call sites (`tests/optimizer/jsx-
transform.test.ts`) updated. Behavior unchanged — the function body's
destructuring restores the same locals; the walk is byte-identical.

## Why beneficial in isolation

- 14 positional args at the call sites were unreadable and order-
  fragile. Each test call site was 4 args and looked fine — the prod
  call sites threaded 13-14 with multiple `undefined` placeholders.
- The previous PR (OSS-410) needed to thread a new `sourcePosition`
  through dev-info; the natural slot was inside an options object, but
  14 args forced inserting it as a nested field on `devOptions`
  instead. The next addition fits cleanly into `TransformAllJsxOptions`
  with no positional shuffling.
- Brings the orchestrator in line with the sibling JSX-family functions
  that closed OSS-374/375/376/377: `transformJsxElement` (15→3),
  `transformJsxFragment` (9→2), `processChildren` (8→3), `processProps`
  (12→3). The orchestrator was the one function that escaped the
  sweep.

## Why foundation for future work

- Closes the loop on OSS-374/375/376/377 properly. STATE.md's previous
  "queue closed" claim was wrong by one function; this PR finally makes
  it true.
- Any future addition to `transformAllJsx`'s parameter list (e.g., the
  deferred OSS-410 follow-up that needs to thread snap-parser/lo-
  emission impedance through dev-info) becomes a one-line
  `TransformAllJsxOptions` field addition instead of a positional-arg
  insertion that touches every call site.
- Removes the last inconsistency a future contributor would have to
  navigate — every JSX-family function is now context+options shaped.

## Risk

- Pure mechanical refactor; no behavior change.
- Baselines verified unchanged: convergence 203/212, full suite
  952/980 (26 failing — same baseline). Typecheck clean.
- Refactor surface narrow (5 files, 1 prod + 3 test refactor sites,
  3 prod call site rewrites).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ameter-reduction arc fully closed (QwikDev#189)

OSS-445 (transformAllJsx 14 args → 2 via input+options) shipped. Pure
mechanical refactor; baselines preserved exactly (convergence 203/212
+ full suite 952/980 unchanged). Closes OSS-374/375/376/377 properly —
`transformAllJsx` was the orchestrator that escaped the May 2025 sweep;
STATE.md's prior "queue closed" claim is now finally accurate.

OPTIMIZER.md cite refreshes folded in: `transformAllJsx` (returned at
jsx.ts:741 → :997, +256 lines past 50-line threshold); `JsxKeyCounter`
(:618–638 → :670–690, +52 lines past threshold); adjacent
`classifyConstness` (:476–605 → :513–642, +37 lines under threshold but
refreshed for section consistency).

No structural change (no phase / marker / convention / migration rule /
entry strategy / ExtractionResult field). Main head: ff11938.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…el capture analysis (QwikDev#190)

Three foundational fixes from the F10 Sub-B audit for example_qwik_router_client.
The fixture itself doesn't flip yet — two additional unblocking issues surfaced
during impl that belong to separate code paths (migration of non-marker module-
level helpers; scope-aware import DCE); filed as sub-issues of OSS-446.

Bug 1 — peer-tool jsx() context-stack push (extract.ts):
The walker already pushed tag + q-e:<event> naming context for JSX-syntax
attributes; the peer-tool form `jsx('tag', { onProp$: $() })` was missing both.
Now mirrors SWC's `handle_jsx` (transform.rs:1163–1188): tag literal/identifier
pushed at the JSX-runtime CallExpression, and Property keys inside the tagged
props ObjectExpression route through transformEventPropName for HTML tags
(strip-`$` for components). Reuses collectJsxFunctionNamesFromIterable; idle
when no JSX-runtime imports.

Bug 2 — parent-module jsx() rewrite (rewrite/index.ts):
OSS-379's transformJsxCalls was segment-only. Now also runs in the parent path
as runPeerToolJsxCallTransform — a sibling of runJsxTransform that fires
independently of the JSX-syntax `enableJsx` gate (the surfacing fixture's `.mjs`
extension short-circuited runJsxTransform). Extends transformJsxCalls to accept
skipRanges so jsx() calls inside extraction argument trees (segment-side
codegen handles those) aren't double-transformed, and to permit SpreadElement
entries in props — emitted inline in source order so compareAst's
mergeJsxSplitProps + mergeGetVarConstProps normalisers collapse SWC's
_jsxSplit(tag, varBag, constBag) into the same shape.

Bug 3 — lexical scope chain for captures (capture-analysis.ts +
transform/index.ts):
analyzeCaptures' `parentScopeIdentifiers` previously used the enclosing
extraction's body scope (when one wrapped this one) or module top-level scope
(otherwise). Both miss decls from intermediate non-marker enclosing functions
— a module-level arrow holding `useVisibleTask$(() => …)` dropped both its
param and its body's consts from captures (runtime crash; the
qwik_router_client `usePreventNavigateQrl` pattern). New
buildClosureLexicalScopes walks the program with a function-scope stack and
records the union of every enclosing scope at each closure's position;
analyzeCaptures consumes that union unconditionally. Mirrors SWC's flattened
`decl_stack` (transform.rs:986–991).

Tests: 13 new regression tests across two files
(oss-446-lexical-scope-captures.test.ts × 6; oss-446-jsx-call-naming.test.ts ×
7); all green. Convergence baseline 203/212 + full suite 952 unchanged.

Refs: OSS-446. Follow-ups: OSS-447 (migration for non-marker module-level
helpers consumed only by segments), OSS-448 (scope-aware import DCE) — both
required to flip example_qwik_router_client convergence.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oundation landed; convergence flip gated on OSS-447 + OSS-448 (QwikDev#191)

PR QwikDev#190 merged at 8aaa782. OSS-446 remains In Progress (parent of OSS-447 +
OSS-448) — the audit during impl surfaced two additional causes on separate
code paths that block the example_qwik_router_client convergence flip:

  - OSS-447: migration policy for non-marker module-level helpers consumed
    by exactly one segment (the useQwikMockRouter case).
  - OSS-448: scope-aware import DCE in filterUnusedImports (the inner-shadow
    const { jsx } = … defeats the regex-based test).

Both filed mid-impl per feedback_parity_audit_multi_root_cause. 18th
confirmed case of that pattern.

STATE.md edits:
  - Last updated bumped to reflect PR QwikDev#190 + the foundation work + the two
    follow-up sub-issues + the cite refreshes folded in here.
  - Current measurements row: head 8aaa782; baselines preserved exactly
    (convergence 203/212 + full suite 952/980 unchanged; +13 regression
    tests now in baseline).
  - Branches in flight `main` row rewritten for OSS-446 context.
  - Most recent meaningful progress: prepended OSS-446 entry, trimmed the
    11-entry-old OSS-430 bullet (back to 10).
  - What to do next: shifted from "no active workstream" to OSS-447/448 as
    the active workstream; corrected the stale F10 Sub-B 3-sub-cluster
    hypothesis (C2/C3 don't exist; the real causes are now mapped to
    OSS-446 / OSS-447 / OSS-448).
  - Recently closed: prepended OSS-446 foundation entry (note OSS-446 itself
    stays In Progress).

OPTIMIZER.md cite refreshes (drift past 50-line threshold from OSS-446 +
cumulative from prior PRs):
  - extract.ts marker-call extraction block: :863–1022 → :962–1129
  - extract.ts inlinedQrl detection: :600–745 → :815–961
  - extract.ts ExtractionBase block: :63–186 → :67–186
  - extract.ts field-table cites (origin/name/displayName/hash/
    canonicalFilename/ctxKind/ctxName/loc): all shifted ~+99 lines
  - extract.ts disambiguateExtractions: :1155–1196 → :1254–1295
  - rewrite/index.ts preConsolidateRawPropsCaptures: :394–428 → :491–540
  - rewrite/index.ts resolveNesting: :452 → :458

No structural OPTIMIZER.md changes (no phase added/removed/renumbered, no
new tool-surface convention name, no migration rule change, no entry
strategy change, no ExtractionResult field change). capture-analysis.ts
cites drifted under threshold (analyzeCaptures, collectScopeIdentifiers,
captures, captureNames, paramNames) — left as-is.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s; rewrite ticket-tour prose WHY-anchored (QwikDev#192)

* refactor(OSS-449): strip Linear ticket refs from extract.ts comments; rewrite ticket-tour prose WHY-anchored

WHAT
First file of the comment-cleanup sweep (OSS-449). Removes all 32
`OSS-XXX` references from src/optimizer/extract.ts. 3 comments deleted
outright (pure ticket-tour stickers with no WHY content). 21 comments
rewritten — sticker stripped, prose re-anchored on the invariant or
constraint the code enforces rather than the historical PR that
introduced it. SWC `transform.rs:...` cross-references kept (they
reference files committed in the repo, not external trackers).

WHY IN ISOLATION
External readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers — those are internal-only. Stripping them
makes comments self-contained and accessible to the file's actual
audience (whoever opens it).

The rewrite step beyond pure deletion is the WHY-not-WHAT cleanup.
Pre-fix comments were a mix of "what we did" (`Pre-fix the filter
excluded X; now it includes X`) and ticket-tour ("OSS-446 Bug 1: ..."),
both of which decay as code evolves. Post-fix comments state the
invariant or constraint that forced the code shape, which stays
accurate across refactors. Examples:

- "OSS-368 — deferred; populated on leave from activeSegmentBodies.bodyIds."
  → "Deferred; populated on leave from activeSegmentBodies.bodyIds."

- "OSS-386: `loc` is documented as [byteStart, byteEnd] in OPTIMIZER.md
  ... this site previously emitted [line, col] (a pre-existing semantic
  mismatch, hidden because convergence's strict-compare skips loc)."
  → "`loc` carries byte offsets, not line/col — per OPTIMIZER.md's
  documented [byteStart, byteEnd] contract that snap fixtures also
  encode."

WHY FOUNDATION
First step in the OSS-449 sweep (estimated 35 files, 243 total refs).
extract.ts is the top offender at 32 refs; getting it cleaned validates
the bucket-classification approach (3 Delete / 21 Rewrite / 0 Keep
across this file) before tackling segment-generation.ts (25 refs) +
rewrite/index.ts (21 refs) + the rest. The WHY-not-WHAT memory
(`feedback_comments_explain_why`) is now demonstrated end-to-end on a
real file — establishes the bar for future comment writing across the
codebase per the project rule encoded in CBP.

RISK
Comment-only edits — no behaviour change. Verified:
- `pnpm typecheck` clean.
- `pnpm vitest convergence --run` → 203/212 unchanged.
- `pnpm vitest run` → full suite passes (no baseline regressions per
  `ci:baseline:check`).
- `grep -rE "OSS-[0-9]+" src/optimizer/extract.ts | wc -l` → 0 (was 32).
- `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 211 (was 243).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from segment-generation.ts + rewrite/index.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second commit in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/segment-generation.ts (was 25 refs → 0)
  - src/optimizer/rewrite/index.ts (was 21 refs → 0)

3 comments deleted outright (`See OSS-NNN.` trailing reference-only
sentences with no WHY content). 40 comments rewritten — sticker
stripped, prose re-anchored on the invariant or constraint the code
enforces. SWC `transform.rs:NNN` references kept (they reference files
committed in the repo, not external trackers). Local cross-references
(`rewrite/inline-body.ts`, `buildElementCaptureMap`, etc.) kept.

WHY IN ISOLATION
Same rationale as the prior extract.ts commit (this sweep is OSS-449):
external readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers, and ticket-tour prose paraphrases the
code in ways that decay across refactors. Examples from this commit:

  - "OSS-432 Bug C: pre-compute the per-segment JSX-key starting counter
    in SOURCE order... Surfaced when Bug A + Bug B exposed the
    segment-side comparison previously masked by the parent mismatch."
    → strip the sticker AND drop the "Surfaced when Bug A + Bug B..."
    ticket-tour tail; keep "Pre-compute the per-segment JSX-key starting
    counter in SOURCE order, independent of the depth-first processing
    order used by the main loop below..."

  - "OSS-438 Fix B: propagate captures... (the original upstream-built
    map keyed by `<`-walk byte offsets had positions 524/630 while the
    walker saw 221/301)."
    → strip sticker AND drop the debugging-detail tail; keep the
    invariant: "Cross-phase positions are unreliable because every
    intervening `parseSync` overwrites the shared buffer."

WHY FOUNDATION
With extract.ts (32 refs), segment-generation.ts (25), and
rewrite/index.ts (21) all clean, the top-3 offenders in src/ are done
(78 of the original 243 refs). The bucket-classification approach has
held up across 78 individual judgement calls without surfacing any
production code where a Linear ticket reference was load-bearing
enough to warrant a GitHub mirror — consistent with the OSS-449
prediction that prod Keeps would be exceedingly rare. The remaining
~165 refs are spread across 32 files (smaller per-file volumes;
mechanical patterns).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    passing tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/segment-generation.ts | wc -l` → 0 (was 25)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/index.ts | wc -l` → 0 (was 21)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 165 (was 243)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-assembly.ts + inline-body.ts (batch 2) (QwikDev#193)

* refactor(OSS-449): strip Linear ticket refs from extract.ts comments; rewrite ticket-tour prose WHY-anchored

WHAT
First file of the comment-cleanup sweep (OSS-449). Removes all 32
`OSS-XXX` references from src/optimizer/extract.ts. 3 comments deleted
outright (pure ticket-tour stickers with no WHY content). 21 comments
rewritten — sticker stripped, prose re-anchored on the invariant or
constraint the code enforces rather than the historical PR that
introduced it. SWC `transform.rs:...` cross-references kept (they
reference files committed in the repo, not external trackers).

WHY IN ISOLATION
External readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers — those are internal-only. Stripping them
makes comments self-contained and accessible to the file's actual
audience (whoever opens it).

The rewrite step beyond pure deletion is the WHY-not-WHAT cleanup.
Pre-fix comments were a mix of "what we did" (`Pre-fix the filter
excluded X; now it includes X`) and ticket-tour ("OSS-446 Bug 1: ..."),
both of which decay as code evolves. Post-fix comments state the
invariant or constraint that forced the code shape, which stays
accurate across refactors. Examples:

- "OSS-368 — deferred; populated on leave from activeSegmentBodies.bodyIds."
  → "Deferred; populated on leave from activeSegmentBodies.bodyIds."

- "OSS-386: `loc` is documented as [byteStart, byteEnd] in OPTIMIZER.md
  ... this site previously emitted [line, col] (a pre-existing semantic
  mismatch, hidden because convergence's strict-compare skips loc)."
  → "`loc` carries byte offsets, not line/col — per OPTIMIZER.md's
  documented [byteStart, byteEnd] contract that snap fixtures also
  encode."

WHY FOUNDATION
First step in the OSS-449 sweep (estimated 35 files, 243 total refs).
extract.ts is the top offender at 32 refs; getting it cleaned validates
the bucket-classification approach (3 Delete / 21 Rewrite / 0 Keep
across this file) before tackling segment-generation.ts (25 refs) +
rewrite/index.ts (21 refs) + the rest. The WHY-not-WHAT memory
(`feedback_comments_explain_why`) is now demonstrated end-to-end on a
real file — establishes the bar for future comment writing across the
codebase per the project rule encoded in CBP.

RISK
Comment-only edits — no behaviour change. Verified:
- `pnpm typecheck` clean.
- `pnpm vitest convergence --run` → 203/212 unchanged.
- `pnpm vitest run` → full suite passes (no baseline regressions per
  `ci:baseline:check`).
- `grep -rE "OSS-[0-9]+" src/optimizer/extract.ts | wc -l` → 0 (was 32).
- `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 211 (was 243).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from segment-generation.ts + rewrite/index.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second commit in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/segment-generation.ts (was 25 refs → 0)
  - src/optimizer/rewrite/index.ts (was 21 refs → 0)

3 comments deleted outright (`See OSS-NNN.` trailing reference-only
sentences with no WHY content). 40 comments rewritten — sticker
stripped, prose re-anchored on the invariant or constraint the code
enforces. SWC `transform.rs:NNN` references kept (they reference files
committed in the repo, not external trackers). Local cross-references
(`rewrite/inline-body.ts`, `buildElementCaptureMap`, etc.) kept.

WHY IN ISOLATION
Same rationale as the prior extract.ts commit (this sweep is OSS-449):
external readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers, and ticket-tour prose paraphrases the
code in ways that decay across refactors. Examples from this commit:

  - "OSS-432 Bug C: pre-compute the per-segment JSX-key starting counter
    in SOURCE order... Surfaced when Bug A + Bug B exposed the
    segment-side comparison previously masked by the parent mismatch."
    → strip the sticker AND drop the "Surfaced when Bug A + Bug B..."
    ticket-tour tail; keep "Pre-compute the per-segment JSX-key starting
    counter in SOURCE order, independent of the depth-first processing
    order used by the main loop below..."

  - "OSS-438 Fix B: propagate captures... (the original upstream-built
    map keyed by `<`-walk byte offsets had positions 524/630 while the
    walker saw 221/301)."
    → strip sticker AND drop the debugging-detail tail; keep the
    invariant: "Cross-phase positions are unreliable because every
    intervening `parseSync` overwrites the shared buffer."

WHY FOUNDATION
With extract.ts (32 refs), segment-generation.ts (25), and
rewrite/index.ts (21) all clean, the top-3 offenders in src/ are done
(78 of the original 243 refs). The bucket-classification approach has
held up across 78 individual judgement calls without surfacing any
production code where a Linear ticket reference was load-bearing
enough to warrant a GitHub mirror — consistent with the OSS-449
prediction that prod Keeps would be exceedingly rare. The remaining
~165 refs are spread across 32 files (smaller per-file volumes;
mechanical patterns).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    passing tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/segment-generation.ts | wc -l` → 0 (was 25)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/index.ts | wc -l` → 0 (was 21)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 165 (was 243)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second batch in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/index.ts (was 19 refs → 0)
  - src/optimizer/rewrite/output-assembly.ts (was 18 refs → 0)
  - src/optimizer/rewrite/inline-body.ts (was 14 refs → 0)

2 trailing-only `See OSS-NNN.` references deleted. 46 sticker-strip
rewrites — each comment's WHY-anchored prose preserved (or refined
where it was tangled with ticket-tour fragments). Several brittle line
references (`extract.ts:696`, `rewrite/index.ts:657`, etc.) and a few
fixture-specific tail clauses (`preserves example_dev_mode_inlined
etc.`, `(example_strip_client_code)`) dropped during the rewrites —
those decay as code evolves and add no invariant content.

WHY IN ISOLATION
Same as the first OSS-449 batch (commit d1318fe + 65363b8): external
readers of an OSS project can't follow `linear.app/kunai/...` URLs or
`OSS-XXX` identifiers, and ticket-tour prose paraphrases the code in
ways that decay across refactors. Examples from this batch:

  - "OSS-407 Fix A: when body is a bare identifier... (see OSS-407 Fix
    C in placeSCalls)."
    → strip both refs; keep "When body is a bare identifier referring
    to a module-level decl... see the forward-dep handling in
    `placeSCalls`."

  - "OSS-408 Fix A: previously skipped inlinedQrl extractions on the
    grounds that 'the name was set explicitly by the upstream tool';
    but SWC ALSO renames them under prod..."
    → strip the "previously skipped" ticket-tour framing; restate as
    the invariant: "SWC renames inlinedQrl extractions under prod...
    preserving the hash suffix so runtime QRL resolution still matches."

WHY FOUNDATION
Combined with the first batch's top-3 offenders (PR QwikDev#192), this PR
brings the OSS-449 sweep to 129 of the original 243 refs cleaned
(53%). Remaining 114 refs spread across 32 smaller-volume files —
mechanical patterns established by this point should make subsequent
batches faster per file.

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/index.ts | wc -l` → 0 (was 19)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/output-assembly.ts | wc -l` → 0 (was 18)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/inline-body.ts | wc -l` → 0 (was 14)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 114 (was 165)

Stacked on top of PR QwikDev#192 (refactor/OSS-449-comment-cleanup-extract).
Will rebase onto main once QwikDev#192 merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-call-transform.ts + signal-analysis.ts + segment-codegen.ts + jsx-props.ts (batch 3) (QwikDev#194)

* refactor(OSS-449): strip Linear ticket refs from extract.ts comments; rewrite ticket-tour prose WHY-anchored

WHAT
First file of the comment-cleanup sweep (OSS-449). Removes all 32
`OSS-XXX` references from src/optimizer/extract.ts. 3 comments deleted
outright (pure ticket-tour stickers with no WHY content). 21 comments
rewritten — sticker stripped, prose re-anchored on the invariant or
constraint the code enforces rather than the historical PR that
introduced it. SWC `transform.rs:...` cross-references kept (they
reference files committed in the repo, not external trackers).

WHY IN ISOLATION
External readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers — those are internal-only. Stripping them
makes comments self-contained and accessible to the file's actual
audience (whoever opens it).

The rewrite step beyond pure deletion is the WHY-not-WHAT cleanup.
Pre-fix comments were a mix of "what we did" (`Pre-fix the filter
excluded X; now it includes X`) and ticket-tour ("OSS-446 Bug 1: ..."),
both of which decay as code evolves. Post-fix comments state the
invariant or constraint that forced the code shape, which stays
accurate across refactors. Examples:

- "OSS-368 — deferred; populated on leave from activeSegmentBodies.bodyIds."
  → "Deferred; populated on leave from activeSegmentBodies.bodyIds."

- "OSS-386: `loc` is documented as [byteStart, byteEnd] in OPTIMIZER.md
  ... this site previously emitted [line, col] (a pre-existing semantic
  mismatch, hidden because convergence's strict-compare skips loc)."
  → "`loc` carries byte offsets, not line/col — per OPTIMIZER.md's
  documented [byteStart, byteEnd] contract that snap fixtures also
  encode."

WHY FOUNDATION
First step in the OSS-449 sweep (estimated 35 files, 243 total refs).
extract.ts is the top offender at 32 refs; getting it cleaned validates
the bucket-classification approach (3 Delete / 21 Rewrite / 0 Keep
across this file) before tackling segment-generation.ts (25 refs) +
rewrite/index.ts (21 refs) + the rest. The WHY-not-WHAT memory
(`feedback_comments_explain_why`) is now demonstrated end-to-end on a
real file — establishes the bar for future comment writing across the
codebase per the project rule encoded in CBP.

RISK
Comment-only edits — no behaviour change. Verified:
- `pnpm typecheck` clean.
- `pnpm vitest convergence --run` → 203/212 unchanged.
- `pnpm vitest run` → full suite passes (no baseline regressions per
  `ci:baseline:check`).
- `grep -rE "OSS-[0-9]+" src/optimizer/extract.ts | wc -l` → 0 (was 32).
- `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 211 (was 243).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from segment-generation.ts + rewrite/index.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second commit in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/segment-generation.ts (was 25 refs → 0)
  - src/optimizer/rewrite/index.ts (was 21 refs → 0)

3 comments deleted outright (`See OSS-NNN.` trailing reference-only
sentences with no WHY content). 40 comments rewritten — sticker
stripped, prose re-anchored on the invariant or constraint the code
enforces. SWC `transform.rs:NNN` references kept (they reference files
committed in the repo, not external trackers). Local cross-references
(`rewrite/inline-body.ts`, `buildElementCaptureMap`, etc.) kept.

WHY IN ISOLATION
Same rationale as the prior extract.ts commit (this sweep is OSS-449):
external readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers, and ticket-tour prose paraphrases the
code in ways that decay across refactors. Examples from this commit:

  - "OSS-432 Bug C: pre-compute the per-segment JSX-key starting counter
    in SOURCE order... Surfaced when Bug A + Bug B exposed the
    segment-side comparison previously masked by the parent mismatch."
    → strip the sticker AND drop the "Surfaced when Bug A + Bug B..."
    ticket-tour tail; keep "Pre-compute the per-segment JSX-key starting
    counter in SOURCE order, independent of the depth-first processing
    order used by the main loop below..."

  - "OSS-438 Fix B: propagate captures... (the original upstream-built
    map keyed by `<`-walk byte offsets had positions 524/630 while the
    walker saw 221/301)."
    → strip sticker AND drop the debugging-detail tail; keep the
    invariant: "Cross-phase positions are unreliable because every
    intervening `parseSync` overwrites the shared buffer."

WHY FOUNDATION
With extract.ts (32 refs), segment-generation.ts (25), and
rewrite/index.ts (21) all clean, the top-3 offenders in src/ are done
(78 of the original 243 refs). The bucket-classification approach has
held up across 78 individual judgement calls without surfacing any
production code where a Linear ticket reference was load-bearing
enough to warrant a GitHub mirror — consistent with the OSS-449
prediction that prod Keeps would be exceedingly rare. The remaining
~165 refs are spread across 32 files (smaller per-file volumes;
mechanical patterns).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    passing tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/segment-generation.ts | wc -l` → 0 (was 25)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/index.ts | wc -l` → 0 (was 21)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 165 (was 243)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second batch in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/index.ts (was 19 refs → 0)
  - src/optimizer/rewrite/output-assembly.ts (was 18 refs → 0)
  - src/optimizer/rewrite/inline-body.ts (was 14 refs → 0)

2 trailing-only `See OSS-NNN.` references deleted. 46 sticker-strip
rewrites — each comment's WHY-anchored prose preserved (or refined
where it was tangled with ticket-tour fragments). Several brittle line
references (`extract.ts:696`, `rewrite/index.ts:657`, etc.) and a few
fixture-specific tail clauses (`preserves example_dev_mode_inlined
etc.`, `(example_strip_client_code)`) dropped during the rewrites —
those decay as code evolves and add no invariant content.

WHY IN ISOLATION
Same as the first OSS-449 batch (commit d1318fe + 65363b8): external
readers of an OSS project can't follow `linear.app/kunai/...` URLs or
`OSS-XXX` identifiers, and ticket-tour prose paraphrases the code in
ways that decay across refactors. Examples from this batch:

  - "OSS-407 Fix A: when body is a bare identifier... (see OSS-407 Fix
    C in placeSCalls)."
    → strip both refs; keep "When body is a bare identifier referring
    to a module-level decl... see the forward-dep handling in
    `placeSCalls`."

  - "OSS-408 Fix A: previously skipped inlinedQrl extractions on the
    grounds that 'the name was set explicitly by the upstream tool';
    but SWC ALSO renames them under prod..."
    → strip the "previously skipped" ticket-tour framing; restate as
    the invariant: "SWC renames inlinedQrl extractions under prod...
    preserving the hash suffix so runtime QRL resolution still matches."

WHY FOUNDATION
Combined with the first batch's top-3 offenders (PR QwikDev#192), this PR
brings the OSS-449 sweep to 129 of the original 243 refs cleaned
(53%). Remaining 114 refs spread across 32 smaller-volume files —
mechanical patterns established by this point should make subsequent
batches faster per file.

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/index.ts | wc -l` → 0 (was 19)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/output-assembly.ts | wc -l` → 0 (was 18)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/inline-body.ts | wc -l` → 0 (was 14)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 114 (was 165)

Stacked on top of PR QwikDev#192 (refactor/OSS-449-comment-cleanup-extract).
Will rebase onto main once QwikDev#192 merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from Tier 1 files (batch 3)

WHAT
Third batch in the OSS-449 sweep. Tier 1 files (≥8 refs each, 50 total):

  - src/optimizer/transform/jsx.ts (11 → 0)
  - src/optimizer/transform/jsx-call-transform.ts (11 → 0)
  - src/optimizer/signal-analysis.ts (11 → 0)
  - src/optimizer/segment-codegen.ts (9 → 0)
  - src/optimizer/transform/jsx-props.ts (8 → 0)

3 trailing-only `See OSS-NNN.` references deleted. 39 sticker-strip
rewrites preserving the WHY-anchored prose. Several fixture-name tails
(`example_strip_client_code`, `example_dev_mode`,
`example_parsed_inlined_qrls`, `example_qwik_react_inline`) and
brittle line refs dropped during the rewrites — those don't anchor
invariants. One duplicate comment block in segment-codegen.ts:727-737
collapsed to a single comment (copy-paste artifact).

WHY IN ISOLATION
Same rationale as batch 1 (extract.ts, PR QwikDev#192) and batch 2
(transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts,
PR QwikDev#193): external readers can't follow `OSS-XXX` refs, and ticket-tour
prose paraphrases code in ways that decay across refactors. Examples
from this batch:

  - "OSS-417: root-identifier substitution and constant-subtree
    simplification share the orchestrator. OSS-418 dropped the OSS-414
    paren-strip pass — raw-props no longer emits defensive parens at
    Property-value positions..."
    → strip all three refs; restate as the invariant: "raw-props doesn't
    emit defensive parens at Property-value positions — precedence-aware
    emission via `expressionNeedsParens` in `raw-props.ts` and
    `props-field-rewrite.ts` means the source slice the `_hf<n>_str`
    generator inherits is paren-free to begin with."

  - "Three semantic divergences from the pre-OSS-369 split:"
    → "Three semantic invariants this collector enforces:" — the
    divergence framing is ticket-tour (anchored to a particular code
    change); the bullets themselves are real invariants that survive
    refactors.

WHY FOUNDATION
Combined with PR QwikDev#192 + PR QwikDev#193, OSS-449 sweep is now at 179 of the
original 243 refs cleaned (74%). Remaining 64 refs across 24 files
(all ≤6 refs per file) — Tier 2 + Tier 3 batches close out the work.
Pattern has been fully mechanical across 12 files now; no Keeps
required for any production file (0 GH mirrors needed across 179
individual judgement calls).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 64 (was 114)

Stacked on top of PR QwikDev#193 (refactor/OSS-449-comment-cleanup-batch2).
Will rebase onto main once QwikDev#192 + QwikDev#193 merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kDev#195)

* refactor(OSS-449): strip Linear ticket refs from extract.ts comments; rewrite ticket-tour prose WHY-anchored

WHAT
First file of the comment-cleanup sweep (OSS-449). Removes all 32
`OSS-XXX` references from src/optimizer/extract.ts. 3 comments deleted
outright (pure ticket-tour stickers with no WHY content). 21 comments
rewritten — sticker stripped, prose re-anchored on the invariant or
constraint the code enforces rather than the historical PR that
introduced it. SWC `transform.rs:...` cross-references kept (they
reference files committed in the repo, not external trackers).

WHY IN ISOLATION
External readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers — those are internal-only. Stripping them
makes comments self-contained and accessible to the file's actual
audience (whoever opens it).

The rewrite step beyond pure deletion is the WHY-not-WHAT cleanup.
Pre-fix comments were a mix of "what we did" (`Pre-fix the filter
excluded X; now it includes X`) and ticket-tour ("OSS-446 Bug 1: ..."),
both of which decay as code evolves. Post-fix comments state the
invariant or constraint that forced the code shape, which stays
accurate across refactors. Examples:

- "OSS-368 — deferred; populated on leave from activeSegmentBodies.bodyIds."
  → "Deferred; populated on leave from activeSegmentBodies.bodyIds."

- "OSS-386: `loc` is documented as [byteStart, byteEnd] in OPTIMIZER.md
  ... this site previously emitted [line, col] (a pre-existing semantic
  mismatch, hidden because convergence's strict-compare skips loc)."
  → "`loc` carries byte offsets, not line/col — per OPTIMIZER.md's
  documented [byteStart, byteEnd] contract that snap fixtures also
  encode."

WHY FOUNDATION
First step in the OSS-449 sweep (estimated 35 files, 243 total refs).
extract.ts is the top offender at 32 refs; getting it cleaned validates
the bucket-classification approach (3 Delete / 21 Rewrite / 0 Keep
across this file) before tackling segment-generation.ts (25 refs) +
rewrite/index.ts (21 refs) + the rest. The WHY-not-WHAT memory
(`feedback_comments_explain_why`) is now demonstrated end-to-end on a
real file — establishes the bar for future comment writing across the
codebase per the project rule encoded in CBP.

RISK
Comment-only edits — no behaviour change. Verified:
- `pnpm typecheck` clean.
- `pnpm vitest convergence --run` → 203/212 unchanged.
- `pnpm vitest run` → full suite passes (no baseline regressions per
  `ci:baseline:check`).
- `grep -rE "OSS-[0-9]+" src/optimizer/extract.ts | wc -l` → 0 (was 32).
- `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 211 (was 243).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from segment-generation.ts + rewrite/index.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second commit in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/segment-generation.ts (was 25 refs → 0)
  - src/optimizer/rewrite/index.ts (was 21 refs → 0)

3 comments deleted outright (`See OSS-NNN.` trailing reference-only
sentences with no WHY content). 40 comments rewritten — sticker
stripped, prose re-anchored on the invariant or constraint the code
enforces. SWC `transform.rs:NNN` references kept (they reference files
committed in the repo, not external trackers). Local cross-references
(`rewrite/inline-body.ts`, `buildElementCaptureMap`, etc.) kept.

WHY IN ISOLATION
Same rationale as the prior extract.ts commit (this sweep is OSS-449):
external readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers, and ticket-tour prose paraphrases the
code in ways that decay across refactors. Examples from this commit:

  - "OSS-432 Bug C: pre-compute the per-segment JSX-key starting counter
    in SOURCE order... Surfaced when Bug A + Bug B exposed the
    segment-side comparison previously masked by the parent mismatch."
    → strip the sticker AND drop the "Surfaced when Bug A + Bug B..."
    ticket-tour tail; keep "Pre-compute the per-segment JSX-key starting
    counter in SOURCE order, independent of the depth-first processing
    order used by the main loop below..."

  - "OSS-438 Fix B: propagate captures... (the original upstream-built
    map keyed by `<`-walk byte offsets had positions 524/630 while the
    walker saw 221/301)."
    → strip sticker AND drop the debugging-detail tail; keep the
    invariant: "Cross-phase positions are unreliable because every
    intervening `parseSync` overwrites the shared buffer."

WHY FOUNDATION
With extract.ts (32 refs), segment-generation.ts (25), and
rewrite/index.ts (21) all clean, the top-3 offenders in src/ are done
(78 of the original 243 refs). The bucket-classification approach has
held up across 78 individual judgement calls without surfacing any
production code where a Linear ticket reference was load-bearing
enough to warrant a GitHub mirror — consistent with the OSS-449
prediction that prod Keeps would be exceedingly rare. The remaining
~165 refs are spread across 32 files (smaller per-file volumes;
mechanical patterns).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    passing tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/segment-generation.ts | wc -l` → 0 (was 25)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/index.ts | wc -l` → 0 (was 21)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 165 (was 243)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second batch in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/index.ts (was 19 refs → 0)
  - src/optimizer/rewrite/output-assembly.ts (was 18 refs → 0)
  - src/optimizer/rewrite/inline-body.ts (was 14 refs → 0)

2 trailing-only `See OSS-NNN.` references deleted. 46 sticker-strip
rewrites — each comment's WHY-anchored prose preserved (or refined
where it was tangled with ticket-tour fragments). Several brittle line
references (`extract.ts:696`, `rewrite/index.ts:657`, etc.) and a few
fixture-specific tail clauses (`preserves example_dev_mode_inlined
etc.`, `(example_strip_client_code)`) dropped during the rewrites —
those decay as code evolves and add no invariant content.

WHY IN ISOLATION
Same as the first OSS-449 batch (commit d1318fe + 65363b8): external
readers of an OSS project can't follow `linear.app/kunai/...` URLs or
`OSS-XXX` identifiers, and ticket-tour prose paraphrases the code in
ways that decay across refactors. Examples from this batch:

  - "OSS-407 Fix A: when body is a bare identifier... (see OSS-407 Fix
    C in placeSCalls)."
    → strip both refs; keep "When body is a bare identifier referring
    to a module-level decl... see the forward-dep handling in
    `placeSCalls`."

  - "OSS-408 Fix A: previously skipped inlinedQrl extractions on the
    grounds that 'the name was set explicitly by the upstream tool';
    but SWC ALSO renames them under prod..."
    → strip the "previously skipped" ticket-tour framing; restate as
    the invariant: "SWC renames inlinedQrl extractions under prod...
    preserving the hash suffix so runtime QRL resolution still matches."

WHY FOUNDATION
Combined with the first batch's top-3 offenders (PR QwikDev#192), this PR
brings the OSS-449 sweep to 129 of the original 243 refs cleaned
(53%). Remaining 114 refs spread across 32 smaller-volume files —
mechanical patterns established by this point should make subsequent
batches faster per file.

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/index.ts | wc -l` → 0 (was 19)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/output-assembly.ts | wc -l` → 0 (was 18)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/inline-body.ts | wc -l` → 0 (was 14)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 114 (was 165)

Stacked on top of PR QwikDev#192 (refactor/OSS-449-comment-cleanup-extract).
Will rebase onto main once QwikDev#192 merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from Tier 1 files (batch 3)

WHAT
Third batch in the OSS-449 sweep. Tier 1 files (≥8 refs each, 50 total):

  - src/optimizer/transform/jsx.ts (11 → 0)
  - src/optimizer/transform/jsx-call-transform.ts (11 → 0)
  - src/optimizer/signal-analysis.ts (11 → 0)
  - src/optimizer/segment-codegen.ts (9 → 0)
  - src/optimizer/transform/jsx-props.ts (8 → 0)

3 trailing-only `See OSS-NNN.` references deleted. 39 sticker-strip
rewrites preserving the WHY-anchored prose. Several fixture-name tails
(`example_strip_client_code`, `example_dev_mode`,
`example_parsed_inlined_qrls`, `example_qwik_react_inline`) and
brittle line refs dropped during the rewrites — those don't anchor
invariants. One duplicate comment block in segment-codegen.ts:727-737
collapsed to a single comment (copy-paste artifact).

WHY IN ISOLATION
Same rationale as batch 1 (extract.ts, PR QwikDev#192) and batch 2
(transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts,
PR QwikDev#193): external readers can't follow `OSS-XXX` refs, and ticket-tour
prose paraphrases code in ways that decay across refactors. Examples
from this batch:

  - "OSS-417: root-identifier substitution and constant-subtree
    simplification share the orchestrator. OSS-418 dropped the OSS-414
    paren-strip pass — raw-props no longer emits defensive parens at
    Property-value positions..."
    → strip all three refs; restate as the invariant: "raw-props doesn't
    emit defensive parens at Property-value positions — precedence-aware
    emission via `expressionNeedsParens` in `raw-props.ts` and
    `props-field-rewrite.ts` means the source slice the `_hf<n>_str`
    generator inherits is paren-free to begin with."

  - "Three semantic divergences from the pre-OSS-369 split:"
    → "Three semantic invariants this collector enforces:" — the
    divergence framing is ticket-tour (anchored to a particular code
    change); the bullets themselves are real invariants that survive
    refactors.

WHY FOUNDATION
Combined with PR QwikDev#192 + PR QwikDev#193, OSS-449 sweep is now at 179 of the
original 243 refs cleaned (74%). Remaining 64 refs across 24 files
(all ≤6 refs per file) — Tier 2 + Tier 3 batches close out the work.
Pattern has been fully mechanical across 12 files now; no Keeps
required for any production file (0 GH mirrors needed across 179
individual judgement calls).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 64 (was 114)

Stacked on top of PR QwikDev#193 (refactor/OSS-449-comment-cleanup-batch2).
Will rebase onto main once QwikDev#192 + QwikDev#193 merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from Tier 2 files (batch 4)

WHAT
Fourth batch in the OSS-449 sweep. Tier 2 files (4–6 refs each, 37 total):

  - src/optimizer/transform/event-capture-promotion.ts (6 → 0)
  - src/optimizer/transform/jsx-elements-core.ts (5 → 0)
  - src/optimizer/transform/diagnostic-detection.ts (5 → 0)
  - src/optimizer/rewrite/raw-props.ts (5 → 0)
  - src/optimizer/utils/range-replace.ts (4 → 0)
  - src/optimizer/types/brands.ts (4 → 0)
  - src/optimizer/rewrite/symbol-collision.ts (4 → 0)
  - src/optimizer/rewrite/rewrite-context.ts (4 → 0)

All sticker-strips with WHY-anchored prose preserved. Several
fixture-name tails (`example_strip_client_code`, `issue_7216_add_test`,
`example_props_optimization`, `example_spread_jsx`) and ticket-tour
fragments ("validated against...", "the case we hit during OSS-384's
call-site sweep", "tracked as a follow-up") dropped — those don't
anchor invariants.

Comparison tables and historical context were preserved where they're
genuinely load-bearing (e.g. `range-replace.ts`'s caller table, the
`brands.ts` HASH_SHAPE rationale).

WHY IN ISOLATION
Same rationale as the prior three batches (PRs QwikDev#192, QwikDev#193, QwikDev#194):
external readers can't follow `OSS-XXX` refs, and ticket-tour prose
paraphrases code in ways that decay across refactors.

WHY FOUNDATION
With this batch, the OSS-449 sweep is at 216 of the original 243 refs
cleaned (89%). Remaining 27 refs across 16 small-volume files (Tier 3,
mostly 1–3 refs each) — one more PR closes out the sweep.

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 27 (was 64)

Stacked on PRs QwikDev#192 + QwikDev#193 + QwikDev#194. Will rebase onto main once the stack
merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oses OSS-449 (QwikDev#196)

* refactor(OSS-449): strip Linear ticket refs from extract.ts comments; rewrite ticket-tour prose WHY-anchored

WHAT
First file of the comment-cleanup sweep (OSS-449). Removes all 32
`OSS-XXX` references from src/optimizer/extract.ts. 3 comments deleted
outright (pure ticket-tour stickers with no WHY content). 21 comments
rewritten — sticker stripped, prose re-anchored on the invariant or
constraint the code enforces rather than the historical PR that
introduced it. SWC `transform.rs:...` cross-references kept (they
reference files committed in the repo, not external trackers).

WHY IN ISOLATION
External readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers — those are internal-only. Stripping them
makes comments self-contained and accessible to the file's actual
audience (whoever opens it).

The rewrite step beyond pure deletion is the WHY-not-WHAT cleanup.
Pre-fix comments were a mix of "what we did" (`Pre-fix the filter
excluded X; now it includes X`) and ticket-tour ("OSS-446 Bug 1: ..."),
both of which decay as code evolves. Post-fix comments state the
invariant or constraint that forced the code shape, which stays
accurate across refactors. Examples:

- "OSS-368 — deferred; populated on leave from activeSegmentBodies.bodyIds."
  → "Deferred; populated on leave from activeSegmentBodies.bodyIds."

- "OSS-386: `loc` is documented as [byteStart, byteEnd] in OPTIMIZER.md
  ... this site previously emitted [line, col] (a pre-existing semantic
  mismatch, hidden because convergence's strict-compare skips loc)."
  → "`loc` carries byte offsets, not line/col — per OPTIMIZER.md's
  documented [byteStart, byteEnd] contract that snap fixtures also
  encode."

WHY FOUNDATION
First step in the OSS-449 sweep (estimated 35 files, 243 total refs).
extract.ts is the top offender at 32 refs; getting it cleaned validates
the bucket-classification approach (3 Delete / 21 Rewrite / 0 Keep
across this file) before tackling segment-generation.ts (25 refs) +
rewrite/index.ts (21 refs) + the rest. The WHY-not-WHAT memory
(`feedback_comments_explain_why`) is now demonstrated end-to-end on a
real file — establishes the bar for future comment writing across the
codebase per the project rule encoded in CBP.

RISK
Comment-only edits — no behaviour change. Verified:
- `pnpm typecheck` clean.
- `pnpm vitest convergence --run` → 203/212 unchanged.
- `pnpm vitest run` → full suite passes (no baseline regressions per
  `ci:baseline:check`).
- `grep -rE "OSS-[0-9]+" src/optimizer/extract.ts | wc -l` → 0 (was 32).
- `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 211 (was 243).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from segment-generation.ts + rewrite/index.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second commit in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/segment-generation.ts (was 25 refs → 0)
  - src/optimizer/rewrite/index.ts (was 21 refs → 0)

3 comments deleted outright (`See OSS-NNN.` trailing reference-only
sentences with no WHY content). 40 comments rewritten — sticker
stripped, prose re-anchored on the invariant or constraint the code
enforces. SWC `transform.rs:NNN` references kept (they reference files
committed in the repo, not external trackers). Local cross-references
(`rewrite/inline-body.ts`, `buildElementCaptureMap`, etc.) kept.

WHY IN ISOLATION
Same rationale as the prior extract.ts commit (this sweep is OSS-449):
external readers of an OSS project can't follow `linear.app/kunai/...`
URLs or `OSS-XXX` identifiers, and ticket-tour prose paraphrases the
code in ways that decay across refactors. Examples from this commit:

  - "OSS-432 Bug C: pre-compute the per-segment JSX-key starting counter
    in SOURCE order... Surfaced when Bug A + Bug B exposed the
    segment-side comparison previously masked by the parent mismatch."
    → strip the sticker AND drop the "Surfaced when Bug A + Bug B..."
    ticket-tour tail; keep "Pre-compute the per-segment JSX-key starting
    counter in SOURCE order, independent of the depth-first processing
    order used by the main loop below..."

  - "OSS-438 Fix B: propagate captures... (the original upstream-built
    map keyed by `<`-walk byte offsets had positions 524/630 while the
    walker saw 221/301)."
    → strip sticker AND drop the debugging-detail tail; keep the
    invariant: "Cross-phase positions are unreliable because every
    intervening `parseSync` overwrites the shared buffer."

WHY FOUNDATION
With extract.ts (32 refs), segment-generation.ts (25), and
rewrite/index.ts (21) all clean, the top-3 offenders in src/ are done
(78 of the original 243 refs). The bucket-classification approach has
held up across 78 individual judgement calls without surfacing any
production code where a Linear ticket reference was load-bearing
enough to warrant a GitHub mirror — consistent with the OSS-449
prediction that prod Keeps would be exceedingly rare. The remaining
~165 refs are spread across 32 files (smaller per-file volumes;
mechanical patterns).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    passing tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/segment-generation.ts | wc -l` → 0 (was 25)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/index.ts | wc -l` → 0 (was 21)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 165 (was 243)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts; rewrite ticket-tour prose WHY-anchored

WHAT
Second batch in the OSS-449 sweep. Files cleaned:

  - src/optimizer/transform/index.ts (was 19 refs → 0)
  - src/optimizer/rewrite/output-assembly.ts (was 18 refs → 0)
  - src/optimizer/rewrite/inline-body.ts (was 14 refs → 0)

2 trailing-only `See OSS-NNN.` references deleted. 46 sticker-strip
rewrites — each comment's WHY-anchored prose preserved (or refined
where it was tangled with ticket-tour fragments). Several brittle line
references (`extract.ts:696`, `rewrite/index.ts:657`, etc.) and a few
fixture-specific tail clauses (`preserves example_dev_mode_inlined
etc.`, `(example_strip_client_code)`) dropped during the rewrites —
those decay as code evolves and add no invariant content.

WHY IN ISOLATION
Same as the first OSS-449 batch (commit d1318fe + 65363b8): external
readers of an OSS project can't follow `linear.app/kunai/...` URLs or
`OSS-XXX` identifiers, and ticket-tour prose paraphrases the code in
ways that decay across refactors. Examples from this batch:

  - "OSS-407 Fix A: when body is a bare identifier... (see OSS-407 Fix
    C in placeSCalls)."
    → strip both refs; keep "When body is a bare identifier referring
    to a module-level decl... see the forward-dep handling in
    `placeSCalls`."

  - "OSS-408 Fix A: previously skipped inlinedQrl extractions on the
    grounds that 'the name was set explicitly by the upstream tool';
    but SWC ALSO renames them under prod..."
    → strip the "previously skipped" ticket-tour framing; restate as
    the invariant: "SWC renames inlinedQrl extractions under prod...
    preserving the hash suffix so runtime QRL resolution still matches."

WHY FOUNDATION
Combined with the first batch's top-3 offenders (PR QwikDev#192), this PR
brings the OSS-449 sweep to 129 of the original 243 refs cleaned
(53%). Remaining 114 refs spread across 32 smaller-volume files —
mechanical patterns established by this point should make subsequent
batches faster per file.

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/optimizer/transform/index.ts | wc -l` → 0 (was 19)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/output-assembly.ts | wc -l` → 0 (was 18)
  - `grep -rE "OSS-[0-9]+" src/optimizer/rewrite/inline-body.ts | wc -l` → 0 (was 14)
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 114 (was 165)

Stacked on top of PR QwikDev#192 (refactor/OSS-449-comment-cleanup-extract).
Will rebase onto main once QwikDev#192 merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from Tier 1 files (batch 3)

WHAT
Third batch in the OSS-449 sweep. Tier 1 files (≥8 refs each, 50 total):

  - src/optimizer/transform/jsx.ts (11 → 0)
  - src/optimizer/transform/jsx-call-transform.ts (11 → 0)
  - src/optimizer/signal-analysis.ts (11 → 0)
  - src/optimizer/segment-codegen.ts (9 → 0)
  - src/optimizer/transform/jsx-props.ts (8 → 0)

3 trailing-only `See OSS-NNN.` references deleted. 39 sticker-strip
rewrites preserving the WHY-anchored prose. Several fixture-name tails
(`example_strip_client_code`, `example_dev_mode`,
`example_parsed_inlined_qrls`, `example_qwik_react_inline`) and
brittle line refs dropped during the rewrites — those don't anchor
invariants. One duplicate comment block in segment-codegen.ts:727-737
collapsed to a single comment (copy-paste artifact).

WHY IN ISOLATION
Same rationale as batch 1 (extract.ts, PR QwikDev#192) and batch 2
(transform/index.ts + rewrite/output-assembly.ts + rewrite/inline-body.ts,
PR QwikDev#193): external readers can't follow `OSS-XXX` refs, and ticket-tour
prose paraphrases code in ways that decay across refactors. Examples
from this batch:

  - "OSS-417: root-identifier substitution and constant-subtree
    simplification share the orchestrator. OSS-418 dropped the OSS-414
    paren-strip pass — raw-props no longer emits defensive parens at
    Property-value positions..."
    → strip all three refs; restate as the invariant: "raw-props doesn't
    emit defensive parens at Property-value positions — precedence-aware
    emission via `expressionNeedsParens` in `raw-props.ts` and
    `props-field-rewrite.ts` means the source slice the `_hf<n>_str`
    generator inherits is paren-free to begin with."

  - "Three semantic divergences from the pre-OSS-369 split:"
    → "Three semantic invariants this collector enforces:" — the
    divergence framing is ticket-tour (anchored to a particular code
    change); the bullets themselves are real invariants that survive
    refactors.

WHY FOUNDATION
Combined with PR QwikDev#192 + PR QwikDev#193, OSS-449 sweep is now at 179 of the
original 243 refs cleaned (74%). Remaining 64 refs across 24 files
(all ≤6 refs per file) — Tier 2 + Tier 3 batches close out the work.
Pattern has been fully mechanical across 12 files now; no Keeps
required for any production file (0 GH mirrors needed across 179
individual judgement calls).

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 64 (was 114)

Stacked on top of PR QwikDev#193 (refactor/OSS-449-comment-cleanup-batch2).
Will rebase onto main once QwikDev#192 + QwikDev#193 merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip Linear refs from Tier 2 files (batch 4)

WHAT
Fourth batch in the OSS-449 sweep. Tier 2 files (4–6 refs each, 37 total):

  - src/optimizer/transform/event-capture-promotion.ts (6 → 0)
  - src/optimizer/transform/jsx-elements-core.ts (5 → 0)
  - src/optimizer/transform/diagnostic-detection.ts (5 → 0)
  - src/optimizer/rewrite/raw-props.ts (5 → 0)
  - src/optimizer/utils/range-replace.ts (4 → 0)
  - src/optimizer/types/brands.ts (4 → 0)
  - src/optimizer/rewrite/symbol-collision.ts (4 → 0)
  - src/optimizer/rewrite/rewrite-context.ts (4 → 0)

All sticker-strips with WHY-anchored prose preserved. Several
fixture-name tails (`example_strip_client_code`, `issue_7216_add_test`,
`example_props_optimization`, `example_spread_jsx`) and ticket-tour
fragments ("validated against...", "the case we hit during OSS-384's
call-site sweep", "tracked as a follow-up") dropped — those don't
anchor invariants.

Comparison tables and historical context were preserved where they're
genuinely load-bearing (e.g. `range-replace.ts`'s caller table, the
`brands.ts` HASH_SHAPE rationale).

WHY IN ISOLATION
Same rationale as the prior three batches (PRs QwikDev#192, QwikDev#193, QwikDev#194):
external readers can't follow `OSS-XXX` refs, and ticket-tour prose
paraphrases code in ways that decay across refactors.

WHY FOUNDATION
With this batch, the OSS-449 sweep is at 216 of the original 243 refs
cleaned (89%). Remaining 27 refs across 16 small-volume files (Tier 3,
mostly 1–3 refs each) — one more PR closes out the sweep.

RISK
Comment-only edits — no behaviour change. Verified:
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions; all 203 + 965 baseline
    tests still pass
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 27 (was 64)

Stacked on PRs QwikDev#192 + QwikDev#193 + QwikDev#194. Will rebase onto main once the stack
merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(OSS-449): strip remaining Linear refs from Tier 3 files — closes OSS-449

WHAT
Fifth and final batch in the OSS-449 sweep. Tier 3 files (1–3 refs
each, 27 total):

  - src/hashing/siphash.ts (1 → 0)
  - src/optimizer/capture-analysis.ts (1 → 0)
  - src/optimizer/dev-mode.ts (1 → 0)
  - src/optimizer/path-utils.ts (3 → 0)
  - src/optimizer/rewrite/const-propagation.ts (1 → 0)
  - src/optimizer/rewrite/lib-mode-collapse.ts (1 → 0)
  - src/optimizer/rewrite/predicates.ts (1 → 0)
  - src/optimizer/segment-codegen/body-transforms.ts (2 → 0)
  - src/optimizer/segment-codegen/import-collection.ts (1 → 0)
  - src/optimizer/transform/module-cleanup.ts (1 → 0)
  - src/optimizer/transform/post-process.ts (3 → 0)
  - src/optimizer/types.ts (3 → 0)
  - src/optimizer/utils/jsx-import-source.ts (1 → 0)
  - src/optimizer/utils/props-field-rewrite.ts (2 → 0)
  - src/optimizer/utils/simplify.ts (3 → 0)
  - src/testing/ast-compare.ts (2 → 0)

All sticker-strips. The Linear references in these files were mostly
introducing prose with `OSS-NNN:` followed by load-bearing WHY content,
or trailing parenthetical "(per OSS-NNN)" attribution.

OSS-449 SWEEP CLOSED
With this batch, the sweep has cleaned ALL 243 originally-found Linear
references across the codebase:

  - PR QwikDev#192 (batch 1, top-3): extract.ts (32), segment-generation.ts
    (25), rewrite/index.ts (21) → 78 refs cleaned
  - PR QwikDev#193 (batch 2): transform/index.ts (19), output-assembly.ts (18),
    inline-body.ts (14) → 51 refs cleaned
  - PR QwikDev#194 (batch 3, Tier 1): jsx.ts (11), jsx-call-transform.ts (11),
    signal-analysis.ts (11), segment-codegen.ts (9), jsx-props.ts (8)
    → 50 refs cleaned
  - PR QwikDev#195 (batch 4, Tier 2): 8 files × 4–6 refs → 37 refs cleaned
  - This PR (batch 5, Tier 3): 16 files × 1–3 refs → 27 refs cleaned

  Total: 78 + 51 + 50 + 37 + 27 = 243 refs cleaned across 36 files.

KEEP COUNT
243 individual judgement calls across the sweep. Zero production-code
Keeps required — i.e. zero GH issue mirrors needed. The OSS-449 ticket
predicted "exceedingly rare for prod" and the prediction held perfectly
end-to-end. The Keep+mirror process is documented in the ticket and
ready for any future case that arises but didn't fire here.

VERIFIED CLEAN
  - `grep -rE "OSS-[0-9]+" src/ --include="*.ts" | wc -l` → 0 (was 243)
  - `grep -rE "linear\.app" src/ --include="*.ts" | wc -l` → 0
  - `pnpm typecheck` clean
  - `pnpm vitest convergence --run` → 203/212 unchanged
  - `pnpm ci:baseline:check` → zero regressions

OSS-449 acceptance criteria all met. Ready to close.

Stacked on PRs QwikDev#192 + QwikDev#193 + QwikDev#194 + QwikDev#195. Will rebase onto main once
the stack merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…stripped from src/ (QwikDev#197)

Five OSS-449 PRs (QwikDev#192/QwikDev#193/QwikDev#194/QwikDev#195/QwikDev#196) merged in sequence today.
Main at ce58ac2. Comment-only sweep across 36 files; convergence
203/212 + full suite 965/980 unchanged.

STATE.md edits:
  - Last updated bumped to reflect the OSS-449 sweep + the OSS-446
    follow-up context that carries over.
  - Current measurements row: head ce58ac2; baselines exact preservation;
    OSS-449 closed note.
  - Branches in flight `main` row rewritten for OSS-449 context +
    OSS-447/OSS-448 as the active workstream pickup.
  - Most recent meaningful progress: prepended OSS-449 entry (covers all
    5 PRs as one logical sweep); trimmed the oldest OSS-431 bullet to
    keep the log at 10.
  - Recently closed: prepended OSS-449 entry.

OPTIMIZER.md audit verdict: no update needed. The OSS-449 sweep touched
many trigger-checklist files but the changes were strictly comment-
text edits — no phase added/removed/renumbered, no new tool-surface
convention, no migration rule change, no entry strategy change, no
ExtractionResult field change. The cite refreshes are also unnecessary
because none of the rewrites moved cited line numbers past the 50-line
drift threshold.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QwikDev#198)

Filed 2026-06-04 alongside the existing OSS-447 + OSS-448 follow-ups
from the OSS-446 stack. Adds a second candidate workstream for any
session picking up the project cold; the parity vs integration
trade-off is explicit in the "What to do next" section.

Tickets created:
  - OSS-450 (umbrella) — TS optimizer drop-in for qwik-bundler
  - OSS-451 (Sub-A) — Public API surface (src/index.ts + exports)
  - OSS-452 (Sub-B) — createOptimizer-compatible factory
  - OSS-453 (Sub-C) — preParsedProgram thread-through audit
  - OSS-454 (Sub-D) — Bundler-side opt-in adapter (qwik-bundler repo PR)
  - OSS-455 (Sub-E) — Parity smoke fixture

Design choices locked at scoping time (per user direction):
  1. Adapter lives in this repo (TS optimizer side) — API parity is the
     rewrite's responsibility, not the bundler's.
  2. Reuse Rolldown's meta.ast — passes the bundler's OXC Program into
     the optimizer to skip the internal parse. Foundation in Sub-C,
     consumed in Sub-D.

Also saved a project memory entry (project_qwik_bundler_integration)
so future sessions surface the sub-goal before they hit STATE.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ev#199)

Forward-looking architectural constraint: Yuku (https://github.com/yuku-toolchain/yuku)
is a planned future drop-in alternative to OXC for the bundler's parser.
Yuku promises ESTree/TS-ESTree output matching OXC's shape, so the swap
should be transparent — but only if the optimizer's external AST input
contract stays parser-agnostic.

Captured as the third locked design choice on the OSS-450 umbrella
("parser-agnostic AST input contract"); also pinned via:
  - Inline comment on the OSS-450 Linear issue
  - Project memory project_qwik_bundler_integration.md update

Practical: Sub-C (OSS-453, preParsedProgram thread-through) must accept
any structurally-compatible ESTree Program, not just OXC's specific
type. Internal parses (parseWithRawTransfer, body re-parses for JSX
walks) can stay OXC-specific for now — those are an optimizer
implementation detail, not the public contract.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ev#200)

Sub-A of the OSS-450 qwik-bundler integration umbrella. Establishes the
package's importable surface as a one-time foundation step; no behaviour
changes in src/optimizer/.

What landed:

- New src/index.ts barrels the public API: transformModule, the
  TransformModulesOptions / TransformOutput / TransformModule(Parent|
  Segment) / SegmentAnalysis / EntryStrategy / Diagnostic / EmitMode /
  MinifyMode / DiagnosticHighlightFlat / WithManualEntryMap types, the
  hasManualEntryMap predicate, and the full brand-types surface
  (FilePath, SourceText, RelativePath, etc.) with their smart
  constructors so consumers can satisfy the branded input types without
  casting at every call site.
- New tsconfig.build.json extends the root tsconfig with rootDir:"src",
  noEmit:false, and excludes tests + src/testing/ so dist/ ships only
  the production surface.
- package.json adds the build script, main/types/exports/files entries.
  Stays private:true; publishing is out of scope for Sub-A.

Smoke-tested: pnpm build emits dist/index.{js,d.ts}; external
import('dist/index.js') resolves all 15 runtime exports;
transformModule round-trips a minimal $() input through the dist.

Baselines preserved: convergence 203/212 + full suite 965/980 unchanged
(this is packaging only — no src/optimizer/ changes).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…T.md (QwikDev#201)

Adds the optional agent_sync block (schema: bootstrap-project skill) so
the portable ~/.claude/skills/agent-sync skill resolves the rules-sync
script without auto-detection, plus a prose section documenting the
.claude/rules → .cursor/rules mirroring contract.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ler integration shipped (QwikDev#200) (QwikDev#202)

PR QwikDev#200 (1296e97) shipped the public API surface foundation step for the
OSS-450 qwik-bundler integration umbrella: src/index.ts barrel + tsconfig.build.json
+ package.json main/types/exports/build script. Packaging-only — baselines
preserved exactly (convergence 203/212 + full suite 965/980 unchanged).

OPTIMIZER.md audit: non-trigger-touching, skipped (PR only touched package.json,
src/index.ts, tsconfig.build.json — none on the trigger checklist).

OSS-450 umbrella status: Sub-A Done; Sub-B (OSS-452 createOptimizer factory)
is the next pickup.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ape (QwikDev#203)

Sub-B of the OSS-450 qwik-bundler integration umbrella. Bridges the API
shape gap between the TS optimizer's sync `transformModule` and SWC's
stateful-async `createOptimizer(opts): Promise<Optimizer>` so the bundler
call site (qwik-bundler/src/rolldown.ts:354) reads through unchanged when
swapping providers:

    const result = await (await getOptimizer()).transformModules(opts);

What landed:

- New `src/create-optimizer.ts` (top-level facade, sibling of index.ts)
  defines `QwikOptimizer`, `OptimizerOptions`, `OptimizerSystem`,
  `SystemEnvironment`, and `Path` interfaces mirroring SWC's public
  surface (from `@qwik.dev/optimizer/dist/index.d.ts`). `createOptimizer`
  is async (`Promise<QwikOptimizer>`) to match SWC even though nothing
  is genuinely async — `Promise.resolve(instance)` satisfies the
  contract. The instance's `transformModules` wraps the synchronous
  `transformModule` and returns `Promise.resolve(result)`.

- Default `sys` stub satisfies the full SWC `OptimizerSystem` interface
  (cwd via process.cwd, env: 'node', os: process.platform,
  dynamicImport/strictDynamicImport via native import(), path delegating
  to pathe). `options.sys` overrides if provided. SWC parity at the
  field level so consumers swapping providers get an identical type
  surface; the TS pipeline never reads `sys` itself.

- Passthrough OptimizerOptions fields (binding / inlineStylesUpToBytes
  / sourcemap / _optimizer) accepted for type-compat with existing SWC
  integration options objects but not consumed.

- src/index.ts re-exports `createOptimizer` + the 5 new public types.

- New `tests/optimizer/create-optimizer.test.ts` with 6 unit tests
  pinning the factory shape, the async round-trip through
  `.transformModules`, custom-sys pass-through, passthrough-fields
  acceptance, pathe delegation, and the bundler's double-await call
  pattern.

Baselines preserved: convergence 203/212 + full suite 965/980 unchanged
(+6 new unit tests will be absorbed into baseline on merge). Typecheck
clean. `pnpm build` emits `dist/create-optimizer.{js,d.ts}` alongside
`dist/index.{js,d.ts}`; external `import('dist/index.js')` resolves
`createOptimizer` and round-trips through it end-to-end.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ler integration shipped (QwikDev#203) (QwikDev#204)

PR QwikDev#203 (c26732d) shipped the createOptimizer factory matching SWC's
stateful-async shape: src/create-optimizer.ts top-level facade + QwikOptimizer
/ OptimizerOptions / OptimizerSystem / SystemEnvironment / Path interfaces +
6 focused unit tests. Baselines preserved exactly (convergence 203/212 + full
suite 965/980 unchanged; +6 unit tests absorbed into baseline on merge).

OPTIMIZER.md audit: non-trigger-touching, skipped (PR only touched new facade
files + barrel re-exports + a new unit test; no pipeline files).

OSS-450 umbrella status: Sub-A ✅ Done (PR QwikDev#200), Sub-B ✅ Done (PR QwikDev#203).
Sub-C (OSS-453 preParsedProgram thread-through audit) is the next pickup —
verifies the existing OSS-350 parameter is wired end-to-end from public entry
through every phase so Sub-D's bundler-side adapter can hand in Rolldown's
meta.ast without an internal re-parse.

State-file edits: Last updated + Last verified + Branches in flight `main`
row (head c26732d, OSS-452 closure summary, Sub-C as next active workstream)
+ new dated entry prepended to "Most recent meaningful progress" + trimmed
oldest entry (OSS-432 from 2026-05-23) per Maintenance "~10 entries" rule.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ev#205)

* feat(OSS-453): thread preParsedProgram through public boundary

Sub-C of the OSS-450 qwik-bundler integration umbrella. Wires the
existing `extractSegments(preParsedProgram)` parameter (added in
OSS-350) all the way out to the public `transformModule` entry so
Sub-D's bundler adapter can hand in Rolldown's `meta.ast` and avoid
the double-parse (host parses for `meta.ast`; optimizer used to parse
again internally via `repairInput`).

Audit found one gap: `repairInput` always called `parseWithRawTransfer`
internally to detect whether repair was needed, even though
`transformModule` already deduplicated its own parse against that
result. So the bundler-host parse was the third one in the chain.

What landed:

- `repairInput(source, filename, preParsedProgram?, preParsedModule?)`
  now short-circuits its internal parse when a Program is supplied,
  trusting the caller's AST (callers like Rolldown wouldn't hand us
  broken source). Existing behavior unchanged when the param is omitted.

- `TransformModuleInput` gains optional `program?: AstProgram` and
  `module?: AstEcmaScriptModule` fields. Documented as opt-in: omit
  and the optimizer parses internally as before; supply and the
  optimizer skips both internal parses (the one in `repairInput` and
  the legacy fallback at `transform/index.ts:118`).

- `transformModule` forwards `input.program` / `input.module` into
  `repairInput`. No other phase changes — Phase 0.5 flatten-destructures
  and downstream body re-parses are out of scope per ticket (they don't
  have access to the parent's `meta.ast` and operate on rewritten
  source anyway).

- `src/index.ts` re-exports `AstProgram` as `Program` and
  `AstEcmaScriptModule` as `EcmaScriptModule` so consumers can type
  their input. Per locked design choice, the contract is structural:
  any ESTree/TS-ESTree-compatible Program satisfies the type at
  runtime — OXC today, Yuku in the future.

- `@oxc-project/types` promoted from devDependency to dependency
  (was already reachable via runtime; needed to be reachable via
  consumer type-resolution after the re-export).

- 5 focused regression tests at
  `tests/optimizer/preparsed-program.test.ts` pin: pre-parsed Program
  acceptance, structural identity vs no-program path on every emitted
  module + segment metadata field, legacy parse-internally path
  preservation, module-optional-when-program-supplied, and end-to-end
  round-trip through `createOptimizer().transformModules()`.

Baselines preserved: convergence 203/212 + full suite 971/980
unchanged (+5 new unit tests will be absorbed into baseline on
merge). Typecheck clean. `pnpm build` emits the updated public types.
Runtime exports unchanged (16; Program/EcmaScriptModule are type-only).

Independent of Sub-D — ships as foundation. The bundler-side adapter
(OSS-454) will pass `meta.ast` into this field; Sub-E's parity smoke
fixture exercises the end-to-end path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(OSS-453): sync pnpm-lock.yaml with @oxc-project/types dep promotion

CI failed on `pnpm install --frozen-lockfile` because the previous commit
moved `@oxc-project/types` from devDependencies to dependencies in
package.json without updating the lockfile. Pure mechanical sync — same
package version, just moved between buckets in the lockfile's importer
manifest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ler integration shipped (QwikDev#205) (QwikDev#206)

PR QwikDev#205 (058839b) wired the preParsedProgram thread-through from the public
boundary down to extract. repairInput short-circuits when caller supplies a
Program; TransformModuleInput gains optional program? + module? fields;
src/index.ts re-exports Program + EcmaScriptModule with structural-ESTree
contract per locked design. @oxc-project/types promoted to dep; lockfile
sync caught by CI install-step failure on initial push, fixed in follow-up
commit + saved as feedback_lockfile_sync_on_dep_changes memory.

Baselines preserved: convergence 203/212 + full suite 971/980 unchanged
(+5 new unit tests absorbed into baseline on merge).

OPTIMIZER.md audit: no update needed — Phase 0 opt-in plumbing only, not
structural. Individual cite drift on Phase 1-5 markers now +17 to +34 lines,
under the 50-line threshold; cumulative-drift sweep deferred per PROJECT.md
convention.

OSS-450 umbrella status: Sub-A ✅ Done, Sub-B ✅ Done, Sub-C ✅ Done. Sub-D
(OSS-454 cross-repo bundler-side adapter) is the next pickup — lives in
qwik-bundler, not this repo. Foundation in this repo now complete end-to-end:
Sub-A barrel exposes createOptimizer + transformModule + types; Sub-B
mirrors SWC's async shape; Sub-C accepts pre-parsed Program.

State-file edits: Last updated + Last verified + Branches in flight `main`
row (head 058839b, OSS-453 closure, Sub-D as next active workstream) +
new dated entry prepended to "Most recent meaningful progress" + trimmed
oldest entry (OSS-435 from 2026-05-24) per Maintenance "~10 entries" rule.
Line-48 markdown table cell contains a TypeScript union (`'swc' \| 'ts'`)
escaped per markdown table rules so the pipe is rendered as a literal
character rather than a cell separator.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t paths) (QwikDev#208)

* fix: promote oxc-parser/oxc-walker/oxc-transform to runtime dependencies

The Sub-A packaging step left `oxc-parser`, `oxc-walker`, and
`oxc-transform` in devDependencies, but all three are imported at
runtime by src/ code (parse.ts, extract.ts, capture-analysis.ts,
const-replacement.ts, variable-migration.ts, rewrite/inline-body.ts,
rewrite/index.ts, rewrite/output-assembly.ts, utils/walk-with-protocol.ts).

When a consumer (qwik-bundler) installs qwik-optimizer-ts and tries
to use it via `optimizer: 'ts'`, the dynamic import resolves but the
optimizer's first internal `import { parseSync } from 'oxc-parser'`
crashes with "Cannot find package 'oxc-parser'" — pnpm's strict
hoisting doesn't surface devDeps to consumers.

Same class of bug as QwikDev#205's `@oxc-project/types` promotion: a runtime
dep that escaped the original Sub-A audit. Cross-checked the entire
`from 'oxc-*'` / `from 'fast-deep-equal'` import surface:

- oxc-parser, oxc-walker, oxc-transform → all 9 src/ files use them → MOVED to deps.
- fast-deep-equal → only used by src/testing/ast-compare.ts (test oracle) →
  stays in devDeps.

Caught by attempting the rolldown-h3 fixture build under
`qwik({ optimizer: 'ts' })`. Pre-fix: "Cannot find package 'oxc-parser'".
Post-fix: the package resolves and the optimizer pipeline runs end-to-end.
(A separate parent/segment path-resolution divergence surfaces past this
fix; tracked as a follow-up — out of scope here.)

No functional change. typecheck + build clean. Convergence + full-suite
baselines preserved (this is packaging only — zero src/ edits). Lockfile
re-synced per `feedback_lockfile_sync_on_dep_changes` memory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: emit segment module.path in the input.path namespace

When a consumer passes absolute `input.path` values (which is what
bundlers do — Rolldown hands plugins absolute file paths), SWC emits
`module.path` as absolute too. Consumers like qwik-bundler rely on this:
their `resolveId` hook joins `dirname(importer)` with the parent's
relative import string, and matches the result against segment-map
keys built from `module.path`. If `module.path` is srcDir-relative
while the importer is absolute, every parent-to-segment lookup misses
and the build fails with "Module not found".

This was caught running `pnpm --dir fixtures/rolldown-h3 build` under
`qwik({ optimizer: 'ts' })` in qwik-bundler — every segment file was
emitted but unreachable from the parent module.

What landed:

- New `inputPath` field on `SegmentGenerationContext`, populated from
  `input.path` directly in transform/index.ts (next to the existing
  `relPath`, which stays srcDir-relative for hashing/naming use).
- Both segment-emit sites in segment-generation.ts now compute
  `module.path` as `join(getDirectory(ctx.inputPath), canonical + ext)`.
  Snapshot fixtures use root-level paths like "test.tsx" where
  getDirectory returns "" — output unchanged. Bundler integrations
  passing absolute paths get absolute outputs back.
- `mkRelativePath` brand validation relaxed to only reject empty
  strings. The leading-slash ban was an over-specification — SWC's
  `TransformModule.path` legitimately holds absolute paths in
  bundler-supplied scenarios. The brand still distinguishes from
  `FilePath` at the type level; the runtime check shrinks to the
  invariant we can actually rely on. Documented inline.
- One brand test renamed + behaviour flipped from "rejects absolute"
  to "accepts absolute (only empty rejected)". Baseline absorbs the
  rename per the existing REGRESSION.md "renamed tests count as
  missing" convention.

End-to-end validation:

- pnpm typecheck clean.
- Convergence 203/212 unchanged. Full suite 976/1004 unchanged
  (snapshot fixtures all use root-level paths so getDirectory("") = ""
  and segment.path is byte-identical to before).
- qwik-bundler's full test suite 167/167 passes against this dist.
- rolldown-h3 fixture builds clean under qwik({ optimizer: 'ts' }).
- The h3 server starts, serves the HTML, and the QRL wiring is intact
  (`<button q:p="0" q-e:click="q-D4Y6RLLt.js#_run#1">`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci): align baseline total with CI environment

The local baseline regen captured `full.total = 1004`, but CI's Linux
environment runs 1002 — two tests run on macOS that don't run on Linux
(probably platform-conditional). The regression check correctly flagged
this as a possible silent test deletion when comparing the PR's run
(1002) against the committed baseline (1004).

Solution: revert the `.ci/baseline.json` totals to the 4f85b3c version
that CI already accepts, then apply only the brand-test rename on top
(`mkRelativePath rejects empty and absolute paths` →
`mkRelativePath rejects only empty strings ...`). This keeps the
renamed test tracked correctly without inflating totals beyond what
CI sees.

Net effect on the baseline file: one entry's name changed in the
`full.passing` set; `total` counts unchanged (1002 / 212). The
auto-baseline-update workflow on main will re-derive everything from
CI's actual run after merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: strip Linear ticket refs from source code comments

Per the project convention (feedback_comments_explain_why memory,
strengthened 2026-06-04): ticket refs belong in PR titles + commit
messages + tracker only. Never in source code, test file headers,
or test descriptions — the audience of source comments doesn't have
access to the tracker and doesn't need to.

OSS-454's Sub-D PR review surfaced this; cleaning up the four sites
introduced by the OSS-450 umbrella's TS-Optimizer-side sub-issues:

- src/optimizer/input-repair.ts (from QwikDev#205): dropped `OSS-453:` prefix
  from the preParsedProgram comment; kept the WHY (eliminates the
  double-parse when integrating with a host that already has the AST).
- src/optimizer/transform/index.ts (from QwikDev#205): dropped `(OSS-453, ...)`
  from the Phase 0 repair comment.
- src/index.ts (from QwikDev#205): dropped `(OSS-453)` from the Program /
  EcmaScriptModule re-export comment.
- src/create-optimizer.ts (from QwikDev#203): rewrote the header comment to
  describe the shape it mirrors (`@qwik.dev/optimizer`'s public surface)
  rather than ticket-tour the sub-issue lineage.
- tests/optimizer/preparsed-program.test.ts (from QwikDev#205): dropped
  `OSS-453 — ` prefix from the describe block.

The OSS-449 sweep cleaned 243 src/ refs in May; OSS-454 introduced 4
new ones in the Sub-A/B/C series that escaped review. The memory is
now hardened with explicit `NEVER` framing + worked examples from
both the Sub-C and Sub-D violations so future agents can't misread it.

Baseline regenerated to absorb the describe-block rename per
REGRESSION.md "renamed tests count as missing" caveat. No functional
change. Convergence 203/212 + full suite 976/1004 unchanged from the
prior measurement (965 → 976 reflects newly-baselined unit tests
from QwikDev#203/QwikDev#205, not new behaviour).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci): align baseline total with CI environment

Same fix as f/oxc-runtime-deps c2a7e75 applied to this branch's
baseline: the local regen captured `full.total = 1004` but CI's
Linux env runs 1002 (two tests run on macOS that don't run on Linux).
The regression check correctly flagged the 1004 → 1002 drop as
possible silent test deletion.

Solution: revert `.ci/baseline.json` totals to the e0520c4 version
(post-OSS-453 / pre-this-branch state that CI accepts) and apply
only the five `OSS-453 — preParsedProgram thread-through ...`
→ `preParsedProgram thread-through ...` describe-block renames that
this PR makes. Totals (1002 full / 212 convergence) match CI.

The auto-baseline-update workflow on main will re-derive everything
from CI's actual run after merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…#207 + QwikDev#208 merged (QwikDev#209)

Two same-day same-track merges (bundler-integration packaging) batched
into one progress entry per the wrap-up convention for tightly-related
merges.

PR QwikDev#208 (6ff151e parent commit 850386b): fixed two packaging blockers
caught by attempting the README's rolldown-h3 fixture under the TS
optimizer — three runtime deps mis-bucketed in devDependencies (oxc-
parser, oxc-walker, oxc-transform → all imported by 9 src/ files);
segment module.path namespace divergence (TS emitted srcDir-relative,
SWC emits in input.path namespace, bundlers' resolveId expected
SWC's). Fix threaded input.path through to SegmentGenerationContext as
new inputPath field; loosened mkRelativePath brand validation.

PR QwikDev#207 (6ff151e): stripped Linear ticket refs from src/ + tests/
comments per the feedback_comments_explain_why memory; strengthened
the memory with explicit "NEVER ticket refs in code" framing +
worked-example entries for both the Sub-C (PR QwikDev#205) and Sub-D
(qwik-bundler PR QwikDev#12) violations.

End-to-end demo working: rolldown-h3 fixture builds + runs under
qwik({ experimental: ['tsOptimizer'] }); h3 server boots; HTML
response carries full Qwik QRL wiring intact.

OPTIMIZER.md audit: no update needed — two trigger-checklist files
touched (transform/index.ts, segment-generation.ts) but no
structural-change criterion fires. New inputPath field is type-
internal; module.path namespace switch is at the output-emission
boundary, not the pipeline shape.

OSS-450 umbrella status: Sub-A/B/C all Done; TS-Optimizer-side
packaging blockers resolved. Sub-D (OSS-454) in qwik-bundler PR QwikDev#12
is in its final shape with optimizer selection driven from
EXPERIMENTAL_FEATURES (`tsOptimizer` flag), validated end-to-end
against rolldown-h3, ready to merge.

State-file edits: Last updated + Last verified + Branches in flight
`main` row (head 6ff151e, batched closure summary) + new dated entry
prepended to "Most recent meaningful progress" + trimmed oldest entry
(OSS-437 from 2026-05-24) per Maintenance "~10 entries" rule.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
github-actions Bot and others added 25 commits July 15, 2026 19:32
…/535 Done, OSS-532 parked (QwikDev#353)

Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…ect crash cleared (QwikDev#354)

Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…mode) (QwikDev#355)

* fix(OSS-536): inject _useHmr into inline/hoist component bodies (hmr mode)

In hmr mode the optimizer injected `_useHmr(devFile)` into `component$`
bodies only on the segment (client) strategy path (post-process.ts). The
inline/hoist strategy — which the dev SSR render uses — emitted the body
with no HMR hook.

`_useHmr` is a Qwik hook: its presence changes a component's serialized
hook/vnode layout. The SSR render (inline/hoist, no hook) serialized ref
offsets one way; the client (segment, with hook) re-rendered differently
under interaction, so vnode ref offsets desynced → an intermittent
`Missing refElement` assert under DOM churn on every ref-bound component
(carousel, checkbox, checklist, collapsible, tree in qwik-design-system).
TS-only; the SWC reference injects the hook in both paths and stays
consistent.

Inject `_useHmr` in the inline/hoist emission path (output-assembly.ts),
gated identically to the segment path: `mode === 'hmr' && devFilePath &&
isAnyComponentCtx(ctxName)`. Extracted the block/expression body-injection
core out of `injectUseHmr` and added `injectUseHmrIntoInlineBody` for the
bare-body shape the inline/hoist path carries.

Browser head-to-head (qwik-design-system dev SSR, TS :5200 vs SWC :5201):
the refElement assert is gone across all 5 routes (carousel 3/3→0,
checklist 4/4→0, checkbox 2/15→0, collapsible 3/3→0, tree 1/8→0); TS SSR
HTML now emits q-d:q-hmr markers + q:template projection elements matching
SWC.

Convergence unchanged (203/9 — no inline/hoist fixture runs in hmr mode).
Full baseline green. +5 regression tests. OPTIMIZER.md useHmr emission-site
note updated.

Closes OSS-536.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* docs(state): record OSS-536 root-cause + fix

Server/client HMR-hook desync fixed; refElement assert gone on all 5
ref-bound qds routes. Branch entry + measurements + progress log updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-536): drop what-comments from useHmr inline-injection path

Remove the inline WHY comment on the inline/hoist _useHmr gate plus the two doc comments on injectHmrCallIntoFunctionBody / injectUseHmrIntoInlineBody added by the fix. The gate mirrors the uncommented segment-path gate; the function names state intent and the behavior is guarded by inline-hoist-usehmr.test.ts. The serialized-layout desync rationale stays in the fix commit message where it can't rot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* docs(state): record OSS-536 full post-fix qds re-sweep (clean)

Full 29-route head-to-head re-sweep post-fix: 0 TS-only divergences across all 23 rendering routes; all 5 fixed routes crash->0; 9 prior-MATCH routes no regression; modal symmetric, 6 identical 404s. Refresh header, progress log (trim to 10), and the what-to-do-next section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…v#356)

PR QwikDev#355 (OSS-536: inject _useHmr into inline/hoist component bodies in hmr
mode) merged to main (c4091ea; baseline 2bdf578). Post-merge wrap-up:
branch fix/oss-536-inline-hoist-usehmr deleted local+remote, qds dist
rebuilt + re-synced, OSS-536 flipped to Done.

STATE refresh: header PR-status + tail, branches table (main head SHA
2bdf578, OSS-536 row removed), measurements (main baseline 203/9
convergence + 1192 full, +5 absorbed), progress-log prepend + trim to 10,
what-to-do-next OSS-536 marked Done. OPTIMIZER.md useHmr emission-site
note already updated in the fix PR — no further audit.


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…ves, wireMigration split (QwikDev#357)

* refactor: remove dead code + an exact-dup helper (hygiene batch A)

What: pure deletions + one import repoint across 7 files.
- applyRawPropsTransformDetailed + RawPropsTransformResult — zero callers.
- collectIdentifiersFromExpr — orphaned (collectSignalDeps uses the
  inlined fallbackCollectIdents); fixed its one stale doc reference.
- findArrowIndex — whole chain dead: canonical in text-scanning.ts, its
  lone import + re-export in body-transforms.ts, no consumers repo-wide.
- addBindingNamesToSet — one-line passthrough; call the already-imported
  addBindingNamesFromPatternToSet directly at all 4 sites.
- partsHaveImport — import-collection.ts kept a byte-identical private
  clone of the body-transforms.ts export it already imports from.

Isolation: removes silently-dead surface area and one duplicate that
could drift from its source. No behavior change.
Foundation: clears the "free wins" tranche ahead of the shared-primitive
consolidation (batch B).
Risk: deletions + one import repoint. typecheck clean; convergence
203/203 and full 1192/1192 baseline-passing tests unchanged. Net -91 LOC.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor: share edit/AST primitives across passes (hygiene batch B)

What: replace hand-rolled duplicates with shared primitives.
- 6 reverse-splice apply loops (dead-code, module-cleanup,
  const-propagation) → the existing applyReplacements; ranges are
  disjoint by construction at every site.
- resolveConstLiterals / resolveConstLiteralsInClosure: extract the
  shared inner walk as collectConstLiteralValues(root, source, offset, …);
  the two now differ only by wrapper-offset vs source-absolute.
- containsJsx / containsUnknownCall / containsImportedReference: fold the
  three deep-existential walks onto a new someAstDescendant primitive in
  ast/guards (sibling of someAstChild); drop containsJsx's vestigial
  array-input branch (no caller passes an array).
- getPropertyName / staticPropName → shared memberStaticPropName; the two
  q_<sym>.w() capture-wrap arms (jsx.ts, jsx-props.ts) → shared
  isCaptureWrappingQrlCall.
- inlineConstCaptures guard + isRealRef → the canonical
  isReplaceableIdentifierPosition (adds a params-position exclusion the
  hand-rolled copies lacked; params shadow, so it can only be more
  correct).

Isolation: one home per operation instead of 2-6 drifting copies; the
divergent-guard risk (each reverse-splice/position-guard copy could rot
independently) is removed.
Foundation: someAstDescendant + memberStaticPropName + the shared
predicates are reused by later hygiene batches (C/D).
Risk: behavior-preserving. typecheck clean; convergence 203/203 and full
1192/1192 baseline-passing tests unchanged. Net -97 LOC.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor: dedupe _noopQrl builders + dev-meta literal (hygiene batch C)

What: the inline/hoist strategy had four near-identical _noopQrl string
builders differing only in the LHS var name (q_<sym> vs sentinel
q_qrl_<counter>), and the {file,lo,hi,displayName} dev-meta object
literal was hand-emitted three times (twice here, once in dev-mode.ts).
- Two private core builders buildNoopQrl(varName, symbolName) /
  buildNoopQrlDev(varName, symbolName, devMeta); the four public builders
  become one-line delegations.
- NoopQrlDevMeta type + formatDevMeta() in dev-mode.ts, now the single
  source of the dev-meta literal for both _noopQrlDEV and qrlDEV.
- Trimmed the redundant format-example doc blocks the delegations no
  longer need.

Isolation: one place each defines the noop-QRL template and the dev-meta
literal; output is byte-identical (snapshot-pinned).
Foundation: formatDevMeta is the reuse point if a third dev-meta emitter
appears.
Risk: string builders are snapshot-pinned; convergence 203/203 and full
1192/1192 baseline-passing tests unchanged (byte-identical). Net -34 LOC.

Deferred (NOT behavior-preserving as pure refactors — the "duplicates"
have diverged):
- Import-before-separator idiom (5 sites): guards genuinely differ
  (substring vs partsHaveImport-structured vs startsWith-import) and the
  canonical helper unshifts where these skip when no separator exists.
- Same-file import ladder (2 sites): different data sources
  (reexportedNames set vs migrationDecisions lookup), skip conditions,
  and default-vs-reexport ordering. Unifying either would normalize
  behavior in edge cases the fixtures may not cover.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor: extract lib-mode marker predicate (hygiene batch D)

What: the identical `name.length > 1 && name.endsWith('$')` lib-mode
marker test appeared at 3 sites (rewrite/index, output-assembly,
module-cleanup), each behind a paragraph-long comment explaining the
same rationale. Extract isLibModePreservedMarker() in qwik/qrl-naming;
the rationale now lives once on the predicate's doc, and the three site
comments (which also referenced the reference implementation, against the
comment convention) are gone.

Isolation: one named predicate for "a $-suffixed marker other than the
bare $"; the intent is stated once instead of re-explained per site.
Foundation: the marker-name predicate is the reuse point if a fourth
lib-mode gate appears.
Risk: identical boolean, surrounding conditions unchanged — behavior
provably preserved. convergence 203/203 and full 1192/1192 unchanged.

Deferred (NOT behavior-preserving as pure refactors):
- isHtmlTagName (4 copies): three genuinely different rules — any-lowercasing
  char vs strict ASCII a-z vs not-uppercase-letter. They disagree on
  digit/non-ASCII-initial tags; unifying normalizes behavior.
- signal-result const/var classification (2 sites): diverge on
  param/in-loop handling — sharing would close a parity gap = change output.
- createTransformSession adoption (5 sites): a parse-mechanism swap with
  wrapper prefix/suffix offset math to verify per site; too much risk
  layered on batch B's const-propagation changes for a boilerplate win.
- marker->Qrl slice dup: the diagnostic caller may not want getQrlCalleeName's
  $/sync$ special-casing; needs verification, not a blind swap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor: split wireMigration into a helper sequencer (hygiene batch E)

What: wireMigration was a ~200-line function interleaving five concerns.
Extract three named helpers, mirroring the generateAllSegmentModules
sequencer pattern (OSS-343):
- resolveMovedDeclImportDeps — a moved decl's import dependencies.
- emitMovedDeclaration — marker-QRL vs plain-decl emission.
- filterMigratedCaptures — drop migrated names from captures + reconcile
  the captures flag against paramNames.
wireMigration is now a ~40-line orchestrator: auto-imports, pre-scan
sets, the move loop (calling the two per-decl helpers), then the capture
filter. Also folded the move-loop's reexport guard to an early-continue.

Isolation: each concern is independently readable and named; the move
loop reads as "resolve deps, emit" instead of 100 lines inline. The
shared-mutation surface (captureInfo, movedQrlSymbols) is now threaded
explicitly through helper parameters rather than closed over.
Foundation: the per-decl helpers are the natural extension points for
the deferred SWC transitive-ordering work (topological emit) noted in
OPTIMIZER.md's migration deep dive.
Risk: pure code motion. typecheck clean; convergence 203/203 and full
1192/1192 baseline-passing tests unchanged. Net -5 LOC.

Also updates the OPTIMIZER.md line refs this move invalidated
(wireMigration/buildDefaultStrategySegment/generateAllSegmentModules).
The doc's other segment-generation.ts refs carry pre-existing cumulative
drift and are left for a dedicated line-ref refresh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor: drop self-evident docs on two batch-B helpers

collectConstLiteralValues and isCaptureWrappingQrlCall each carried a doc
block that only restated what the name + logic already say (the offset
parameter's two modes are shown by its two call sites; the q_<sym>.w
shape is exactly what the predicate checks, and the const-classification
rationale belongs at the call site, not on the shape detector). Comment-
only; no behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Deletions (assert nothing / exact duplicate):
- extract.test.ts: two disambiguateExtractions stubs — one had zero
  expect() calls, the other only asserted length on an input that by
  construction produces no disambiguation. Both superseded by the working
  "disambiguates multiple extractions with same display name" test.
- fnsignal-nonreactive-map.test.ts: a byte-identical duplicate of
  fnsignal-computed-key.test.ts's computed-key test.
- segment-only-debug.test.ts: a debug harness ending in
  expect(true).toBe(true) that ran a full-corpus transform each CI run to
  console.log a report — an investigation artifact, not a test, and not
  referenced by any doc.

Strengthened in place (kept the test IDs; each now fails on real
regression instead of passing vacuously):
- failure-families.test.ts: had zero assertions (a categorize-and-log
  harness). Added corpus-present + complete-partition guards so a missing
  or dropped snapshot surfaces. Kept as a test since docs reference it as
  a secondary signal.
- transform.test.ts: two ctxKind tests asserted inside `if (seg)` guards
  that vanish if extraction stops emitting the segment — now assert the
  segment is found first. The const-vs-var test only checked a
  `_jsxSorted("div"` call existed — now also asserts both prop values
  survive. Dropped a reference-implementation comment.
- rewrite-parent.test.ts Test 9: named "parent-child relationship" but
  only asserted extraction count — now asserts a nested extraction's
  parent resolves to another extraction's symbol.

Baseline: the four deletions drop four passing IDs and the total. Mapped
.ci/baseline.json from the stored (CI-true) baseline — removed exactly
those four IDs, decremented full.total 1217 -> 1213 — rather than
regenerating locally (local totals carry +2 from the QWIK_HOME benchmark
skips). Verified: convergence 203/203, full 1188/1188, 1:1 with zero
unaccounted adds/removes.


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* refactor(OSS-540): extract plainQrlName primitive (finding QwikDev#6)

What: extract the special-case-free `$`→`Qrl` slice into `plainQrlName`;
`getQrlCalleeName` now layers its bare-`$`/`sync$` cases on top of it, and
the C05 diagnostic export-name check uses `plainQrlName` directly instead of
its own inline `slice(0,-1)+'Qrl'`.

Why: removes the duplicated slice while preserving the diagnostic's exact
current behavior — it intentionally does NOT want getQrlCalleeName's marker
special-casing (a user `sync$`/`$` export must still be checked against
`syncQrl`/`Qrl`, not `_qrlSync`/``). Naively sharing getQrlCalleeName would
have changed that; the primitive avoids the change.

Foundation: resolves the OSS-540 "marker→Qrl slice dup" finding as a safe
extraction rather than a behavior-changing merge.

Risk: none — pure extraction. Typecheck clean; +3 plainQrlName pins;
42/42 in rewrite-calls + diagnostics suites, unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-540): unify raw-name HTML predicate on isHtmlElement (finding QwikDev#3)

What: point segment-generation's local `isHtmlElementName` at the canonical
`isHtmlElement`, and drop the redundant a-z re-check in jsx-elements-core's
`tagIsHtml` (its `tag.startsWith('"')` already encodes processJsxTag's
isHtmlElement decision). Left jsx-children's `isComponent` alone — it is a
distinct uppercase check; expressing it as `!isHtmlElement` would flip
member-expression children (empty tagStr → HTML).

Why: the audit flagged "4 copies" of the HTML-tag test, but only one was a
divergent copy of the raw-name predicate. segment-generation used a strict
ASCII a-z rule while the rest of the pipeline uses Rule L (first char equals
its lowercase); they disagreed on digit/non-ASCII-initial tags. Unifying
removes the latent inconsistency and leaves one canonical predicate.

Foundation: resolves the OSS-540 isHtmlTagName finding — single source of
truth for "is this raw tag name an HTML element".

Risk: none on real input. The two rules agree on every valid tag (a-z
lowercase → HTML, A-Z → component); they diverge only on digit/non-ASCII
initials, which are invalid/absent in the fixture corpus. Convergence
203/9 unchanged; +4 edge-case pins (hyphenated, caseless-initial, empty).
The 3 unrelated failures in segment/jsx dirs are pre-existing on main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-540): adopt createTransformSession in 4 body-reparse sites (finding QwikDev#5)

What: replace hand-rolled wrapper-prefix + parseSync + offset-math in four
body-text reparse sites with the canonical `createTransformSession`:
- const-propagation.ts ×3 (resolveConstLiterals, inlineConstCaptures,
  propagateConstLiteralsInBody) — read AST positions, edit the unwrapped
  body via applyReplacements; now use session.program + session.offset.
- lib-mode-collapse.ts substituteInnerQVarsInText — edits a MagicString on
  the wrapped source; now uses session.edits + session.toSource(), which
  also removes the fragile manual `.slice(offset, len-1)` suffix trimming.

Why: every one of these reimplemented the same wrap/parse/offset idiom with
its own prefix (`__rl__`/`__ic__`/`__pb__`/`__body__`) and its own filename,
so their wrapped-source strings never matched the canonical session's — no
shared parse memo, and four subtly different offset computations to keep
correct. Routing them through createTransformSession gives one wrapper idiom
and lets repeated parses of the same body version share a cached parse.

Foundation: resolves the OSS-540 createTransformSession-adoption finding for
the clean-swap sites; single canonical body-reparse path.

Deferred (documented): inline-body.ts's JSX-in-inline-body reparse keeps its
hand-rolled wrapper — its prefix length escapes into the JSX transform's
dev-info `sourcePosition.wrapperPrefixLen`, so adopting the session would
have to thread session.wrapperPrefix.length through source-map positioning;
bounded benefit, real source-map risk, left for a dedicated pass.

Risk: none. parseWithRawTransfer (the session's parse) is exactly the
parseSync(RAW_TRANSFER_PARSER_OPTIONS) these sites used; the offset shift
(15/17 → 16) is applied consistently within each session. Typecheck clean;
const-propagation + lib-mode suites 23/23; convergence 203/9 unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-540): unify ensureCoreImports onto canonical import helpers (finding QwikDev#1)

What: ensureCoreImports now uses `partsHaveImport` for its already-imported
guard and `insertImportBeforeSeparator` for the insert, replacing its
loose `startsWith('import') && includes(sym)` guard and inline
`splice(sepIdx, 0, ...)`. The dead no-separator early-return is dropped.

Why: the audit flagged three divergent guards for "is this symbol already
imported"; ensureCoreImports carried the loosest (substring-on-import-line),
the one most prone to false positives. The single caller guarantees a `//`
separator right before the call, so the early-return branch was unreachable
and the guard's precision was the only real difference. partsHaveImport is
behavior-identical here because the core symbol set has no substring
collisions.

Foundation: resolves the OSS-540 import-before-separator finding for the
provably-safe site; ensureCoreImports now shares one insert idiom with the
rest of import-collection/segment-codegen.

Deferred (documented): the segment-codegen raw-splice sites keep their own
no-separator fallbacks (append-import-then-separator / append-import / skip),
which are genuinely distinct from the canonical unshift and can't collapse
without changing behavior. One of them also has a `, sym`-substring guard
that false-positives on _noopQrl vs _noopQrlDEV; correcting it is a real
behavior change, left out of this behavior-preserving pass.

Risk: none on real input. Guard is identical for the core symbols; no-sep
branch was dead; the insert switch flips core-import order from reverse to
forward, which is not semantically checked (imports are order-independent)
and regresses nothing. Convergence 203/9, full 1188 baseline all pass;
+4 ensureCoreImports contract pins.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-540): share the same-file import ladder (finding QwikDev#2)

What: extract `resolveSameFileImportName` (+ `formatSameFileImport`) as the
single same-file-symbol import resolver, and route both prior copies through
it: import-collection's `addSameFileImport` (which emitted import strings)
and segment-generation's `resolveMovedDeclImportDeps` (which builds
MovedImportDep objects).

Why: the audit flagged these two ladders as divergent — different data
sources (a migration-decision lookup vs a precomputed reexportedNames set)
and opposite reexport-vs-default evaluation order. On inspection they encode
the same decision: the reexport predicate is identical (`reexport &&
!isExported` at both sites), and the reexport/default arms are mutually
exclusive (a default export is always isExported, so it can never enter the
reexport arm), which makes the order difference unobservable. Unifying makes
that equivalence explicit and removes the drift risk of two ladders that
must stay in lockstep by hand.

Foundation: one canonical same-file import resolution; the two callers now
differ only in how they format the shared result (string vs dep object).

Risk: none. The resolver reproduces every arm of both ladders; the order
switch is unobservable by the mutual-exclusivity argument above. Typecheck
clean; convergence 203/9, full 1188 baseline all pass; +8 resolver/formatter
pins covering all four arms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* fix(OSS-540): share _fnSignal deps-const classifier, close _jsxDEV param gap (finding QwikDev#4)

What: extract `fnSignalDepsAllConst` (jsx.ts) as the single deps-const
predicate for _fnSignal prop classification, and route both classifiers
through it — the raw-JSX path (jsx-props `processProps`, two call sites) and
the pre-transformed `_jsxDEV` path (jsx-call-transform `classifyProp`).

Why (behavior change): `classifyProp` was missing the raw path's
component-parameter arm — a dep that's a closure parameter counts as
const-eligible on a *component* element (not on HTML). So on the `_jsxDEV`
path a param-dependent _fnSignal prop on a component element was wrongly
placed in the var-props bag instead of the const bag. Confirmed by
byte-level probe:
  before: _jsxSorted(Inner, { title: _fnSignal(_hf0, [props], …) }, null, null, …)
  after:  _jsxSorted(Inner, null, { title: _fnSignal(_hf0, [props], …) }, null, …)
Now the `_jsxDEV` path classifies identically to the raw-JSX path. The raw
path's other arm (`!inLoop`) is not portable — the `_jsxDEV` path has no loop
tracking — so classifyProp gains only the param arm.

Scope: convergence is unaffected (every fixture is raw JSX; the `_jsxDEV`
path is never exercised there). This path is covered by the jsxdev unit tier
and real bundler builds (qds/router). A qds head-to-head is the definitive
validation — recommended follow-up before relying on the qds output shift.

Also: dropped the SWC-reference comments from the edited processProps block
(the param/component rationale now lives once on fnSignalDepsAllConst's doc).

Risk: full suite + convergence green (203/9, 1188 baseline all pass); no
existing test regressed. +2 jsxdev pins: component element → const bag (the
fix), HTML element → var bag (param arm correctly HTML-gated, unchanged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-540): drop what-comments on small helpers (PR QwikDev#359 review)

Remove WHAT-comments that restated what the name and body already say:
- plainQrlName: doc deleted — name + the getQrlCalleeName body below are
  self-evident, and a test pins the special-case-free contract.
- fnSignalDepsAllConst: trimmed to the one non-obvious WHY (params are
  const-eligible only on component elements).
- ensureCoreImports: doc deleted — name + body say it.

Also restructured processProps's _fnSignal block: the two empty
guard branches (each carrying a fall-through comment) collapse into named
`isRawWhenNonConst` / `excludedFromHoist` booleans, so the code speaks for
itself with no comments.

Behavior-preserving: typecheck clean; convergence 203/9, full 1188 baseline
all pass; no test changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…SS-537 hygiene sweep complete (QwikDev#360)

- main → 36417d2; OSS-538/539/540 Done (PRs QwikDev#357/QwikDev#358/QwikDev#359 merged).
- Header rewritten to the current state: OSS-540's six consolidations, with
  QwikDev#4 flagged as a `_jsxDEV`-path parity change (not a convergence flip) whose
  definitive validation is a still-pending qds head-to-head.
- Measurements: 203/9 convergence, 1188 baseline all pass (+20 absorbed).
- Branches: main head bumped; merged OSS-540 branch removed.
- Progress log: prepend QwikDev#359 + QwikDev#357/QwikDev#358 entries, trim oldest 2.
- Regenerated .cursor/rules mirrors (STATE.mdc; OPTIMIZER.mdc drift corrected).


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…Dev#361)

* refactor: de-any jsx-transform.test.ts AST-extraction helpers

What: replace the two `any`-returning parse helpers (`parseExpr` plus its
dead byte-identical twin `parseJsx`) with four typed helpers — `parseExpr`,
`parseExprStatement`, `parseJsxElement`, `parseJsxFragment` — and collapse
the 18 inline `(program.body[0] as any).expression` node extractions into
single typed-helper calls. Drop the `collectScopeAwareBindings(program as
any)` cast (assignable directly). 20 `any`s and one dead helper removed.

Why (isolation): the helpers now return `Expression` / `JSXElement` /
`JSXFragment` and assert node structure, so a malformed parse throws a named
error instead of silently propagating `undefined` into the assertion — a
strictly stronger test. Upholds the hard "no `any`" type-discipline rule.

Why (foundation): the typed-extraction pattern is the reusable template for
the deferred `tests/optimizer` de-any effort (STATE.md "Held / deferred") —
the same `(body[0] as any).expression` idiom recurs across sibling specs
(capture-analysis, jsx-arrow-prop-value, …) and adopts these helpers next.

Risk: test-only, one file, touches no src. Verified behavior-identical —
62 pass / 2 fail before and after (the 2 are pre-existing SWC-parity
known-failures, not in the baseline passing set, untouched). typecheck
clean; local gate green: convergence 203/203, full 1208/1208 baseline-
passing, zero regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor: extract shared typed AST-parse helpers for tests

What: promote the four typed parse helpers (`parseExpr`,
`parseExprWithSource`, `parseJsxElement`, `parseJsxFragment`) from
jsx-transform.test.ts into a shared `tests/optimizer/helpers/parse-nodes.ts`
module, and adopt them in signal-analysis.test.ts — removing its last two
`any`s (its own `{ node, source }` parse helper duplicated the pattern).

Why (isolation): a second consumer appeared, so the helpers move to one home
instead of being copied. One typed definition of "parse a string into an AST
node", asserting structure at the boundary, now serves both specs.

Why (foundation): this is the reusable surface the deferred `tests/optimizer`
de-any effort (STATE.md "Held / deferred") builds on — sibling specs that
share the `(body[0] as any).expression` idiom adopt these helpers next
instead of re-deriving them.

Risk: test-only, touches no src; the new module is a non-test `.ts` (adds no
tests). Verified behavior-identical — jsx-transform 62/2, signal-analysis
25/1, unchanged before/after (the 3 fails are pre-existing SWC-parity
known-failures outside the baseline passing set). typecheck clean; gate
green: convergence 203/203, full 1208/1208, zero regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…lla filed (QwikDev#362)

PR QwikDev#361 (test-infrastructure de-any) merged to main (d30c4ab):
jsx-transform.test.ts + signal-analysis.test.ts de-anied, shared
tests/optimizer/helpers/parse-nodes.ts extracted. Test-only; gate green
(convergence 203/9 unchanged, full 1208 baseline all pass).

- Bump Last updated + main head SHA (36417d2 -> d30c4ab) + measurements.
- Prepend progress entry; trim oldest (Stranded-QwikDev#348).
- Correct the "Held / deferred" de-any note: now tracked as umbrella
  OSS-541 + subs OSS-542 (tests/optimizer + oxc-walker) / OSS-543
  (ast-compare oracle narrowing -- NOT mechanical as previously billed).
- Regenerate .cursor/rules/STATE.mdc mirror.

OPTIMIZER.md audit: PR touched only tests/ -- no trigger-checklist file,
no update needed.


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
De-any the low-risk test-spec track of the OSS-541 umbrella (test-only).

What changed:
- Typed the oxc-walker pattern in capture-analysis.test.ts (~19 sites) and
  loop-hoisting.test.ts: AstNode/AstFunction callbacks, this.skip() via the
  walker's contextual this, dropped every `program as any`.
- capture-analysis.test.ts: unified the two near-identical dollar-arg helpers
  behind typed collectors (asClosureArg/collectDollarArgs/collectParentScopeIds/
  collectImportedNames/buildDollarArgFacts), removing the duplication.
- Extracted the duplicated AST position-stripping normalizer from
  convergence-breakdown + failure-families into tests/optimizer/helpers/
  ast-normalize.ts (unknown + isRecord narrowing, no casts).
- Typed findFirstCall/findFirstNode to return CallExpression/AstNode and throw
  on absence (the parse-nodes.ts convention); every callsite supplies valid
  input.
- transform.test.ts: `as any` -> `as SegmentMetadataInternal`, the sanctioned
  test idiom already used in stripped-qrl-cleanup.test.ts for reaching the
  internal captureNames field.

Beneficial in isolation: removes the actionable `any` from tests/optimizer,
upholding the "any is never the right answer" rule; kills two duplicated `strip`
normalizers; typed walker callbacks surface AST-shape mistakes at compile time.

Foundation: extends the parse-nodes.ts typed-helper pattern (PR QwikDev#361);
ast-normalize.ts becomes the shared normalizer for breakdown-style tests.
Completes Sub A of OSS-541, leaving OSS-543 (ast-compare.ts oracle) as the only
remaining de-any.

Risk: test-only, behavior-preserving. Casts are erased at runtime; refactored
helpers are semantically identical. Convergence 203/9 and full 1208 baseline all
pass, 0 regressions; the 6 pre-existing transform.test.ts failures are unchanged
(verified against main).

Refs: OSS-542 (sub of OSS-541).


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…subs landed (QwikDev#365)

OSS-542 (QwikDev#363) merged to main (0e56468); OSS-543 (QwikDev#364) In Review.
Bumped main SHA + Last verified; prepended the umbrella progress entry
and trimmed the log to ~10. Regenerated the .cursor/rules/STATE.mdc mirror.


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…v#364)

* refactor(OSS-543): de-any the ast-compare differential oracle

De-any the higher-risk track of the OSS-541 umbrella: the AST
differential-comparison oracle (`src/testing/ast-compare.ts`, ~164 `any`
sites across 71 normalizer functions), consumed by both the convergence
suite and production `output-assembly.ts`.

What changed:
- Every code-level `any` replaced with typed narrowing. Node params ->
  `AstCompatNode`; recursive-clone/walk params + returns -> `unknown`;
  local accumulators -> `Record<string, unknown>` / `unknown[]`.
- Three shared narrowing primitives carry the per-site work: reused
  `isAstNode` from `optimizer/ast/guards.ts`, plus local `isRecord` and
  `asArray` (returns the SAME array reference so in-place push/splice/
  sort/index-assign still mutate the real tree) and `asString`.
- Strict-oxc-typed helpers that actually receive the loose post-strip
  tree were retyped to `AstCompatNode`/`unknown`
  (`isReorderableDeclaration`, `stripFrameworkHelperImports` + its
  closures); the now-unused `Directive`/`ImportDeclaration`/
  `ModuleExportName`/`Program`/`Statement` imports were dropped.
- Removed a provably-dead `=== 'AssignmentPattern'` check in
  `inlineDestructuredBindings` (the preceding `!== 'Identifier'` break
  already covers it) rather than keep a type-defeating `: unknown` dodge.

No `as` casts introduced (the sanctioned one-cast-at-the-boundary lives
inside `guards.ts`'s `isAstNode`); narrowing is guard-based throughout.

Beneficial in isolation: closes the last `any` hole in the test
infrastructure and makes the oracle's dynamic AST access compile-time
checked. Foundation: completes OSS-541.

Risk: this is the differential oracle — a weakened comparison would
silently mask convergence regressions. Verified BIT-IDENTICAL: the full
pass/fail set is unchanged (before pass=1208 fail=25, after pass=1208
fail=25; 0 regressed, 0 newly-passing, 0 gained-fail, 0 lost-fail),
confirmed by re-running the whole suite and diffing test-id sets.
`pnpm typecheck` clean.

Closes OSS-543 (sub of OSS-541).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* refactor(OSS-543): drop doc comments on trivial asArray/asString helpers

Per review: the one-line JSDoc on `asArray`/`asString` only restated the
name + body (WHAT-narration). The names and one-line bodies are self-evident.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…lla closed (QwikDev#366)

OSS-543 (QwikDev#364) merged to main (b7fa34c); OSS-541/542/543 all Done.
Bumped main SHA + Last verified; prepended the close-out entry and
trimmed the log to ~10. Regenerated the .cursor/rules/STATE.mdc mirror.


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…SWC parity) (QwikDev#367)

* fix(OSS-471): MOVE single-consumer server$ binding into its segment (SWC parity)

A module-level `const testServer$ = server$(…)` referenced only inside one
nested `onClick$` was re-exported (`_auto_`) instead of moved into its single
consumer, diverging from the reference optimizer. Four coupled fixes, each
verified byte-for-byte against the reference on the canonical route shape:

- Capture over-attribution: a parent extraction dropped module-level captures
  whose every occurrence falls inside a nested child's byte range. Gated to
  file-emitting strategies — under inline/hoist the child body stays inline
  (`q_X.s(IDENT)`), so the parent still references the name and the reexport
  must survive (e.g. `useStyle$(STYLES)`).
- Escaped-name match in `tryBuildMarkerDeclMove` and the parallel
  `movedMarkerSymbols` detection: a `$`-suffixed decl's displayName is escaped
  (`testServer$` → `…_testServer_server`), so a raw match missed it — leaving a
  broken raw-text move and an un-demoted parent QRL binding.
- Marker-QRL callee imports from the marker's real source (`@qwik.dev/router`),
  not hardcoded core.
- PURE annotation on the moved wrap is per-callee (`componentQrl` pure,
  `serverQrl` not), via `needsPureAnnotation`.

Reachable (non-stripped) output now matches the reference: parent emits a bare
QRL registration, the handler segment is a self-contained
`serverQrl(qrl(…))` move. The stripped variant registers via `_noopQrl` (a
`qrl(()=>import(strippedChunk))` would resolve to the chunk's `null` export);
its local var name is a known cosmetic divergence on an unreachable path.

Three baseline tests that pinned the reexport behavior updated to the MOVE
(IDs kept for the name-based gate); one focused strip-aware test added.
Convergence-neutral (203/203); full suite 1208 pass, 0 regressions, +1 new.

Refs: OSS-471 (sub of OSS-456).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* chore(OSS-471): trim inline docs per review

Apply the comment ladder to the OSS-471 diff: delete WHAT-narration, lean on
self-documenting locals (`moduleLevelCaptures`, `usedOutsideAnyChild`) and
`expect(...)` message args, and drop comments the tests already guard (the
inline/hoist exclusion gate is pinned by the hoist-regctxname STYLES test).
Only genuinely-irrecoverable one-line WHYs remain (the module-level capture
invariant, the escapeSymbol match, the retained test-ID note). No behavior
change — typecheck clean, affected tests + convergence unchanged.

Refs: OSS-471 (sub of OSS-456).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

* chore(OSS-471): drop remaining inline comments; rename tests to match contract

Remove every inline `//` comment from the OSS-471 diff — the code, the
self-documenting locals, and the `expect(...)` messages carry the intent, and
the rationale lives in the commit/PR/Linear. The two router-integration tests
whose names described the old reexport behavior are renamed to state the MOVE
contract directly (no explanatory comment needed); the two baseline IDs are
mapped through in `.ci/baseline.json` (REGRESSION.md deliberate-migration).

No behavior change — typecheck clean, convergence 203/203, full 1208 pass, 0
regressions (verified against the mapped baseline).

Refs: OSS-471 (sub of OSS-456).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… landed (QwikDev#368)

OSS-471 (single-consumer server$ binding MOVE, SWC parity) merged via PR QwikDev#367
→ main (02b2610); OSS-471 Done, closing an OSS-456 sub (OSS-473 is the last
open one). Bump Last-updated + measurements (convergence 203/9 unchanged; full
1209 after baseline auto-update), main-row head SHA, drop OSS-471 from the
Backlog list, prepend the progress entry + trim to 10. OPTIMIZER.md audited —
no update (bug-fix/type-internal; cited refs <50-line drift).


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…migration hygiene) (QwikDev#369)

Prepares the tree for migration into the Qwik core monorepo, where the SWC
optimizer ships as a sibling package and "matches SWC" comments become
actively misleading. Comment-only across 163 files (plus 5 test-name
rewordings); no behavior change.

- Comment volume 9,918 -> 2,617 lines (-74%): deleted WHAT-narration, section
  banners, numbered step markers, JSDoc that restated signatures, and test
  preambles (tests self-document via describe/it names). Kept only
  irrecoverable one-line WHYs (invariants, external-tool workarounds).
- Scrubbed every reference-optimizer mention from comments AND test
  descriptions (~300 across 73 files): SWC, *.rs file:line refs, Rust fn
  names, @qwik.dev/optimizer, "matches SWC"/"SWC parity". Behavioral notes
  reworded as this optimizer's own contract. NAPI retained only where it
  names the native-binding ABI the public types conform to. The benchmark's
  functional SWC references (it loads and times the native optimizer) stay.
- Renamed 7 test names that editorialized "matches SWC"/"NAPI parity";
  the 7 IDs are mapped 1:1 in .ci/baseline.json (deliberate migration).

Verification: oxc-based skeleton proof shows 163/168 changed files
code-identical and the other 5 differ only in the intentional test-name
strings; full suite 1234/1209/25 unchanged from the pre-sweep baseline;
typecheck clean; baseline gate green (203 convergence, 1209 full).


Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Remove TS-Optimizer-repo-specific infrastructure that is redundant inside the
Qwik monorepo (which provides its own): the .ci baseline-regression system and
its scripts/, the .github workflows, .claude/.cursor agent rules, .planning
docs, the agent-sync tooling, the root-only pnpm-lock.yaml, and the
swc-reference-only pinned copy of the optimizer (packages/optimizer is the
source of truth here). Also drop the agent-facing AGENTS.md/CLAUDE.md and the
point-in-time RCA writeup. Package build/test stays self-contained (tsdown +
vitest). History for every removed file is preserved in the grafted commits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v
Reconcile package.json for its new home: drop the baseline/CI scripts (whose
files were removed with the standalone infra), repoint repository/homepage/bugs
to QwikDev/qwik with a `directory` field, and remove the package-level
`packageManager` pin (the root owns it; its version differed from root). Add
the package's dependencies to the workspace lockfile via pnpm install.

Verified in-tree: typecheck clean, `tsdown` build emits dist, and the full
vitest suite runs with a byte-identical pass/fail set to standalone
(1209/1234 passing; the 25 failures are the pre-existing convergence/parity
gaps, unchanged by the move).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v
…timizer

Match the monorepo convention (packages/optimizer -> @qwik.dev/optimizer): drop
the now-redundant `qwik-` prefix and scope the package under @qwik.dev. Moves
the directory to packages/ts-optimizer (history preserved via git rename
detection), updates package name + repository/homepage/directory metadata, the
README, and the index.ts header, and regenerates the workspace lockfile.

Verified in the new location: typecheck clean, build emits dist, full suite
1209/1234 passing (25 pre-existing convergence/parity failures unchanged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJEPKkGz766mEd1Y7pHi8v
@scottweaver
scottweaver requested review from a team as code owners July 23, 2026 14:41
@changeset-bot

changeset-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 39297d4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@Varixo

Varixo commented Jul 23, 2026

Copy link
Copy Markdown
Member

hey @scottweaver, please change target branch to main, v2 is now on main

@scottweaver
scottweaver changed the base branch from build/v2 to main July 23, 2026 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants