@lssm/lib.contracts 1.11.1 → 1.41.1

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 (293) hide show
  1. package/README.md +1 -1
  2. package/dist/_virtual/rolldown_runtime.js +1 -0
  3. package/dist/app-config/app-config.feature.js +1 -0
  4. package/dist/app-config/contracts.js +1 -1
  5. package/dist/app-config/docs/app-config.docblock.js +220 -0
  6. package/dist/app-config/events.js +1 -1
  7. package/dist/app-config/index.js +1 -1
  8. package/dist/app-config/lifecycle-contracts.js +1 -1
  9. package/dist/capabilities/docs/capabilities.docblock.js +1 -0
  10. package/dist/contract-registry/index.js +1 -0
  11. package/dist/contract-registry/schemas.js +1 -0
  12. package/dist/contract-registry/types.js +0 -0
  13. package/dist/data-views/docs/data-views.docblock.js +1 -0
  14. package/dist/docs/PUBLISHING.docblock.js +76 -0
  15. package/dist/docs/accessibility_wcag_compliance_specs.docblock.js +350 -0
  16. package/dist/docs/index.js +1 -0
  17. package/dist/docs/meta.docs.js +13 -0
  18. package/dist/docs/presentations.js +1 -0
  19. package/dist/docs/registry.js +1 -0
  20. package/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +383 -0
  21. package/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +68 -0
  22. package/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +140 -0
  23. package/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +86 -0
  24. package/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +1 -0
  25. package/dist/docs/tech/auth/better-auth-nextjs.docblock.js +58 -0
  26. package/dist/docs/tech/contracts/README.docblock.js +1 -0
  27. package/dist/docs/tech/contracts/create-subscription.docblock.js +1 -0
  28. package/dist/docs/tech/contracts/graphql-typed-outputs.docblock.js +180 -0
  29. package/dist/docs/tech/contracts/migrations.docblock.js +1 -0
  30. package/dist/docs/tech/contracts/openapi-export.docblock.js +38 -0
  31. package/dist/docs/tech/contracts/ops-to-presentation-linking.docblock.js +62 -0
  32. package/dist/docs/tech/contracts/overlays.docblock.js +68 -0
  33. package/dist/docs/tech/contracts/tests.docblock.js +132 -0
  34. package/dist/docs/tech/contracts/themes.docblock.js +1 -0
  35. package/dist/docs/tech/contracts/vertical-pocket-family-office.docblock.js +106 -0
  36. package/dist/docs/tech/lifecycle-stage-system.docblock.js +213 -0
  37. package/dist/docs/tech/llm/llm-integration.docblock.js +289 -0
  38. package/dist/docs/tech/mcp-endpoints.docblock.js +1 -0
  39. package/dist/docs/tech/presentation-runtime.docblock.js +1 -0
  40. package/dist/docs/tech/schema/README.docblock.js +262 -0
  41. package/dist/docs/tech/studio/learning-events.docblock.js +1 -0
  42. package/dist/docs/tech/studio/learning-journeys.docblock.js +57 -0
  43. package/dist/docs/tech/studio/platform-admin-panel.docblock.js +63 -0
  44. package/dist/docs/tech/studio/project-access-teams.docblock.js +36 -0
  45. package/dist/docs/tech/studio/project-routing.docblock.js +1 -0
  46. package/dist/docs/tech/studio/sandbox-unlogged.docblock.js +20 -0
  47. package/dist/docs/tech/studio/team-invitations.docblock.js +65 -0
  48. package/dist/docs/tech/studio/workspace-ops.docblock.js +1 -0
  49. package/dist/docs/tech/studio/workspaces.docblock.js +41 -0
  50. package/dist/docs/tech/telemetry-ingest.docblock.js +122 -0
  51. package/dist/docs/tech/templates/runtime.docblock.js +1 -0
  52. package/dist/docs/tech/vscode-extension.docblock.js +68 -0
  53. package/dist/docs/tech/workflows/overview.docblock.js +1 -0
  54. package/dist/docs/tech-contracts.docs.js +76 -0
  55. package/dist/docs/types.js +0 -0
  56. package/dist/events.js +1 -1
  57. package/dist/experiments/docs/experiments.docblock.js +128 -0
  58. package/dist/forms/docs/forms.docblock.js +1 -0
  59. package/dist/index.js +1 -1
  60. package/dist/install.js +1 -1
  61. package/dist/integrations/contracts.js +1 -1
  62. package/dist/integrations/docs/integrations.docblock.js +1 -0
  63. package/dist/integrations/index.js +1 -1
  64. package/dist/integrations/openbanking/contracts/accounts.js +1 -1
  65. package/dist/integrations/openbanking/contracts/balances.js +1 -1
  66. package/dist/integrations/openbanking/contracts/index.js +1 -1
  67. package/dist/integrations/openbanking/contracts/transactions.js +1 -1
  68. package/dist/integrations/openbanking/models.js +1 -1
  69. package/dist/integrations/openbanking/openbanking.feature.js +1 -0
  70. package/dist/integrations/providers/impls/index.js +1 -1
  71. package/dist/integrations/providers/impls/provider-factory.js +1 -1
  72. package/dist/integrations/providers/index.js +1 -1
  73. package/dist/integrations/providers/registry.js +1 -0
  74. package/dist/integrations/secrets/aws-secret-manager.js +1 -0
  75. package/dist/integrations/secrets/gcp-secret-manager.js +1 -1
  76. package/dist/integrations/secrets/index.js +1 -1
  77. package/dist/integrations/secrets/scaleway-secret-manager.js +1 -0
  78. package/dist/jobs/define-job.js +1 -0
  79. package/dist/jobs/gcp-cloud-tasks.js +1 -1
  80. package/dist/jobs/gcp-pubsub.js +1 -1
  81. package/dist/jobs/handlers/index.js +1 -1
  82. package/dist/jobs/handlers/ping-handler.js +1 -0
  83. package/dist/jobs/index.js +1 -1
  84. package/dist/jobs/memory-queue.js +1 -1
  85. package/dist/jobs/queue.js +1 -0
  86. package/dist/jobs/scaleway-sqs-queue.js +1 -0
  87. package/dist/knowledge/contracts.js +1 -1
  88. package/dist/knowledge/docs/knowledge.docblock.js +138 -0
  89. package/dist/llm/exporters.js +8 -0
  90. package/dist/llm/index.js +1 -0
  91. package/dist/llm/prompts.js +220 -0
  92. package/dist/llm/types.js +0 -0
  93. package/dist/onboarding-base.js +1 -1
  94. package/dist/openapi.js +1 -0
  95. package/dist/openbanking/docs/openbanking.docblock.js +109 -0
  96. package/dist/policy/docs/policy.docblock.js +1 -0
  97. package/dist/presentations/docs/presentations-conventions.docblock.js +8 -0
  98. package/dist/presentations.js +1 -1
  99. package/dist/presentations.v2.js +7 -1
  100. package/dist/prompt.js +1 -1
  101. package/dist/promptRegistry.js +1 -1
  102. package/dist/regenerator/docs/regenerator.docblock.js +184 -0
  103. package/dist/registry.js +1 -1
  104. package/dist/resources.js +1 -1
  105. package/dist/schema-to-markdown.js +10 -0
  106. package/dist/server/graphql-pothos.js +1 -1
  107. package/dist/server/index.js +1 -1
  108. package/dist/server/mcp/createMcpServer.js +1 -0
  109. package/dist/server/mcp/mcpTypes.js +0 -0
  110. package/dist/server/mcp/registerPresentations.js +1 -0
  111. package/dist/server/mcp/registerPrompts.js +3 -0
  112. package/dist/server/mcp/registerResources.js +1 -0
  113. package/dist/server/mcp/registerTools.js +1 -0
  114. package/dist/server/provider-mcp.js +1 -1
  115. package/dist/telemetry/docs/telemetry.docblock.js +139 -0
  116. package/package.json +354 -193
  117. package/dist/app-config/branding.d.ts +0 -55
  118. package/dist/app-config/contracts.d.ts +0 -244
  119. package/dist/app-config/events.d.ts +0 -122
  120. package/dist/app-config/index.d.ts +0 -8
  121. package/dist/app-config/lifecycle-contracts.d.ts +0 -382
  122. package/dist/app-config/lifecycle.d.ts +0 -27
  123. package/dist/app-config/runtime.d.ts +0 -114
  124. package/dist/app-config/spec.d.ts +0 -175
  125. package/dist/app-config/validation.d.ts +0 -47
  126. package/dist/capabilities/openbanking.d.ts +0 -9
  127. package/dist/capabilities.d.ts +0 -45
  128. package/dist/client/index.d.ts +0 -6
  129. package/dist/client/react/drivers/rn-reusables.d.ts +0 -22
  130. package/dist/client/react/drivers/shadcn.d.ts +0 -12
  131. package/dist/client/react/feature-render.d.ts +0 -20
  132. package/dist/client/react/form-render.d.ts +0 -91
  133. package/dist/client/react/index.d.ts +0 -5
  134. package/dist/contracts-adapter-hydration.d.ts +0 -15
  135. package/dist/contracts-adapter-input.d.ts +0 -10
  136. package/dist/data-views/query-generator.d.ts +0 -39
  137. package/dist/data-views/runtime.d.ts +0 -26
  138. package/dist/data-views.d.ts +0 -131
  139. package/dist/events.d.ts +0 -44
  140. package/dist/experiments/evaluator.d.ts +0 -37
  141. package/dist/experiments/spec-resolver.d.ts +0 -16
  142. package/dist/experiments/spec.d.ts +0 -89
  143. package/dist/features.d.ts +0 -87
  144. package/dist/forms.d.ts +0 -258
  145. package/dist/graphql-federation/dist/index.js +0 -1
  146. package/dist/index.d.ts +0 -130
  147. package/dist/install.d.ts +0 -76
  148. package/dist/integrations/binding.d.ts +0 -17
  149. package/dist/integrations/connection.d.ts +0 -51
  150. package/dist/integrations/contracts.d.ts +0 -435
  151. package/dist/integrations/health.d.ts +0 -21
  152. package/dist/integrations/index.d.ts +0 -53
  153. package/dist/integrations/openbanking/contracts/accounts.d.ts +0 -287
  154. package/dist/integrations/openbanking/contracts/balances.d.ts +0 -163
  155. package/dist/integrations/openbanking/contracts/index.d.ts +0 -9
  156. package/dist/integrations/openbanking/contracts/transactions.d.ts +0 -211
  157. package/dist/integrations/openbanking/guards.d.ts +0 -12
  158. package/dist/integrations/openbanking/models.d.ts +0 -228
  159. package/dist/integrations/openbanking/telemetry.d.ts +0 -15
  160. package/dist/integrations/providers/calendar.d.ts +0 -78
  161. package/dist/integrations/providers/elevenlabs.d.ts +0 -7
  162. package/dist/integrations/providers/email.d.ts +0 -86
  163. package/dist/integrations/providers/embedding.d.ts +0 -24
  164. package/dist/integrations/providers/gcs-storage.d.ts +0 -7
  165. package/dist/integrations/providers/gmail.d.ts +0 -7
  166. package/dist/integrations/providers/google-calendar.d.ts +0 -7
  167. package/dist/integrations/providers/impls/elevenlabs-voice.d.ts +0 -20
  168. package/dist/integrations/providers/impls/gcs-storage.d.ts +0 -24
  169. package/dist/integrations/providers/impls/gmail-inbound.d.ts +0 -26
  170. package/dist/integrations/providers/impls/gmail-outbound.d.ts +0 -18
  171. package/dist/integrations/providers/impls/google-calendar.d.ts +0 -23
  172. package/dist/integrations/providers/impls/index.d.ts +0 -15
  173. package/dist/integrations/providers/impls/mistral-embedding.d.ts +0 -23
  174. package/dist/integrations/providers/impls/mistral-llm.d.ts +0 -31
  175. package/dist/integrations/providers/impls/postmark-email.d.ts +0 -19
  176. package/dist/integrations/providers/impls/powens-client.d.ts +0 -124
  177. package/dist/integrations/providers/impls/powens-openbanking.d.ts +0 -27
  178. package/dist/integrations/providers/impls/provider-factory.d.ts +0 -26
  179. package/dist/integrations/providers/impls/qdrant-vector.d.ts +0 -24
  180. package/dist/integrations/providers/impls/stripe-payments.d.ts +0 -28
  181. package/dist/integrations/providers/impls/twilio-sms.d.ts +0 -20
  182. package/dist/integrations/providers/index.d.ts +0 -36
  183. package/dist/integrations/providers/llm.d.ts +0 -82
  184. package/dist/integrations/providers/mistral.d.ts +0 -7
  185. package/dist/integrations/providers/openbanking.d.ts +0 -128
  186. package/dist/integrations/providers/payments.d.ts +0 -109
  187. package/dist/integrations/providers/postmark.d.ts +0 -7
  188. package/dist/integrations/providers/powens.d.ts +0 -7
  189. package/dist/integrations/providers/qdrant.d.ts +0 -7
  190. package/dist/integrations/providers/sms.d.ts +0 -34
  191. package/dist/integrations/providers/storage.d.ts +0 -60
  192. package/dist/integrations/providers/stripe.d.ts +0 -7
  193. package/dist/integrations/providers/twilio-sms.d.ts +0 -7
  194. package/dist/integrations/providers/vector-store.d.ts +0 -43
  195. package/dist/integrations/providers/voice.d.ts +0 -34
  196. package/dist/integrations/runtime.d.ts +0 -99
  197. package/dist/integrations/secrets/env-secret-provider.d.ts +0 -31
  198. package/dist/integrations/secrets/gcp-secret-manager.d.ts +0 -32
  199. package/dist/integrations/secrets/index.d.ts +0 -5
  200. package/dist/integrations/secrets/manager.d.ts +0 -47
  201. package/dist/integrations/secrets/provider.d.ts +0 -52
  202. package/dist/integrations/spec.d.ts +0 -79
  203. package/dist/jobs/gcp-cloud-tasks.d.ts +0 -41
  204. package/dist/jobs/gcp-pubsub.d.ts +0 -25
  205. package/dist/jobs/handlers/gmail-sync-handler.d.ts +0 -9
  206. package/dist/jobs/handlers/index.d.ts +0 -3
  207. package/dist/jobs/handlers/storage-document-handler.d.ts +0 -12
  208. package/dist/jobs/index.d.ts +0 -7
  209. package/dist/jobs/memory-queue.d.ts +0 -18
  210. package/dist/jobs/queue.d.ts +0 -26
  211. package/dist/jsonschema.d.ts +0 -26
  212. package/dist/knowledge/binding.d.ts +0 -25
  213. package/dist/knowledge/contracts.d.ts +0 -316
  214. package/dist/knowledge/index.d.ts +0 -10
  215. package/dist/knowledge/ingestion/document-processor.d.ts +0 -24
  216. package/dist/knowledge/ingestion/embedding-service.d.ts +0 -12
  217. package/dist/knowledge/ingestion/gmail-adapter.d.ts +0 -18
  218. package/dist/knowledge/ingestion/index.d.ts +0 -6
  219. package/dist/knowledge/ingestion/storage-adapter.d.ts +0 -15
  220. package/dist/knowledge/ingestion/vector-indexer.d.ts +0 -18
  221. package/dist/knowledge/query/index.d.ts +0 -2
  222. package/dist/knowledge/query/service.d.ts +0 -29
  223. package/dist/knowledge/runtime.d.ts +0 -32
  224. package/dist/knowledge/source.d.ts +0 -32
  225. package/dist/knowledge/spaces/email-threads.d.ts +0 -7
  226. package/dist/knowledge/spaces/financial-docs.d.ts +0 -7
  227. package/dist/knowledge/spaces/financial-overview.d.ts +0 -7
  228. package/dist/knowledge/spaces/index.d.ts +0 -7
  229. package/dist/knowledge/spaces/product-canon.d.ts +0 -7
  230. package/dist/knowledge/spaces/support-faq.d.ts +0 -7
  231. package/dist/knowledge/spaces/uploaded-docs.d.ts +0 -7
  232. package/dist/knowledge/spec.d.ts +0 -52
  233. package/dist/markdown.d.ts +0 -21
  234. package/dist/migrations.d.ts +0 -52
  235. package/dist/onboarding-base.d.ts +0 -137
  236. package/dist/ownership.d.ts +0 -75
  237. package/dist/policy/engine.d.ts +0 -39
  238. package/dist/policy/opa-adapter.d.ts +0 -45
  239. package/dist/policy/spec.d.ts +0 -114
  240. package/dist/presentations.backcompat.d.ts +0 -7
  241. package/dist/presentations.d.ts +0 -96
  242. package/dist/presentations.v2.d.ts +0 -95
  243. package/dist/prompt.d.ts +0 -60
  244. package/dist/promptRegistry.d.ts +0 -15
  245. package/dist/regenerator/adapters.d.ts +0 -19
  246. package/dist/regenerator/executor.d.ts +0 -70
  247. package/dist/regenerator/index.d.ts +0 -7
  248. package/dist/regenerator/service.d.ts +0 -33
  249. package/dist/regenerator/sinks.d.ts +0 -26
  250. package/dist/regenerator/types.d.ts +0 -107
  251. package/dist/regenerator/utils.d.ts +0 -9
  252. package/dist/registry.d.ts +0 -72
  253. package/dist/resources.d.ts +0 -64
  254. package/dist/schema/dist/EnumType.js +0 -1
  255. package/dist/schema/dist/FieldType.js +0 -1
  256. package/dist/schema/dist/ScalarTypeEnum.js +0 -1
  257. package/dist/schema/dist/SchemaModel.js +0 -1
  258. package/dist/schema/dist/index.js +0 -1
  259. package/dist/server/graphql-pothos.d.ts +0 -31
  260. package/dist/server/graphql-schema-export.d.ts +0 -6
  261. package/dist/server/graphql-schema-export.js +0 -1
  262. package/dist/server/index.d.ts +0 -9
  263. package/dist/server/provider-mcp.d.ts +0 -51
  264. package/dist/server/rest-elysia.d.ts +0 -40
  265. package/dist/server/rest-express.d.ts +0 -16
  266. package/dist/server/rest-generic.d.ts +0 -32
  267. package/dist/server/rest-next-app.d.ts +0 -35
  268. package/dist/server/rest-next-mcp.d.ts +0 -11
  269. package/dist/server/rest-next-pages.d.ts +0 -9
  270. package/dist/spec.d.ts +0 -171
  271. package/dist/telemetry/anomaly.d.ts +0 -27
  272. package/dist/telemetry/index.d.ts +0 -4
  273. package/dist/telemetry/spec.d.ts +0 -98
  274. package/dist/telemetry/tracker.d.ts +0 -51
  275. package/dist/tests/index.d.ts +0 -3
  276. package/dist/tests/runner.d.ts +0 -43
  277. package/dist/tests/spec.d.ts +0 -89
  278. package/dist/themes.d.ts +0 -55
  279. package/dist/translations/catalog.d.ts +0 -28
  280. package/dist/translations/tenant.d.ts +0 -15
  281. package/dist/types/all.d.ts +0 -60
  282. package/dist/types.d.ts +0 -88
  283. package/dist/workflow/adapters/db-adapter.d.ts +0 -34
  284. package/dist/workflow/adapters/file-adapter.d.ts +0 -14
  285. package/dist/workflow/adapters/index.d.ts +0 -4
  286. package/dist/workflow/adapters/memory-store.d.ts +0 -18
  287. package/dist/workflow/expression.d.ts +0 -9
  288. package/dist/workflow/index.d.ts +0 -10
  289. package/dist/workflow/runner.d.ts +0 -74
  290. package/dist/workflow/sla-monitor.d.ts +0 -20
  291. package/dist/workflow/spec.d.ts +0 -99
  292. package/dist/workflow/state.d.ts +0 -35
  293. package/dist/workflow/validation.d.ts +0 -28
@@ -0,0 +1,220 @@
1
+ import{specToAgentPrompt as e,specToFullMarkdown as t}from"./exporters.js";const n={"claude-code":`You are an expert TypeScript developer working with ContractSpec, a spec-first development framework.
2
+
3
+ Your code follows these principles:
4
+ - Type-safe with comprehensive TypeScript types (no \`any\`)
5
+ - Well-documented with JSDoc comments
6
+ - Production-ready with proper error handling
7
+ - Following SOLID principles and clean code practices
8
+ - Modular and testable
9
+
10
+ When implementing specs:
11
+ 1. Validate input against the schema before processing
12
+ 2. Handle all error cases defined in the spec
13
+ 3. Emit events as specified in sideEffects
14
+ 4. Respect policy constraints (auth, rate limits, PII handling)
15
+ 5. Follow the acceptance scenarios as your implementation guide
16
+
17
+ Generate clean, idiomatic TypeScript that exactly matches the specification.`,"cursor-cli":`You are implementing features for a ContractSpec-driven codebase.
18
+
19
+ ContractSpec is a spec-first framework where specifications define:
20
+ - Operations (commands and queries) with typed I/O
21
+ - Events that operations emit
22
+ - Presentations for UI components
23
+ - Features that group related specs
24
+
25
+ When working with specs:
26
+ - Read the spec carefully before implementing
27
+ - Match the input/output types exactly
28
+ - Implement all error cases
29
+ - Follow the acceptance scenarios
30
+ - Respect policy constraints
31
+
32
+ Use the project's existing patterns and conventions.`,"generic-mcp":`You are a code generation assistant working with ContractSpec specifications.
33
+
34
+ ContractSpec specs define:
35
+ - meta: name, version, kind (command/query), description, goal, context
36
+ - io: input schema, output schema, error definitions
37
+ - policy: auth level, rate limits, feature flags, PII handling
38
+ - sideEffects: events to emit, analytics, audit
39
+ - acceptance: scenarios and examples
40
+
41
+ Your task is to generate or modify code that complies with the given specification.
42
+ Follow the spec exactly and handle all defined cases.`};function r(r,i,a){let o=n[i],s=t(r),c;return c=i===`claude-code`?`## Implementation Task
43
+
44
+ Implement the following ContractSpec operation:
45
+
46
+ ${s}
47
+
48
+ ${a?.targetPath?`**Target file:** \`${a.targetPath}\`\n`:``}
49
+ ${a?.existingCode?`**Existing code to modify:**\n\`\`\`typescript\n${a.existingCode}\n\`\`\`\n`:``}
50
+
51
+ Generate a complete, production-ready TypeScript implementation that:
52
+ 1. Exports a handler function matching the spec signature
53
+ 2. Validates input using the schema
54
+ 3. Handles all defined error cases
55
+ 4. Emits events as specified
56
+ 5. Includes JSDoc documentation
57
+
58
+ Provide ONLY the TypeScript code.`:i===`cursor-cli`?`Implement this ContractSpec operation.
59
+
60
+ ${s}
61
+
62
+ ${a?.targetPath?`Target: ${a.targetPath}\n`:``}
63
+
64
+ Requirements:
65
+ - TypeScript with strict types
66
+ - Handle all error cases
67
+ - Emit specified events
68
+ - Follow acceptance scenarios`:e(r,{taskType:`implement`,existingCode:a?.existingCode}),{agent:i,systemPrompt:o,taskPrompt:c}}function i(e,r,i){let a=i?.testFramework??`vitest`,o=`## Test Generation Task
69
+
70
+ Generate comprehensive tests for this specification:
71
+
72
+ ${t(e)}
73
+
74
+ ${i?.implementationCode?`**Implementation:**\n\`\`\`typescript\n${i.implementationCode}\n\`\`\`\n`:``}
75
+
76
+ **Test Framework:** ${a}
77
+
78
+ Generate tests that:
79
+ 1. Cover all acceptance scenarios from the spec
80
+ 2. Test all defined error cases
81
+ 3. Verify input validation
82
+ 4. Check event emissions
83
+ 5. Test edge cases
84
+
85
+ Use descriptive test names: "should [behavior] when [condition]"
86
+
87
+ Provide a complete test file.`;return{agent:r,systemPrompt:n[r],taskPrompt:o}}function a(e,r,i){let a=`## Code Review Task
88
+
89
+ Review this implementation against its specification:
90
+
91
+ **Specification:**
92
+ ${t(e)}
93
+
94
+ **Implementation:**
95
+ \`\`\`typescript
96
+ ${i}
97
+ \`\`\`
98
+
99
+ Provide a structured review:
100
+
101
+ ### Compliance Check
102
+ - [ ] Input types match spec
103
+ - [ ] Output types match spec
104
+ - [ ] All error cases handled
105
+ - [ ] Events emitted correctly
106
+ - [ ] Policy constraints respected
107
+
108
+ ### Issues Found
109
+ List any issues with severity (error/warning/info)
110
+
111
+ ### Suggestions
112
+ List improvements and recommendations
113
+
114
+ Be thorough and precise. Focus on spec compliance first, then code quality.`;return{agent:r,systemPrompt:n[r],taskPrompt:a}}function o(e,n){return{agent:`generic-mcp`,taskPrompt:`## Semantic Verification Task
115
+
116
+ Verify that this implementation fulfills the specification's intent.
117
+
118
+ **Specification:**
119
+ ${t(e)}
120
+
121
+ **Implementation:**
122
+ \`\`\`typescript
123
+ ${n}
124
+ \`\`\`
125
+
126
+ Analyze and respond with JSON:
127
+
128
+ \`\`\`json
129
+ {
130
+ "passed": true/false,
131
+ "score": 0-100,
132
+ "compliance": {
133
+ "inputTypes": { "match": true/false, "issues": [] },
134
+ "outputTypes": { "match": true/false, "issues": [] },
135
+ "errorHandling": { "coverage": "full/partial/none", "missing": [] },
136
+ "eventEmission": { "correct": true/false, "issues": [] },
137
+ "policyCompliance": { "auth": true/false, "rateLimit": true/false, "pii": true/false }
138
+ },
139
+ "scenarios": [
140
+ { "name": "scenario name", "covered": true/false, "notes": "" }
141
+ ],
142
+ "issues": [
143
+ { "severity": "error/warning/info", "category": "type/export/import/scenario/error_handling/semantic", "message": "", "suggestion": "" }
144
+ ],
145
+ "summary": "Brief summary of verification results"
146
+ }
147
+ \`\`\``}}function s(e,n){let r=e.meta,i=[],a=n?.projectRoot??`src`,o=r.name.replace(/\./g,`/`);(r.kind===`command`||r.kind===`query`)&&i.push({path:`${a}/${o}/handler.ts`,purpose:`Main handler implementation`,type:`create`},{path:`${a}/${o}/types.ts`,purpose:`Type definitions`,type:`create`},{path:`${a}/${o}/handler.test.ts`,purpose:`Handler tests`,type:`create`});let s=[],c=1;s.push({order:c++,title:`Define Types`,description:`Create TypeScript types for input, output, and internal data structures`,acceptanceCriteria:[`Input type matches spec schema exactly`,`Output type matches spec schema exactly`,`Error types defined for all error cases`]}),s.push({order:c++,title:`Implement Input Validation`,description:`Add validation logic for the input payload`,acceptanceCriteria:[`All required fields are validated`,`Type constraints are enforced`,`Validation errors return appropriate error codes`]}),s.push({order:c++,title:`Implement Core Logic`,description:`Implement the main business logic of the operation`,acceptanceCriteria:e.acceptance?.scenarios?.map(e=>e.name)??[`Operation completes successfully for valid input`]}),e.io.errors&&Object.keys(e.io.errors).length>0&&s.push({order:c++,title:`Implement Error Handling`,description:`Handle all defined error cases`,acceptanceCriteria:Object.entries(e.io.errors).map(([e,t])=>`Handle ${e}: ${t.when}`)}),e.sideEffects?.emits?.length&&s.push({order:c++,title:`Implement Event Emission`,description:`Emit events as specified`,acceptanceCriteria:e.sideEffects.emits.map(e=>`ref`in e?`Emit ${e.ref.name}.v${e.ref.version} when ${e.when}`:`Emit ${e.name}.v${e.version} when ${e.when}`)}),s.push({order:c++,title:`Write Tests`,description:`Create comprehensive test suite`,acceptanceCriteria:[`All acceptance scenarios covered`,`All error cases tested`,`Edge cases handled`,`Events verified`]});let l={policy:[],security:[],pii:[]};return l.policy.push(`Auth level: ${e.policy.auth}`),e.policy.idempotent!==void 0&&l.policy.push(`Idempotent: ${e.policy.idempotent}`),e.policy.rateLimit&&l.policy.push(`Rate limit: ${e.policy.rateLimit.rpm} rpm per ${e.policy.rateLimit.key}`),e.policy.flags?.length&&l.policy.push(`Feature flags required: ${e.policy.flags.join(`, `)}`),e.policy.escalate&&l.security.push(`Escalation required: ${e.policy.escalate}`),e.policy.pii?.length&&(l.pii=e.policy.pii),{target:{type:`spec`,name:r.name,version:r.version},context:{goal:r.goal,description:r.description,background:r.context},specMarkdown:t(e),fileStructure:i,steps:s,constraints:l,verificationChecklist:[`Input validation works for all cases`,`Output matches expected schema`,`All error cases return correct codes`,`Events are emitted with correct payloads`,`Auth requirements are enforced`,`Rate limiting is applied (if applicable)`,`PII fields are handled correctly`,`All acceptance scenarios pass`,`Tests provide adequate coverage`]}}function c(e,t){let r;return r=t===`claude-code`?`## Implementation Plan: ${e.target.name}.v${e.target.version}
148
+
149
+ ### Context
150
+ **Goal:** ${e.context.goal}
151
+
152
+ **Background:** ${e.context.background}
153
+
154
+ ### Specification
155
+ ${e.specMarkdown}
156
+
157
+ ### File Structure
158
+ ${e.fileStructure.map(e=>`- \`${e.path}\` (${e.type}): ${e.purpose}`).join(`
159
+ `)}
160
+
161
+ ### Implementation Steps
162
+ ${e.steps.map(e=>`
163
+ #### Step ${e.order}: ${e.title}
164
+ ${e.description}
165
+
166
+ **Acceptance Criteria:**
167
+ ${e.acceptanceCriteria.map(e=>`- [ ] ${e}`).join(`
168
+ `)}
169
+ `).join(`
170
+ `)}
171
+
172
+ ### Constraints
173
+ ${e.constraints.policy.length?`**Policy:**\n${e.constraints.policy.map(e=>`- ${e}`).join(`
174
+ `)}\n`:``}
175
+ ${e.constraints.security.length?`**Security:**\n${e.constraints.security.map(e=>`- ${e}`).join(`
176
+ `)}\n`:``}
177
+ ${e.constraints.pii.length?`**PII Handling:**\n${e.constraints.pii.map(e=>`- ${e}`).join(`
178
+ `)}\n`:``}
179
+
180
+ ### Verification Checklist
181
+ ${e.verificationChecklist.map(e=>`- [ ] ${e}`).join(`
182
+ `)}
183
+
184
+ Implement this plan step by step.`:t===`cursor-cli`?`# ${e.target.name}.v${e.target.version}
185
+
186
+ ${e.context.goal}
187
+
188
+ ## Spec
189
+ ${e.specMarkdown}
190
+
191
+ ## Files to create
192
+ ${e.fileStructure.map(e=>`${e.type}: ${e.path}`).join(`
193
+ `)}
194
+
195
+ ## Steps
196
+ ${e.steps.map(e=>`${e.order}. ${e.title}`).join(`
197
+ `)}`:`Implementation plan for ${e.target.name}.v${e.target.version}
198
+
199
+ ${e.specMarkdown}
200
+
201
+ Steps:
202
+ ${e.steps.map(e=>`${e.order}. ${e.title}: ${e.description}`).join(`
203
+ `)}`,{agent:t,systemPrompt:n[t],taskPrompt:r}}function l(e,n,r){return{agent:`generic-mcp`,taskPrompt:`## Fix Specification Violations
204
+
205
+ The following implementation has violations against its specification:
206
+
207
+ **Specification:**
208
+ ${t(e)}
209
+
210
+ **Current Implementation:**
211
+ \`\`\`typescript
212
+ ${n}
213
+ \`\`\`
214
+
215
+ **Violations Found:**
216
+ ${r.map((e,t)=>`${t+1}. ${e.message}${e.suggestion?`\n Suggestion: ${e.suggestion}`:``}`).join(`
217
+ `)}
218
+
219
+ Fix ALL violations while maintaining existing functionality.
220
+ Provide the corrected implementation.`}}export{n as AGENT_SYSTEM_PROMPTS,c as formatPlanForAgent,l as generateFixViolationsPrompt,s as generateImplementationPlan,r as generateImplementationPrompt,a as generateReviewPrompt,i as generateTestPrompt,o as generateVerificationPrompt};
File without changes
@@ -1 +1 @@
1
- import{l as e}from"./schema/dist/ScalarTypeEnum.js";import{t}from"./schema/dist/SchemaModel.js";import"./schema/dist/index.js";import{defineCommand as n,defineQuery as r}from"./spec.js";import{OwnersEnum as i,StabilityEnum as a}from"./ownership.js";const o=new t({name:`SaveOnboardingDraftInput`,description:`Input for saving onboarding draft`,fields:{data:{type:e.JSON(),isOptional:!1}}}),s=new t({name:`SaveOnboardingDraftOutput`,description:`Output for saving onboarding draft`,fields:{id:{type:e.ID(),isOptional:!1},organizationId:{type:e.ID(),isOptional:!1}}}),c=n({meta:{name:`base.onboarding.saveDraft`,version:1,stability:a.Beta,owners:[i.PlatformSigil],tags:[`onboarding`,`draft`],description:`Save or update onboarding draft for active organization`,goal:`Persist onboarding progress incrementally for resumption and safety`,context:`Auto-saves every few seconds during onboarding; enables users to leave and resume`},io:{input:o,output:s},policy:{auth:`user`,escalate:null},transport:{gql:{field:`saveOnboardingDraft`},rest:{method:`POST`}}}),l=new t({name:`GetOnboardingDraftOutput`,description:`Onboarding draft payload`,fields:{id:{type:e.ID(),isOptional:!0},organizationId:{type:e.ID(),isOptional:!0},data:{type:e.JSON(),isOptional:!0},createdAt:{type:e.DateTime(),isOptional:!0},updatedAt:{type:e.DateTime(),isOptional:!0}}}),u=r({meta:{name:`base.onboarding.getDraft`,version:1,stability:a.Beta,owners:[i.PlatformSigil],tags:[`onboarding`,`draft`],description:`Get onboarding draft for active organization`,goal:`Retrieve saved onboarding progress`,context:`Called on mount to restore in-progress onboarding`},io:{input:null,output:l},policy:{auth:`user`,escalate:null},transport:{gql:{field:`getOnboardingDraft`},rest:{method:`GET`}}}),d=new t({name:`DeleteOnboardingDraftOutput`,description:`Result of delete operation`,fields:{ok:{type:e.Boolean(),isOptional:!1}}}),f=n({meta:{name:`base.onboarding.deleteDraft`,version:1,stability:a.Beta,owners:[i.PlatformSigil],tags:[`onboarding`,`draft`],description:`Delete onboarding draft for active organization`,goal:`Clear draft after completion or if user wants to restart`,context:`Called after successful onboarding or explicit user reset`},io:{input:null,output:d},policy:{auth:`user`,escalate:null},transport:{gql:{field:`deleteOnboardingDraft`},rest:{method:`POST`}}}),p=new t({name:`CompleteOnboardingBaseInput`,description:`Input for completing onboarding`,fields:{data:{type:e.JSON(),isOptional:!1}}}),m=new t({name:`CompleteOnboardingBaseOutput`,description:`Result of onboarding completion`,fields:{success:{type:e.Boolean(),isOptional:!1},userId:{type:e.ID(),isOptional:!0},organizationId:{type:e.ID(),isOptional:!0}}}),h=n({meta:{name:`base.onboarding.complete`,version:1,stability:a.Beta,owners:[i.PlatformSigil],tags:[`onboarding`],description:`Complete onboarding and finalize user/organization setup`,goal:`Transition from draft to active profile`,context:`Validates all required fields, creates/updates entities, marks onboarding complete`},io:{input:p,output:m},policy:{auth:`user`,escalate:null},transport:{gql:{field:`completeOnboarding`},rest:{method:`POST`}}});export{p as CompleteOnboardingBaseInput,m as CompleteOnboardingBaseOutput,h as CompleteOnboardingBaseSpec,f as DeleteOnboardingDraftBaseSpec,d as DeleteOnboardingDraftOutput,u as GetOnboardingDraftBaseSpec,l as GetOnboardingDraftOutput,c as SaveOnboardingDraftBaseSpec,o as SaveOnboardingDraftInput,s as SaveOnboardingDraftOutput};
1
+ import{defineCommand as e,defineQuery as t}from"./spec.js";import{OwnersEnum as n,StabilityEnum as r}from"./ownership.js";import{ScalarTypeEnum as i,SchemaModel as a}from"@lssm/lib.schema";const o=new a({name:`SaveOnboardingDraftInput`,description:`Input for saving onboarding draft`,fields:{data:{type:i.JSON(),isOptional:!1}}}),s=new a({name:`SaveOnboardingDraftOutput`,description:`Output for saving onboarding draft`,fields:{id:{type:i.ID(),isOptional:!1},organizationId:{type:i.ID(),isOptional:!1}}}),c=e({meta:{name:`base.onboarding.saveDraft`,version:1,stability:r.Beta,owners:[n.PlatformSigil],tags:[`onboarding`,`draft`],description:`Save or update onboarding draft for active organization`,goal:`Persist onboarding progress incrementally for resumption and safety`,context:`Auto-saves every few seconds during onboarding; enables users to leave and resume`},io:{input:o,output:s},policy:{auth:`user`,escalate:null},transport:{gql:{field:`saveOnboardingDraft`},rest:{method:`POST`}}}),l=new a({name:`GetOnboardingDraftOutput`,description:`Onboarding draft payload`,fields:{id:{type:i.ID(),isOptional:!0},organizationId:{type:i.ID(),isOptional:!0},data:{type:i.JSON(),isOptional:!0},createdAt:{type:i.DateTime(),isOptional:!0},updatedAt:{type:i.DateTime(),isOptional:!0}}}),u=t({meta:{name:`base.onboarding.getDraft`,version:1,stability:r.Beta,owners:[n.PlatformSigil],tags:[`onboarding`,`draft`],description:`Get onboarding draft for active organization`,goal:`Retrieve saved onboarding progress`,context:`Called on mount to restore in-progress onboarding`},io:{input:null,output:l},policy:{auth:`user`,escalate:null},transport:{gql:{field:`getOnboardingDraft`},rest:{method:`GET`}}}),d=new a({name:`DeleteOnboardingDraftOutput`,description:`Result of delete operation`,fields:{ok:{type:i.Boolean(),isOptional:!1}}}),f=e({meta:{name:`base.onboarding.deleteDraft`,version:1,stability:r.Beta,owners:[n.PlatformSigil],tags:[`onboarding`,`draft`],description:`Delete onboarding draft for active organization`,goal:`Clear draft after completion or if user wants to restart`,context:`Called after successful onboarding or explicit user reset`},io:{input:null,output:d},policy:{auth:`user`,escalate:null},transport:{gql:{field:`deleteOnboardingDraft`},rest:{method:`POST`}}}),p=new a({name:`CompleteOnboardingBaseInput`,description:`Input for completing onboarding`,fields:{data:{type:i.JSON(),isOptional:!1}}}),m=new a({name:`CompleteOnboardingBaseOutput`,description:`Result of onboarding completion`,fields:{success:{type:i.Boolean(),isOptional:!1},userId:{type:i.ID(),isOptional:!0},organizationId:{type:i.ID(),isOptional:!0}}}),h=e({meta:{name:`base.onboarding.complete`,version:1,stability:r.Beta,owners:[n.PlatformSigil],tags:[`onboarding`],description:`Complete onboarding and finalize user/organization setup`,goal:`Transition from draft to active profile`,context:`Validates all required fields, creates/updates entities, marks onboarding complete`},io:{input:p,output:m},policy:{auth:`user`,escalate:null},transport:{gql:{field:`completeOnboarding`},rest:{method:`POST`}}});export{p as CompleteOnboardingBaseInput,m as CompleteOnboardingBaseOutput,h as CompleteOnboardingBaseSpec,f as DeleteOnboardingDraftBaseSpec,d as DeleteOnboardingDraftOutput,u as GetOnboardingDraftBaseSpec,l as GetOnboardingDraftOutput,c as SaveOnboardingDraftBaseSpec,o as SaveOnboardingDraftInput,s as SaveOnboardingDraftOutput};
@@ -0,0 +1 @@
1
+ import{defaultRestPath as e,jsonSchemaForSpec as t}from"./jsonschema.js";function n(e,t){return`${e.replace(/\./g,`_`)}_v${t}`}function r(e,t,r){return`${e}_${n(t,r)}`}function i(e,t){return(t??(e===`query`?`GET`:`POST`)).toLowerCase()}function a(t){let n=t.transport?.rest?.path??e(t.meta.name,t.meta.version);return n.startsWith(`/`)?n:`/${n}`}function o(e,o={}){let s=e.listSpecs().filter(e=>e.meta.kind===`command`||e.meta.kind===`query`).slice().sort((e,t)=>{let n=e.meta.name.localeCompare(t.meta.name);return n===0?e.meta.version-t.meta.version:n}),c={openapi:`3.1.0`,info:{title:o.title??`ContractSpec API`,version:o.version??`0.0.0`,...o.description?{description:o.description}:{}},...o.servers?{servers:o.servers}:{},paths:{},components:{schemas:{}}};for(let e of s){let o=t(e),s=i(e.meta.kind,e.transport?.rest?.method),l=a(e),u=n(e.meta.name,e.meta.version),d=c.paths[l]??={},f={operationId:u,summary:e.meta.description??e.meta.name,description:e.meta.description,tags:e.meta.tags??[],"x-contractspec":{name:e.meta.name,version:e.meta.version,kind:e.meta.kind},responses:{}};if(o.input){let t=r(`Input`,e.meta.name,e.meta.version);c.components.schemas[t]=o.input,f.requestBody={required:!0,content:{"application/json":{schema:{$ref:`#/components/schemas/${t}`}}}}}let p={};if(o.output){let t=r(`Output`,e.meta.name,e.meta.version);c.components.schemas[t]=o.output,p[200]={description:`OK`,content:{"application/json":{schema:{$ref:`#/components/schemas/${t}`}}}}}else p[200]={description:`OK`};f.responses=p,d[s]=f}return c}export{o as openApiForRegistry};
@@ -0,0 +1,109 @@
1
+ import{registerDocBlocks as e}from"../../docs/registry.js";import"../../registry.js";const t=[{id:`docs.tech.contracts.openbanking`,title:`Open Banking (Powens) Overview`,summary:`The Pocket Family Office vertical now supports read-only open banking capabilities powered by Powens. This doc summarises the contract surfaces, canonical data models, workflows, telemetry, and guardrails introduced to make Powens a first-class integration.`,kind:`reference`,visibility:`public`,route:`/docs/tech/contracts/openbanking`,tags:[`tech`,`contracts`,`openbanking`],body:`# Open Banking (Powens) Overview
2
+
3
+ The Pocket Family Office vertical now supports read-only open banking capabilities powered by Powens. This doc summarises the contract surfaces, canonical data models, workflows, telemetry, and guardrails introduced to make Powens a first-class integration.
4
+
5
+ ## Integration Spec
6
+
7
+ Powens is registered under \`openbanking.powens\` with category \`open-banking\` and currently supports the BYOK ownership mode. The spec exposes three read-only capabilities:
8
+
9
+ - \`openbanking.accounts.read\`
10
+ - \`openbanking.transactions.read\`
11
+ - \`openbanking.balances.read\`
12
+
13
+ Configuration and secrets are separated:
14
+
15
+ | Config Field | Description |
16
+ | --- | --- |
17
+ | \`environment\` | Powens environment (\`sandbox\` \\| \`production\`) |
18
+ | \`baseUrl?\` | Optional API base URL override |
19
+ | \`region?\` | Optional Powens region identifier |
20
+ | \`pollingIntervalMs?\` | Optional custom sync cadence |
21
+
22
+ | Secret Field | Description |
23
+ | --- | --- |
24
+ | \`clientId\` | Powens OAuth client identifier |
25
+ | \`clientSecret\` | Powens OAuth client secret |
26
+ | \`apiKey?\` | Optional supplemental Powens API key |
27
+ | \`webhookSecret?\` | Optional webhook signing secret |
28
+
29
+ ## Canonical Data Models
30
+
31
+ Canonical schemas live in \`@lssm/lib.contracts/integrations/openbanking/models\`:
32
+
33
+ - \`BankAccountRecord\` – account metadata (institution, IBAN/BIC, masked numbers, balances, sync timestamps)
34
+ - \`BankTransactionRecord\` – transaction ledger (amounts, categories, counterparty, status)
35
+ - \`AccountBalanceRecord\` – balance snapshots per account and balance type
36
+
37
+ These schemas power the vertical contracts and workflows, ensuring downstream features never use raw Powens payloads directly.
38
+
39
+ ## Provider Implementation
40
+
41
+ \`PowensOpenBankingProvider\` wraps \`PowensClient\` which handles OAuth token management, request retries, and error mapping. The provider maps Powens payloads to the canonical interfaces exported from \`integrations/providers/openbanking\`.
42
+
43
+ Factory support lives in \`IntegrationProviderFactory.createOpenBankingProvider\`, which validates configuration, loads BYOK secrets, and instantiates the provider.
44
+
45
+ ## Contracts
46
+
47
+ Command/query contracts exist under \`integrations/openbanking/contracts\`:
48
+
49
+ - \`openbanking.accounts.sync\` & \`openbanking.accounts.list\`
50
+ - \`openbanking.transactions.sync\` & \`openbanking.transactions.list\`
51
+ - \`openbanking.balances.refresh\` & \`openbanking.balances.get\`
52
+
53
+ The Pocket Family Office bundle also exposes \`pfo.openbanking.generate-overview\`, which aggregates balances and transactions into a derived knowledge document.
54
+
55
+ ## Workflows
56
+
57
+ New workflow specs (all requiring the \`primaryOpenBanking\` slot) orchestrate the sync flows:
58
+
59
+ - \`pfo.workflow.sync-openbanking-accounts\`
60
+ - \`pfo.workflow.sync-openbanking-transactions\`
61
+ - \`pfo.workflow.refresh-openbanking-balances\`
62
+ - \`pfo.workflow.generate-openbanking-overview\`
63
+
64
+ Each workflow runs against the Powens provider, persists canonical records, and emits telemetry.
65
+
66
+ ## Knowledge & LLM Exposure
67
+
68
+ Raw Powens payloads are never stored in knowledge spaces. Instead, \`knowledge.financial-overview\` captures derived summaries (cashflow, category breakdowns, balance trends) produced by \`pfo.openbanking.generate-overview\`. The space is \`operational\` category with 180-day retention and automation write access.
69
+
70
+ When exposing data to LLMs or analytics:
71
+
72
+ - Use derived summaries only.
73
+ - Redact PII fields using \`redactOpenBankingTelemetryPayload\`.
74
+ - Never emit IBANs, unmasked account numbers, or counterparty detail in telemetry/logs.
75
+
76
+ ## Telemetry
77
+
78
+ Telemetry constants live in \`integrations/openbanking/telemetry\`. Key events:
79
+
80
+ - \`openbanking.accounts.synced\`
81
+ - \`openbanking.transactions.synced\`
82
+ - \`openbanking.balances.refreshed\`
83
+ - \`openbanking.overview.generated\`
84
+
85
+ All events require tenant/app/blueprint/config metadata, and sensitive properties are flagged to avoid accidental leakage.
86
+
87
+ ## Guardrails
88
+
89
+ \`ensurePrimaryOpenBankingIntegration\` verifies \`primaryOpenBanking\` is bound and healthy before workflows proceed. Runtime pre-flight checks already block workflows when the connection is disconnected or in error status.
90
+
91
+ ## Blueprint & Tenant Defaults
92
+
93
+ \`pocketFamilyOfficeBlueprint\` now includes:
94
+
95
+ - \`primaryOpenBanking\` slot (required, BYOK)
96
+ - \`openbanking.*.read\` capabilities enabled by default
97
+ - Workflow bindings for the new sync flows
98
+
99
+ Sample tenant bindings (\`tenant.sample.ts\`) reference \`conn-powens-primary\` and bind the new knowledge space.
100
+
101
+ ---
102
+
103
+ Follow this doc when extending open banking support (e.g., adding payment initiation, additional providers, or expanded analytics) to keep the integration consistent and audited.
104
+
105
+
106
+
107
+
108
+
109
+ `}];e(t);export{t as tech_contracts_openbanking_DocBlocks};
@@ -0,0 +1 @@
1
+ import{registerDocBlocks as e}from"../../docs/registry.js";import"../../registry.js";const t=[{id:`docs.tech.contracts.policy`,title:`PolicySpec & PolicyEngine`,summary:"`PolicySpec` gives a declarative, typed home for access-control logic covering:",kind:`reference`,visibility:`public`,route:`/docs/tech/contracts/policy`,tags:[`tech`,`contracts`,`policy`],body:"# PolicySpec & PolicyEngine\n\n## Purpose\n\n`PolicySpec` gives a declarative, typed home for access-control logic covering:\n- **Who** can perform an action (ABAC/ReBAC style rules)\n- **What** they can access (resources + optional field-level overrides)\n- **When** special conditions apply (contextual expressions)\n- **How** PII should be handled (consent/retention hints)\n\n`PolicyEngine` evaluates one or more policies and returns an `allow`/`deny` decision, field-level outcomes, and PII metadata suitable for downstream enforcement (`SpecRegistry` → `ctx.decide`).\n\n## Location\n\n- Types & registry: `packages/libs/contracts/src/policy/spec.ts`\n- Runtime evaluation: `packages/libs/contracts/src/policy/engine.ts`\n- Tests: `packages/.../policy/engine.test.ts`\n\n## `PolicySpec`\n\n```ts\nexport interface PolicySpec {\n meta: PolicyMeta; // ownership metadata + { name, version, scope? }\n rules: PolicyRule[]; // allow/deny rules for actions\n fieldPolicies?: FieldPolicyRule[];\n pii?: { fields: string[]; consentRequired?: boolean; retentionDays?: number };\n relationships?: RelationshipDefinition[];\n consents?: ConsentDefinition[];\n rateLimits?: RateLimitDefinition[];\n opa?: { package: string; decision?: string };\n}\n```\n\n- `PolicyRule`\n - `effect`: `'allow' | 'deny'`\n - `actions`: e.g., `['read', 'write', 'delete']` (string namespace is flexible)\n - `subject`: `{ roles?: string[]; attributes?: { attr: matcher } }`\n - `resource`: `{ type: string; fields?: string[]; attributes?: {...} }`\n - `relationships`: `{ relation, objectId?, objectType? }[]` → ReBAC checks (use `objectId: '$resource'` to target the current resource)\n - `requiresConsent`: `['consent_id']` → references spec-level consent definitions\n - `flags`: feature flags that must be enabled (`DecisionContext.flags`)\n - `rateLimit`: string reference to `rateLimits` entry or inline object `{ rpm, key?, windowSeconds?, burst? }`\n - `escalate`: `'human_review' | null` to indicate manual approval\n - `conditions`: optional expression snippets evaluated against `{ subject, resource, context }`\n- `FieldPolicyRule`\n - `field`: dot-path string (e.g., `contact.email`)\n - `actions`: subset of `['read', 'write']`\n - Same `subject` / `resource` / `conditions` shape\n - Useful for redacting specific fields, even when the global action is allowed\n- `RelationshipDefinition`\n - Canonical tuples for relationship graph (`subjectType`, `relation`, `objectType`, `transitive?`)\n- `ConsentDefinition`\n - `{ id, scope, purpose, lawfulBasis?, expiresInDays?, required? }`\n- `RateLimitDefinition`\n - `{ id, rpm, key?, windowSeconds?, burst? }`\n- `PolicyRef`\n - `{ name: string; version: number }` → attach to contract specs / workflows\n\n## Registry\n\n```ts\nconst registry = new PolicyRegistry();\nregistry.register(CorePolicySpec);\nconst spec = registry.get('core.default', 1);\n```\n\nGuarantees uniqueness per `(name, version)` and exposes helpers to resolve highest versions.\n\n## Engine\n\n```ts\nconst engine = new PolicyEngine(policyRegistry);\n\nconst decision = engine.decide({\n action: 'read',\n subject: { roles: ['admin'] },\n resource: { type: 'resident', fields: ['contact.email'] },\n policies: [{ name: 'core.default', version: 1 }],\n});\n/*\n{\n effect: 'allow',\n reason: 'core.default',\n fieldDecisions: [{ field: 'contact.email', effect: 'allow' }],\n pii: { fields: ['contact.email'], consentRequired: true }\n}\n*/\n```\n\n- First matching **deny** wins; otherwise the first **allow** is returned.\n- Field policies are aggregated across referenced policies:\n - Later denies override earlier allows for a given field.\n - Returned as `fieldDecisions` to simplify downstream masking.\n- PII metadata is surfaced when defined to help adapt logging/telemetry.\n\n### Expression Support\n\nConditions accept small JS snippets (e.g., `subject.attributes.orgId === context.orgId`). The engine runs them in a constrained scope (`subject`, `resource`, `context`) without access to global state.\n\n### ReBAC & Relationships\n\n- Provide relationship tuples via `PolicySpec.relationships` for documentation/validation.\n- Reference them inside rules with `relationships: [{ relation: 'manager_of', objectType: 'resident', objectId: '$resource' }]`.\n- The execution context must populate `subject.relationships` (`[{ relation, object, objectType }]`) for the engine to evaluate ReBAC guards.\n\n### Consent & Rate Limits\n\n- Declare reusable consent definitions under `consents`. Rules list the IDs they require; if a user session lacks the consent (`DecisionContext.consents`), the engine returns `effect: 'deny'` with `reason: 'consent_required'` and enumerates missing consents.\n- Attach rate limits either inline or via `rateLimits` references. When a rule matches, the engine surfaces `{ rpm, key, windowSeconds?, burst? }` so callers can feed it to shared limiters.\n\n### OPA Adapter\n\n- `OPAPolicyAdapter` bridges engine decisions to Open Policy Agent (OPA). It forwards the evaluation context + policies to OPA and merges any override result (`effect`, `reason`, `fieldDecisions`, `requiredConsents`).\n- Use when migrating to OPA policies or running defense-in-depth: call `engine.decide()`, then pass the preliminary decision to `adapter.evaluate(...)`. The adapter marks merged decisions with `evaluatedBy: 'opa'`.\n- OPA inputs include meta, rules, relationships, rate limits, and consent catalogs to simplify policy authoring on the OPA side.\n\n## Contract Integration\n\n`ContractSpec.policy` now supports:\n\n```ts\npolicy: {\n auth: 'anonymous' | 'user' | 'admin';\n ...\n policies?: PolicyRef[]; // policies evaluated before execution\n fieldPolicies?: { // field hints (read/write) per policy\n field: string;\n actions: ('read' | 'write')[];\n policy?: PolicyRef;\n }[];\n}\n```\n\nAdapters can resolve refs through a shared `PolicyEngine` and populate `ctx.decide` so `SpecRegistry.execute` benefits from centralized enforcement.\n\n## Authoring Guidelines\n\n1. Prefer **allow-by-default** policies but explicitly deny sensitive flows (defense-in-depth).\n2. Keep rule scopes narrow (per feature/operation) and compose multiple `PolicyRef`s when necessary.\n3. Store PII field lists here to avoid duplication across logs/telemetry.\n4. Use explicit rule reasons for auditability and better developer feedback.\n5. Treat versioning seriously; bump `meta.version` whenever behavior changes.\n\n## Future Enhancements\n\n- Richer expression language (composable predicates, time-based conditions).\n- Multi-tenant relationship graph services (store/resolve relationships at scale).\n- Tooling that auto-generates docs/tests for policies referenced in specs.\n\n"}];e(t);export{t as tech_contracts_policy_DocBlocks};
@@ -0,0 +1,8 @@
1
+ import{registerDocBlocks as e}from"../../docs/registry.js";import"../../registry.js";const t=[{id:`docs.tech.contracts.presentations-conventions`,title:`Presentations Conventions (A11y & i18n)`,summary:"- Always provide `meta.description` (≥ 3 chars) — used by a11y/docs/agents.",kind:`reference`,visibility:`public`,route:`/docs/tech/contracts/presentations-conventions`,tags:[`tech`,`contracts`,`presentations-conventions`],body:`## Presentations Conventions (A11y & i18n)
2
+
3
+ - Always provide \`meta.description\` (≥ 3 chars) — used by a11y/docs/agents.
4
+ - Prefer source = BlockNote for rich guides; use component key for interactive flows.
5
+ - i18n strings belong in host apps; descriptors carry keys/defaults only.
6
+ - Target selection: include only what you intend to support to avoid drift.
7
+ - PII: declare JSON-like paths under \`policy.pii\`; engine redacts in outputs.
8
+ `}];e(t);export{t as tech_contracts_presentations_conventions_DocBlocks};
@@ -1 +1 @@
1
- import e from"zod";function t(e){return`${e.meta.name}.v${e.meta.version}`}var n=class{items=new Map;register(e){let n=t(e);if(this.items.has(n))throw Error(`Duplicate presentation ${n}`);return this.items.set(n,e),this}list(){return[...this.items.values()]}get(e,t){if(t!=null)return this.items.get(`${e}.v${t}`);let n,r=-1/0;for(let[t,i]of this.items.entries())t.startsWith(`${e}.v`)&&i.meta.version>r&&(r=i.meta.version,n=i);return n}};function r(t){let n={meta:{name:t.meta.name,version:t.meta.version,stability:t.meta.stability??`stable`,tags:t.meta.tags??[],description:t.meta.description??``},kind:t.content.kind};return t.content.kind===`web_component`?{...n,framework:t.content.framework,componentKey:t.content.componentKey,props:e.toJSONSchema(t.content.props.getZod())}:t.content.kind===`markdown`?{...n,content:t.content.content,resourceUri:t.content.resourceUri}:{...n,mimeType:t.content.mimeType,model:e.toJSONSchema(t.content.model.getZod())}}export{n as PresentationRegistry,r as jsonSchemaForPresentation};
1
+ import e from"zod";function t(e){return`${e.meta.name}.v${e.meta.version}`}var n=class{items=new Map;constructor(e){e&&e.forEach(e=>this.register(e))}register(e){let n=t(e);if(this.items.has(n))throw Error(`Duplicate presentation ${n}`);return this.items.set(n,e),this}list(){return[...this.items.values()]}get(e,t){if(t!=null)return this.items.get(`${e}.v${t}`);let n,r=-1/0;for(let[t,i]of this.items.entries())t.startsWith(`${e}.v`)&&i.meta.version>r&&(r=i.meta.version,n=i);return n}};function r(t){let n={meta:{name:t.meta.name,version:t.meta.version,stability:t.meta.stability??`stable`,tags:t.meta.tags??[],description:t.meta.description??``},kind:t.content.kind};return t.content.kind===`web_component`?{...n,framework:t.content.framework,componentKey:t.content.componentKey,props:e.toJSONSchema(t.content.props.getZod())}:t.content.kind===`markdown`?{...n,content:t.content.content,resourceUri:t.content.resourceUri}:{...n,mimeType:t.content.mimeType,model:e.toJSONSchema(t.content.model.getZod())}}export{n as PresentationRegistry,r as jsonSchemaForPresentation};
@@ -1 +1,7 @@
1
- var e=class{renderers=new Map;validators=[];register(e){let t=this.renderers.get(e.target)??[];return t.push(e),this.renderers.set(e.target,t),this}addValidator(e){return this.validators.push(e),this}async render(e,t,n){if(!t.targets.includes(e))throw Error(`Target ${e} not declared for ${t.meta.name}.v${t.meta.version}`);for(let r of this.validators)await r.validate(t,e,n);let r=this.renderers.get(e)??[];for(let e of r)try{return await e.render(t,n)}catch{}throw Error(`No renderer available for ${e}`)}};function t(){let t=new e,n=(e,t)=>{let n=JSON.parse(JSON.stringify(t)),r=e.policy?.pii??[],i=(e,t)=>{let n=t.replace(/^\//,``).replace(/\[(\d+)\]/g,`.$1`).split(`.`).filter(Boolean),r=e;for(let e=0;e<n.length-1;e++){let t=n[e];if(r&&typeof r==`object`&&t in r)r=r[t];else return}let i=n[n.length-1];r&&typeof r==`object`&&i&&i in r&&(r[i]=`[REDACTED]`)};for(let e of r)i(n,e);return n};return t.register({target:`markdown`,async render(e){if(e.source.type===`blocknotejs`){let t=n(e,{text:typeof e.source.docJson==`string`?e.source.docJson:JSON.stringify(e.source.docJson)});return{mimeType:`text/markdown`,body:String(t.text)}}if(e.source.type===`component`)return{mimeType:`text/markdown`,body:`${`# ${e.meta.name} v${e.meta.version}`}${e.meta.description?`\n\n${e.meta.description}`:``}${e.meta.tags&&e.meta.tags.length?`\n\nTags: ${e.meta.tags.join(`, `)}`:``}${e.meta.owners&&e.meta.owners.length?`\n\nOwners: ${e.meta.owners.join(`, `)}`:``}${`\n\nComponent: \`${e.source.componentKey}\``}${e.policy?.pii?.length?`\n\nRedacted paths: ${e.policy.pii.map(e=>`\`${e}\``).join(`, `)}`:``}`};throw Error(`unsupported`)}}),t.register({target:`application/json`,async render(e){let t=n(e,{meta:e.meta,source:e.source});return{mimeType:`application/json`,body:JSON.stringify(t,null,2)}}}),t.register({target:`application/xml`,async render(e){let t=n(e,{meta:e.meta,source:e.source});return{mimeType:`application/xml`,body:`<presentation name="${e.meta.name}" version="${e.meta.version}"><json>${encodeURIComponent(JSON.stringify(t))}</json></presentation>`}}}),t}function n(e){return e.register({target:`react`,async render(e){if(e.source.type===`component`){let t=e.source.props&&e.source.props.getZod().safeParse({}).success?{}:void 0;return{kind:`react_component`,componentKey:e.source.componentKey,props:t}}return{kind:`blocknotejs`,docJson:e.source.docJson,blockConfig:e.source.blockConfig}}}),e}function r(e){return e.addValidator({validate(e){if(!e.meta.description||e.meta.description.length<3)throw Error(`Presentation ${e.meta.name}.v${e.meta.version} missing meta.description`)}}),e}export{e as TransformEngine,t as createDefaultTransformEngine,r as registerBasicValidation,n as registerDefaultReactRenderer};
1
+ import{schemaToMarkdown as e}from"./schema-to-markdown.js";import t from"react";import n from"turndown";const r=new n;function i(e){let t=e.text??``;return!e.marks||e.marks.length===0?t:e.marks.reduce((e,t)=>{switch(t.type){case`bold`:return`**${e}**`;case`italic`:return`*${e}*`;case`underline`:return`__${e}__`;case`strike`:return`~~${e}~~`;case`code`:return`\`${e}\``;case`link`:{let n=t.attrs?.href??``;return n?`[${e}](${n})`:e}default:return e}},t)}function a(e){return e?.length?e.map(e=>s(e)).join(``):``}function o(e,t=!1){if(!e?.length)return``;let n=1;return e.map(e=>{let r=a(e.content??[]);return r?`${t?`${n++}. `:`- `}${r}`:``}).filter(Boolean).join(`
2
+ `)}function s(e){switch(e.type){case`doc`:return a(e.content);case`paragraph`:{let t=a(e.content);return t.trim().length?t:``}case`heading`:{let t=Math.min(Math.max(e.attrs?.level??1,1),6);return`${`#`.repeat(t)} ${a(e.content)}`.trim()}case`bullet_list`:return o(e.content,!1);case`ordered_list`:return o(e.content,!0);case`list_item`:return a(e.content);case`blockquote`:return a(e.content).split(`
3
+ `).map(e=>`> ${e}`).join(`
4
+ `);case`code_block`:{let t=a(e.content);return t?`\`\`\`\n${t}\n\`\`\``:``}case`horizontal_rule`:return`---`;case`hard_break`:return`
5
+ `;case`text`:return i(e);default:return e.text?i(e):``}}function c(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&`html`in e){let t=String(e.html);return r.turndown(t)}let t=e;if(t?.type===`doc`||t?.content)return(t.content??[]).map(e=>s(e)).filter(Boolean).join(`
6
+
7
+ `).trim();try{return JSON.stringify(e,null,2)}catch{return String(e)}}var l=class{renderers=new Map;validators=[];register(e){let t=this.renderers.get(e.target)??[];return t.push(e),this.renderers.set(e.target,t),this}prependRegister(e){let t=this.renderers.get(e.target)??[];return t.unshift(e),this.renderers.set(e.target,t),this}addValidator(e){return this.validators.push(e),this}async render(e,t,n){if(!t.targets.includes(e))throw Error(`Target ${e} not declared for ${t.meta.name}.v${t.meta.version}`);for(let r of this.validators)await r.validate(t,e,n);let r=this.renderers.get(e)??[];for(let e of r)try{return await e.render(t,n)}catch{}throw Error(`No renderer available for ${e}`)}};function u(){let t=new l,n=(e,t)=>{let n=JSON.parse(JSON.stringify(t)),r=e.policy?.pii??[],i=(e,t)=>{let n=t.replace(/^\//,``).replace(/\[(\d+)\]/g,`.$1`).split(`.`).filter(Boolean),r=e;for(let e=0;e<n.length-1;e++){let t=n[e];if(r&&typeof r==`object`&&t in r)r=r[t];else return}let i=n[n.length-1];r&&typeof r==`object`&&i&&i in r&&(r[i]=`[REDACTED]`)};for(let e of r)i(n,e);return n};return t.register({target:`markdown`,async render(t,r){let i=r?.data;if(!i&&r?.fetchData&&(i=await r.fetchData()),t.source.type===`component`&&t.source.props&&i!==void 0){let n=Array.isArray(i),r=!n&&typeof i==`object`&&!!i&&!Object.values(i).some(e=>Array.isArray(e)||typeof e==`object`&&!!e);if(n||r)return{mimeType:`text/markdown`,body:e(t.source.props,i,{title:t.meta.description??t.meta.name,description:`${t.meta.name} v${t.meta.version}`})};throw Error(`Complex data structure for ${t.meta.name} - expecting custom renderer`)}if(t.source.type===`blocknotejs`){let e=n(t,{text:c(t.source.docJson)});return{mimeType:`text/markdown`,body:String(e.text)}}if(t.source.type===`component`&&i!==void 0)throw Error(`No schema (source.props) available for ${t.meta.name} - expecting custom renderer`);if(t.source.type===`component`)return{mimeType:`text/markdown`,body:`${`# ${t.meta.name} v${t.meta.version}`}${t.meta.description?`\n\n${t.meta.description}`:``}${t.meta.tags&&t.meta.tags.length?`\n\nTags: ${t.meta.tags.join(`, `)}`:``}${t.meta.owners&&t.meta.owners.length?`\n\nOwners: ${t.meta.owners.join(`, `)}`:``}${`\n\nComponent: \`${t.source.componentKey}\``}${t.policy?.pii?.length?`\n\nRedacted paths: ${t.policy.pii.map(e=>`\`${e}\``).join(`, `)}`:``}`};throw Error(`unsupported`)}}),t.register({target:`application/json`,async render(e){let t=n(e,{meta:e.meta,source:e.source});return{mimeType:`application/json`,body:JSON.stringify(t,null,2)}}}),t.register({target:`application/xml`,async render(e){let t=n(e,{meta:e.meta,source:e.source});return{mimeType:`application/xml`,body:`<presentation name="${e.meta.name}" version="${e.meta.version}"><json>${encodeURIComponent(JSON.stringify(t))}</json></presentation>`}}}),t}function d(e){return e.register({target:`react`,async render(e){if(e.source.type===`component`){let t=e.source.props&&e.source.props.getZod().safeParse({}).success?{}:void 0;return{kind:`react_component`,componentKey:e.source.componentKey,props:t}}return{kind:`blocknotejs`,docJson:e.source.docJson,blockConfig:e.source.blockConfig}}}),e}function f(e){return e.addValidator({validate(e){if(!e.meta.description||e.meta.description.length<3)throw Error(`Presentation ${e.meta.name}.v${e.meta.version} missing meta.description`)}}),e}function p(e,r){let i=new n({headingStyle:`atx`,codeBlockStyle:`fenced`,bulletListMarker:`-`});return i.addRule(`link`,{filter:`a`,replacement:(e,t)=>{let n=t.href;return n&&e?`[${e}](${n})`:e||``}}),e.prependRegister({target:`markdown`,async render(e,n){if(e.source.type!==`component`)throw Error(`React-to-markdown renderer only handles component presentations`);let{renderToStaticMarkup:a}=await import(`react-dom/server`),o=r[e.source.componentKey];if(!o)throw Error(`Component ${e.source.componentKey} not found in componentMap`);let s;try{s=a(t.createElement(o,e.source.props?{}:void 0))}catch(t){throw Error(`Failed to render component ${e.source.componentKey}: ${t instanceof Error?t.message:`Unknown error`}`)}let c;try{c=i.turndown(s)}catch(e){throw Error(`Failed to convert HTML to markdown: ${e instanceof Error?e.message:`Unknown error`}`)}return e.policy?.pii&&e.policy.pii.length>0?{mimeType:`text/markdown`,body:c.replace(/\[REDACTED\]/g,`[REDACTED]`)}:{mimeType:`text/markdown`,body:c}}}),e}export{l as TransformEngine,u as createDefaultTransformEngine,f as registerBasicValidation,d as registerDefaultReactRenderer,p as registerReactToMarkdownRenderer};
package/dist/prompt.js CHANGED
@@ -1 +1 @@
1
- import{z as e}from"zod";function t(e){return e}export{t as definePrompt};
1
+ import"zod";function e(e){return e}export{e as definePrompt};
@@ -1 +1 @@
1
- import{z as e}from"zod";var t=class{prompts=new Map;register(e){let t=`${e.meta.name}.v${e.meta.version}`;if(this.prompts.has(t))throw Error(`Duplicate prompt ${t}`);return this.prompts.set(t,e),this}list(){return[...this.prompts.values()]}get(e,t){if(t!=null)return this.prompts.get(`${e}.v${t}`);let n,r=-1/0;for(let[t,i]of this.prompts.entries())t.startsWith(`${e}.v`)&&i.meta.version>r&&(r=i.meta.version,n=i);return n}};export{t as PromptRegistry};
1
+ import"zod";var e=class{prompts=new Map;register(e){let t=`${e.meta.name}.v${e.meta.version}`;if(this.prompts.has(t))throw Error(`Duplicate prompt ${t}`);return this.prompts.set(t,e),this}list(){return[...this.prompts.values()]}get(e,t){if(t!=null)return this.prompts.get(`${e}.v${t}`);let n,r=-1/0;for(let[t,i]of this.prompts.entries())t.startsWith(`${e}.v`)&&i.meta.version>r&&(r=i.meta.version,n=i);return n}};export{e as PromptRegistry};
@@ -0,0 +1,184 @@
1
+ import{registerDocBlocks as e}from"../../docs/registry.js";import"../../registry.js";const t=[{id:`docs.tech.contracts.regenerator`,title:`Regenerator Service`,summary:`The Regenerator daemon observes telemetry, error, and behavior streams, then suggests spec-level changes (not code patches) that can be reviewed and applied through the App Studio.`,kind:`reference`,visibility:`public`,route:`/docs/tech/contracts/regenerator`,tags:[`tech`,`contracts`,`regenerator`],body:`## Regenerator Service
2
+
3
+ The Regenerator daemon observes telemetry, error, and behavior streams, then suggests spec-level changes (not code patches) that can be reviewed and applied through the App Studio.
4
+
5
+ - Runtime entrypoint: \`packages/libs/contracts/src/regenerator/service.ts\`
6
+ - Types/interfaces: \`packages/libs/contracts/src/regenerator/types.ts\`
7
+ - Signal adapters: \`packages/libs/contracts/src/regenerator/adapters.ts\`
8
+
9
+ ### Architecture
10
+
11
+ \`\`\`text
12
+ Signal Adapters ──► RegeneratorService ──► Rules ──► ProposalSink
13
+ ▲ │
14
+ │ ▼
15
+ Telemetry / Errors / Behavior Spec change proposals
16
+ \`\`\`
17
+
18
+ 1. **Signal adapters** pull batches of telemetry, error logs, or behavior metrics for each \`RegenerationContext\`.
19
+ 2. \`RegeneratorService\` schedules polling (\`resolveAppConfig\` + \`composeAppConfig\` provide context).
20
+ 3. **Rules** implement domain heuristics and emit \`SpecChangeProposal\` objects.
21
+ 4. **Proposal sinks** persist or forward proposals for human review.
22
+
23
+ ### Key types
24
+
25
+ \`\`\`ts
26
+ export interface RegenerationContext {
27
+ id: string;
28
+ blueprint: AppBlueprintSpec;
29
+ tenantConfig: TenantAppConfig;
30
+ resolved: ResolvedAppConfig;
31
+ }
32
+
33
+ export interface RegeneratorRule {
34
+ id: string;
35
+ description: string;
36
+ evaluate(
37
+ context: RegenerationContext,
38
+ signals: RegeneratorSignal[]
39
+ ): Promise<SpecChangeProposal[]>;
40
+ }
41
+
42
+ export interface SpecChangeProposal {
43
+ id: string;
44
+ title: string;
45
+ summary: string;
46
+ confidence: 'low' | 'medium' | 'high';
47
+ target: ProposalTarget;
48
+ actions: ProposalAction[];
49
+ blockers?: ProposalBlocker[];
50
+ signalIds: string[];
51
+ createdAt: Date;
52
+ }
53
+ \`\`\`
54
+
55
+ - Signals are normalized envelopes: telemetry (\`count\`, anomaly score), errors, and behavior trends.
56
+ - Proposals reference blueprint or tenant specs via \`ProposalTarget\`.
57
+ - Actions encode what the automation should perform (update blueprint, run tests/migrations, trigger regeneration).
58
+
59
+ ### Providing signals
60
+
61
+ Implement \`TelemetrySignalProvider\`, \`ErrorSignalProvider\`, or \`BehaviorSignalProvider\`:
62
+
63
+ \`\`\`ts
64
+ const service = new RegeneratorService({
65
+ contexts,
66
+ adapters: {
67
+ telemetry: new PosthogTelemetryAdapter(),
68
+ errors: new SentryErrorAdapter(),
69
+ },
70
+ rules: [new WorkflowFailureRule(), new DataViewUsageRule()],
71
+ sink: new ProposalQueueSink(),
72
+ pollIntervalMs: 60_000,
73
+ });
74
+ \`\`\`
75
+
76
+ Adapters receive the full \`RegenerationContext\`, making it easy to scope queries per tenant/app.
77
+
78
+ ### Authoring rules
79
+
80
+ Rules focus on signals → proposals:
81
+
82
+ \`\`\`ts
83
+ class WorkflowFailureRule implements RegeneratorRule {
84
+ id = 'workflow-failure';
85
+ description = 'Suggest splitting workflows that exceed failure thresholds';
86
+
87
+ async evaluate(context, signals) {
88
+ const failures = signals.filter(
89
+ (signal) =>
90
+ signal.type === 'telemetry' &&
91
+ signal.signal.eventName === 'workflow.failure' &&
92
+ signal.signal.count >= 10
93
+ );
94
+
95
+ if (failures.length === 0) return [];
96
+
97
+ return [
98
+ {
99
+ id: \`\${this.id}-\${context.id}\`,
100
+ title: 'Split onboarding workflow',
101
+ summary: 'Step 3 fails consistently; propose dedicated remediation branch.',
102
+ confidence: 'medium',
103
+ rationale: ['Failure count ≥ 10 within last window'],
104
+ target: {
105
+ specType: 'workflow',
106
+ reference: { name: 'onboarding.workflow', version: 1 },
107
+ tenantScoped: true,
108
+ },
109
+ actions: [
110
+ { kind: 'update_tenant_config', summary: 'Add alternate fallback path' },
111
+ { kind: 'run_tests', tests: ['workflows/onboarding.spec.ts'] },
112
+ ],
113
+ signalIds: failures.map((f) => f.signal.eventName),
114
+ createdAt: new Date(),
115
+ },
116
+ ];
117
+ }
118
+ }
119
+ \`\`\`
120
+
121
+ ### Reviewing proposals
122
+
123
+ Proposals flow to a \`ProposalSink\` (queue, DB, messaging bus). The Studio will surface:
124
+
125
+ 1. Signal evidence (telemetry counts, error metadata)
126
+ 2. Proposed spec diffs and required actions (tests/migrations)
127
+ 3. Approval workflow (approve → write spec diff → run automation)
128
+
129
+ ### CLI driver
130
+
131
+ Run the regenerator daemon from the CLI:
132
+
133
+ \`\`\`bash
134
+ bunx contracts regenerator ./app.blueprint.ts ./tenant.config.ts ./regenerator.rules.ts auto \\
135
+ --executor ./regenerator.executor.ts \\
136
+ --poll-interval 60000 \\
137
+ --batch-duration 300000 \\
138
+ --dry-run
139
+ \`\`\`
140
+
141
+ - Expects modules exporting default \`AppBlueprintSpec\`, \`TenantAppConfig\`, and one or more \`RegenerationRule\`s.
142
+ - Pass a sink module path, or use the special \`auto\` value with \`--executor <module>\` to instantiate an \`ExecutorProposalSink\`.
143
+ - Executor modules can export a \`ProposalExecutor\` instance, a factory, or a plain dependency object for the executor constructor. Optional exports: \`sinkOptions\`, \`logger\`, \`onResult\`, \`dryRun\`.
144
+ - Optionally provide \`--contexts ./contexts.ts\` to load custom context arrays (advanced multi-tenant scenarios).
145
+ - Use \`--dry-run\` to preview actions without mutating specs/configs, and \`--once\` for CI smoke tests.
146
+
147
+ ### Proposal executor
148
+
149
+ \`ProposalExecutor\` + \`ExecutorProposalSink\` orchestrate follow-up actions once a proposal is approved:
150
+
151
+ - Interfaces for applying blueprint or tenant-config updates (\`BlueprintUpdater\`, \`TenantConfigUpdater\`).
152
+ - Hooks for running contract tests and migrations (\`TestExecutor\`, \`MigrationExecutor\`).
153
+ - Optional trigger to recompose the runtime (\`RegenerationTrigger\`).
154
+ - Built-in \`dryRun\` mode to preview outcomes.
155
+ - Pluggable result logging/forwarding via \`ExecutorSinkOptions\`.
156
+
157
+ \`\`\`ts
158
+ import {
159
+ ProposalExecutor,
160
+ ExecutorProposalSink,
161
+ } from '@lssm/lib.contracts/regenerator';
162
+
163
+ const executor = new ProposalExecutor({
164
+ tenantConfigUpdater,
165
+ testExecutor,
166
+ migrationExecutor,
167
+ regenerationTrigger,
168
+ });
169
+
170
+ const sink = new ExecutorProposalSink(executor, {
171
+ dryRun: false,
172
+ onResult: ({ result }) => console.log(result.status),
173
+ });
174
+ \`\`\`
175
+
176
+ Execution results include per-action status (\`success\`, \`skipped\`, \`failed\`) plus aggregated proposal status (\`success\`, \`partial\`, \`failed\`). Missing dependencies mark actions as \`skipped\`, making it easy to plug into partial automation flows today and extend later.
177
+
178
+ ### Next steps
179
+
180
+ - Build adapters for existing telemetry/error providers.
181
+ - Encode canonical rules (workflow failure, feature under-use, high latency).
182
+ - Integrate with App Studio proposal inbox and automate acceptance (write spec diff, run tests, queue migrations).
183
+
184
+ `}];e(t);export{t as tech_contracts_regenerator_DocBlocks};
package/dist/registry.js CHANGED
@@ -1 +1 @@
1
- import{eventKey as e}from"./events.js";import{isEmitDeclRef as t}from"./spec.js";function n(e,t){return`${e}.v${t}`}var r=class{specs=new Map;handlers=new Map;register(e){let t=n(e.meta.name,e.meta.version);if(this.specs.has(t))throw Error(`Duplicate spec ${t}`);return this.specs.set(t,e),this}bind(e,t){let r=n(e.meta.name,e.meta.version);if(!this.specs.has(r))throw Error(`Cannot bind; spec not found: ${r}`);if(this.handlers.has(r))throw Error(`Handler already bound for ${r}`);return this.handlers.set(r,t),this}getSpec(e,t){if(t!=null)return this.specs.get(n(e,t));let r,i=-1/0;for(let[t,n]of this.specs.entries())t.startsWith(`${e}.v`)&&n.meta.version>i&&(i=n.meta.version,r=n);return r}getHandler(e,t){let r=this.getSpec(e,t);if(r)return this.handlers.get(n(r.meta.name,r.meta.version))}listSpecs(){return[...this.specs.values()]}listBound(){let e=[];for(let[t,n]of this.specs.entries()){let r=this.handlers.get(t);r&&e.push({spec:n,handler:r})}return e}async execute(r,i,a,o){let s=this.getSpec(r,i);if(!s)throw Error(`Spec not found for ${r}${i?`.v${i}`:``}`);let c=await o.specVariantResolver?.resolve({name:s.meta.name,version:s.meta.version,kind:s.meta.kind},o)??s,l=n(c.meta.name,c.meta.version),u=this.handlers.get(l);if(!u){let e=n(s.meta.name,s.meta.version);u=this.handlers.get(e),l=e}if(!u)throw Error(`No handler bound for ${l}`);let d=c.io.input?.getZod().parse(a);if(o.decide){let[e,t]=c.meta.name.split(`.`),n=await o.decide({service:e,command:t,version:c.meta.version,actor:o.actor??`anonymous`,channel:o.channel,roles:o.roles,organizationId:o.organizationId,userId:o.userId,flags:[]});if(n.effect===`deny`)throw Error(`PolicyDenied: ${c.meta.name}.v${c.meta.version}`);if(n.rateLimit&&o.rateLimit){let e=n.rateLimit.key??`default`,t=n.rateLimit.rpm??60;await o.rateLimit(e,1,t)}}let f=new Map;if(c.sideEffects?.emits)for(let e of c.sideEffects.emits)t(e)?f.set(`${e.ref.name}.v${e.ref.version}`,e.ref.payload):f.set(`${e.name}.v${e.version}`,e.payload);let p=async(t,r,i)=>{let a=e(t,r),s=f.get(a);if(!s)throw Error(`UndeclaredEvent: ${a} not allowed by ${n(c.meta.name,c.meta.version)}`);let l=s.getZod().parse(i);await o.eventPublisher?.({name:t,version:r,payload:l,traceId:o.traceId})};o.appConfig&&(o.branding||=o.appConfig.branding,o.translation?o.translation.config||(o.translation={...o.translation,config:o.appConfig.translation}):o.translation={config:o.appConfig.translation});let m=o.telemetry,h=async(e,t)=>{if(!(!m||!e?.event))try{let n=e.properties?.(t)??{};await m.track(e.event.name,e.event.version??1,n,{tenantId:o.organizationId??void 0,organizationId:o.organizationId,userId:o.userId,actor:o.actor,channel:o.channel,metadata:o.traceId?{traceId:o.traceId}:void 0})}catch{}},g;try{g=await u(d,{...o,__emitGuard__:p})}catch(e){throw c.telemetry?.failure&&await h(c.telemetry.failure,{input:d??a,error:e}),e}c.telemetry?.success&&await h(c.telemetry.success,{input:d??a,output:g});let _=c.io.output;return _?.getZod?_.getZod().parse(g):g}};export{r as SpecRegistry,n as opKey};
1
+ import{eventKey as e}from"./events.js";import{isEmitDeclRef as t}from"./spec.js";import{defaultDocRegistry as n,docId as r,registerDocBlocks as i}from"./docs/registry.js";function a(e,t){return`${e}.v${t}`}var o=class{specs=new Map;handlers=new Map;register(e){let t=a(e.meta.name,e.meta.version);if(this.specs.has(t))throw Error(`Duplicate spec ${t}`);return this.specs.set(t,e),this}bind(e,t){let n=a(e.meta.name,e.meta.version);if(!this.specs.has(n))throw Error(`Cannot bind; spec not found: ${n}`);if(this.handlers.has(n))throw Error(`Handler already bound for ${n}`);return this.handlers.set(n,t),this}getSpec(e,t){if(t!=null)return this.specs.get(a(e,t));let n,r=-1/0;for(let[t,i]of this.specs.entries())t.startsWith(`${e}.v`)&&i.meta.version>r&&(r=i.meta.version,n=i);return n}getHandler(e,t){let n=this.getSpec(e,t);if(n)return this.handlers.get(a(n.meta.name,n.meta.version))}listSpecs(){return[...this.specs.values()]}listBound(){let e=[];for(let[t,n]of this.specs.entries()){let r=this.handlers.get(t);r&&e.push({spec:n,handler:r})}return e}async execute(n,r,i,o){let s=this.getSpec(n,r);if(!s)throw Error(`Spec not found for ${n}${r?`.v${r}`:``}`);let c=await o.specVariantResolver?.resolve({name:s.meta.name,version:s.meta.version,kind:s.meta.kind},o)??s,l=a(c.meta.name,c.meta.version),u=this.handlers.get(l);if(!u){let e=a(s.meta.name,s.meta.version);u=this.handlers.get(e),l=e}if(!u)throw Error(`No handler bound for ${l}`);let d=c.io.input?.getZod().parse(i);if(o.decide){let[e,t]=c.meta.name.split(`.`),n=await o.decide({service:e,command:t,version:c.meta.version,actor:o.actor??`anonymous`,channel:o.channel,roles:o.roles,organizationId:o.organizationId,userId:o.userId,flags:[]});if(n.effect===`deny`)throw Error(`PolicyDenied: ${c.meta.name}.v${c.meta.version}`);if(n.rateLimit&&o.rateLimit){let e=n.rateLimit.key??`default`,t=n.rateLimit.rpm??60;await o.rateLimit(e,1,t)}}let f=new Map;if(c.sideEffects?.emits)for(let e of c.sideEffects.emits)t(e)?f.set(`${e.ref.name}.v${e.ref.version}`,e.ref.payload):f.set(`${e.name}.v${e.version}`,e.payload);let p=async(t,n,r)=>{let i=e(t,n),s=f.get(i);if(!s)throw Error(`UndeclaredEvent: ${i} not allowed by ${a(c.meta.name,c.meta.version)}`);let l=s.getZod().parse(r);await o.eventPublisher?.({name:t,version:n,payload:l,traceId:o.traceId})};o.appConfig&&(o.branding||=o.appConfig.branding,o.translation?o.translation.config||(o.translation={...o.translation,config:o.appConfig.translation}):o.translation={config:o.appConfig.translation});let m=o.telemetry,h=async(e,t)=>{if(!(!m||!e?.event))try{let n=e.properties?.(t)??{};await m.track(e.event.name,e.event.version??1,n,{tenantId:o.organizationId??void 0,organizationId:o.organizationId,userId:o.userId,actor:o.actor,channel:o.channel,metadata:o.traceId?{traceId:o.traceId}:void 0})}catch{}},g;try{g=await u(d,{...o,__emitGuard__:p})}catch(e){throw c.telemetry?.failure&&await h(c.telemetry.failure,{input:d??i,error:e}),e}c.telemetry?.success&&await h(c.telemetry.success,{input:d??i,output:g});let _=c.io.output;return _?.getZod?_.getZod().parse(g):g}};export{o as SpecRegistry,n as defaultDocRegistry,r as docId,a as opKey,i as registerDocBlocks};
package/dist/resources.js CHANGED
@@ -1 +1 @@
1
- import{z as e}from"zod";function t(e){return e}var n=class{templates=[];register(e){return this.templates.push(e),this}listTemplates(){return[...this.templates]}match(e){for(let t of this.templates){let n=RegExp(`^`+t.meta.uriTemplate.replace(/\{[^}]+\}/g,`([^/]+)`)+`$`),r=e.match(n);if(!r)continue;let i=[...t.meta.uriTemplate.matchAll(/\{([^}]+)\}/g)].map(e=>e[1]),a={};return i.forEach((e,t)=>a[e]=decodeURIComponent(r[t+1])),{tmpl:t,params:a}}}};function r(e,t){return{kind:`resource_ref`,uriTemplate:e,varName:t.varName??`id`,graphQLType:t.graphQLType,many:t.many}}function i(e){let t=e;return!!t&&t.kind===`resource_ref`&&typeof t.uriTemplate==`string`}export{n as ResourceRegistry,t as defineResourceTemplate,i as isResourceRef,r as resourceRef};
1
+ import"zod";function e(e){return e}var t=class{templates=[];register(e){return this.templates.push(e),this}listTemplates(){return[...this.templates]}match(e){for(let t of this.templates){let n=RegExp(`^`+t.meta.uriTemplate.replace(/\{[^}]+\}/g,`([^/]+)`)+`$`),r=e.match(n);if(!r)continue;let i=[...t.meta.uriTemplate.matchAll(/\{([^}]+)\}/g)].map(e=>e[1]),a={};return i.forEach((e,t)=>a[e]=decodeURIComponent(r[t+1])),{tmpl:t,params:a}}}};function n(e,t){return{kind:`resource_ref`,uriTemplate:e,varName:t.varName??`id`,graphQLType:t.graphQLType,many:t.many}}function r(e){let t=e;return!!t&&t.kind===`resource_ref`&&typeof t.uriTemplate==`string`}export{t as ResourceRegistry,e as defineResourceTemplate,r as isResourceRef,n as resourceRef};