Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
cdb46ed
feat(tui-infra): close out node:smol-tui — enforce node: prefix + loc…
jdalton May 22, 2026
08f556b
chore(deps): bump opentui v0.1.99 -> v0.2.15 + drop obsolete rgba-typ…
jdalton May 22, 2026
9f64591
chore: prep-wave cleanups — env import migration + oxlint sort-* auto…
jdalton May 22, 2026
20e7765
chore(lint): convert file-scope oxlint-disable to per-line for vitest…
jdalton May 22, 2026
8a69d76
chore(lint): drop leading underscore from identifiers (fleet rule soc…
jdalton May 22, 2026
6929924
chore(lint): fix socket/no-logger-newline-literal violations (11 sites)
jdalton May 22, 2026
cabf714
chore(lint): convert remaining file-scope oxlint-disable directives t…
jdalton May 22, 2026
8262111
fix(tui-infra): correct include paths in tui_binding.cc
jdalton May 22, 2026
096e83d
feat(tui-infra): add renderables.hpp/cc — DrawBox + DrawTextWrapped (B1)
jdalton May 22, 2026
16fd2b4
feat(node-smol): wire tui::DrawBox + DrawTextWrapped into node:smol-t…
jdalton May 22, 2026
edcb255
feat(node-smol): add stripAnsi to node:smol-util (B-util-strip-ansi)
jdalton May 22, 2026
5f5e287
feat(node-smol): add decodeHtml + encodeHtml to node:smol-util (B-uti…
jdalton May 22, 2026
c7b4e0b
perf(smol-util): tighter stripAnsi + decodeHtml hot paths
jdalton May 22, 2026
43e1a61
feat(tui-infra): node:smol-tui.stringWidth + Unicode 17.0 tables (B-t…
jdalton May 22, 2026
bde3594
chore(deps): add md4c submodule at v0.5.3 (B-md4c-infra scaffolding)
jdalton May 22, 2026
6e1a234
feat(node-smol): node:smol-markdown — CommonMark/GFM parser via md4c …
jdalton May 22, 2026
ebf0d2e
chore(deps): add tree-sitter submodule at v0.26.9 (B-tree-sitter-infr…
jdalton May 22, 2026
5a2bcdf
feat(node-smol): node:smol-tree-sitter — incremental parser binding (…
jdalton May 22, 2026
9f11a35
feat(node-smol): node:smol-webgpu STUB binding (Phase C)
jdalton May 22, 2026
9243d97
feat(node-smol): add userland integration examples for node:smol-tui …
jdalton May 22, 2026
241aabd
perf(tui-infra): BMP fast path in CodepointWidth — skip wide-table se…
jdalton May 22, 2026
1b7c6b3
perf(tui-infra): DrawBox uses FillRect for edges + hoists Cell constr…
jdalton May 22, 2026
59bbea5
perf(smol-util): real fast paths in stripAnsi + encodeHtml — skip UTF…
jdalton May 22, 2026
3fa059f
perf(smol-tui): V8 Fast API for rendererDrawBox + drawTextWrapped + c…
jdalton May 22, 2026
d3021ab
perf(smol-tree-sitter): cache v8::String per node type + cache child …
jdalton May 22, 2026
9af9ebf
perf(smol-markdown): hoist undefined handle + cache event_count
jdalton May 22, 2026
eb5e6c4
perf(tui-infra): Renderer::Flush swaps prev/next buffers + compile-ti…
jdalton May 22, 2026
8140377
perf(tui-infra): hoist Cell-style + row pointer out of DrawText loop
jdalton May 22, 2026
bb7e052
refactor(tui-infra): consolidate DecodeUtf8 + Utf8ByteLen into tui/ut…
jdalton May 22, 2026
6aa226b
perf(tui-infra): specialize WriteU8 — strip dead branches for uint8 m…
jdalton May 22, 2026
093d22d
refactor(tui-infra): move EncodeUtf8 into the shared utf8.hpp
jdalton May 22, 2026
98ab591
perf(tui-infra): hoist y*w into row_base in Renderer::Flush inner loop
jdalton May 22, 2026
2bfe227
perf(smol-util): stack buffers + memchr-vectorized scan for stripAnsi…
jdalton May 22, 2026
dbb74a2
perf(tui-infra): default Cell::operator== + explicit reserved byte fo…
jdalton May 22, 2026
23b324f
perf(smol-util): real SIMD pass for stripAnsi/encodeHtml sentinel scans
jdalton May 22, 2026
40064d4
feat(node-smol): node:smol-keymap — C++ chord matcher (B2)
jdalton May 22, 2026
ae811dd
feat(node-smol): node:smol-qrcode — QR encoder via libqrencode v4.1.1…
jdalton May 22, 2026
49f461c
perf(tui-infra): row-level memcmp fast-skip in Renderer::Flush
jdalton May 22, 2026
4b91e33
perf(smol-keymap): reuse scratch vector across MatchKey calls — no he…
jdalton May 22, 2026
cf3e396
perf(smol-tree-sitter): convert recursive EmitNode to iterative curso…
jdalton May 22, 2026
557bb87
perf(smol-tree-sitter): recursion + depth cap (1024) — matches ultrat…
jdalton May 22, 2026
41216a6
perf(tui-infra): WriteAttributes walks set bits via __builtin_ctz
jdalton May 22, 2026
ff30011
perf(smol-qrcode): zero-copy buffer adoption via ArrayBuffer::NewBack…
jdalton May 22, 2026
ec003b1
perf(smol-markdown): size-aware event vector reserve avoids reallocation
jdalton May 22, 2026
176eff0
perf(smol-markdown): zero-copy parseMarkdownStream — single ArrayBuff…
jdalton May 22, 2026
339a73b
perf(smol-tree-sitter): zero-copy parseStream — single ArrayBuffer wi…
jdalton May 22, 2026
90e99b6
feat(dawn-builder): scaffold new builder package for Dawn / WebGPU (D1)
jdalton May 22, 2026
5f8b27c
chore(deps): add Dawn submodule + lockstep row (D2)
jdalton May 22, 2026
05e9c80
chore(deps): pin Dawn submodule to chromium/7852 branch tip
jdalton May 22, 2026
2f7dada
feat(dawn-builder): cmake + ninja build wrapper (D3)
jdalton May 22, 2026
5c02a64
feat(node-smol): include external pin files in SOURCE_PATCHED cache k…
jdalton May 22, 2026
27d63b3
chore(prim): apply primordials to new smol-markdown / smol-tree-sitte…
jdalton May 22, 2026
b9d02bc
feat(webgpu): gate isAvailable on HAVE_DAWN build define (D5)
jdalton May 22, 2026
67919e2
chore(temporal): consolidate two submodules into one track-latest ref…
jdalton May 22, 2026
4a4f6b6
docs(skills): rewire /updating-node ↔ /updating-temporal-infra coupling
jdalton May 22, 2026
b084c46
chore(cache): bump all cache versions to invalidate after temporal co…
jdalton May 22, 2026
3e0a881
chore(gitmodules): refresh Node sha256 comment to v26.2.0 baseline
jdalton May 22, 2026
86324fe
fix(build-infra): repoint escapeRegExp import to socket-lib v6 export
jdalton May 22, 2026
96a6ef8
fix(build-infra): include -stable aliases in CACHE_BUSTING_DEPS
jdalton May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .claude/skills/updating-node/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,29 @@ sequential:
2. **stubs** — consumes curl + lief; produces platform stubs that
binsuite + node-smol SEA-inject.
3. **binsuite** — consumes stubs (+ curl, lief).
4. **node-smol** — consumes stubs + binsuite + curl + lief; the
final layer.
4. **temporal-infra** — invokes `/updating-temporal-infra` to refresh
the parity reference + audit the C++ port for drift. Short-
circuits if `boa-dev/temporal` hasn't cut a new tag since the
last run (no commit, cascade proceeds). When it DOES move, the
C++ port catches up before node-smol consumes the changes via
`additions/source-patched/`.
5. **node-smol** — consumes stubs + binsuite + curl + lief + the
refreshed temporal C++ port; the final layer.

Adjacent vendor syncs (independent of the chain): `updating-fast-webstreams`,
`updating-zstd` — can run any time.

**Why the order matters:** node-smol embeds the stub-injected `curl`
binary plus the LIEF library; dispatching node-smol before its
binary plus the LIEF library AND consumes the temporal C++ port via
`additions/source-patched/`; dispatching node-smol before its
prerequisites cascade leaves it building against stale dependencies
and surfaces "fixed" issues in the wrong layer.

**Coupling is one-way:** `/updating-node` exercises
`/updating-temporal-infra` so every Node bump has a current parity
reference. A standalone `/updating-temporal-infra` run (boa-dev/temporal
cuts a tag while Node is current) does NOT drag in a Node rebuild.

### Phase 4: Report

Version change, commits created, patch status, post-update results.
Expand Down
101 changes: 24 additions & 77 deletions .claude/skills/updating-temporal-infra/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,69 +22,19 @@ submodule + lockstep row when upstream cuts a new release.
- **Kind**: `feature-parity` (lockstep.json) — the port re-implements
the Rust crate's externally observable behavior, not the source.

## Why this tracks-latest (not locked) — emerging language feature

[`Temporal`](https://tc39.es/proposal-temporal/) is the
**Stage 4** ECMAScript proposal (recently promoted from Stage 3)
for first-class date/time/timezone/calendar handling. Spec:
<https://tc39.es/proposal-temporal/>. Implementations are still
shipping (V8 14.x has it behind a flag), boa-dev/temporal lands
fixes regularly, and divergence between our port and the
canonical Rust implementation is a real risk.

### UNLIKE lief / curl / cjson / libdeflate / etc.

For most upstreams socket-btm vendors, we sync the submodule SHA
to **whatever version upstream Node ships** (via `deps/<name>/`).
That's the right policy for stable C/C++ libraries with frozen
APIs — the goal is reproducible Node builds, not tracking the
library's own cadence.

**Temporal is different.** It's an emerging language feature, not
a stable utility library:

- The TC39 proposal is still settling edge cases (calendar
ambiguity, ISO week math, leap-second semantics).
- boa-dev/temporal cuts releases on its own cadence, often
faster than upstream Node bumps.
- V8's Temporal implementation lives in
`deps/v8/src/objects/js-temporal-objects.cc` and depends on
the Rust crate via FFI through `temporal_capi`. V8 may pin
an older boa-dev/temporal than what's current.
- Locking us to V8's pin would mean the C++ port can never
exercise newer Temporal API shapes than what V8 happens to
ship — defeats the point of an independent port.

**Two submodules, two policies:**

| Submodule | Policy | Driven by |
|---|---|---|
| `packages/node-smol-builder/upstream/temporal` | **locked** to upstream Node's `deps/crates/Cargo.toml` pin (currently v0.1.0) | `updating-node` cascade |
| `packages/temporal-infra/upstream/temporal` | **track-latest** boa-dev/temporal release | this skill |

**They DO NOT need to agree.** node-smol's submodule is what V8
links against (the Rust crate compiled into the binary).
temporal-infra's submodule is the **parity reference** for the
hand-written C++ port — source of truth for "what should the API
surface look like." A newer parity reference than what V8 ships
against is fine; the C++ port matches the upstream API even when
V8 doesn't expose every new symbol yet.

The annotations in `.gitmodules` make this explicit:
## Why this tracks-latest — emerging language feature

```
# temporal-v0.1.0 (locked: pinned by upstream Node ...)
[submodule "packages/node-smol-builder/upstream/temporal"]
...
# temporal-vX.Y.Z (track-latest: bump independently via updating-temporal-infra)
[submodule "packages/temporal-infra/upstream/temporal"]
...
```
[`Temporal`](https://tc39.es/proposal-temporal/) is the **Stage 4** ECMAScript proposal (recently promoted from Stage 3) for first-class date/time/timezone/calendar handling. boa-dev/temporal lands fixes on its own cadence — often faster than upstream Node bumps — and the C++ port at `packages/temporal-infra/src/socketsecurity/temporal/` mirrors the canonical Rust crate so the port stays aligned with what the spec is actually doing.

V8's link target is the **vendored copy** inside the Node submodule at `deps/crates/vendor/temporal_rs/`. That's V8's concern; we don't track it explicitly. Our single top-level temporal submodule (`packages/temporal-infra/upstream/temporal`) exists for the C++ port to consume — track-latest, no separate locked copy.

The same logic applies to any **future emerging-feature ports** (decorators, pattern matching, etc.) — the `*-infra` package tracks the proposal cadence; V8's link target stays whatever Node ships.

## Coupling with `/updating-node`

`/updating-node` invokes this skill as a sub-step in its Phase 3 cascade order (between `binsuite` and `node-smol`). When Node cuts a new tag, the cascade refreshes the parity reference and audits the C++ port for drift before building node-smol. If this skill's Phase 2 short-circuits at "already at latest," the cascade proceeds straight to node-smol with no temporal commit.

The same logic applies to any **future emerging-feature ports**
(decorators, pattern matching, etc.) — the *-infra package
tracks the proposal cadence, the node-smol vendor copy stays
locked to whatever Node ships.
The reverse coupling does not apply: a standalone temporal bump (this skill invoked directly) does NOT drag in a Node rebuild.

## Process

Expand All @@ -103,21 +53,16 @@ CURRENT=$(git describe --tags 2>/dev/null || echo "unknown")

If `LATEST == CURRENT`, exit 0 with "already at latest."

### Phase 3 — Bump only temporal-infra's submodule
### Phase 3 — Bump the temporal submodule

```bash
# Bump temporal-infra to the latest upstream tag.
# Bump the canonical temporal submodule to the latest upstream tag.
git -C packages/temporal-infra/upstream/temporal checkout "$LATEST"
```

**Do NOT bump `packages/node-smol-builder/upstream/temporal`** —
that submodule is locked to upstream Node's `deps/crates/Cargo.toml`
pin. Bumping it independently would diverge what V8 links against
from what upstream expects, and is the `updating-node` skill's
job, not this one.
Update the `.gitmodules` annotation: `# temporal-vX.Y.Z (canonical temporal submodule; …)` → new tag.

Update `.gitmodules` annotation for THIS submodule only:
`# temporal-vX.Y.Z (track-latest: ...)` → new tag.
There is exactly one temporal submodule (consolidated from the earlier two-submodule split in commit `67919e29`). V8's link target lives in the vendored Rust crate inside the Node submodule (`deps/crates/vendor/temporal_rs/`) and is unaffected by this bump — bumping the parity reference cannot diverge V8's link target.

### Phase 4 — Update lockstep.json

Expand Down Expand Up @@ -202,10 +147,12 @@ a parser update across all 4 ultrathink lang impls.
follow-ups for task #217 (the implementation work). Don't block
the SHA bump on having every symbol ported; the port catches
up incrementally.
- **node-smol's submodule SHA drifts ahead of temporal-infra's**:
fine — node-smol's vendored copy is the V8 link target;
temporal-infra's is the parity reference and may legitimately
be ahead. Concerning only in the reverse direction (V8 has a
newer Temporal API than the parity reference), in which case
consult upstream Node's `deps/crates/Cargo.toml` and decide
whether to bump temporal-infra forward.
- **V8's link target is newer than the parity reference**:
V8's vendored `deps/crates/vendor/temporal_rs/` (inside the Node
submodule) is whatever Node ships; the parity reference at
`packages/temporal-infra/upstream/temporal` is whatever
boa-dev/temporal cuts. Usually parity is ahead. If V8 is ahead
(rare — only when Node ships a brand-new temporal_rs before
boa-dev tags it), consult upstream Node's `deps/crates/Cargo.toml`
and bump the parity submodule to a commit that matches or
exceeds V8's pin.
Loading