Skip to content

edag/todo: end chain lambdas by absence (option), not null - #1755

Merged
sergey-shandar merged 18 commits into
mainfrom
claude/option-null-lambdas-mqpwck
Aug 28, 2026
Merged

edag/todo: end chain lambdas by absence (option), not null#1755
sergey-shandar merged 18 commits into
mainfrom
claude/option-null-lambdas-mqpwck

Conversation

@sergey-shandar

@sergey-shandar sergey-shandar commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Files fjs/edag/todo/option-terminated-lambdas.md — an investigation and design for dropping the explicit null chain terminator, so a plain read is ['.', a, 'b'] and terminals are genuine 2-tuples (['|()', c], ['|!()', c]). Documentation only: no schema, type, or evaluator changes yet — those are the TODO's task list.

What the issue records:

  • The module's argument for the explicit null ("a two-element terminal handed a real continuation would validate as the terminal with the rest silently dropped") predates closed-by-default tuples: the chain grammar landed 53077ae (2026-08-26) against open tuples, closedness by length landed 7852819 (2026-08-27), and the latter's design (types/rtti/todo: closed containers by default, then option as omission #1725) already named option as omission. Under the closed model the smuggled continuation is rejected by length — verified against the real validate, with an acceptance/rejection table in the issue.
  • The chosen spelling is arity-split unions: each node or step whose continuation may end is a union of its two closed arities, with no option anywhere in the chain schemas — verified against the real validate, no rtti change needed, and a trailing hole (sparse array) matches neither arm, so the same change keeps validate(exp) rejecting every hole, pinned in the proofs.
  • The option spelling was verified too (optional trailing tuple elements render exactly; the recursive lambda thunks need AbsentOr phantoms pinned with CheckRaw) and is recorded as the rejected alternative: making it canonical requires an rtti rule that tuple absence is the array ending before the position, whose prerequisite cascades through rtti's canonical algebra — reader/printer docs, the [option]/[] collapse in toData, interior absent bits, and referenced nodes where stripping changes the recursive fixpoint.
  • The design also scopes the host boundary: prototype-supplied indices flip symmetrically between the spellings (measured both below and past length), amnesia's walkers stay on the destructuring read pattern with skip joining them, and hostile-host hardening remains rtti's tracked question.
  • Migration scope: small in code (schemas, types.ts, amnesia's k === nullk === undefined plus skip destructuring), mechanical in proofs and prose (~200 trailing nulls, README tables, and the downstream djs designs that prescribe the old spellings).

https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

Files the investigation: the explicit null terminator predates closed-by-
default tuples (7852819), whose design (930fa65, #1725) already named option
as omission. Records the verified runtime and type-level behavior, the
AbsentOr/CheckRaw phantom pattern the recursive lambdas need, the trailing-
hole widening, and the migration tasks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e
@sergey-shandar
sergey-shandar marked this pull request as ready for review August 28, 2026 15:40
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@sergey-shandar sergey-shandar changed the title End chain lambdas by absence, not null edag/todo: end chain lambdas by absence (option), not null Aug 28, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
functionalscript 16d59f9 Commit Preview URL

Branch Preview URL
Aug 28 2026, 05:35 PM

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2981ad5026

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
sergey-shandar and others added 2 commits August 28, 2026 08:46
…anisms

Review finding on #1755: leaving 'where hole rejection lives' as an open
task would let the migration ship a validation regression, which AGENTS.md
forbids deferring. The task is now a hard gate with two acceptable
mechanisms: arity-split unions (verified — closedness by length rejects
every hole with no rtti change), or an rtti rule that tuple absence is the
array ending before the position, filed and landed first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d50a0ba34c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
Review finding on #1755: the schema/type tasks prescribed the option
spelling unconditionally, so following them under the arity-split mechanism
would put option back at the lambda roots and reintroduce the trailing-hole
regression. The mechanism choice is now the first task and the schema and
type tasks are spelled per mechanism; the hole-rejection pins move into the
proof task, required either way.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a2957c5b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
Review finding on #1755, confirmed against trimPrefix in
fjs/rtti/data/module.f.mjs: once a hole is no member, [option] and []
denote one array set, and the data form keeps them canonically distinct
today exactly because they differ on new Array(1). The prerequisite rtti
issue for the past-the-end rule must therefore also specify the arraySet
normalization and carry cmp/equal/subset, the data reader, and the printer
- a surface mechanism 1 does not touch, which the issue now notes as an
argument for mechanism 1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eab016cf6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
Comment thread fjs/edag/todo/option-terminated-lambdas.md
…igns

Two review findings on #1755, both verified. Under the past-the-end rule an
absent bit is realizable only in the all-optional trailing run, so interior
absence becomes unobservable — [or(option, number), 3] comes to denote
[number, 3] while toData keeps its absentBit — and the prerequisite rtti
issue must strip it, the same trailing-run split TupleTs makes. And the
respelling task now covers the active downstream designs
(compile-modules-to-edag.md, interpret-edag.md, the bun-parentheses blocker)
plus a repo-wide sweep, leaving released changelog entries as history.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8f7b1cdda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
Third mechanism-2 gap in a row on #1755, this one with no local answer: a
referenced rule like r = or(option, [r]) can sit where its root absence is
unobservable and where it is not, so stripping the rule changes the
fixpoint, and the data form declines to see through references. The design
now decides instead of choosing later: arity-split unions are the mechanism,
and the past-the-end rule is recorded as the rejected alternative with the
full cascade (readers/printer docs, [option]/[] collapse, interior bits,
referenced nodes) as the reason. Tasks lose their per-mechanism branching.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34b0e22860

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md
…tti's

Review finding on #1755, measured both ways: a prototype-supplied member
behind an own trailing hole is read by both spellings alike — index 3
supplying ['|()', c, null] validates under today's schema and rejects under
the split one, ['|()', c] exactly the reverse — so neither is hole-proof
against a polluted Array.prototype and neither ever was, while a pristine
prototype rejects every hole in both. The gate's claim is now stated as
about the value's own members under rtti's reading model, with the
hostile-host question left where it is tracked
(hostile-accessor-hermetic-read-path; the Beyond-length caveat).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2718720440

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
… reads it

Review finding on #1755, measured: past the end the split 3-arity arm
accepts a length-3 dot whatever Array.prototype[3] holds — the unanswered
region rtti's Beyond-length caveat states for every bare tuple — while
today's schema accepts the same value the moment that index inherits its
own null, so the flips are symmetric there too. The claimed executor crash
is wrong: amnesia reads nodes by destructuring and the array iterator stops
at length, so the inherited index is never read — the fourth slot of a
length-3 node is undefined under Array.prototype[3]='junk' while a direct
node[3] would read it. The gate paragraph now covers both regions and the
amnesia task pins the destructuring read pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b354654e9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md Outdated
sergey-shandar and others added 3 commits August 28, 2026 09:28
…tion

Review finding on #1755, confirmed in amnesia/module.f.mjs: the three
lambda walkers destructure, but skip reads k[0]/k[1]/k[2] directly — safe
today only because every step carries an own third member. After the
migration a short step's k[2] would read the prototype, so a polluted
Array.prototype[2] could hand skip an inherited continuation the step's
own trailing null masks today. The gate paragraph now states the exception
and the amnesia task requires rewriting skip to destructure in the same
change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b111a745ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md
claude and others added 3 commits August 28, 2026 16:34
Tenth review round on #1755 flips the eighth's remedy: destructuring
dispatches an own overridden Symbol.iterator, so it now asks for
length-checked indexed reads instead. The doc closes the family: under a
hostile host every read style has its own attack, the three lambda walkers
destructure today so an iterator-hostile step already misleads the current
evaluator identically, and amnesia's README scopes it as deliberately not
a VM — its guarantees assume a DJS value on a pristine host, where the
styles coincide. skip joins the one uniform pattern; hostile-host executor
hardening is out of amnesia's charter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@o2alexanderfedin o2alexanderfedin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — the engineering holds. Three doc-level things below, one of which is worth fixing before merge.

Verified empirically against the real validate at this head: the symmetric prototype-pollution flip reproduces in all four quadrants plus both pristine controls, exactly as the text describes — neither spelling is pollution-proof, and both reject the hole under a clean prototype. The premise mechanism 2's rejection turns on also holds: validate([])(new Array(1)) errors while validate([option])(new Array(1)) is ok, matching trimPrefix's own doc comment. skip's k[2] really is the only indexed continuation read — the other three destructure — and destructuring genuinely does not reach a polluted past-length index while node[3] does. All 18 links resolve; no leftover mechanism-2 language survives the rewrite.

  1. Wrong section number, worth fixing. The note cites AGENTS.md §1, "Merge the knowledge". That paragraph is in §5, Pull requests and releases. The quoted words are exact; only the number is off, and a future reader chasing §1 will not find it.

  2. The PR description is now superseded, and this repo squash-merges it into history. The body still says the note "names two acceptable mechanisms", but the final text commits to arity-split and rejects the rtti rule. Left as is, mainline history will permanently describe a design the note argues against.

  3. One quotation is not verbatim. The note attributes to amnesia's README: "deliberately not a VM to run FunctionalScript on". The README says "It is not a VM for FunctionalScript, and nothing that matters should run on it"; "deliberately" comes from execution-models.md. The substance is right — amnesia does disclaim VM status — but every other quote in this note is character-exact, so the marks read as verbatim here too.

Minor: the Related bullet offering identity-aware-parse.md as "the Stage 2 validator the hole check could join" presumes a standalone runtime hole check. Under arity-split, rejection is structural and pinned in proofs — there is nothing left to join.

The cascade argued for a hypothetical mechanism-2 redesign could not be run, since that code does not exist. Its premises are real, though: toData keeps the absent bit unconditionally, and _SplitTs/_InteriorTs do make the trailing-run split the note credits TupleTs with.

tsc 0; npm test not run — docs-only against the true merge-base.

Review fixes from the approving human review on #1755: the Merge-the-
knowledge paragraph is AGENTS.md §5, not §1; amnesia's README is quoted
verbatim with the 'deliberately' phrasing attributed to the edag README
where it lives; and the identity-aware-parse Related bullet no longer
implies a runtime hole check exists to join — rejection is structural
under arity-split.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

Copy link
Copy Markdown
Contributor Author

All four review points from @o2alexanderfedin's approval are addressed:

  1. § fixed (3dc5cc7): the "Merge the knowledge" citation now reads AGENTS.md §5.
  2. PR description updated to the final design — it now states arity-split as the chosen spelling with the hole gate structural, and records the option spelling as the rejected alternative, so the squash commit will describe what the note actually argues.
  3. Quote made verbatim (3dc5cc7): amnesia's README is quoted exactly ("It is not a VM for FunctionalScript, and nothing that matters should run on it"), with the "deliberately not a VM" phrasing attributed to the edag README where it lives.
  4. Related bullet reworded (3dc5cc7): identity-aware-parse is now cited for the identity caveats validate(exp) keeps either way, with hole rejection noted as structural — nothing left to join.

Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3dc5cc74c9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fjs/edag/todo/option-terminated-lambdas.md
Review finding on #1755: the implementation changes accepted graphs and
the exported types, so per AGENTS.md \u00a75 it needs a
changelog/unreleased/<PR>.md entry prefixed BREAKING CHANGES with the
matching Changelog section, updating every importer in the same PR. Added
as a task.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AQH2SZCpDhyQUgByxkV46e

@o2alexanderfedin o2alexanderfedin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. All three checked out:

  • AGENTS.md §5 is right — "Merge the knowledge" is at line 112 under "Pull requests and releases".
  • The quotation now splits correctly. Amnesia's README does say "It is not a VM for FunctionalScript, and nothing that matters should run on it" verbatim, and ../README.md does say "deliberately not a VM to run FunctionalScript on", across a line break at lines 43-44. Both attributions land where the words actually are.
  • The identity-aware-parse.md bullet no longer offers a hole check to join, which matches arity-split making rejection structural.

The added BREAKING CHANGES task is a good catch on your side — the migration does stop previously valid graphs from validating.

@sergey-shandar
sergey-shandar added this pull request to the merge queue Aug 28, 2026
Merged via the queue into main with commit b89916d Aug 28, 2026
19 checks passed
@sergey-shandar
sergey-shandar deleted the claude/option-null-lambdas-mqpwck branch August 28, 2026 18:50
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.

3 participants