@cotal-ai/core 0.12.0 → 0.13.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.
Files changed (152) hide show
  1. package/dist/acls.d.ts +31 -7
  2. package/dist/acls.d.ts.map +1 -1
  3. package/dist/acls.js +105 -17
  4. package/dist/acls.js.map +1 -1
  5. package/dist/agent-file.js +1 -1
  6. package/dist/agent-file.js.map +1 -1
  7. package/dist/auth-provider.d.ts +8 -0
  8. package/dist/auth-provider.d.ts.map +1 -1
  9. package/dist/auth-provider.js.map +1 -1
  10. package/dist/backup.d.ts.map +1 -1
  11. package/dist/backup.js +6 -4
  12. package/dist/backup.js.map +1 -1
  13. package/dist/broker-floor.d.ts +34 -0
  14. package/dist/broker-floor.d.ts.map +1 -0
  15. package/dist/broker-floor.js +39 -0
  16. package/dist/broker-floor.js.map +1 -0
  17. package/dist/canonical.d.ts +24 -0
  18. package/dist/canonical.d.ts.map +1 -0
  19. package/dist/canonical.js +159 -0
  20. package/dist/canonical.js.map +1 -0
  21. package/dist/connector.d.ts +4 -0
  22. package/dist/connector.d.ts.map +1 -1
  23. package/dist/endpoint-action.d.ts +424 -0
  24. package/dist/endpoint-action.d.ts.map +1 -0
  25. package/dist/endpoint-action.js +910 -0
  26. package/dist/endpoint-action.js.map +1 -0
  27. package/dist/endpoint-binding.d.ts +344 -0
  28. package/dist/endpoint-binding.d.ts.map +1 -0
  29. package/dist/endpoint-binding.js +753 -0
  30. package/dist/endpoint-binding.js.map +1 -0
  31. package/dist/endpoint-checkpoint.d.ts +292 -0
  32. package/dist/endpoint-checkpoint.d.ts.map +1 -0
  33. package/dist/endpoint-checkpoint.js +818 -0
  34. package/dist/endpoint-checkpoint.js.map +1 -0
  35. package/dist/endpoint-cluster.d.ts +95 -0
  36. package/dist/endpoint-cluster.d.ts.map +1 -0
  37. package/dist/endpoint-cluster.js +194 -0
  38. package/dist/endpoint-cluster.js.map +1 -0
  39. package/dist/endpoint-contract-store.d.ts +90 -0
  40. package/dist/endpoint-contract-store.d.ts.map +1 -0
  41. package/dist/endpoint-contract-store.js +348 -0
  42. package/dist/endpoint-contract-store.js.map +1 -0
  43. package/dist/endpoint-envelope.d.ts +165 -0
  44. package/dist/endpoint-envelope.d.ts.map +1 -0
  45. package/dist/endpoint-envelope.js +346 -0
  46. package/dist/endpoint-envelope.js.map +1 -0
  47. package/dist/endpoint-grants.d.ts +123 -0
  48. package/dist/endpoint-grants.d.ts.map +1 -0
  49. package/dist/endpoint-grants.js +215 -0
  50. package/dist/endpoint-grants.js.map +1 -0
  51. package/dist/endpoint-guard.d.ts +222 -0
  52. package/dist/endpoint-guard.d.ts.map +1 -0
  53. package/dist/endpoint-guard.js +468 -0
  54. package/dist/endpoint-guard.js.map +1 -0
  55. package/dist/endpoint-handle.d.ts +176 -0
  56. package/dist/endpoint-handle.d.ts.map +1 -0
  57. package/dist/endpoint-handle.js +608 -0
  58. package/dist/endpoint-handle.js.map +1 -0
  59. package/dist/endpoint-journal.d.ts +225 -0
  60. package/dist/endpoint-journal.d.ts.map +1 -0
  61. package/dist/endpoint-journal.js +431 -0
  62. package/dist/endpoint-journal.js.map +1 -0
  63. package/dist/endpoint-receipt.d.ts +225 -0
  64. package/dist/endpoint-receipt.d.ts.map +1 -0
  65. package/dist/endpoint-receipt.js +417 -0
  66. package/dist/endpoint-receipt.js.map +1 -0
  67. package/dist/endpoint-records.d.ts +243 -0
  68. package/dist/endpoint-records.d.ts.map +1 -0
  69. package/dist/endpoint-records.js +591 -0
  70. package/dist/endpoint-records.js.map +1 -0
  71. package/dist/endpoint-serve.d.ts +176 -0
  72. package/dist/endpoint-serve.d.ts.map +1 -0
  73. package/dist/endpoint-serve.js +446 -0
  74. package/dist/endpoint-serve.js.map +1 -0
  75. package/dist/endpoint-service.d.ts +518 -0
  76. package/dist/endpoint-service.d.ts.map +1 -0
  77. package/dist/endpoint-service.js +973 -0
  78. package/dist/endpoint-service.js.map +1 -0
  79. package/dist/endpoint-session.d.ts +398 -0
  80. package/dist/endpoint-session.d.ts.map +1 -0
  81. package/dist/endpoint-session.js +834 -0
  82. package/dist/endpoint-session.js.map +1 -0
  83. package/dist/endpoint-signing.d.ts +105 -0
  84. package/dist/endpoint-signing.d.ts.map +1 -0
  85. package/dist/endpoint-signing.js +190 -0
  86. package/dist/endpoint-signing.js.map +1 -0
  87. package/dist/endpoint-subjects.d.ts +222 -0
  88. package/dist/endpoint-subjects.d.ts.map +1 -0
  89. package/dist/endpoint-subjects.js +381 -0
  90. package/dist/endpoint-subjects.js.map +1 -0
  91. package/dist/endpoint-supervisor.d.ts +19 -0
  92. package/dist/endpoint-supervisor.d.ts.map +1 -0
  93. package/dist/endpoint-supervisor.js +12 -0
  94. package/dist/endpoint-supervisor.js.map +1 -0
  95. package/dist/endpoint-traits.d.ts +225 -0
  96. package/dist/endpoint-traits.d.ts.map +1 -0
  97. package/dist/endpoint-traits.js +469 -0
  98. package/dist/endpoint-traits.js.map +1 -0
  99. package/dist/endpoint-verbs.d.ts +277 -0
  100. package/dist/endpoint-verbs.d.ts.map +1 -0
  101. package/dist/endpoint-verbs.js +576 -0
  102. package/dist/endpoint-verbs.js.map +1 -0
  103. package/dist/endpoint-virtual.d.ts +308 -0
  104. package/dist/endpoint-virtual.d.ts.map +1 -0
  105. package/dist/endpoint-virtual.js +440 -0
  106. package/dist/endpoint-virtual.js.map +1 -0
  107. package/dist/endpoint-work.d.ts +304 -0
  108. package/dist/endpoint-work.d.ts.map +1 -0
  109. package/dist/endpoint-work.js +728 -0
  110. package/dist/endpoint-work.js.map +1 -0
  111. package/dist/endpoint.d.ts +66 -22
  112. package/dist/endpoint.d.ts.map +1 -1
  113. package/dist/endpoint.js +289 -89
  114. package/dist/endpoint.js.map +1 -1
  115. package/dist/evict.d.ts +95 -32
  116. package/dist/evict.d.ts.map +1 -1
  117. package/dist/evict.js +193 -3
  118. package/dist/evict.js.map +1 -1
  119. package/dist/index.d.ts +25 -0
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +25 -0
  122. package/dist/index.js.map +1 -1
  123. package/dist/lease.d.ts +4 -0
  124. package/dist/lease.d.ts.map +1 -1
  125. package/dist/lease.js.map +1 -1
  126. package/dist/members.d.ts +4 -4
  127. package/dist/members.d.ts.map +1 -1
  128. package/dist/members.js +12 -12
  129. package/dist/members.js.map +1 -1
  130. package/dist/provision.d.ts +70 -18
  131. package/dist/provision.d.ts.map +1 -1
  132. package/dist/provision.js +194 -33
  133. package/dist/provision.js.map +1 -1
  134. package/dist/safe-pattern.d.ts +33 -0
  135. package/dist/safe-pattern.d.ts.map +1 -0
  136. package/dist/safe-pattern.js +486 -0
  137. package/dist/safe-pattern.js.map +1 -0
  138. package/dist/schema-profile.d.ts +93 -0
  139. package/dist/schema-profile.d.ts.map +1 -0
  140. package/dist/schema-profile.js +284 -0
  141. package/dist/schema-profile.js.map +1 -0
  142. package/dist/streams.d.ts +13 -8
  143. package/dist/streams.d.ts.map +1 -1
  144. package/dist/streams.js +35 -18
  145. package/dist/streams.js.map +1 -1
  146. package/dist/subjects.d.ts +100 -40
  147. package/dist/subjects.d.ts.map +1 -1
  148. package/dist/subjects.js +136 -60
  149. package/dist/subjects.js.map +1 -1
  150. package/dist/types.d.ts +9 -0
  151. package/dist/types.d.ts.map +1 -1
  152. package/package.json +3 -1
@@ -0,0 +1,24 @@
1
+ /** Digest identity form used everywhere a contract artifact is referenced: `sha256:<hex>`. */
2
+ export declare const DIGEST_PREFIX: "sha256:";
3
+ /** True iff `s` is a well-formed `sha256:<hex>` artifact digest. */
4
+ export declare function isContractDigest(s: string): boolean;
5
+ /** True iff the string is well-formed UTF-16 (no unpaired surrogate). A lone surrogate has NO
6
+ * UTF-8 byte encoding — encoders silently substitute U+FFFD, so two distinct malformed strings
7
+ * can collapse to one byte sequence; anything digest- or wire-bound must refuse them. */
8
+ export declare function isWellFormedUnicode(s: string): boolean;
9
+ /** RFC 8785 canonical JSON text of a value (strict: I-JSON enforced, no undefined→null). */
10
+ export declare function canonicalJson(value: unknown): string;
11
+ /** Content address of a contract artifact: `sha256:<hex>` over its RFC 8785 form (SPEC §13.7). */
12
+ export declare function contractDigest(value: unknown): string;
13
+ /** `sha256:<hex>` over RAW bytes (a string digests as its UTF-8 encoding), NEVER re-canonicalized:
14
+ * the digest form for artifacts carried as opaque bytes — the §13.3 `auth` slot (`authDigest`,
15
+ * digested exactly as carried) and the §13.4 raw stored submission bytes (`submissionDigest`).
16
+ * A string input MUST be well-formed UTF-16: a lone surrogate has no UTF-8 encoding, the
17
+ * encoder would substitute U+FFFD, and two DISTINCT carried values would silently share one
18
+ * digest — the opposite of "exactly as carried". Throws instead. */
19
+ export declare function rawDigest(data: Uint8Array | string): string;
20
+ /** Verify fetched artifact BYTES against their advertised digest (verify-on-read, SPEC §13.7):
21
+ * content addressing, not store ACLs, is the tamper boundary. The bytes must parse as JSON and
22
+ * re-canonicalize to the digest; anything else throws. Returns the parsed artifact. */
23
+ export declare function verifyArtifact(bytes: Uint8Array, digest: string): unknown;
24
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAYA,8FAA8F;AAC9F,eAAO,MAAM,aAAa,EAAG,SAAkB,CAAC;AAGhD,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;0FAE0F;AAC1F,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEtD;AAsFD,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGpD;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AAED;;;;;qEAKqE;AACrE,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAS3D;AAED;;wFAEwF;AACxF,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAWzE"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * RFC 8785 canonical JSON and content addressing (SPEC §13.7, D28).
3
+ *
4
+ * Contract identity is the SHA-256 digest of the RFC 8785 canonicalization of a JSON value,
5
+ * over I-JSON: lone surrogates are rejected loudly (never escaped through), because a digest
6
+ * over non-interchangeable text is not an identity. The strict `canonicalizeEx` path is pinned
7
+ * (`undefinedInArrayToNull: false`): an `undefined` anywhere in the value is a programming
8
+ * error, not data, and MUST NOT silently become `null`.
9
+ */
10
+ import { createHash } from "node:crypto";
11
+ import { canonicalizeEx } from "json-canonicalize";
12
+ /** Digest identity form used everywhere a contract artifact is referenced: `sha256:<hex>`. */
13
+ export const DIGEST_PREFIX = "sha256:";
14
+ const DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
15
+ /** True iff `s` is a well-formed `sha256:<hex>` artifact digest. */
16
+ export function isContractDigest(s) {
17
+ return DIGEST_RE.test(s);
18
+ }
19
+ /** True iff the string is well-formed UTF-16 (no unpaired surrogate). A lone surrogate has NO
20
+ * UTF-8 byte encoding — encoders silently substitute U+FFFD, so two distinct malformed strings
21
+ * can collapse to one byte sequence; anything digest- or wire-bound must refuse them. */
22
+ export function isWellFormedUnicode(s) {
23
+ return !hasLoneSurrogate(s);
24
+ }
25
+ /** True iff the string contains an unpaired UTF-16 surrogate (not well-formed / I-JSON
26
+ * violation). Manual scan: the repo's TS lib target predates `String#isWellFormed`. */
27
+ function hasLoneSurrogate(s) {
28
+ for (let i = 0; i < s.length; i++) {
29
+ const c = s.charCodeAt(i);
30
+ if (c >= 0xd800 && c <= 0xdbff) {
31
+ const n = s.charCodeAt(i + 1);
32
+ if (!(n >= 0xdc00 && n <= 0xdfff))
33
+ return true;
34
+ i++; // well-formed pair; skip the low half
35
+ }
36
+ else if (c >= 0xdc00 && c <= 0xdfff) {
37
+ return true; // low surrogate with no preceding high half
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ /** Walk a JSON value and throw on anything that cannot canonicalize EXACTLY (D28: verification
43
+ * and digesting must never run over a normalizing projection):
44
+ * - strings that are not well-formed UTF-16 (a lone surrogate violates I-JSON; canonicalizing
45
+ * it would mint a digest for text that cannot interchange), in values AND keys;
46
+ * - `undefined` anywhere and non-finite numbers (RFC 8785 cannot represent them);
47
+ * - NON-PLAIN-DATA graphs. `Object.entries` sees only enumerable string-keyed own data props,
48
+ * and the canonicalizer applies `toJSON`, so a symbol-keyed or non-enumerable own property,
49
+ * an accessor, or a class/exotic instance (Date → ISO string, Map → `{}`) would be SILENTLY
50
+ * projected away or rewritten — the exact field-dropping class D28 forbids (an artifact
51
+ * carrying state its signature never covered must refuse, not launder through the
52
+ * projection). Objects must be ordinary with a `null`/`Object.prototype` prototype and only
53
+ * enumerable string-keyed own DATA properties; arrays must be ordinary `Array.prototype`
54
+ * arrays with no holes and no extra own properties. */
55
+ function assertInterchangeable(v, path) {
56
+ if (v === null)
57
+ return;
58
+ switch (typeof v) {
59
+ case "string":
60
+ if (hasLoneSurrogate(v))
61
+ throw new Error(`canonicalJson: lone surrogate in string at ${path} (I-JSON violation)`);
62
+ return;
63
+ case "number":
64
+ if (!Number.isFinite(v))
65
+ throw new Error(`canonicalJson: non-finite number at ${path}`);
66
+ return;
67
+ case "boolean":
68
+ return;
69
+ case "undefined":
70
+ throw new Error(`canonicalJson: undefined at ${path} (strict mode never coerces to null)`);
71
+ case "object": {
72
+ if (Array.isArray(v)) {
73
+ if (Object.getPrototypeOf(v) !== Array.prototype)
74
+ throw new Error(`canonicalJson: non-ordinary array at ${path} (a subclassed/exotic array canonicalizes through projections)`);
75
+ for (const k of Reflect.ownKeys(v)) {
76
+ if (typeof k !== "string")
77
+ throw new Error(`canonicalJson: symbol-keyed own property on array at ${path} (invisible to canonicalization; refusing the projection)`);
78
+ if (k === "length")
79
+ continue;
80
+ if (!/^(0|[1-9][0-9]*)$/.test(k) || Number(k) >= v.length)
81
+ throw new Error(`canonicalJson: non-index own property "${k}" on array at ${path} (invisible to canonicalization; refusing the projection)`);
82
+ }
83
+ for (let i = 0; i < v.length; i++) {
84
+ const d = Object.getOwnPropertyDescriptor(v, i);
85
+ if (d === undefined)
86
+ throw new Error(`canonicalJson: hole at ${path}[${i}] (a hole would be coerced to null; refusing the projection)`);
87
+ if (!d.enumerable || d.get !== undefined || d.set !== undefined)
88
+ throw new Error(`canonicalJson: non-enumerable or accessor element at ${path}[${i}] (refusing the projection)`);
89
+ assertInterchangeable(v[i], `${path}[${i}]`);
90
+ }
91
+ return;
92
+ }
93
+ const proto = Object.getPrototypeOf(v);
94
+ if (proto !== Object.prototype && proto !== null)
95
+ throw new Error(`canonicalJson: non-plain object at ${path} (a class/exotic instance canonicalizes through projections like toJSON; only plain data objects are interchangeable)`);
96
+ for (const k of Reflect.ownKeys(v)) {
97
+ if (typeof k !== "string")
98
+ throw new Error(`canonicalJson: symbol-keyed own property at ${path} (invisible to canonicalization; refusing the projection)`);
99
+ if (hasLoneSurrogate(k))
100
+ throw new Error(`canonicalJson: lone surrogate in key at ${path}.${k}`);
101
+ const d = Object.getOwnPropertyDescriptor(v, k);
102
+ if (!d.enumerable)
103
+ throw new Error(`canonicalJson: non-enumerable own property "${k}" at ${path} (invisible to canonicalization; refusing the projection)`);
104
+ if (d.get !== undefined || d.set !== undefined)
105
+ throw new Error(`canonicalJson: accessor property "${k}" at ${path} (a getter is code, not data; refusing the projection)`);
106
+ assertInterchangeable(v[k], `${path}.${k}`);
107
+ }
108
+ return;
109
+ }
110
+ default:
111
+ throw new Error(`canonicalJson: unsupported ${typeof v} at ${path}`);
112
+ }
113
+ }
114
+ /** RFC 8785 canonical JSON text of a value (strict: I-JSON enforced, no undefined→null). */
115
+ export function canonicalJson(value) {
116
+ assertInterchangeable(value, "$");
117
+ return canonicalizeEx(value, { undefinedInArrayToNull: false });
118
+ }
119
+ /** Content address of a contract artifact: `sha256:<hex>` over its RFC 8785 form (SPEC §13.7). */
120
+ export function contractDigest(value) {
121
+ return DIGEST_PREFIX + createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
122
+ }
123
+ /** `sha256:<hex>` over RAW bytes (a string digests as its UTF-8 encoding), NEVER re-canonicalized:
124
+ * the digest form for artifacts carried as opaque bytes — the §13.3 `auth` slot (`authDigest`,
125
+ * digested exactly as carried) and the §13.4 raw stored submission bytes (`submissionDigest`).
126
+ * A string input MUST be well-formed UTF-16: a lone surrogate has no UTF-8 encoding, the
127
+ * encoder would substitute U+FFFD, and two DISTINCT carried values would silently share one
128
+ * digest — the opposite of "exactly as carried". Throws instead. */
129
+ export function rawDigest(data) {
130
+ const h = createHash("sha256");
131
+ if (typeof data === "string") {
132
+ if (hasLoneSurrogate(data))
133
+ throw new Error("rawDigest: lone surrogate in string input; no UTF-8 encoding exists, the digest would not be over the carried value");
134
+ h.update(data, "utf8");
135
+ }
136
+ else {
137
+ h.update(data);
138
+ }
139
+ return DIGEST_PREFIX + h.digest("hex");
140
+ }
141
+ /** Verify fetched artifact BYTES against their advertised digest (verify-on-read, SPEC §13.7):
142
+ * content addressing, not store ACLs, is the tamper boundary. The bytes must parse as JSON and
143
+ * re-canonicalize to the digest; anything else throws. Returns the parsed artifact. */
144
+ export function verifyArtifact(bytes, digest) {
145
+ if (!isContractDigest(digest))
146
+ throw new Error(`verifyArtifact: malformed digest ${JSON.stringify(digest)}`);
147
+ let parsed;
148
+ try {
149
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
150
+ }
151
+ catch (e) {
152
+ throw new Error(`verifyArtifact: artifact for ${digest} is not valid UTF-8 JSON: ${e.message}`);
153
+ }
154
+ const actual = contractDigest(parsed);
155
+ if (actual !== digest)
156
+ throw new Error(`verifyArtifact: digest mismatch; advertised ${digest}, content is ${actual}`);
157
+ return parsed;
158
+ }
159
+ //# sourceMappingURL=canonical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,10 @@ export interface LaunchOpts {
23
23
  sentinelCredsPath: string;
24
24
  bearerCmd: string[];
25
25
  };
26
+ /** The incarnation's lifecycle UID (SPEC §13.1), minted by the launcher at spawn. The connector
27
+ * forwards it (`COTAL_LIFECYCLE_UID`) so the session's endpoint binds its lifecycle-keyed
28
+ * dm/dlv/chathist durables — the same exact names its credential pins. */
29
+ lifecycleUid?: string;
26
30
  servers?: string;
27
31
  /** The agent's resolved access policy — the SAME read/post set the manager mints the agent's
28
32
  * creds from. The connector forwards it (`COTAL_SUBSCRIBE` / `COTAL_ALLOW_SUBSCRIBE` /
@@ -1 +1 @@
1
- {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,424 @@
1
+ /**
2
+ * The ACTION composite (SPEC §13.6): a long-running command as a pattern over the journal +
3
+ * records + events — zero new transport. `action` is a command MARKER, never a class: an
4
+ * action's submissions are `class: journal`, its accept/reject is the durable decision fact
5
+ * (§13.4), and there is no reply-rail answer to recover.
6
+ *
7
+ * THE RESULT FACT IS THE SINGLE TERMINAL ARBITER; THE STATUS ONLY EVER FOLLOWS IT, and every
8
+ * authority coordinate is bound to the PERSISTED accepted goal, never a caller claim. The
9
+ * pieces, each owned by the §13.9 principal named on its row:
10
+ * - the GOAL BIND (canonicalizer): a create-only CAS on
11
+ * `epf.<e>.goal.<caller triple>.<goalId>.bind` carrying the accepted fingerprint, BEFORE
12
+ * acceptance — the bind keys on `goalId` and stops a second distinct submission before
13
+ * acceptance and effect. A bind whose winner crashed BEFORE acceptance (no goal record) is
14
+ * ORPHANED, and a same-fingerprint resubmission ADOPTS it ({@link resolveGoalSubmission}).
15
+ * - the GOAL RECORD (commit path): `goal.<e>.<caller triple>.<goalId>` spec (the accepted
16
+ * definition — the trusted source every later seam validates against) + status (the CURRENT
17
+ * state projection). The status vocabulary is `accepted → running ⇄ waiting → terminal`,
18
+ * `cancelling` between a cancel and its terminal. A TERMINAL status exists ONLY as the
19
+ * projection of the committed result fact ({@link projectGoalTerminal}); {@link
20
+ * transitionGoal} refuses terminal targets, so the status never leads the journal. Every
21
+ * EXECUTOR-authored transition on a TARGET-PINNED goal proves the executor's fresh
22
+ * lifecycle/epoch currency (§13.6 item 7: a superseded epoch cannot commit transitions).
23
+ * - the TERMINAL RESULT (commit path): a create-only CAS on
24
+ * `epf.<e>.goal.<caller triple>.<goalId>.result` — the ONE commit point where completion,
25
+ * cancel, expiry-deny, and the readiness `uncertain` settle race, first terminal fact wins
26
+ * uniformly. The raw CAS is PRIVATE; the public commit takes a CLOSED CAUSE whose
27
+ * authoritative predicate is verified INSIDE the boundary (a `complete` proves executor
28
+ * currency, a `cancel` proves the goal is `cancelling`, a `readiness` proves the deadline
29
+ * passed) and DERIVES the terminal state from the cause — a raw state is never accepted.
30
+ * - the TOMBSTONE (§13.6 item 5): the summary lives INSIDE the one immutable result fact;
31
+ * retaining the fact the full idempotency horizon satisfies both retention minimums, and
32
+ * early payload eviction is a serving-layer policy answered with {@link goalTombstone}.
33
+ * - PROGRESS rides per-goal events, read-scoped to the caller at mint time.
34
+ *
35
+ * Every seam takes a BRANDED {@link ActionContext} bonding the record store + fact stream +
36
+ * space, so a composition mixup cannot read an accepted spec from space A and project through
37
+ * space B. Clocks are inputs everywhere (`now`, `acceptedAt`): the owner's clock decides.
38
+ */
39
+ import type { KV } from "@nats-io/kv";
40
+ import { type JetStreamClient, type JetStreamManager } from "@nats-io/jetstream";
41
+ import { type NatsConnection } from "@nats-io/transport-node";
42
+ import { EpEnvelopeError } from "./endpoint-envelope.js";
43
+ import { type EpCaller, type ParsedEpRequest } from "./endpoint-subjects.js";
44
+ import { type Receipt, type ReceiptStoreContext } from "./endpoint-receipt.js";
45
+ /** A trusted, space-bonded action context: the KV + JS + JSM all DERIVE from one binding-layer
46
+ * connection and one space by the constructor (never injected independently — a branded bundle
47
+ * of split resources would still split accepted state from terminal authority), so a
48
+ * composition mixup can never read an accepted spec through one broker and commit its terminal
49
+ * through another. BRANDED: a hand-assembled structural look-alike is rejected at every seam,
50
+ * not just discouraged. */
51
+ export interface ActionContext {
52
+ kv: KV;
53
+ js: JetStreamClient;
54
+ jsm: JetStreamManager;
55
+ space: string;
56
+ }
57
+ export declare function actionContext(nc: NatsConnection, space: string): Promise<ActionContext>;
58
+ /** A CONSTRUCTION-BOUND owner-authority proof: minted only from the branded context by the
59
+ * commit principal itself, and accepted only against THAT context. This replaces a raw
60
+ * `ownerAuthored` boolean — a flag any caller could set by typo or confusion — with a value
61
+ * that cannot be hand-assembled and cannot leak across contexts: owner authority over a
62
+ * target-pinned goal's pause/deny is proven by construction, never asserted (SPEC 13.6). */
63
+ export interface OwnerCommitProof {
64
+ readonly space: string;
65
+ }
66
+ export declare function ownerCommitProof(ctx: ActionContext): OwnerCommitProof;
67
+ /** A GATE-MINTED clearance: the only key that opens a GUARDED goal's edge into `running`
68
+ * (SPEC 13.6: a guarded command MUST NOT effect until the guard answered allow, and `running`
69
+ * IS effecting). The mint lives behind a ONE-SHOT claim that THE guard gate module takes at
70
+ * load, so no other holder of an action context can mint gate passage - an owner proof
71
+ * deliberately does NOT satisfy this edge (any context holder mints owner proofs; only the
72
+ * gate, whose allow/release/reconcile arms verified the guard's answer, mints clearance). */
73
+ export interface GuardClearance {
74
+ readonly goalId: string;
75
+ }
76
+ /** ONE-SHOT handoff of the clearance mint to THE gate (endpoint-guard claims it at module
77
+ * load; the package always loads it). Every later call is a loud refusal: there is exactly
78
+ * one gate, so a second claimant is by definition not it (SPEC 13.6). */
79
+ export declare function claimGuardClearanceMint(): (ctx: ActionContext, goalId: string) => GuardClearance;
80
+ /** A goal's coordinates: the owning endpoint + the caller triple + the client-chosen goalId. */
81
+ export interface GoalRef {
82
+ endpoint: string;
83
+ caller: EpCaller;
84
+ goalId: string;
85
+ }
86
+ /** Snapshot a caller-supplied ref to a validated DETACHED copy at seam entry, BEFORE the first
87
+ * await: a shared mutable ref can otherwise split one operation's identity across its reads,
88
+ * its CAS, and its terminal publish. Exported for the guard seams, which detach the goal they
89
+ * bind, resume, and project against the same discipline. */
90
+ export declare function snapshotRef(ref: GoalRef): GoalRef;
91
+ /** Derive a goal ref STRUCTURALLY from the broker-authenticated request (§13.6): the caller
92
+ * triple comes from the subject the broker admitted, DETACHED so a later mutation of the parsed
93
+ * request cannot retarget it, never from body fields — a seam taking this ref addresses only
94
+ * the authenticated caller's own goals. */
95
+ export declare function goalRefOf(request: ParsedEpRequest, goalId: string): GoalRef;
96
+ /** The goal's terminal-result fact subject (`epf.<e>.goal.<triple>.<goalId>.result`, §13.2). */
97
+ export declare function goalResultSubject(space: string, ref: GoalRef): string;
98
+ /** The per-goal progress EVENT topic tail (§13.2 reserved topics). */
99
+ export declare function goalProgressTopic(ref: GoalRef): string[];
100
+ /** The bind fact: the goalId's accepted fingerprint, immutable for the goal's lifetime. */
101
+ export interface GoalBindFact {
102
+ v: 1;
103
+ goalId: string;
104
+ fingerprint: string;
105
+ }
106
+ /** Bind a goal to its accepted fingerprint BEFORE acceptance (the canonicalizer's seam): a
107
+ * create-only CAS per goalId. The winner proceeds; a loser reads the recorded bind and decides
108
+ * (same fingerprint = retry, different = `conflict` before acceptance and effect). The subject
109
+ * derives from the goal ref — ONE entry-derived identity (a caller derives it from the
110
+ * broker-authenticated request via {@link goalRefOf} exactly once), never body fields. */
111
+ export declare function bindGoal(ctx: ActionContext, ref: GoalRef, fingerprint: string): Promise<{
112
+ bound: true;
113
+ } | {
114
+ bound: false;
115
+ existing: GoalBindFact;
116
+ }>;
117
+ /** The submission-vs-bind verdict (§13.6 item 5 + orphan recovery). */
118
+ export type GoalSubmissionVerdict = {
119
+ kind: "new";
120
+ } | {
121
+ kind: "cached";
122
+ bind: GoalBindFact;
123
+ result?: GoalResultFact;
124
+ } | {
125
+ kind: "adopted";
126
+ bind: GoalBindFact;
127
+ } | {
128
+ kind: "conflict";
129
+ bind: GoalBindFact;
130
+ };
131
+ /** Resolve a goal submission against the bind rail (the canonicalizer's composed seam): NEW
132
+ * work (bind won); the caller's retry serving the CACHED decision/outcome (same fingerprint +
133
+ * a persisted goal whose spec AGREES with the bind); orphan ADOPTION (same fingerprint, no goal
134
+ * record — the bind winner crashed pre-acceptance); or `conflict` (different fingerprint). A
135
+ * persisted spec whose fingerprint disagrees with the bind is a loud `internal` (garbled
136
+ * authority chain), never a silent cached serve. */
137
+ export declare function resolveGoalSubmission(ctx: ActionContext, request: ParsedEpRequest, goalId: string, fingerprint: string): Promise<GoalSubmissionVerdict>;
138
+ /** The §13.6 single status vocabulary for every long-running surface. */
139
+ export declare const GOAL_STATES: readonly ["accepted", "running", "waiting", "cancelling", "succeeded", "failed", "cancelled", "expired", "uncertain"];
140
+ export type GoalState = (typeof GOAL_STATES)[number];
141
+ /** All five are TERMINAL and immutable; first-terminal-fact-wins applies uniformly. */
142
+ export declare const GOAL_TERMINAL_STATES: readonly GoalState[];
143
+ /** The legal §13.6 transitions: `accepted → running ⇄ waiting`, `cancelling` between a cancel
144
+ * and its terminal, every non-terminal may project a terminal, a terminal absorbs. */
145
+ export declare function isLegalGoalTransition(from: GoalState, to: GoalState): boolean;
146
+ /** The goal SPEC (written once at acceptance): the accepted definition every later seam
147
+ * validates against — the terminal commit stamps ITS fingerprint from here, the readiness
148
+ * settle reads ITS bound from here, and a target-pinned goal fences on ITS target lifecycle. */
149
+ export interface GoalSpecValue {
150
+ v: 1;
151
+ goalId: string;
152
+ fingerprint: string;
153
+ command: string;
154
+ caller: {
155
+ id: string;
156
+ lifecycleUid: string;
157
+ };
158
+ target?: {
159
+ owner: string;
160
+ actor: string;
161
+ lifecycleUid: string;
162
+ mappingRevision: number;
163
+ };
164
+ /** The accepted submission's request id — the goal's ADDRESS for its durable acceptance fact
165
+ * (`epf.<e>.dec.<triple>.<id>`), written at acceptance when it is known. The raw submission
166
+ * (EPJ) is age-evicted, so receipt reconstruction after a crash reads the acceptance THROUGH
167
+ * this address and proves the chain (id + sourceSeq + fingerprint) before minting (§13.10). */
168
+ requestId: string;
169
+ /** The guard endpoint named by the command's VERIFIED `ai.cotal.guarded` trait value,
170
+ * recorded at acceptance. Its PRESENCE is what {@link transitionGoal} enforces: a guarded
171
+ * goal's edge into `running` opens only with THE gate's {@link GuardClearance} - an
172
+ * unrecorded guard binding is unenforceable, so the acceptance path MUST record it
173
+ * (SPEC 13.6/13.7). */
174
+ guard?: string;
175
+ sourceSeq: number;
176
+ acceptedAt: number;
177
+ readinessDeadlineMs?: number;
178
+ }
179
+ /** Read the persisted accepted goal (`undefined` = never accepted). A DEL marker refuses. */
180
+ export declare function readGoalSpec(ctx: ActionContext, ref: GoalRef): Promise<{
181
+ value: GoalSpecValue;
182
+ revision: number;
183
+ } | undefined>;
184
+ /** The goal STATUS value: the current state projection. State-dependent fields are CLOSED. */
185
+ export interface GoalStatusValue extends Record<string, unknown> {
186
+ state: GoalState;
187
+ checkpoint?: {
188
+ token: string;
189
+ deadlineGeneration: number;
190
+ };
191
+ cancelMode?: "graceful" | "terminate";
192
+ observedSpecRevision: number;
193
+ }
194
+ /** Create the goal record at acceptance, IDEMPOTENTLY (spec create-only, then the `accepted`
195
+ * status): a crash between the two writes (or an adopted-retry replay) re-reads the spec,
196
+ * requires it CONTENT-IDENTICAL, and ensures the status — no stranded spec-only goal. */
197
+ export declare function createGoal(ctx: ActionContext, ref: GoalRef, spec: Omit<GoalSpecValue, "v" | "goalId">): Promise<{
198
+ specRevision: number;
199
+ }>;
200
+ /** Read the goal's current status projection (`undefined` = unknown goal). */
201
+ export declare function readGoalStatus(ctx: ActionContext, ref: GoalRef): Promise<{
202
+ value: GoalStatusValue;
203
+ revision: number;
204
+ } | undefined>;
205
+ /** Leader-read a goal's status projection by ref ALONE (no {@link ActionContext}) — a fencing read
206
+ * for a caller OUTSIDE the action module. The retirement drain uses it to decide whether an
207
+ * accepted ACTION goal is still `accepted` (never entered `running`, the guard/currency-fenced
208
+ * effecting edge, so provably never effected) before it may create-only cancel it: a `cancelled`
209
+ * terminal must mean the effect did NOT run (SPEC 13.6). `undefined` = no goal record at all
210
+ * (never created ⇒ never ran). Leader-served (read-your-writes), so a running executor's
211
+ * transition is never missed as a stale absence and a mis-read never authorizes a false cancel. */
212
+ export declare function readGoalStatusByRefLeader(jsm: JetStreamManager, space: string, ref: GoalRef): Promise<GoalStatusValue | undefined>;
213
+ /** The executor's authenticated identity (subject/creds, never a body claim), required when a
214
+ * goal's spec pins a target lifecycle (§13.6 item 7). */
215
+ export interface GoalExecutor {
216
+ lifecycleUid: string;
217
+ epoch: number;
218
+ }
219
+ /** CAS the goal's status through the NON-TERMINAL machine. A TERMINAL target is REFUSED (a
220
+ * terminal status exists only as {@link projectGoalTerminal}). An EXECUTOR-authored PROGRESS
221
+ * transition (`running`/`waiting`) on a TARGET-PINNED goal MUST prove the executor's fresh
222
+ * currency; a `cancelling` transition is owner/caller-authored (its authority is the cancel's
223
+ * broker-authenticated caller, {@link requestGoalCancel}) and takes no executor; an OWNER pause
224
+ * (guard hold → `waiting`) may declare `ownerAuthored`. A target-pinned progress transition
225
+ * with neither executor nor `ownerAuthored` is refused. */
226
+ export declare function transitionGoal(ctx: ActionContext, ref: GoalRef, to: GoalState, opts?: {
227
+ fields?: Partial<Pick<GoalStatusValue, "checkpoint" | "cancelMode">>;
228
+ executor?: GoalExecutor;
229
+ resolveCurrentEpoch?: (target: {
230
+ owner: string;
231
+ actor: string;
232
+ lifecycleUid: string;
233
+ }) => Promise<number | null> | number | null;
234
+ epochResolveBudgetMs?: number;
235
+ /** The owner's own commit principal drives this (guard-hold pause/release): a
236
+ * CONSTRUCTION-BOUND {@link ownerCommitProof} from THIS context, never a raw flag. */
237
+ owner?: OwnerCommitProof;
238
+ /** THE gate's construction-bound {@link GuardClearance} - REQUIRED on a GUARDED goal's
239
+ * edge into `running` (SPEC 13.6 MUST-NOT-effect-until-allow; an owner proof does NOT
240
+ * satisfy this edge, since any context holder mints owner proofs). */
241
+ clearance?: GuardClearance;
242
+ }): Promise<GoalStatusValue>;
243
+ /** Project the WINNING terminal fact onto the status — the ONLY path a status reaches a terminal
244
+ * state, and the crash reconciler for a commit that fenced the fact but died before projecting.
245
+ * Cross-checks the fact's fingerprint against the persisted spec (a terminal fact whose
246
+ * fingerprint disagrees with the accepted goal is a garbled authority chain). */
247
+ export declare function projectGoalTerminal(ctx: ActionContext, ref: GoalRef): Promise<GoalStatusValue>;
248
+ export type GoalOutcomeState = "succeeded" | "failed" | "cancelled" | "expired" | "uncertain";
249
+ /** The goal's terminal fact + the §13.6 item-5 tombstone summary in one immutable artifact. */
250
+ export interface GoalResultFact {
251
+ v: 1;
252
+ goalId: string;
253
+ fingerprint: string;
254
+ state: GoalOutcomeState;
255
+ outcomeDigest: string;
256
+ data?: unknown;
257
+ ts: number;
258
+ }
259
+ /** Build the retirement-cancelled goal terminal (§13.8 option (i)): the FIRST-CLASS `cancelled`
260
+ * outcome state the goal union ALREADY carries — no new wire shape — bound to the acceptance's
261
+ * fingerprint, with the retirement attribution riding the digest-bound payload
262
+ * (`data.cancelledBy = { opId, target }`). Published create-only on the goal's result subject,
263
+ * so a racing real commit wins by landing first (first-terminal-wins, §13.8). A retirement
264
+ * cancels only ITS OWN target's accepted goals. */
265
+ export declare function goalCancelledResultOf(acceptance: {
266
+ fingerprint: string;
267
+ request: Record<string, unknown>;
268
+ target?: {
269
+ owner: string;
270
+ actor: string;
271
+ lifecycleUid: string;
272
+ };
273
+ }, cancelled: {
274
+ opId: string;
275
+ target: {
276
+ owner: string;
277
+ actor: string;
278
+ lifecycleUid: string;
279
+ };
280
+ }, ts: number): GoalResultFact;
281
+ /** The §13.6 item-5 tombstone serving form for a payload-evicted retry. */
282
+ export declare function goalTombstone(fact: GoalResultFact): GoalResultFact;
283
+ /** Closed validation, IDENTITY-BOUND to the ref, with the tombstone digest RE-VERIFIED. */
284
+ export declare function parseGoalResultFact(raw: unknown, subject: string, ref: GoalRef): GoalResultFact;
285
+ /** Read the goal's cached terminal outcome (`undefined` = not terminal yet). */
286
+ export declare function readGoalResult(ctx: ActionContext, ref: GoalRef): Promise<GoalResultFact | undefined>;
287
+ /** What receipt emission needs beyond the action context: the receipt store bonded to the SAME
288
+ * space AND the same connection, the EMITTING instance recorded as EVIDENCE (who produced this
289
+ * attestation - after a crash the reconciling instance records ITSELF here, so this is never
290
+ * proof of who EXECUTED the goal, and never redemption authority; the executed outcome's
291
+ * authority is the committed terminal fact alone), and the receipts-scoped signer + key. */
292
+ export interface ReceiptEmissionWiring {
293
+ store: ReceiptStoreContext;
294
+ instance: {
295
+ id: string;
296
+ instanceId: string;
297
+ epoch: number;
298
+ };
299
+ signer: {
300
+ keyId: string;
301
+ };
302
+ keyPair: {
303
+ sign(input: Uint8Array): Uint8Array;
304
+ };
305
+ }
306
+ /** One emission attempt's outcome: `emitted` (this attempt's receipt won the create-only CAS)
307
+ * or `converged` (a receipt already attests these facts — an earlier attempt's or a racing
308
+ * emitter's, ADOPTED only after it proves agreement with the facts). A recorded receipt that
309
+ * DISAGREES with the committed facts is a loud `conflict`, never adopted. */
310
+ export type ReceiptEmissionResult = {
311
+ outcome: "emitted" | "converged";
312
+ receipt: Receipt;
313
+ };
314
+ /** The durable backstop for the §13.10 MUST-emit guarantee: re-derive and publish the receipt
315
+ * for a goal whose terminal committed but whose emission was omitted (a crash between the
316
+ * terminal CAS and the publish, or a commit made without emission wiring). Reads the persisted
317
+ * spec and the committed terminal FRESH, then runs the SAME emission seam the inline path uses.
318
+ * `no-terminal` = nothing to attest yet (the goal simply is not terminal — never an error). */
319
+ export declare function reconcileReceiptEmission(ctx: ActionContext, wiring: ReceiptEmissionWiring, args: {
320
+ ref: GoalRef;
321
+ now: number;
322
+ }): Promise<ReceiptEmissionResult | {
323
+ outcome: "no-terminal";
324
+ }>;
325
+ /** A deny's AUTHORITATIVE PREDICATE (§13.6): a bare `deny` proves nothing, so the commit
326
+ * boundary requires and VERIFIES one of:
327
+ * - `hold-expired`: the named checkpoint's recorded spec must BIND this exact goal and its
328
+ * recorded one-use settlement must be `expired` (the arbiter's own fact — a live or resumed
329
+ * hold never denies);
330
+ * - `owner`: the owner's construction-bound {@link ownerCommitProof} from THIS context (a
331
+ * guard-verdict deny the owner itself is committing). */
332
+ export type GoalDenial = {
333
+ kind: "hold-expired";
334
+ token: string;
335
+ } | {
336
+ kind: "owner";
337
+ owner: OwnerCommitProof;
338
+ };
339
+ /** The closed terminal CAUSE (§13.6): the public commit accepts ONLY these, each with its own
340
+ * authoritative predicate verified inside the boundary; the terminal state is DERIVED, never a
341
+ * raw caller value.
342
+ * - `complete`: the executor's own outcome (`succeeded`|`failed`), proving fresh currency for
343
+ * a target-pinned goal;
344
+ * - `cancel`: `cancelled`, requiring the goal to be `cancelling` (a cancel was requested);
345
+ * - `deny`: `failed`, requiring the verified {@link GoalDenial} predicate (a bare deny cause
346
+ * is refused — any commit-seam holder could otherwise fail any accepted goal);
347
+ * - `readiness`: `uncertain`, the OWNER's deadline settlement, requiring `now` past the
348
+ * persisted acceptance-relative readiness deadline (no executor — a target-pinned goal's
349
+ * owner deadline is reachable). */
350
+ export type GoalCommitCause = {
351
+ cause: "complete";
352
+ state: "succeeded" | "failed";
353
+ data?: unknown;
354
+ executor?: GoalExecutor;
355
+ resolveCurrentEpoch?: (target: {
356
+ owner: string;
357
+ actor: string;
358
+ lifecycleUid: string;
359
+ }) => Promise<number | null> | number | null;
360
+ epochResolveBudgetMs?: number;
361
+ } | {
362
+ cause: "cancel";
363
+ data?: unknown;
364
+ } | {
365
+ cause: "deny";
366
+ denial: GoalDenial;
367
+ data?: unknown;
368
+ } | {
369
+ cause: "readiness";
370
+ };
371
+ /** Commit the goal's terminal state at the ONE mediated commit point, BOUND to the persisted
372
+ * accepted goal and its CAUSE (see {@link GoalCommitCause}). First terminal fact wins uniformly
373
+ * (completion, cancel, deny, and readiness race here); a loser observes the winner and its
374
+ * projection converges. Every operation input detaches at ENTRY (single-read, before the first
375
+ * await): a caller mutating cause/state/data/executor across the spec read changes nothing.
376
+ *
377
+ * RECEIPT EMISSION (§13.10): with `receipts` wired, the commit emits the terminal's receipt
378
+ * INLINE, best-effort, for the WINNING fact (won or lost — the terminal is committed either
379
+ * way and emission is idempotent). Invalid wiring refuses at ENTRY, before any terminal
380
+ * commits; a RUNTIME emission failure after the irreversible commit surfaces as
381
+ * `receiptEmission: { outcome: "failed" }` — it never masks the committed terminal, and
382
+ * {@link reconcileReceiptEmission} is the durable backstop that converges it. */
383
+ export declare function commitGoalResult(ctx: ActionContext, args: {
384
+ ref: GoalRef;
385
+ now: number;
386
+ receipts?: ReceiptEmissionWiring;
387
+ } & GoalCommitCause): Promise<{
388
+ won: boolean;
389
+ fact: GoalResultFact;
390
+ status: GoalStatusValue;
391
+ receiptEmission?: ReceiptEmissionResult | {
392
+ outcome: "failed";
393
+ error: EpEnvelopeError;
394
+ };
395
+ }>;
396
+ /** The reverse-DNS detail kind carrying a goal's cached terminal fact on an error (§13.3). */
397
+ export declare const GOAL_TERMINAL_DETAIL_KIND = "ai.cotal.goal.terminal";
398
+ /** The reserved `cancel` command's handler seam. The goal ref derives STRUCTURALLY from the
399
+ * broker-authenticated request (a caller cancels only its own goals). Unknown = failed-
400
+ * precondition; terminal = failed-precondition with the cached outcome on error.details;
401
+ * otherwise the status transitions to `cancelling` (owner/caller-authored — no executor) and
402
+ * the owner later commits the `cancel` cause. A completion that landed during the transition is
403
+ * observed AFTER it and converges the projection. */
404
+ export declare function requestGoalCancel(ctx: ActionContext, args: {
405
+ request: ParsedEpRequest;
406
+ goalId: string;
407
+ mode: "graceful" | "terminate";
408
+ }): Promise<GoalStatusValue>;
409
+ /** Settle a goal `uncertain` at its persisted acceptance-relative readiness deadline (the
410
+ * `readiness` cause). The bound is read from the PERSISTED spec; a target-pinned goal is
411
+ * REACHABLE (readiness is the owner's deadline, not an executor completion, so no executor is
412
+ * required). A racing late success that committed first wins and this returns the winner. */
413
+ export declare function settleGoalUncertain(ctx: ActionContext, args: {
414
+ ref: GoalRef;
415
+ now: number;
416
+ }): Promise<{
417
+ won: boolean;
418
+ fact: GoalResultFact;
419
+ status: GoalStatusValue;
420
+ }>;
421
+ /** Classify a resubmission against the recorded bind: same fingerprint = retry (cached), else
422
+ * `conflict`. {@link resolveGoalSubmission} composes this with the orphaned-bind recovery. */
423
+ export declare function classifyGoalReuse(existing: GoalBindFact, submittedFingerprint: string): "cached" | "conflict";
424
+ //# sourceMappingURL=endpoint-action.d.ts.map