@agenticprimitives/fabric 0.0.0-alpha.1 → 0.0.0-alpha.3

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 (35) hide show
  1. package/dist/messaging/board.d.ts +84 -4
  2. package/dist/messaging/board.d.ts.map +1 -1
  3. package/dist/messaging/board.js +98 -7
  4. package/dist/messaging/board.js.map +1 -1
  5. package/dist/messaging/consult-routing.d.ts +289 -0
  6. package/dist/messaging/consult-routing.d.ts.map +1 -0
  7. package/dist/messaging/consult-routing.js +455 -0
  8. package/dist/messaging/consult-routing.js.map +1 -0
  9. package/dist/messaging/consult.d.ts +158 -0
  10. package/dist/messaging/consult.d.ts.map +1 -0
  11. package/dist/messaging/consult.js +141 -0
  12. package/dist/messaging/consult.js.map +1 -0
  13. package/dist/messaging/directory.d.ts +16 -0
  14. package/dist/messaging/directory.d.ts.map +1 -1
  15. package/dist/messaging/directory.js.map +1 -1
  16. package/dist/messaging/inbox-assistant.d.ts +68 -0
  17. package/dist/messaging/inbox-assistant.d.ts.map +1 -0
  18. package/dist/messaging/inbox-assistant.js +102 -0
  19. package/dist/messaging/inbox-assistant.js.map +1 -0
  20. package/dist/messaging/index.d.ts +6 -3
  21. package/dist/messaging/index.d.ts.map +1 -1
  22. package/dist/messaging/index.js +13 -2
  23. package/dist/messaging/index.js.map +1 -1
  24. package/dist/messaging/types.d.ts +22 -0
  25. package/dist/messaging/types.d.ts.map +1 -1
  26. package/dist/messaging/types.js +15 -1
  27. package/dist/messaging/types.js.map +1 -1
  28. package/dist/messaging/vault-store.d.ts +33 -0
  29. package/dist/messaging/vault-store.d.ts.map +1 -1
  30. package/dist/messaging/vault-store.js +53 -5
  31. package/dist/messaging/vault-store.js.map +1 -1
  32. package/dist/record-catalog.d.ts.map +1 -1
  33. package/dist/record-catalog.js +12 -0
  34. package/dist/record-catalog.js.map +1 -1
  35. package/package.json +8 -8
@@ -1,23 +1,95 @@
1
1
  import type { CanonicalAgentId } from '@agenticprimitives/types';
2
- import type { ConversationDescriptorV1, MessageEnvelopeV1 } from './types.js';
2
+ import type { ContextRefV1, ConversationDescriptorV1, MessageEnvelopeV1 } from './types.js';
3
+ import { type ConsultProvenanceV1 } from './consult.js';
3
4
  export interface ChannelMessageEntryV1 {
4
5
  envelope: MessageEnvelopeV1;
5
6
  authorName: string;
7
+ /** spec 324 §9 acting-agent provenance (spec 327): WHO performed the authoring move when it was
8
+ * not a human session — for org-assistant posts, the org SA (CAIP-10). Absent ⇒ human-session
9
+ * post. Never erased; the UI renders an "agent" badge from it. */
10
+ actor?: CanonicalAgentId;
11
+ /** spec 329 §6 — PROV attribution on a turn-2 synthesis post (consulted agents + the contributing
12
+ * ConsultationIntent record ids). Absent on every non-synthesis post. */
13
+ prov?: ConsultProvenanceV1;
14
+ }
15
+ /** Steward-controlled org-assistant enablement for one topic (spec 327; 318 §8.1 slice — the org's
16
+ * OWN agent, not a participant bot). Handle + display name are captured AT ENABLE TIME so trigger
17
+ * matching and attribution need no per-post chain read (ADR-0012); re-enabling refreshes both
18
+ * after a name rotation. */
19
+ export interface TopicAssistantV1 {
20
+ /** 'mention' — reply only when a post @-mentions the org. 'all' — reply to every member post. */
21
+ trigger: 'mention' | 'all';
22
+ /** Lowercased mention label, e.g. 'grace' for grace.impact — matched as @grace / @grace.impact.
23
+ * Empty ONLY for trigger:'all' (a nameless org cannot be mentioned). */
24
+ mentionHandle: string;
25
+ /** Author display name stamped on assistant posts (org primary name / profile display name). */
26
+ displayName: string;
27
+ enabledBy: string;
28
+ enabledAt: string;
29
+ }
30
+ /** Steward-controlled member ROUTING enablement for one topic (spec 329 §7): the org's assistant
31
+ * may consult opted-in member agents in this topic. Requires the assistant ON (routing is a mode
32
+ * of the 327 assistant, never a second bot); the org-level consult wire (§3.1) is custodied
33
+ * separately at the org's execution point — flag without wire ⇒ routing stays inert. */
34
+ export interface TopicRoutingV1 {
35
+ /** Fan-out K per routed question (1..5, default 3 — spec 329 §4). */
36
+ maxFanout: number;
37
+ enabledBy: string;
38
+ enabledAt: string;
6
39
  }
7
40
  export interface ChannelV1 {
8
41
  descriptor: ConversationDescriptorV1;
9
42
  title: string;
10
43
  createdBy: string;
11
44
  messages: ChannelMessageEntryV1[];
45
+ /** apmsg:participationPolicy — `open` (every org MEMBER automatically participates; derived, never a
46
+ * stored list) or `restricted` (invite-only; `participants` is the projection of accepted
47
+ * DiscussionParticipation situations). Absent ⇒ resolved from legacy `visibility` (public→open,
48
+ * private→restricted); absent both ⇒ open. */
49
+ participationPolicy?: 'open' | 'restricted';
12
50
  visibility?: 'public' | 'private';
13
- /** For a private topic: the member SAs (lowercased 0x) allowed to see/post. The creator is always included. */
51
+ /** For a restricted topic: the PARTICIPANT SAs (lowercased 0x) allowed to see/post — a projection of
52
+ * accepted participations (the creator is always included). Legacy field name `members` kept on the
53
+ * wire; these are discussion PARTICIPANTS, not the org member roster. */
14
54
  members?: string[];
55
+ /** Present ⇔ the org's own agent participates in this topic (spec 327). */
56
+ assistant?: TopicAssistantV1;
57
+ /** Present ⇔ member routing is steward-enabled on this topic (spec 329; requires `assistant`). */
58
+ routing?: TopicRoutingV1;
15
59
  }
16
- /** Can `viewerSa` (0x) see this topic? Public ⇒ always; private ⇒ only if listed in `members`. `isSteward`
17
- * overrides (a steward manages every topic). One mechanism — used by the store list + the UI. */
60
+ /** Resolve a topic's participation policy, mapping the legacy `visibility` wire field
61
+ * (public→open, private→restricted). Absent both ⇒ open (the default + all legacy topics). */
62
+ export declare function channelParticipationPolicy(channel: Pick<ChannelV1, 'participationPolicy' | 'visibility'>): 'open' | 'restricted';
63
+ /** Can `viewerSa` (0x) see this topic? OPEN ⇒ always (every org member; the caller already gated org
64
+ * membership). RESTRICTED ⇒ only listed participants. `isSteward` overrides (a steward/custodian is a
65
+ * facilitator of every topic). One mechanism — used by the store list + the UI. */
18
66
  export declare function canSeeChannel(channel: ChannelV1, viewerSa: string, isSteward?: boolean): boolean;
19
67
  /** Bounded per-channel history in the board doc (projection only — bodies live in the vault). */
20
68
  export declare const BOARD_HISTORY_LIMIT = 200;
69
+ /** Should a just-committed post trigger the topic's org assistant (spec 327 §3)? Pure predicate —
70
+ * the caller supplies the posted body text (it never round-trips through the stored entry, whose
71
+ * body is hash-bound in the vault). False when the assistant is off, when the post is itself
72
+ * agent-authored (`actor` set), or when the author IS the org — the community contextRef, NOT
73
+ * `descriptor.owner` (that is the topic CREATOR) — so the assistant NEVER triggers itself, even
74
+ * in `trigger:'all'` topics. */
75
+ export declare function assistantTrigger(channel: Pick<ChannelV1, 'assistant' | 'descriptor'>, post: {
76
+ from: CanonicalAgentId;
77
+ actor?: CanonicalAgentId;
78
+ bodyText: string;
79
+ }): boolean;
80
+ /** Enable/refresh (`assistant` set) or disable (`assistant` undefined) the org assistant on a topic
81
+ * (mutates the channel on success). Steward gating + audit are the caller's, as with every board
82
+ * mutation. `trigger:'mention'` requires a mention handle — a nameless org cannot be mentioned. */
83
+ export declare function setTopicAssistant(board: ChannelV1[], channelId: string, assistant: TopicAssistantV1 | undefined): BoardResult<{
84
+ channel: ChannelV1;
85
+ }>;
86
+ /** Enable/refresh (`routing` set) or disable (`routing` undefined) member routing on a topic
87
+ * (spec 329 §7). Enabling REQUIRES the 327 assistant to be on (routing is a mode of the
88
+ * assistant's turn); fan-out is clamped fail-closed to the approved 1..5 window. Disabling the
89
+ * ASSISTANT also disables routing transitively (setTopicAssistant clears it below). */
90
+ export declare function setTopicRouting(board: ChannelV1[], channelId: string, routing: TopicRoutingV1 | undefined): BoardResult<{
91
+ channel: ChannelV1;
92
+ }>;
21
93
  export type BoardResult<T> = {
22
94
  ok: true;
23
95
  } & T | {
@@ -33,6 +105,7 @@ export declare function createBoardChannel(board: ChannelV1[], opts: {
33
105
  title: string;
34
106
  createdBy: string;
35
107
  now?: string;
108
+ participationPolicy?: 'open' | 'restricted';
36
109
  visibility?: 'public' | 'private';
37
110
  members?: string[];
38
111
  creatorSa?: string;
@@ -48,6 +121,13 @@ export declare function appendBoardPost(board: ChannelV1[], opts: {
48
121
  authorName: string;
49
122
  bodyText: string;
50
123
  now?: string;
124
+ actor?: CanonicalAgentId;
125
+ /** spec 329 §6 — EXTRA context refs beyond the channel's own (the `routed-consultation` chip on
126
+ * the turn-1 status + turn-2 synthesis). Appended after the descriptor refs, deduped by
127
+ * kind+id; the envelope validator's MAX_CONTEXT_REFS bound still applies (fail-closed). */
128
+ contextRefs?: ContextRefV1[];
129
+ /** spec 329 §6 — PROV attribution stored on the entry (synthesis posts only). */
130
+ prov?: ConsultProvenanceV1;
51
131
  }): Promise<BoardResult<{
52
132
  envelope: MessageEnvelopeV1;
53
133
  }>>;
@@ -1 +1 @@
1
- {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/messaging/board.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAKjE,OAAO,KAAK,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE9E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,wBAAwB,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAGlC,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAClC,+GAA+G;IAC/G,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;kGACkG;AAClG,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,OAAO,CAK9F;AAED,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,CAAC,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E;;6FAE6F;AAC7F,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9K,WAAW,CAAC;IAAE,OAAO,EAAE,SAAS,CAAA;CAAE,CAAC,CA+BrC;AAED;;uFAEuF;AACvF,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtG,OAAO,CAAC,WAAW,CAAC;IAAE,QAAQ,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAAC,CA8BvD"}
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/messaging/board.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,19 @@ import { generateConversationId, generateMessageId, validateMessageEnvelope } fr
2
2
  import { sha256Hex32 } from './hash.js';
3
3
  import { validateConversationDescriptor } from './conversation.js';
4
4
  import { topicBodyResource } from './vault-store.js';
5
- /** Can `viewerSa` (0x) see this topic? Public ⇒ always; private ⇒ only if listed in `members`. `isSteward`
6
- * overrides (a steward manages every topic). One mechanism — used by the store list + the UI. */
5
+ import { ROUTING_FANOUT_DEFAULT, ROUTING_FANOUT_MAX, ROUTING_FANOUT_MIN } from './consult.js';
6
+ /** Resolve a topic's participation policy, mapping the legacy `visibility` wire field
7
+ * (public→open, private→restricted). Absent both ⇒ open (the default + all legacy topics). */
8
+ export function channelParticipationPolicy(channel) {
9
+ if (channel.participationPolicy)
10
+ return channel.participationPolicy;
11
+ return channel.visibility === 'private' ? 'restricted' : 'open';
12
+ }
13
+ /** Can `viewerSa` (0x) see this topic? OPEN ⇒ always (every org member; the caller already gated org
14
+ * membership). RESTRICTED ⇒ only listed participants. `isSteward` overrides (a steward/custodian is a
15
+ * facilitator of every topic). One mechanism — used by the store list + the UI. */
7
16
  export function canSeeChannel(channel, viewerSa, isSteward = false) {
8
- if (channel.visibility !== 'private')
17
+ if (channelParticipationPolicy(channel) === 'open')
9
18
  return true;
10
19
  if (isSteward)
11
20
  return true;
@@ -14,6 +23,82 @@ export function canSeeChannel(channel, viewerSa, isSteward = false) {
14
23
  }
15
24
  /** Bounded per-channel history in the board doc (projection only — bodies live in the vault). */
16
25
  export const BOARD_HISTORY_LIMIT = 200;
26
+ /** Should a just-committed post trigger the topic's org assistant (spec 327 §3)? Pure predicate —
27
+ * the caller supplies the posted body text (it never round-trips through the stored entry, whose
28
+ * body is hash-bound in the vault). False when the assistant is off, when the post is itself
29
+ * agent-authored (`actor` set), or when the author IS the org — the community contextRef, NOT
30
+ * `descriptor.owner` (that is the topic CREATOR) — so the assistant NEVER triggers itself, even
31
+ * in `trigger:'all'` topics. */
32
+ export function assistantTrigger(channel, post) {
33
+ const assistant = channel.assistant;
34
+ if (!assistant)
35
+ return false;
36
+ if (post.actor)
37
+ return false;
38
+ const org = channel.descriptor.contextRefs?.find((r) => r.kind === 'community')?.id?.toLowerCase();
39
+ if (org && String(post.from).toLowerCase().endsWith(org))
40
+ return false;
41
+ if (assistant.trigger === 'all')
42
+ return true;
43
+ const handle = assistant.mentionHandle.trim().toLowerCase();
44
+ if (!handle)
45
+ return false;
46
+ // @handle, optionally with its dotted parent name (@handle.<parent>…) — TLD-agnostic (the parent
47
+ // registry is app config, never package vocabulary — ADR-0021). Case-insensitive, word-bounded
48
+ // (name labels are [a-z0-9-]); a preceding name char (e.g. an email local part) is not a mention.
49
+ const esc = handle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
50
+ const mention = new RegExp(`(?:^|[^a-z0-9-])@${esc}(?:\\.[a-z0-9-]+)*(?![a-z0-9-])`, 'i');
51
+ if (mention.test(post.bodyText))
52
+ return true;
53
+ // `@ask` — the universal, org-agnostic assistant alias: members shouldn't have to remember the
54
+ // org's handle to talk to its assistant. Same word-bounding rules; only meaningful where an
55
+ // assistant is enabled, so it can never mis-route across orgs.
56
+ return ASK_ALIAS.test(post.bodyText);
57
+ }
58
+ const ASK_ALIAS = /(?:^|[^a-z0-9-])@ask(?![a-z0-9-])/i;
59
+ /** Enable/refresh (`assistant` set) or disable (`assistant` undefined) the org assistant on a topic
60
+ * (mutates the channel on success). Steward gating + audit are the caller's, as with every board
61
+ * mutation. `trigger:'mention'` requires a mention handle — a nameless org cannot be mentioned. */
62
+ export function setTopicAssistant(board, channelId, assistant) {
63
+ const channel = board.find((c) => c.descriptor.id === channelId);
64
+ if (!channel)
65
+ return { ok: false, error: 'unknown channel' };
66
+ if (!assistant) {
67
+ delete channel.assistant;
68
+ // spec 329 §8 — assistant off ⇒ routing off transitively (routing is a mode of the assistant).
69
+ delete channel.routing;
70
+ return { ok: true, channel };
71
+ }
72
+ const mentionHandle = assistant.mentionHandle.trim().toLowerCase();
73
+ if (assistant.trigger === 'mention' && !mentionHandle) {
74
+ return { ok: false, error: 'mention trigger requires the org to have a primary name' };
75
+ }
76
+ if (!assistant.displayName.trim())
77
+ return { ok: false, error: 'displayName required' };
78
+ channel.assistant = { ...assistant, mentionHandle };
79
+ return { ok: true, channel };
80
+ }
81
+ /** Enable/refresh (`routing` set) or disable (`routing` undefined) member routing on a topic
82
+ * (spec 329 §7). Enabling REQUIRES the 327 assistant to be on (routing is a mode of the
83
+ * assistant's turn); fan-out is clamped fail-closed to the approved 1..5 window. Disabling the
84
+ * ASSISTANT also disables routing transitively (setTopicAssistant clears it below). */
85
+ export function setTopicRouting(board, channelId, routing) {
86
+ const channel = board.find((c) => c.descriptor.id === channelId);
87
+ if (!channel)
88
+ return { ok: false, error: 'unknown channel' };
89
+ if (!routing) {
90
+ delete channel.routing;
91
+ return { ok: true, channel };
92
+ }
93
+ if (!channel.assistant)
94
+ return { ok: false, error: 'routing requires the topic assistant to be enabled first' };
95
+ const raw = Number(routing.maxFanout);
96
+ const maxFanout = Number.isFinite(raw)
97
+ ? Math.min(Math.max(Math.round(raw), ROUTING_FANOUT_MIN), ROUTING_FANOUT_MAX)
98
+ : ROUTING_FANOUT_DEFAULT;
99
+ channel.routing = { ...routing, maxFanout };
100
+ return { ok: true, channel };
101
+ }
17
102
  /** Create a channel on the board (mutates `board` on success). Title-unique per context.
18
103
  * `contextId` is the org/context SA (substrate vocabulary — spec 322 §5; the wire literal
19
104
  * `kind:'community'` is inside signed hashes and renames only at 316's envelope re-cut). */
@@ -24,7 +109,8 @@ export function createBoardChannel(board, opts) {
24
109
  if (board.some((c) => c.title.toLowerCase() === title.toLowerCase())) {
25
110
  return { ok: false, error: 'a channel with this title already exists' };
26
111
  }
27
- const isPrivate = opts.visibility === 'private';
112
+ // New callers say participationPolicy; legacy callers say visibility. restricted ≡ private.
113
+ const isPrivate = opts.participationPolicy ? opts.participationPolicy === 'restricted' : opts.visibility === 'private';
28
114
  const descriptor = {
29
115
  version: 'ap.conversation.v1',
30
116
  id: generateConversationId(),
@@ -40,12 +126,14 @@ export function createBoardChannel(board, opts) {
40
126
  const errors = validateConversationDescriptor(descriptor);
41
127
  if (errors.length > 0)
42
128
  return { ok: false, error: `invalid channel: ${errors.join(', ')}` };
43
- // The creator is always a member of a private topic; dedupe + lowercase.
129
+ // The creator is always a participant of a restricted topic; dedupe + lowercase.
44
130
  const members = isPrivate
45
131
  ? [...new Set([opts.creatorSa?.toLowerCase(), ...(opts.members ?? []).map((m) => m.toLowerCase())].filter((m) => !!m))]
46
132
  : undefined;
47
133
  const channel = {
48
134
  descriptor, title, createdBy: opts.createdBy, messages: [],
135
+ // Dual-write: participationPolicy is the vocabulary; visibility stays for legacy readers.
136
+ participationPolicy: isPrivate ? 'restricted' : 'open',
49
137
  ...(isPrivate ? { visibility: 'private', members } : {}),
50
138
  };
51
139
  board.push(channel);
@@ -63,6 +151,9 @@ export async function appendBoardPost(board, opts) {
63
151
  return { ok: false, error: 'unknown channel' };
64
152
  const now = opts.now ?? new Date().toISOString();
65
153
  const messageId = generateMessageId();
154
+ const baseRefs = channel.descriptor.contextRefs ?? [];
155
+ const extraRefs = (opts.contextRefs ?? []).filter((r) => !baseRefs.some((b) => b.kind === r.kind && b.id === r.id));
156
+ const contextRefs = [...baseRefs, ...extraRefs];
66
157
  const envelope = {
67
158
  version: 'ap.message.v1',
68
159
  id: messageId,
@@ -76,12 +167,12 @@ export async function appendBoardPost(board, opts) {
76
167
  body: { resource: topicBodyResource(channel.descriptor.id, messageId), classification: 'internal', updatedAt: now },
77
168
  bodyHash: await sha256Hex32(new TextEncoder().encode(bodyText)),
78
169
  bodyContentType: 'text/plain',
79
- contextRefs: channel.descriptor.contextRefs,
170
+ contextRefs,
80
171
  };
81
172
  const errors = validateMessageEnvelope(envelope);
82
173
  if (errors.length > 0)
83
174
  return { ok: false, error: `invalid post: ${errors.join(', ')}` };
84
- channel.messages.push({ envelope, authorName: opts.authorName });
175
+ channel.messages.push({ envelope, authorName: opts.authorName, ...(opts.actor ? { actor: opts.actor } : {}), ...(opts.prov ? { prov: opts.prov } : {}) });
85
176
  if (channel.messages.length > BOARD_HISTORY_LIMIT) {
86
177
  channel.messages.splice(0, channel.messages.length - BOARD_HISTORY_LIMIT);
87
178
  }
@@ -1 +1 @@
1
- {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/messaging/board.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/messaging/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,289 @@
1
+ import { consultGrantRecordKey, type ConsultAnswerV1, type ConsultProvenanceV1, type ConsultRequestV1, type ConsultationIntentV1 } from './consult.js';
2
+ import { type ChannelV1 } from './board.js';
3
+ /** Org-DO pending-consult ring key (spec 329 §4.1). */
4
+ export declare const routingPendingKey: (topicId: string, questionId: string) => string;
5
+ /** ConsultationIntent description-record key (spec 329 §5) — one per consulted member. */
6
+ export declare const consultationIntentKey: (questionId: string, memberSA: string) => string;
7
+ /** One row of the org's directory as the eligibility filter consumes it (already gate-verified by
8
+ * the execution point; `current` is the isListingCurrent verdict at read time). */
9
+ export interface ConsultRosterRowV1 {
10
+ /** Listing subject (CAIP-10 or 0x). */
11
+ subject: string;
12
+ displayName: string;
13
+ /** The aporg:consultable listing HINT (spec 329 §2.2). Absent ⇒ false. */
14
+ consultable?: boolean;
15
+ /** The member's self-asserted PRIMARY ROLE in THIS org (spec 329 §12), from their signed
16
+ * listing — e.g. 'tax advisor'. Absent ⇒ no role asserted (never inferred). */
17
+ orgRole?: string;
18
+ current: boolean;
19
+ }
20
+ export interface EligibleConsultMemberV1 {
21
+ /** Lowercased 0x member SA. */
22
+ memberSA: string;
23
+ displayName: string;
24
+ /** spec 329 §12 — the listing-sourced org role, carried through ranking to the candidate. */
25
+ orgRole?: string;
26
+ }
27
+ /**
28
+ * roster ∩ topic participants ∩ consultable-hinted ∩ grant-present. Fail-closed on consent from
29
+ * BOTH directions (spec 329 §2.2): flag without grant ⇒ excluded; grant without flag ⇒ excluded.
30
+ * Restricted topics consult `canSeeChannel` participants only (a member is never asked about a
31
+ * conversation they cannot see); the org itself is never a candidate (org agents are not
32
+ * consultable — §4 loop prevention).
33
+ */
34
+ export declare function eligibleConsultMembers(args: {
35
+ roster: ConsultRosterRowV1[];
36
+ channel: Pick<ChannelV1, 'participationPolicy' | 'visibility' | 'members'>;
37
+ /** Member SAs (lowercased 0x) with a PRESENT consultability grant in the org's grant store. */
38
+ grantMembers: string[];
39
+ /** The org SA (0x) — excluded structurally. */
40
+ orgSA: string;
41
+ }): EligibleConsultMemberV1[];
42
+ /** The public discovery facets one candidate enriches with (ADR-0040 public tier only — the
43
+ * demo-discovery-mcp `/agent` projection). All optional; missing facets mean fewer signals. */
44
+ export interface ConsultCandidateFacetsV1 {
45
+ name?: string | null;
46
+ displayName?: string | null;
47
+ description?: string | null;
48
+ /** `atl:skills` public assertion (spec 282), comma-joined. Post-spec-331 this carries canonical
49
+ * CAPABILITY IDS, not free text. */
50
+ skills?: string | null;
51
+ /** Spec 331 — the capability ids parsed out of `skills` by discovery. `[]` = declared nothing
52
+ * structured; that is an answer, never a wildcard. */
53
+ capabilityIds?: string[];
54
+ /** Spec 331 — the three public facet predicates, comma-joined as published on chain.
55
+ * languages = BCP-47 lowercase; regions = ISO 3166 / GeoFeatureRegistry uppercase;
56
+ * focusAreas = open subject labels (soft boost ONLY, never a filter). */
57
+ languages?: string | null;
58
+ regions?: string | null;
59
+ focusAreas?: string | null;
60
+ facets?: string[];
61
+ shaclConforms?: boolean;
62
+ registered?: boolean;
63
+ /** Discovery agent kind, when known (e.g. 'person' | 'org'). Org-kind candidates are DROPPED —
64
+ * person agents only (spec 329 §4 depth-1 rule). */
65
+ kind?: string | null;
66
+ /** Claimed-capability tier (capability-architecture.md §2 `aps:claimsCapability`) — the capability ids
67
+ * this member is BOTH declared for AND INDEPENDENTLY endorsed for. The abuse rules (self-endorsement
68
+ * ignored, volume deduped by issuer, same-org discounted, staleness decayed) are ALREADY applied by the
69
+ * discovery transport that reads the raw attestations (demo-a2a discovery-facets), so this list is the
70
+ * clean, trustworthy signal: an id here means "an independent third party vouched, and the subject also
71
+ * claims it". The pure scorer never re-derives it — one policy, computed where the raw data lives. */
72
+ endorsedCapabilityIds?: string[];
73
+ /** DISTINCT non-self issuers of valid endorsements (self + volume already collapsed). Corroboration. */
74
+ independentEndorsers?: number;
75
+ }
76
+ /** One surfaced candidate (the apdisc:MatchCandidate shape, flattened): score + evidence path. */
77
+ export interface ConsultCandidateV1 {
78
+ memberSA: string;
79
+ displayName: string;
80
+ /** Discovery handle (the `name` facet, e.g. 'alice.impact'), when known. */
81
+ handle?: string;
82
+ /** spec 329 §12 — the member's self-asserted PRIMARY ROLE in this org, sourced from their SIGNED
83
+ * listing (NOT from discovery): a question addressing a role ("@ask tax advisor …") selects the
84
+ * candidate(s) holding it, ahead of a generic skill match. Absent ⇒ none asserted; the routed
85
+ * turn must then fall back to published skills (never invent a role). Survives degraded mode —
86
+ * it is roster-sourced, so discovery being unreachable does not erase it. */
87
+ orgRole?: string;
88
+ /** The candidate's PUBLISHED `atl:skills` labels (spec 282, parsed from the comma-joined public
89
+ * assertion). Empty ⇒ none published OR none readable — `enriched` says which (spec 329 §4:
90
+ * the routed turn matches the question's subject against THESE; an empty list must be stated
91
+ * explicitly so the model never hallucinates expertise). */
92
+ skills: string[];
93
+ /** 0..1 — `0.6·fit + 0.4·trust` (spec 281). 0 in degraded (un-enriched) mode. */
94
+ score: number;
95
+ /** Whether discovery facets informed this candidate (false ⇒ roster-only signals). */
96
+ enriched: boolean;
97
+ /** Human-readable evidence citations (audit + attribution basis). */
98
+ evidence: string[];
99
+ satisfiedMandates: string[];
100
+ /** Spec 331 — the capability ids this member declared (empty ⇒ none published/none readable). */
101
+ capabilityIds?: string[];
102
+ /** How many needed capability ids matched (exact + specialization). Tie-break + audit. */
103
+ capabilityHits?: number;
104
+ /** How many requested region codes matched. A BOOST and a tie-break — never a filter. */
105
+ regionHits?: number;
106
+ /** True ⇒ this candidate's fit rests on lexical matching alone, because the question resolved to
107
+ * no capability id. Surfaced so "it still passes for the old reason" is visible, not silent. */
108
+ lexicalOnly?: boolean;
109
+ /** Claimed-capability tier — the requested capability ids this member is both declared for AND
110
+ * independently endorsed for (the ones the endorsement boost fired on). Surfaced for the UI/evidence. */
111
+ endorsedCapabilityIds?: string[];
112
+ }
113
+ export interface ConsultRankingV1 {
114
+ /** False ⇔ discovery was unreachable — the un-enriched, un-ranked eligible set (spec 329 §4
115
+ * degraded mode: fail-open to fewer signals, NEVER to more candidates). */
116
+ enriched: boolean;
117
+ candidates: ConsultCandidateV1[];
118
+ droppedByMandates: number;
119
+ }
120
+ /** A question resolved into structured need (spec 331 §4.1). Every field optional: a caller with no
121
+ * catalog supplies none and the matcher degrades to the lexical fallback — VISIBLY, via evidence. */
122
+ export interface StructuredNeedV1 {
123
+ /** Canonical capability ids the question resolved to. */
124
+ capabilityIds?: string[];
125
+ /** Their descendants in the catalog DAG, pre-expanded by the caller (downward walk only). */
126
+ specializationIds?: string[];
127
+ /** Uppercase region codes the question named. */
128
+ regions?: string[];
129
+ /** BCP-47 tags the question named. */
130
+ languages?: string[];
131
+ /** Focus-area labels the question named. */
132
+ focusAreas?: string[];
133
+ }
134
+ /**
135
+ * Rank the ELIGIBLE set (spec 281 verbatim: mandates filter, `0.6·fit + 0.4·trust` scores,
136
+ * top-`max` surfaced with evidence). `facets === null` ⇒ discovery unreachable ⇒ degraded mode:
137
+ * the eligible set passes through un-ranked with `enriched:false`. A candidate discovery does not
138
+ * know keeps its consent-derived seat (fewer signals, never fewer rights) but ranks below enriched
139
+ * peers and is exempt from skill mandates it cannot prove or disprove — eligibility (consent) was
140
+ * already settled structurally.
141
+ */
142
+ export declare function rankConsultCandidates(args: {
143
+ eligible: EligibleConsultMemberV1[];
144
+ facets: Record<string, ConsultCandidateFacetsV1> | null;
145
+ need: string;
146
+ /** requireSkill mandates (spec 281 hard filters) — applied only to enriched candidates. */
147
+ skillHints?: string[];
148
+ /** Spec 331 — the question resolved into structured need. Omit it and ranking is exactly the
149
+ * pre-migration lexical behaviour, so adoption is incremental rather than a flag day. */
150
+ structured?: StructuredNeedV1;
151
+ max?: number;
152
+ }): ConsultRankingV1;
153
+ /**
154
+ * May THIS trigger offer the routing tools (find_members / ask_member)? False unless the topic's
155
+ * routing flag AND assistant are on, the org consult wire is custodied, and the triggering post is
156
+ * HUMAN-authored — an actor-marked (agent-authored) post can NEVER re-trigger routing, which with
157
+ * the consult handler's empty routing toolset makes consults depth-1 by construction.
158
+ */
159
+ export declare function routingToolsAllowed(args: {
160
+ routing: unknown;
161
+ assistant: unknown;
162
+ wirePresent: boolean;
163
+ triggerActor?: string | null;
164
+ }): boolean;
165
+ /** How the routed turn actually ended (the harness's own counters — never planner claims). */
166
+ export interface RoutedTurnStateV1 {
167
+ /** Did post_topic_message commit a reply this dispatch? */
168
+ posted: boolean;
169
+ /** Consults actually submitted (ask_member successes). */
170
+ askedCount: number;
171
+ /** The run's terminal outcome ('failed' also covers a thrown routed attempt). */
172
+ outcome: 'completed' | 'failed';
173
+ error?: string;
174
+ }
175
+ export type RoutedTurnDegradeV1 =
176
+ /** Reply posted — nothing to repair (`cause` present iff routed residue failed after the post: audit-only). */
177
+ {
178
+ action: 'none';
179
+ cause?: string;
180
+ }
181
+ /** Consults ARE in flight but no reply landed ⇒ the harness posts the deterministic honest
182
+ * status itself (determinism by construction — turn 2 will follow up). */
183
+ | {
184
+ action: 'post-status';
185
+ cause: string;
186
+ }
187
+ /** Nothing posted, nothing asked ⇒ degrade to the plain spec-327 single-tool turn
188
+ * (routing inert for this dispatch, never a dead turn). */
189
+ | {
190
+ action: 'plain-turn';
191
+ cause: string;
192
+ };
193
+ /** The degrade verdict for a finished (or thrown) ROUTED turn. Fail-closed toward the member:
194
+ * every branch ends with a posted reply. */
195
+ export declare function routedTurnDegrade(s: RoutedTurnStateV1): RoutedTurnDegradeV1;
196
+ /** Build the ConsultRequestV1 the org puts on the task rail, clipping question + tail to the
197
+ * member-side parse bounds so what is sent IS what the member's gate accepts. */
198
+ export declare function buildConsultRequest(args: {
199
+ question: string;
200
+ orgSA: string;
201
+ topicId: string;
202
+ questionId: string;
203
+ topicTitle?: string;
204
+ tail?: Array<{
205
+ author: string;
206
+ bodyText: string;
207
+ }>;
208
+ }): ConsultRequestV1;
209
+ /** Build the drafted→expressed ConsultationIntent description record (spec 329 §5). */
210
+ export declare function buildConsultationIntentRecord(args: {
211
+ questionId: string;
212
+ orgSA: string;
213
+ memberSA: string;
214
+ topicId: string;
215
+ timeoutMs?: number;
216
+ now?: string;
217
+ }): ConsultationIntentV1;
218
+ export type ConsultOutcomeStatus = 'answered' | 'declined' | 'timedOut' | 'failed' | 'revoked';
219
+ /** One consulted member's terminal outcome, as the synthesis turn consumes it. */
220
+ export interface ConsultOutcomeV1 {
221
+ memberSA: string;
222
+ displayName: string;
223
+ status: ConsultOutcomeStatus;
224
+ /** Present iff status === 'answered' (the validated ConsultAnswer body). */
225
+ answer?: ConsultAnswerV1;
226
+ }
227
+ export interface ConsultAttributionV1 {
228
+ /** Everyone consulted (display names, ask order). */
229
+ consulted: string[];
230
+ /** Whose answers contributed to the synthesis. */
231
+ contributed: string[];
232
+ declined: string[];
233
+ timedOut: string[];
234
+ failed: string[];
235
+ /** Revoked mid-flight (spec 329 W4 rule: their answer is discarded, attribution says so). */
236
+ revoked: string[];
237
+ }
238
+ /** Deterministic attribution buckets — the synthesis post + audit derive from THIS, never from
239
+ * planner output (the LLM words the reply; the harness owns who-said-what). */
240
+ export declare function consultAttribution(outcomes: ConsultOutcomeV1[]): ConsultAttributionV1;
241
+ /** PROV fields for the synthesis post (spec 329 §6): every consulted agent, derived-from ONLY the
242
+ * contributing answers' ConsultationIntent record ids. */
243
+ export declare function buildConsultProvenance(questionId: string, outcomes: ConsultOutcomeV1[]): ConsultProvenanceV1;
244
+ /** The harness-read context block the synthesis goal embeds (answers quoted WITH names — the
245
+ * approved quoting decision; non-answers stated plainly so the model can attribute honestly). */
246
+ export declare function synthesisOutcomeLines(outcomes: ConsultOutcomeV1[]): string;
247
+ /** The deterministic (rule-based) synthesis body — exact attribution, no model required. */
248
+ export declare function deterministicSynthesisBody(question: string, outcomes: ConsultOutcomeV1[]): string;
249
+ /** The one-phrase SELECTION BASIS for a candidate (spec 329 §4 skill-based auto-selection):
250
+ * the turn-1 status post and the goal's candidate lines both state WHY a member is (or may be)
251
+ * consulted — published capabilities when they exist, and the honest lesser basis when they don't.
252
+ * Prose says CAPABILITY (capability-architecture.md §1); the `skills` field name is the legacy
253
+ * `atl:skills` projection key and is immutable. */
254
+ export declare function consultSelectionBasis(c: Pick<ConsultCandidateV1, 'skills' | 'enriched' | 'orgRole' | 'endorsedCapabilityIds'>, matchedRole?: boolean): string;
255
+ /** One compact goal line per candidate — published skills FIRST (the model matches the question's
256
+ * subject against these), an EXPLICIT no-skills marker (never hallucinated expertise), then the
257
+ * ranking-evidence hint. */
258
+ /**
259
+ * Render a published capability for a HUMAN: `adv:succession-plan-design` → "succession plan
260
+ * design". Presentation only — the id string is the identity and is never rewritten (ADR-0051's
261
+ * prose/key split: the prose says "capability", the key stays exactly as published).
262
+ *
263
+ * This is a pure transform on the CURIE, deliberately NOT a catalog lookup: the catalog is a
264
+ * downstream domain artifact and this package must not depend on one. A canonical prefLabel would
265
+ * read slightly better; a substrate dependency on an advisory vocabulary would cost much more than
266
+ * that is worth. A token that is not CURIE-shaped (a legacy free-text label) passes through
267
+ * untouched.
268
+ */
269
+ export declare function humanizeCapability(id: string): string;
270
+ export declare function consultCandidateLine(c: ConsultCandidateV1): string;
271
+ /**
272
+ * Does the question ADDRESS this candidate's org role (spec 329 §12)? Pure, deterministic, and
273
+ * conservative: a normalized substring match of the asserted role phrase in the question
274
+ * ("@ask tax advisor …", "ask our tax advisor about …" both hit "tax advisor"). Used by the
275
+ * DETERMINISTIC (no-LLM) routed turn to state an honest basis; the LLM turn does its own matching
276
+ * under ROUTING_CONTRACT. No role asserted ⇒ false (a role is never inferred from skills).
277
+ */
278
+ export declare function questionAddressesRole(question: string, orgRole: string | undefined): boolean;
279
+ /** The deterministic turn-1 status body — the honest "asking N members" post (spec 329 §4.1).
280
+ * Entries may carry a selection `basis` (see consultSelectionBasis), rendered in parentheses:
281
+ * "Asking 1 member's agent (alice (published skills: water systems)) — …". Plain strings keep
282
+ * the pre-329-§4 shape. */
283
+ export declare function deterministicStatusBody(members: Array<string | {
284
+ displayName: string;
285
+ basis?: string;
286
+ }>): string;
287
+ /** Re-export the grant-store key so execution points scanning eligibility import ONE name. */
288
+ export { consultGrantRecordKey };
289
+ //# sourceMappingURL=consult-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consult-routing.d.ts","sourceRoot":"","sources":["../../src/messaging/consult-routing.ts"],"names":[],"mappings":"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"}