@clossys/butler 0.1.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 (54) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/LICENSE +21 -0
  3. package/README.md +260 -0
  4. package/dist/audit-shape.check.d.ts +32 -0
  5. package/dist/audit-shape.check.d.ts.map +1 -0
  6. package/dist/audit-shape.check.js +7 -0
  7. package/dist/audit-shape.check.js.map +1 -0
  8. package/dist/cli.d.ts +54 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +426 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/contract.d.ts +256 -0
  13. package/dist/contract.d.ts.map +1 -0
  14. package/dist/contract.js +377 -0
  15. package/dist/contract.js.map +1 -0
  16. package/dist/inbound/index.d.ts +120 -0
  17. package/dist/inbound/index.d.ts.map +1 -0
  18. package/dist/inbound/index.js +125 -0
  19. package/dist/inbound/index.js.map +1 -0
  20. package/dist/index.d.ts +50 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +47 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/schema.d.ts +374 -0
  25. package/dist/schema.d.ts.map +1 -0
  26. package/dist/schema.js +304 -0
  27. package/dist/schema.js.map +1 -0
  28. package/dist/validation.d.ts +74 -0
  29. package/dist/validation.d.ts.map +1 -0
  30. package/dist/validation.js +140 -0
  31. package/dist/validation.js.map +1 -0
  32. package/dist/web/index.d.ts +5 -0
  33. package/dist/web/index.d.ts.map +1 -0
  34. package/dist/web/index.js +25 -0
  35. package/dist/web/index.js.map +1 -0
  36. package/dist/web/internal/peer-version.d.ts +53 -0
  37. package/dist/web/internal/peer-version.d.ts.map +1 -0
  38. package/dist/web/internal/peer-version.js +136 -0
  39. package/dist/web/internal/peer-version.js.map +1 -0
  40. package/dist/web/useStandingWants.d.ts +75 -0
  41. package/dist/web/useStandingWants.d.ts.map +1 -0
  42. package/dist/web/useStandingWants.js +66 -0
  43. package/dist/web/useStandingWants.js.map +1 -0
  44. package/package.json +93 -0
  45. package/src/audit-shape.check.ts +37 -0
  46. package/src/cli.ts +445 -0
  47. package/src/contract.ts +534 -0
  48. package/src/inbound/index.ts +190 -0
  49. package/src/index.ts +113 -0
  50. package/src/schema.ts +622 -0
  51. package/src/validation.ts +172 -0
  52. package/src/web/index.ts +27 -0
  53. package/src/web/internal/peer-version.ts +159 -0
  54. package/src/web/useStandingWants.ts +139 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * The runtime contract: evaluate one stored want, decide one change to it,
3
+ * and the three gates that read a whole set of them.
4
+ *
5
+ * THE LOOP THIS CLOSES
6
+ * ---------------------
7
+ * A stated want is the setpoint. Acting on it is the act. Reading the
8
+ * interpretation back to the person, and asking whether the standing
9
+ * answer is still current, is the observation. Unconfirmed intents and
10
+ * expired instructions are the comparison. Re-asking is the correction. A
11
+ * preference written to a row and never re-checked has no observation and
12
+ * no comparison — it is an open loop, and closing it is the entire reason
13
+ * this package exists.
14
+ *
15
+ * Everything here is pure. No I/O, no clock read, no ambient state:
16
+ * `evaluateStandingInstruction` and `decideStandingChange` take `now` as a
17
+ * parameter rather than calling `Date.now()` themselves, so the same
18
+ * inputs always produce the same output and a test can put the clock
19
+ * anywhere it needs it. Storage and audit are host-supplied ports
20
+ * (`StandingInstructionStore`, `StandingAuditLedger` in `schema.ts`); this
21
+ * file never touches either.
22
+ *
23
+ * THE THREE GATES
24
+ * ----------------
25
+ * Each returns the same shape of three-state result: `ok: true` when it
26
+ * genuinely checked something and found nothing; `ok: false` with a
27
+ * violation reason and findings when it checked and found something; and
28
+ * `ok: false` with an INDETERMINATE reason when there was nothing to check
29
+ * at all. `cli.ts` maps those onto `0` / `1` / `2` and never collapses the
30
+ * third into either of the first two. A gate that reports "clean" after
31
+ * checking nothing is worse than no gate.
32
+ */
33
+ import type { ConfidenceFloor, ConfirmationRecord, InstructionUsage, IntentRecord, PolicyVersion, PreferencePath, StandingAction, StandingAuditEvent, StandingEvaluation, StandingEvaluationPolicy, StandingInstruction, StandingTopic } from "./schema.js";
34
+ /**
35
+ * Compares one stored instruction against the policy in force AND the
36
+ * clock. This is the check a weaker tool skips: asking whether a row
37
+ * exists, or reading a boolean off it, cannot see age, so a row three
38
+ * policy versions old and a year past its own declared window both read as
39
+ * a pass. Presence is not currency.
40
+ *
41
+ * - `undefined` input, and a record whose own `state.kind` is `"absent"`,
42
+ * both return `{ status: "absent", reason: "no-record" }`. There is no
43
+ * third "never asked" representation, and this function deliberately does
44
+ * not runtime-validate its typed input or fall back to `"absent"` for a
45
+ * malformed one — a silent fallback would make a broken record
46
+ * indistinguishable from a subject who was genuinely never asked. Untyped
47
+ * input is validated at the boundary, by `schema.ts`'s validators.
48
+ * - An INFERRED instruction with no `confirmedAt` returns
49
+ * `{ status: "absent", reason: "unconfirmed-inference" }`. An inferred
50
+ * want is not a want we have until the person says it is; treating one as
51
+ * binding is the same defect as reading absence as permission, one step
52
+ * further upstream.
53
+ * - A `"granted"` record whose `policyVersion` differs from
54
+ * `currentPolicyVersion` is ALWAYS stale, unconditionally. A policy
55
+ * change invalidates prior permission by definition.
56
+ * - A `"denied"` record whose `policyVersion` differs is stale only when
57
+ * `policy.invalidateDenialOnPolicyBump` is `true`. Whether a policy bump
58
+ * also invalidates a prior refusal is a jurisdiction judgment; `policy`
59
+ * has no default, so nobody gets either answer by accident.
60
+ * - Independently of the policy version, a record whose `decidedAt` is more
61
+ * than `currency.days` before `at` is stale with reason
62
+ * `"window-elapsed"` — for grants AND denials alike. The window is the
63
+ * consumer's own declared statement of how long their own answer keeps
64
+ * speaking, and a refusal that has expired is as much a reason to ask
65
+ * again as a permission that has.
66
+ *
67
+ * When both a policy bump and an elapsed window apply, `"policy-superseded"`
68
+ * is reported: it is the more specific fact, it names something that
69
+ * happened on this side of the boundary rather than merely time passing,
70
+ * and either way the answer is the same — ask again.
71
+ */
72
+ export declare function evaluateStandingInstruction(instruction: StandingInstruction | undefined, currentPolicyVersion: PolicyVersion, policy: StandingEvaluationPolicy, at: string): StandingEvaluation;
73
+ /**
74
+ * The pure decision core for one change to one standing instruction:
75
+ * produces the new record and its audit event. The caller's
76
+ * `StandingInstructionStore` and `StandingAuditLedger` perform the writes.
77
+ *
78
+ * `actorId` and `subjectId` are separate parameters, in that order, and
79
+ * are never derived from one another — an actor recording a subject's own
80
+ * decision and an actor deciding on a subject's behalf must be
81
+ * distinguishable in the audit trail, and a single conflated id makes them
82
+ * identical forever.
83
+ *
84
+ * Withdrawing produces `state: { kind: "absent" }`: the same value a
85
+ * subject who was never asked has. That is deliberate and it is the point
86
+ * of the three-state model — a withdrawal returns the person to "we do not
87
+ * have a want here", which is not permission, rather than to a `false`
88
+ * that some later boolean read could round back up.
89
+ */
90
+ export declare function decideStandingChange(actorId: string, subjectId: string, instructionId: string, action: StandingAction, now: string): {
91
+ instruction: StandingInstruction;
92
+ auditEvent: StandingAuditEvent;
93
+ };
94
+ /**
95
+ * A pure audit-event builder for a subject reopening their preference
96
+ * surface, independent of whether they change anything once it is open.
97
+ * Reopening at all is audit-worthy on its own: it is the observation half
98
+ * of the loop, and a surface nobody ever reopens is a surface whose
99
+ * instructions are never re-checked.
100
+ */
101
+ export declare function recordReopened(actorId: string, subjectId: string, topic: StandingTopic, policyVersion: PolicyVersion, now: string): StandingAuditEvent;
102
+ /**
103
+ * A pure audit-event builder for the moment `evaluateStandingInstruction`
104
+ * reports a stored answer stale. `reason` picks the event type, so an
105
+ * auditor can tell a policy bump from an expired window without re-deriving
106
+ * it. `previousPolicyVersion` is the version the invalidated record
107
+ * actually answered; `currentPolicyVersion` is the one in force now.
108
+ * Calling this is optional — the evaluation itself performs no I/O and
109
+ * emits nothing — but a host that wants staleness to appear in its trail
110
+ * rather than only ever being silently recomputed on read calls it once it
111
+ * observes a `"stale"` evaluation.
112
+ */
113
+ export declare function recordStaleness(actorId: string, subjectId: string, topic: StandingTopic, reason: "policy-superseded" | "window-elapsed", previousPolicyVersion: PolicyVersion, currentPolicyVersion: PolicyVersion, now: string): StandingAuditEvent;
114
+ export type ConfirmationFindingKind =
115
+ /** Something was done on this reading and the subject never answered a read-back at all. */
116
+ "acted-without-confirmation"
117
+ /** Something was done on this reading after the subject said it was misread. */
118
+ | "acted-against-misread"
119
+ /** Something was done on this reading after the subject said they could not tell. `"unclear"` is not a quiet yes. */
120
+ | "acted-against-unclear"
121
+ /** A reading below the declared floor was acted on with no hand-off and no confirmation. */
122
+ | "below-floor-acted-silently"
123
+ /** A read-back answers an intent that is not in the set being checked. */
124
+ | "confirmation-without-intent";
125
+ export interface ConfirmationFinding {
126
+ kind: ConfirmationFindingKind;
127
+ intentId: string;
128
+ /** The actor that dispositioned the intent, or the subject that answered a dangling read-back. Never both, never merged. */
129
+ actorId?: string;
130
+ message: string;
131
+ }
132
+ export type ConfirmationFailureReason = "unconfirmed-intents" | "no-intents-provided";
133
+ export interface ConfirmationCompletenessResult {
134
+ ok: boolean;
135
+ reason?: ConfirmationFailureReason;
136
+ intentsChecked: number;
137
+ confirmationsChecked: number;
138
+ /** The floor actually applied, echoed back so a report names the number it judged against rather than implying a universal one. */
139
+ floorApplied: number;
140
+ findings: ConfirmationFinding[];
141
+ }
142
+ /**
143
+ * GATE 1 — every acted-on intent has the subject's own confirmation, or an
144
+ * explicit below-floor hand-off.
145
+ *
146
+ * Pure, no I/O. `floor` is supplied by the caller and has no default
147
+ * anywhere in this package: the number below which a reading is too weak
148
+ * to act on is one of the consumer's own values, and a floor this package
149
+ * invented would be this package authoring it.
150
+ *
151
+ * The below-floor rule is the AI-native half. A reading whose confidence
152
+ * is strictly below the floor may still be acted on — but only after the
153
+ * subject confirms it. What it may never be is acted on SILENTLY: a
154
+ * below-floor reading has to become a confirmation request or an explicit
155
+ * hand-off, and `"handed-off"` is a first-class disposition precisely so
156
+ * declining to act is representable as a decision rather than as an
157
+ * absence of one.
158
+ *
159
+ * `ok: false` with `"no-intents-provided"` is not a violation — it is this
160
+ * gate saying it never formed an opinion, and `cli.ts` maps it to `2`.
161
+ */
162
+ export declare function checkConfirmationCompleteness(intents: readonly IntentRecord[], confirmations: readonly ConfirmationRecord[], floor: ConfidenceFloor): ConfirmationCompletenessResult;
163
+ export type CurrencyFindingKind =
164
+ /** An instruction was relied on after its own declared window ran out. */
165
+ "used-past-window"
166
+ /** An instruction was relied on after the policy version it answered was superseded. */
167
+ | "used-after-policy-superseded"
168
+ /** An instruction was relied on while there was no answer on record — including an inference the subject never confirmed. Absence is not permission. */
169
+ | "used-while-absent"
170
+ /** A usage names an instruction that is not in the set being checked. */
171
+ | "usage-without-instruction";
172
+ export interface CurrencyFinding {
173
+ kind: CurrencyFindingKind;
174
+ instructionId: string;
175
+ /** Whoever relied on the instruction. Separate from the instruction's own `subjectId`, always. */
176
+ actorId: string;
177
+ usedAt: string;
178
+ message: string;
179
+ }
180
+ export type CurrencyFailureReason = "stale-instructions-used" | "no-instructions-provided" | "no-usages-provided";
181
+ export interface CurrencyResult {
182
+ ok: boolean;
183
+ reason?: CurrencyFailureReason;
184
+ instructionsChecked: number;
185
+ usagesChecked: number;
186
+ findings: CurrencyFinding[];
187
+ }
188
+ /**
189
+ * GATE 2 — no standing instruction is used past its declared window.
190
+ *
191
+ * Pure, no I/O. Reads USAGES, not instructions alone, and that is the
192
+ * whole design: a set of instructions with nobody relying on them proves
193
+ * nothing, while a set of usages is a record of the loop actually being
194
+ * closed or not. Each usage carries the policy version in force at the
195
+ * moment it happened, so this gate replays a real decision rather than
196
+ * re-deriving one against today's policy.
197
+ *
198
+ * `policy.invalidateDenialOnPolicyBump` has no default — see
199
+ * `evaluateStandingInstruction`. A caller that cannot supply it does not
200
+ * get a guess.
201
+ *
202
+ * `used-while-absent` is here because it is the same defect the three-state
203
+ * model exists to prevent, observed one layer up: relying on nothing at all
204
+ * — a subject never asked, or an inference they never confirmed — is not a
205
+ * currency problem in the narrow sense, but it is exactly what a boolean
206
+ * read of a missing row silently permits, and a gate that only measured
207
+ * age would pass it.
208
+ *
209
+ * `ok: false` with either "nothing provided" reason is indeterminate, and
210
+ * `cli.ts` maps it to `2`.
211
+ */
212
+ export declare function checkCurrency(instructions: readonly StandingInstruction[], usages: readonly InstructionUsage[], policy: StandingEvaluationPolicy): CurrencyResult;
213
+ export type WithdrawalParityFindingKind =
214
+ /** The surface declares a way in and no way out. */
215
+ "withdrawal-unavailable"
216
+ /** Withdrawing takes more discrete actions than granting did. */
217
+ | "withdrawal-costs-more-steps"
218
+ /** Withdrawing requires contacting a human where granting did not. */
219
+ | "withdrawal-requires-contact"
220
+ /** Withdrawing requires an account where granting did not. */
221
+ | "withdrawal-requires-account";
222
+ export interface WithdrawalParityFinding {
223
+ kind: WithdrawalParityFindingKind;
224
+ surfaceId: string;
225
+ topic: StandingTopic;
226
+ message: string;
227
+ }
228
+ export type WithdrawalParityFailureReason = "withdrawal-harder-than-granting" | "no-paths-provided";
229
+ export interface WithdrawalParityResult {
230
+ ok: boolean;
231
+ reason?: WithdrawalParityFailureReason;
232
+ pathsChecked: number;
233
+ findings: WithdrawalParityFinding[];
234
+ }
235
+ /**
236
+ * GATE 3 — withdrawing is no harder than granting.
237
+ *
238
+ * Pure, no I/O. Compares the two routes a consumer measured itself, using
239
+ * three coarse countable facts rather than a score: a parity claim that
240
+ * produces a number nobody can trace back to a step is not evidence.
241
+ *
242
+ * A missing `withdraw` path is the loudest finding here, not a skipped
243
+ * comparison. A surface that offers a way in and no way out is the extreme
244
+ * of the same defect, and a gate that quietly had nothing to compare would
245
+ * report it as a pass.
246
+ *
247
+ * Reopening is not a degraded path, and this gate is only the measurement
248
+ * half of that. The API half is structural and lives in `./web`, where
249
+ * `withdraw` shares `grant`'s and `deny`'s exact call shape, so there is no
250
+ * separate, harder-to-reach function for revoking than for giving.
251
+ *
252
+ * `ok: false` with `"no-paths-provided"` is indeterminate, and `cli.ts`
253
+ * maps it to `2`.
254
+ */
255
+ export declare function checkWithdrawalParity(paths: readonly PreferencePath[]): WithdrawalParityResult;
256
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,377 @@
1
+ /**
2
+ * The runtime contract: evaluate one stored want, decide one change to it,
3
+ * and the three gates that read a whole set of them.
4
+ *
5
+ * THE LOOP THIS CLOSES
6
+ * ---------------------
7
+ * A stated want is the setpoint. Acting on it is the act. Reading the
8
+ * interpretation back to the person, and asking whether the standing
9
+ * answer is still current, is the observation. Unconfirmed intents and
10
+ * expired instructions are the comparison. Re-asking is the correction. A
11
+ * preference written to a row and never re-checked has no observation and
12
+ * no comparison — it is an open loop, and closing it is the entire reason
13
+ * this package exists.
14
+ *
15
+ * Everything here is pure. No I/O, no clock read, no ambient state:
16
+ * `evaluateStandingInstruction` and `decideStandingChange` take `now` as a
17
+ * parameter rather than calling `Date.now()` themselves, so the same
18
+ * inputs always produce the same output and a test can put the clock
19
+ * anywhere it needs it. Storage and audit are host-supplied ports
20
+ * (`StandingInstructionStore`, `StandingAuditLedger` in `schema.ts`); this
21
+ * file never touches either.
22
+ *
23
+ * THE THREE GATES
24
+ * ----------------
25
+ * Each returns the same shape of three-state result: `ok: true` when it
26
+ * genuinely checked something and found nothing; `ok: false` with a
27
+ * violation reason and findings when it checked and found something; and
28
+ * `ok: false` with an INDETERMINATE reason when there was nothing to check
29
+ * at all. `cli.ts` maps those onto `0` / `1` / `2` and never collapses the
30
+ * third into either of the first two. A gate that reports "clean" after
31
+ * checking nothing is worse than no gate.
32
+ */
33
+ const MILLISECONDS_PER_DAY = 86_400_000;
34
+ function samePolicyVersion(a, b) {
35
+ return a.policyId === b.policyId && a.version === b.version;
36
+ }
37
+ function windowElapsed(decidedAt, currency, at) {
38
+ const decided = Date.parse(decidedAt);
39
+ const asked = Date.parse(at);
40
+ if (Number.isNaN(decided) || Number.isNaN(asked))
41
+ return false;
42
+ return asked - decided > currency.days * MILLISECONDS_PER_DAY;
43
+ }
44
+ /**
45
+ * Compares one stored instruction against the policy in force AND the
46
+ * clock. This is the check a weaker tool skips: asking whether a row
47
+ * exists, or reading a boolean off it, cannot see age, so a row three
48
+ * policy versions old and a year past its own declared window both read as
49
+ * a pass. Presence is not currency.
50
+ *
51
+ * - `undefined` input, and a record whose own `state.kind` is `"absent"`,
52
+ * both return `{ status: "absent", reason: "no-record" }`. There is no
53
+ * third "never asked" representation, and this function deliberately does
54
+ * not runtime-validate its typed input or fall back to `"absent"` for a
55
+ * malformed one — a silent fallback would make a broken record
56
+ * indistinguishable from a subject who was genuinely never asked. Untyped
57
+ * input is validated at the boundary, by `schema.ts`'s validators.
58
+ * - An INFERRED instruction with no `confirmedAt` returns
59
+ * `{ status: "absent", reason: "unconfirmed-inference" }`. An inferred
60
+ * want is not a want we have until the person says it is; treating one as
61
+ * binding is the same defect as reading absence as permission, one step
62
+ * further upstream.
63
+ * - A `"granted"` record whose `policyVersion` differs from
64
+ * `currentPolicyVersion` is ALWAYS stale, unconditionally. A policy
65
+ * change invalidates prior permission by definition.
66
+ * - A `"denied"` record whose `policyVersion` differs is stale only when
67
+ * `policy.invalidateDenialOnPolicyBump` is `true`. Whether a policy bump
68
+ * also invalidates a prior refusal is a jurisdiction judgment; `policy`
69
+ * has no default, so nobody gets either answer by accident.
70
+ * - Independently of the policy version, a record whose `decidedAt` is more
71
+ * than `currency.days` before `at` is stale with reason
72
+ * `"window-elapsed"` — for grants AND denials alike. The window is the
73
+ * consumer's own declared statement of how long their own answer keeps
74
+ * speaking, and a refusal that has expired is as much a reason to ask
75
+ * again as a permission that has.
76
+ *
77
+ * When both a policy bump and an elapsed window apply, `"policy-superseded"`
78
+ * is reported: it is the more specific fact, it names something that
79
+ * happened on this side of the boundary rather than merely time passing,
80
+ * and either way the answer is the same — ask again.
81
+ */
82
+ export function evaluateStandingInstruction(instruction, currentPolicyVersion, policy, at) {
83
+ if (instruction === undefined || instruction.state.kind === "absent") {
84
+ return { status: "absent", reason: "no-record" };
85
+ }
86
+ if (instruction.provenance === "inferred" && instruction.confirmedAt === undefined) {
87
+ return { status: "absent", reason: "unconfirmed-inference" };
88
+ }
89
+ const { state } = instruction;
90
+ const current = samePolicyVersion(state.policyVersion, currentPolicyVersion);
91
+ const expired = windowElapsed(state.decidedAt, instruction.currency, at);
92
+ if (state.kind === "granted") {
93
+ if (!current)
94
+ return { status: "stale", reason: "policy-superseded", previousPolicyVersion: state.policyVersion, decidedAt: state.decidedAt };
95
+ if (expired)
96
+ return { status: "stale", reason: "window-elapsed", previousPolicyVersion: state.policyVersion, decidedAt: state.decidedAt };
97
+ return { status: "granted", policyVersion: state.policyVersion };
98
+ }
99
+ // state.kind === "denied"
100
+ if (!current && policy.invalidateDenialOnPolicyBump) {
101
+ return { status: "stale", reason: "policy-superseded", previousPolicyVersion: state.policyVersion, decidedAt: state.decidedAt };
102
+ }
103
+ if (expired)
104
+ return { status: "stale", reason: "window-elapsed", previousPolicyVersion: state.policyVersion, decidedAt: state.decidedAt };
105
+ return { status: "denied", policyVersion: state.policyVersion };
106
+ }
107
+ /**
108
+ * The pure decision core for one change to one standing instruction:
109
+ * produces the new record and its audit event. The caller's
110
+ * `StandingInstructionStore` and `StandingAuditLedger` perform the writes.
111
+ *
112
+ * `actorId` and `subjectId` are separate parameters, in that order, and
113
+ * are never derived from one another — an actor recording a subject's own
114
+ * decision and an actor deciding on a subject's behalf must be
115
+ * distinguishable in the audit trail, and a single conflated id makes them
116
+ * identical forever.
117
+ *
118
+ * Withdrawing produces `state: { kind: "absent" }`: the same value a
119
+ * subject who was never asked has. That is deliberate and it is the point
120
+ * of the three-state model — a withdrawal returns the person to "we do not
121
+ * have a want here", which is not permission, rather than to a `false`
122
+ * that some later boolean read could round back up.
123
+ */
124
+ export function decideStandingChange(actorId, subjectId, instructionId, action, now) {
125
+ const base = { instructionId, subjectId, topic: action.topic, provenance: "stated", currency: action.currency };
126
+ const instruction = action.kind === "grant"
127
+ ? { ...base, state: { kind: "granted", policyVersion: action.policyVersion, decidedAt: now } }
128
+ : action.kind === "deny"
129
+ ? { ...base, state: { kind: "denied", policyVersion: action.policyVersion, decidedAt: now } }
130
+ : { ...base, state: { kind: "absent" } };
131
+ const auditEvent = {
132
+ subjectId,
133
+ actorId,
134
+ topic: action.topic,
135
+ type: action.kind === "grant" ? "granted" : action.kind === "deny" ? "denied" : "withdrawn",
136
+ policyVersion: action.policyVersion,
137
+ occurredAt: now,
138
+ };
139
+ return { instruction, auditEvent };
140
+ }
141
+ /**
142
+ * A pure audit-event builder for a subject reopening their preference
143
+ * surface, independent of whether they change anything once it is open.
144
+ * Reopening at all is audit-worthy on its own: it is the observation half
145
+ * of the loop, and a surface nobody ever reopens is a surface whose
146
+ * instructions are never re-checked.
147
+ */
148
+ export function recordReopened(actorId, subjectId, topic, policyVersion, now) {
149
+ return { subjectId, actorId, topic, type: "reopened", policyVersion, occurredAt: now };
150
+ }
151
+ /**
152
+ * A pure audit-event builder for the moment `evaluateStandingInstruction`
153
+ * reports a stored answer stale. `reason` picks the event type, so an
154
+ * auditor can tell a policy bump from an expired window without re-deriving
155
+ * it. `previousPolicyVersion` is the version the invalidated record
156
+ * actually answered; `currentPolicyVersion` is the one in force now.
157
+ * Calling this is optional — the evaluation itself performs no I/O and
158
+ * emits nothing — but a host that wants staleness to appear in its trail
159
+ * rather than only ever being silently recomputed on read calls it once it
160
+ * observes a `"stale"` evaluation.
161
+ */
162
+ export function recordStaleness(actorId, subjectId, topic, reason, previousPolicyVersion, currentPolicyVersion, now) {
163
+ return {
164
+ subjectId,
165
+ actorId,
166
+ topic,
167
+ type: reason,
168
+ policyVersion: currentPolicyVersion,
169
+ previousPolicyVersion,
170
+ occurredAt: now,
171
+ };
172
+ }
173
+ /**
174
+ * GATE 1 — every acted-on intent has the subject's own confirmation, or an
175
+ * explicit below-floor hand-off.
176
+ *
177
+ * Pure, no I/O. `floor` is supplied by the caller and has no default
178
+ * anywhere in this package: the number below which a reading is too weak
179
+ * to act on is one of the consumer's own values, and a floor this package
180
+ * invented would be this package authoring it.
181
+ *
182
+ * The below-floor rule is the AI-native half. A reading whose confidence
183
+ * is strictly below the floor may still be acted on — but only after the
184
+ * subject confirms it. What it may never be is acted on SILENTLY: a
185
+ * below-floor reading has to become a confirmation request or an explicit
186
+ * hand-off, and `"handed-off"` is a first-class disposition precisely so
187
+ * declining to act is representable as a decision rather than as an
188
+ * absence of one.
189
+ *
190
+ * `ok: false` with `"no-intents-provided"` is not a violation — it is this
191
+ * gate saying it never formed an opinion, and `cli.ts` maps it to `2`.
192
+ */
193
+ export function checkConfirmationCompleteness(intents, confirmations, floor) {
194
+ const base = { intentsChecked: intents.length, confirmationsChecked: confirmations.length, floorApplied: floor.minimumConfidence };
195
+ if (intents.length === 0) {
196
+ return { ok: false, reason: "no-intents-provided", ...base, findings: [] };
197
+ }
198
+ const byIntentId = new Map();
199
+ for (const confirmation of confirmations)
200
+ byIntentId.set(confirmation.intentId, confirmation);
201
+ const knownIntentIds = new Set(intents.map((intent) => intent.intentId));
202
+ const findings = [];
203
+ for (const intent of intents) {
204
+ const confirmation = byIntentId.get(intent.intentId);
205
+ const belowFloor = intent.confidence < floor.minimumConfidence;
206
+ if (intent.disposition !== "acted") {
207
+ // "handed-off" and "awaiting-confirmation" are both explicit,
208
+ // recorded decisions not to act yet. Neither needs a confirmation to
209
+ // be complete, because neither has done anything.
210
+ continue;
211
+ }
212
+ if (confirmation === undefined) {
213
+ findings.push({
214
+ kind: belowFloor ? "below-floor-acted-silently" : "acted-without-confirmation",
215
+ intentId: intent.intentId,
216
+ actorId: intent.actorId,
217
+ message: belowFloor
218
+ ? `acted on a reading of confidence ${intent.confidence} below the declared floor ${floor.minimumConfidence}, with no confirmation and no hand-off`
219
+ : "acted with no confirmation record from the subject",
220
+ });
221
+ continue;
222
+ }
223
+ if (confirmation.verdict === "misread") {
224
+ findings.push({
225
+ kind: "acted-against-misread",
226
+ intentId: intent.intentId,
227
+ actorId: intent.actorId,
228
+ message: "acted after the subject answered the read-back with \"misread\"",
229
+ });
230
+ continue;
231
+ }
232
+ if (confirmation.verdict === "unclear") {
233
+ findings.push({
234
+ kind: "acted-against-unclear",
235
+ intentId: intent.intentId,
236
+ actorId: intent.actorId,
237
+ message: "acted after the subject answered the read-back with \"unclear\"",
238
+ });
239
+ }
240
+ }
241
+ for (const confirmation of confirmations) {
242
+ if (knownIntentIds.has(confirmation.intentId))
243
+ continue;
244
+ findings.push({
245
+ kind: "confirmation-without-intent",
246
+ intentId: confirmation.intentId,
247
+ message: "a read-back answers an intent that is not in the set being checked",
248
+ });
249
+ }
250
+ if (findings.length > 0)
251
+ return { ok: false, reason: "unconfirmed-intents", ...base, findings };
252
+ return { ok: true, ...base, findings: [] };
253
+ }
254
+ /**
255
+ * GATE 2 — no standing instruction is used past its declared window.
256
+ *
257
+ * Pure, no I/O. Reads USAGES, not instructions alone, and that is the
258
+ * whole design: a set of instructions with nobody relying on them proves
259
+ * nothing, while a set of usages is a record of the loop actually being
260
+ * closed or not. Each usage carries the policy version in force at the
261
+ * moment it happened, so this gate replays a real decision rather than
262
+ * re-deriving one against today's policy.
263
+ *
264
+ * `policy.invalidateDenialOnPolicyBump` has no default — see
265
+ * `evaluateStandingInstruction`. A caller that cannot supply it does not
266
+ * get a guess.
267
+ *
268
+ * `used-while-absent` is here because it is the same defect the three-state
269
+ * model exists to prevent, observed one layer up: relying on nothing at all
270
+ * — a subject never asked, or an inference they never confirmed — is not a
271
+ * currency problem in the narrow sense, but it is exactly what a boolean
272
+ * read of a missing row silently permits, and a gate that only measured
273
+ * age would pass it.
274
+ *
275
+ * `ok: false` with either "nothing provided" reason is indeterminate, and
276
+ * `cli.ts` maps it to `2`.
277
+ */
278
+ export function checkCurrency(instructions, usages, policy) {
279
+ const base = { instructionsChecked: instructions.length, usagesChecked: usages.length };
280
+ if (instructions.length === 0)
281
+ return { ok: false, reason: "no-instructions-provided", ...base, findings: [] };
282
+ if (usages.length === 0)
283
+ return { ok: false, reason: "no-usages-provided", ...base, findings: [] };
284
+ const byId = new Map();
285
+ for (const instruction of instructions)
286
+ byId.set(instruction.instructionId, instruction);
287
+ const findings = [];
288
+ for (const usage of usages) {
289
+ const instruction = byId.get(usage.instructionId);
290
+ if (instruction === undefined) {
291
+ findings.push({
292
+ kind: "usage-without-instruction",
293
+ instructionId: usage.instructionId,
294
+ actorId: usage.actorId,
295
+ usedAt: usage.usedAt,
296
+ message: "relied on an instruction that is not in the set being checked",
297
+ });
298
+ continue;
299
+ }
300
+ const evaluation = evaluateStandingInstruction(instruction, usage.currentPolicyVersion, policy, usage.usedAt);
301
+ if (evaluation.status === "absent") {
302
+ findings.push({
303
+ kind: "used-while-absent",
304
+ instructionId: usage.instructionId,
305
+ actorId: usage.actorId,
306
+ usedAt: usage.usedAt,
307
+ message: evaluation.reason === "unconfirmed-inference"
308
+ ? "relied on an inferred instruction the subject never confirmed"
309
+ : "relied on an instruction with no answer on record",
310
+ });
311
+ continue;
312
+ }
313
+ if (evaluation.status === "stale") {
314
+ findings.push({
315
+ kind: evaluation.reason === "window-elapsed" ? "used-past-window" : "used-after-policy-superseded",
316
+ instructionId: usage.instructionId,
317
+ actorId: usage.actorId,
318
+ usedAt: usage.usedAt,
319
+ message: evaluation.reason === "window-elapsed"
320
+ ? `relied on an answer decided at ${evaluation.decidedAt}, past its declared window of ${instruction.currency.days} day(s)`
321
+ : `relied on an answer to policy ${evaluation.previousPolicyVersion.policyId}@${evaluation.previousPolicyVersion.version}, superseded by ${usage.currentPolicyVersion.policyId}@${usage.currentPolicyVersion.version}`,
322
+ });
323
+ }
324
+ }
325
+ if (findings.length > 0)
326
+ return { ok: false, reason: "stale-instructions-used", ...base, findings };
327
+ return { ok: true, ...base, findings: [] };
328
+ }
329
+ /**
330
+ * GATE 3 — withdrawing is no harder than granting.
331
+ *
332
+ * Pure, no I/O. Compares the two routes a consumer measured itself, using
333
+ * three coarse countable facts rather than a score: a parity claim that
334
+ * produces a number nobody can trace back to a step is not evidence.
335
+ *
336
+ * A missing `withdraw` path is the loudest finding here, not a skipped
337
+ * comparison. A surface that offers a way in and no way out is the extreme
338
+ * of the same defect, and a gate that quietly had nothing to compare would
339
+ * report it as a pass.
340
+ *
341
+ * Reopening is not a degraded path, and this gate is only the measurement
342
+ * half of that. The API half is structural and lives in `./web`, where
343
+ * `withdraw` shares `grant`'s and `deny`'s exact call shape, so there is no
344
+ * separate, harder-to-reach function for revoking than for giving.
345
+ *
346
+ * `ok: false` with `"no-paths-provided"` is indeterminate, and `cli.ts`
347
+ * maps it to `2`.
348
+ */
349
+ export function checkWithdrawalParity(paths) {
350
+ if (paths.length === 0)
351
+ return { ok: false, reason: "no-paths-provided", pathsChecked: 0, findings: [] };
352
+ const findings = [];
353
+ for (const path of paths) {
354
+ const where = { surfaceId: path.surfaceId, topic: path.topic };
355
+ if (path.withdraw === undefined) {
356
+ findings.push({ ...where, kind: "withdrawal-unavailable", message: "declares a grant path and no withdraw path at all" });
357
+ continue;
358
+ }
359
+ if (path.withdraw.steps > path.grant.steps) {
360
+ findings.push({
361
+ ...where,
362
+ kind: "withdrawal-costs-more-steps",
363
+ message: `withdrawing takes ${path.withdraw.steps} step(s) against granting's ${path.grant.steps}`,
364
+ });
365
+ }
366
+ if (path.withdraw.requiresContact && !path.grant.requiresContact) {
367
+ findings.push({ ...where, kind: "withdrawal-requires-contact", message: "withdrawing requires contacting a human where granting did not" });
368
+ }
369
+ if (path.withdraw.requiresAccount && !path.grant.requiresAccount) {
370
+ findings.push({ ...where, kind: "withdrawal-requires-account", message: "withdrawing requires an account where granting did not" });
371
+ }
372
+ }
373
+ if (findings.length > 0)
374
+ return { ok: false, reason: "withdrawal-harder-than-granting", pathsChecked: paths.length, findings };
375
+ return { ok: true, pathsChecked: paths.length, findings: [] };
376
+ }
377
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}