Skip to content

feat(dom): INT-08 real VDOM reconciler + .as→.affine rename (Refs #183 #255)#256

Merged
hyperpolymath merged 1 commit into
mainfrom
int08-183-dom-reconciler
May 19, 2026
Merged

feat(dom): INT-08 real VDOM reconciler + .as→.affine rename (Refs #183 #255)#256
hyperpolymath merged 1 commit into
mainfrom
int08-183-dom-reconciler

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

INT-08 — DOM reconciler in affinescript-dom (#183)

The old affinescript-dom/src/dom.as did not parse (Void, ->
match arms, List[T], {id:String}) and h()/mount() did not
render — an aspirational stub never run through the compiler. It also
used the wrong extension: AffineScript source is canonically .affine
(bin/main.ml:67), so src/dom.as was uncompilable by the toolchain.

Landed

  • src/dom.assrc/dom.affine; package.json main/exports repointed.
  • Real virtual-DOM: VNode enum, text/h builders (arbitrary attrs + children), render (full tree → real DOM), mount, and a minimal-mutation reconcile (attr set/remove, text patch, child append/remove, tag-change replace). Structured for the codegen single-pass-declaration-order constraint (self-recursive render/reconcile, inline children, for-count vnode_len instead of the unavailable len).

Gate

Compiles end-to-end (resolve→typecheck→codegen→wasm) — same bar as the Stage-C stdlib AOT suite. dune test --force 271/271, zero regression.

Runtime blocker (disclosed, not hidden)

#255 — a pre-existing wasm-codegen defect found during this work: for-in/while loop bodies never execute in the compiled module (tests/codegen/test_for_loop.affine returns 0 not 15; reproduces at 81a59bf; no test_for_loop.mjs ever asserted it). The reconciler logic is correct AffineScript and runs once #255 lands. No runtime e2e harness is shipped until #255 — a test that cannot pass would be dishonest.

Refs #183 (reconciler implemented; runtime gated on #255) #255. Not Closes — owner closes per ISSUE-CLOSURE.

🤖 Generated with Claude Code

…#255)

The previous `affinescript-dom/src/dom.as` did NOT parse (`Void`, `->`
match arms, `List[T]`, `{id:String}`) and `h()`/`mount()` did not
render — an aspirational stub that had never been through the compiler.
It also used the wrong extension: AffineScript source is canonically
`.affine` (bin/main.ml:67), so `src/dom.as` could never be compiled by
the toolchain. (Thanks to the owner for catching the `.as` vs `.affine`
question.)

- Renamed `src/dom.as` → `src/dom.affine`; repointed package.json
  `main`/`exports`.
- Replaced the stub with a real, compiling virtual-DOM: `VNode`
  enum, `text`/`h` builders (arbitrary attrs + children, not the old
  `{id:String}`-only), `render` (full tree → real DOM), `mount`, and a
  minimal-mutation `reconcile` (attr set/remove, text patch, child
  append/remove, tag-change replace). Structured around the codegen
  single-pass-declaration-order constraint (no cross-fn mutual
  recursion): `render`/`reconcile` are self-recursive, children handled
  inline; `len` (absent in the wasm-AOT subset) replaced by a
  `for`-count `vnode_len` helper.

GATE: compiles end-to-end (resolve→typecheck→codegen→wasm) — the same
bar as the Stage-C stdlib AOT suite. `dune test --force` 271/271, zero
regression.

RUNTIME is blocked by #255, a **pre-existing** wasm-codegen defect
discovered during this work: `for-in`/`while` loop bodies never execute
in the compiled module (canonical `tests/codegen/test_for_loop.affine`
returns 0 not 15; reproduces unchanged at 81a59bf; there is no
`test_for_loop.mjs`, so the suite never caught it). The reconciler
logic is correct AffineScript and will run once #255 lands. No runtime
e2e harness is shipped until then (a harness that cannot pass would be
dishonest).

Refs #183 (reconciler implemented; runtime gated on #255) #255.
Not Closes — owner closes per ISSUE-CLOSURE.
@hyperpolymath hyperpolymath merged commit 1ce5ff5 into main May 19, 2026
12 of 13 checks passed
@hyperpolymath hyperpolymath deleted the int08-183-dom-reconciler branch May 19, 2026 16:59
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 44 issues detected

Severity Count
🔴 Critical 12
🟠 High 21
🟡 Medium 11

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Stray AI.a2ml in root -- use 0-AI-MANIFEST.a2ml only",
    "type": "banned",
    "file": "AI.a2ml",
    "action": "delete",
    "rule_module": "root_hygiene",
    "severity": "high"
  },
  {
    "reason": "Superseded by 0-AI-MANIFEST.a2ml",
    "type": "banned",
    "file": "AI.djot",
    "action": "delete",
    "rule_module": "root_hygiene",
    "severity": "high"
  },
  {
    "reason": "Issue in quality.yml",
    "type": "missing_workflow",
    "file": "quality.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in security-policy.yml",
    "type": "missing_workflow",
    "file": "security-policy.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/example/smoke_driver.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/cli.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/compile.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/runner.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

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