Skip to content

Dev#328

Merged
cukas merged 8 commits into
mainfrom
dev
May 27, 2026
Merged

Dev#328
cukas merged 8 commits into
mainfrom
dev

Conversation

@cukas
Copy link
Copy Markdown
Contributor

@cukas cukas commented May 27, 2026

What

Why

How

Checklist

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

cukas and others added 8 commits May 27, 2026 11:12
…bility — goal oracle

The differential harness exposed a cliff the codegen-string tests masked: the
most-common portable form (filter/map/find with x.field) emits ATTRIBUTE access,
which raises AttributeError on dict elements — the real shape of inline-schema,
fetch-JSON, and literal arrays. Plus whole method families (array
includes/join/slice/indexOf/some/every/reduce; string
includes/slice/substring/indexOf/padStart/padEnd/repeat) are unlowered, and
split(sep,limit) silently diverges (JS first-N vs Python maxsplit).

30 RED fixtures in 3 gateable slices (arr-core / arr-method / str-method).
Each slice is a goal task gated on `conformance.mjs --filter "<slice>:"`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…subscripting (arr-core)

Salvages and corrects the codex forge candidate for the conformance-backfill
arr-core task. Replaces the fragile regex-iteration array-method lowering with a
balanced, string-aware scanner (consistent with the JSON/Math/Number lowerers),
fixing two defects in the candidate:

  - single-char fields (`x.n`) were not subscripted (regex required 2+ chars)
  - chained `.filter().map()` produced garbled syntax once filter emitted a
    quoted subscript, because the regex receiver char-class couldn't span `"`

Member access on the bound element now lowers to dict-subscript form
(`x.active` → `x["active"]`, `x.meta.tag` → `x["meta"]["tag"]`) so iterating a
list of dicts works at runtime; chaining composes by nesting comprehensions;
`map((x, i) => …)` lowers via enumerate(). Method calls (`x.toUpperCase()`) are
left for the string-method pass.

Updates 6 codegen-string tests that had frozen the prior attribute-access
output the differential harness proves fails on dicts.

arr-core conformance: 9/9. Full fastapi suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e/some/every/reduce (arr-method)

Winner of the agon forge for the conformance-backfill arr-method task (codex,
score 93; gemini also passed). Extends the task-01 balanced array-method scanner
with the value/predicate-arg methods, reusing parseArrowCallback +
lowerDictMemberAccess for the callback forms:

  arr.includes(v)            -> (v in arr)
  arr.indexOf(v[, from])     -> next((__i for __i,__v in enumerate(arr) ...), -1)  (-1-safe, no raise)
  arr.join(sep)              -> sep.join(str(__v) for __v in arr)                  (JS str coercion)
  arr.slice(a, b)            -> arr[a:b]  (1-arg + negative forms)
  arr.some((x) => P)         -> any(P for x in arr)
  arr.every((x) => P)        -> all(P for x in arr)
  arr.reduce((a, b) => B, s) -> functools.reduce(lambda a, b: B, arr, s)           (adds import functools)

reduce defers its lambda `:` via a placeholder until after the dict-key-quoting
pass so the colon isn't mistaken for a dict-key separator. includes/indexOf/slice
are receiver-agnostic, so the string-receiver str-method fixtures for those also
pass now (str-method 11→5 remaining).

arr-method conformance: 10/10. arr-core still 9/9. Full fastapi suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…/repeat + split-limit trap (str-method)

Winner of the agon forge for the conformance-backfill str-method task (claude,
score 93; codex also passed). includes/indexOf/slice already lowered via the
receiver-agnostic arr-method path; this adds the string-specific methods:

  s.padStart(n, fill) -> s.rjust(n, fill)   (bare rename; default fill " ")
  s.padEnd(n, fill)   -> s.ljust(n, fill)
  s.substring(a, b)   -> s[a:b]             (simple non-negative form)
  s.repeat(n)         -> (s * n)
  s.split(sep, limit) -> s.split(sep)[:limit]   THE TRAP: Python's 2nd split arg
                          is maxsplit (keeps the remainder); JS keeps only the
                          first `limit` parts. No-limit s.split(sep) left raw.

Generalizes lowerStringReplaceFirstOnly → lowerStringArgMethods (one balanced,
string-aware scan shared across replace/substring/repeat/split; no new char
loop). substring's JS arg-swap/negative-clamp edge is scoped out with a comment
(diverges from Python slicing); only the fixture's non-negative form is lowered.

Full conformance: 84/84 (arr-core 9 + arr-method 10 + str-method 11 + the rest).
Full fastapi suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… data fields before a method call

Addresses two latent bugs codex review flagged on the arr-core scanner
(ab192611) — both outside the committed conformance fixtures:

1. filter/find/some with a second (index) callback param left the index
   unbound: `items.filter((x, i) => i > 0)` emitted `[x for x in items if i > 0]`
   → NameError. Now every arrow method binds the index via enumerate() when a
   second param is present, matching map.

2. lowerDictMemberAccess left a whole member chain as attribute access when it
   was followed by `(`, so a data field before a method wasn't subscripted and
   nested array methods broke on dicts. Now the leading data fields are
   subscripted and only the final method segment stays attribute access:
     x.name.toUpperCase()        -> x["name"].upper()
     x.tags.map((t) => t.name)   -> [t["name"] for t in x["tags"]]   (nested)

Adds regression tests for both. Full conformance still 84/84; fastapi suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(python): array/string method portability — conformance-backfill (84/84 differential)
…push

The conformance harness (scripts/conformance.mjs) executes portable KERN
expressions through BOTH the Python (FastAPI) and Express (JS) codegen paths and
diffs the runtime results — the gate that caught the host-builtin and
array/string-method portability bug cliffs. Until now it ran nowhere automatic;
an unrun parity gate is theater, so wire it in:

- package.json: `check:conformance` (build core/python/express + run the harness),
  mirroring `check:python-codegen`.
- ci.yml: a "Differential conformance (Python↔Express parity)" step after the
  codegen quality gate. Unlike that step (ast-valid but semantically blind), this
  proves behavioral parity by executing the generated artifacts.
- pre-push.mjs: gated `runConformance()` — fires only when @kernlang/core,
  /python, or /express are affected; `KERN_PRE_PUSH_SKIP_CONFORMANCE=1` escape
  hatch. Runs before the heavier scoped review so a regression fails fast.

Verified green on clean dev (gate won't block the base); pre-push unit tests 11/0;
trigger logic confirmed per-scenario (python/express/core fire, unrelated skip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ci(parity): gate Python↔Express differential conformance in CI + pre-push
@cukas cukas merged commit f0816d5 into main May 27, 2026
6 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