Skip to content

Propose 24 DRY / separation-of-concerns issues across fjs and nanvm-lib - #1510

Merged
sergey-shandar merged 3 commits into
mainfrom
claude/wizardly-wright-iac7qg
Aug 13, 2026
Merged

Propose 24 DRY / separation-of-concerns issues across fjs and nanvm-lib#1510
sergey-shandar merged 3 commits into
mainfrom
claude/wizardly-wright-iac7qg

Conversation

@sergey-shandar

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

Copy link
Copy Markdown
Contributor

Documentation-only sweep filing 24 new todo/ issues; no code changes, so no CHANGELOG entry per AGENTS.md §8.3. Every finding was verified against the source (and, where noted, reproduced at runtime), and checked against the existing todo/ backlog so none duplicates an already-filed issue — each file's Related section links the nearest neighbors and states the boundary.

fjs (19)

Protocol & MCP:

  • fjs/protocol/json_rpc/todo/dispatch-at-lookup.md (P2) — dispatch reads its handler table with handlers[method], so wire-supplied prototype names (constructor, toString) resolve to callables; reproduced at runtime. Every other dispatcher already uses object.at for exactly this reason.
  • fjs/protocol/mcp/todo/result-adapter.md — own the Result<T, string> → ToolsCallResult adapter next to okResult/errorResult
  • fjs/mcp/todo/casmcpserver-share-cas.md — flatten casMcpServer per §6.4 and build fileCas(sha256)(home) once instead of three times

Types:

  • fjs/types/result/todo/ok-then.md (P2) — add okThen, the pure Result bind hand-rolled at ~10 sites; fjs/effects already ships the effectful twin okStep
  • fjs/types/bit_vec/todo/front-from-unpack-split.mdfront/removeFront are hand-written per bit order but derivable from the injected unpackSplit
  • fjs/types/uint8array/todo/tovec-precomputed-bound.mdtoVec precomputes a size bound, the exact thing §5.6 forbids; its sibling listToVec shows the fix
  • fjs/types/bigfloat/todo/from-decimal.md — decimal literal → BigFloat is implemented twice (js and djs tokenizers), in neither module that owns BigFloat
  • fjs/types/byte_set/todo/torangemap-payload.mdtoRangeMap bakes a SortedSet<string> DFA payload into a bitmask-algebra leaf
  • fjs/types/patricia_trie/todo/declarative-stack-fold.mdend is a right fold written as a descending index loop; index arithmetic re-implements array's last/splitLast
  • fjs/types/sorted_list/todo/tail-reduce-shadowing.md — two opposite tailReduces (keep vs. drop the tail) share one name, one shadowing the other
  • fjs/types/array/todo/head-tail-null-guard.md (P4) — head/tail re-inline the emptiness guard the split functions already own

Text, media & parsing:

  • fjs/text/ascii/todo/hex-digit-codec.md — hex-digit ↔ value has no owner; three hand-rolled copies (the djs copy silently accepts non-hex input)
  • fjs/media/json/todo/escape-table-single-owner.md — the JS/JSON string-escape table is written three times (table, range-map dispatch, switch); also flags a stale premise in issue 157
  • fjs/fsc/todo/orphaned-json-grammar.md — a dead, unproofed third copy of the JSON BNF grammar that bnf-grammar-single-owner's two-copy inventory would strand
  • fjs/fsm/todo/sorted-set-key.mdfsm uses the JSON serializer as a canonical set key, transitively loading the whole JS tokenizer into DFA construction
  • fjs/fsm/todo/torange-ascii-range.mdtoRange re-implements ascii.range by hand and crashes on a one-character string (RangeError, reproduced)

Effects, CAS & CI:

  • fjs/effects/node/todo/state-types-conventions.mdEnv re-rolls StringMap, two index signatures lack ? (the runtime code checks undefined the type says can't happen), State fields lack readonly
  • fjs/ci/todo/dead-nix-flake-job.md (P4) — nodeNixFlakeJob is a dead, byte-identical duplicate of the private nixFlakeJob, plus three no-op aliases
  • fjs/cas/todo/filecasoperation-duplicates.md (P5) — FileCasOperation lists Now, Readdir, Rm twice

nanvm-lib (5)

  • error-constructors.md — thrown error values are ad-hoc string literals in five places with three naming conventions; propose a vm/error.rs vocabulary
  • zip-longest.md — three hand-rolled "walk two sequences to the longer end" loops (abs_add_vec, abs_sub_vec, eq_by_); add Iter::zip_longest, drop the unused try_reduce
  • numeric-operator-home.mdNumeric's algebra is split across three modules: Neg open-coded on Any, no From<Numeric> for Unpacked, Mul boxes into Any inside the operator
  • sized-index-for-refs.mdSizedIndex::index_iter takes self by value while IContainer::items() returns &(?Sized), so six sites fall back to 0..len indexing; also unblocks debug-delimited-fmt-helper
  • operator-impl-placement.md (P4) — Add/AddAssign for String and Mul for Any sit in the vm/impls/ grab-bag while their types' directories hold their other operators

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qa71k3CG6oejRMYwfwCc8P

Documentation-only sweep filing new todo/ issues; no code changes.

fjs findings include: json_rpc dispatch reads handlers with bracket
indexing instead of object.at (prototype names reach the handler table);
a missing pure Result bind (okThen) hand-rolled at ~10 sites; bit_vec
front/removeFront derivable from unpackSplit; an orphaned third JSON BNF
grammar in fjs/fsc; hex-digit and string-escape codecs written three
times each; decimal-to-BigFloat duplicated in both tokenizers; fsm using
the JSON serializer as a set key; a dead CI nix flake job; and record
type/readonly deviations in effects/node types.

nanvm-lib findings include: no owner for thrown error values; a missing
zip_longest behind three hand-rolled dual-sequence walks; Numeric's
operator algebra split across three modules; SizedIndex unreachable from
IContainer::items forcing indexed loops; and two more operator impls
stranded in vm/impls/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qa71k3CG6oejRMYwfwCc8P
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 13, 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 da5177a Commit Preview URL

Branch Preview URL
Aug 13 2026, 06:11 AM

@sergey-shandar sergey-shandar changed the title Add 20 todo issues across multiple modules Propose 24 DRY / separation-of-concerns issues across fjs and nanvm-lib Aug 13, 2026

@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.

Approving. I did not evaluate all 24 proposals — that is not a review, that is a design review of 24 separate issues. Instead I verified four in depth and machine-checked every path:line citation across all 24. The hit rate is high enough that I would trust the rest.

Head note: I started at 77d35a6d and the head moved to da5177ac while I was checking (two merges of main, pulling in #1507/#1508/#1509 — no proposal doc changed). Everything below is re-measured at da5177ac. Against the current main (20cd6aa9) this PR is exactly 24 files, all under todo/ directories, so §8.3 wants no CHANGELOG entry and none is present. node bin/linkcheck.mjs output is byte-identical to main, so all the new cross-references between these docs resolve.

Deep-checked (4 of 24) — the duplication is real in every one

fjs/types/array/todo/head-tail-null-guard.mdtail is at :59 and head at :72, both verbatim a => a.length === 0 ? null : uncheck…(a); splitFirst at :64-69 does route through map(…)(first(a)). The «two holdouts in a module whose house style is nullable.map» framing is accurate, and the sibling split-last-nullable-map.md it points at exists.

fjs/text/ascii/todo/hex-digit-codec.md — all five citations land: media/json/serializer:48-50, js/tokenizer:599-612, djs/tokenizer:360-366, js/tokenizer:153-154 (rangeSmallAF/rangeCapitalAF), djs/tokenizer:336. fjs/text/ascii does export digit0, latinCapitalLetterF (:162) and latinSmallLetterF (:197). The best part is not the DRY claim but the bug it noticed in passing: the djs copy's final branch really is an unguarded : cp - (latinSmallLetterA - 10), so a non-hex code point yields a garbage digit where the js copy rejects. That is worth its own issue even if the codec extraction never happens.

fjs/ci/todo/dead-nix-flake-job.md — every claim checks out: nodeNixFlakeJob (node/module.f.mjs:134-137) and nixFlakeJob (ci/module.f.mjs:49) are the same expression; grep -rn nodeNixFlakeJob fjs/ finds only its own definition, so the export really is dead; nodeJob = steps => ubuntuArm(steps) at :73, nodeMainSteps = platformNodeSteps at :139, nixJobs = nodeNixJobs at :44 are all present; basicNode (:32-35) is referenced only from fjs/ci/node/proof.f.mjs. One wrinkle for whoever implements it: «make it private» would leave basicNode with no consumer at all except the proof, so the real choice is «use it or delete it».

nanvm-lib/todo/zip-longest.md — the three walks are where it says (abs_add_vec's four-arm match (iter_a.next(), iter_b.next()), abs_sub_vec's trailing iter_b.next().is_some(), Iter::eq_by_'s identical skeleton), abs_cmp_vec does hand-roll a descending while using neither, and src/vm/bigint/mod.rs:104 carries literally // NOTE: use .index_iter in abs_* helpers. — nice catch, the codebase had already noticed half of this. grep -rn try_reduce src/ tests/ returns exactly one line, its own definition, so «zero call sites» is right, and Either is already imported in common/iter.rs as the proposal assumes. Its §5.4 citation is correct — that section is «Reuse, DRY, and separation of concerns».

Bulk check: 44 resolvable path:line citations, 2 out of range

I resolved every file:line / file:line-line reference in all 24 docs against the tree and checked the range fits the file. Two do not:

  • fjs/mcp/todo/casmcpserver-share-cas.md cites fjs/dev/update/module.f.mjs:99-106 as «the in-repo model» — that file is 37 lines. The file is the right one (it does use history / historyStep / step), but the pattern lives at roughly :23-27.
  • fjs/types/result/todo/ok-then.md cites fjs/dev/package_json/module.f.mjs:145-150 — that file is 38 lines. Again the right file (the t === 'error' short-circuit is there), but at :34-36.

Both look like they were taken against a larger or older version of those two modules. Everything else in ok-then.md is exact, including all four fjs/cas/evo/module.f.mjs ranges (:396-415 really is five consecutive [0] === 'error' guards in one function, and :283-287, :495-505 land correctly) and fjs/effects/module.f.mjs:300-309 for okStep. The bare-basename shorthands in the nanvm docs (mod.rs:185-205, function/debug.rs:11, bigint/debug.rs:18-22) all resolve under nanvm-lib/src/vm/ — those are fine, my resolver just needed the prefix.

No convention conflicts found

All 24 follow the house issue shape (## title, **Priority:**, **Status:** open, Problem / Proposal / Tasks). None proposes try/catch, a node: import in FunctionalScript source, or anything else that cuts against AGENTS.md; the whole set is aimed squarely at §5.4, which is where it belongs.

Nit: the PR title says 24 and the head commit message says «Propose 19». 24 files is right.

Nothing here blocks. Filing these as todo/ entries costs nothing and each one I checked was a real, precisely located duplication.

@sergey-shandar
sergey-shandar marked this pull request as ready for review August 13, 2026 06:17
@sergey-shandar
sergey-shandar added this pull request to the merge queue Aug 13, 2026
Merged via the queue into main with commit e9a6dba Aug 13, 2026
19 checks passed
@sergey-shandar
sergey-shandar deleted the claude/wizardly-wright-iac7qg branch August 13, 2026 21: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.

3 participants