Clotho Task 4a: closed inventory, substrate, git + code weavers#117
Merged
Conversation
…t draft)
Implements frozen v12 Task 4a:
- clotho/weavers/util.mjs — shared substrate: comment/string-aware lexer; the ONE
D33 module-load classifier + relative-specifier resolver + closure derivation;
Phase-1 export scanner + static-import parser; real-file walker; D26/D29
counted-iterator; D21 physical-containment; no-shell weaver-facing git wrapper;
source-descriptor seeding.
- clotho/inventory.mjs — closed inventory: package/doc roots + exclusions,
contract-files (D31), run sources, five weavers + integer versions, the frozen
REQUIRED_INVENTORY_IDS table, the deep-frozen D32 loader-safe-exports map, and
the git/code implementation-file closures (D33). Per AM-17, only the git and
code weavers' inventories are committed at this PR.
- clotho/weavers/git.mjs — git weaver: introduced-by edges via exact path-scoped
git log; earliest result; malformed output fatal.
- clotho/weavers/code.mjs — code weaver: depends-on edges, all four endpoint
shapes; symbol- vs file-level threading; unrepresentable-consumer only for
unresolvable specifiers.
- scripts/test-{util,inventory,git,code,closure}.mjs — full unit matrix incl.
closure-equality (inventories proven equal to derived closures, never trusted),
frozen-table equality, D32 deep-equal/deep-freeze, counted-iterator and
containment semantics; all registered in test-all.mjs.
npm test green (7 tests); confined to clotho/; zero deps; node: stdlib only.
Authorization: The Eye's Clotho Phase 1 implementation decision (#109), v12
sha256:bdc93901…, authz-005, per-task cadence.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…+ codex)
Applies all consolidated round-1 findings as one revision:
- ONE resolver (D33): code.mjs uses util's shared resolveRelativeSpecifier;
private resolveModulePath deleted. Explicit .mjs only (no append, no other ext).
- Classifier exactness: mode-stack lexer blanks regex-literal interiors and
preserves template ${...} code; each from-clause bound to its own governing
keyword (forward parse); obj.import()/a.module.require() member calls excluded;
export * as ns from recognized.
- D21 containment: lstat the allowed root in place (reject symlinked root) before
any realpath; deepest existing ancestor resolved beneath the repo real path.
- walkFiles fails closed: throws on any symlinked entry (no silent skip); closure
entry points get the same symlink/regular/containment checks.
- Git wrapper: validateGitArgs accepts exactly the frozen arg arrays (order
enforced); fixed cwd/shell:false/encoding applied last so caller options cannot
override them.
- Duplicate export descriptors are fatal (scanExports no longer de-dupes names);
unsupported-export warnings propagate.
- Structured warnings {weaver,message} on both weavers (D10/AM-39 weaver side;
driver check stays Task 5).
- Real closure-equality harness with per-form omission fixtures + all fatal
failure modes; AM-34 test 19 strengthened against renaming.
- Fixed a pre-existing NUL-byte harness artifact in seedSourceDescriptors.
npm test green (7 tests); confined to clotho/; zero deps; no NUL bytes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…+ codex) - Classifier: skips ALL JS whitespace (not just U+0020) so imports after tab/ newline are detected; decodes string escapes (\x2e/. relative literals); module.require/bare require no longer double-classify. - Unified fail-closed component walker: lstat every component of the repo-root ancestor chain and candidate parents before any realpath; reject symlink components; ENOENT tail distinguished from other lstat errors; used by resolveRelativeSpecifier, walkFiles, deriveAcceptedClosure, physicalContainment. - identifierUsedOutside: a `/` after return/throw/case is a regex literal, so a binding only in `return /binding/` is not a false use. - scanExports: per-keyword dispatch warns for every unsupported form incl. computed exports and dynamic symbol flow. - code.mjs: unrepresentable-consumer reserved for explicit-.mjs specifiers that don't resolve to a real file below closed roots; non-.mjs -> no edge; symlink/ escape/non-regular -> fail closed. - git.mjs: only "" is no-result; "\n"/internal blank line is fatal. - Tests: AM-34 test-19 asserts deriveAcceptedClosure calls both shared functions; counted-source final-break boundary pinned (D29 run-to-completion); direct locator-field assertions in test-code; fixtures for every fix. Review artifact now includes registry.mjs (leaf; both committed closures correct). npm test green (7 tests); confined to clotho/; zero deps; no NUL bytes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…_ROOTS curation Round-3 required-seat findings (claude + codex): - Lexer regex/division soundness: paren-kind stack distinguishes regex after a control-condition ) from division after an expression )/]/}/identifier; `of` removed from regex-introducing set. - One canonical repo-relative POSIX validator (isCanonicalRepoRelPosix) for walker outputs, resolved closure paths, and git path args (reject absolute/ ./../backslash/NUL). - git CRLF: parseShaLines accepts LF or CRLF; bare CR / blank / non-40-hex fatal. - LEDGER_SOURCES reframed as a committed CLOSED source inventory whose exact reviewed value at this SHA is empty (Clotho weaves no committed ledger artifact); removed the AM-17-deferral misframing; added exact shape assertion. - Chain-walk helpers consolidated; counted-iterator N-1 contract ratified in comment + unit; test pins (export const = call, git imports only registry, non-.mjs missing-file silence, both-iterables-exhausted). PACKAGE_ROOTS scope (The Eye's ruling): TELOS spine only (5 packages), with an explicit PACKAGE_ROOTS_EXCLUDE = [ai-forge, forge, saas-forge] and a completeness test discovering every package.json dir and requiring discovered == ROOTS ∪ EXCLUDE, ROOTS ∩ EXCLUDE = ∅. Per The Eye, this scope ruling is being frozen into the plan via a narrow Daedalus delta (v12 -> v13) BEFORE acceptance — this commit preserves the held implementation; it is not accepted until the plan is amended and re-authorized. npm test green (7 tests); confined to clotho/; zero deps; no NUL bytes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
claude confirmed the implementation strong/faithful (AM-40 correctly implemented); these are bounded test-only additions: - Direct real-repo closure equality (test-closure §12): deriveAcceptedClosure of git/code/registry deep-equals the exact expected lists (registry proven leaf => git/code inventories are the genuine recursive fixed point); derived array shown on failure. - Accounting unreachability (test-util §12): walks own+symbol keys of the iterable and its iterator, asserting the D26 accounting accessor/counts are never exposed to the weaver. - require-of-non-.mjs fatal (test-closure §13): literal require()/module.require() of a .cjs target is fatal ambiguous-extension in closure derivation, never a .cjs edge. No weaver/util/inventory behavior change. npm test green (7 suites); confined to clotho/; committed closures unchanged. Reviewed against v13 (authz-006). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…+ codex) vs v13
- Counted-iterator: removed the unauthorized "RATIFIED contract" framing; the
iterator already counts N on natural for...of completion. Reframed comment+test
to derive semantics from the frozen "without fatal error" definition + D29
exhaustion; early-break tail is partial (uncounted).
- Lexer: postfix ++/-- => following / is division, so x++ / import("./m.mjs") is
detected (was masked); import/export as a property key/member is never a load
site (no keyword->from bleed).
- Declaration-aware scanners: scanExports ignores { export: 1 } property keys;
scanImports span extends through assert{}/with{} so identifiers there are not
uses.
- Canonical validator applied to resolveRelativeSpecifier + deriveAcceptedClosure
entry outputs (fatal on noncanonical).
- Fail-closed fs: only ENOENT is absence; every other lstat/readdir error throws /
returns false (walkFiles, physicalContainment, closure entry).
- PACKAGE_ROOTS completeness over TRACKED package.json (git ls-files), exact set
equality both directions + disjointness + sorted/unique AM-40 arrays.
- code-weaver fixture: used named import absent from a seeded target's exports ->
file-level fallback (not unrepresentable-consumer).
- Header provenance -> plan v13 (v12 + AM-40); per-form omission binding comment.
npm test green (7 suites); confined to clotho/; committed closures unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…) + refinements
Crux (codex hard stops): replaced the "split on every import/export token" lexer
heuristic with a shared parseModuleDecl + moduleDecls generator that delimits real
statement-position declarations by brace-matching the specifier list. Both
classifyModuleLoads and scanImports consume it, so:
- export { h as import } from "./helper.mjs" — a keyword-named alias no longer
truncates the export region; the file is reached (closure no longer omits it).
- const o = { import: 1 }; ... import { alpha } from "./dep.mjs" — the property key
no longer starts a spurious declaration nor swallows the real import; a
pre-declaration use of alpha is detected (edge emitted, not suppressed).
- property/member/meta lookalikes ({import:1}, o.export, import.meta) => no site.
Regressions in test-util/test-closure (keyword-alias re-export, whitespace
module.require closure fixture).
claude refinements: git validate-before-spawn unit; blob_sha same-file pin;
GLOBAL_EXCLUDE/DOC_WEAVER_EXCLUDE deferred-wiring comment.
npm test green (7 suites); committed closures unchanged (git {registry,git},
code {registry,code,util}); confined to clotho/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…ons (v15)
Implements The Eye's AM-41 (v15, authz-008) enforced closed source-profile
contract for the shared D33 scanner:
- Enforced profile: ProfileError + PROFILE_DIAGNOSTIC (unsupported-module-lexical-
profile). lex() blanks one optional leading shebang (#! byte0/line1/LF|CRLF) and
flags the first out-of-profile construct; classify/scan/closure fail closed
(no edge, no closure result, no coverage) for an out-of-profile entry or member.
- Exact out-of-profile set b1-b6: bare CR/U+2028/U+2029; non-leading #! (code
position; #! in a string/comment is in-profile per The Eye); <!-- / line-leading
-->; string line-continuation / legacy-octal escape; string-literal specifier/
alias name; unterminated string/comment/leading-shebang.
- Token context: member/private/whitespace/comment loader lookalikes not loads;
dynamic import options/trailing comma accepted; contextual `from` as a name;
closure resolver traverses .mjs+.cjs, code.mjs stays .mjs-only.
- Original-uncollapsed-component containment in the shared resolver (lstat before
..-collapse) + junction fixture.
- Two proved properties: supported-profile forms correct under variation
(incl. LF/CRLF leading shebang, #!-in-string/comment); each b1-b6 fails closed.
Committed closures unchanged (git {registry,git}, code {registry,code,util}).
npm test green (7 suites); confined to clotho/; no NUL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
… (claude + codex)
- Regex/division by previous-significant-token (comment/space-robust prevSigWord),
incl. control-head and for(..of) contexts (return /*c*/ /re/, if /*c*/ (a) /re/).
- Complete fail-closed profile: unterminated template, out-of-set string escapes,
and truncated static/call forms (import{x}from, export * from, import("./x",,
require("./x") all throw unsupported-module-lexical-profile (b6).
- Original-order containment: originalChainSymlinkFree no longer bails at first
ENOENT; physicalContainment walks original uncollapsed components before resolve;
link/.. and missing/../link/.. fixtures require kind===symlink.
- Closure extension generalization: shared closure resolver traverses every
explicit-extension existing target (.cjs/.js/.json/...); code.mjs stays .mjs-only;
extensionless stays fatal.
- git.mjs self-validates symbol (identifier) + path (repo-rel POSIX) before the git
call. git wrapper drops the caller options bag (no env/argv0/cwd passthrough).
- test git ls-files via pinned no-shell allowlist; multi-declarator export const
warns; inventory.mjs proven a profile-clean closure leaf.
Committed closures unchanged (git {registry,git}, code {registry,code,util}).
npm test green (7 suites); confined to clotho/; no NUL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…ex convergence)
Applies codex's complete exhaustive enforced-profile list as one revision:
- Regex/division: await/yield in REGEX_KEYWORDS; brace-kind stack (block } => regex,
object } => division). prevSigChar skips ALL whitespace + comments (obj.\nimport()
is a member call). Call-position-only (function/method/property loader words not
loads).
- Fail-closed completeness: b5 string-literal specifier/alias names (export {x as
"public"}, import {"a" as b}); b6 unterminated regex (EOF/newline/char-class),
truncated import{x}/export*, unbalanced dynamic options; malformed escapes
\xG0/\uZZZZ/\u{}/out-of-range (range-safe decodeEscape, no RangeError leak);
whitespace-prefixed line-leading -->.
- scanExports: member/method/private export lookalikes emit neither symbol nor
warning.
- Closure external membership: admit only approved merkle-dag/ primitives regardless
of allowExternal contents; inventory constrains PERMITTED_EXTERNAL_CLOSURE_FILES to
merkle-dag/ paths.
- git runner controlled env: strips GIT_DIR/GIT_WORK_TREE/GIT_COMMON_DIR/... so
inherited env cannot redirect the repo (two-repo unit).
- Backslash specifier rejected before resolution (Windows containment).
- code-weaver: default binding named `from` no longer dropped.
Committed closures unchanged (git {registry,git}, code {registry,code,util}).
npm test green (7 suites); confined to clotho/; no NUL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
…/b6 (codex)
- Significant-token completeness: string/template/regex literals reset the
prev-significant token to a VALUE (so `/` after them is division), clearing stale
keyword state; a class/function body { } is classified as a BLOCK (blockHeadPending)
so a regex after `class C {}` is a regex and division-adjacent dynamic imports stay
visible (return "x" / import("./dep.mjs") / 1 => import edge present).
- b5: a string-literal name reached directly in an import/export clause (incl.
`export * as "ns" from`) fails closed; identifier namespace alias still classifies.
- b6: a literal-specifier dynamic import with unbalanced/truncated options or an
unclosed call throws unsupported-module-lexical-profile instead of degrading to
no-edge; valid options/trailing comma still classify.
Committed closures unchanged (git {registry,git}, code {registry,code,util}).
npm test green (7 suites); confined to clotho/; no NUL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
… (class-fix)
Root/class fixes replacing case-by-case patches:
- Regex-vs-division as a DENY rule: division only after a VALUE token (identifier,
numeric/string/template/regex literal, this/super/true/false/null, )/]/value-}/
postfix); regex after every reserved keyword automatically (default/extends/case/
... no longer a hand-maintained allow-list). Division-adjacent dynamic imports
stay visible; regex lookalikes after keywords create no edge.
- One complete horizontal-whitespace predicate (tab/VT/FF/space/NBSP/BOM) used
everywhere, incl. the b3 line-leading --> scan (\f--> fails closed).
- Bare/truncated `import` (terminated by ; or EOF) fails closed (b6) without
affecting import()/import.meta/import "x"/clauses/{import:1}.
Committed closures unchanged (git {registry,git}, code {registry,code,util}).
npm test green (7 suites); confined to clotho/; no NUL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8pTab2QMpfM2KsZmwkeYg
dsmcewan
marked this pull request as ready for review
July 17, 2026 05:50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements frozen v12 Task 4a (
clotho/inventory.mjs,clotho/weavers/util.mjs,clotho/weavers/git.mjs,clotho/weavers/code.mjs,clotho/scripts/test-closure.mjsresolver + closure derivation; comment/string-aware lexer; Phase-1 export
scanner + import parser; real-file walker; D26/D29 counted-iterator; D21
physical-containment; no-shell weaver-facing git wrapper; source seeding.
contract-files (D31), run sources, five weavers + integer versions, the frozen
REQUIRED_INVENTORY_IDStable, the deep-frozen D32 loader-safe-exports map,git/code implementation closures (D33). Per AM-17, only git+code weaver
inventories are committed at this PR; ledger/test/doc land in 4b, orchestrator
in Task 5.
introduced-by) and code weaver(
depends-on, all four endpoint shapes).accepted-relative-module-load closure (never trusted), with fixtures for every
accepted form and all fatal/no-edge failure modes.
Authorization: The Eye's Clotho Phase 1 implementation decision (#109), v12
sha256:bdc93901…, authz-005, per-task cadence.npm testgreen (7 tests);confined to
clotho/; zero dependencies.🤖 Generated with Claude Code