This file adds repo-specific rules for the @async/framework checkout. The
root workspace AGENTS.md still applies.
- Work from this repository checkout and check
git status --short --branchbefore editing. - This package is
@async/framework: a no-build Async runtime with browser and server entrypoints, signals, command events, route partials, cache split, SSR activation, and streaming boundaries. - Use Node.js 24 or newer and
pnpm11. Keep the package ESM-only with.jssource files and explicit.jsimport extensions. Do not add.mjsfiles unless a tool explicitly requires one. - Main source lives in
src/; tests live intests/<suite>/*.test.js, categorized by suite (unit,runtime,router,server,timing,performance,build,examples— seetests/README.md); examples live inexamples/; docs and system contracts live inREADME.md,docs/, andspecs/.
- For behavioral changes, start with
specs/framework.md, then read the relevantspecs/framework/*.mdsubsystem contract before editing. - If implementation and specs disagree, treat it as a framework design issue: deliberately update the spec or change the implementation to match it.
- Preserve the core runtime contract: no VDOM, no hidden hydration/diff/rerender path, no implicit fetches during startup, and no server-only state or cache contents leaking into browser snapshots.
- Keep the no-compiler layers (L0-L3, L5) understandable without future compiler layers. Compiler-layer work (L4, L6, L7) must compile down to the same HTML, registry, snapshot, server-envelope, route-partial, cache, and boundary protocol.
Use these abbreviations in ADRs, issues, review notes, and Codex prompts:
The layer model is the L0-L7 abstraction layers owned by
specs/framework/15-abstraction-layers.md. Layers are authoring abstractions;
capabilities are protocol properties available from the lowest layer the
protocol allows.
L0Enhance: behavior references on server-owned HTML. Protocol attributes plus a script tag; native/MPA partial swaps; no app model, build, or client router.L1Interpret: the runtime-interpreted app model, no build. Registries,Async.use(...)conventions, scoped fragment components, lifecycle, scheduler-batched bindings.L2Bundle: build as delivery plus client routing and an app server. Bundling must not change protocol semantics; the build stays optional here.L3SSR: server-rendered component functions with browser activation from snapshots. No hydration, no rerender. (Not "Resume": resume is the protocol-wide contract, not a layer.)L4Transform: JSX/TSX source transforms lowering onto the same protocol, mainly JSX/TSX lowering to protocol records. First layer where a build is required.L5Stream: progressive documents; boundary fallback and settling; reveal ordering; async signals settling server-side. No compiler required.L6Reorder: out-of-order settling automated by the Optimizer: Qwik-styleserver$, co-located server-function extraction, chunks, lazy descriptors, generated plans, runtime slices. The OOS protocol itself is L5-available.L7Optimize: whole-program compiler (specs/framework/16-whole-program-compiler.md). Specification only.- Legacy mapping: pre-2026-07 notes use
L1for layers L0-L1,L1.5for the server/streaming capability set (now spread across L3 and L5), andL2for the compiler layers (L4, L6, L7). See the legacy table inspecs/framework/15-abstraction-layers.md. NB: no-build profile, covering layers L0-L3 and L5. Author HTML and JavaScript run directly withAsync.start(...), default shorthand attributes, and no compiler.BR: build-required profile, covering layers L4, L6, and L7. Author JSX/TSX uses imports such as@async/framework/jsx; the compiler/optimizer emits protocol-compatible output the no-compiler layers can speak.OOS: out-of-order streaming/rendering. Chunks may become ready in a different order than source order.Suspense: async boundary ownership for fallback and final content.Reveal: OOS commit policy for sibling boundaries, such asas-ready,forwards,backwards,together, plus tail visibility.Plan: generated or virtual framework plan. In BR it is private compiler plumbing, not a hand-written author API.Optimizer: the L6 BR compiler pipeline that classifies source, signals, ownership, events, Suspense/Reveal, runtime slices, chunks, and plan output. Distinct from the deferred L7 whole-program compiler.
- In framework docs, ADRs, specs, examples, review notes, and prompts, always
describe author-facing syntax with the default shorthand prefixes:
async:,signal:,on:,class:, andintersect:. - Use
on:syntax for no-build event examples. Use JSX event props such asonClickonly when the subject is the BR JSX authoring profile or its lowering toon:click. - Treat
data-async-*,data-signal-*,data-on-*, and related data attributes as configured compatibility forms, not the framework's syntax. Do not use them when explaining syntax or giving ordinary examples. Mention them only when the subject is custom attribute configuration, raw compatibility behavior, or compatibility tests. - For reveal examples, prefer
async:reveal,async:reveal-order, andasync:reveal-tail.
- Edit source, tests, examples, scripts, specs,
package.json, andpipeline.ts; do not edit generated output as the source of truth. scripts/build-framework-bundle.jsowns generated package artifacts indist/, includingbrowser.js,browser.min.js,browser.umd.min.js,browser.ts,browser.d.ts,framework.ts,framework.d.ts,server.js, anddist/package.json.- The generated
dist/directory is the package root fornpm packand release publishing. Consumers still receive package-root artifacts; they should not import fromdist/. pipeline.tsowns GitHub Actions, Pages, release, GitHub Packages mirror, npm publish, release doctor wiring, and generated pipeline scripts/locks.- Do not hand-edit
.github/workflows/async-pipeline.ymlexcept to inspect generated output. Changepipeline.ts, then run:
pnpm run pipeline:sync:generate
pnpm run pipeline:sync:check
pnpm run pipeline:github:check- For public API or export-map changes, update the relevant source exports, docs/specs, and tests together.
- Cover root imports,
@async/framework/browser,@async/framework/server, generated declarations, and browser/server bundle separation when the public surface changes. - Do not run local package verification commands such as
pnpm run pack:check,npm pack, or local publish dry runs by default. Leave package verification to the release workflow unless the user explicitly asks for a local package check. - Keep browser bundles free of server-only registry internals and implicit global fetch behavior.
- Focused behavior check:
node --test tests/<suite>/<area>.test.js, or a whole suite viapnpm run test:<suite>(unit,runtime,router,server,timing,performance,build,examples). - Frame-timing or commit-phase changes must add coverage in
tests/timing/with an explicit frame-timed scheduler (seetests/README.md) — node's synchronous commits hide browser-only failures. - Hot-path changes (files registered in
tests/performance/hot-paths.json) must keep the performance contracts green; new hot paths get a registry entry, a// @hot-paths:contract test, and atest.performancepipeline input so changes auto-select the suite. - Runtime checks:
pnpm testandpnpm run bundle:check. - Registry/docs/workflow checks:
pnpm run registry:lint,pnpm run pipeline:pages, andpnpm run release:check. - Documentation-only changes can use
git diff --checkwhen package behavior, generated artifacts, and workflow definitions are untouched.
- Release automation stays generated through Async Pipeline and
async/actions. - The publish order is GitHub Packages mirror first, npm publish second, and release doctor last.
- Do not bypass the generated GitHub Actions publish path with local publish commands unless the user explicitly asks for a local release operation.