@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.
- package/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/docs/ADAPTERS.md +215 -0
- package/package.json +80 -0
- package/schemas/direction-delta.schema.json +55 -0
- package/schemas/exact-match.schema.json +88 -0
- package/schemas/outcomes.contract.json +4084 -0
- package/schemas/outcomes.schema.json +3936 -0
- package/src/adapters/direction-delta.d.ts +2 -0
- package/src/adapters/direction-delta.gen.d.ts +13 -0
- package/src/adapters/direction-delta.gen.js +3 -0
- package/src/adapters/direction-delta.js +29 -0
- package/src/adapters/exact-match.d.ts +2 -0
- package/src/adapters/exact-match.gen.d.ts +39 -0
- package/src/adapters/exact-match.gen.js +3 -0
- package/src/adapters/exact-match.js +40 -0
- package/src/adapters.d.ts +50 -0
- package/src/adapters.js +1 -0
- package/src/contract.d.ts +3285 -0
- package/src/contract.js +6 -0
- package/src/domain.d.ts +19 -0
- package/src/domain.js +45 -0
- package/src/errors.d.ts +23 -0
- package/src/errors.js +11 -0
- package/src/evaluation.d.ts +49 -0
- package/src/evaluation.js +174 -0
- package/src/handlers.d.ts +15 -0
- package/src/handlers.js +18 -0
- package/src/history.d.ts +4 -0
- package/src/history.js +56 -0
- package/src/identity.d.ts +9 -0
- package/src/identity.js +17 -0
- package/src/index.d.ts +15 -0
- package/src/index.js +9 -0
- package/src/operations.d.ts +16 -0
- package/src/operations.js +108 -0
- package/src/outcomes.contracts.gen.d.ts +1767 -0
- package/src/outcomes.contracts.gen.js +3 -0
- package/src/persistence.d.ts +10 -0
- package/src/persistence.js +88 -0
- package/src/projection.d.ts +13 -0
- package/src/projection.js +59 -0
- package/src/promotion.d.ts +17 -0
- package/src/promotion.js +96 -0
- package/src/proposal-operation.d.ts +17 -0
- package/src/proposal-operation.js +110 -0
- package/src/proposer.d.ts +107 -0
- package/src/proposer.js +89 -0
- package/src/refinement.d.ts +40 -0
- package/src/refinement.js +167 -0
- package/src/resolution.d.ts +12 -0
- package/src/resolution.js +62 -0
- package/src/schema.d.ts +8 -0
- package/src/schema.js +34 -0
- package/src/scoring.d.ts +15 -0
- package/src/scoring.js +37 -0
- package/src/service-context.d.ts +50 -0
- package/src/service-context.js +81 -0
- package/src/service.d.ts +22 -0
- package/src/service.js +159 -0
- package/src/store.d.ts +42 -0
- package/src/store.js +70 -0
- package/src/transitions.d.ts +7 -0
- 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.
|
package/docs/ADAPTERS.md
ADDED
|
@@ -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
|
+
}
|