Skip to content

feat(kernel-utils): add sheaf programming module#870

Draft
grypez wants to merge 7 commits intomainfrom
grypez/bringing-in-the-sheaves
Draft

feat(kernel-utils): add sheaf programming module#870
grypez wants to merge 7 commits intomainfrom
grypez/bringing-in-the-sheaves

Conversation

@grypez
Copy link
Contributor

@grypez grypez commented Mar 4, 2026

Introduce operational presheaf + sheafify for guard-based dispatch:

  • Section/guard types, presheaf construction, stalk filtering
  • Late decider (lift) selects winner when multiple sections match
  • Modular sheaf/ directory with single-concern files and e2e tests

@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 76.51%
⬆️ +0.41%
6827 / 8922
🔵 Statements 76.43%
⬆️ +0.44%
6944 / 9085
🔵 Functions 74.42%
⬆️ +0.47%
1694 / 2276
🔵 Branches 75.6%
⬆️ +0.25%
2557 / 3382
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/kernel-utils/src/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/kernel-utils/src/sheaf/guard.ts 98.33% 95.83% 100% 98.21% 53
packages/kernel-utils/src/sheaf/metadata.ts 100% 100% 100% 100%
packages/kernel-utils/src/sheaf/sheafify.ts 92.5% 75% 100% 92.17% 45, 48, 103, 120, 158-161, 163-165, 169-171, 243, 263
packages/kernel-utils/src/sheaf/stalk.ts 89.47% 86.66% 100% 88.23% 37, 76
packages/kernel-utils/src/sheaf/types.ts 100% 100% 100% 100%
Generated in workflow #3911 for commit f4bb458 by the Vitest Coverage Report Action

@grypez grypez force-pushed the grypez/schema-dunder branch from 4184513 to 03f6113 Compare March 9, 2026 19:07
@grypez grypez force-pushed the grypez/bringing-in-the-sheaves branch from 487dd20 to 282a277 Compare March 9, 2026 19:08
@grypez grypez changed the title feat(kernel-exo): add sheaf programming module feat(kernel-utils): add sheaf programming module Mar 9, 2026
@grypez grypez force-pushed the grypez/bringing-in-the-sheaves branch from 4123110 to 2519237 Compare March 10, 2026 14:28
Base automatically changed from grypez/schema-dunder to main March 10, 2026 16:59
grypez and others added 7 commits March 10, 2026 18:06
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ESCRIPTION

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion

`getSection({ guard, lift })` now requires an explicit interface guard,
mirroring how `makeExo` always requires one. `getGlobalSection({ lift })`
is the new convenience wrapper that computes the full union guard from
all presheaf sections, analogous to `makeDefaultExo`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… dispatch

Replace string-log side-channels and return-value inference with explicit
vi.fn() spy assertions. Each section's handler is a named mock; tests call
expect(spy).toHaveBeenCalledWith(...) and .not.toHaveBeenCalled() to verify
routing directly rather than inferring it from coincident return values.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rg sections

`getGuardAt` was returning `undefined` for positions beyond a section's
fixed argument range, even when a `restArgGuard` was present. This caused
rest-arg sections to be absent from optional-position unions, producing
a false negative: e.g. `M.call().rest(M.string())` would not cover
position 0 in the union, so a call `['hello']` would fail the collected
guard even though the section accepts it.

Fix: fall through to `payload.restArgGuard` after exhausting the optional
array, so rest-arg sections contribute to every optional position in the
union.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add MetaDataSpec<M> discriminated union (constant | source | callable) so
that sheaf metadata can vary with call arguments rather than being static.

- constant(v)   — static value, evaluated once
- source(s)     — JS source string compiled via Compartment at sheafify
                  construction time, called at dispatch time
- callable(fn)  — live function called at dispatch time

PresheafSection.metadata changes from M to MetaDataSpec<M> (breaking).
A new EvaluatedSection<M> type carries post-evaluation metadata and is
what Lift receives as its germs array.  EvaluatedSection is distinct from
PresheafSection because the "germ" in the sheaf-theoretic sense only
exists after quotienting by the metadata-equivalence relation (the
collapseEquivalent step); EvaluatedSection describes the pre-collapse
stage where the spec has been applied to the invocation args.

getStalk is generalised to <T extends { exo: Section }> so it works over
ResolvedSection (the internal post-resolution type) without a cast.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- getStalk: accept readonly T[] to allow frozen section arrays
- evaluatedStalk map: omit metadata property when undefined to satisfy
  exactOptionalPropertyTypes (metadata?: M ≠ metadata: M | undefined)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@grypez grypez force-pushed the grypez/bringing-in-the-sheaves branch from 0a7b40c to f4bb458 Compare March 10, 2026 22:07
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