@contractspec/example.policy-safe-knowledge-assistant 1.57.0 → 1.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.turbo/turbo-build.log +58 -60
  2. package/.turbo/turbo-prebuild.log +1 -0
  3. package/CHANGELOG.md +41 -0
  4. package/dist/browser/docs/index.js +38 -0
  5. package/dist/browser/docs/policy-safe-knowledge-assistant.docblock.js +38 -0
  6. package/dist/browser/example.js +37 -0
  7. package/dist/browser/handlers/index.js +334 -0
  8. package/dist/browser/handlers/policy-safe-knowledge-assistant.handlers.js +334 -0
  9. package/dist/browser/index.js +917 -0
  10. package/dist/browser/orchestrator/buildAnswer.js +73 -0
  11. package/dist/browser/policy-safe-knowledge-assistant.feature.js +57 -0
  12. package/dist/browser/seed/fixtures.js +35 -0
  13. package/dist/browser/seed/index.js +35 -0
  14. package/dist/browser/seeders/index.js +12 -0
  15. package/dist/browser/ui/PolicySafeKnowledgeAssistantDashboard.js +420 -0
  16. package/dist/browser/ui/hooks/usePolicySafeKnowledgeAssistant.js +154 -0
  17. package/dist/browser/ui/index.js +420 -0
  18. package/dist/docs/index.d.ts +2 -1
  19. package/dist/docs/index.d.ts.map +1 -0
  20. package/dist/docs/index.js +39 -1
  21. package/dist/docs/policy-safe-knowledge-assistant.docblock.d.ts +2 -1
  22. package/dist/docs/policy-safe-knowledge-assistant.docblock.d.ts.map +1 -0
  23. package/dist/docs/policy-safe-knowledge-assistant.docblock.js +37 -33
  24. package/dist/example.d.ts +2 -6
  25. package/dist/example.d.ts.map +1 -1
  26. package/dist/example.js +36 -51
  27. package/dist/handlers/index.d.ts +2 -2
  28. package/dist/handlers/index.d.ts.map +1 -0
  29. package/dist/handlers/index.js +334 -2
  30. package/dist/handlers/policy-safe-knowledge-assistant.handlers.d.ts +124 -121
  31. package/dist/handlers/policy-safe-knowledge-assistant.handlers.d.ts.map +1 -1
  32. package/dist/handlers/policy-safe-knowledge-assistant.handlers.js +325 -254
  33. package/dist/index.d.ts +11 -8
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +918 -10
  36. package/dist/integration.test.d.ts +2 -0
  37. package/dist/integration.test.d.ts.map +1 -0
  38. package/dist/node/docs/index.js +38 -0
  39. package/dist/node/docs/policy-safe-knowledge-assistant.docblock.js +38 -0
  40. package/dist/node/example.js +37 -0
  41. package/dist/node/handlers/index.js +334 -0
  42. package/dist/node/handlers/policy-safe-knowledge-assistant.handlers.js +334 -0
  43. package/dist/node/index.js +917 -0
  44. package/dist/node/orchestrator/buildAnswer.js +73 -0
  45. package/dist/node/policy-safe-knowledge-assistant.feature.js +57 -0
  46. package/dist/node/seed/fixtures.js +35 -0
  47. package/dist/node/seed/index.js +35 -0
  48. package/dist/node/seeders/index.js +12 -0
  49. package/dist/node/ui/PolicySafeKnowledgeAssistantDashboard.js +420 -0
  50. package/dist/node/ui/hooks/usePolicySafeKnowledgeAssistant.js +154 -0
  51. package/dist/node/ui/index.js +420 -0
  52. package/dist/orchestrator/buildAnswer.d.ts +40 -42
  53. package/dist/orchestrator/buildAnswer.d.ts.map +1 -1
  54. package/dist/orchestrator/buildAnswer.js +72 -75
  55. package/dist/policy-safe-knowledge-assistant.feature.d.ts +1 -6
  56. package/dist/policy-safe-knowledge-assistant.feature.d.ts.map +1 -1
  57. package/dist/policy-safe-knowledge-assistant.feature.js +56 -148
  58. package/dist/seed/fixtures.d.ts +28 -31
  59. package/dist/seed/fixtures.d.ts.map +1 -1
  60. package/dist/seed/fixtures.js +35 -33
  61. package/dist/seed/index.d.ts +2 -2
  62. package/dist/seed/index.d.ts.map +1 -0
  63. package/dist/seed/index.js +36 -3
  64. package/dist/seeders/index.d.ts +4 -8
  65. package/dist/seeders/index.d.ts.map +1 -1
  66. package/dist/seeders/index.js +11 -14
  67. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.d.ts +1 -6
  68. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.d.ts.map +1 -1
  69. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.js +415 -225
  70. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts +49 -51
  71. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts.map +1 -1
  72. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.js +147 -185
  73. package/dist/ui/index.d.ts +2 -2
  74. package/dist/ui/index.d.ts.map +1 -0
  75. package/dist/ui/index.js +420 -2
  76. package/package.json +173 -44
  77. package/tsdown.config.js +1 -2
  78. package/.turbo/turbo-build$colon$bundle.log +0 -60
  79. package/dist/docs/policy-safe-knowledge-assistant.docblock.js.map +0 -1
  80. package/dist/example.js.map +0 -1
  81. package/dist/handlers/policy-safe-knowledge-assistant.handlers.js.map +0 -1
  82. package/dist/orchestrator/buildAnswer.js.map +0 -1
  83. package/dist/policy-safe-knowledge-assistant.feature.js.map +0 -1
  84. package/dist/seed/fixtures.js.map +0 -1
  85. package/dist/seeders/index.js.map +0 -1
  86. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.js.map +0 -1
  87. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.js.map +0 -1
  88. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,154 @@
1
+ // src/ui/hooks/usePolicySafeKnowledgeAssistant.ts
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+ import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
4
+ "use client";
5
+ function isCitationLike(value) {
6
+ if (!value || typeof value !== "object")
7
+ return false;
8
+ const v = value;
9
+ return typeof v.kbSnapshotId === "string" && typeof v.sourceId === "string";
10
+ }
11
+ function toCitations(value) {
12
+ if (!Array.isArray(value))
13
+ return [];
14
+ return value.filter(isCitationLike).map((c) => ({
15
+ kbSnapshotId: c.kbSnapshotId,
16
+ sourceId: c.sourceId,
17
+ excerpt: c.excerpt
18
+ }));
19
+ }
20
+ function usePolicySafeKnowledgeAssistant() {
21
+ const { handlers, projectId } = useTemplateRuntime();
22
+ const api = handlers.policySafeKnowledgeAssistant;
23
+ const [state, setState] = useState({
24
+ context: null,
25
+ loading: true,
26
+ error: null,
27
+ lastAnswer: null,
28
+ lastRuleId: null,
29
+ lastRuleVersionId: null,
30
+ lastSnapshotId: null,
31
+ lastReviewTaskId: null
32
+ });
33
+ const refreshContext = useCallback(async () => {
34
+ try {
35
+ setState((s) => ({ ...s, loading: true, error: null }));
36
+ const ctx = await api.getUserContext({ projectId });
37
+ setState((s) => ({
38
+ ...s,
39
+ context: {
40
+ locale: ctx.locale,
41
+ jurisdiction: ctx.jurisdiction,
42
+ allowedScope: ctx.allowedScope,
43
+ kbSnapshotId: ctx.kbSnapshotId
44
+ },
45
+ loading: false
46
+ }));
47
+ } catch (e) {
48
+ setState((s) => ({
49
+ ...s,
50
+ loading: false,
51
+ error: e instanceof Error ? e : new Error("Unknown error")
52
+ }));
53
+ }
54
+ }, [api, projectId]);
55
+ useEffect(() => {
56
+ refreshContext();
57
+ }, [refreshContext]);
58
+ const setContext = useCallback(async (input) => {
59
+ const ctx = await api.setUserContext({ projectId, ...input });
60
+ setState((s) => ({
61
+ ...s,
62
+ context: {
63
+ locale: ctx.locale,
64
+ jurisdiction: ctx.jurisdiction,
65
+ allowedScope: ctx.allowedScope,
66
+ kbSnapshotId: ctx.kbSnapshotId
67
+ }
68
+ }));
69
+ }, [api, projectId]);
70
+ const askAssistant = useCallback(async (question) => {
71
+ const answerUnknown = await api.answer({ projectId, question });
72
+ const answer = answerUnknown;
73
+ setState((s) => ({
74
+ ...s,
75
+ lastAnswer: {
76
+ refused: answer.refused,
77
+ refusalReason: answer.refusalReason,
78
+ sections: answer.sections,
79
+ citations: toCitations(answerUnknown.citations)
80
+ }
81
+ }));
82
+ }, [api, projectId]);
83
+ const createDemoRule = useCallback(async () => {
84
+ const rule = await api.createRule({
85
+ projectId,
86
+ jurisdiction: state.context?.jurisdiction ?? "EU",
87
+ topicKey: "tax_reporting"
88
+ });
89
+ setState((s) => ({ ...s, lastRuleId: rule.id }));
90
+ return rule.id;
91
+ }, [api, projectId, state.context?.jurisdiction]);
92
+ const upsertRuleVersion = useCallback(async (input) => {
93
+ const rv = await api.upsertRuleVersion({
94
+ projectId,
95
+ ruleId: input.ruleId,
96
+ content: input.content,
97
+ sourceRefs: [{ sourceDocumentId: "src_demo", excerpt: "demo excerpt" }]
98
+ });
99
+ setState((s) => ({ ...s, lastRuleVersionId: rv.id }));
100
+ return rv.id;
101
+ }, [api, projectId]);
102
+ const approveRuleVersion = useCallback(async (ruleVersionId) => {
103
+ await api.approveRuleVersion({ ruleVersionId, approver: "demo_expert" });
104
+ }, [api]);
105
+ const publishSnapshot = useCallback(async () => {
106
+ const snap = await api.publishSnapshot({
107
+ projectId,
108
+ jurisdiction: state.context?.jurisdiction ?? "EU",
109
+ asOfDate: new Date("2026-02-01T00:00:00.000Z")
110
+ });
111
+ setState((s) => ({ ...s, lastSnapshotId: snap.id }));
112
+ await refreshContext();
113
+ return snap.id;
114
+ }, [api, projectId, refreshContext, state.context?.jurisdiction]);
115
+ const simulateHighRiskChangeAndApprove = useCallback(async (ruleVersionId) => {
116
+ const cand = await api.createChangeCandidate({
117
+ projectId,
118
+ jurisdiction: state.context?.jurisdiction ?? "EU",
119
+ diffSummary: "Simulated change (demo)",
120
+ riskLevel: "high",
121
+ proposedRuleVersionIds: [ruleVersionId]
122
+ });
123
+ const review = await api.createReviewTask({ changeCandidateId: cand.id });
124
+ setState((s) => ({ ...s, lastReviewTaskId: review.id }));
125
+ await api.submitDecision({
126
+ reviewTaskId: review.id,
127
+ decision: "approve",
128
+ decidedByRole: "expert",
129
+ decidedBy: "demo_expert"
130
+ });
131
+ await api.publishIfReady({
132
+ jurisdiction: state.context?.jurisdiction ?? "EU"
133
+ });
134
+ return review.id;
135
+ }, [api, projectId, state.context?.jurisdiction]);
136
+ const derived = useMemo(() => ({ projectId }), [projectId]);
137
+ return {
138
+ state,
139
+ derived,
140
+ actions: {
141
+ refreshContext,
142
+ setContext,
143
+ askAssistant,
144
+ createDemoRule,
145
+ upsertRuleVersion,
146
+ approveRuleVersion,
147
+ publishSnapshot,
148
+ simulateHighRiskChangeAndApprove
149
+ }
150
+ };
151
+ }
152
+ export {
153
+ usePolicySafeKnowledgeAssistant
154
+ };
@@ -0,0 +1,420 @@
1
+ // src/ui/hooks/usePolicySafeKnowledgeAssistant.ts
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+ import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
4
+ "use client";
5
+ function isCitationLike(value) {
6
+ if (!value || typeof value !== "object")
7
+ return false;
8
+ const v = value;
9
+ return typeof v.kbSnapshotId === "string" && typeof v.sourceId === "string";
10
+ }
11
+ function toCitations(value) {
12
+ if (!Array.isArray(value))
13
+ return [];
14
+ return value.filter(isCitationLike).map((c) => ({
15
+ kbSnapshotId: c.kbSnapshotId,
16
+ sourceId: c.sourceId,
17
+ excerpt: c.excerpt
18
+ }));
19
+ }
20
+ function usePolicySafeKnowledgeAssistant() {
21
+ const { handlers, projectId } = useTemplateRuntime();
22
+ const api = handlers.policySafeKnowledgeAssistant;
23
+ const [state, setState] = useState({
24
+ context: null,
25
+ loading: true,
26
+ error: null,
27
+ lastAnswer: null,
28
+ lastRuleId: null,
29
+ lastRuleVersionId: null,
30
+ lastSnapshotId: null,
31
+ lastReviewTaskId: null
32
+ });
33
+ const refreshContext = useCallback(async () => {
34
+ try {
35
+ setState((s) => ({ ...s, loading: true, error: null }));
36
+ const ctx = await api.getUserContext({ projectId });
37
+ setState((s) => ({
38
+ ...s,
39
+ context: {
40
+ locale: ctx.locale,
41
+ jurisdiction: ctx.jurisdiction,
42
+ allowedScope: ctx.allowedScope,
43
+ kbSnapshotId: ctx.kbSnapshotId
44
+ },
45
+ loading: false
46
+ }));
47
+ } catch (e) {
48
+ setState((s) => ({
49
+ ...s,
50
+ loading: false,
51
+ error: e instanceof Error ? e : new Error("Unknown error")
52
+ }));
53
+ }
54
+ }, [api, projectId]);
55
+ useEffect(() => {
56
+ refreshContext();
57
+ }, [refreshContext]);
58
+ const setContext = useCallback(async (input) => {
59
+ const ctx = await api.setUserContext({ projectId, ...input });
60
+ setState((s) => ({
61
+ ...s,
62
+ context: {
63
+ locale: ctx.locale,
64
+ jurisdiction: ctx.jurisdiction,
65
+ allowedScope: ctx.allowedScope,
66
+ kbSnapshotId: ctx.kbSnapshotId
67
+ }
68
+ }));
69
+ }, [api, projectId]);
70
+ const askAssistant = useCallback(async (question) => {
71
+ const answerUnknown = await api.answer({ projectId, question });
72
+ const answer = answerUnknown;
73
+ setState((s) => ({
74
+ ...s,
75
+ lastAnswer: {
76
+ refused: answer.refused,
77
+ refusalReason: answer.refusalReason,
78
+ sections: answer.sections,
79
+ citations: toCitations(answerUnknown.citations)
80
+ }
81
+ }));
82
+ }, [api, projectId]);
83
+ const createDemoRule = useCallback(async () => {
84
+ const rule = await api.createRule({
85
+ projectId,
86
+ jurisdiction: state.context?.jurisdiction ?? "EU",
87
+ topicKey: "tax_reporting"
88
+ });
89
+ setState((s) => ({ ...s, lastRuleId: rule.id }));
90
+ return rule.id;
91
+ }, [api, projectId, state.context?.jurisdiction]);
92
+ const upsertRuleVersion = useCallback(async (input) => {
93
+ const rv = await api.upsertRuleVersion({
94
+ projectId,
95
+ ruleId: input.ruleId,
96
+ content: input.content,
97
+ sourceRefs: [{ sourceDocumentId: "src_demo", excerpt: "demo excerpt" }]
98
+ });
99
+ setState((s) => ({ ...s, lastRuleVersionId: rv.id }));
100
+ return rv.id;
101
+ }, [api, projectId]);
102
+ const approveRuleVersion = useCallback(async (ruleVersionId) => {
103
+ await api.approveRuleVersion({ ruleVersionId, approver: "demo_expert" });
104
+ }, [api]);
105
+ const publishSnapshot = useCallback(async () => {
106
+ const snap = await api.publishSnapshot({
107
+ projectId,
108
+ jurisdiction: state.context?.jurisdiction ?? "EU",
109
+ asOfDate: new Date("2026-02-01T00:00:00.000Z")
110
+ });
111
+ setState((s) => ({ ...s, lastSnapshotId: snap.id }));
112
+ await refreshContext();
113
+ return snap.id;
114
+ }, [api, projectId, refreshContext, state.context?.jurisdiction]);
115
+ const simulateHighRiskChangeAndApprove = useCallback(async (ruleVersionId) => {
116
+ const cand = await api.createChangeCandidate({
117
+ projectId,
118
+ jurisdiction: state.context?.jurisdiction ?? "EU",
119
+ diffSummary: "Simulated change (demo)",
120
+ riskLevel: "high",
121
+ proposedRuleVersionIds: [ruleVersionId]
122
+ });
123
+ const review = await api.createReviewTask({ changeCandidateId: cand.id });
124
+ setState((s) => ({ ...s, lastReviewTaskId: review.id }));
125
+ await api.submitDecision({
126
+ reviewTaskId: review.id,
127
+ decision: "approve",
128
+ decidedByRole: "expert",
129
+ decidedBy: "demo_expert"
130
+ });
131
+ await api.publishIfReady({
132
+ jurisdiction: state.context?.jurisdiction ?? "EU"
133
+ });
134
+ return review.id;
135
+ }, [api, projectId, state.context?.jurisdiction]);
136
+ const derived = useMemo(() => ({ projectId }), [projectId]);
137
+ return {
138
+ state,
139
+ derived,
140
+ actions: {
141
+ refreshContext,
142
+ setContext,
143
+ askAssistant,
144
+ createDemoRule,
145
+ upsertRuleVersion,
146
+ approveRuleVersion,
147
+ publishSnapshot,
148
+ simulateHighRiskChangeAndApprove
149
+ }
150
+ };
151
+ }
152
+
153
+ // src/ui/PolicySafeKnowledgeAssistantDashboard.tsx
154
+ import { useCallback as useCallback2, useMemo as useMemo2, useState as useState2 } from "react";
155
+ import {
156
+ Button,
157
+ ErrorState,
158
+ LoaderBlock,
159
+ StatCard,
160
+ StatCardGroup
161
+ } from "@contractspec/lib.design-system";
162
+ import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
163
+ import { Input } from "@contractspec/lib.ui-kit-web/ui/input";
164
+ import { Textarea } from "@contractspec/lib.ui-kit-web/ui/textarea";
165
+ import {
166
+ Select,
167
+ SelectContent,
168
+ SelectItem,
169
+ SelectTrigger,
170
+ SelectValue
171
+ } from "@contractspec/lib.ui-kit-web/ui/select";
172
+ import { jsxDEV } from "react/jsx-dev-runtime";
173
+ "use client";
174
+ function PolicySafeKnowledgeAssistantDashboard() {
175
+ const { state, actions } = usePolicySafeKnowledgeAssistant();
176
+ const [question, setQuestion] = useState2("reporting obligations");
177
+ const [content, setContent] = useState2("EU: Reporting obligations v2 (updated)");
178
+ const [locale, setLocale] = useState2("en-GB");
179
+ const [jurisdiction, setJurisdiction] = useState2("EU");
180
+ const [allowedScope, setAllowedScope] = useState2("education_only");
181
+ const snapshotId = state.context?.kbSnapshotId ?? state.lastSnapshotId ?? null;
182
+ const stats = useMemo2(() => {
183
+ return [
184
+ { label: "Locale", value: state.context?.locale ?? "—" },
185
+ { label: "Jurisdiction", value: state.context?.jurisdiction ?? "—" },
186
+ { label: "Scope", value: state.context?.allowedScope ?? "—" },
187
+ { label: "KB Snapshot", value: snapshotId ?? "—" }
188
+ ];
189
+ }, [
190
+ snapshotId,
191
+ state.context?.allowedScope,
192
+ state.context?.jurisdiction,
193
+ state.context?.locale
194
+ ]);
195
+ const handleSetContext = useCallback2(async () => {
196
+ await actions.setContext({ locale, jurisdiction, allowedScope });
197
+ }, [actions, allowedScope, jurisdiction, locale]);
198
+ const handleAsk = useCallback2(async () => {
199
+ await actions.askAssistant(question);
200
+ }, [actions, question]);
201
+ const handleAdminPublishFlow = useCallback2(async () => {
202
+ const ruleId = state.lastRuleId ?? await actions.createDemoRule();
203
+ const rvId = await actions.upsertRuleVersion({ ruleId, content });
204
+ await actions.approveRuleVersion(rvId);
205
+ await actions.simulateHighRiskChangeAndApprove(rvId);
206
+ await actions.publishSnapshot();
207
+ }, [actions, content, state.lastRuleId]);
208
+ if (state.loading && !state.context) {
209
+ return /* @__PURE__ */ jsxDEV(LoaderBlock, {
210
+ label: "Loading demo..."
211
+ }, undefined, false, undefined, this);
212
+ }
213
+ if (state.error) {
214
+ return /* @__PURE__ */ jsxDEV(ErrorState, {
215
+ title: "Failed to load demo",
216
+ description: state.error.message,
217
+ onRetry: actions.refreshContext,
218
+ retryLabel: "Retry"
219
+ }, undefined, false, undefined, this);
220
+ }
221
+ return /* @__PURE__ */ jsxDEV("div", {
222
+ className: "space-y-6",
223
+ children: [
224
+ /* @__PURE__ */ jsxDEV(StatCardGroup, {
225
+ children: stats.map((s) => /* @__PURE__ */ jsxDEV(StatCard, {
226
+ label: s.label,
227
+ value: String(s.value)
228
+ }, s.label, false, undefined, this))
229
+ }, undefined, false, undefined, this),
230
+ /* @__PURE__ */ jsxDEV(Card, {
231
+ className: "p-4",
232
+ children: [
233
+ /* @__PURE__ */ jsxDEV("h3", {
234
+ className: "text-lg font-semibold",
235
+ children: "1) Onboarding (explicit locale + jurisdiction)"
236
+ }, undefined, false, undefined, this),
237
+ /* @__PURE__ */ jsxDEV("div", {
238
+ className: "mt-3 grid gap-3 md:grid-cols-3",
239
+ children: [
240
+ /* @__PURE__ */ jsxDEV("div", {
241
+ children: [
242
+ /* @__PURE__ */ jsxDEV("div", {
243
+ className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase",
244
+ children: "Locale"
245
+ }, undefined, false, undefined, this),
246
+ /* @__PURE__ */ jsxDEV(Input, {
247
+ value: locale,
248
+ onChange: (e) => setLocale(e.target.value)
249
+ }, undefined, false, undefined, this)
250
+ ]
251
+ }, undefined, true, undefined, this),
252
+ /* @__PURE__ */ jsxDEV("div", {
253
+ children: [
254
+ /* @__PURE__ */ jsxDEV("div", {
255
+ className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase",
256
+ children: "Jurisdiction"
257
+ }, undefined, false, undefined, this),
258
+ /* @__PURE__ */ jsxDEV(Input, {
259
+ value: jurisdiction,
260
+ onChange: (e) => setJurisdiction(e.target.value)
261
+ }, undefined, false, undefined, this)
262
+ ]
263
+ }, undefined, true, undefined, this),
264
+ /* @__PURE__ */ jsxDEV("div", {
265
+ children: [
266
+ /* @__PURE__ */ jsxDEV("div", {
267
+ className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase",
268
+ children: "Allowed scope"
269
+ }, undefined, false, undefined, this),
270
+ /* @__PURE__ */ jsxDEV(Select, {
271
+ value: allowedScope,
272
+ onValueChange: (v) => setAllowedScope(v),
273
+ children: [
274
+ /* @__PURE__ */ jsxDEV(SelectTrigger, {
275
+ children: /* @__PURE__ */ jsxDEV(SelectValue, {
276
+ placeholder: "Select scope"
277
+ }, undefined, false, undefined, this)
278
+ }, undefined, false, undefined, this),
279
+ /* @__PURE__ */ jsxDEV(SelectContent, {
280
+ children: [
281
+ /* @__PURE__ */ jsxDEV(SelectItem, {
282
+ value: "education_only",
283
+ children: "education_only"
284
+ }, undefined, false, undefined, this),
285
+ /* @__PURE__ */ jsxDEV(SelectItem, {
286
+ value: "generic_info",
287
+ children: "generic_info"
288
+ }, undefined, false, undefined, this),
289
+ /* @__PURE__ */ jsxDEV(SelectItem, {
290
+ value: "escalation_required",
291
+ children: "escalation_required"
292
+ }, undefined, false, undefined, this)
293
+ ]
294
+ }, undefined, true, undefined, this)
295
+ ]
296
+ }, undefined, true, undefined, this)
297
+ ]
298
+ }, undefined, true, undefined, this)
299
+ ]
300
+ }, undefined, true, undefined, this),
301
+ /* @__PURE__ */ jsxDEV("div", {
302
+ className: "mt-4 flex gap-2",
303
+ children: [
304
+ /* @__PURE__ */ jsxDEV(Button, {
305
+ onPress: handleSetContext,
306
+ children: "Save context"
307
+ }, undefined, false, undefined, this),
308
+ /* @__PURE__ */ jsxDEV(Button, {
309
+ variant: "outline",
310
+ onPress: actions.refreshContext,
311
+ children: "Refresh"
312
+ }, undefined, false, undefined, this)
313
+ ]
314
+ }, undefined, true, undefined, this)
315
+ ]
316
+ }, undefined, true, undefined, this),
317
+ /* @__PURE__ */ jsxDEV(Card, {
318
+ className: "p-4",
319
+ children: [
320
+ /* @__PURE__ */ jsxDEV("h3", {
321
+ className: "text-lg font-semibold",
322
+ children: "2) Ask the assistant (must cite KB snapshot)"
323
+ }, undefined, false, undefined, this),
324
+ /* @__PURE__ */ jsxDEV("div", {
325
+ className: "mt-3 flex flex-col gap-3",
326
+ children: [
327
+ /* @__PURE__ */ jsxDEV(Input, {
328
+ value: question,
329
+ onChange: (e) => setQuestion(e.target.value)
330
+ }, undefined, false, undefined, this),
331
+ /* @__PURE__ */ jsxDEV("div", {
332
+ className: "flex gap-2",
333
+ children: /* @__PURE__ */ jsxDEV(Button, {
334
+ onPress: handleAsk,
335
+ children: "Ask"
336
+ }, undefined, false, undefined, this)
337
+ }, undefined, false, undefined, this)
338
+ ]
339
+ }, undefined, true, undefined, this),
340
+ state.lastAnswer ? /* @__PURE__ */ jsxDEV("div", {
341
+ className: "mt-4 space-y-3",
342
+ children: [
343
+ state.lastAnswer.refused ? /* @__PURE__ */ jsxDEV("div", {
344
+ className: "text-sm text-red-600",
345
+ children: [
346
+ "Refused: ",
347
+ state.lastAnswer.refusalReason ?? "UNKNOWN"
348
+ ]
349
+ }, undefined, true, undefined, this) : null,
350
+ state.lastAnswer.sections.map((s, idx) => /* @__PURE__ */ jsxDEV("div", {
351
+ children: [
352
+ /* @__PURE__ */ jsxDEV("div", {
353
+ className: "text-sm font-semibold",
354
+ children: s.heading
355
+ }, undefined, false, undefined, this),
356
+ /* @__PURE__ */ jsxDEV("div", {
357
+ className: "text-muted-foreground text-sm",
358
+ children: s.body
359
+ }, undefined, false, undefined, this)
360
+ ]
361
+ }, `${s.heading}-${idx}`, true, undefined, this)),
362
+ /* @__PURE__ */ jsxDEV("div", {
363
+ className: "text-sm font-semibold",
364
+ children: "Citations"
365
+ }, undefined, false, undefined, this),
366
+ /* @__PURE__ */ jsxDEV("ul", {
367
+ className: "text-muted-foreground list-disc pl-5 text-sm",
368
+ children: state.lastAnswer.citations.map((c) => /* @__PURE__ */ jsxDEV("li", {
369
+ children: [
370
+ c.kbSnapshotId,
371
+ " — ",
372
+ c.sourceId
373
+ ]
374
+ }, `${c.kbSnapshotId}-${c.sourceId}`, true, undefined, this))
375
+ }, undefined, false, undefined, this)
376
+ ]
377
+ }, undefined, true, undefined, this) : null
378
+ ]
379
+ }, undefined, true, undefined, this),
380
+ /* @__PURE__ */ jsxDEV(Card, {
381
+ className: "p-4",
382
+ children: [
383
+ /* @__PURE__ */ jsxDEV("h3", {
384
+ className: "text-lg font-semibold",
385
+ children: "3) Admin: publish a new snapshot (HITL)"
386
+ }, undefined, false, undefined, this),
387
+ /* @__PURE__ */ jsxDEV("div", {
388
+ className: "mt-3 space-y-3",
389
+ children: [
390
+ /* @__PURE__ */ jsxDEV(Textarea, {
391
+ value: content,
392
+ onChange: (e) => setContent(e.target.value)
393
+ }, undefined, false, undefined, this),
394
+ /* @__PURE__ */ jsxDEV(Button, {
395
+ onPress: handleAdminPublishFlow,
396
+ children: "Simulate change → review → approve → publish snapshot"
397
+ }, undefined, false, undefined, this)
398
+ ]
399
+ }, undefined, true, undefined, this)
400
+ ]
401
+ }, undefined, true, undefined, this),
402
+ /* @__PURE__ */ jsxDEV(Card, {
403
+ className: "p-4",
404
+ children: [
405
+ /* @__PURE__ */ jsxDEV("h3", {
406
+ className: "text-lg font-semibold",
407
+ children: "4) Learning hub (patterns)"
408
+ }, undefined, false, undefined, this),
409
+ /* @__PURE__ */ jsxDEV("p", {
410
+ className: "text-muted-foreground mt-2 text-sm",
411
+ children: "This template includes drills, ambient coach, and quests as reusable Learning Journey tracks. The interactive learning UI is demonstrated in dedicated Learning Journey examples."
412
+ }, undefined, false, undefined, this)
413
+ ]
414
+ }, undefined, true, undefined, this)
415
+ ]
416
+ }, undefined, true, undefined, this);
417
+ }
418
+ export {
419
+ PolicySafeKnowledgeAssistantDashboard
420
+ };
@@ -1,53 +1,51 @@
1
- //#region src/orchestrator/buildAnswer.d.ts
2
1
  type AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';
3
- interface AssistantAnswerIR {
4
- locale: string;
5
- jurisdiction: string;
6
- allowedScope: AllowedScope;
7
- sections: {
8
- heading: string;
9
- body: string;
10
- }[];
11
- citations: {
12
- kbSnapshotId: string;
13
- sourceType: string;
14
- sourceId: string;
15
- title?: string;
16
- excerpt?: string;
17
- }[];
18
- disclaimers?: string[];
19
- riskFlags?: string[];
20
- refused?: boolean;
21
- refusalReason?: string;
22
- }
23
- interface BuildAnswerInput {
24
- envelope: {
25
- traceId: string;
2
+ export interface AssistantAnswerIR {
26
3
  locale: string;
27
- kbSnapshotId: string;
28
- allowedScope: AllowedScope;
29
- regulatoryContext: {
30
- jurisdiction: string;
31
- };
32
- };
33
- question: string;
34
- kbSearch: (input: {
35
- snapshotId: string;
36
4
  jurisdiction: string;
37
- query: string;
38
- }) => Promise<{
39
- items: {
40
- ruleVersionId: string;
41
- excerpt?: string;
5
+ allowedScope: AllowedScope;
6
+ sections: {
7
+ heading: string;
8
+ body: string;
42
9
  }[];
43
- }>;
10
+ citations: {
11
+ kbSnapshotId: string;
12
+ sourceType: string;
13
+ sourceId: string;
14
+ title?: string;
15
+ excerpt?: string;
16
+ }[];
17
+ disclaimers?: string[];
18
+ riskFlags?: string[];
19
+ refused?: boolean;
20
+ refusalReason?: string;
21
+ }
22
+ export interface BuildAnswerInput {
23
+ envelope: {
24
+ traceId: string;
25
+ locale: string;
26
+ kbSnapshotId: string;
27
+ allowedScope: AllowedScope;
28
+ regulatoryContext: {
29
+ jurisdiction: string;
30
+ };
31
+ };
32
+ question: string;
33
+ kbSearch: (input: {
34
+ snapshotId: string;
35
+ jurisdiction: string;
36
+ query: string;
37
+ }) => Promise<{
38
+ items: {
39
+ ruleVersionId: string;
40
+ excerpt?: string;
41
+ }[];
42
+ }>;
44
43
  }
45
44
  /**
46
45
  * Build a policy-safe assistant answer derived from KB search results.
47
46
  *
48
47
  * Deterministic: no LLM calls; if search yields no results, it refuses.
49
48
  */
50
- declare function buildPolicySafeAnswer(input: BuildAnswerInput): Promise<AssistantAnswerIR>;
51
- //#endregion
52
- export { AssistantAnswerIR, BuildAnswerInput, buildPolicySafeAnswer };
49
+ export declare function buildPolicySafeAnswer(input: BuildAnswerInput): Promise<AssistantAnswerIR>;
50
+ export {};
53
51
  //# sourceMappingURL=buildAnswer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildAnswer.d.ts","names":[],"sources":["../../src/orchestrator/buildAnswer.ts"],"mappings":";KAMK,YAAA;AAAA,UAEY,iBAAA;EACf,MAAA;EACA,YAAA;EACA,YAAA,EAAc,YAAA;EACd,QAAA;IAAY,OAAA;IAAiB,IAAA;EAAA;EAC7B,SAAA;IACE,YAAA;IACA,UAAA;IACA,QAAA;IACA,KAAA;IACA,OAAA;EAAA;EAEF,WAAA;EACA,SAAA;EACA,OAAA;EACA,aAAA;AAAA;AAAA,UAGe,gBAAA;EACf,QAAA;IACE,OAAA;IACA,MAAA;IACA,YAAA;IACA,YAAA,EAAc,YAAA;IACd,iBAAA;MAAqB,YAAA;IAAA;EAAA;EAEvB,QAAA;EACA,QAAA,GAAW,KAAA;IACT,UAAA;IACA,YAAA;IACA,KAAA;EAAA,MACI,OAAA;IAAU,KAAA;MAAS,aAAA;MAAuB,OAAA;IAAA;EAAA;AAAA;;;;;;iBAQ5B,qBAAA,CACpB,KAAA,EAAO,gBAAA,GACN,OAAA,CAAQ,iBAAA"}
1
+ {"version":3,"file":"buildAnswer.d.ts","sourceRoot":"","sources":["../../src/orchestrator/buildAnswer.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG,gBAAgB,GAAG,cAAc,GAAG,qBAAqB,CAAC;AAE9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,SAAS,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;IACJ,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,YAAY,CAAC;QAC3B,iBAAiB,EAAE;YAAE,YAAY,EAAE,MAAM,CAAA;SAAE,CAAC;KAC7C,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE;YAAE,aAAa,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC,CAAC;CACzE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CAwE5B"}