Files
rose-ash/plans/hs-blockers-drain.md
giles 4f98f5f89d hs: drain plan for blockers + Bucket E + F
Tracks the path from 1277/1496 (85.4%) to 100%. Records each blocker's
fix sketch, files in scope, and order of attack. Cluster #31 spec'd in
detail for the next focused sit-down.
2026-04-25 08:54:05 +00:00

7.0 KiB

HS conformance — blockers drain

Goal: take hyperscript conformance from 1277/1496 (85.4%) to 1496/1496 (100%) by clearing the blocked clusters and the design-done Bucket E subsystems.

This plan exists because the per-iteration loops/hs agent can't fit these into its 30-min budget — they need dedicated multi-commit sit-downs. Track progress here; refer to plans/hs-conformance-to-100.md for the canonical cluster ledger.

Current state (2026-04-25)

  • Loop running in /root/rose-ash-loops/hs (branch loops/hs)
  • sx-tree MCP fixed (was a session-stale binary issue — restart of claude in the tmux window picked it up). Loop hinted to retry #32, #29 first.
  • Recent loop progress: ~1 commit/6h — easy wins drained, what's left needs focused attention.

Remaining work

Bucket-A/B/C blockers (small, in-place fixes)

# Cluster Tests Effort Blocker Fix sketch
17 tell semantics +3 ~1h Implicit-default-target ambiguity. bare add .bar inside tell X should target X but explicit to me must reach the original element. Add beingTold symbol distinct from me; bare commands compile to beingTold-or-me; explicit me always the original.
22 window global fn fallback +2-4 ~1h foo() where foo isn't SX-defined needs to fall back to (host-global "foo"). Three attempts failed: guard (host-level error not catchable), env-has? (not in HS kernel), hs-win-call (NativeFn not callable from CALL). Add symbol-bound? predicate to HS kernel OR a host-call-fn primitive with arity-agnostic dispatch.
29 hyperscript:before:init / :after:init / :parse-error events +4-6 ~30m (post sx-tree fix) Was sx-tree MCP outage. Now unblocked — loop should retry. 4 of 6 tests need stricter parser error-rejection (out of scope; mark partial). Edit integration.sx to fire DOM events at activation boundaries.

Bucket D — medium features

# Cluster Tests Effort Status
31 runtime null-safety error reporting +15-18 2-4h THIS SESSION'S TARGET. Plan node fully spec'd: 5 pieces of work.
32 MutationObserver mock + on mutation +10-15 ~2h Was sx-tree-blocked. Now unblocked — loop hinted to retry. Multi-file: parser, compiler, runtime, runner mock, generator skip-list.
33 cookie API +2 (remaining) ~30m Partial done (+3). Remaining 2 need hs-method-call runtime fallback for unknown methods + hs-for-each recognising host-array/proxy collections.
34 event modifier DSL +6-8 ~1-2h elsewhere, every, count filters (once/twice/3 times/ranges), from elsewhere. Pending.
35 namespaced def +3 ~30m Pending.

Bucket E — subsystems (design docs landed, multi-commit each)

Each has a design doc with a step-by-step checklist. These are 1-2 days of focused work each, not loop-fits.

# Subsystem Tests Design doc Branch
36 WebSocket + socket + RPC Proxy +12-16 plans/designs/e36-websocket.md worktree-agent-a9daf73703f520257
37 Tokenizer-as-API +16-17 plans/designs/e37-tokenizer-api.md worktree-agent-a6bb61d59cc0be8b4
38 SourceInfo API +4 plans/designs/e38-sourceinfo.md agent-e38-sourceinfo
39 WebWorker plugin (parser-only stub) +1 plans/designs/e39-webworker.md hs-design-e39-webworker
40 Real Fetch / non-2xx / before-fetch +7 plans/designs/e40-real-fetch.md worktree-agent-a94612a4283eaa5e0

Bucket F — generator translation gaps

~25 tests SKIP'd because tests/playwright/generate-sx-tests.py bails with return None. Single dedicated generator-repair sit-down once Bucket D is drained. ~half-day.

Order of attack

In approximate cost-per-test order:

  1. Loop self-heal (no human work) — wait for #29, #32 to land via the running loop ⏱️ ~next 1-2 hours
  2. #31 null-safety — biggest scoped single win, dedicated worktree agent (this session)
  3. #33 cookie API remainder — quick partial completion
  4. #17 / #22 / #34 / #35 — small fiddly fixes, one sit-down each
  5. Bucket E — pick one subsystem at a time. #39 (WebWorker stub) first — single commit, smallest. Then #38 (SourceInfo) — 4 commits. Then the bigger three (#36, #37, #40).
  6. Bucket F — generator repair sweep at the end.

Estimated total to 100%: ~10-15 days of focused work, parallelisable across branches.

Cluster #31 spec (full detail)

The plan note from hs-conformance-to-100.md:

18 tests in runtimeErrors. When accessing .foo on nil, emit a structured error with position info. One coordinated fix in the compiler emit paths for property access, function calls, set/put.

Required pieces:

  1. Generator-side eval-hs-error helper + recognizer for expect(await error("HS")).toBe("MSG") blocks. In tests/playwright/generate-sx-tests.py.
  2. Runtime helpers in lib/hyperscript/runtime.sx:
    • hs-null-error! raising '<sel>' is null
    • hs-named-target — wraps a query result with the original selector source
    • hs-named-target-list — same for list results
  3. Compiler patches at every target-position (query SEL) emit — wrap in named-target carrying the original selector source. ~17 command emit paths in lib/hyperscript/compiler.sx: add, remove, hide, show, measure, settle, trigger, send, set, default, increment, decrement, put, toggle, transition, append, take.
  4. Function-call null-check at bare (name), hs-method-call, and host-get chains, deriving the leftmost-uncalled-name ('x' / 'x.y') from the parse tree.
  5. Possessive-base null-check (set x's y to true'x' is null).

Files in scope:

  • lib/hyperscript/runtime.sx (new helpers)
  • lib/hyperscript/compiler.sx (~17 emit-path edits)
  • tests/playwright/generate-sx-tests.py (test recognizer)
  • tests/hs-run-filtered.js (if mock helpers needed)
  • shared/static/wasm/sx/hs-runtime.sx + hs-compiler.sx (WASM staging copies)

Approach: target-named pieces incrementally — runtime helpers first (no compiler change), then compiler emit paths in batches (group similar commands), then function-call/possessive at the end. Each batch is one commit if it lands +N tests; mark partial if it only unlocks part.

Watch for: smoke-range regressions (tests flipping pass→fail). Each commit: rerun smoke 0-195 and the runtimeErrors suite.

Notes for future sessions

  • plans/hs-conformance-to-100.md is the canonical cluster ledger — update it on every commit.
  • plans/hs-conformance-scoreboard.md is the live tally — bump Merged: and the bucket roll-up.
  • Loop has scope rule "never edit spec/evaluator.sx or broader SX kernel" — most fixes here stay in lib/hyperscript/**, tests/, generator. If a fix needs kernel work, surface to the user; don't merge silently.
  • Cluster #22's symbol-bound? predicate would be a kernel addition — that's a real cross-boundary scope expansion.