Commit Graph
100 Commits
Author SHA1 Message Date
tmu f7b7a06f1a ✅ Assert the fallback receives real boolean/nullish tags 2026-09-22 10:33:26 +00:00
tmu c06538d6c1 📝 Check off the tagged-union non-key tags task 2026-09-22 10:23:06 +00:00
tmu e96ca12149 ✨ Allow boolean and nullish tags in tagged unions
A `boolean` / `null` / `undefined` discriminant cannot key a handler
map, so the tagged-union matcher now routes it through the
`PatternKey` / `PatternParam` projection the primitive-union matcher
already used. Both matchers share the projection from
`matcher-shared.ts`; `MapTaggedUnion`, `Handlers`, `HandledMembers`
and `MustBePartial` key off the projected form and invert it to
recover the real member.

Covers exhaustive and fallback dispatch, the redundant-fallback
guard, and the LSP popup offering the tags by name.
2026-09-22 10:22:59 +00:00
tmu b81a8149d9 🔀 Merge chore/rename-primitive-union into main 2026-09-22 09:58:28 +00:00
tmu a88d49ffe2 📝 Check off the primitive-union rename 2026-09-22 09:47:05 +00:00
tmu 02f736507c ♻️ Rename primitive to primitive-union
`getMatcher` / `getMatcherW` become `getPrimitiveUnionMatcher` /
`getPrimitiveUnionMatcherW`; `src/primitive.ts` and its test move to
`src/primitive-union.*`. The `Union` suffix mirrors `getTaggedUnionMatcher`.
2026-09-22 09:46:59 +00:00
tmu 0727117afb 🔀 Merge chore/lsp-symbol-search-rule into main 2026-09-22 09:43:56 +00:00
tmu b293e611b2 📝 Prefer LSP for symbol lookup in AGENTS 2026-09-22 09:43:08 +00:00
tmu 63b020338e 🔀 Merge chore/backlog-notes into main 2026-09-22 09:15:04 +00:00
tmu 32b9ce0987 📝 Note two matcher gaps in the backlog
Record the non-exhaustive broad-type hole in the primitive matcher and the
never-typed handler parameters the tagged-union matcher produces when a
property is a union, so both can be picked up as their own work units.
2026-09-22 09:14:58 +00:00
tmu 434c3a2222 🔀 Merge feature/tagged-union-matcher into main
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 27s
CI / publish (push) Skipped
CI / maintain (push) Failing after 15s
2026-09-21 23:29:48 +00:00
tmu 6280061737 📝 Note the primitive-union rename in the backlog 2026-09-21 23:24:06 +00:00
tmu 23a2776d55 📝 Note the widened-string-union matcher test 2026-09-21 23:21:19 +00:00
tmu 937d84ea48 ♻️ Share matcher internals 2026-09-21 23:15:09 +00:00
tmu 6f4f509b69 ⚡ Inline the tag read into dispatch 2026-09-21 23:02:56 +00:00
tmu 3f22e5ca01 🔥 Drop unused unified-signature disables 2026-09-21 22:53:42 +00:00
tmu 78e9af600d ✅ Cover the discriminant-key popup 2026-09-21 22:36:30 +00:00
tmu 8ab3c6dbc6 📝 Document the tagged-union matcher 2026-09-21 22:14:22 +00:00
tmu c0fc090ee4 ✨ Add a matcher for tagged unions 2026-09-21 22:14:10 +00:00
tmu a4b4618c9f 🚀 Release 0.5.0
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 30s
CI / maintain (push) Failing after 14s
CI / publish (push) Failing after 17s
2026-09-21 13:11:27 +00:00
tmu bf711cf9fc 🔀 Merge chore/test-handler-runtime-arguments into main 2026-09-21 13:09:10 +00:00
tmu 9e03c52473 ✅ Assert the shape each handler receives
A handler's `expectTypeOf(shape)` only proved the type the compiler inferred;
nothing observed the argument `dispatch` passed. Passing `String(shape)` at the
call site therefore kept the whole suite green while breaking every key whose
property name differs from its value (`true`, `null`, `1`).

Pair each handler expectation with a runtime assertion: `assert.equal` where a
handler runs for one shape, the disjunction over the set a `_` fallback accepts
where it runs for several. Where the exact value matters the fallback returns
its shape verbatim and the call site asserts it; a widening pattern absorbs the
remainder type into the return union, so the claim stays strict-free. The
mutation above now fails 10 of the 33 tests.

Rule: CONTRIBUTING.md, rationale: development/testing.md § Handler arguments.
2026-09-21 12:52:58 +00:00
tmu aa6d71076c 🔀 Merge feature/boolean-null-undefined-patterns into main 2026-09-21 11:27:29 +00:00
tmu 80d498e4f4 ⚡ Index dispatch with the raw shape key
String(shape) defeats V8's numeric-key fast path (measured ~2x on
number-keyed dispatch). JS already coerces boolean/null/undefined to the
same property key, so assert shape to string | number and index directly.
The assertion is TS2538-only; the facade keeps it sound. Needs a source
no-unsafe-type-assertion disable, next to the existing one.
2026-09-21 11:23:14 +00:00
tmu 1ad19ba308 📝 Document matcher caveats in the README
State the end-user limits once, in README § Caveats: a member colliding
with its stringification, the unsupported symbol/bigint, and NaN/-0. Drop
the duplicated known-issue prose from development/library.md and the
source comment; link to the README instead.
2026-09-21 10:33:36 +00:00
tmu 16904440cf 📝 Place test-wide suppressions in the config
Drop the fixed no-floating-promises header exception from CONTRIBUTING.md
and AGENTS.md; agents must not add a source disable or edit .oxlintrc.json.
Record the split in tooling.md and testing.md: a one-site false positive is a
source disable, a file-class one lives in the test override.
2026-09-21 10:01:30 +00:00
tmu 9b7dec96e0 🔧 Move test lint disables to oxlint config
The no-floating-promises header was repeated at the top of every test
file. Centralize it, and the no-null suppression the new null/undefined
cases need, in the **/*.test.ts override.
2026-09-21 09:56:39 +00:00
tmu 45495fe2a8 ✨ Match boolean, null and undefined
Extend the matcher universe beyond string | number so a union can carry
boolean, null and undefined members. true|false, null and undefined are
not property keys, so handler keys are their stringification while the
callback still receives the real member. Symbols are rejected (a brand
is compile-time only) and bigint is not a property key.
2026-09-21 09:44:44 +00:00
tmu c32fe08c73 🔀 Merge chore/spike-redundant-fallback into main
CI / release-gate (push) Successful in 3s
CI / build (push) Successful in 24s
CI / publish (push) Skipped
CI / maintain (push) Failing after 16s
2026-09-20 22:08:35 +00:00
tmu f27966e803 ✨ Reject a fallback for an exhaustive map
A fallback paired with a handler map that already covers `T` was still
accepted, even though its remainder is empty. Fold the guard into
`Handled`'s own (F-bounded) constraint so it is checked after inference;
a conditional in the fallback parameter is evaluated while `Handled` is
still its constraint and rejects every partial map whose handler callbacks
need contextual typing.
2026-09-20 22:05:40 +00:00
tmu 7e7f716424 🚀 Release 0.4.0
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 30s
CI / maintain (push) Failing after 14s
CI / publish (push) Failing after 16s
2026-09-20 21:46:32 +00:00
tmu 62db7de537 🔀 Merge chore/unify-task-branching into main 2026-09-20 21:44:21 +00:00
tmu ff823b3cba 📝 Route every task through the full branching model
Drop the leaf-task exception in AGENTS.md: a task without subtasks was implemented on the current branch, bypassing create:branch / create:finish. Every task now opens and closes a branch, so the clean-tree / current-main / green-baseline preconditions and the post-merge verify always apply.
2026-09-20 21:43:46 +00:00
tmu eeb831b717 🔀 Merge feature/fallback-remainder into main
CI / release-gate (push) Successful in 3s
CI / build (push) Successful in 24s
CI / publish (push) Skipped
CI / maintain (push) Failing after 15s
2026-09-19 00:02:23 +00:00
tmu ae7ffb6fa2 📝 Document the two-argument fallback
Rewrite development/library.md around the new shape: the fallback is a second
argument (so it can receive the remainder), `R` needs an inference site in the
handler map, `Exact` restores the excess-property check, and the overload order
is load-bearing. Record this branch's rejected alternatives (single-object `_`,
currying, `this`/HKT, variance/`const`/`NoInfer`/brands) and the redundant-
fallback known issue. Add the changelog note and check off the backlog task.
2026-09-18 23:52:47 +00:00
tmu 0d6a3f1b9b ✅ Cover the dispatch throw
An open universe (`getMatcher<string>()`) types its handler map as an index
signature, so a runtime map with fewer keys still satisfies the exhaustive
overload. Calling the matcher with a missing shape reaches the dispatch guard
and throws — no cast needed.
2026-09-18 23:48:59 +00:00
tmu 8615723c64 ✅ Cover fallback autocompletes
When a fallback argument is present, the second overload supplies the
contextual type, so the handler map popup offers optional keys (`a? b? c?`)
and handled keys stay optional (`b? c?`). The exhaustive one-argument popup
is unchanged. Covered for both factories.
2026-09-18 23:44:51 +00:00
tmu 935e82d205 ✅ Reject a mismatched strict fallback
The factory-contract test now also covers a fallback whose return does not
fit the common return of the handler map — a `number` handler with a
`string` fallback — which `getMatcherW` accepts as `number | string`.
2026-09-18 23:37:44 +00:00
tmu c7223dbe69 🐛 Infer strict return from the handler map
The fallback overload could not infer `R` from the handlers: `R` appeared
only inside the `Exact` constraint, which is not an inference site, so with
inferred handler params it collapsed to `unknown` and the matcher silently
returned `UnaryFn<T, unknown>`. Adding `Partial<Handlers<T, R>>` to the
handler parameter gives `R` an inference site, so the common return is
inferred from the handlers and the fallback alike.

Tests drop their explicit handler return annotations: real handlers are short
and unannotated, and the common type is now inferred from them.
2026-09-18 23:33:34 +00:00
tmu 2d3577716d ✨ Narrow the fallback to unhandled keys
The fallback is now the second factory argument — `(handlers, (s) => …)` —
so its parameter is `Exclude<T, keyof handlers>`. A property's contextual
type is fixed before TypeScript infers its sibling keys, so the remainder is
not expressible while the fallback sits in the handler map; a later argument
is contextually typed from inference on an earlier one.

Both factories take the new shape; the tests and autocomplete probes follow.
The generic overloads guard excess keys with type-fest's `Exact`, so the
error lands on the offending property. A redundant fallback (a full handler
map plus one) is still accepted — the guard for it does not survive inference
and is left to its backlog task.
2026-09-18 23:08:16 +00:00
tmu cc88c07961 🚀 Release 0.3.0
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 29s
CI / maintain (push) Failing after 15s
CI / publish (push) Failing after 18s
2026-09-18 07:51:16 +00:00
tmu 62c37e6d89 🔀 Merge chore/protocol-backed-lsp-helper into main
CI / release-gate (push) Successful in 3s
CI / build (push) Successful in 24s
CI / publish (push) Skipped
CI / maintain (push) Failing after 14s
2026-09-18 07:45:22 +00:00
tmu 947eac8089 ⏪ Revert the LSP notes in testing.md
The protocol cross-link and the TS-internal shutdown-race explanation were
too detailed for the category doc. The helper comment keeps a short,
self-contained note on the stdin-EOF workaround.
2026-09-18 07:43:36 +00:00
tmu eea2fbb17d 🚨 Silence helper oxlint warnings
The completion helper is test-only (excluded from dist/), so the
style-only no-magic-numbers and unicorn/no-null warnings are tolerable
here. A file-level disable keeps them out of check:oxlint without touching
the project config.
2026-09-18 07:38:13 +00:00
tmu b278a153d3 📝 Check off the LSP shutdown bug
Record the cause (Session.updateWatches raced against exit) and the
stdin-EOF fix now that npm run verify is green with no context-canceled
output.
2026-09-18 07:31:10 +00:00
tmu 8b73143740 🐛 Stop the LSP shutdown context-canceled log
The TS 7 Go server races Session.updateWatches against the exit
notification; handleExit returns io.EOF, the background context is
cancelled, and the bare error is flushed to stderr once the outgoing
queue closes (server.go / logger.go). Send shutdown and close stdin
instead: EOF makes the server exit cleanly (code 0, no output), with the
kill kept as a fallback. testing.md records the cause.
2026-09-18 07:31:04 +00:00
tmu 13497d1df8 📝 Check off the LSP helper task
npm run verify is green: 23 tests pass, check:tsc, check:oxlint, check:oxfmt
and check:cspell clean with the protocol-backed helper.
2026-09-18 07:17:19 +00:00
tmu 998c4bfd80 📝 Document the protocol-backed LSP helper
Note that the autocomplete helper drives the server through
vscode-languageserver-protocol, cross-link the tooling decision, and replace
the obsolete string-id known issue with the benign context-canceled stderr
the Go server emits on shutdown.
2026-09-18 07:16:45 +00:00
tmu 9f56d7ae8e ♻️ Back LSP helper with protocol library
Replace the hand-rolled JSON-RPC client (framing, pending map, reply
dispatch) with createMessageConnection and typed requests from
vscode-languageserver-protocol. A catch-all onRequest answers the server
requests the old client replied to, and CompletionList/CompletionItem
replace the ad-hoc shape guards. Public LspSession API is unchanged.
2026-09-18 07:16:25 +00:00
tmu 94ccc16963 ➕ Add the LSP protocol dependency
The autocomplete helper drives tsc --lsp --stdio; vscode-languageserver-protocol
supplies the transport (re-exported vscode-jsonrpc/node) and the typed LSP
requests, replacing the hand-rolled JSON-RPC client. Record the choice and
the rejected alternatives in tooling.md.
2026-09-18 07:14:45 +00:00
tmu 0b97632a7c 📝 Track protocol-backed LSP helper
The autocomplete helper still carries a hand-rolled JSON-RPC client
(Content-Length framing, a pending-request map, server-request replies).
vscode-languageserver-protocol provides all of it plus typed requests, so
track the move as a task with subtasks.
2026-09-18 07:14:18 +00:00
tmu 6f87c2f3b5 🔀 Merge chore/adopt-three-overload-matcher into main 2026-09-17 21:56:41 +00:00
tmu 88159296d4 📝 Drop the stale scripts test glob from testing.md
No tests live under scripts/, and every test script (test, test:unit, test:ci,
watch:test) globs only src/**/*.test.ts, so state that. The scripts/**
oxlint scope it was confused with still exists and carries the same
import/no-nodejs-modules exception as the test-helper scope.
2026-09-17 21:55:41 +00:00
tmu 800c11139d ♻️ Name the matcher factories getMatcher / getMatcherW
Drop the strict/widened aliases from src/index.ts so the factories are
exported under their own names, and align the type tests, the autocomplete
probe (which now imports the public surface from ./index.ts) and library.md
with them.

Also correct the widened-overload comment: the excess-property check does not
apply to a generic P, so MatcherWidening's keyof guard — not the closed
constraint — is what rejects keys outside T/_, as library.md already
documented.
2026-09-17 21:48:54 +00:00
tmu 05fad0fcd6 📝 Record the autocomplete and matcher-design decisions
The matcher is now two three-overload factories; library.md documents why
the union merge, inferred universe, conditional RequireKeys and cases-first
paths were rejected, and lists the two open issues (the fallback sees all of
T; a redundant _ is still accepted). testing.md records the language server
as the autocomplete oracle, and CONTRIBUTING points the exception at the
matcher's own test file.

The backlog marks the design-doc and autocomplete groundwork done alongside
the adoption.
2026-09-17 20:59:28 +00:00
tmu 58d127da4e ✅ Test the LSP completion helper against the server
The helper's own contract — marker handling, requested position, label
extraction and the rejection when the marker is absent — is asserted against
in-memory documents whose contextual types are written inline, so the helper
is tested without coupling to the library's code.
2026-09-17 20:59:19 +00:00
tmu 165bd9e3df ♻️ Adopt the three-overload matcher
strict/widened each take the exhaustive/fallback pattern shape in three
overloads ordered ExhaustiveLoose -> Fallback -> Handlers. TypeScript reads
the first overload for the object-literal popup (_?, a, b) and the last for
the missing-key error, so autocomplete and the error message are tuned
independently. The fallback is a pattern shape, not a factory, so the four
getPrimitiveUnionMatcher* factories collapse to two.

src/index.ts re-exports the two factories; the prototype scratch files that
explored the alternatives are removed.
2026-09-17 20:59:09 +00:00
tmu 02634f41de 🔀 Merge chore/test-util-home into main 2026-09-17 13:33:41 +00:00
tmu 9da5b5dbf2 📝 Note the test-helper home in the changelog 2026-09-17 13:23:36 +00:00
tmu dc57529f0f 📝 Correct the upstream claim in branch.sh
`main` tracks `origin` (ssh); the comment claiming it tracked an
https companion remote was stale.
2026-09-17 13:23:34 +00:00
tmu 484e5c8ca5 📝 Allow the floating-promise header in test files
Agents may add the fixed file-level typescript/no-floating-promises
oxlint-disable header at the top of a `*.test.ts` file — the
expectTypeOf() misidentification is a documented false positive
(development/testing.md § Known issues) and the await/void workarounds
collide with eslint/no-void. Every other suppression stays the human
last resort it was.
2026-09-17 13:23:32 +00:00
tmu c51e32d6a6 📝 Record the test-helper home decision
development/testing.md § Test helpers: why name beats path under
import/no-relative-parent-imports, why the key needs `#`, why the
`__tests__` folder name, and what was rejected (flat placement, tsconfig
paths, rule exemptions).
2026-09-17 13:23:29 +00:00
tmu 9e5522c131 🚚 Home test helpers behind #test-utils/*
src/util/__tests__/ holds shared test helpers, reached from anywhere
in the source tree as `#test-utils/<name>.ts` through
package.json#imports. A bare `~/…` is not a valid imports key — Node
requires `#` — and a direction-free specifier keeps
import/no-relative-parent-imports from ever firing. The `__tests__`
folder name is the pattern tsconfig.build.json already excludes, so
helpers can never ship. Lint scoping: import/no-nodejs-modules off for
the folder (the probe spawns a language server) and
typescript/promise-function-async off to match its promise-returning
style. The LSP probe moves in from scripts/; a smoke test pins the
specifier's resolution and typing without starting a server.
2026-09-17 13:23:27 +00:00
tmu ee146ce350 🚀 Release 0.2.0
CI / release-gate (push) Successful in 3s
CI / build (push) Successful in 24s
CI / maintain (push) Failing after 15s
CI / publish (push) Failing after 17s
2026-09-16 22:07:16 +00:00
tmu 33c6d9dc8d 🔀 Merge chore/remove-example-code into main 2026-09-16 22:06:17 +00:00
tmu 65e885989b 📝 Backlog the README walkthrough restoration
The example-code removal stripped the synopsis and examples with the
template modules; track bringing them back around the real API, with the
previous section order recorded so its placement is not re-guessed.
2026-09-16 22:05:05 +00:00
tmu 16092350b8 📝 Check off example-code removal in backlog
Note the finished work under [Unreleased] and mark the task and its
subtasks done; retarget the v1.0 coverage tasks at the surviving
primitive module.
2026-09-16 21:58:14 +00:00
tmu a3eb6183af 🔥 Remove the match and pattern example modules
They were the template's demo API, not the library's real surface. Drop
them, their README walkthrough, and the tooling note that cited their
disable directives, and point index.ts at the primitive matchers that
remain.
2026-09-16 21:57:55 +00:00
tmu ce3d618757 🔥 Remove the example index spec
The spec only exercised the template's match/P example API. Removing it
first lets the modules and exports it imports go next without leaving a
dangling reference.
2026-09-16 21:57:42 +00:00
tmu 73e5bc0093 🔀 Merge chore/straighten-oxc-rules into main
CI / release-gate (push) Successful in 3s
CI / build (push) Successful in 23s
CI / publish (push) Skipped
CI / maintain (push) Failing after 14s
2026-09-16 21:50:14 +00:00
tmu 08513b36a9 📝 Check off straighten-oxc-rules in backlog
Note the finished work under [Unreleased] and mark the task and its
subtasks done.
2026-09-16 21:46:04 +00:00
tmu 068d6b4998 ♻️ Use line comments in primitive matchers
Replace the three `/* */` prose blocks with `//` line comments, matching
the rest of the codebase and the comment style the oxlint config now
allows.
2026-09-16 21:46:00 +00:00
tmu fa0b7f2e84 🔧 Allow ternaries and lowercase comments
Turn off `eslint/no-ternary` and `eslint/capitalized-comments` in the
project config: both encode a style the project rejects, so they belong in
the config's rule map rather than a per-site disable.

Scope the adjacent `oxlint-disable` decision to false positives and
record why a rejected stylistic rule is turned off project-wide.
2026-09-16 21:45:54 +00:00
tmu 71ecd508b7 🔀 Merge feature/primitve-pattern-matching into main 2026-09-16 21:40:57 +00:00
tmu c13bc2f408 📝 Document why any is retained in primitive matchers
Rewriting without any was evaluated; the alternatives were more
complex than the current solution. Record the rationale next to the
two oxlint-disable sites so the suppression is not re-litigated.
2026-09-16 21:39:46 +00:00
tmu 8e2691e6aa 📝 Will add backlog items found while working 2026-09-16 20:43:01 +00:00
tmu 16650b07e3 📝 Backlog primitive literal coverage questions 2026-09-16 20:01:20 +00:00
tmu a0f0894339 ✅ Spec mixed string and numeric union keys 2026-09-16 20:01:12 +00:00
tmu ed71929365 ✅ Check matcher handler params
The primitive union matchers invoke every handler with the matched
literal, but the specs wrote their handlers with zero parameters, so
the passed value and its inferred key-literal type went untested.

Declare the parameter on each such handler and pin it with
expectTypeOf, matching the style the two already-correct handlers used.
The `_` fallbacks assert the whole union rather than a single literal.
Return-type expectations are unchanged, so the W / non-W widening
distinctions are still covered.
2026-09-16 19:29:04 +00:00
tmu cce030b8e5 🐛 Type partial W matcher without an any cast
getPrimitiveUnionMatcherPartialW was declared with the intended
P-inferring signature but assigned via `as any`, hiding that the
declared parameter was not assignable to the implementation's. The
union in PatternPrimitiveUnionPartial makes the `_` arm demand
`_ ∈ keyof P`, which the exhaustive arm cannot prove.

Intersect the inference hook Simplify<P> with the implementation's
parameter shape, R pinned to PatternReturns<P>, so the assignment
type-checks while callers keep inferring P from the argument.

Add a spec for the exhaustive (no `_`) pattern.
2026-09-16 19:10:40 +00:00
tmu 2ff67801e0 ✨ Add VS Code node:test debugging and runner config
launch.json: 'Debug current test file' F5 config running
node --test --strip-types on the active file.

settings.json: register .ts with the connor4312.nodejs-testing
extension via nodejs-testing.extensions, using --strip-types (the
repo pins node >=26 with native type stripping) instead of tsx, so
the extension discovers src/*.test.ts and shows Run/Debug lenses
above test() calls in the native Testing UI.

extensions.json: recommend connor4312.nodejs-testing; cspell.json:
allow 'connor' for the extension id.

.gitignore: un-ignore .vscode/launch.json so the config is shared.
2026-09-16 17:34:53 +00:00
tmu 62a5599ab3 📝 Require labeled AAA blocks in tests
Rule in CONTRIBUTING.md; decision, why and rejected unlabeled
ordering in development/testing.md.
2026-09-16 16:00:43 +00:00
tmu 34567856a5 ♻️ Label arrange-act-assert blocks in specs
Rework every test body into // Arrange / // Act / // Assert blocks
separated by blank lines: the factory is arranged once, the matcher is
built from it in a single act, and all type/runtime checks sink to the
end. index.test.ts adopts the same shape.

Also migrate off expect-type's deprecated toMatchTypeOf: the checks
are assignability tests, so toExtend is the faithful replacement.
2026-09-16 16:00:41 +00:00
tmu a25ac6d1e2 ✅ Spec primitive union matchers
Type-driven tests: every expectTypeOf pairs an assert, covering the
header matrix (exhaustive vs partial patterns, strict R vs widened
returns, string and numeric keys, _ fallback wiring).

Negative cases use Parameters<typeof factory>[0] assignability because
expect-type's .not.toBeCallableWith collapses to never on these generic
Simplify<>-wrapped signatures.

Same documented expectTypeOf floating-promise false positive as
index.test.ts, so the same file-level disable applies; testing.md
known-issue updated to list both files.
2026-09-16 14:52:30 +00:00
tmu 40bf652b97 ✨ Add primitive union pattern matchers
Curried matchers over string|number literal unions in four variants
(exhaustive/partial x strict/widened return inference), per the header
matrix in src/primitive.ts.

- Adds type-fest for Simplify/ValueOf.
- Deliberate oxlint escape hatches (as any dispatch) until a cast-free
  formulation lands; see the file comments.
2026-09-16 14:52:21 +00:00
tmu 1e13917cbe 🚀 Release 0.1.8
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 25s
CI / maintain (push) Successful in 15s
CI / publish (push) Failing after 15s
2026-09-16 09:01:49 +00:00
tmu 42281a0f10 🔀 Merge chore/upgrade-deps into main 2026-09-16 08:56:32 +00:00
tmu c15bc0153e 📝 Require concise prose in development/
Actionable sentence in CONTRIBUTING.md § Rules the tools don't enforce;
the why — humans skim, agents imitate the dominant style, so verbosity
compounds — in development/README.md § Decision blocks. Both sides in
one commit per the write-each-fact-once rule.
2026-09-16 08:00:36 +00:00
tmu ae319f6547 🔧 Ignore @types/node in maintain:outdated
DefinitelyTyped keeps the @types/node latest dist-tag on the LTS line,
so check-outdated compared the current-line types against a lower
version: a permanent "reverted" flag, scan exit 1, zero signal. Ignored
by package name; --types filtering and a version-scoped pin rejected
(rationale in development/tooling.md).
2026-09-16 07:55:25 +00:00
tmu 63e8edce79 ⬆️ Upgrade dependencies
@types/node to ^26.6.1 and cspell to ^10.3.2 — the only packages
check-outdated found behind the registry, both bumps within the existing
semver ranges. cspell 10.3.2 drops its transitive
fast-json-stable-stringify. npm run verify is green with no rule or
format fallout. maintain:outdated still flags @types/node as "reverted"
because DefinitelyTyped's latest dist-tag stays on the 22.x LTS series;
known false positive, advisory scan only.
2026-09-16 07:31:49 +00:00
tmu b456a430a7 🚀 Release 0.1.7
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 22s
CI / maintain (push) Failing after 14s
CI / publish (push) Failing after 15s
2026-09-16 07:23:24 +00:00
tmu 36d8c4feae 🔀 Merge chore/resolve-finish-push-tension into main 2026-09-16 07:21:55 +00:00
tmu d646fd1ec4 ♻️ Let create:branch start from an ahead main
`create:finish` leaves the merge local until `create:release` pushes it, so
`main` is routinely ahead of its upstream between a merge and a release. The
branch front door demanded an exact match and refused until it was pushed,
forcing a manual `git push` that the model deliberately keeps out of it.

Reject only a `main` that is behind its upstream — matching `create:finish`,
which already tolerates being ahead — and record why pushing from `finish` was
rejected instead. The push stays with `create:release`, so the merge remains
reviewable locally, and the known issue about the deadlock is gone.

Resolves: backlog task "Resolve the finish/push tension".
2026-09-15 22:14:51 +00:00
tmu 177d63fa95 🔀 Merge chore/prune-backlog-and-changelog-rule into main
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 20s
CI / publish (push) Skipped
CI / maintain (push) Failing after 14s
2026-09-15 22:09:21 +00:00
tmu f6f820a648 📝 Require a changelog note before finishing a branch
A merged branch must carry a final commit adding a short summary of the
work under [Unreleased] in CHANGELOG.md. create:release derives the bump
heuristic from that body, so notes have to exist before release day;
rationale in development/workflow.md.
2026-09-15 22:08:08 +00:00
tmu c5cc903221 📝 Prune the backlog of closed tasks
All completed and cancelled entries are implemented and reflected in the
docs, CI and changelog; only still-open tasks remain.
2026-09-15 21:58:44 +00:00
tmu cf73857931 🚀 Release 0.1.6
CI / release-gate (push) Successful in 3s
CI / build (push) Successful in 23s
CI / maintain (push) Failing after 14s
CI / publish (push) Failing after 15s
2026-09-15 21:53:19 +00:00
tmu 9f038a230d 🔀 Merge chore/docs-restructure into main
CI / release-gate (push) Successful in 2s
CI / build (push) Successful in 20s
CI / publish (push) Skipped
CI / maintain (push) Failing after 16s
2026-09-15 21:51:33 +00:00
tmu 1465926783 📝 Check off the docs restructure and note it in the changelog 2026-09-15 21:51:21 +00:00
tmu 5e7d40b013 📝 Improve docs after split 2026-09-15 21:46:41 +00:00