@contractspec/example.policy-safe-knowledge-assistant 1.46.1 → 1.48.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 (50) hide show
  1. package/.turbo/turbo-build$colon$bundle.log +50 -30
  2. package/.turbo/turbo-build.log +49 -29
  3. package/CHANGELOG.md +66 -0
  4. package/README.md +7 -8
  5. package/dist/example.d.ts +2 -2
  6. package/dist/example.d.ts.map +1 -1
  7. package/dist/example.js +5 -3
  8. package/dist/example.js.map +1 -1
  9. package/dist/handlers/index.d.ts +2 -0
  10. package/dist/handlers/index.js +3 -0
  11. package/dist/handlers/policy-safe-knowledge-assistant.handlers.d.ts +127 -0
  12. package/dist/handlers/policy-safe-knowledge-assistant.handlers.d.ts.map +1 -0
  13. package/dist/handlers/policy-safe-knowledge-assistant.handlers.js +264 -0
  14. package/dist/handlers/policy-safe-knowledge-assistant.handlers.js.map +1 -0
  15. package/dist/index.d.ts +5 -2
  16. package/dist/index.js +5 -2
  17. package/dist/orchestrator/buildAnswer.js.map +1 -1
  18. package/dist/policy-safe-knowledge-assistant.feature.d.ts +7 -0
  19. package/dist/policy-safe-knowledge-assistant.feature.d.ts.map +1 -0
  20. package/dist/{feature.js → policy-safe-knowledge-assistant.feature.js} +6 -4
  21. package/dist/policy-safe-knowledge-assistant.feature.js.map +1 -0
  22. package/dist/seeders/index.d.ts +10 -0
  23. package/dist/seeders/index.d.ts.map +1 -0
  24. package/dist/seeders/index.js +16 -0
  25. package/dist/seeders/index.js.map +1 -0
  26. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.d.ts +7 -0
  27. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.d.ts.map +1 -0
  28. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.js +231 -0
  29. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.js.map +1 -0
  30. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts +55 -0
  31. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts.map +1 -0
  32. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.js +193 -0
  33. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.js.map +1 -0
  34. package/dist/ui/index.d.ts +2 -0
  35. package/dist/ui/index.js +3 -0
  36. package/package.json +27 -15
  37. package/src/example.ts +4 -4
  38. package/src/handlers/index.ts +1 -0
  39. package/src/handlers/policy-safe-knowledge-assistant.handlers.ts +476 -0
  40. package/src/index.ts +3 -1
  41. package/src/{feature.ts → policy-safe-knowledge-assistant.feature.ts} +3 -3
  42. package/src/seeders/index.ts +20 -0
  43. package/src/ui/PolicySafeKnowledgeAssistantDashboard.tsx +206 -0
  44. package/src/ui/hooks/usePolicySafeKnowledgeAssistant.ts +229 -0
  45. package/src/ui/index.ts +1 -0
  46. package/tsconfig.tsbuildinfo +1 -1
  47. package/IMPLEMENTATION_SKETCH.md +0 -40
  48. package/dist/feature.d.ts +0 -7
  49. package/dist/feature.d.ts.map +0 -1
  50. package/dist/feature.js.map +0 -1
@@ -0,0 +1,231 @@
1
+ 'use client';
2
+
3
+ import { usePolicySafeKnowledgeAssistant } from "./hooks/usePolicySafeKnowledgeAssistant.js";
4
+ import { useCallback, useMemo, useState } from "react";
5
+ import { Button, ErrorState, LoaderBlock, StatCard, StatCardGroup } from "@contractspec/lib.design-system";
6
+ import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
7
+ import { Input } from "@contractspec/lib.ui-kit-web/ui/input";
8
+ import { Textarea } from "@contractspec/lib.ui-kit-web/ui/textarea";
9
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@contractspec/lib.ui-kit-web/ui/select";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+
12
+ //#region src/ui/PolicySafeKnowledgeAssistantDashboard.tsx
13
+ function PolicySafeKnowledgeAssistantDashboard() {
14
+ const { state, actions } = usePolicySafeKnowledgeAssistant();
15
+ const [question, setQuestion] = useState("reporting obligations");
16
+ const [content, setContent] = useState("EU: Reporting obligations v2 (updated)");
17
+ const [locale, setLocale] = useState("en-GB");
18
+ const [jurisdiction, setJurisdiction] = useState("EU");
19
+ const [allowedScope, setAllowedScope] = useState("education_only");
20
+ const snapshotId = state.context?.kbSnapshotId ?? state.lastSnapshotId ?? null;
21
+ const stats = useMemo(() => {
22
+ return [
23
+ {
24
+ label: "Locale",
25
+ value: state.context?.locale ?? "—"
26
+ },
27
+ {
28
+ label: "Jurisdiction",
29
+ value: state.context?.jurisdiction ?? "—"
30
+ },
31
+ {
32
+ label: "Scope",
33
+ value: state.context?.allowedScope ?? "—"
34
+ },
35
+ {
36
+ label: "KB Snapshot",
37
+ value: snapshotId ?? "—"
38
+ }
39
+ ];
40
+ }, [
41
+ snapshotId,
42
+ state.context?.allowedScope,
43
+ state.context?.jurisdiction,
44
+ state.context?.locale
45
+ ]);
46
+ const handleSetContext = useCallback(async () => {
47
+ await actions.setContext({
48
+ locale,
49
+ jurisdiction,
50
+ allowedScope
51
+ });
52
+ }, [
53
+ actions,
54
+ allowedScope,
55
+ jurisdiction,
56
+ locale
57
+ ]);
58
+ const handleAsk = useCallback(async () => {
59
+ await actions.askAssistant(question);
60
+ }, [actions, question]);
61
+ const handleAdminPublishFlow = useCallback(async () => {
62
+ const ruleId = state.lastRuleId ?? await actions.createDemoRule();
63
+ const rvId = await actions.upsertRuleVersion({
64
+ ruleId,
65
+ content
66
+ });
67
+ await actions.approveRuleVersion(rvId);
68
+ await actions.simulateHighRiskChangeAndApprove(rvId);
69
+ await actions.publishSnapshot();
70
+ }, [
71
+ actions,
72
+ content,
73
+ state.lastRuleId
74
+ ]);
75
+ if (state.loading && !state.context) return /* @__PURE__ */ jsx(LoaderBlock, { label: "Loading demo..." });
76
+ if (state.error) return /* @__PURE__ */ jsx(ErrorState, {
77
+ title: "Failed to load demo",
78
+ description: state.error.message,
79
+ onRetry: actions.refreshContext,
80
+ retryLabel: "Retry"
81
+ });
82
+ return /* @__PURE__ */ jsxs("div", {
83
+ className: "space-y-6",
84
+ children: [
85
+ /* @__PURE__ */ jsx(StatCardGroup, { children: stats.map((s) => /* @__PURE__ */ jsx(StatCard, {
86
+ label: s.label,
87
+ value: String(s.value)
88
+ }, s.label)) }),
89
+ /* @__PURE__ */ jsxs(Card, {
90
+ className: "p-4",
91
+ children: [
92
+ /* @__PURE__ */ jsx("h3", {
93
+ className: "text-lg font-semibold",
94
+ children: "1) Onboarding (explicit locale + jurisdiction)"
95
+ }),
96
+ /* @__PURE__ */ jsxs("div", {
97
+ className: "mt-3 grid gap-3 md:grid-cols-3",
98
+ children: [
99
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
100
+ className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase",
101
+ children: "Locale"
102
+ }), /* @__PURE__ */ jsx(Input, {
103
+ value: locale,
104
+ onChange: (e) => setLocale(e.target.value)
105
+ })] }),
106
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
107
+ className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase",
108
+ children: "Jurisdiction"
109
+ }), /* @__PURE__ */ jsx(Input, {
110
+ value: jurisdiction,
111
+ onChange: (e) => setJurisdiction(e.target.value)
112
+ })] }),
113
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
114
+ className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase",
115
+ children: "Allowed scope"
116
+ }), /* @__PURE__ */ jsxs(Select, {
117
+ value: allowedScope,
118
+ onValueChange: (v) => setAllowedScope(v),
119
+ children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select scope" }) }), /* @__PURE__ */ jsxs(SelectContent, { children: [
120
+ /* @__PURE__ */ jsx(SelectItem, {
121
+ value: "education_only",
122
+ children: "education_only"
123
+ }),
124
+ /* @__PURE__ */ jsx(SelectItem, {
125
+ value: "generic_info",
126
+ children: "generic_info"
127
+ }),
128
+ /* @__PURE__ */ jsx(SelectItem, {
129
+ value: "escalation_required",
130
+ children: "escalation_required"
131
+ })
132
+ ] })]
133
+ })] })
134
+ ]
135
+ }),
136
+ /* @__PURE__ */ jsxs("div", {
137
+ className: "mt-4 flex gap-2",
138
+ children: [/* @__PURE__ */ jsx(Button, {
139
+ onPress: handleSetContext,
140
+ children: "Save context"
141
+ }), /* @__PURE__ */ jsx(Button, {
142
+ variant: "outline",
143
+ onPress: actions.refreshContext,
144
+ children: "Refresh"
145
+ })]
146
+ })
147
+ ]
148
+ }),
149
+ /* @__PURE__ */ jsxs(Card, {
150
+ className: "p-4",
151
+ children: [
152
+ /* @__PURE__ */ jsx("h3", {
153
+ className: "text-lg font-semibold",
154
+ children: "2) Ask the assistant (must cite KB snapshot)"
155
+ }),
156
+ /* @__PURE__ */ jsxs("div", {
157
+ className: "mt-3 flex flex-col gap-3",
158
+ children: [/* @__PURE__ */ jsx(Input, {
159
+ value: question,
160
+ onChange: (e) => setQuestion(e.target.value)
161
+ }), /* @__PURE__ */ jsx("div", {
162
+ className: "flex gap-2",
163
+ children: /* @__PURE__ */ jsx(Button, {
164
+ onPress: handleAsk,
165
+ children: "Ask"
166
+ })
167
+ })]
168
+ }),
169
+ state.lastAnswer ? /* @__PURE__ */ jsxs("div", {
170
+ className: "mt-4 space-y-3",
171
+ children: [
172
+ state.lastAnswer.refused ? /* @__PURE__ */ jsxs("div", {
173
+ className: "text-sm text-red-600",
174
+ children: ["Refused: ", state.lastAnswer.refusalReason ?? "UNKNOWN"]
175
+ }) : null,
176
+ state.lastAnswer.sections.map((s, idx) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
177
+ className: "text-sm font-semibold",
178
+ children: s.heading
179
+ }), /* @__PURE__ */ jsx("div", {
180
+ className: "text-muted-foreground text-sm",
181
+ children: s.body
182
+ })] }, `${s.heading}-${idx}`)),
183
+ /* @__PURE__ */ jsx("div", {
184
+ className: "text-sm font-semibold",
185
+ children: "Citations"
186
+ }),
187
+ /* @__PURE__ */ jsx("ul", {
188
+ className: "text-muted-foreground list-disc pl-5 text-sm",
189
+ children: state.lastAnswer.citations.map((c) => /* @__PURE__ */ jsxs("li", { children: [
190
+ c.kbSnapshotId,
191
+ " — ",
192
+ c.sourceId
193
+ ] }, `${c.kbSnapshotId}-${c.sourceId}`))
194
+ })
195
+ ]
196
+ }) : null
197
+ ]
198
+ }),
199
+ /* @__PURE__ */ jsxs(Card, {
200
+ className: "p-4",
201
+ children: [/* @__PURE__ */ jsx("h3", {
202
+ className: "text-lg font-semibold",
203
+ children: "3) Admin: publish a new snapshot (HITL)"
204
+ }), /* @__PURE__ */ jsxs("div", {
205
+ className: "mt-3 space-y-3",
206
+ children: [/* @__PURE__ */ jsx(Textarea, {
207
+ value: content,
208
+ onChange: (e) => setContent(e.target.value)
209
+ }), /* @__PURE__ */ jsx(Button, {
210
+ onPress: handleAdminPublishFlow,
211
+ children: "Simulate change → review → approve → publish snapshot"
212
+ })]
213
+ })]
214
+ }),
215
+ /* @__PURE__ */ jsxs(Card, {
216
+ className: "p-4",
217
+ children: [/* @__PURE__ */ jsx("h3", {
218
+ className: "text-lg font-semibold",
219
+ children: "4) Learning hub (patterns)"
220
+ }), /* @__PURE__ */ jsx("p", {
221
+ className: "text-muted-foreground mt-2 text-sm",
222
+ 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."
223
+ })]
224
+ })
225
+ ]
226
+ });
227
+ }
228
+
229
+ //#endregion
230
+ export { PolicySafeKnowledgeAssistantDashboard };
231
+ //# sourceMappingURL=PolicySafeKnowledgeAssistantDashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicySafeKnowledgeAssistantDashboard.js","names":[],"sources":["../../src/ui/PolicySafeKnowledgeAssistantDashboard.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState } from 'react';\nimport {\n Button,\n ErrorState,\n LoaderBlock,\n StatCard,\n StatCardGroup,\n} from '@contractspec/lib.design-system';\nimport { Card } from '@contractspec/lib.ui-kit-web/ui/card';\nimport { Input } from '@contractspec/lib.ui-kit-web/ui/input';\nimport { Textarea } from '@contractspec/lib.ui-kit-web/ui/textarea';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@contractspec/lib.ui-kit-web/ui/select';\n\nimport { usePolicySafeKnowledgeAssistant } from './hooks/usePolicySafeKnowledgeAssistant';\n\ntype AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';\n\nexport function PolicySafeKnowledgeAssistantDashboard() {\n const { state, actions } = usePolicySafeKnowledgeAssistant();\n const [question, setQuestion] = useState('reporting obligations');\n const [content, setContent] = useState(\n 'EU: Reporting obligations v2 (updated)'\n );\n const [locale, setLocale] = useState('en-GB');\n const [jurisdiction, setJurisdiction] = useState('EU');\n const [allowedScope, setAllowedScope] =\n useState<AllowedScope>('education_only');\n\n const snapshotId =\n state.context?.kbSnapshotId ?? state.lastSnapshotId ?? null;\n\n const stats = useMemo(() => {\n return [\n { label: 'Locale', value: state.context?.locale ?? '—' },\n { label: 'Jurisdiction', value: state.context?.jurisdiction ?? '—' },\n { label: 'Scope', value: state.context?.allowedScope ?? '—' },\n { label: 'KB Snapshot', value: snapshotId ?? '—' },\n ];\n }, [\n snapshotId,\n state.context?.allowedScope,\n state.context?.jurisdiction,\n state.context?.locale,\n ]);\n\n const handleSetContext = useCallback(async () => {\n await actions.setContext({ locale, jurisdiction, allowedScope });\n }, [actions, allowedScope, jurisdiction, locale]);\n\n const handleAsk = useCallback(async () => {\n await actions.askAssistant(question);\n }, [actions, question]);\n\n const handleAdminPublishFlow = useCallback(async () => {\n const ruleId = state.lastRuleId ?? (await actions.createDemoRule());\n const rvId = await actions.upsertRuleVersion({ ruleId, content });\n await actions.approveRuleVersion(rvId);\n await actions.simulateHighRiskChangeAndApprove(rvId);\n await actions.publishSnapshot();\n }, [actions, content, state.lastRuleId]);\n\n if (state.loading && !state.context) {\n return <LoaderBlock label=\"Loading demo...\" />;\n }\n\n if (state.error) {\n return (\n <ErrorState\n title=\"Failed to load demo\"\n description={state.error.message}\n onRetry={actions.refreshContext}\n retryLabel=\"Retry\"\n />\n );\n }\n\n return (\n <div className=\"space-y-6\">\n <StatCardGroup>\n {stats.map((s) => (\n <StatCard key={s.label} label={s.label} value={String(s.value)} />\n ))}\n </StatCardGroup>\n\n <Card className=\"p-4\">\n <h3 className=\"text-lg font-semibold\">\n 1) Onboarding (explicit locale + jurisdiction)\n </h3>\n <div className=\"mt-3 grid gap-3 md:grid-cols-3\">\n <div>\n <div className=\"text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase\">\n Locale\n </div>\n <Input value={locale} onChange={(e) => setLocale(e.target.value)} />\n </div>\n <div>\n <div className=\"text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase\">\n Jurisdiction\n </div>\n <Input\n value={jurisdiction}\n onChange={(e) => setJurisdiction(e.target.value)}\n />\n </div>\n <div>\n <div className=\"text-muted-foreground mb-1 text-xs font-semibold tracking-wide uppercase\">\n Allowed scope\n </div>\n <Select\n value={allowedScope}\n onValueChange={(v) => setAllowedScope(v as AllowedScope)}\n >\n <SelectTrigger>\n <SelectValue placeholder=\"Select scope\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"education_only\">education_only</SelectItem>\n <SelectItem value=\"generic_info\">generic_info</SelectItem>\n <SelectItem value=\"escalation_required\">\n escalation_required\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Button onPress={handleSetContext}>Save context</Button>\n <Button variant=\"outline\" onPress={actions.refreshContext}>\n Refresh\n </Button>\n </div>\n </Card>\n\n <Card className=\"p-4\">\n <h3 className=\"text-lg font-semibold\">\n 2) Ask the assistant (must cite KB snapshot)\n </h3>\n <div className=\"mt-3 flex flex-col gap-3\">\n <Input\n value={question}\n onChange={(e) => setQuestion(e.target.value)}\n />\n <div className=\"flex gap-2\">\n <Button onPress={handleAsk}>Ask</Button>\n </div>\n </div>\n\n {state.lastAnswer ? (\n <div className=\"mt-4 space-y-3\">\n {state.lastAnswer.refused ? (\n <div className=\"text-sm text-red-600\">\n Refused: {state.lastAnswer.refusalReason ?? 'UNKNOWN'}\n </div>\n ) : null}\n {state.lastAnswer.sections.map((s, idx) => (\n <div key={`${s.heading}-${idx}`}>\n <div className=\"text-sm font-semibold\">{s.heading}</div>\n <div className=\"text-muted-foreground text-sm\">{s.body}</div>\n </div>\n ))}\n <div className=\"text-sm font-semibold\">Citations</div>\n <ul className=\"text-muted-foreground list-disc pl-5 text-sm\">\n {state.lastAnswer.citations.map((c) => (\n <li key={`${c.kbSnapshotId}-${c.sourceId}`}>\n {c.kbSnapshotId} — {c.sourceId}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n </Card>\n\n <Card className=\"p-4\">\n <h3 className=\"text-lg font-semibold\">\n 3) Admin: publish a new snapshot (HITL)\n </h3>\n <div className=\"mt-3 space-y-3\">\n <Textarea\n value={content}\n onChange={(e) => setContent(e.target.value)}\n />\n <Button onPress={handleAdminPublishFlow}>\n Simulate change → review → approve → publish snapshot\n </Button>\n </div>\n </Card>\n\n <Card className=\"p-4\">\n <h3 className=\"text-lg font-semibold\">4) Learning hub (patterns)</h3>\n <p className=\"text-muted-foreground mt-2 text-sm\">\n This template includes drills, ambient coach, and quests as reusable\n Learning Journey tracks. The interactive learning UI is demonstrated\n in dedicated Learning Journey examples.\n </p>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ //#region src/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts
2
+ type AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';
3
+ interface UsePolicySafeKnowledgeAssistantState {
4
+ context: {
5
+ locale: string;
6
+ jurisdiction: string;
7
+ allowedScope: AllowedScope;
8
+ kbSnapshotId: string | null;
9
+ } | null;
10
+ loading: boolean;
11
+ error: Error | null;
12
+ lastAnswer: {
13
+ refused?: boolean;
14
+ refusalReason?: string;
15
+ sections: {
16
+ heading: string;
17
+ body: string;
18
+ }[];
19
+ citations: {
20
+ kbSnapshotId: string;
21
+ sourceId: string;
22
+ excerpt?: string;
23
+ }[];
24
+ } | null;
25
+ lastRuleId: string | null;
26
+ lastRuleVersionId: string | null;
27
+ lastSnapshotId: string | null;
28
+ lastReviewTaskId: string | null;
29
+ }
30
+ declare function usePolicySafeKnowledgeAssistant(): {
31
+ state: UsePolicySafeKnowledgeAssistantState;
32
+ derived: {
33
+ projectId: string;
34
+ };
35
+ actions: {
36
+ refreshContext: () => Promise<void>;
37
+ setContext: (input: {
38
+ locale: string;
39
+ jurisdiction: string;
40
+ allowedScope: AllowedScope;
41
+ }) => Promise<void>;
42
+ askAssistant: (question: string) => Promise<void>;
43
+ createDemoRule: () => Promise<string>;
44
+ upsertRuleVersion: (input: {
45
+ ruleId: string;
46
+ content: string;
47
+ }) => Promise<string>;
48
+ approveRuleVersion: (ruleVersionId: string) => Promise<void>;
49
+ publishSnapshot: () => Promise<string>;
50
+ simulateHighRiskChangeAndApprove: (ruleVersionId: string) => Promise<string>;
51
+ };
52
+ };
53
+ //#endregion
54
+ export { UsePolicySafeKnowledgeAssistantState, usePolicySafeKnowledgeAssistant };
55
+ //# sourceMappingURL=usePolicySafeKnowledgeAssistant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePolicySafeKnowledgeAssistant.d.ts","names":[],"sources":["../../../src/ui/hooks/usePolicySafeKnowledgeAssistant.ts"],"sourcesContent":[],"mappings":";KAKK,YAAA;AAAA,UAGY,oCAAA,CAHA;EAGA,OAAA,EAAA;IAsDD,MAAA,EAAA,MAAA;;kBAlDE;IAkGE,YAAA,EAAA,MAAA,GAAA,IAAA;EACf,CAAA,GAAA,IAAA;EAgBsB,OAAA,EAAA,OAAA;SA/GlB;EA4I4C,UAAA,EAAA;IAcrB,OAAA,CAAA,EAAA,OAAA;;IAkBA,QAAA,EAAA;MAAA,OAAA,EAAA,MAAA;;;;;;;;;;;;;;iBA9HhB,+BAAA,CAAA;;;;;;;;;;oBAgDI;UACf;wCAgBsB;;;;;UA6B0B;mDAcrB;;iEAkBA"}
@@ -0,0 +1,193 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useEffect, useMemo, useState } from "react";
4
+ import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
5
+
6
+ //#region src/ui/hooks/usePolicySafeKnowledgeAssistant.ts
7
+ function isCitationLike(value) {
8
+ if (!value || typeof value !== "object") return false;
9
+ const v = value;
10
+ return typeof v.kbSnapshotId === "string" && typeof v.sourceId === "string";
11
+ }
12
+ function toCitations(value) {
13
+ if (!Array.isArray(value)) 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) => ({
36
+ ...s,
37
+ loading: true,
38
+ error: null
39
+ }));
40
+ const ctx = await api.getUserContext({ projectId });
41
+ setState((s) => ({
42
+ ...s,
43
+ context: {
44
+ locale: ctx.locale,
45
+ jurisdiction: ctx.jurisdiction,
46
+ allowedScope: ctx.allowedScope,
47
+ kbSnapshotId: ctx.kbSnapshotId
48
+ },
49
+ loading: false
50
+ }));
51
+ } catch (e) {
52
+ setState((s) => ({
53
+ ...s,
54
+ loading: false,
55
+ error: e instanceof Error ? e : /* @__PURE__ */ new Error("Unknown error")
56
+ }));
57
+ }
58
+ }, [api, projectId]);
59
+ useEffect(() => {
60
+ refreshContext();
61
+ }, [refreshContext]);
62
+ const setContext = useCallback(async (input) => {
63
+ const ctx = await api.setUserContext({
64
+ projectId,
65
+ ...input
66
+ });
67
+ setState((s) => ({
68
+ ...s,
69
+ context: {
70
+ locale: ctx.locale,
71
+ jurisdiction: ctx.jurisdiction,
72
+ allowedScope: ctx.allowedScope,
73
+ kbSnapshotId: ctx.kbSnapshotId
74
+ }
75
+ }));
76
+ }, [api, projectId]);
77
+ const askAssistant = useCallback(async (question) => {
78
+ const answerUnknown = await api.answer({
79
+ projectId,
80
+ question
81
+ });
82
+ const answer = answerUnknown;
83
+ setState((s) => ({
84
+ ...s,
85
+ lastAnswer: {
86
+ refused: answer.refused,
87
+ refusalReason: answer.refusalReason,
88
+ sections: answer.sections,
89
+ citations: toCitations(answerUnknown.citations)
90
+ }
91
+ }));
92
+ }, [api, projectId]);
93
+ const createDemoRule = useCallback(async () => {
94
+ const rule = await api.createRule({
95
+ projectId,
96
+ jurisdiction: state.context?.jurisdiction ?? "EU",
97
+ topicKey: "tax_reporting"
98
+ });
99
+ setState((s) => ({
100
+ ...s,
101
+ lastRuleId: rule.id
102
+ }));
103
+ return rule.id;
104
+ }, [
105
+ api,
106
+ projectId,
107
+ state.context?.jurisdiction
108
+ ]);
109
+ const upsertRuleVersion = useCallback(async (input) => {
110
+ const rv = await api.upsertRuleVersion({
111
+ projectId,
112
+ ruleId: input.ruleId,
113
+ content: input.content,
114
+ sourceRefs: [{
115
+ sourceDocumentId: "src_demo",
116
+ excerpt: "demo excerpt"
117
+ }]
118
+ });
119
+ setState((s) => ({
120
+ ...s,
121
+ lastRuleVersionId: rv.id
122
+ }));
123
+ return rv.id;
124
+ }, [api, projectId]);
125
+ const approveRuleVersion = useCallback(async (ruleVersionId) => {
126
+ await api.approveRuleVersion({
127
+ ruleVersionId,
128
+ approver: "demo_expert"
129
+ });
130
+ }, [api]);
131
+ const publishSnapshot = useCallback(async () => {
132
+ const snap = await api.publishSnapshot({
133
+ projectId,
134
+ jurisdiction: state.context?.jurisdiction ?? "EU",
135
+ asOfDate: /* @__PURE__ */ new Date("2026-02-01T00:00:00.000Z")
136
+ });
137
+ setState((s) => ({
138
+ ...s,
139
+ lastSnapshotId: snap.id
140
+ }));
141
+ await refreshContext();
142
+ return snap.id;
143
+ }, [
144
+ api,
145
+ projectId,
146
+ refreshContext,
147
+ state.context?.jurisdiction
148
+ ]);
149
+ const simulateHighRiskChangeAndApprove = useCallback(async (ruleVersionId) => {
150
+ const cand = await api.createChangeCandidate({
151
+ projectId,
152
+ jurisdiction: state.context?.jurisdiction ?? "EU",
153
+ diffSummary: "Simulated change (demo)",
154
+ riskLevel: "high",
155
+ proposedRuleVersionIds: [ruleVersionId]
156
+ });
157
+ const review = await api.createReviewTask({ changeCandidateId: cand.id });
158
+ setState((s) => ({
159
+ ...s,
160
+ lastReviewTaskId: review.id
161
+ }));
162
+ await api.submitDecision({
163
+ reviewTaskId: review.id,
164
+ decision: "approve",
165
+ decidedByRole: "expert",
166
+ decidedBy: "demo_expert"
167
+ });
168
+ await api.publishIfReady({ jurisdiction: state.context?.jurisdiction ?? "EU" });
169
+ return review.id;
170
+ }, [
171
+ api,
172
+ projectId,
173
+ state.context?.jurisdiction
174
+ ]);
175
+ return {
176
+ state,
177
+ derived: useMemo(() => ({ projectId }), [projectId]),
178
+ actions: {
179
+ refreshContext,
180
+ setContext,
181
+ askAssistant,
182
+ createDemoRule,
183
+ upsertRuleVersion,
184
+ approveRuleVersion,
185
+ publishSnapshot,
186
+ simulateHighRiskChangeAndApprove
187
+ }
188
+ };
189
+ }
190
+
191
+ //#endregion
192
+ export { usePolicySafeKnowledgeAssistant };
193
+ //# sourceMappingURL=usePolicySafeKnowledgeAssistant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePolicySafeKnowledgeAssistant.js","names":[],"sources":["../../../src/ui/hooks/usePolicySafeKnowledgeAssistant.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useTemplateRuntime } from '@contractspec/lib.example-shared-ui';\n\ntype AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';\ntype RiskLevel = 'low' | 'medium' | 'high';\n\nexport interface UsePolicySafeKnowledgeAssistantState {\n context: {\n locale: string;\n jurisdiction: string;\n allowedScope: AllowedScope;\n kbSnapshotId: string | null;\n } | null;\n loading: boolean;\n error: Error | null;\n lastAnswer: {\n refused?: boolean;\n refusalReason?: string;\n sections: { heading: string; body: string }[];\n citations: {\n kbSnapshotId: string;\n sourceId: string;\n excerpt?: string;\n }[];\n } | null;\n lastRuleId: string | null;\n lastRuleVersionId: string | null;\n lastSnapshotId: string | null;\n lastReviewTaskId: string | null;\n}\n\ninterface CitationLike {\n kbSnapshotId: string;\n sourceId: string;\n excerpt?: string;\n}\ninterface AnswerLike {\n refused?: boolean;\n refusalReason?: string;\n sections: { heading: string; body: string }[];\n citations: CitationLike[];\n}\n\nfunction isCitationLike(value: unknown): value is CitationLike {\n if (!value || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return typeof v.kbSnapshotId === 'string' && typeof v.sourceId === 'string';\n}\n\nfunction toCitations(value: unknown): CitationLike[] {\n if (!Array.isArray(value)) return [];\n return value.filter(isCitationLike).map((c) => ({\n kbSnapshotId: c.kbSnapshotId,\n sourceId: c.sourceId,\n excerpt: c.excerpt,\n }));\n}\n\nimport type { PolicySafeKnowledgeAssistantHandlers } from '../../handlers/policy-safe-knowledge-assistant.handlers';\n\nexport function usePolicySafeKnowledgeAssistant() {\n const { handlers, projectId } = useTemplateRuntime<{\n policySafeKnowledgeAssistant: PolicySafeKnowledgeAssistantHandlers;\n }>();\n const api = handlers.policySafeKnowledgeAssistant;\n\n const [state, setState] = useState<UsePolicySafeKnowledgeAssistantState>({\n context: null,\n loading: true,\n error: null,\n lastAnswer: null,\n lastRuleId: null,\n lastRuleVersionId: null,\n lastSnapshotId: null,\n lastReviewTaskId: null,\n });\n\n const refreshContext = useCallback(async () => {\n try {\n setState((s) => ({ ...s, loading: true, error: null }));\n const ctx = await api.getUserContext({ projectId });\n setState((s) => ({\n ...s,\n context: {\n locale: ctx.locale,\n jurisdiction: ctx.jurisdiction,\n allowedScope: ctx.allowedScope,\n kbSnapshotId: ctx.kbSnapshotId,\n },\n loading: false,\n }));\n } catch (e) {\n setState((s) => ({\n ...s,\n loading: false,\n error: e instanceof Error ? e : new Error('Unknown error'),\n }));\n }\n }, [api, projectId]);\n\n useEffect(() => {\n refreshContext();\n }, [refreshContext]);\n\n const setContext = useCallback(\n async (input: {\n locale: string;\n jurisdiction: string;\n allowedScope: AllowedScope;\n }) => {\n const ctx = await api.setUserContext({ projectId, ...input });\n setState((s) => ({\n ...s,\n context: {\n locale: ctx.locale,\n jurisdiction: ctx.jurisdiction,\n allowedScope: ctx.allowedScope,\n kbSnapshotId: ctx.kbSnapshotId,\n },\n }));\n },\n [api, projectId]\n );\n\n const askAssistant = useCallback(\n async (question: string) => {\n const answerUnknown: unknown = await api.answer({ projectId, question });\n const answer = answerUnknown as AnswerLike;\n setState((s) => ({\n ...s,\n lastAnswer: {\n refused: answer.refused,\n refusalReason: answer.refusalReason,\n sections: answer.sections,\n citations: toCitations(\n (answerUnknown as { citations?: unknown }).citations\n ),\n },\n }));\n },\n [api, projectId]\n );\n\n const createDemoRule = useCallback(async () => {\n const rule = await api.createRule({\n projectId,\n jurisdiction: state.context?.jurisdiction ?? 'EU',\n topicKey: 'tax_reporting',\n });\n setState((s) => ({ ...s, lastRuleId: rule.id }));\n return rule.id as string;\n }, [api, projectId, state.context?.jurisdiction]);\n\n const upsertRuleVersion = useCallback(\n async (input: { ruleId: string; content: string }) => {\n const rv = await api.upsertRuleVersion({\n projectId,\n ruleId: input.ruleId,\n content: input.content,\n sourceRefs: [{ sourceDocumentId: 'src_demo', excerpt: 'demo excerpt' }],\n });\n setState((s) => ({ ...s, lastRuleVersionId: rv.id }));\n return rv.id as string;\n },\n [api, projectId]\n );\n\n const approveRuleVersion = useCallback(\n async (ruleVersionId: string) => {\n await api.approveRuleVersion({ ruleVersionId, approver: 'demo_expert' });\n },\n [api]\n );\n\n const publishSnapshot = useCallback(async () => {\n const snap = await api.publishSnapshot({\n projectId,\n jurisdiction: state.context?.jurisdiction ?? 'EU',\n asOfDate: new Date('2026-02-01T00:00:00.000Z'),\n });\n setState((s) => ({ ...s, lastSnapshotId: snap.id }));\n await refreshContext();\n return snap.id as string;\n }, [api, projectId, refreshContext, state.context?.jurisdiction]);\n\n const simulateHighRiskChangeAndApprove = useCallback(\n async (ruleVersionId: string) => {\n const cand = await api.createChangeCandidate({\n projectId,\n jurisdiction: state.context?.jurisdiction ?? 'EU',\n diffSummary: 'Simulated change (demo)',\n riskLevel: 'high' satisfies RiskLevel,\n proposedRuleVersionIds: [ruleVersionId],\n });\n const review = await api.createReviewTask({ changeCandidateId: cand.id });\n setState((s) => ({ ...s, lastReviewTaskId: review.id }));\n await api.submitDecision({\n reviewTaskId: review.id,\n decision: 'approve',\n decidedByRole: 'expert',\n decidedBy: 'demo_expert',\n });\n await api.publishIfReady({\n jurisdiction: state.context?.jurisdiction ?? 'EU',\n });\n return review.id as string;\n },\n [api, projectId, state.context?.jurisdiction]\n );\n\n const derived = useMemo(() => ({ projectId }), [projectId]);\n\n return {\n state,\n derived,\n actions: {\n refreshContext,\n setContext,\n askAssistant,\n createDemoRule,\n upsertRuleVersion,\n approveRuleVersion,\n publishSnapshot,\n simulateHighRiskChangeAndApprove,\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { PolicySafeKnowledgeAssistantDashboard } from "./PolicySafeKnowledgeAssistantDashboard.js";
2
+ export { PolicySafeKnowledgeAssistantDashboard };
@@ -0,0 +1,3 @@
1
+ import { PolicySafeKnowledgeAssistantDashboard } from "./PolicySafeKnowledgeAssistantDashboard.js";
2
+
3
+ export { PolicySafeKnowledgeAssistantDashboard };
package/package.json CHANGED
@@ -1,20 +1,24 @@
1
1
  {
2
2
  "name": "@contractspec/example.policy-safe-knowledge-assistant",
3
- "version": "1.46.1",
3
+ "version": "1.48.0",
4
4
  "description": "All-in-one template example: policy-safe knowledge assistant with locale/jurisdiction gating, versioned KB snapshots, HITL update pipeline, and learning hub.",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
6
  "types": "./dist/index.d.ts",
9
7
  "exports": {
10
8
  ".": "./dist/index.js",
11
9
  "./docs": "./dist/docs/index.js",
12
10
  "./docs/policy-safe-knowledge-assistant.docblock": "./dist/docs/policy-safe-knowledge-assistant.docblock.js",
13
11
  "./example": "./dist/example.js",
14
- "./feature": "./dist/feature.js",
12
+ "./handlers": "./dist/handlers/index.js",
13
+ "./handlers/policy-safe-knowledge-assistant.handlers": "./dist/handlers/policy-safe-knowledge-assistant.handlers.js",
15
14
  "./orchestrator/buildAnswer": "./dist/orchestrator/buildAnswer.js",
15
+ "./policy-safe-knowledge-assistant.feature": "./dist/policy-safe-knowledge-assistant.feature.js",
16
16
  "./seed": "./dist/seed/index.js",
17
17
  "./seed/fixtures": "./dist/seed/fixtures.js",
18
+ "./seeders": "./dist/seeders/index.js",
19
+ "./ui": "./dist/ui/index.js",
20
+ "./ui/hooks/usePolicySafeKnowledgeAssistant": "./dist/ui/hooks/usePolicySafeKnowledgeAssistant.js",
21
+ "./ui/PolicySafeKnowledgeAssistantDashboard": "./dist/ui/PolicySafeKnowledgeAssistantDashboard.js",
18
22
  "./*": "./*"
19
23
  },
20
24
  "scripts": {
@@ -31,18 +35,26 @@
31
35
  "test": "bun test"
32
36
  },
33
37
  "dependencies": {
34
- "@contractspec/example.locale-jurisdiction-gate": "1.46.1",
35
- "@contractspec/example.versioned-knowledge-base": "1.46.1",
36
- "@contractspec/example.kb-update-pipeline": "1.46.1",
37
- "@contractspec/example.learning-patterns": "1.46.1",
38
- "@contractspec/lib.contracts": "1.46.1",
39
- "@contractspec/module.learning-journey": "1.46.1"
38
+ "@contractspec/example.kb-update-pipeline": "1.48.0",
39
+ "@contractspec/example.learning-patterns": "1.48.0",
40
+ "@contractspec/example.locale-jurisdiction-gate": "1.48.0",
41
+ "@contractspec/example.versioned-knowledge-base": "1.48.0",
42
+ "@contractspec/lib.contracts": "1.48.0",
43
+ "@contractspec/lib.design-system": "1.48.0",
44
+ "@contractspec/lib.example-shared-ui": "1.2.0",
45
+ "@contractspec/lib.runtime-sandbox": "0.3.0",
46
+ "@contractspec/lib.ui-kit-web": "1.48.0",
47
+ "@contractspec/module.learning-journey": "1.48.0",
48
+ "react": "19.2.3",
49
+ "react-dom": "19.2.3"
40
50
  },
41
51
  "devDependencies": {
42
- "@contractspec/tool.tsdown": "1.46.1",
43
- "@contractspec/tool.typescript": "1.46.1",
44
- "tsdown": "^0.18.3",
45
- "typescript": "^5.9.3"
52
+ "@contractspec/tool.tsdown": "1.48.0",
53
+ "@contractspec/tool.typescript": "1.48.0",
54
+ "tsdown": "^0.19.0",
55
+ "typescript": "^5.9.3",
56
+ "@types/react": "^19.2.8",
57
+ "@types/react-dom": "^19.2.2"
46
58
  },
47
59
  "publishConfig": {
48
60
  "access": "public",
@@ -51,7 +63,7 @@
51
63
  "./docs": "./dist/docs/index.js",
52
64
  "./docs/policy-safe-knowledge-assistant.docblock": "./dist/docs/policy-safe-knowledge-assistant.docblock.js",
53
65
  "./example": "./dist/example.js",
54
- "./feature": "./dist/feature.js",
66
+ "./policy-safe-knowledge-assistant.feature": "./dist/policy-safe-knowledge-assistant.feature.js",
55
67
  "./orchestrator/buildAnswer": "./dist/orchestrator/buildAnswer.js",
56
68
  "./seed": "./dist/seed/index.js",
57
69
  "./seed/fixtures": "./dist/seed/fixtures.js",
package/src/example.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { ExampleSpec } from '@contractspec/lib.contracts';
1
+ import { defineExample } from '@contractspec/lib.contracts';
2
2
 
3
- const example: ExampleSpec = {
3
+ const example = defineExample({
4
4
  meta: {
5
5
  key: 'policy-safe-knowledge-assistant',
6
6
  version: '1.0.0',
@@ -19,7 +19,7 @@ const example: ExampleSpec = {
19
19
  },
20
20
  entrypoints: {
21
21
  packageName: '@contractspec/example.policy-safe-knowledge-assistant',
22
- feature: './feature',
22
+ feature: './policy-safe-knowledge-assistant.feature',
23
23
  docs: './docs',
24
24
  },
25
25
  surfaces: {
@@ -31,6 +31,6 @@ const example: ExampleSpec = {
31
31
  studio: { enabled: true, installable: true },
32
32
  mcp: { enabled: true },
33
33
  },
34
- };
34
+ });
35
35
 
36
36
  export default example;
@@ -0,0 +1 @@
1
+ export * from './policy-safe-knowledge-assistant.handlers';