@tangleai/outcomes 0.24.1

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +142 -0
  4. package/docs/ADAPTERS.md +215 -0
  5. package/package.json +80 -0
  6. package/schemas/direction-delta.schema.json +55 -0
  7. package/schemas/exact-match.schema.json +88 -0
  8. package/schemas/outcomes.contract.json +4084 -0
  9. package/schemas/outcomes.schema.json +3936 -0
  10. package/src/adapters/direction-delta.d.ts +2 -0
  11. package/src/adapters/direction-delta.gen.d.ts +13 -0
  12. package/src/adapters/direction-delta.gen.js +3 -0
  13. package/src/adapters/direction-delta.js +29 -0
  14. package/src/adapters/exact-match.d.ts +2 -0
  15. package/src/adapters/exact-match.gen.d.ts +39 -0
  16. package/src/adapters/exact-match.gen.js +3 -0
  17. package/src/adapters/exact-match.js +40 -0
  18. package/src/adapters.d.ts +50 -0
  19. package/src/adapters.js +1 -0
  20. package/src/contract.d.ts +3285 -0
  21. package/src/contract.js +6 -0
  22. package/src/domain.d.ts +19 -0
  23. package/src/domain.js +45 -0
  24. package/src/errors.d.ts +23 -0
  25. package/src/errors.js +11 -0
  26. package/src/evaluation.d.ts +49 -0
  27. package/src/evaluation.js +174 -0
  28. package/src/handlers.d.ts +15 -0
  29. package/src/handlers.js +18 -0
  30. package/src/history.d.ts +4 -0
  31. package/src/history.js +56 -0
  32. package/src/identity.d.ts +9 -0
  33. package/src/identity.js +17 -0
  34. package/src/index.d.ts +15 -0
  35. package/src/index.js +9 -0
  36. package/src/operations.d.ts +16 -0
  37. package/src/operations.js +108 -0
  38. package/src/outcomes.contracts.gen.d.ts +1767 -0
  39. package/src/outcomes.contracts.gen.js +3 -0
  40. package/src/persistence.d.ts +10 -0
  41. package/src/persistence.js +88 -0
  42. package/src/projection.d.ts +13 -0
  43. package/src/projection.js +59 -0
  44. package/src/promotion.d.ts +17 -0
  45. package/src/promotion.js +96 -0
  46. package/src/proposal-operation.d.ts +17 -0
  47. package/src/proposal-operation.js +110 -0
  48. package/src/proposer.d.ts +107 -0
  49. package/src/proposer.js +89 -0
  50. package/src/refinement.d.ts +40 -0
  51. package/src/refinement.js +167 -0
  52. package/src/resolution.d.ts +12 -0
  53. package/src/resolution.js +62 -0
  54. package/src/schema.d.ts +8 -0
  55. package/src/schema.js +34 -0
  56. package/src/scoring.d.ts +15 -0
  57. package/src/scoring.js +37 -0
  58. package/src/service-context.d.ts +50 -0
  59. package/src/service-context.js +81 -0
  60. package/src/service.d.ts +22 -0
  61. package/src/service.js +159 -0
  62. package/src/store.d.ts +42 -0
  63. package/src/store.js +70 -0
  64. package/src/transitions.d.ts +7 -0
  65. package/src/transitions.js +56 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # @tangleai/outcomes
2
+
3
+ ## 0.24.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @tangleai/agents@0.24.1
8
+ - @tangleai/config@0.24.1
9
+ - @tangleai/core@0.24.1
10
+ - @tangleai/memory@0.24.1
11
+ - @tangleai/models@0.24.1
12
+
13
+ ## 0.24.0
14
+
15
+ ### Minor Changes
16
+
17
+ - Add the outcomes package for independently evidenced decisions, deterministic scoring, atomic confidence projection, bounded artifact refinement and explicitly approved promotion and rollback. The public operation contract, two-domain adapter kit and keyless example share the same scoped request receipts, one-use held-out gates, full head revision checks and interruption recovery.
18
+
19
+ The store adapter owns outcome records and memory changes in one SQLite transaction. The new pure confidence helper preserves fact fields; existing applyOutcome calls retain their original duplicate-citation and timestamp behavior and do not acquire a durable replay guarantee. No existing persisted memory format changes. Hosts opt into the new lifecycle, provide evidence and approval authority, and use a new artifact key for schema or policy changes. Scripted paired measurements and Node/Bun packed consumers qualify the mechanism; downstream domain integrations and automatic promotion remain separate work.
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies
24
+ - @tangleai/memory@0.24.0
25
+ - @tangleai/agents@0.24.0
26
+ - @tangleai/config@0.24.0
27
+ - @tangleai/core@0.24.0
28
+ - @tangleai/models@0.24.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joham (jklarenbeek@gmail.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @tangleai/outcomes
2
+
3
+ Immutable evidenced decisions, deterministic scores, atomic memory projection,
4
+ and explicitly approved domain artifacts. The host supplies scope, adapters,
5
+ evidence resolver and authority. The package discovers no credentials and runs
6
+ no scheduler.
7
+
8
+ ## Public lifecycle
9
+
10
+ `await createOutcomeService(options)` returns `create`, `resolve`, `score`,
11
+ `project`, `reflect`, `evaluate`, `approve`, `promote`, `rollback`, `reconcile`,
12
+ `inspect`, `history` and `injectChecked`. Methods accept unknown JSON and return
13
+ `{ok:true,value,replayed,writes}` or `{ok:false,issues:[{code,path,detail,retryable}]}`.
14
+ Mutation envelopes carry `scopeId`, `artifactKey`, `requestKey`, normalized UTC
15
+ `at`, and operation-specific `input`. Reads omit requestKey and at. Closed
16
+ schemas and generated TypeScript contracts are exported at `./schemas/outcomes`
17
+ and `./contracts`.
18
+
19
+ - `create` records a pending decision, its exact input/output, cutoff and decision
20
+ times, adapter/configuration revisions, cited memories and used artifact id or
21
+ explicit static baseline. It returns `decisionId`.
22
+ - `resolve` accepts evidence references. A trusted resolver supplies immutable
23
+ source bytes bound to decision id, scope, subject, issuer and observation time.
24
+ Their digests and timestamps are checked before a bounded snapshot is retained.
25
+ One resolution is accepted per decision; arrival lateness never rewrites the
26
+ observed time. It returns `resolutionId`.
27
+ - `score` executes the pinned pure adapter and commits a score plus an authorized
28
+ projection intent. It returns `scoreId` and `projectionIntentId`.
29
+ - `project` atomically applies confidence to sorted unique citations and writes a
30
+ terminal receipt. It returns `projectionReceiptId`, `applied`, `missing` and
31
+ `changedMemoryWrites`. Missing memories remain terminal skips; clamped unchanged
32
+ confidence is processed but not written. Fact timestamps and every other field
33
+ are preserved.
34
+ - `reflect` stages a root (`mode:create`) or a child of the captured checked head
35
+ (`mode:evolve`). Roots supply a full payload; children use add/remove/replace/
36
+ test JSON Patch over the payload alone. Jaren's guarded refiner and patch engine
37
+ prepare detached candidates. Schema-valid candidates rejected by later semantic
38
+ or churn gates remain inspectable; oversized malformed outputs retain bounded
39
+ diagnostics. No-op children create no payload version.
40
+ - `evaluate` obtains a host-registered held-out slot only after reserving it.
41
+ Candidate and paired baseline use identical cases and the registered scorer.
42
+ Eligibility requires complete coverage, strict positive mean utility, no domain
43
+ regression, valid bounds and registered call/cost limits. Case ids and content
44
+ cannot overlap training or previously consumed holdouts. Returns `evaluationId`,
45
+ `eligible`, `issues` and `caseReportId`.
46
+ - `approve` needs the construction-time host principal's approval capability.
47
+ It binds action, candidate, evaluation, policy and the exact expected head.
48
+ Request JSON cannot grant authority. `promote` consumes that approval and CASes
49
+ both head version and revision. `rollback` requires a new action-specific
50
+ approval for a previously checked and active version. Both return
51
+ `activationEventId` and `head`; every real transition increments revision.
52
+ - `injectChecked` verifies the exact scope/artifact head and returns its payload,
53
+ version, evaluation, activation and head references. It writes nothing. A
54
+ missing head is OUTC1004, and corrupt provenance is refused.
55
+
56
+ A scope is the closed `{namespace,domain,subject}` object; `scopeIdOf` computes its
57
+ canonical SHA-256 identity. Artifact keys are explicit host choices. Changing
58
+ an established lineage's schema or bounds requires a new artifact key. Retained
59
+ versions and audit records are immutable, including inactive and rolled-back
60
+ versions.
61
+
62
+ ## Durability and replay
63
+
64
+ `createMemoryOutcomeStore()` owns reference persistence and its `memories` view.
65
+ `@tangleai/store`'s `createOutcomeStore(db)` owns the same records and the existing
66
+ memories collection in one immediate Jaren transaction on Node or Bun SQLite.
67
+ `createOutcomeStoreAdapter` is a trusted atomic persistence extension, not a wire
68
+ write API. An unrelated ordinary MemoryStore cannot provide atomic receipts.
69
+
70
+ Within a scope, an accepted request key binds the operation and complete canonical
71
+ input, including supplied time. Exact completed replay returns its original
72
+ business result with zero writes/calls. Changed input conflicts. A new key for a
73
+ completed unique stage is OUTC1007, with an inspectable refusal receipt where
74
+ storage is available. Known rollback is explicitly retryable. Resolution remains
75
+ committed if scoring or projection fails. Lost acknowledgements reread stable
76
+ receipts; unavailable recovery reports OUTC1017 rather than guessing.
77
+
78
+ ## Reference adapters and limits
79
+
80
+ `./adapters/direction-delta` exports `createDirectionDeltaAdapter`: `{base}` plus
81
+ `{offset}` predicts a finite number. Same sign and absolute error strictly below
82
+ 0.05 is success; same sign otherwise is partial; different sign is failure. Zero
83
+ is nonnegative. Missing, non-finite and string numbers are refused.
84
+
85
+ `./adapters/exact-match` exports `createExactMatchAdapter`: a token selects the
86
+ longest case-sensitive prefix, or fallbackLabel. At most 16 unique nonblank
87
+ prefixes are sorted by descending Unicode code-point length then code-point
88
+ order. Exact case-sensitive label equality is success; otherwise failure. Common
89
+ utility is success=1, partial=0.5, failure=0.
90
+
91
+ Default policy bounds are 10 retained payload versions per scope/artifact,
92
+ 32,768 canonical UTF-8 payload bytes, 32 patch operations, 32 changed leaf paths
93
+ and 8,192 UTF-8 reflection bytes. Empty containers and removed leaves count in
94
+ churn. Capacity is reserved before a model dispatch; nothing silently evicts
95
+ ancestry or rollback targets. Audit history is append-only and unbounded. Other
96
+ input bounds are 16 evidence references/32,768 combined snapshot bytes, 128
97
+ training scores or held-out cases, and 262,144 bytes per held-out registration or
98
+ model proposal context. These are conservative defaults, not measured optima.
99
+
100
+ ## Optional model proposals
101
+
102
+ `./proposer` exports `createStructuredOutcomeProposer` and
103
+ `outcomeProposalComponents`. Register the exact prompt/response-schema revisions,
104
+ then inject profile-resolution input, a role, fetch, clock, deadline factory and
105
+ any credential/cache explicitly. The shipped config resolver, structured-output
106
+ client, wire replay key and budget account supply one HTTP attempt, zero repairs,
107
+ one concurrent call and a maximum 120-second deadline. A registered finite output
108
+ ceiling of at most 8,192 tokens is required. Only training data, parent payload,
109
+ domain schema and bounds reach the proposer; evaluation labels and authority do
110
+ not. The ordinary package entry does not import this provider adapter.
111
+
112
+ Dispatch and returned output are durably recorded before staging. Completed
113
+ replay never calls the provider. Uncertain dispatch retains capacity and requires
114
+ host-authorized `reconcile` with trusted retained-output or no-dispatch evidence.
115
+ Reconciliation cannot approve or activate an artifact. Missing monetary usage is
116
+ reported as unknown; a report hash is not a signature or authority credential.
117
+
118
+ The [measured fixture](../../docs/OUTCOME_BENCHMARK.md) separates static decisions,
119
+ checked scripted candidates, failed guards and unresolved outcomes. Its scripted
120
+ improvement does not establish autonomous or real-domain learning.
121
+
122
+ ## Operations and adapter kit
123
+
124
+ `createOutcomeContract` and `createOutcomeHandlers` expose all 13 operations
125
+ through Jaren local/HTTP bindings. Use `validateOutput:'always'`; durable replay
126
+ is owned by the outcome service. Principals omitted at construction cannot
127
+ approve or reconcile. Scope access is checked before reads and replay.
128
+ `inspect({id,includeLineage:true})` gives a bounded ancestry view; `history` pages
129
+ 50 records by default, at most 200, with a fixed upper sequence per cursor.
130
+
131
+ See [the adapter kit](docs/ADAPTERS.md) for schemas, trust wiring, gates, errors,
132
+ recovery and downstream ownership. Run `npm run outcomes:smoke` in the repository
133
+ or `node examples/outcomes.ts --db /tmp/outcomes.sqlite` for the persistent
134
+ two-domain walkthrough. `./schemas/contract` is the generated v1 wire document;
135
+ `./contract` exports the compiled factory and handlers.
136
+
137
+ Reservations are audited before host work. Lost reservation acknowledgement
138
+ recovers an explicit retry; a trusted no-dispatch proof can reconcile a stranded
139
+ reservation and fences its prior attempt. Histories retain these attempts even
140
+ before a terminal operation receipt exists. The reference store is browser
141
+ importable; SQLite remains in the separate store package and providers require
142
+ explicit host injection.
@@ -0,0 +1,215 @@
1
+ # Outcome adapter kit
2
+
3
+ `@tangleai/outcomes` records decisions, independently resolved outcomes, scores,
4
+ projections, proposals, evaluations and explicit approvals. Hosts invoke these
5
+ stages; the package installs no worker, scheduler or domain integration.
6
+
7
+ Start with `node examples/outcomes.ts` in the repository. It runs both reference
8
+ adapters without keys or network access. `node examples/outcomes.ts --db
9
+ /tmp/outcomes.sqlite` uses the store adapter; repeating the command returns the
10
+ same immutable ids with zero new writes or resolver calls. It stages a root and
11
+ child in each domain, checks both, promotes both, then separately approves a
12
+ rollback to the root. Times, request keys and fixtures are fixed for replay.
13
+
14
+ ## Register a domain and evidence authority
15
+
16
+ An `OutcomeAdapter` supplies four closed JSON schemas (input, decision output,
17
+ resolution and artifact), a schema/scorer revision identity, a static payload,
18
+ a pure `interpret(input, payload)`, a pure `score(output, resolution)`, and
19
+ semantic `validatePayload`. Optional normalization runs before artifact hashing.
20
+ Schema digests and the complete adapter identity are checked at construction.
21
+ Register immutable adapters; do not change their functions behind a revision.
22
+ No submitted scorer program or submitted success/eligibility flag runs as code.
23
+
24
+ The reference factories live at `@tangleai/outcomes/adapters/direction-delta`
25
+ and `@tangleai/outcomes/adapters/exact-match`; their schemas have corresponding
26
+ `./schemas/…` exports. Direction/delta requires finite `predicted` and `actual`
27
+ numbers: equal sign and absolute error strictly below 0.05 is success; equal
28
+ sign outside that tolerance is partial; different sign is failure. Zero has the
29
+ nonnegative sign. Missing values never become zero. An offset artifact interprets
30
+ `{base}` as `{predicted: base + offset}`, refusing non-finite results.
31
+ Exact match compares case-sensitive labels. Its artifact has a fallback label
32
+ and up to 16 unique prefix rules; the longest Unicode-code-point prefix wins.
33
+ Normalization gives a stable rule ordering. No fuzzy match or label coercion
34
+ changes a verdict. Utility is always success 1, partial 0.5, failure 0.
35
+
36
+ Inject a trusted `EvidenceResolver` with a revision and `resolve(reference,
37
+ scope)`. Wire commands carry only `{sourceId,digest}`. The resolver returns the
38
+ retained `Source`: source id, decision id, scope id, subject, issuer, observed
39
+ time, payload and digest. The digest is the canonical revision of all those
40
+ fields except `digest`. Verify origin in your resolver before returning it.
41
+ The service checks the requested digest, decision/scope/subject binding,
42
+ chronology and domain schema and retains the exact snapshot. Decision evidence
43
+ must name that decision; held-out and reconciliation evidence uses
44
+ `decisionId:null`. A hash proves byte agreement, not external truth or authority.
45
+ Arrival may be late; observed time must still follow decision time. One accepted
46
+ resolution per decision is immutable in v1; source corrections need a separate
47
+ future policy. At most 16 references and 32,768 combined snapshot bytes are read.
48
+
49
+ ## Bind the host before handling JSON
50
+
51
+ Construct `createOutcomeService({store, scope, adapters, resolver,
52
+ authorizeMemoryIds, ...})`. The closed scope is `{namespace,domain,subject}`.
53
+ Every operation compares its `scopeId` with that host binding, including reads
54
+ and replay. An id alone grants no access. `authorizeMemoryIds` returns an allowed
55
+ boolean and immutable authorization revision for the sorted unique citations.
56
+ Keep namespace-to-memory access enforcement in this host callback.
57
+
58
+ Omitting `principal` denies both approval and reconciliation:
59
+
60
+ ```ts
61
+ const service = await createOutcomeService({
62
+ store, scope, adapters: [adapter], resolver,
63
+ authorizeMemoryIds: async ids => ({
64
+ allowed: ids.every(id => authorizedIds.has(id)),
65
+ authorizationId,
66
+ }),
67
+ });
68
+ const handlers = createOutcomeHandlers({
69
+ resolveHost: () => ({ service, allowScope: id => id === service.scopeId }),
70
+ });
71
+ ```
72
+
73
+ For a trusted review service, supply an immutable principal with `id`,
74
+ `authorityId` (a revision), `approve:true` and the explicitly granted
75
+ `reconcile` capability. Never derive those booleans from request JSON or model
76
+ text. HTTP hosts use their existing authentication to resolve `ctx.host` to a
77
+ service and `allowScope` policy. Local clients have no custom host context;
78
+ bind the host in the handler-factory closure. `OUTCOME_MODEL_OPERATIONS` excludes
79
+ approve and reconcile. A model's service must also omit those capabilities;
80
+ manually invoking their names then returns OUTC1012. Filtering a tool list alone
81
+ is not an authorization boundary.
82
+
83
+ `createOutcomeContract()` and `createOutcomeHandlers()` are exported from the
84
+ root and `./contract`. `./schemas/contract` exports the generated portable
85
+ contract. Each `outcomes.*` operation maps to one direct service method; wire
86
+ `outcomes.inject` maps to `injectChecked`. Use Jaren local/HTTP bindings with
87
+ `validateOutput:'always'`. Malformed input is JC2050 and broken handler/output
88
+ is JC2070; a valid domain refusal remains `{ok:false,issues:[…]}` with OUTC
89
+ codes. Transport idempotency is explicitly `none`. Durable request receipts,
90
+ not a local client's annotation, implement business replay.
91
+
92
+ ## Stage and resolve a decision
93
+
94
+ Every mutation takes `{scopeId,artifactKey,requestKey,at,input}`; reads omit the
95
+ key and time. Times are normalized UTC strings with milliseconds. A request key
96
+ is unique across operations within a scope and binds the entire canonical
97
+ command, including time. Keep the same command to retry it. Completed exact
98
+ replay returns its original value with `replayed:true,writes:0`; changed command
99
+ bytes under that key fail OUTC1007. A new key repeating an already unique stage
100
+ also fails OUTC1007 and may append its first refusal receipt.
101
+
102
+ Call `create` with the decision-time input/output, pinned adapter and static
103
+ payload, decision/cutoff/expected-resolution times, configuration, citations and
104
+ `usedVersionId` (null for static). It returns `decisionId`. Checked decisions
105
+ must reproduce their output from the current checked version. Deliver independent
106
+ evidence to `resolve({decisionId,evidence,receivedAt})`; its `resolutionId`
107
+ feeds `score({resolutionId})`. Score returns `scoreId` and
108
+ `projectionIntentId`. It never resolves pending decisions or accepts a verdict.
109
+
110
+ `project({scoreId})` returns `projectionReceiptId`, `applied`, `missing` and
111
+ `changedMemoryWrites`. The same atomic owner must store memories and receipts:
112
+ use `createMemoryOutcomeStore()` or `@tangleai/store`'s `createOutcomeStore(db)`.
113
+ An unrelated four-method memory store cannot acquire this guarantee. Projection
114
+ reads current confidence, applies shared arithmetic once per unique authorized
115
+ id, and commits the memory changes and receipt together. It preserves fact time,
116
+ text, evidence, embeddings and supersession fields. Missing memories are terminal
117
+ counted skips; later restoration does not reapply a completed score. Empty
118
+ citations complete with zero memory writes. The old memory `applyOutcome` remains
119
+ a plain helper with its original duplicate and timestamp behavior.
120
+
121
+ ## Create, evolve, check, approve and restore
122
+
123
+ `reflect` consumes prior independent `scoreIds`, a configuration and citations
124
+ to those scores. Create mode requires a full root payload, null parent and no
125
+ patch. Evolve requires the current checked parent, null payload and bounded JSON
126
+ Patch operations. Jaren guarded refinement and JSON Patch are the generic engines.
127
+ A no-op child returns a reflection with `versionId:null`. Valid but semantically
128
+ ineligible proposals remain inactive, inspectable versions with issues.
129
+
130
+ Defaults are 10 retained payload versions per scope/artifact, 32,768 canonical
131
+ UTF-8 payload bytes, 32 patch operations, 32 changed leaf paths (union of before
132
+ and after leaves, including array indices), and 8,192 reflection UTF-8 bytes.
133
+ Version capacity is reserved before a model call. All valid staged, rejected and
134
+ checked versions count; audit receipts have no total storage cap. Change policy
135
+ or schema under a new artifact key rather than silently resetting a lineage.
136
+ These are conservative registered bounds, not measured optimal values.
137
+
138
+ The default proposer is the caller's explicitly scripted payload. Optional
139
+ `createStructuredOutcomeProposer` at `./proposer` consumes a registered resolved
140
+ configuration, injected fetch/key/clock/deadline, existing structured output,
141
+ replay and budget seams. It requires one HTTP attempt, zero repair calls, one
142
+ concurrent call, bounded output and at most 120 seconds per host deadline.
143
+ Only prior training evidence and parent payload go to the model. The core reads
144
+ no credentials or environment. Monetary cost is null when unavailable, not zero.
145
+ Do not reuse another campaign's spend authorization.
146
+
147
+ After freezing the candidate, the host's `evaluationSlot(slotId,versionId,scope)`
148
+ returns an independently registered `EvaluationSlot`. It binds candidate,
149
+ expected `{versionId,revision}`, training scores, evaluator and gate-policy
150
+ revisions, held-out cases/sources and request/cost ceilings. The service checks
151
+ these sources through the resolver and retains the registration before scoring.
152
+ Training and held-out ids and content digests must be disjoint. A candidate and
153
+ slot are each evaluated once; renamed/reused held-out content cannot become a
154
+ fresh slot. Registrations and proposal training are bounded to 128 cases/scores
155
+ and 262,144 canonical bytes.
156
+
157
+ `evaluate({versionId,slotId})` returns evaluation/case-report ids, eligibility and
158
+ issues. Eligibility requires complete nonempty paired coverage, no failures,
159
+ strictly positive mean utility over the registered baseline, no domain loss,
160
+ matching pinned revisions, semantic/size/churn gates and cost/request bounds.
161
+ Failed candidates remain visible. These fixture gates do not establish practical
162
+ improvement for your domain.
163
+
164
+ A trusted principal invokes `approve` with action, version/evaluation ids,
165
+ expected head pair and reason. Approval does not activate. `promote({approvalId})`
166
+ rereads all dependencies and compares both version and monotonic revision in one
167
+ transaction. The empty head is `{versionId:null,revision:0}`. Each real promotion
168
+ or rollback increments revision; replay does not. `injectChecked` validates the
169
+ full checked provenance and returns payload, head and version/evaluation/event
170
+ ids. It performs no learning or writes; absent heads return OUTC1004 so hosts
171
+ can explicitly use their static baseline.
172
+
173
+ Rollback requires a fresh action-specific approval for a previously checked and
174
+ active version in that artifact. Call `rollback({approvalId})`; all versions,
175
+ failed candidates and activation history survive. A→B→A changes revision and
176
+ invalidates approvals carrying A's old head pair. There is no unguarded setter.
177
+
178
+ ## Inspect and recover
179
+
180
+ `inspect({id})` validates and returns the immutable typed record.
181
+ `includeLineage:true` returns `{record,lineage}` with at most maxVersions ancestors
182
+ for an artifact version; other kinds return an empty lineage. Missing records,
183
+ corrupt bytes/edges and cycles are refusals. Follow typed ids for other stages.
184
+ `history` defaults to 50 entries, caps page size at 200, and orders by per-scope
185
+ sequence then id. Its cursor binds scope/artifact/filter revision and fixed upper
186
+ sequence. Concurrent appends are outside subsequent pages of that snapshot.
187
+ Cursors are pagination state, not authorization credentials. SQLite applies
188
+ indexed scope/sequence predicates and SQL LIMIT; no whole collection is returned
189
+ for history. The reference in-memory implementation scans its finite maps.
190
+
191
+ Reservations append immutable audit events before external work. Lost reservation
192
+ acknowledgements are recovered without stranding the key. A trusted no-dispatch
193
+ proof can also reconcile an interrupted reservation and increments its attempt
194
+ generation to fence the old worker. Known rolled-back storage failures are explicitly retryable. Already committed
195
+ receipts recover lost acknowledgements. An external dispatch with unknown result
196
+ is OUTC1017 and cannot automatically redispatch. A host with reconciliation
197
+ capability supplies independent retained-output or no-dispatch proof binding
198
+ attempt id, attempt number, input digest and the recorded wire request digest.
199
+ Retained output resumes local staging; a proven no-dispatch result allows an
200
+ explicit retry. Reconciliation does not approve or activate a proposal. A
201
+ retryable or uncertain failure is not a completed result, and the service cannot
202
+ promise a durable diagnostic while its storage is unavailable.
203
+
204
+ ## Consumer ownership
205
+
206
+ | Consumer | Downstream responsibility |
207
+ |---|---|
208
+ | Milkyway | Forecast checkpoints, note schema, observation feeds and source-correction policy |
209
+ | Trading | Realized return, fees, position/accounting identity and independent settlement evidence |
210
+ | Repository evolution | Patch sandbox, repository state, execution permissions and independent checks |
211
+ | Research | Evidence provenance, claim/state schema and resolution authority |
212
+ | Desktop | Input collection, authentication, principal mapping, review controls and UI |
213
+
214
+ None of these domain integrations ships in this kit. Reuse the lifecycle while
215
+ keeping their schemas, trusted sources and deployment policies in their hosts.
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@tangleai/outcomes",
3
+ "version": "0.24.1",
4
+ "description": "Evidenced decisions, deterministic retrospective checks and explicitly approved artifact promotion",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./src/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.d.ts",
11
+ "import": "./src/index.js",
12
+ "default": "./src/index.js"
13
+ },
14
+ "./contracts": {
15
+ "types": "./src/outcomes.contracts.gen.d.ts",
16
+ "import": "./src/outcomes.contracts.gen.js",
17
+ "default": "./src/outcomes.contracts.gen.js"
18
+ },
19
+ "./schemas/outcomes": "./schemas/outcomes.schema.json",
20
+ "./package.json": "./package.json",
21
+ "./adapters/direction-delta": {
22
+ "types": "./src/adapters/direction-delta.d.ts",
23
+ "import": "./src/adapters/direction-delta.js",
24
+ "default": "./src/adapters/direction-delta.js"
25
+ },
26
+ "./schemas/direction-delta": "./schemas/direction-delta.schema.json",
27
+ "./adapters/exact-match": {
28
+ "types": "./src/adapters/exact-match.d.ts",
29
+ "import": "./src/adapters/exact-match.js",
30
+ "default": "./src/adapters/exact-match.js"
31
+ },
32
+ "./schemas/exact-match": "./schemas/exact-match.schema.json",
33
+ "./proposer": {
34
+ "types": "./src/proposer.d.ts",
35
+ "import": "./src/proposer.js",
36
+ "default": "./src/proposer.js"
37
+ },
38
+ "./contract": {
39
+ "types": "./src/contract.d.ts",
40
+ "import": "./src/contract.js",
41
+ "default": "./src/contract.js"
42
+ },
43
+ "./schemas/contract": "./schemas/outcomes.contract.json"
44
+ },
45
+ "engines": {
46
+ "node": ">=24"
47
+ },
48
+ "sideEffects": false,
49
+ "dependencies": {
50
+ "@jarenjs/core": "0.86.0",
51
+ "@jarenjs/json": "0.86.0",
52
+ "@jarenjs/validate": "0.86.0",
53
+ "@tangleai/core": "^0.24.1",
54
+ "@tangleai/memory": "^0.24.1",
55
+ "@tangleai/models": "^0.24.1",
56
+ "@tangleai/agents": "^0.24.1",
57
+ "@tangleai/config": "^0.24.1",
58
+ "@jarenjs/contract": "0.86.0"
59
+ },
60
+ "private": false,
61
+ "types": "./src/index.d.ts",
62
+ "files": [
63
+ "src/**/*.js",
64
+ "src/**/*.d.ts",
65
+ "schemas/**/*.json",
66
+ "README.md",
67
+ "LICENSE",
68
+ "CHANGELOG.md",
69
+ "docs/**/*.md"
70
+ ],
71
+ "publishConfig": {
72
+ "access": "public",
73
+ "registry": "https://registry.npmjs.org/"
74
+ },
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "git+https://github.com/jklarenbeek/tangleai.git",
78
+ "directory": "packages/outcomes"
79
+ }
80
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://tangleai.dev/outcomes/direction-delta",
4
+ "$ref": "#/$defs/artifact",
5
+ "$defs": {
6
+ "input": {
7
+ "type": "object",
8
+ "properties": {
9
+ "base": {
10
+ "type": "number"
11
+ }
12
+ },
13
+ "required": [
14
+ "base"
15
+ ],
16
+ "additionalProperties": false
17
+ },
18
+ "output": {
19
+ "type": "object",
20
+ "properties": {
21
+ "predicted": {
22
+ "type": "number"
23
+ }
24
+ },
25
+ "required": [
26
+ "predicted"
27
+ ],
28
+ "additionalProperties": false
29
+ },
30
+ "resolution": {
31
+ "type": "object",
32
+ "properties": {
33
+ "actual": {
34
+ "type": "number"
35
+ }
36
+ },
37
+ "required": [
38
+ "actual"
39
+ ],
40
+ "additionalProperties": false
41
+ },
42
+ "artifact": {
43
+ "type": "object",
44
+ "properties": {
45
+ "offset": {
46
+ "type": "number"
47
+ }
48
+ },
49
+ "required": [
50
+ "offset"
51
+ ],
52
+ "additionalProperties": false
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,88 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://tangleai.dev/outcomes/exact-match",
4
+ "$ref": "#/$defs/artifact",
5
+ "$defs": {
6
+ "input": {
7
+ "type": "object",
8
+ "properties": {
9
+ "token": {
10
+ "type": "string",
11
+ "minLength": 1,
12
+ "pattern": "\\S"
13
+ }
14
+ },
15
+ "required": [
16
+ "token"
17
+ ],
18
+ "additionalProperties": false
19
+ },
20
+ "output": {
21
+ "type": "object",
22
+ "properties": {
23
+ "label": {
24
+ "type": "string",
25
+ "minLength": 1,
26
+ "pattern": "\\S"
27
+ }
28
+ },
29
+ "required": [
30
+ "label"
31
+ ],
32
+ "additionalProperties": false
33
+ },
34
+ "resolution": {
35
+ "type": "object",
36
+ "properties": {
37
+ "label": {
38
+ "type": "string",
39
+ "minLength": 1,
40
+ "pattern": "\\S"
41
+ }
42
+ },
43
+ "required": [
44
+ "label"
45
+ ],
46
+ "additionalProperties": false
47
+ },
48
+ "artifact": {
49
+ "type": "object",
50
+ "properties": {
51
+ "fallbackLabel": {
52
+ "type": "string",
53
+ "minLength": 1,
54
+ "pattern": "\\S"
55
+ },
56
+ "rules": {
57
+ "type": "array",
58
+ "maxItems": 16,
59
+ "items": {
60
+ "type": "object",
61
+ "properties": {
62
+ "prefix": {
63
+ "type": "string",
64
+ "minLength": 1,
65
+ "pattern": "\\S"
66
+ },
67
+ "label": {
68
+ "type": "string",
69
+ "minLength": 1,
70
+ "pattern": "\\S"
71
+ }
72
+ },
73
+ "required": [
74
+ "prefix",
75
+ "label"
76
+ ],
77
+ "additionalProperties": false
78
+ }
79
+ }
80
+ },
81
+ "required": [
82
+ "fallbackLabel",
83
+ "rules"
84
+ ],
85
+ "additionalProperties": false
86
+ }
87
+ }
88
+ }