spec: implement Direction 1 + 2 implicit binder auto-introduction (#20)#43
Open
kumavis wants to merge 1 commit into
Open
spec: implement Direction 1 + 2 implicit binder auto-introduction (#20)#43kumavis wants to merge 1 commit into
kumavis wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Implements the remaining work from docs/tracking/2026-02-22_IMPROVED_IMPLICIT_INFERENCE.org (Issue #20) by making spec signatures auto-introduce implicit binders for free capitalized identifiers (Direction 1) and refine higher-kinded binder kinds based on :where / inline trait constraints (Direction 2), plus updates stdlib specs and documentation to use the canonical “bare” form.
Changes:
- Update
process-specto preserve list-valued WS metadata entries (e.g.(:where (Foo A))) and to canonicalize auto-detected implicit binder ordering by kind after kind propagation. - Refactor many stdlib/book
.prologosspecs to drop redundant explicit{A : Type}/{C : Type -> Type}binders. - Add regression + idempotence tests and update tracking/docs to reflect the completed design.
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| racket/prologos/macros.rkt | Fix WS metadata merge shape for list-valued keys; add kind-ranking + post-propagation canonical ordering of auto-detected binders. |
| racket/prologos/tests/test-extended-spec.rkt | Adds new tests covering D1+D2 combined behavior, bare-vs-explicit idempotence, and single-inline-:where regression. |
| racket/prologos/lib/prologos/data/transducer.prologos | Removes redundant explicit Type binders from transducer specs to rely on auto-introduction. |
| racket/prologos/lib/prologos/data/map-entry.prologos | Removes redundant {K V : Type} spec binders. |
| racket/prologos/lib/prologos/core/string-ops.prologos | Removes redundant {A : Type} from string fold specs. |
| racket/prologos/lib/prologos/core/set.prologos | Removes redundant {A ... : Type} from set helper specs. |
| racket/prologos/lib/prologos/core/pvec.prologos | Removes redundant {A ... : Type} from persistent vector helper specs. |
| racket/prologos/lib/prologos/core/map.prologos | Removes redundant {K V : Type} from map helper specs. |
| racket/prologos/lib/prologos/core/lattice.prologos | Keeps explicit {K V : Type} for order-sensitive call sites; adds explanatory comments. |
| racket/prologos/lib/prologos/core/generic-ops.prologos | Removes redundant {A B : Type} {C : Type -> Type} from generic ops specs. |
| racket/prologos/lib/prologos/core/fio.prologos | Removes redundant {A : Type} from fio-with-file spec. |
| racket/prologos/lib/prologos/core/collections.prologos | Refactors collection API specs to canonical bare implicit style. |
| racket/prologos/lib/prologos/book/sets.prologos | Mirrors core set spec refactor in book chapter. |
| racket/prologos/lib/prologos/book/persistent-vectors.prologos | Mirrors core pvec spec refactor in book chapter. |
| racket/prologos/lib/prologos/book/maps.prologos | Mirrors core map/map-entry spec refactor in book chapter. |
| racket/prologos/lib/prologos/book/lattices.prologos | Mirrors lattice set-subset? spec change in book chapter. |
| racket/prologos/lib/prologos/book/generic-operations.prologos | Mirrors core generic ops spec refactor in book chapter. |
| racket/prologos/lib/prologos/book/datum-and-homoiconicity.prologos | Mirrors transducer spec refactor in book chapter. |
| racket/prologos/lib/prologos/book/collection-functions.prologos | Mirrors core collections spec refactor in book chapter. |
| racket/prologos/lib/prologos/book/characters-and-strings.prologos | Mirrors core string-ops spec refactor in book chapter. |
| racket/prologos/data/cache/pnet/prologos/data/nat.pnet | Updates a generated .pnet cache snapshot (likely unintended to commit). |
| racket/prologos/data/benchmarks/failures/test-reducible.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-pipe-compose-e2e-02.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-lang-errors-02-ws.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-lang-errors-01-sexp.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-lang-04-repl.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-lang-03-macros.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-lang-02-ws.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-lang-01-sexp.rkt.log | Removes benchmark failure log content. |
| racket/prologos/data/benchmarks/failures/test-functor-ws.rkt.log | Removes benchmark failure log content. |
| docs/tracking/MASTER_ROADMAP.org | Adds roadmap entry for Improved Implicit Inference (#20) completion. |
| docs/tracking/2026-02-22_IMPROVED_IMPLICIT_INFERENCE.org | Marks design as DONE and documents implementation details + follow-ups. |
| docs/spec/grammar.org | Updates spec grammar documentation to present the bare implicit form as canonical. |
| .claude/rules/prologos-syntax.md | Updates contributor guidance to prefer bare implicit variables in spec. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Closes the planned-but-unimplemented work from
`docs/tracking/2026-02-22_IMPROVED_IMPLICIT_INFERENCE.org`.
**Direction 1.** Bare capitalized identifiers in a `spec` are auto-
introduced as kind-`Type` implicit binders. `{A : Type}` is no longer
needed.
**Direction 2.** Higher-kinded variables get their kind inferred from
`:where` and inline trait constraints. `{C : Type -> Type}` is no longer
needed when a `Seqable C` / `Buildable C` constraint pins the kind.
Three changes in `macros.rkt`:
1. The keyword-headed-children merge in `process-spec` flattens single-
element `:where (Foo A)` into the bare constraint `(Foo A)` and crashes
`expand-bundle-constraints` at `(car 'Foo)`. Fixed by keeping known
list-valued keys (`:where`, `:properties`, `:laws`, `:includes`,
`:examples`, `:see-also`, `:implicits`) as lists.
2. After `propagate-kinds-from-constraints`, the auto-detected portion of
the binder list is now sorted by kind (kind-`Type` first, then higher-
kinded). This matches the convention `{A B : Type} {C : Type -> Type}`
that explicit-binder users have written for years and keeps the
inserted-implicit-arg order stable when callers omit explicit binders.
Explicit and `:over` binders keep their declared order.
3. New `kind-rank` / `implicit-binder-kind-ranks-before?` helpers; new
`auto-detected-names` accumulator threaded through the refinement
pipeline.
Stdlib refactor: redundant `{A : Type}`, `{A B : Type}`, `{K V : Type}`,
and `{C : Type -> Type}` binders dropped from spec lines across 17 files
in `core/` + `book/` + `data/`. The two specs `map-merge-with` and
`map-lattice-leq` retain explicit `{K V : Type}` because the Map-K-V
Lattice impl bodies pass `K V` as explicit type args; source-walk-order
auto-detection (which sees V first in `[V V -> V]`) would silently flip
the call-site argument order. Inline comments document the caveat.
Tests: 3 new cases in `test-extended-spec.rkt` covering the issue's
target form (`spec gmap [A -> B] -> [C A] -> [C B] :where (Seqable C)
(Buildable C)`), bare-vs-explicit idempotence, and the single-constraint
inline `:where` regression. All 15 affected test files (296 tests) and
all 19 spec/elaborator/HKT/trait test files (389 tests) pass.
Docs: `docs/spec/grammar.org` and `.claude/rules/prologos-syntax.md`
updated to document the canonical bare form; design doc flipped
PLANNED → DONE; Master Roadmap entry added.
https://claude.ai/code/session_01UEKqhSHN5y9XEg88BkFnsW
data: refresh test timings + propagator-cache + failure logs
Build artifacts from the issue #20 verification runs. The failure logs
are all pre-existing infrastructure issues (`prologos/propagator` and
`rackcheck` collection imports unresolvable in this sandbox without the
`prologos` package installed and rackcheck wired in) — none are caused
by the spec / auto-introduction changes.
https://claude.ai/code/session_01UEKqhSHN5y9XEg88BkFnsW
data: drop stale + environment-only failure logs
The previous commit (a254cda) committed 17 failure logs that were a mix
of stale and resolvable:
- 9 logs referenced `/Users/avanti/dev/projects/prologos/...` paths
(the user's local Mac tree), for tests that don't even exist in this
repo — purely stale.
- 6 logs (test-attribute-record, test-facet-tag-dispatch,
test-meta-feedback, test-ppn-track4, test-propagator-patterns,
test-sre-coverage) failed with "collection not found: prologos/
propagator" because the `prologos` collection wasn't linked in this
sandbox. Fixed by `raco link --user --name prologos racket/prologos`;
all 6 now pass (91 tests total).
- 2 logs (test-generators, test-properties) genuinely require the
external `rackcheck` package, which can't be installed here because
the package catalog (download.racket-lang.org/releases/9.0/catalog)
returns 403 and github.com clones are blocked from this sandbox.
These are not real failures of the codebase — only of the sandbox's
network reachability — and they're orthogonal to issue #20.
Net change: drop all 17 stale logs. The 2 rackcheck-blocked tests will
fail again on any machine without rackcheck installed; they're a known
external-dep gap, not introduced or affected by this branch.
https://claude.ai/code/session_01UEKqhSHN5y9XEg88BkFnsW
data: revert all benchmark/failures/ diffs to match main
Restore the 9 stale failure logs that were on main before this branch.
The previous two commits (a254cda, dbd42c9) churned this directory
unnecessarily; this commit makes the branch's net diff for
racket/prologos/data/benchmarks/failures/ empty against main.
https://claude.ai/code/session_01UEKqhSHN5y9XEg88BkFnsW
spec: address PR #43 review comments
1. kind-rank: rank ANY (Type n) as 0, not just (Type 0). Forward-
defensive against universe-level inference producing (Type 1+) for
auto-introduced binders — those would previously have fallen to the
"elaborate" rank and sorted after higher-kinded arrows.
2. Drop the racket/prologos/data/cache/pnet/prologos/data/nat.pnet diff.
The file embeds an absolute build path + timestamp; the cache directory
is already in .gitignore (the file is tracked from before the ignore
rule). The diff was pure path/timestamp churn with no semantic change.
https://claude.ai/code/session_01UEKqhSHN5y9XEg88BkFnsW
30d484e to
4dccebe
Compare
kumavis
pushed a commit
that referenced
this pull request
May 19, 2026
Cross-impl check against @endo/ocapn revealed that Phase 52b's dedicated op:deposit-gift / op:withdraw-gift wire ops are NOT the canonical OCapN model. Endo dispatches gift handoff as method calls on the bootstrap object (export 0) with signed HandoffReceive envelopes — not as dedicated CapTPOp variants. Our wire ops are a Prologos extension. The gift TABLE (Phase 52) is unaffected; only the wire-level surface (Phase 52b) is in question. Three resolution paths logged in roadmap: (a) revert + redesign as bootstrap-method dispatch (b) keep as fast-path + add bootstrap-method dispatch alongside (c) document deviation, defer decision Pitfall #43 logged: wire-format invented before checking peer reference impl. The workflow rule "external cross-impl gates are mandatory test infrastructure for protocol ports" was violated — Phase 52b's tests were all hand-written internal round-trips, no @endo/ocapn peer was consulted. Codified the prevention: Phase 0 of any wire-extension phase is "search the reference implementation for the wire shape." https://claude.ai/code/session_01YM6gc3cMNH2Ymor4jdZY8u
kumavis
pushed a commit
that referenced
this pull request
May 19, 2026
…+ cross-impl gate The previous Phase 52b shipped dedicated op:deposit-gift / op:withdraw-gift wire ops. Those are NOT the OCapN canonical model — @endo/ocapn dispatches gift handoff as METHOD CALLS on the bootstrap object (export 0), inside the normal op:deliver flow (see @endo/ocapn/src/client/ocapn.js:528+). This commit reverts the non-canonical surface and re-implements the dispatch in the spec-compatible form. REVERTED from prior 52b (commit 6d10c58): - op-deposit-gift / op-withdraw-gift CapTPOp variants (all 4 predicates + 4 selectors + encoder + decoder + dispatch) - dedicated wire tags op:deposit-gift / op:withdraw-gift - 11 internal-only tests that exercised the non-canonical shape ADDED (canonical bootstrap-method dispatch): - maybe-bootstrap-method gateway in captp-bridge: when an op-deliver arrives with target=0 and args is a syrup-list starting with a recognised method-symbol, route to the gift handlers; otherwise fall through to the normal op-deliver dispatch path. - dispatch-deposit-gift-rest / dispatch-withdraw-gift-rest: extract gid (Nat) + refr/resolver from the args tail. - do-deposit-gift / do-withdraw-reply: the actual gift-table mutations + reply-bytes queueing. - syrup-list-or-nil + syrup-symbol-name: 1-arg shape filters that let callers avoid 11-arm SyrupValue match enumeration. Wire shape now matches @endo/ocapn: Deposit: <op:deliver <desc:export 0> (sym deposit-gift, gid+, <desc:export xid+>) false false> Withdraw: <op:deliver <desc:export 0> (sym withdraw-gift, gid+) <desc:answer ap+> false> Reply: <op:deliver <desc:answer ap+> <desc:export xid+> false false> (Reply uses the standard op:deliver-to-answer path — peer's local promise tied to ap resolves with the gift refr.) The gift TABLE infrastructure from Phase 52 (bs-add-gift, bs-lookup-gift, bs-remove-gift) is UNCHANGED — it was always correct; only the wire-surface layer needed revision. Cross-impl gate (new): peer-bootstrap-gift.mjs receives our 3-frame session+deposit+withdraw blob, decodes via @endo/ocapn's Syrup decoder, verifies the structural shape matches what @Endo would treat as canonical bootstrap-method dispatch. The wire-shape validation is what's tested; @Endo's deposit-gift / withdraw-gift HANDLERS aren't exercised (they require signed HandoffReceive envelopes + key-pair management beyond Phase 52b's scope). Pitfall discovered & worked around: @Endo's syrup decoder prefixes decoded symbols with a "syrup:" namespace (Symbol with description "syrup:deposit-gift" rather than "deposit-gift"). The peer's isSymWithSuffix accepts both forms — defensive against future namespace changes. Not codified as a goblin-pitfall since it's an @endo/JS-decoder quirk, not Prologos. Tests (149 bridge + 9 new bootstrap-dispatch tests + 1 interop): - deposit-gift via op:deliver to bootstrap records the gift - records correct gid→xid mapping - non-export refr is silent drop - withdraw-gift looks up + queues reply - unknown gid is silent drop - no answer-pos is silent drop (no reply channel) - reply wire shape: op:deliver to desc:answer with desc:export gift - non-bootstrap target falls through (regression) - unknown method symbol falls through (regression) - cross-impl: @Endo decodes our 3-frame blob and confirms shape Pitfall #43 (Wire-format invented before checking peer reference impl) reverted from goblin-pitfalls — that's an OCapN methodology lesson, not a Prologos language/tooling bug. Goblins doc focuses on Prologos-specific issues. https://claude.ai/code/session_01YM6gc3cMNH2Ymor4jdZY8u
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.
Fixes #20
Closes the planned-but-unimplemented work from
docs/tracking/2026-02-22_IMPROVED_IMPLICIT_INFERENCE.org.Direction 1. Bare capitalized identifiers in a
specare auto-introduced as kind-
Typeimplicit binders.{A : Type}is no longerneeded.
Direction 2. Higher-kinded variables get their kind inferred from
:whereand inline trait constraints.{C : Type -> Type}is no longerneeded when a
Seqable C/Buildable Cconstraint pins the kind.Three changes in
macros.rkt:The keyword-headed-children merge in
process-specflattens single-element
:where (Foo A)into the bare constraint(Foo A)and crashesexpand-bundle-constraintsat(car 'Foo). Fixed by keeping knownlist-valued keys (
:where,:properties,:laws,:includes,:examples,:see-also,:implicits) as lists.After
propagate-kinds-from-constraints, the auto-detected portion ofthe binder list is now sorted by kind (kind-
Typefirst, then higher-kinded). This matches the convention
{A B : Type} {C : Type -> Type}that explicit-binder users have written for years and keeps the
inserted-implicit-arg order stable when callers omit explicit binders.
Explicit and
:overbinders keep their declared order.New
kind-rank/implicit-binder-kind-ranks-before?helpers; newauto-detected-namesaccumulator threaded through the refinementpipeline.
Stdlib refactor: redundant
{A : Type},{A B : Type},{K V : Type},and
{C : Type -> Type}binders dropped from spec lines across 17 filesin
core/+book/+data/. The two specsmap-merge-withandmap-lattice-leqretain explicit{K V : Type}because the Map-K-VLattice impl bodies pass
K Vas explicit type args; source-walk-orderauto-detection (which sees V first in
[V V -> V]) would silently flipthe call-site argument order. Inline comments document the caveat.
Tests: 3 new cases in
test-extended-spec.rktcovering the issue'starget form (
spec gmap [A -> B] -> [C A] -> [C B] :where (Seqable C) (Buildable C)), bare-vs-explicit idempotence, and the single-constraintinline
:whereregression. All 15 affected test files (296 tests) andall 19 spec/elaborator/HKT/trait test files (389 tests) pass.
Docs:
docs/spec/grammar.organd.claude/rules/prologos-syntax.mdupdated to document the canonical bare form; design doc flipped
PLANNED → DONE; Master Roadmap entry added.
https://claude.ai/code/session_01UEKqhSHN5y9XEg88BkFnsW