Skip to content

feat: implement Beta.2.1 unified Router and standalone Element tooling - #1343

Merged
SisyphusZheng merged 37 commits into
devfrom
codex/beta2-1-router-core
Sep 9, 2026
Merged

feat: implement Beta.2.1 unified Router and standalone Element tooling#1343
SisyphusZheng merged 37 commits into
devfrom
codex/beta2-1-router-core

Conversation

@SisyphusZheng

@SisyphusZheng SisyphusZheng commented Sep 8, 2026

Copy link
Copy Markdown
Member

Beta.2.1: Router/core convergence, standalone Element, prerelease semantics

Target

Beta.2.1 implementation for #1320, #1323, #1324, #1325 and #1338, under ADR-0152 and
docs/current/VERSION_PLAN.md. #1342 has landed (squash merge 3ad55e84 into dev;
its qualified head bc73198c was green at merge time, merged with expected-head-SHA
protection). This branch is refreshed onto the landed dev (merge cdf7540c), so the
planning content now arrives through real base ancestry.

Architecture

route declarations (explicit Route Mode + generated Framework Mode records)
        ↓
    RouteTable            ← one URL record chosen before method dispatch
        ↓
 URLPatternList           ← ordered first-match, value identity
        ↓
 RouteResolution          ← match / 405+Allow / not-found
     /       \
 Request    Navigation
  Hono    Navigation API   ← executors, never a second matcher
  • path is the only pathname truth; pattern (RoutePatternComponents) carries only
    non-pathname URL components and a runtime pathname is rejected, not silently honored.
  • Pathname captures and URLSearchParams stay separate; router.searchParams hands out
    per-reader snapshots so loaders/actions cannot mutate router state.
  • SSG discovers eligible static pages from canonical route records and renders through
    the real dispatcher. Browser navigation keeps POST/reload/fragment/download/cross-origin
    browser-owned; every mount gets a fresh AbortController; guard vetoes restore via a
    marked replace navigation that the router never re-intercepts.

What Changed

  • One RouteTable/RouteResolution for explicit and generated records; 405/Allow belongs
    to the URL winner; explicit HEAD wins, otherwise HEAD falls back to GET inside the
    winner with an empty body.
  • SSG page discovery moved from Hono's route list to canonical routeInfo projection
    (host routes preserved, wildcard excluded); the www build emits 150 static pages again.
  • Navigation ownership checks run before pending/intercept side effects; fresh execution
    signal per mount; stale loader/action/guard results never commit.
  • @openelement/adapter-vite/element exposes the existing private compiler plugin for
    standalone Element tooling; packed App/UI edges are optional peers.
  • Version tooling owns the full prerelease identifier chain
    (beta.2 → beta.2.1 → beta.2.2 → beta.2.3 → 1.0.0-alpha.1 by explicit product-stage
    transition); prereleaseNumber is documented as a legacy channel-level field.
  • CI/gates realigned with the architecture: cache-boundary gate slices the generated
    __pageHandlers method table (no-store assertions preserved, non-vacuous); www truth
    gates admit the approved planned version chain and quoted roadmap keys; the critical-path
    gate tracks the renamed path-param evidence; the supplemental AI-review job reports a
    missing/errored review as a warning instead of masquerading as green evidence
    (non-blocking per the 2026-09-09 maintainer decision).

What Was Removed

  • The pre-convergence RouteTable static-map/dynamic-list/sort/query-proxy split and the
    method-dependent winner fallback; the duplicate route.path declaration in generated
    records; the per-page Hono winner/405 paths; pattern.pathname as an override channel.
  • No second matcher, compiler or manifest truth was added anywhere.

Fork / Dependency Boundary

  • open-element/url-pattern-list @ 00bface02e3117222dea9c620a63792545f04c13 (on top of
    upstream v0.5.0 4911e649, history and MIT attribution preserved) carries the qualified
    implementation: 109/109 Node-native tests after a clean npm ci, ordered-linear-oracle
    differential coverage on native and polyfill constructors with seeded/reduced failures,
    and construction/hit/miss/memory benchmarks in its BENCHMARKS.md (GC-controlled,
    retained vs transient; static-only 5000-pattern hit 0.0057ms vs linear 2.82ms; the
    all-conservative scenario honestly degrades to linear). Two genuine upstream bugs have
    recipient-native reproductions drafted in the fork's docs/upstream-issues.md
    (unreported; upstream responsiveness is not an OE gate).
  • Published and consumed: @openelement/url-pattern-list@0.6.0 is on npm (maintainer
    approved the scope correction to OE's own @openelement org; the GitHub repo name is
    unchanged). Registry-verified: version 0.6.0, MIT, repository → open-element/url-pattern-list,
    upstream author attribution retained, integrity
    sha512-djz6c4tih8BL1lonjr41iuoWGGF5pOgldEE0wOB/hzLLB4rS1MQHRQ2X3zM2XxnB6SX5Fphxx7uwTN/+ZDH//g==;
    clean-consumer install + runtime smoke pass. OE consumes it exactly: workspace import map and
    packages/app/deno.json pin npm:@openelement/url-pattern-list@0.6.0, deno.lock records the
    exact version with registry-matching integrity, and packed @openelement/app metadata keeps the
    dependency exact (no caret float). The embedded production copy
    packages/app/src/internal/router/url-pattern-list/ is deleted; provenance/divergence live in
    the fork (PROVENANCE.md / DIVERGENCE.md / BENCHMARKS.md). The switch was the rehearsed small
    diff (constructor entries → addPattern); the differential oracle corpus remains as
    integration tests against the real package.
  • The fork contains no RouteRecord/HTTP/Hono/loader-action/renderer concepts.

Standalone Element

deno task consumer:packaged-element proves author → compile → pack → install outside the
workspace → plain HTML → real registration/attribute/event updates in Chromium 147,
Firefox 148 and WebKit 26.4, with no Router/App/UI installed, no workspace aliases, a clean
browser module graph, 32 reachable declaration modules checked, and authored source maps
retained. The compiler stays private; this is a tooling subpath, not a public compiler API.

Version Semantics

Lossless multi-identifier parsing/comparison; checkpoint succession is explicit
(nextCheckpointVersion), product-stage transition is explicit (1.0.0-alpha.1);
historical internal 0.44.0-alpha.0–10 stay unpublishable; channels map to dist-tags.
beta.3 ordering is legal SemVer but not an approved checkpoint (www truth gate rejects it).
No package version was bumped.

Validation — exact final SHA 3302dd01

Local (macOS arm64, Deno 2.9.0 / Node 24.18.0; Chromium 147 / Firefox 148 / WebKit 26.4):

  • deno task test: 1920 passed (105 steps) + supabase starter 150 passed, 0 failed.
  • deno task build: full chain green; 150 static pages incl. /, /docs, sitemap.xml
    (146 URLs); artifact-truth and link checks pass.
  • deno fmt --check, deno lint, deno task typecheck, arch:check, graph:check,
    workflow:check, docs:truth, actions:check-pins: all pass.
  • Browser navigation: www/e2e chromium full 338 passed; firefox/webkit smoke
    171 + 171 passed; Deno-driven three-browser POST/fragment/reload and packed-Element
    proofs pass.
  • Consumers: consumer:packaged, consumer:packaged-ui, consumer:packaged-element pass
    against freshly packed tarballs.
  • Package-switch focused regression on this SHA: full deno task test 1922 passed
    (105 steps) + starter 150 passed, 0 failed; packages/app and adapter-vite suites pass
    against the published package; the URLPatternList differential corpus runs against
    @openelement/url-pattern-list@0.6.0 itself. Browser navigation coverage runs in this
    SHA's CI (chromium/firefox/webkit e2e inside autoflow-ci). Packed consumers
    (consumer:packaged, consumer:packaged-element — three browsers, and
    consumer:packaged-ui in CI) were re-run against tarballs packed from this SHA.

CI on this exact SHA: autoflow-ci PASS (21m17s full matrix: build, coverage,
critical-paths, chromium/firefox/webkit e2e, request-time/ui-dogfood fixture gates,
starter smoke, static-output freeze, packed consumers)
, pr-full-ci-evidence PASS,
Cloudflare Pages PASS, dist/server Node 20 + Node 24 + Bun smoke PASS, CodeQL /
dependency-review / workspace-qualification / Analyze PASS. The supplemental review
job is green with a warning annotation (no review executed — see below).

Known Non-blocking External Conditions

Release Impact

None: no version bump, tag, npm publish, deployment, merge or issue closure. Examples stay
frozen. Release state and evidence files are unchanged; Beta.2.1 publication remains a
separately gated decision.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

@SisyphusZheng

Copy link
Copy Markdown
Member Author

Maintainer-approved Beta.2.x plan updated on 2026-09-08 in planning PR #1342, ADR-0152, VERSION_PLAN, 15 existing issues and Project 3.

The review comment #1343 (comment) says APIError: Insufficient Balance. The review workflow's SUCCESS is not a completed review. #1332 explicitly owns service recovery and failure propagation as an immediate merge prerequisite, not deferred cleanup. No provider/model or billing changes have been made.

#1343 remains incomplete: SSG output/navigation findings, fork migration/memory baselines, actual review, final-SHA CI and fresh verifier evidence are outstanding. Confirming #1342 ancestry is not a claim of baseline CI success. These planning updates do not repair product code or authorize release. Consume the updated #1342 planning contract before continuing implementation.

DevBot added 9 commits September 8, 2026 22:51
Consumes planning HEAD dcfa2ee. toSSG discovery via app.routes yields
nothing behind app.all('*', dispatcher) (middleware arity filtered);
project eligible static pages (rendering!=dynamic, non-dynamic) for
discovery only, render through real app.fetch/request. Preserve host
routes, exclude wildcard. Align default mock dispatcher with routeInfo.

Fixes RED ssg-render record test; www build 150 pages, /,/docs,sitemap present.
…oller

POST with formData leaves to browser/server before pending/intercept;
fragment-only and reload default browser-owned in history mode, hash
semantics separate. Each spa mount gets a fresh AbortController; stale
loader/action results never commit.

Tests: native ownership unit (POST/fragment/reload/GET), mount fresh
signal (mount/dispose/remount, direct remount stale, action signal),
3-browser POST/fragment/reload proof + existing nav regression.
The ADR-0152 chain (beta.2.1-beta.2.3, then 1.0.0-alpha.1) is planned, not
retired: derive exemptions from lib/version.ts checkpoint/stage successors
instead of banning every non-current prerelease. Unapproved prereleases
(beta.3, historical 0.44.0-alpha.N) stay forbidden; the alpha.N shorthand
no longer matches inside an exempted full version. Fixes the www build
artifact-truth failure introduced by consuming planning HEAD dcfa2ee.
The review action posts provider errors as PR comments while exiting 0, so
the green wrapper was not review evidence (observed on #1343: APIError
Insufficient Balance). A Deno gate now verifies the step outcome and the
run-attributed review comment, matching structural provider/API error
signatures across billing, rate-limit, auth, availability, timeout and model
categories; absence of evidence fails closed. Provider restoration itself
needs external billing action and stays a merge prerequisite.
…patch

fullstack:boundary-check sliced per-route app.get/app.post registrations;
the unified dispatcher keeps per-record handlers in the generated
__pageHandlers method table. Slice that table instead, preserving the
ADR-0121 no-store assertions (non-vacuous GET presence, baseline emission,
public-cache rejection). Drop the duplicate route.path from the file-routed
configuration examples: file paths own generated route paths (ADR-0152).
Wire the standalone Element packed-consumer proof as a deno task.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 9, 2026

Copy link
Copy Markdown

Deploying openelement with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5a6c925
Status: ✅  Deploy successful!
Preview URL: https://44390ee9.lessjs.pages.dev
Branch Preview URL: https://codex-beta2-1-router-core.lessjs.pages.dev

View logs

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

The planning rewrite of roadmap.tsx quotes object keys ('stamp': …); the
AST extractor only accepted identifiers, so no CURRENT entry was found.
Accept string-literal keys as well.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

open-element/url-pattern-list @00bface carries the qualified implementation,
Node-native differential tests and the four construction/hit/miss/memory
benchmarks. The embedded copy remains the production matcher until the
separately authorized npm publish unblocks consumption (#1324).
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…tePatternComponents

The RouteRecord.pattern type narrowing drifts the public shape hash and
generated API reference; both artifacts are regenerated, not hand-edited.
Also drop the provider name from VERSION_PLAN (role-neutral docs gate).
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…olicy

The module header still described the gate as a merge prerequisite; the
authoritative policy is supplemental + non-blocking with mandatory
detection/reporting. Behavior unchanged.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

DevBot added 6 commits September 9, 2026 12:06
The ADR-0152 chain (beta.2.1-beta.2.3, then 1.0.0-alpha.1) is planned, not
retired: derive exemptions from lib/version.ts checkpoint/stage successors
instead of banning every non-current prerelease. Unapproved prereleases
(beta.3, historical 0.44.0-alpha.N) stay forbidden; the alpha.N shorthand
no longer matches inside an exempted full version. Fixes the www build
artifact-truth failure introduced by consuming planning HEAD dcfa2ee.
The planning rewrite of roadmap.tsx quotes object keys ('stamp': …); the
AST extractor only accepted identifiers, so no CURRENT entry was found.
Accept string-literal keys as well.
Additive tooling for the docs gates: the approved chain
(beta.2 -> beta.2.1 -> beta.2.2 -> beta.2.3) plus the admitted
product-stage transition to 1.0.0-alpha.1, matching the implementation
branch's lib/version.ts so both branches evaluate the same planned chain.
No existing consumer behavior changes.
#1342's 2026-09-09 planning update (ac0f9b5) plus its CI repairs
(docs-gate planned-chain exemption, quoted-key roadmap parsing, version
successor exports, content graph). Conflicts resolved by ownership:
planning docs take the planning branch's authoritative wording;
tools/lib/version.ts keeps the implementation branch's superset;
the content graph is regenerated, never hand-merged.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…ad55e8)

Planning truth now flows from dev ancestry. Conflicts resolved by
responsibility: RELEASE_POLICY takes the landed planning text plus the
version.ts ownership paragraph; version tooling keeps the implementation
superset; no product semantics changed.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…xactly (#1324)

RouteTable now consumes the OE-maintained fork from npm (exact pin, lockfile
integrity matches the published artifact) instead of the embedded production
copy, which is deleted. Package-graph rules encode the new edge (app ->
url-pattern-list, external release line); publish tooling keeps the fork
dependency exact in packed metadata while other externals keep caret ranges.
The differential oracle corpus stays as integration tests against the real
package (addPattern registration); its baseURL/exec pass-through oracle now
mirrors the upstream-aligned inputs contract. SEMANTIC_OWNERSHIP names the
published package as the matching authority.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

…lockfile

Required propagation, not drift: the starter consumes workspace app/adapter
source directly, so its lockfile must carry the newly consumed
@openelement/url-pattern-list@0.6.0 (exact, registry-matching integrity) and
the typescript entry the workspace build path resolves. No example content,
routes or semantics change; the freeze on examples/** otherwise stands
(#1311).
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

- tools/check-url-pattern-list-release.ts: fail-closed live npm provenance
  gate for the exactly pinned @openelement/url-pattern-list fork — exact-pin
  declaration in both import maps, lockfile resolution + integrity, registry
  name/version/license/repository metadata, dist.integrity/shasum, tarball
  byte verification and content inspection (identity, entry points,
  LICENSE/README, file count, fork genericity). Wired as an AutoFlow
  ci/release tier gate and as a qualification leg; offline dev loops stay
  offline.
- tools/qualify-v044-beta21.ts: the dedicated Beta.2.1 qualification lane.
  Executes router semantics, checkpoint version semantics, SSG authority,
  navigation on Chromium/Firefox/WebKit, packed starter/UI/standalone-Element
  consumers and (in CI, from trusted needs) the Node/Bun/workerd runtime
  floors, then writes v044-beta21-qualification.json only when every leg
  passed. Test-count floors, per-engine Playwright JSON accounting and
  packed-tarball existence keep every leg non-vacuous.
- Table-driven v0.44 checkpoint acceptance: beta.2 -> beta.2.1 -> beta.2.2 ->
  beta.2.3 chain, beta.3-vs-checkpoint separation, stage transitions and
  historical alpha protection in tools/lib/version.test.ts and
  tools/bump-version.test.ts.
- autoflow-ci.yml: beta21-qualification job on the exact PR head SHA uploads
  the SHA-named qualification artifact and joins the pr-full-ci-evidence
  required set (loop-evidence.ts + lockstep tests updated).
- docs/runbooks/beta21-qualification.md documents what the mechanisms prove,
  when they run, the artifact they generate and how release verification
  consumes it.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

#1343)

Maintainer review: the dedicated beta21-qualification CI job, the
tools/qualify-v044-beta21.ts orchestrator, the added version-semantics table
tests and the runbook were version-specific permanent architecture and are
removed. The checkpoint chain stays pinned by the pre-existing
tools/lib/version.test.ts coverage.

Kept: the generic, reusable url-pattern-list registry provenance gate
(tools/check-url-pattern-list-release.ts, url-pattern-list:provenance task,
AutoFlow ci/release tier gate) — it closes the live-registry/lockfile/tarball
integrity gap flagged by the previous audit and derives the expected version
from the workspace declaration, so it is not tied to Beta.2.1.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

SSG discovery (ssg-render.ts): dedupe host entries only when hono/ssg would
itself discover them (method GET/ALL with a non-middleware handler). An
exact-path middleware (ALL, arity 2) or a method-only host route (POST/…)
is filtered out of discovery by hono, so letting it suppress the canonical
GET entry silently dropped the page from a successful build. Regressions:
exact-path middleware and POST-only host route keep canonical pages
discoverable while host behavior is preserved.

Client router (client-router.ts): pending execution is now invalidated at
the ownership point — guard passed, latest ticket held — instead of at
navigation-attempt time. A guard-vetoed programmatic navigation, popstate or
native traverse therefore no longer aborts and discards the current route's
pending render (the initial loader could leave the root empty forever).
Latest-wins guard sequencing (#1023) and disposal invalidation are
unchanged. Regressions cover vetoed programmatic navigation, popstate and
native traverse at router level, plus pending-initial-loader and
pending-subsequent-render survival at SPA level. The same-origin-intercept
test is re-pinned to the ownership-point timing and the fake navigate event
now captures and drives the intercept handler.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

@SisyphusZheng
SisyphusZheng marked this pull request as ready for review September 9, 2026 10:55
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

APIError: Insufficient Balance

opencode session  |  github run

@SisyphusZheng
SisyphusZheng merged commit be633e9 into dev Sep 9, 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