Skip to content

Codex/host namespace parity#432

Merged
cukas merged 18 commits into
mainfrom
codex/host-namespace-parity
Jun 15, 2026
Merged

Codex/host namespace parity#432
cukas merged 18 commits into
mainfrom
codex/host-namespace-parity

Conversation

@cukas

@cukas cukas commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

What

Why

How

Checklist

  • tsc -b passes
  • pnpm test passes
  • pnpm test:kern passes
  • pnpm lint passes
  • kern review packages/ --recursive checked

Comment thread packages/core/src/codegen/type-system.ts
Comment thread packages/core/src/codegen/type-system.ts
CI "Build & Test" runs `pnpm lint` (biome) BEFORE build and was failing fast
(~21s) on format reflow + unsorted imports across the host-namespace-parity
commits. Apply `biome format --write` + `biome check --write` import-sort,
scoped strictly to this PR's own changed files. No semantic changes; tsc -b
core clean, pnpm lint exits 0. The kern-guard ts18046/ts2339/ts2366 comments
were pinned to superseded commit 5bde97a and no longer reproduce on HEAD.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
Comment thread packages/core/src/codegen/type-system.ts
…rce of truth (gaps 1-4)

Tribunal-hardened fixes that keep the TS-emit path, the Python-emit path, and
the IR-validation pass in lockstep against the single KERN_STDLIB registry:

GAP 1 — IR-validate ↔ emit parity for stdlib members. The IR validator
(`rejectUnboundHostNamespace`) now consults the same KERN_STDLIB registry the
emitter uses: an unknown member on a stdlib root (`Number.foo`, `Math.bogus`)
is rejected at validation time exactly as the emitter's `throwUnknownStdlibMember`
would later throw, closing the drift where the validator silently PASSED what
emit rejects. The stdlib check is scoped to real `Module.member` access/calls
(the `'constructor'`/`'call'` sentinels are excluded so `new Map(...)` / bare
`Map()` / `new Number(5)` keep matching emit), and runs before the user-binding
check to mirror the emitter's binding-agnostic stdlib dispatch.

GAP 2 — closure callee unwrap. `collectClosureBlockMemberAccesses` now
normalizes a wrapped call callee (parenthesized / as / satisfies / non-null /
legacy type-assert, plus the right operand of a comma sequence) to its
underlying identifier via a fixpoint loop, so `(process as any)()` /
`(0, process)()` still surface their host-namespace root.

GAP 3 — parse-failure raw passthrough. `emitConstValue` no longer runs the raw
host-namespace scanner on the parse-FAILURE branch (there is no AST to validate,
and the scanner threw on legitimately-unparseable escape-hatch input). Raw text
ships verbatim, identical to the Python const-value path.

GAP 4 — legacy param defaults via the real TS parser. `parseLegacyParams`
replaces the hand-rolled char-scanner with `ts.createSourceFile`, auto-handling
`===`/`>=`, regex literals with commas, nested generics, and template literals
in param defaults — so a param shadowing a host root is detected correctly.

Adds `host-namespace-parity-gaps.test.ts` (34 cases) and updates the slice4cd
parse-failure test to the GAP-3 contract.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
…mport typescript from host-namespace-ir (blockers 1+2)

Post-review fixes on top of the gaps-1-4 collapse:

BLOCKER 1 — the GAP-3 "ship raw on parse failure" relaxation had leaked into the
SHARED IR validator (`validateExpressionValue`), so it fail-OPENED for EVERY
expression prop: an unparseable host root like `Date.now(]` as a FIELD value or
legacy PARAM DEFAULT validated OK and emitted verbatim invalid TS. The relaxation
is now scoped to the ONE sanctioned site — a `const`'s `value` prop
(`shipRawOnParseFailure`, set via `isConstValueEscapeHatch`). Every other
expression prop re-runs the raw host-namespace scan on parse failure and fails
CLOSED (honoring user shadowing). The const.value escape-hatch still ships raw
verbatim at emit, identical to the Python path (slice4cd GAP-3 test stays green).

BLOCKER 2 — GAP-4's `import ts from 'typescript'` made host-namespace-ir.js a 6th
static `typescript` importer in the core barrel graph, breaking the
browser-spine-import-graph pin (exactly 5). The `ts.createSourceFile`-based legacy
param parsing is RELOCATED into closure-eligibility.ts (which already owns the
`typescript` import + `parseClosureBlockAst`) as the exported
`parseLegacyParamSignature`; host-namespace-ir.ts imports THAT and no longer
imports `typescript`. The pin stays at 5.

IMPORTANT 3 — `parseLegacyParamSignature` checks `source.parseDiagnostics`: a
MALFORMED params string (`process = (`) returns `null` instead of producing a
phantom recovery-AST binding, so the body's `process.exit()` is no longer wrongly
treated as shadowed. `validateLegacyParams` turns that `null` into a fail-closed
raw host-namespace scan (rejecting a host root in the malformed string, e.g.
`ts:number=Date.now(]` → `Date.now`) + zero trusted bindings.

Test coverage added to host-namespace-parity-gaps.test.ts:
 - BLOCKER 1: field value / legacy param default `Date.now(]` REJECT; no-host-root
   unparseable input soft-passes; const.value escape-hatch still ships raw.
 - GAP 1 shadowed-stdlib-root: `Math.bogus(1)` with `Math` user-bound still REJECTS;
   a portable member stays valid with the root user-bound.
 - GAP 2 member + new contexts: `(0, process).foo` and `new (0, process)()` surface
   `process` and are rejected by the closure-block validator.
 - IMPORTANT 3: malformed `process = (` does not phantom-shadow; host root in a
   malformed default is still rejected.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
Comment thread packages/core/src/codegen/host-namespace-ir.ts
cukas added 3 commits June 15, 2026 12:27
…parity

# Conflicts:
#	packages/core/src/closure-eligibility.ts
#	packages/core/src/codegen-expression.ts
#	packages/core/src/codegen/body-ts.ts
…parity

# Conflicts:
#	packages/python/src/codegen-body-python.ts
Comment thread packages/core/src/codegen-expression.ts
@cukas cukas merged commit 8a1d282 into main Jun 15, 2026
3 of 4 checks passed
@cukas cukas deleted the codex/host-namespace-parity branch June 15, 2026 13:10
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.

2 participants