Skip to content

fix: Diagnostics + Edge Cases - #82

Merged
codecaaron merged 9 commits into
mainfrom
fix/ani-015-root-issues
Aug 7, 2026
Merged

fix: Diagnostics + Edge Cases#82
codecaaron merged 9 commits into
mainfrom
fix/ani-015-root-issues

Conversation

@codecaaron

Copy link
Copy Markdown
Owner

No description provided.

codecaaron and others added 9 commits August 7, 2026 01:43
…ject selectors (ANI-027 part 1)

Ancestor-prefixed subject keys ('[x] &') previously fell through selector
recognition and vanished with zero diagnostics; registered aliases with the
same shape emitted dead '.C[x] &' rules. Extraction now records a
per-property skip carrying the stable code animus.selector.unsupported-subject
(error severity), selector-alias values are validated at the system boundary,
and one policy point in manifest-diagnostics escalates error-severity
diagnostics to build failures under strict while non-strict consumers warn.

CssDiagnostic gains optional code/severity fields (absent fields serialize
byte-identically). OpenSpec change: ani-015-root-issues (increment 01).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… transparency (ANI-020)

Deliberate v1-parity departure (register-tracked): parse_variant_arg and the
compound second arg now resolve identifier-backed maps, base styles, and
option objects through the same extraction-time statics as .styles()
arguments — same-file or imported across package boundaries via engine Pass A.
TS type wrappers (as const, satisfies, non-null, parens) are transparent at
every evaluation surface: const collection, expression eval, object/identifier
span indexing, and chain-argument capture, so `.styles(x as const)` extracts
like `.styles(x)` instead of dropping the chain.

Inline-vs-binding byte-equality pinned at unit and engine level; genuinely
dynamic maps keep their skip witness. Parity oracle byte-stable (register
stayed empty). OpenSpec change: ani-015-root-issues (increment 02).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y (ANI-024)

A style-only edit re-transforms to byte-identical output (class names hash
filename::binding, never style values), yet the changed module was forwarded
unconditionally — the zero-new-bytes js-update re-executed the module, minted
a fresh createComponent forwardRef, and remounted the consumer's React
subtree (Ark IDs regenerated, focus fell to body, contenteditable state
lost). The hot-update hook now records the hash of each component-bearing
module's served output at transform time and, when a post-edit re-transform
matches it, excludes the module from the update set while still delivering
CSS through the components virtual module. The decision is computed once by
the owning dispatch and travels in HotUpdateResult; suppressed modules are
re-warmed via transformRequest so later unrelated updates never observe an
invalidated node. Mixed style+code edits deliver normally (full-output hash,
never replacement strings).

Also removes the write-only fragmentCache (incrementality honesty; its
unimplemented fragment-splice spec requirement is retired in the same
OpenSpec change) and adds hot-payload capture + module-warmth probes to the
dev-lane adapter with four gate scenarios.

OpenSpec change: ani-015-root-issues (increment 03).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
createKeyframes collections in external package entries were invisible:
discovery was a QuickJS scan of the consumer system entry only, so
`animationName: motion.pulse` via a named import was rejected as a
non-static member expression and silently dropped. A new keyframes-only
loader scan (scanKeyframesExports) evaluates each discovered external entry
through the same strip/resolve/bundle/eval pipeline and reads NOTHING but
`__brand === 'Keyframes'` named exports — the consumer system remains the
singular config authority for everything else. Collections merge into the
analysis inputs (consumer wins name collisions, coded diagnostic
animus.keyframes.export-collision; failed entries degrade to
animus.keyframes.external-entry-failed instead of aborting analysis), and
the existing export-name registry + Pass A enrichment + single emission
path resolve refs with zero new Rust hashing (runtime FNV stays the only
name implementation). Both plugins wired, including re-apply after
geological-reset system reloads; discovery-time diagnostics travel through
the single shared surfacing policy point via AnalysisOptions.extraDiagnostics.

OpenSpec change: ani-015-root-issues (increment 04).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d, and functional-pseudo subjects (ANI-027 root fix)

The stored selector form becomes the full &-carrying branch and every
emission/composition site substitutes the composed class at each unquoted
subject position (quote-aware, so attribute values containing & are never
rewritten). '[aria-sort="ascending"] &', '[x] &:hover', comma lists mixing
leading and ancestor branches, registered ancestor aliases
(_groupHover: '.group:hover &'), ':is(&, .peer)', and sibling-self '& + &'
all emit correctly — the last previously emitted a dead '.C + &' rule.
Bare ':hover' shorthands gain their implicit subject; leading-subject forms
reproduce today's bytes exactly (parity oracle: 64/64, zero divergences).
Cascade bucketing classifies by the subject suffix, preserving every
existing bucket. The unsupported-subject diagnostic narrows to keys whose
every & sits inside quoted text; selector-alias validation follows.
RawSelectorKey widens so the & may sit anywhere in a typed key, with
positive and negative type-contract tests.

OpenSpec change: ani-015-root-issues (increment 05).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…or selectors, and external keyframes (increment 06)

test-ds now exports an as-const variant map (kitSizes), a createKeyframes
collection (kitMotion) from its entry, registered ancestor aliases
(_groupHover/_dark), and an ancestor-selector recipe (GroupItem);
e2e/vite-app consumes each next to inline siblings and its assert lane
gains four helpers: variant declaration parity (binding-backed vs inline —
byte-identical, Lightning CSS merges the sibling rules), unique keyframes
bodies, ancestor/repeated-subject selector emission, and a zero-literal-&
sweep (guardrail G7). Showcase docs' _print at-rule-as-selector example is
replaced with _rtl; the verified _groupHover/_dark and '& + &' examples
stand. e2e/next-app gains transpilePackages for the TS-source test-ds entry
(webpack applies no transpilation to external package sources; the animus
loader passes componentless files through verbatim by spec) — a product
finding for real TS-source DS packages on Next+webpack.

OpenSpec change: ani-015-root-issues (increment 06, delegated).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecaaron
codecaaron merged commit c291b97 into main Aug 7, 2026
12 checks passed
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.

1 participant