@agenticprimitives/fabric 0.0.0-alpha.4 → 0.0.0-alpha.8

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 (130) hide show
  1. package/CLAUDE.md +22 -2
  2. package/README.md +16 -16
  3. package/dist/case-emissions.d.ts +95 -0
  4. package/dist/case-emissions.d.ts.map +1 -0
  5. package/dist/case-emissions.js +208 -0
  6. package/dist/case-emissions.js.map +1 -0
  7. package/dist/case-machine.d.ts +28 -2
  8. package/dist/case-machine.d.ts.map +1 -1
  9. package/dist/case-machine.js +34 -7
  10. package/dist/case-machine.js.map +1 -1
  11. package/dist/cloudflare/index.d.ts +1 -0
  12. package/dist/cloudflare/index.d.ts.map +1 -1
  13. package/dist/cloudflare/index.js +4 -0
  14. package/dist/cloudflare/index.js.map +1 -1
  15. package/dist/cloudflare/interaction-store.d.ts +55 -0
  16. package/dist/cloudflare/interaction-store.d.ts.map +1 -0
  17. package/dist/cloudflare/interaction-store.js +230 -0
  18. package/dist/cloudflare/interaction-store.js.map +1 -0
  19. package/dist/cloudflare/principal-gateway-do.d.ts +118 -2
  20. package/dist/cloudflare/principal-gateway-do.d.ts.map +1 -1
  21. package/dist/cloudflare/principal-gateway-do.js +182 -7
  22. package/dist/cloudflare/principal-gateway-do.js.map +1 -1
  23. package/dist/communicative-act.d.ts +24 -1
  24. package/dist/communicative-act.d.ts.map +1 -1
  25. package/dist/communicative-act.js +28 -0
  26. package/dist/communicative-act.js.map +1 -1
  27. package/dist/delivery-envelope.d.ts.map +1 -1
  28. package/dist/delivery-envelope.js +0 -1
  29. package/dist/delivery-envelope.js.map +1 -1
  30. package/dist/enum-retirement.d.ts +43 -0
  31. package/dist/enum-retirement.d.ts.map +1 -0
  32. package/dist/enum-retirement.js +93 -0
  33. package/dist/enum-retirement.js.map +1 -0
  34. package/dist/exchange-record.d.ts +35 -4
  35. package/dist/exchange-record.d.ts.map +1 -1
  36. package/dist/exchange-record.js.map +1 -1
  37. package/dist/exchange-reducer.d.ts +32 -4
  38. package/dist/exchange-reducer.d.ts.map +1 -1
  39. package/dist/exchange-reducer.js +75 -1
  40. package/dist/exchange-reducer.js.map +1 -1
  41. package/dist/exchange-state.d.ts +30 -8
  42. package/dist/exchange-state.d.ts.map +1 -1
  43. package/dist/exchange-state.js +12 -10
  44. package/dist/exchange-state.js.map +1 -1
  45. package/dist/inbox-doc.d.ts +2 -2
  46. package/dist/inbox-doc.d.ts.map +1 -1
  47. package/dist/inbox-doc.js.map +1 -1
  48. package/dist/inbox-projection.d.ts +2 -2
  49. package/dist/inbox-projection.d.ts.map +1 -1
  50. package/dist/inbox-projection.js.map +1 -1
  51. package/dist/index.d.ts +21 -3
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +32 -2
  54. package/dist/index.js.map +1 -1
  55. package/dist/interaction-machines.d.ts +136 -0
  56. package/dist/interaction-machines.d.ts.map +1 -0
  57. package/dist/interaction-machines.js +174 -0
  58. package/dist/interaction-machines.js.map +1 -0
  59. package/dist/interaction-profile.d.ts +126 -0
  60. package/dist/interaction-profile.d.ts.map +1 -0
  61. package/dist/interaction-profile.js +192 -0
  62. package/dist/interaction-profile.js.map +1 -0
  63. package/dist/interaction-record.d.ts +168 -0
  64. package/dist/interaction-record.d.ts.map +1 -0
  65. package/dist/interaction-record.js +108 -0
  66. package/dist/interaction-record.js.map +1 -0
  67. package/dist/interactions/machine.d.ts +2 -2
  68. package/dist/interactions/machine.d.ts.map +1 -1
  69. package/dist/interactions/machine.js +2 -2
  70. package/dist/interactions/machine.js.map +1 -1
  71. package/dist/interactions/store.d.ts +9 -0
  72. package/dist/interactions/store.d.ts.map +1 -1
  73. package/dist/interactions/store.js +57 -2
  74. package/dist/interactions/store.js.map +1 -1
  75. package/dist/messaging/board.d.ts +3 -3
  76. package/dist/messaging/board.d.ts.map +1 -1
  77. package/dist/messaging/board.js +2 -2
  78. package/dist/messaging/board.js.map +1 -1
  79. package/dist/messaging/conversation-interaction.d.ts +66 -0
  80. package/dist/messaging/conversation-interaction.d.ts.map +1 -0
  81. package/dist/messaging/conversation-interaction.js +139 -0
  82. package/dist/messaging/conversation-interaction.js.map +1 -0
  83. package/dist/messaging/delivery.d.ts +2 -2
  84. package/dist/messaging/delivery.d.ts.map +1 -1
  85. package/dist/messaging/delivery.js +8 -1
  86. package/dist/messaging/delivery.js.map +1 -1
  87. package/dist/messaging/envelope.d.ts +7 -3
  88. package/dist/messaging/envelope.d.ts.map +1 -1
  89. package/dist/messaging/envelope.js +18 -1
  90. package/dist/messaging/envelope.js.map +1 -1
  91. package/dist/messaging/hash.d.ts +8 -2
  92. package/dist/messaging/hash.d.ts.map +1 -1
  93. package/dist/messaging/hash.js +6 -0
  94. package/dist/messaging/hash.js.map +1 -1
  95. package/dist/messaging/inbox-assistant.d.ts +16 -4
  96. package/dist/messaging/inbox-assistant.d.ts.map +1 -1
  97. package/dist/messaging/inbox-assistant.js +27 -4
  98. package/dist/messaging/inbox-assistant.js.map +1 -1
  99. package/dist/messaging/index.d.ts +4 -1
  100. package/dist/messaging/index.d.ts.map +1 -1
  101. package/dist/messaging/index.js +4 -0
  102. package/dist/messaging/index.js.map +1 -1
  103. package/dist/messaging/projector.d.ts +3 -3
  104. package/dist/messaging/projector.d.ts.map +1 -1
  105. package/dist/messaging/projector.js.map +1 -1
  106. package/dist/messaging/receipts.d.ts +3 -3
  107. package/dist/messaging/receipts.d.ts.map +1 -1
  108. package/dist/messaging/receipts.js.map +1 -1
  109. package/dist/messaging/rules.d.ts +10 -3
  110. package/dist/messaging/rules.d.ts.map +1 -1
  111. package/dist/messaging/rules.js +8 -1
  112. package/dist/messaging/rules.js.map +1 -1
  113. package/dist/messaging/store.d.ts +4 -4
  114. package/dist/messaging/store.d.ts.map +1 -1
  115. package/dist/messaging/store.js +5 -3
  116. package/dist/messaging/store.js.map +1 -1
  117. package/dist/messaging/types.d.ts +30 -0
  118. package/dist/messaging/types.d.ts.map +1 -1
  119. package/dist/messaging/types.js +3 -0
  120. package/dist/messaging/types.js.map +1 -1
  121. package/dist/messaging/vault-store.d.ts +2 -2
  122. package/dist/messaging/vault-store.d.ts.map +1 -1
  123. package/dist/protocol-binding.d.ts +71 -0
  124. package/dist/protocol-binding.d.ts.map +1 -0
  125. package/dist/protocol-binding.js +0 -0
  126. package/dist/protocol-binding.js.map +1 -0
  127. package/dist/record-catalog.d.ts.map +1 -1
  128. package/dist/record-catalog.js +7 -0
  129. package/dist/record-catalog.js.map +1 -1
  130. package/package.json +7 -7
@@ -0,0 +1,136 @@
1
+ import type { CanonicalAgentId } from '@agenticprimitives/types';
2
+ import type { InteractionId, ParticipationV1 } from './interaction-record.js';
3
+ /** Shared rejection vocabulary. Every machine is fail-closed: an unknown or ill-timed move is a TYPED
4
+ * rejection, never a silent no-op, because a silent no-op is indistinguishable from success. */
5
+ export type MachineRejection = 'invalid-transition' | 'unauthorized-actor' | 'terminal-state' | 'wrong-subject';
6
+ export type MachineResult<T> = {
7
+ ok: true;
8
+ next: T;
9
+ } | {
10
+ ok: false;
11
+ reason: MachineRejection;
12
+ };
13
+ /**
14
+ * What one participant's client has done with an exchange. Deliberately separate from delivery: two
15
+ * recipients of the same exchange have different inbox states, and neither is a fact about the
16
+ * exchange itself.
17
+ *
18
+ * `read` is the state ADR-0058 §16 is most careful about. It means a client marked something read. It
19
+ * is not comprehension, not acknowledgement, not consent, and not acceptance.
20
+ */
21
+ export type InboxState = 'unread' | 'read' | 'archived' | 'deleted';
22
+ export type InboxTransition = 'mark-read' | 'mark-unread' | 'archive' | 'restore' | 'delete';
23
+ export interface InboxEntryV1 {
24
+ /** WHOSE inbox. The state belongs to this viewer alone. */
25
+ viewer: CanonicalAgentId;
26
+ exchangeId: string;
27
+ state: InboxState;
28
+ updatedAt: string;
29
+ }
30
+ /**
31
+ * Only the viewer moves their own inbox state.
32
+ *
33
+ * `deleted` is a tombstone, not an erasure: `restore` can bring it back, and the exchange itself is
34
+ * untouched. One participant deleting their copy must never remove the record other participants and
35
+ * the audit trail depend on.
36
+ */
37
+ export declare function applyInboxTransition(entry: InboxEntryV1, event: {
38
+ transition: InboxTransition;
39
+ actor: CanonicalAgentId;
40
+ at: string;
41
+ }): MachineResult<InboxEntryV1>;
42
+ export type InteractionState = 'forming' | 'active' | 'suspended' | 'concluded' | 'abandoned';
43
+ export type InteractionTransition = 'open' | 'suspend' | 'resume' | 'conclude' | 'abandon';
44
+ export declare const TERMINAL_INTERACTION_STATES: readonly InteractionState[];
45
+ export interface InteractionLifecycleV1 {
46
+ interactionId: InteractionId;
47
+ state: InteractionState;
48
+ /** The SA custodying the interaction. Ending it is a custodial act, not a participant's. */
49
+ principal: CanonicalAgentId;
50
+ participations: readonly ParticipationV1[];
51
+ updatedAt: string;
52
+ }
53
+ /**
54
+ * Ending an interaction is CUSTODIAL — the principal, not any participant. A counterparty who could
55
+ * conclude a negotiation could end it the moment it stopped favouring them.
56
+ *
57
+ * Concluding does NOT touch commitments. That separation is the entire reason this machine and the
58
+ * commitment machine are distinct: otherwise closing a conversation quietly voids what was promised
59
+ * in it, and the party who benefits from that is exactly the party who closes it.
60
+ */
61
+ export declare function applyInteractionTransition(lifecycle: InteractionLifecycleV1, event: {
62
+ transition: InteractionTransition;
63
+ actor: CanonicalAgentId;
64
+ at: string;
65
+ }): MachineResult<InteractionLifecycleV1>;
66
+ /**
67
+ * A determination's own lifecycle, separate from the work it may authorize.
68
+ *
69
+ * `granted` means a decision was recorded. It does not mean anything ran, and it does not by itself
70
+ * permit anything — the authority re-check happens at the moment of acting regardless of what this
71
+ * says (ADR-0041). A `DecisionReceipt` attests that a decision was made, never that it was executed.
72
+ */
73
+ export type DecisionState = 'pending' | 'granted' | 'refused' | 'withdrawn' | 'expired' | 'superseded';
74
+ export type DecisionTransition = 'grant' | 'refuse' | 'withdraw' | 'expire' | 'supersede';
75
+ export declare const TERMINAL_DECISION_STATES: readonly DecisionState[];
76
+ export interface DecisionRecordV1 {
77
+ decisionId: string;
78
+ state: DecisionState;
79
+ /** Whose determination this is. */
80
+ decider: CanonicalAgentId;
81
+ /** What it is about — an exchange, an act, a request. */
82
+ subject: string;
83
+ decidedAt?: string;
84
+ expiresAt?: string;
85
+ updatedAt: string;
86
+ }
87
+ /** Only the decider moves their own decision. `expire` is the exception: time is not an actor, so any
88
+ * party may record that the deadline passed, and only once it actually has. */
89
+ export declare function applyDecisionTransition(decision: DecisionRecordV1, event: {
90
+ transition: DecisionTransition;
91
+ actor: CanonicalAgentId;
92
+ at: string;
93
+ subject?: string;
94
+ }): MachineResult<DecisionRecordV1>;
95
+ /**
96
+ * A normative obligation with a debtor, a creditor and its own lifecycle.
97
+ *
98
+ * The two states doing the real work are `fulfilment-claimed` and `discharged`, and they are separate
99
+ * because the debtor saying "done" and the obligation ENDING are different facts with different
100
+ * signers. Collapsing them lets the party who owes the obligation declare it satisfied — which is the
101
+ * failure ADR-0058 §15 names when it says workflow completion discharges nothing on its own.
102
+ */
103
+ export type CommitmentState = 'proposed' | 'active' | 'fulfilment-claimed' | 'discharged' | 'breached' | 'void';
104
+ export type CommitmentTransition = 'activate' | 'claim-fulfilment' | 'dispute-claim' | 'discharge' | 'assert-breach' | 'void';
105
+ export declare const TERMINAL_COMMITMENT_STATES: readonly CommitmentState[];
106
+ export interface CommitmentRecordV1 {
107
+ commitmentId: string;
108
+ state: CommitmentState;
109
+ /** Who owes. */
110
+ debtor: CanonicalAgentId;
111
+ /** Who is owed. */
112
+ creditor: CanonicalAgentId;
113
+ /** The Offer this obligation came from — an Offer is not a Commitment (ADR-0058 §15). */
114
+ fromOffer?: string;
115
+ updatedAt: string;
116
+ }
117
+ export declare function applyCommitmentTransition(commitment: CommitmentRecordV1, event: {
118
+ transition: CommitmentTransition;
119
+ actor: CanonicalAgentId;
120
+ at: string;
121
+ }): MachineResult<CommitmentRecordV1>;
122
+ /**
123
+ * Whether finishing the work discharges the obligation.
124
+ *
125
+ * The answer is NO unless the profile says otherwise, and this function exists so that answer has a
126
+ * name a caller can find instead of an assumption a caller can make. A profile MAY declare
127
+ * auto-discharge for obligations whose fulfilment is objectively observable (a payment settling); it
128
+ * MUST NOT for anything requiring the creditor's judgement, which is most things.
129
+ *
130
+ * There is no code path from an execution event to a commitment transition. That is deliberate: the
131
+ * link has to be written by a profile that chose it, so the choice appears in a diff.
132
+ */
133
+ export declare function mayDischargeOnExecution(profile: {
134
+ autoDischargeOnExecution?: boolean;
135
+ }): boolean;
136
+ //# sourceMappingURL=interaction-machines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interaction-machines.d.ts","sourceRoot":"","sources":["../src/interaction-machines.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,174 @@
1
+ // The four state machines spec 340 §5 names and the fabric did not have.
2
+ //
3
+ // Six machines, never collapsed: `delivery · inbox · interaction · decision · commitment · execution`.
4
+ // Two exist — `ExecState` (delivery/transport) and `CaseState` (execution substate). These are the
5
+ // other four.
6
+ //
7
+ // WHY SIX AND NOT ONE. A single `status` field forces every question through one answer, and the
8
+ // answers genuinely differ. The chain that must never be short-circuited:
9
+ //
10
+ // delivered ≠ admitted ≠ authenticated ≠ canonical-agent-bound ≠ authorized ≠ executed ≠ completed
11
+ //
12
+ // Each collapse below is a real, specific misreading — not a theoretical one:
13
+ //
14
+ // inbox into delivery → "they read it" becomes "they agreed". Read state is PER-VIEWER and
15
+ // proves only that a client marked something read (ADR-0058 §16).
16
+ // decision into execution → a granted decision reads as work done. Deciding is not doing.
17
+ // commitment into execution → finishing the work discharges the obligation. It does not, unless the
18
+ // profile's discharge conditions are met (ADR-0058 §15) — which is why
19
+ // `claim-fulfilment` and `discharge` are two states with two signers.
20
+ // interaction into case → concluding a conversation silently voids what was promised in it.
21
+ //
22
+ // NONE OF THESE MACHINES IS AUTHORITY. They record what a situation IS, never what a party MAY do.
23
+ // A transition being legal here says nothing about whether the actor was permitted to make it —
24
+ // that is `delegation` + `entitlements` + `tool-policy`, re-evaluated at the moment of acting
25
+ // (ADR-0041, ADR-0043). The role checks below are integrity checks on the record's own shape
26
+ // ("the creditor releases their own claim"), not permission grants.
27
+ const INBOX_TRANSITIONS = {
28
+ 'mark-read': { from: ['unread', 'archived'], to: 'read' },
29
+ // Reversible on purpose: marking unread is a UI affordance, and a machine that forbade it would push
30
+ // clients into tracking read state somewhere this machine could not see.
31
+ 'mark-unread': { from: ['read', 'archived'], to: 'unread' },
32
+ archive: { from: ['unread', 'read'], to: 'archived' },
33
+ restore: { from: ['archived', 'deleted'], to: 'read' },
34
+ delete: { from: ['unread', 'read', 'archived'], to: 'deleted' },
35
+ };
36
+ /**
37
+ * Only the viewer moves their own inbox state.
38
+ *
39
+ * `deleted` is a tombstone, not an erasure: `restore` can bring it back, and the exchange itself is
40
+ * untouched. One participant deleting their copy must never remove the record other participants and
41
+ * the audit trail depend on.
42
+ */
43
+ export function applyInboxTransition(entry, event) {
44
+ if (event.actor !== entry.viewer)
45
+ return { ok: false, reason: 'unauthorized-actor' };
46
+ const spec = INBOX_TRANSITIONS[event.transition];
47
+ if (!spec)
48
+ return { ok: false, reason: 'invalid-transition' };
49
+ if (!spec.from.includes(entry.state))
50
+ return { ok: false, reason: 'invalid-transition' };
51
+ return { ok: true, next: { ...entry, state: spec.to, updatedAt: event.at } };
52
+ }
53
+ export const TERMINAL_INTERACTION_STATES = ['concluded', 'abandoned'];
54
+ const INTERACTION_TRANSITIONS = {
55
+ open: { from: ['forming'], to: 'active', custodialOnly: false },
56
+ suspend: { from: ['active'], to: 'suspended', custodialOnly: true },
57
+ resume: { from: ['suspended'], to: 'active', custodialOnly: true },
58
+ conclude: { from: ['active', 'suspended'], to: 'concluded', custodialOnly: true },
59
+ abandon: { from: ['forming', 'active', 'suspended'], to: 'abandoned', custodialOnly: true },
60
+ };
61
+ /**
62
+ * Ending an interaction is CUSTODIAL — the principal, not any participant. A counterparty who could
63
+ * conclude a negotiation could end it the moment it stopped favouring them.
64
+ *
65
+ * Concluding does NOT touch commitments. That separation is the entire reason this machine and the
66
+ * commitment machine are distinct: otherwise closing a conversation quietly voids what was promised
67
+ * in it, and the party who benefits from that is exactly the party who closes it.
68
+ */
69
+ export function applyInteractionTransition(lifecycle, event) {
70
+ const spec = INTERACTION_TRANSITIONS[event.transition];
71
+ if (!spec)
72
+ return { ok: false, reason: 'invalid-transition' };
73
+ if (TERMINAL_INTERACTION_STATES.includes(lifecycle.state))
74
+ return { ok: false, reason: 'terminal-state' };
75
+ if (!spec.from.includes(lifecycle.state))
76
+ return { ok: false, reason: 'invalid-transition' };
77
+ if (spec.custodialOnly) {
78
+ if (event.actor !== lifecycle.principal)
79
+ return { ok: false, reason: 'unauthorized-actor' };
80
+ }
81
+ else {
82
+ const isParticipant = lifecycle.participations.some((p) => p.agent === event.actor && p.leftAt === undefined);
83
+ if (!isParticipant && event.actor !== lifecycle.principal)
84
+ return { ok: false, reason: 'unauthorized-actor' };
85
+ }
86
+ return { ok: true, next: { ...lifecycle, state: spec.to, updatedAt: event.at } };
87
+ }
88
+ export const TERMINAL_DECISION_STATES = [
89
+ 'refused', 'withdrawn', 'expired', 'superseded',
90
+ ];
91
+ const DECISION_TRANSITIONS = {
92
+ grant: { from: ['pending'], to: 'granted' },
93
+ refuse: { from: ['pending'], to: 'refused' },
94
+ // A GRANT may be withdrawn; a refusal may not be "un-refused" into nothing — reversing a refusal is
95
+ // a NEW decision, so the trail shows both rather than one mutable verdict.
96
+ withdraw: { from: ['pending', 'granted'], to: 'withdrawn' },
97
+ expire: { from: ['pending', 'granted'], to: 'expired' },
98
+ supersede: { from: ['pending', 'granted'], to: 'superseded' },
99
+ };
100
+ /** Only the decider moves their own decision. `expire` is the exception: time is not an actor, so any
101
+ * party may record that the deadline passed, and only once it actually has. */
102
+ export function applyDecisionTransition(decision, event) {
103
+ if (event.subject !== undefined && event.subject !== decision.subject) {
104
+ return { ok: false, reason: 'wrong-subject' };
105
+ }
106
+ const spec = DECISION_TRANSITIONS[event.transition];
107
+ if (!spec)
108
+ return { ok: false, reason: 'invalid-transition' };
109
+ if (!spec.from.includes(decision.state)) {
110
+ return { ok: false, reason: TERMINAL_DECISION_STATES.includes(decision.state) ? 'terminal-state' : 'invalid-transition' };
111
+ }
112
+ if (event.transition === 'expire') {
113
+ if (decision.expiresAt === undefined || Date.parse(event.at) < Date.parse(decision.expiresAt)) {
114
+ return { ok: false, reason: 'invalid-transition' };
115
+ }
116
+ }
117
+ else if (event.actor !== decision.decider) {
118
+ return { ok: false, reason: 'unauthorized-actor' };
119
+ }
120
+ return {
121
+ ok: true,
122
+ next: {
123
+ ...decision,
124
+ state: spec.to,
125
+ decidedAt: spec.to === 'granted' || spec.to === 'refused' ? event.at : decision.decidedAt,
126
+ updatedAt: event.at,
127
+ },
128
+ };
129
+ }
130
+ export const TERMINAL_COMMITMENT_STATES = ['discharged', 'breached', 'void'];
131
+ const COMMITMENT_TRANSITIONS = {
132
+ // Activation follows a VALID, authorized Accept. This machine records that it happened; it does not
133
+ // judge the acceptance — acceptance by an unauthorized party creates nothing, and the check for that
134
+ // lives in the authority layer, which is why no amount of calling `activate` here can substitute.
135
+ activate: { from: ['proposed'], to: 'active', signers: ['creditor'] },
136
+ 'claim-fulfilment': { from: ['active'], to: 'fulfilment-claimed', signers: ['debtor'] },
137
+ 'dispute-claim': { from: ['fulfilment-claimed'], to: 'active', signers: ['creditor'] },
138
+ discharge: { from: ['active', 'fulfilment-claimed'], to: 'discharged', signers: ['creditor'] },
139
+ 'assert-breach': { from: ['active', 'fulfilment-claimed'], to: 'breached', signers: ['creditor'] },
140
+ // Only the creditor voids: giving up your own claim is yours to do; cancelling what you owe is not.
141
+ void: { from: ['proposed', 'active'], to: 'void', signers: ['creditor'] },
142
+ };
143
+ export function applyCommitmentTransition(commitment, event) {
144
+ const spec = COMMITMENT_TRANSITIONS[event.transition];
145
+ if (!spec)
146
+ return { ok: false, reason: 'invalid-transition' };
147
+ if (TERMINAL_COMMITMENT_STATES.includes(commitment.state))
148
+ return { ok: false, reason: 'terminal-state' };
149
+ if (!spec.from.includes(commitment.state))
150
+ return { ok: false, reason: 'invalid-transition' };
151
+ const parties = new Set();
152
+ if (event.actor === commitment.debtor)
153
+ parties.add('debtor');
154
+ if (event.actor === commitment.creditor)
155
+ parties.add('creditor');
156
+ if (!spec.signers.some((p) => parties.has(p)))
157
+ return { ok: false, reason: 'unauthorized-actor' };
158
+ return { ok: true, next: { ...commitment, state: spec.to, updatedAt: event.at } };
159
+ }
160
+ /**
161
+ * Whether finishing the work discharges the obligation.
162
+ *
163
+ * The answer is NO unless the profile says otherwise, and this function exists so that answer has a
164
+ * name a caller can find instead of an assumption a caller can make. A profile MAY declare
165
+ * auto-discharge for obligations whose fulfilment is objectively observable (a payment settling); it
166
+ * MUST NOT for anything requiring the creditor's judgement, which is most things.
167
+ *
168
+ * There is no code path from an execution event to a commitment transition. That is deliberate: the
169
+ * link has to be written by a profile that chose it, so the choice appears in a diff.
170
+ */
171
+ export function mayDischargeOnExecution(profile) {
172
+ return profile.autoDischargeOnExecution === true;
173
+ }
174
+ //# sourceMappingURL=interaction-machines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interaction-machines.js","sourceRoot":"","sources":["../src/interaction-machines.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import type { Performative } from './communicative-act.js';
2
+ import { type ProfileVersion } from './interaction-record.js';
3
+ export interface InteractionProfileV1 {
4
+ version: 'ap.interaction-profile.v1';
5
+ /** `<name>/<semver>` — the string every Exchange in this interaction pins. */
6
+ profileVersion: ProfileVersion;
7
+ /** Human-readable purpose. Documentation, never dispatched on. */
8
+ purpose: string;
9
+ /** Role names this profile defines. Roles live HERE and not in a substrate-wide enum: a role has no
10
+ * meaning outside the interaction kind that defines it, and enumerating them centrally would
11
+ * rebuild the frozen taxonomy profiles exist to replace. */
12
+ roles: readonly string[];
13
+ /** Acts permitted in this interaction. An act outside the set is refused — not because it is
14
+ * forbidden behaviour, but because a Conversation containing an ACCEPT has no defined meaning. */
15
+ permittedActs: readonly Performative[];
16
+ /** `ContextReferenceV1.kind`s every Exchange in this interaction MUST pin. Empty is legitimate: a
17
+ * plain conversation genuinely evaluates nothing, and demanding a delegation ref would be theatre. */
18
+ requiredContextKinds: readonly string[];
19
+ /** Which acts may CREATE a normative obligation. Empty means this interaction cannot produce one,
20
+ * which is true of most of them and worth stating rather than leaving to inference. */
21
+ commitmentCreatingActs: readonly Performative[];
22
+ /** Whether completing execution discharges an obligation. Defaults to false everywhere; see
23
+ * `mayDischargeOnExecution`. Set true ONLY where fulfilment is objectively observable. */
24
+ autoDischargeOnExecution?: boolean;
25
+ /** The close reasons this profile recognizes. A profile that cannot name why it ended forces every
26
+ * distinct ending into one "closed", and the difference between declined and expired is the
27
+ * difference between a party's decision and the passage of time. */
28
+ closeReasons: readonly string[];
29
+ }
30
+ export type ProfileViolation = {
31
+ reason: 'profile-version-mismatch';
32
+ pinned: string;
33
+ expected: ProfileVersion;
34
+ } | {
35
+ reason: 'malformed-profile-version';
36
+ value: string;
37
+ } | {
38
+ reason: 'act-not-permitted';
39
+ act: Performative;
40
+ } | {
41
+ reason: 'missing-required-context';
42
+ kind: string;
43
+ } | {
44
+ reason: 'commitment-from-non-creating-act';
45
+ act: Performative;
46
+ };
47
+ /** The subject of a profile check — deliberately structural, so a caller can validate a move BEFORE
48
+ * building a full record rather than only after. */
49
+ export interface ExchangeUnderProfile {
50
+ profileVersion: string;
51
+ acts: readonly Performative[];
52
+ contextKinds: readonly string[];
53
+ /** Set when this exchange claims to create an obligation. */
54
+ createsCommitment?: boolean;
55
+ }
56
+ /**
57
+ * Every violation, not the first.
58
+ *
59
+ * A caller fixing one at a time needs N round trips to learn the exchange was never valid, and the
60
+ * usual outcome of that is a caller who stops checking.
61
+ */
62
+ export declare function checkExchangeAgainstProfile(profile: InteractionProfileV1, exchange: ExchangeUnderProfile): readonly ProfileViolation[];
63
+ /** Plain conversation. Creates no obligations, requires no context — and saying so explicitly is the
64
+ * point: the overwhelming majority of exchanges are this, and they should not carry ceremony. */
65
+ export declare const DIRECT_PROFILE: InteractionProfileV1;
66
+ /** Terms are proposed, countered and accepted. The only profile in this starter set where an ACCEPT
67
+ * can create an obligation, which is exactly why ACCEPT is not in the others. */
68
+ export declare const NEGOTIATION_PROFILE: InteractionProfileV1;
69
+ /** A question routed to a member and answered. `structured-only` by construction: the permitted acts
70
+ * contain no PROPOSE, so a consultation cannot quietly become a negotiation. */
71
+ export declare const CONSULTATION_PROFILE: InteractionProfileV1;
72
+ /**
73
+ * Spec 336's pre-task provider qualification, expressed as a profile of this model rather than as a
74
+ * parallel one. This is the profile mechanism's actual test: an existing, independently-designed
75
+ * chain either fits or it does not.
76
+ *
77
+ * IT MOSTLY FITS, AND WHERE IT DOES NOT, THE FINDING IS REAL — see `ENGAGEMENT_RESPONSE_KIND_AXES`
78
+ * below. `requiredContextKinds` is `['intent-projection']` because §3.1's rule is that an offer binds
79
+ * to the projection the provider REVIEWED, not to undisclosed facts in the intent; an engagement
80
+ * exchange that pins no projection cannot later be checked against what was actually disclosed.
81
+ *
82
+ * `commitmentCreatingActs` is EMPTY, and that is the load-bearing line. Nine of the chain's ten steps
83
+ * grant nothing; only the Mandate authorizes, and a Mandate is issued by `delegation`, not created by
84
+ * an act in this interaction. An engagement that could mint an obligation would be spec 336's central
85
+ * claim undone by its own profile.
86
+ */
87
+ export declare const ENGAGEMENT_PROFILE: InteractionProfileV1;
88
+ /**
89
+ * An org topic — the first profile that describes something already in production (spec 340 W11).
90
+ *
91
+ * Org topics were an Interaction in everything but name: the org SA owns the board, members join and
92
+ * leave, `facilitator`/`contributor` are its roles, and it opens and closes. This profile names that
93
+ * rather than building anything new.
94
+ *
95
+ * `commitmentCreatingActs` is empty and `PROPOSE`/`ACCEPT` are absent from the permitted set: a topic
96
+ * is a discussion board. If a negotiation happens in one, it belongs in its own Interaction under the
97
+ * negotiation profile — which is exactly ADR-0058 §14's rule that a thread is promoted only when it
98
+ * acquires an independent property, applied to the case that actually occurs.
99
+ */
100
+ export declare const TOPIC_PROFILE: InteractionProfileV1;
101
+ export declare const PROFILE_LIBRARY: readonly InteractionProfileV1[];
102
+ export declare function profileFor(version: string): InteractionProfileV1 | undefined;
103
+ /**
104
+ * Spec 336 §3.5's six "response kinds" are NOT one axis.
105
+ *
106
+ * Four are performatives — WHAT the act does, its illocutionary force. Two are classifications of the
107
+ * CONTENT an INFORM carries. Modelling all six as one enumeration is the same defect spec 336 itself
108
+ * diagnosed one level up, when it split probe "mode" into three orthogonal axes because one
109
+ * enumeration doing three jobs made ordinary positions unsayable.
110
+ *
111
+ * The consequence if left merged: `human-ux-required` would need a performative of its own, and the
112
+ * scheme would grow a concept per business outcome until it was a catalog — exactly what SKOS act
113
+ * kinds exist to prevent. Keeping the split means a provider saying "I need a human channel" is an
114
+ * INFORM whose content says so, which is what it actually is.
115
+ *
116
+ * This is a finding against spec 336 §3.5, recorded here because the profile is where it surfaced.
117
+ * It changes no wire format: the response kind stays on the content, where it already lives.
118
+ */
119
+ export declare const ENGAGEMENT_RESPONSE_KIND_AXES: Readonly<Record<string, {
120
+ axis: 'performative';
121
+ performative: Performative;
122
+ } | {
123
+ axis: 'content';
124
+ carriedBy: Performative;
125
+ }>>;
126
+ //# sourceMappingURL=interaction-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interaction-profile.d.ts","sourceRoot":"","sources":["../src/interaction-profile.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEhF,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,2BAA2B,CAAC;IACrC,8EAA8E;IAC9E,cAAc,EAAE,cAAc,CAAC;IAC/B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB;;iEAE6D;IAC7D,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB;uGACmG;IACnG,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IACvC;2GACuG;IACvG,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;4FACwF;IACxF,sBAAsB,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD;+FAC2F;IAC3F,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;yEAEqE;IACrE,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,0BAA0B,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,GAChF;IAAE,MAAM,EAAE,2BAA2B,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,MAAM,EAAE,mBAAmB,CAAC;IAAC,GAAG,EAAE,YAAY,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,0BAA0B,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,kCAAkC,CAAC;IAAC,GAAG,EAAE,YAAY,CAAA;CAAE,CAAC;AAEtE;qDACqD;AACrD,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,SAAS,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,oBAAoB,GAC7B,SAAS,gBAAgB,EAAE,CAgC7B;AAID;kGACkG;AAClG,eAAO,MAAM,cAAc,EAAE,oBAS5B,CAAC;AAEF;kFACkF;AAClF,eAAO,MAAM,mBAAmB,EAAE,oBASjC,CAAC;AAEF;iFACiF;AACjF,eAAO,MAAM,oBAAoB,EAAE,oBASlC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,EAAE,oBAkBhC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,EAAE,oBAY3B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,SAAS,oBAAoB,EAM1D,CAAC;AAEF,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAE5E;AAID;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAClD,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,CAepH,CAAC"}