@systemfsoftware/effect-cell-types 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,109 @@
|
|
|
1
1
|
# @systemfsoftware/effect-cell-types
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- Ship cell contracts as type-level constructors under namespace exports.
|
|
8
|
+
|
|
9
|
+
`Workflow.make` replaces the hand-written `Workflow<C, D, E>` annotation: it infers the decision and
|
|
10
|
+
error channels from its argument and derives the `UninhabitedDecision` / `UninhabitedError` markers, so
|
|
11
|
+
a total decision becomes uncallable rather than merely unannotated. `Policy` ships as a bare
|
|
12
|
+
`A`/`E`-preserving combinator type, which declines a `make` because a constructor would be the identity
|
|
13
|
+
function on the type — it forces nothing the type does not already carry.
|
|
14
|
+
|
|
15
|
+
Breaking, and deliberately not softened per `REPO-R1`:
|
|
16
|
+
|
|
17
|
+
- The barrel now uses namespace exports (`export * as Workflow`, `export * as Policy`) following the
|
|
18
|
+
Effect convention, so consumers write `Workflow.Workflow<C, D, E>` and `Workflow.make`.
|
|
19
|
+
- `src/workflow.kernel.ts` and `src/workflow-contract.kernel.ts` are gone, replaced by `src/Workflow.ts`
|
|
20
|
+
under the one-concept-per-file PascalCase convention this package publishes into.
|
|
21
|
+
- The four exported contract aliases — `InhabitedWorkflowIsCallable`,
|
|
22
|
+
`DecisionUnionSurvivesDistribution`, `NeverDecisionIsRejected`, `NeverErrorIsRejected` — leave the
|
|
23
|
+
public surface. They were type-level test assertions exported only because the package had no test
|
|
24
|
+
file; they now live in `test-types/Workflow.tst.ts` where they belong.
|
|
25
|
+
- The package stops being type-only and emits a runtime entry, so `README.md`'s claim that it "emits no
|
|
26
|
+
runtime values" is corrected and consumers gain a real module.
|
|
27
|
+
|
|
28
|
+
A `Schema` cell constructor was prototyped and withdrawn: its brand recorded only that `make` had been
|
|
29
|
+
called — provenance, not a proposition — and every rejection it produced came from the parameter type
|
|
30
|
+
alone, so `const s: S.Schema<A, I> = …` rejects identically. `S.Schema` is already the composer.
|
|
31
|
+
|
|
32
|
+
- The Cell description becomes an ordered sequence of phase records (name, kind, convention, run) under a description root carrying the package module name and the I/O-cell classification, so consumers fold the value to recover the whole vocabulary instead of re-declaring it.
|
|
33
|
+
|
|
34
|
+
**Migration.** A description built with the public constructors needs no change — `Cell.read(...) -> Cell.decode(...) -> ... -> Cell.write(...)` and `Cell.apply` behave exactly as before. Two things break:
|
|
35
|
+
|
|
36
|
+
- `Layer<P>` was a record of optional name-keyed slots (`layer.read`, `layer.decode`, …) and is now `{ phases: ReadonlyArray<Phase<P>> }`. Code reading a slot by name reads `layer.phases.find((phase) => phase.name === 'read')` instead, or folds the array.
|
|
37
|
+
- A hand-built layer object, legal under the old optional-slot type, no longer type-checks. Build it with the constructors; they are what write the stage brands the interpreter reads.
|
|
38
|
+
|
|
39
|
+
`Cell.apply`'s runtime contract narrowed with the shape: it executes the phases in the order the value declares and requires a write phase closing each layer, where before it ran a fixed five-phase sequence and died on an unfilled slot. Constructor-built descriptions cannot tell the difference — the chain only type-checks in canonical order.
|
|
40
|
+
|
|
41
|
+
- The Workflow brand: `make` is the only door to a decide slot.
|
|
42
|
+
|
|
43
|
+
`Workflow<C, D, E>` and `Cell.DecidePhase<P>` carry a phantom `WorkflowBrand` conjunct applied
|
|
44
|
+
solely by `Workflow.make` through the existing assertion narrowing — no runtime property, `make`
|
|
45
|
+
stays the identity it always was. The consumer's signature is the forcing function: a bare
|
|
46
|
+
function handed where a decide run is demanded is now a compile error naming the brand, so a
|
|
47
|
+
decision cannot reach production without passing through the constructor every gate keys on.
|
|
48
|
+
|
|
49
|
+
Breaking by design (`REPO-R1`): the two inline adapter sites (cli's admission adapter,
|
|
50
|
+
claude-compat's submit-hook adapter) become `make`-wrapped, and the cell-gen either-pass
|
|
51
|
+
fixture reshapes to one exhaustive path with the failure injection decided before the boundary.
|
|
52
|
+
|
|
53
|
+
- `Workflow.make` refuses an uninhabited or untagged channel at the call. Previously `Workflow<C, D, never>` resolved to a marker interface with no call signature, so the mistake surfaced only where something called the workflow — and a workflow nothing calls yet compiled clean at exit 0. The markers now ride an intersection on the parameter function's return type, `decide: (command: C) => Either<D, E> & Inhabited<D, E>`, where `D` and `E` still infer from the `Either` conjunct while the marker conjunct is what an uninhabited channel fails to satisfy. The diagnostic lands on the `Workflow.make` call and names the marker whose property type spells the fix.
|
|
54
|
+
|
|
55
|
+
Three new exports: `Inhabited`, `UntaggedError` and `Tagged`.
|
|
56
|
+
|
|
57
|
+
**Migration.** A workflow whose channels are both inhabited and whose error carries a `_tag` needs no change — `Inhabited` resolves to `unknown` and the intersection collapses to the plain `Either`. Three shapes now fail at the constructor instead of at the caller:
|
|
58
|
+
|
|
59
|
+
- `Either<D, never>` — the workflow cannot fail, so it decides nothing. Give it an error variant, or move it to a `*.kernel.ts`.
|
|
60
|
+
- `Either<never, E>` — the workflow can never succeed. Give it a decision variant it can return.
|
|
61
|
+
- `Either<D, Error>` — a bare `Error` carries no `_tag` to dispatch on. Declare the error as an `S.TaggedError`.
|
|
62
|
+
|
|
63
|
+
### Minor Changes
|
|
64
|
+
|
|
65
|
+
- Publish the description's vocabulary as part of the package's own surface: `Cell.vocabulary` (the phase names, kinds, conventions and intra-layer order, folded from the canonical description at module load), `Cell.canonical`, `Cell.DESCRIPTION_MODULE`, `Cell.IO_CELLS` and the `Cell.IoCellClassification` type derived from it.
|
|
66
|
+
|
|
67
|
+
This is what lets a consumer recover every axis by walking a value instead of restating it beside one. The classification type is `typeof IO_CELLS` rather than a hand-written twin, so a reclassified cell cannot drift between the two.
|
|
68
|
+
|
|
69
|
+
Generators, lint rules and type-level observers built on this walk live in their own packages and depend on this one; nothing in this package depends on them.
|
|
70
|
+
|
|
71
|
+
- Add `Cell` — an I/O sandwich whose phase order is carried by types.
|
|
72
|
+
|
|
73
|
+
`Cell.Phases` names the five stages of one sandwich, and each chaining constructor returns a type carrying the required member the next constructor's parameter demands, so a wrong order omits that member and fails to compile. The diagnostic is the instruction: the member's name is a sentence, so composing `decode` before `read` reports `Property 'call read(command) before decode(raw)' is missing in type 'DecideDone<Bag>' but required in type 'ReadDone<Bag>'`.
|
|
74
|
+
|
|
75
|
+
The stages are siblings rather than a hierarchy. Under a hierarchy a later stage is assignable to an earlier stage's parameter and an inversion still compiles; as siblings, every inversion is a missing member. The constructors are dual, data-last overload first, so a description reads in the order it runs when written in `pipe`.
|
|
76
|
+
|
|
77
|
+
Both kinds of `Left` are carried by the phase types rather than chosen by the interpreter. A `decode` `Left` is fatal — nothing consumes it, so its only route is the derived error channel and no write runs. A `decide` `Left` is an outcome: `EncodePhase` receives the whole `Either`, so it cannot be unwrapped and both branches reach the write.
|
|
78
|
+
|
|
79
|
+
`Cell.apply` is the interpreter — the one place a description becomes effects. It folds the phases in declared order and derives the error channel from the phases it was handed.
|
|
80
|
+
|
|
81
|
+
- cut over to effect v4 (4.0.0-rc.108): public surface derives from effect types; peers flip effect ^3→^4
|
|
82
|
+
|
|
83
|
+
- Add the Wire alphabet: a declaration is built from members this workspace mints, so a foreign type
|
|
84
|
+
named in a wire declaration is a compile error at the authoring site rather than a lint finding
|
|
85
|
+
somewhere else. Marking sits on the schema, not the decoded value, and every combinator takes marked
|
|
86
|
+
inputs and returns marked outputs, so a workspace-local alias of a vendor type confers no mark and is
|
|
87
|
+
refused too. The alphabet covers primitives, literals, `nullOr`, `undefinedOr`, `nullishOr`, `array`,
|
|
88
|
+
`optional`, `record`, `union`, `tuple`, `suspend` and `refine`, which is wide enough that a real
|
|
89
|
+
payload does not have to escape it to be expressed. `transform` and `compose` are deliberately
|
|
90
|
+
absent, being the laundering hop the alphabet exists to refuse.
|
|
91
|
+
|
|
92
|
+
What this does not do: the mark is a phantom, and TypeScript has no nominal types, so any value
|
|
93
|
+
legitimately carrying it can donate it to another type by intersection — `Object.assign` over a
|
|
94
|
+
marked primitive is enough, and writing the intersection out is enough. Five such routes are pinned
|
|
95
|
+
by type tests as accepted. The alphabet therefore refuses the accidental case and makes no claim to
|
|
96
|
+
be an enumerable set of doors; deciding admissibility belongs to a checker that resolves where a
|
|
97
|
+
member's type was declared.
|
|
98
|
+
|
|
99
|
+
### Patch Changes
|
|
100
|
+
|
|
101
|
+
- Array types are spelled one way. `Array<T>` and `ReadonlyArray<T>` in emitted
|
|
102
|
+
declarations become `T[]` and `readonly T[]`, which the type checker cannot tell
|
|
103
|
+
apart: no exported type changes, only how it is written.
|
|
104
|
+
|
|
105
|
+
- New version is published through npm trusted publishing, so it carries a provenance attestation you can verify.
|
|
106
|
+
|
|
3
107
|
## 2.0.0
|
|
4
108
|
|
|
5
109
|
### Major Changes
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/effect-cell-types",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "3.0.0",
|
|
5
5
|
"author": "Ryan Lee <drdgvhbh@gmail.com>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
|
|
9
|
-
"directory": "packages/effect
|
|
9
|
+
"directory": "packages/core/effect/cell/types"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://github.com/systemfsoftware/systemfsoftware/tree/main/packages/effect
|
|
11
|
+
"homepage": "https://github.com/systemfsoftware/systemfsoftware/tree/main/packages/core/effect/cell/types#readme",
|
|
12
12
|
"bugs": "https://github.com/systemfsoftware/systemfsoftware/issues",
|
|
13
13
|
"description": "Type-level contracts for the repo's cell taxonomy, starting with the Workflow decision channel — branded Workflow<C, D, E> types plus a runtime make constructor every effect kernel can share.",
|
|
14
14
|
"keywords": [
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"tsdown": "^0.22.14",
|
|
43
43
|
"tstyche": "^7.1.0",
|
|
44
44
|
"vitest": "^4.1.10",
|
|
45
|
-
"@systemfsoftware/effect-gherkin-spec": "
|
|
46
|
-
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
45
|
+
"@systemfsoftware/effect-gherkin-spec": "2.0.0",
|
|
47
46
|
"@systemfsoftware/vitest-config": "^0.1.0",
|
|
48
|
-
"@systemfsoftware/tsconfig": "^1.3.
|
|
47
|
+
"@systemfsoftware/tsconfig": "^1.3.3",
|
|
48
|
+
"@systemfsoftware/oxlint-config": "^0.1.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"effect": "4.0.0-rc.108"
|