@contractspec/example.policy-safe-knowledge-assistant 0.0.0-canary-20260113170453

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 (69) hide show
  1. package/.turbo/turbo-build$colon$bundle.log +55 -0
  2. package/.turbo/turbo-build.log +56 -0
  3. package/CHANGELOG.md +585 -0
  4. package/LICENSE +21 -0
  5. package/README.md +22 -0
  6. package/dist/docs/index.d.ts +1 -0
  7. package/dist/docs/index.js +1 -0
  8. package/dist/docs/policy-safe-knowledge-assistant.docblock.d.ts +1 -0
  9. package/dist/docs/policy-safe-knowledge-assistant.docblock.js +35 -0
  10. package/dist/docs/policy-safe-knowledge-assistant.docblock.js.map +1 -0
  11. package/dist/example.d.ts +7 -0
  12. package/dist/example.d.ts.map +1 -0
  13. package/dist/example.js +54 -0
  14. package/dist/example.js.map +1 -0
  15. package/dist/handlers/index.d.ts +2 -0
  16. package/dist/handlers/index.js +3 -0
  17. package/dist/handlers/policy-safe-knowledge-assistant.handlers.d.ts +127 -0
  18. package/dist/handlers/policy-safe-knowledge-assistant.handlers.d.ts.map +1 -0
  19. package/dist/handlers/policy-safe-knowledge-assistant.handlers.js +264 -0
  20. package/dist/handlers/policy-safe-knowledge-assistant.handlers.js.map +1 -0
  21. package/dist/index.d.ts +8 -0
  22. package/dist/index.js +10 -0
  23. package/dist/orchestrator/buildAnswer.d.ts +53 -0
  24. package/dist/orchestrator/buildAnswer.d.ts.map +1 -0
  25. package/dist/orchestrator/buildAnswer.js +77 -0
  26. package/dist/orchestrator/buildAnswer.js.map +1 -0
  27. package/dist/policy-safe-knowledge-assistant.feature.d.ts +7 -0
  28. package/dist/policy-safe-knowledge-assistant.feature.d.ts.map +1 -0
  29. package/dist/policy-safe-knowledge-assistant.feature.js +150 -0
  30. package/dist/policy-safe-knowledge-assistant.feature.js.map +1 -0
  31. package/dist/seed/fixtures.d.ts +35 -0
  32. package/dist/seed/fixtures.d.ts.map +1 -0
  33. package/dist/seed/fixtures.js +34 -0
  34. package/dist/seed/fixtures.js.map +1 -0
  35. package/dist/seed/index.d.ts +2 -0
  36. package/dist/seed/index.js +3 -0
  37. package/dist/seeders/index.d.ts +10 -0
  38. package/dist/seeders/index.d.ts.map +1 -0
  39. package/dist/seeders/index.js +16 -0
  40. package/dist/seeders/index.js.map +1 -0
  41. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.d.ts +7 -0
  42. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.d.ts.map +1 -0
  43. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.js +231 -0
  44. package/dist/ui/PolicySafeKnowledgeAssistantDashboard.js.map +1 -0
  45. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts +55 -0
  46. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.d.ts.map +1 -0
  47. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.js +193 -0
  48. package/dist/ui/hooks/usePolicySafeKnowledgeAssistant.js.map +1 -0
  49. package/dist/ui/index.d.ts +2 -0
  50. package/dist/ui/index.js +3 -0
  51. package/package.json +81 -0
  52. package/src/docs/index.ts +1 -0
  53. package/src/docs/policy-safe-knowledge-assistant.docblock.ts +28 -0
  54. package/src/example.ts +36 -0
  55. package/src/handlers/index.ts +1 -0
  56. package/src/handlers/policy-safe-knowledge-assistant.handlers.ts +476 -0
  57. package/src/index.ts +11 -0
  58. package/src/integration.test.ts +108 -0
  59. package/src/orchestrator/buildAnswer.ts +122 -0
  60. package/src/policy-safe-knowledge-assistant.feature.ts +58 -0
  61. package/src/seed/fixtures.ts +31 -0
  62. package/src/seed/index.ts +1 -0
  63. package/src/seeders/index.ts +20 -0
  64. package/src/ui/PolicySafeKnowledgeAssistantDashboard.tsx +206 -0
  65. package/src/ui/hooks/usePolicySafeKnowledgeAssistant.ts +229 -0
  66. package/src/ui/index.ts +1 -0
  67. package/tsconfig.json +19 -0
  68. package/tsconfig.tsbuildinfo +1 -0
  69. package/tsdown.config.js +17 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildAnswer.js","names":[],"sources":["../../src/orchestrator/buildAnswer.ts"],"sourcesContent":["import {\n enforceAllowedScope,\n enforceCitations,\n validateEnvelope,\n} from '@contractspec/example.locale-jurisdiction-gate/policy/guard';\n\ntype AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';\n\nexport interface AssistantAnswerIR {\n locale: string;\n jurisdiction: string;\n allowedScope: AllowedScope;\n sections: { heading: string; body: string }[];\n citations: {\n kbSnapshotId: string;\n sourceType: string;\n sourceId: string;\n title?: string;\n excerpt?: string;\n }[];\n disclaimers?: string[];\n riskFlags?: string[];\n refused?: boolean;\n refusalReason?: string;\n}\n\nexport interface BuildAnswerInput {\n envelope: {\n traceId: string;\n locale: string;\n kbSnapshotId: string;\n allowedScope: AllowedScope;\n regulatoryContext: { jurisdiction: string };\n };\n question: string;\n kbSearch: (input: {\n snapshotId: string;\n jurisdiction: string;\n query: string;\n }) => Promise<{ items: { ruleVersionId: string; excerpt?: string }[] }>;\n}\n\n/**\n * Build a policy-safe assistant answer derived from KB search results.\n *\n * Deterministic: no LLM calls; if search yields no results, it refuses.\n */\nexport async function buildPolicySafeAnswer(\n input: BuildAnswerInput\n): Promise<AssistantAnswerIR> {\n const env = validateEnvelope(input.envelope);\n if (!env.ok) {\n return {\n locale: input.envelope.locale ?? 'en-GB',\n jurisdiction: input.envelope.regulatoryContext?.jurisdiction ?? 'UNKNOWN',\n allowedScope: input.envelope.allowedScope ?? 'education_only',\n sections: [{ heading: 'Request blocked', body: env.error.message }],\n citations: [],\n disclaimers: ['This system refuses to answer without a valid envelope.'],\n riskFlags: [env.error.code],\n refused: true,\n refusalReason: env.error.code,\n };\n }\n\n const results = await input.kbSearch({\n snapshotId: env.value.kbSnapshotId,\n jurisdiction: env.value.regulatoryContext?.jurisdiction ?? 'UNKNOWN',\n query: input.question,\n });\n\n const citations = results.items.map((item) => ({\n kbSnapshotId: env.value.kbSnapshotId,\n sourceType: 'ruleVersion',\n sourceId: item.ruleVersionId,\n title: 'Curated rule version',\n excerpt: item.excerpt,\n }));\n\n const draft: AssistantAnswerIR = {\n locale: env.value.locale,\n jurisdiction: env.value.regulatoryContext?.jurisdiction ?? 'UNKNOWN',\n allowedScope: env.value.allowedScope,\n sections: [\n {\n heading: 'Answer (KB-derived)',\n body:\n results.items.length > 0\n ? `This answer is derived from ${results.items.length} curated rule version(s) in the referenced snapshot.`\n : 'No curated knowledge found in the referenced snapshot.',\n },\n ],\n citations,\n disclaimers: ['Educational demo only.'],\n riskFlags: [],\n };\n\n const scope = enforceAllowedScope(env.value.allowedScope, draft);\n if (!scope.ok) {\n return {\n ...draft,\n sections: [{ heading: 'Escalation required', body: scope.error.message }],\n refused: true,\n refusalReason: scope.error.code,\n riskFlags: [...(draft.riskFlags ?? []), scope.error.code],\n };\n }\n\n const cited = enforceCitations(draft);\n if (!cited.ok) {\n return {\n ...draft,\n sections: [{ heading: 'Request blocked', body: cited.error.message }],\n citations: [],\n refused: true,\n refusalReason: cited.error.code,\n riskFlags: [...(draft.riskFlags ?? []), cited.error.code],\n };\n }\n\n return draft;\n}\n"],"mappings":";;;;;;;;AA+CA,eAAsB,sBACpB,OAC4B;CAC5B,MAAM,MAAM,iBAAiB,MAAM,SAAS;AAC5C,KAAI,CAAC,IAAI,GACP,QAAO;EACL,QAAQ,MAAM,SAAS,UAAU;EACjC,cAAc,MAAM,SAAS,mBAAmB,gBAAgB;EAChE,cAAc,MAAM,SAAS,gBAAgB;EAC7C,UAAU,CAAC;GAAE,SAAS;GAAmB,MAAM,IAAI,MAAM;GAAS,CAAC;EACnE,WAAW,EAAE;EACb,aAAa,CAAC,0DAA0D;EACxE,WAAW,CAAC,IAAI,MAAM,KAAK;EAC3B,SAAS;EACT,eAAe,IAAI,MAAM;EAC1B;CAGH,MAAM,UAAU,MAAM,MAAM,SAAS;EACnC,YAAY,IAAI,MAAM;EACtB,cAAc,IAAI,MAAM,mBAAmB,gBAAgB;EAC3D,OAAO,MAAM;EACd,CAAC;CAEF,MAAM,YAAY,QAAQ,MAAM,KAAK,UAAU;EAC7C,cAAc,IAAI,MAAM;EACxB,YAAY;EACZ,UAAU,KAAK;EACf,OAAO;EACP,SAAS,KAAK;EACf,EAAE;CAEH,MAAM,QAA2B;EAC/B,QAAQ,IAAI,MAAM;EAClB,cAAc,IAAI,MAAM,mBAAmB,gBAAgB;EAC3D,cAAc,IAAI,MAAM;EACxB,UAAU,CACR;GACE,SAAS;GACT,MACE,QAAQ,MAAM,SAAS,IACnB,+BAA+B,QAAQ,MAAM,OAAO,wDACpD;GACP,CACF;EACD;EACA,aAAa,CAAC,yBAAyB;EACvC,WAAW,EAAE;EACd;CAED,MAAM,QAAQ,oBAAoB,IAAI,MAAM,cAAc,MAAM;AAChE,KAAI,CAAC,MAAM,GACT,QAAO;EACL,GAAG;EACH,UAAU,CAAC;GAAE,SAAS;GAAuB,MAAM,MAAM,MAAM;GAAS,CAAC;EACzE,SAAS;EACT,eAAe,MAAM,MAAM;EAC3B,WAAW,CAAC,GAAI,MAAM,aAAa,EAAE,EAAG,MAAM,MAAM,KAAK;EAC1D;CAGH,MAAM,QAAQ,iBAAiB,MAAM;AACrC,KAAI,CAAC,MAAM,GACT,QAAO;EACL,GAAG;EACH,UAAU,CAAC;GAAE,SAAS;GAAmB,MAAM,MAAM,MAAM;GAAS,CAAC;EACrE,WAAW,EAAE;EACb,SAAS;EACT,eAAe,MAAM,MAAM;EAC3B,WAAW,CAAC,GAAI,MAAM,aAAa,EAAE,EAAG,MAAM,MAAM,KAAK;EAC1D;AAGH,QAAO"}
@@ -0,0 +1,7 @@
1
+ import * as _contractspec_lib_contracts0 from "@contractspec/lib.contracts";
2
+
3
+ //#region src/policy-safe-knowledge-assistant.feature.d.ts
4
+ declare const PolicySafeKnowledgeAssistantFeature: _contractspec_lib_contracts0.FeatureModuleSpec;
5
+ //#endregion
6
+ export { PolicySafeKnowledgeAssistantFeature };
7
+ //# sourceMappingURL=policy-safe-knowledge-assistant.feature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-safe-knowledge-assistant.feature.d.ts","names":[],"sources":["../src/policy-safe-knowledge-assistant.feature.ts"],"sourcesContent":[],"mappings":";;;cAEa,qCAuDX,4BAAA,CAvD8C"}
@@ -0,0 +1,150 @@
1
+ import { defineFeature } from "@contractspec/lib.contracts";
2
+
3
+ //#region src/policy-safe-knowledge-assistant.feature.ts
4
+ const PolicySafeKnowledgeAssistantFeature = defineFeature({
5
+ meta: {
6
+ key: "policy-safe-knowledge-assistant",
7
+ version: "1.0.0",
8
+ title: "Policy-safe Knowledge Assistant",
9
+ description: "All-in-one example composing locale/jurisdiction gate + versioned KB + HITL pipeline + learning hub.",
10
+ domain: "knowledge",
11
+ owners: ["@examples"],
12
+ tags: [
13
+ "assistant",
14
+ "knowledge",
15
+ "policy",
16
+ "hitl",
17
+ "learning"
18
+ ],
19
+ stability: "experimental"
20
+ },
21
+ operations: [
22
+ {
23
+ key: "assistant.answer",
24
+ version: "1.0.0"
25
+ },
26
+ {
27
+ key: "assistant.explainConcept",
28
+ version: "1.0.0"
29
+ },
30
+ {
31
+ key: "kb.ingestSource",
32
+ version: "1.0.0"
33
+ },
34
+ {
35
+ key: "kb.upsertRuleVersion",
36
+ version: "1.0.0"
37
+ },
38
+ {
39
+ key: "kb.approveRuleVersion",
40
+ version: "1.0.0"
41
+ },
42
+ {
43
+ key: "kb.publishSnapshot",
44
+ version: "1.0.0"
45
+ },
46
+ {
47
+ key: "kb.search",
48
+ version: "1.0.0"
49
+ },
50
+ {
51
+ key: "kbPipeline.runWatch",
52
+ version: "1.0.0"
53
+ },
54
+ {
55
+ key: "kbPipeline.createReviewTask",
56
+ version: "1.0.0"
57
+ },
58
+ {
59
+ key: "kbPipeline.submitDecision",
60
+ version: "1.0.0"
61
+ },
62
+ {
63
+ key: "kbPipeline.publishIfReady",
64
+ version: "1.0.0"
65
+ }
66
+ ],
67
+ events: [
68
+ {
69
+ key: "assistant.answer.requested",
70
+ version: "1.0.0"
71
+ },
72
+ {
73
+ key: "assistant.answer.blocked",
74
+ version: "1.0.0"
75
+ },
76
+ {
77
+ key: "assistant.answer.delivered",
78
+ version: "1.0.0"
79
+ },
80
+ {
81
+ key: "kb.source.ingested",
82
+ version: "1.0.0"
83
+ },
84
+ {
85
+ key: "kb.ruleVersion.created",
86
+ version: "1.0.0"
87
+ },
88
+ {
89
+ key: "kb.ruleVersion.approved",
90
+ version: "1.0.0"
91
+ },
92
+ {
93
+ key: "kb.snapshot.published",
94
+ version: "1.0.0"
95
+ },
96
+ {
97
+ key: "kb.change.detected",
98
+ version: "1.0.0"
99
+ },
100
+ {
101
+ key: "kb.review.requested",
102
+ version: "1.0.0"
103
+ },
104
+ {
105
+ key: "kb.review.decided",
106
+ version: "1.0.0"
107
+ }
108
+ ],
109
+ presentations: [],
110
+ opToPresentation: [],
111
+ presentationsTargets: [],
112
+ capabilities: { requires: [
113
+ {
114
+ key: "identity",
115
+ version: "1.0.0"
116
+ },
117
+ {
118
+ key: "audit-trail",
119
+ version: "1.0.0"
120
+ },
121
+ {
122
+ key: "notifications",
123
+ version: "1.0.0"
124
+ },
125
+ {
126
+ key: "jobs",
127
+ version: "1.0.0"
128
+ },
129
+ {
130
+ key: "feature-flags",
131
+ version: "1.0.0"
132
+ },
133
+ {
134
+ key: "files",
135
+ version: "1.0.0"
136
+ },
137
+ {
138
+ key: "metering",
139
+ version: "1.0.0"
140
+ },
141
+ {
142
+ key: "learning-journey",
143
+ version: "1.0.0"
144
+ }
145
+ ] }
146
+ });
147
+
148
+ //#endregion
149
+ export { PolicySafeKnowledgeAssistantFeature };
150
+ //# sourceMappingURL=policy-safe-knowledge-assistant.feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-safe-knowledge-assistant.feature.js","names":[],"sources":["../src/policy-safe-knowledge-assistant.feature.ts"],"sourcesContent":["import { defineFeature } from '@contractspec/lib.contracts';\n\nexport const PolicySafeKnowledgeAssistantFeature = defineFeature({\n meta: {\n key: 'policy-safe-knowledge-assistant',\n version: '1.0.0',\n title: 'Policy-safe Knowledge Assistant',\n description:\n 'All-in-one example composing locale/jurisdiction gate + versioned KB + HITL pipeline + learning hub.',\n domain: 'knowledge',\n owners: ['@examples'],\n tags: ['assistant', 'knowledge', 'policy', 'hitl', 'learning'],\n stability: 'experimental',\n },\n operations: [\n // Gate\n { key: 'assistant.answer', version: '1.0.0' },\n { key: 'assistant.explainConcept', version: '1.0.0' },\n // KB\n { key: 'kb.ingestSource', version: '1.0.0' },\n { key: 'kb.upsertRuleVersion', version: '1.0.0' },\n { key: 'kb.approveRuleVersion', version: '1.0.0' },\n { key: 'kb.publishSnapshot', version: '1.0.0' },\n { key: 'kb.search', version: '1.0.0' },\n // Pipeline\n { key: 'kbPipeline.runWatch', version: '1.0.0' },\n { key: 'kbPipeline.createReviewTask', version: '1.0.0' },\n { key: 'kbPipeline.submitDecision', version: '1.0.0' },\n { key: 'kbPipeline.publishIfReady', version: '1.0.0' },\n ],\n events: [\n { key: 'assistant.answer.requested', version: '1.0.0' },\n { key: 'assistant.answer.blocked', version: '1.0.0' },\n { key: 'assistant.answer.delivered', version: '1.0.0' },\n { key: 'kb.source.ingested', version: '1.0.0' },\n { key: 'kb.ruleVersion.created', version: '1.0.0' },\n { key: 'kb.ruleVersion.approved', version: '1.0.0' },\n { key: 'kb.snapshot.published', version: '1.0.0' },\n { key: 'kb.change.detected', version: '1.0.0' },\n { key: 'kb.review.requested', version: '1.0.0' },\n { key: 'kb.review.decided', version: '1.0.0' },\n ],\n presentations: [],\n opToPresentation: [],\n presentationsTargets: [],\n capabilities: {\n requires: [\n { key: 'identity', version: '1.0.0' },\n { key: 'audit-trail', version: '1.0.0' },\n { key: 'notifications', version: '1.0.0' },\n { key: 'jobs', version: '1.0.0' },\n { key: 'feature-flags', version: '1.0.0' },\n { key: 'files', version: '1.0.0' },\n { key: 'metering', version: '1.0.0' },\n { key: 'learning-journey', version: '1.0.0' },\n ],\n },\n});\n"],"mappings":";;;AAEA,MAAa,sCAAsC,cAAc;CAC/D,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,YAAY;EACrB,MAAM;GAAC;GAAa;GAAa;GAAU;GAAQ;GAAW;EAC9D,WAAW;EACZ;CACD,YAAY;EAEV;GAAE,KAAK;GAAoB,SAAS;GAAS;EAC7C;GAAE,KAAK;GAA4B,SAAS;GAAS;EAErD;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAwB,SAAS;GAAS;EACjD;GAAE,KAAK;GAAyB,SAAS;GAAS;EAClD;GAAE,KAAK;GAAsB,SAAS;GAAS;EAC/C;GAAE,KAAK;GAAa,SAAS;GAAS;EAEtC;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAA+B,SAAS;GAAS;EACxD;GAAE,KAAK;GAA6B,SAAS;GAAS;EACtD;GAAE,KAAK;GAA6B,SAAS;GAAS;EACvD;CACD,QAAQ;EACN;GAAE,KAAK;GAA8B,SAAS;GAAS;EACvD;GAAE,KAAK;GAA4B,SAAS;GAAS;EACrD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACvD;GAAE,KAAK;GAAsB,SAAS;GAAS;EAC/C;GAAE,KAAK;GAA0B,SAAS;GAAS;EACnD;GAAE,KAAK;GAA2B,SAAS;GAAS;EACpD;GAAE,KAAK;GAAyB,SAAS;GAAS;EAClD;GAAE,KAAK;GAAsB,SAAS;GAAS;EAC/C;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAqB,SAAS;GAAS;EAC/C;CACD,eAAe,EAAE;CACjB,kBAAkB,EAAE;CACpB,sBAAsB,EAAE;CACxB,cAAc,EACZ,UAAU;EACR;GAAE,KAAK;GAAY,SAAS;GAAS;EACrC;GAAE,KAAK;GAAe,SAAS;GAAS;EACxC;GAAE,KAAK;GAAiB,SAAS;GAAS;EAC1C;GAAE,KAAK;GAAQ,SAAS;GAAS;EACjC;GAAE,KAAK;GAAiB,SAAS;GAAS;EAC1C;GAAE,KAAK;GAAS,SAAS;GAAS;EAClC;GAAE,KAAK;GAAY,SAAS;GAAS;EACrC;GAAE,KAAK;GAAoB,SAAS;GAAS;EAC9C,EACF;CACF,CAAC"}
@@ -0,0 +1,35 @@
1
+ //#region src/seed/fixtures.d.ts
2
+ declare const DEMO_FIXTURES: {
3
+ readonly jurisdictions: readonly ["EU", "FR"];
4
+ readonly locales: readonly ["en-GB", "fr-FR"];
5
+ readonly demoOrgId: "org_demo";
6
+ readonly demoUserId: "user_demo";
7
+ readonly sources: {
8
+ readonly EU_SOURCE_1: {
9
+ readonly jurisdiction: "EU";
10
+ readonly authority: "DemoAuthority";
11
+ readonly title: "EU Demo Source v1";
12
+ readonly fetchedAt: Date;
13
+ readonly hash: "hash_eu_v1";
14
+ readonly fileId: "file_eu_v1";
15
+ };
16
+ readonly EU_SOURCE_2: {
17
+ readonly jurisdiction: "EU";
18
+ readonly authority: "DemoAuthority";
19
+ readonly title: "EU Demo Source v2";
20
+ readonly fetchedAt: Date;
21
+ readonly hash: "hash_eu_v2";
22
+ readonly fileId: "file_eu_v2";
23
+ };
24
+ };
25
+ readonly rules: {
26
+ readonly EU_RULE_TAX: {
27
+ readonly id: "rule_eu_tax";
28
+ readonly jurisdiction: "EU";
29
+ readonly topicKey: "tax_reporting";
30
+ };
31
+ };
32
+ };
33
+ //#endregion
34
+ export { DEMO_FIXTURES };
35
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","names":[],"sources":["../../src/seed/fixtures.ts"],"sourcesContent":[],"mappings":";cAAa;EAAA,SAAA,aA8BH,EAAA,SAAA,CAAA,IAAA,EAAA,IAAA,CAAA;;;;;;;;;0BAAA;;;;;;;;0BAAA"}
@@ -0,0 +1,34 @@
1
+ //#region src/seed/fixtures.ts
2
+ const DEMO_FIXTURES = {
3
+ jurisdictions: ["EU", "FR"],
4
+ locales: ["en-GB", "fr-FR"],
5
+ demoOrgId: "org_demo",
6
+ demoUserId: "user_demo",
7
+ sources: {
8
+ EU_SOURCE_1: {
9
+ jurisdiction: "EU",
10
+ authority: "DemoAuthority",
11
+ title: "EU Demo Source v1",
12
+ fetchedAt: /* @__PURE__ */ new Date("2026-01-01T00:00:00.000Z"),
13
+ hash: "hash_eu_v1",
14
+ fileId: "file_eu_v1"
15
+ },
16
+ EU_SOURCE_2: {
17
+ jurisdiction: "EU",
18
+ authority: "DemoAuthority",
19
+ title: "EU Demo Source v2",
20
+ fetchedAt: /* @__PURE__ */ new Date("2026-02-01T00:00:00.000Z"),
21
+ hash: "hash_eu_v2",
22
+ fileId: "file_eu_v2"
23
+ }
24
+ },
25
+ rules: { EU_RULE_TAX: {
26
+ id: "rule_eu_tax",
27
+ jurisdiction: "EU",
28
+ topicKey: "tax_reporting"
29
+ } }
30
+ };
31
+
32
+ //#endregion
33
+ export { DEMO_FIXTURES };
34
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","names":[],"sources":["../../src/seed/fixtures.ts"],"sourcesContent":["export const DEMO_FIXTURES = {\n jurisdictions: ['EU', 'FR'] as const,\n locales: ['en-GB', 'fr-FR'] as const,\n demoOrgId: 'org_demo',\n demoUserId: 'user_demo',\n sources: {\n EU_SOURCE_1: {\n jurisdiction: 'EU',\n authority: 'DemoAuthority',\n title: 'EU Demo Source v1',\n fetchedAt: new Date('2026-01-01T00:00:00.000Z'),\n hash: 'hash_eu_v1',\n fileId: 'file_eu_v1',\n },\n EU_SOURCE_2: {\n jurisdiction: 'EU',\n authority: 'DemoAuthority',\n title: 'EU Demo Source v2',\n fetchedAt: new Date('2026-02-01T00:00:00.000Z'),\n hash: 'hash_eu_v2',\n fileId: 'file_eu_v2',\n },\n },\n rules: {\n EU_RULE_TAX: {\n id: 'rule_eu_tax',\n jurisdiction: 'EU',\n topicKey: 'tax_reporting',\n },\n },\n} as const;\n"],"mappings":";AAAA,MAAa,gBAAgB;CAC3B,eAAe,CAAC,MAAM,KAAK;CAC3B,SAAS,CAAC,SAAS,QAAQ;CAC3B,WAAW;CACX,YAAY;CACZ,SAAS;EACP,aAAa;GACX,cAAc;GACd,WAAW;GACX,OAAO;GACP,2BAAW,IAAI,KAAK,2BAA2B;GAC/C,MAAM;GACN,QAAQ;GACT;EACD,aAAa;GACX,cAAc;GACd,WAAW;GACX,OAAO;GACP,2BAAW,IAAI,KAAK,2BAA2B;GAC/C,MAAM;GACN,QAAQ;GACT;EACF;CACD,OAAO,EACL,aAAa;EACX,IAAI;EACJ,cAAc;EACd,UAAU;EACX,EACF;CACF"}
@@ -0,0 +1,2 @@
1
+ import { DEMO_FIXTURES } from "./fixtures.js";
2
+ export { DEMO_FIXTURES };
@@ -0,0 +1,3 @@
1
+ import { DEMO_FIXTURES } from "./fixtures.js";
2
+
3
+ export { DEMO_FIXTURES };
@@ -0,0 +1,10 @@
1
+ import { DatabasePort } from "@contractspec/lib.runtime-sandbox";
2
+
3
+ //#region src/seeders/index.d.ts
4
+ declare function seedPolicyKnowledgeAssistant(params: {
5
+ projectId: string;
6
+ db: DatabasePort;
7
+ }): Promise<void>;
8
+ //#endregion
9
+ export { seedPolicyKnowledgeAssistant };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/seeders/index.ts"],"sourcesContent":[],"mappings":";;;iBAEsB,4BAAA;;EAAA,EAAA,EAEhB,YAFgB;IAGrB"}
@@ -0,0 +1,16 @@
1
+ //#region src/seeders/index.ts
2
+ async function seedPolicyKnowledgeAssistant(params) {
3
+ const { projectId, db } = params;
4
+ if ((await db.query(`SELECT COUNT(*) as count FROM psa_user_context WHERE "projectId" = $1`, [projectId])).rows[0]?.count > 0) return;
5
+ await db.execute(`INSERT INTO psa_user_context ("projectId", locale, jurisdiction, "allowedScope")
6
+ VALUES ($1, $2, $3, $4)`, [
7
+ projectId,
8
+ "en-GB",
9
+ "EU",
10
+ "education_only"
11
+ ]);
12
+ }
13
+
14
+ //#endregion
15
+ export { seedPolicyKnowledgeAssistant };
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/seeders/index.ts"],"sourcesContent":["import type { DatabasePort } from '@contractspec/lib.runtime-sandbox';\n\nexport async function seedPolicyKnowledgeAssistant(params: {\n projectId: string;\n db: DatabasePort;\n}) {\n const { projectId, db } = params;\n\n const existing = await db.query(\n `SELECT COUNT(*) as count FROM psa_user_context WHERE \"projectId\" = $1`,\n [projectId]\n );\n if ((existing.rows[0]?.count as number) > 0) return;\n\n await db.execute(\n `INSERT INTO psa_user_context (\"projectId\", locale, jurisdiction, \"allowedScope\")\n VALUES ($1, $2, $3, $4)`,\n [projectId, 'en-GB', 'EU', 'education_only']\n );\n}\n"],"mappings":";AAEA,eAAsB,6BAA6B,QAGhD;CACD,MAAM,EAAE,WAAW,OAAO;AAM1B,MAJiB,MAAM,GAAG,MACxB,yEACA,CAAC,UAAU,CACZ,EACa,KAAK,IAAI,QAAmB,EAAG;AAE7C,OAAM,GAAG,QACP;+BAEA;EAAC;EAAW;EAAS;EAAM;EAAiB,CAC7C"}
@@ -0,0 +1,7 @@
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+
3
+ //#region src/ui/PolicySafeKnowledgeAssistantDashboard.d.ts
4
+ declare function PolicySafeKnowledgeAssistantDashboard(): react_jsx_runtime0.JSX.Element;
5
+ //#endregion
6
+ export { PolicySafeKnowledgeAssistantDashboard };
7
+ //# sourceMappingURL=PolicySafeKnowledgeAssistantDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicySafeKnowledgeAssistantDashboard.d.ts","names":[],"sources":["../../src/ui/PolicySafeKnowledgeAssistantDashboard.tsx"],"sourcesContent":[],"mappings":";;;iBAyBgB,qCAAA,CAAA,GAAqC,kBAAA,CAAA,GAAA,CAAA"}
@@ -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":";;;;;;;;;;;;AAyBA,SAAgB,wCAAwC;CACtD,MAAM,EAAE,OAAO,YAAY,iCAAiC;CAC5D,MAAM,CAAC,UAAU,eAAe,SAAS,wBAAwB;CACjE,MAAM,CAAC,SAAS,cAAc,SAC5B,yCACD;CACD,MAAM,CAAC,QAAQ,aAAa,SAAS,QAAQ;CAC7C,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,CAAC,cAAc,mBACnB,SAAuB,iBAAiB;CAE1C,MAAM,aACJ,MAAM,SAAS,gBAAgB,MAAM,kBAAkB;CAEzD,MAAM,QAAQ,cAAc;AAC1B,SAAO;GACL;IAAE,OAAO;IAAU,OAAO,MAAM,SAAS,UAAU;IAAK;GACxD;IAAE,OAAO;IAAgB,OAAO,MAAM,SAAS,gBAAgB;IAAK;GACpE;IAAE,OAAO;IAAS,OAAO,MAAM,SAAS,gBAAgB;IAAK;GAC7D;IAAE,OAAO;IAAe,OAAO,cAAc;IAAK;GACnD;IACA;EACD;EACA,MAAM,SAAS;EACf,MAAM,SAAS;EACf,MAAM,SAAS;EAChB,CAAC;CAEF,MAAM,mBAAmB,YAAY,YAAY;AAC/C,QAAM,QAAQ,WAAW;GAAE;GAAQ;GAAc;GAAc,CAAC;IAC/D;EAAC;EAAS;EAAc;EAAc;EAAO,CAAC;CAEjD,MAAM,YAAY,YAAY,YAAY;AACxC,QAAM,QAAQ,aAAa,SAAS;IACnC,CAAC,SAAS,SAAS,CAAC;CAEvB,MAAM,yBAAyB,YAAY,YAAY;EACrD,MAAM,SAAS,MAAM,cAAe,MAAM,QAAQ,gBAAgB;EAClE,MAAM,OAAO,MAAM,QAAQ,kBAAkB;GAAE;GAAQ;GAAS,CAAC;AACjE,QAAM,QAAQ,mBAAmB,KAAK;AACtC,QAAM,QAAQ,iCAAiC,KAAK;AACpD,QAAM,QAAQ,iBAAiB;IAC9B;EAAC;EAAS;EAAS,MAAM;EAAW,CAAC;AAExC,KAAI,MAAM,WAAW,CAAC,MAAM,QAC1B,QAAO,oBAAC,eAAY,OAAM,oBAAoB;AAGhD,KAAI,MAAM,MACR,QACE,oBAAC;EACC,OAAM;EACN,aAAa,MAAM,MAAM;EACzB,SAAS,QAAQ;EACjB,YAAW;GACX;AAIN,QACE,qBAAC;EAAI,WAAU;;GACb,oBAAC,2BACE,MAAM,KAAK,MACV,oBAAC;IAAuB,OAAO,EAAE;IAAO,OAAO,OAAO,EAAE,MAAM;MAA/C,EAAE,MAAiD,CAClE,GACY;GAEhB,qBAAC;IAAK,WAAU;;KACd,oBAAC;MAAG,WAAU;gBAAwB;OAEjC;KACL,qBAAC;MAAI,WAAU;;OACb,qBAAC,oBACC,oBAAC;QAAI,WAAU;kBAA2E;SAEpF,EACN,oBAAC;QAAM,OAAO;QAAQ,WAAW,MAAM,UAAU,EAAE,OAAO,MAAM;SAAI,IAChE;OACN,qBAAC,oBACC,oBAAC;QAAI,WAAU;kBAA2E;SAEpF,EACN,oBAAC;QACC,OAAO;QACP,WAAW,MAAM,gBAAgB,EAAE,OAAO,MAAM;SAChD,IACE;OACN,qBAAC,oBACC,oBAAC;QAAI,WAAU;kBAA2E;SAEpF,EACN,qBAAC;QACC,OAAO;QACP,gBAAgB,MAAM,gBAAgB,EAAkB;mBAExD,oBAAC,2BACC,oBAAC,eAAY,aAAY,iBAAiB,GAC5B,EAChB,qBAAC;SACC,oBAAC;UAAW,OAAM;oBAAiB;WAA2B;SAC9D,oBAAC;UAAW,OAAM;oBAAe;WAAyB;SAC1D,oBAAC;UAAW,OAAM;oBAAsB;WAE3B;YACC;SACT,IACL;;OACF;KACN,qBAAC;MAAI,WAAU;iBACb,oBAAC;OAAO,SAAS;iBAAkB;QAAqB,EACxD,oBAAC;OAAO,SAAQ;OAAU,SAAS,QAAQ;iBAAgB;QAElD;OACL;;KACD;GAEP,qBAAC;IAAK,WAAU;;KACd,oBAAC;MAAG,WAAU;gBAAwB;OAEjC;KACL,qBAAC;MAAI,WAAU;iBACb,oBAAC;OACC,OAAO;OACP,WAAW,MAAM,YAAY,EAAE,OAAO,MAAM;QAC5C,EACF,oBAAC;OAAI,WAAU;iBACb,oBAAC;QAAO,SAAS;kBAAW;SAAY;QACpC;OACF;KAEL,MAAM,aACL,qBAAC;MAAI,WAAU;;OACZ,MAAM,WAAW,UAChB,qBAAC;QAAI,WAAU;mBAAuB,aAC1B,MAAM,WAAW,iBAAiB;SACxC,GACJ;OACH,MAAM,WAAW,SAAS,KAAK,GAAG,QACjC,qBAAC,oBACC,oBAAC;QAAI,WAAU;kBAAyB,EAAE;SAAc,EACxD,oBAAC;QAAI,WAAU;kBAAiC,EAAE;SAAW,KAFrD,GAAG,EAAE,QAAQ,GAAG,MAGpB,CACN;OACF,oBAAC;QAAI,WAAU;kBAAwB;SAAe;OACtD,oBAAC;QAAG,WAAU;kBACX,MAAM,WAAW,UAAU,KAAK,MAC/B,qBAAC;SACE,EAAE;SAAa;SAAI,EAAE;aADf,GAAG,EAAE,aAAa,GAAG,EAAE,WAE3B,CACL;SACC;;OACD,GACJ;;KACC;GAEP,qBAAC;IAAK,WAAU;eACd,oBAAC;KAAG,WAAU;eAAwB;MAEjC,EACL,qBAAC;KAAI,WAAU;gBACb,oBAAC;MACC,OAAO;MACP,WAAW,MAAM,WAAW,EAAE,OAAO,MAAM;OAC3C,EACF,oBAAC;MAAO,SAAS;gBAAwB;OAEhC;MACL;KACD;GAEP,qBAAC;IAAK,WAAU;eACd,oBAAC;KAAG,WAAU;eAAwB;MAA+B,EACrE,oBAAC;KAAE,WAAU;eAAqC;MAI9C;KACC;;GACH"}
@@ -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"}