@lssm/lib.contracts 0.0.0-canary-20251217062943 → 0.0.0-canary-20251217072406

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 (237) hide show
  1. package/dist/app-config/app-config.feature.js +53 -1
  2. package/dist/app-config/contracts.d.ts +50 -50
  3. package/dist/app-config/contracts.js +396 -1
  4. package/dist/app-config/docs/app-config.docblock.js +22 -220
  5. package/dist/app-config/events.js +168 -1
  6. package/dist/app-config/index.js +8 -1
  7. package/dist/app-config/lifecycle-contracts.js +441 -1
  8. package/dist/app-config/runtime.js +617 -1
  9. package/dist/app-config/spec.js +36 -1
  10. package/dist/app-config/validation.js +538 -1
  11. package/dist/capabilities/docs/capabilities.docblock.js +22 -1
  12. package/dist/capabilities/openbanking.js +92 -1
  13. package/dist/capabilities.js +50 -1
  14. package/dist/client/index.js +9 -1
  15. package/dist/client/react/drivers/rn-reusables.js +21 -1
  16. package/dist/client/react/drivers/shadcn.js +11 -1
  17. package/dist/client/react/feature-render.js +43 -1
  18. package/dist/client/react/form-render.js +298 -1
  19. package/dist/client/react/index.js +8 -1
  20. package/dist/contract-registry/index.js +3 -1
  21. package/dist/contract-registry/schemas.js +61 -1
  22. package/dist/contracts-adapter-hydration.js +41 -1
  23. package/dist/contracts-adapter-input.js +77 -1
  24. package/dist/data-views/docs/data-views.docblock.js +22 -1
  25. package/dist/data-views/query-generator.js +48 -1
  26. package/dist/data-views/runtime.js +39 -1
  27. package/dist/data-views.js +35 -1
  28. package/dist/docs/PUBLISHING.docblock.js +17 -76
  29. package/dist/docs/accessibility_wcag_compliance_specs.docblock.js +17 -350
  30. package/dist/docs/index.js +33 -1
  31. package/dist/docs/meta.docs.js +15 -2
  32. package/dist/docs/presentations.js +77 -1
  33. package/dist/docs/registry.js +51 -1
  34. package/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +17 -383
  35. package/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +17 -68
  36. package/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +17 -140
  37. package/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +17 -86
  38. package/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +17 -1
  39. package/dist/docs/tech/auth/better-auth-nextjs.docblock.js +25 -2
  40. package/dist/docs/tech/contracts/README.docblock.js +21 -1
  41. package/dist/docs/tech/contracts/create-subscription.docblock.js +21 -1
  42. package/dist/docs/tech/contracts/graphql-typed-outputs.docblock.js +21 -180
  43. package/dist/docs/tech/contracts/migrations.docblock.js +21 -1
  44. package/dist/docs/tech/contracts/openapi-export.docblock.js +22 -2
  45. package/dist/docs/tech/contracts/ops-to-presentation-linking.docblock.js +19 -60
  46. package/dist/docs/tech/contracts/overlays.docblock.js +21 -68
  47. package/dist/docs/tech/contracts/tests.docblock.js +21 -132
  48. package/dist/docs/tech/contracts/themes.docblock.js +21 -1
  49. package/dist/docs/tech/contracts/vertical-pocket-family-office.docblock.js +21 -106
  50. package/dist/docs/tech/lifecycle-stage-system.docblock.js +17 -213
  51. package/dist/docs/tech/llm/llm-integration.docblock.js +74 -5
  52. package/dist/docs/tech/mcp-endpoints.docblock.js +38 -1
  53. package/dist/docs/tech/presentation-runtime.docblock.js +17 -1
  54. package/dist/docs/tech/schema/README.docblock.js +21 -262
  55. package/dist/docs/tech/studio/learning-events.docblock.js +49 -1
  56. package/dist/docs/tech/studio/learning-journeys.docblock.js +25 -2
  57. package/dist/docs/tech/studio/platform-admin-panel.docblock.js +24 -2
  58. package/dist/docs/tech/studio/project-access-teams.docblock.js +26 -16
  59. package/dist/docs/tech/studio/project-routing.docblock.js +68 -1
  60. package/dist/docs/tech/studio/sandbox-unlogged.docblock.js +23 -2
  61. package/dist/docs/tech/studio/team-invitations.docblock.js +41 -36
  62. package/dist/docs/tech/studio/workspace-ops.docblock.js +48 -1
  63. package/dist/docs/tech/studio/workspaces.docblock.js +24 -2
  64. package/dist/docs/tech/telemetry-ingest.docblock.js +37 -3
  65. package/dist/docs/tech/templates/runtime.docblock.js +21 -1
  66. package/dist/docs/tech/vscode-extension.docblock.js +37 -3
  67. package/dist/docs/tech/workflows/overview.docblock.js +21 -1
  68. package/dist/docs/tech-contracts.docs.js +19 -2
  69. package/dist/events.js +12 -1
  70. package/dist/experiments/docs/experiments.docblock.js +22 -128
  71. package/dist/experiments/evaluator.js +101 -1
  72. package/dist/experiments/spec.js +33 -1
  73. package/dist/features.js +68 -1
  74. package/dist/forms/docs/forms.docblock.js +22 -1
  75. package/dist/forms.js +119 -1
  76. package/dist/index.js +107 -1
  77. package/dist/install.js +40 -1
  78. package/dist/integrations/contracts.d.ts +102 -102
  79. package/dist/integrations/contracts.js +388 -1
  80. package/dist/integrations/docs/integrations.docblock.js +95 -1
  81. package/dist/integrations/health.js +69 -1
  82. package/dist/integrations/index.js +23 -1
  83. package/dist/integrations/openbanking/contracts/accounts.d.ts +66 -66
  84. package/dist/integrations/openbanking/contracts/accounts.js +237 -1
  85. package/dist/integrations/openbanking/contracts/balances.d.ts +34 -34
  86. package/dist/integrations/openbanking/contracts/balances.js +167 -1
  87. package/dist/integrations/openbanking/contracts/index.js +12 -1
  88. package/dist/integrations/openbanking/contracts/transactions.d.ts +48 -48
  89. package/dist/integrations/openbanking/contracts/transactions.js +218 -1
  90. package/dist/integrations/openbanking/guards.js +32 -1
  91. package/dist/integrations/openbanking/models.d.ts +55 -55
  92. package/dist/integrations/openbanking/models.js +242 -1
  93. package/dist/integrations/openbanking/openbanking.feature.js +68 -1
  94. package/dist/integrations/openbanking/telemetry.js +39 -1
  95. package/dist/integrations/providers/elevenlabs.js +56 -1
  96. package/dist/integrations/providers/gcs-storage.js +79 -1
  97. package/dist/integrations/providers/gmail.js +91 -1
  98. package/dist/integrations/providers/google-calendar.js +70 -1
  99. package/dist/integrations/providers/impls/elevenlabs-voice.js +95 -1
  100. package/dist/integrations/providers/impls/gcs-storage.js +88 -1
  101. package/dist/integrations/providers/impls/gmail-inbound.js +200 -1
  102. package/dist/integrations/providers/impls/gmail-outbound.js +104 -5
  103. package/dist/integrations/providers/impls/google-calendar.js +154 -1
  104. package/dist/integrations/providers/impls/index.js +16 -1
  105. package/dist/integrations/providers/impls/mistral-embedding.js +41 -1
  106. package/dist/integrations/providers/impls/mistral-llm.js +247 -1
  107. package/dist/integrations/providers/impls/postmark-email.js +55 -1
  108. package/dist/integrations/providers/impls/powens-client.js +171 -1
  109. package/dist/integrations/providers/impls/powens-openbanking.js +218 -1
  110. package/dist/integrations/providers/impls/provider-factory.js +142 -1
  111. package/dist/integrations/providers/impls/qdrant-vector.js +69 -1
  112. package/dist/integrations/providers/impls/stripe-payments.js +202 -1
  113. package/dist/integrations/providers/impls/twilio-sms.js +58 -1
  114. package/dist/integrations/providers/index.js +13 -1
  115. package/dist/integrations/providers/mistral.js +72 -1
  116. package/dist/integrations/providers/postmark.js +72 -1
  117. package/dist/integrations/providers/powens.js +120 -1
  118. package/dist/integrations/providers/qdrant.js +77 -1
  119. package/dist/integrations/providers/registry.js +34 -1
  120. package/dist/integrations/providers/stripe.js +87 -1
  121. package/dist/integrations/providers/twilio-sms.js +65 -1
  122. package/dist/integrations/runtime.js +186 -1
  123. package/dist/integrations/secrets/aws-secret-manager.js +231 -1
  124. package/dist/integrations/secrets/env-secret-provider.js +81 -1
  125. package/dist/integrations/secrets/gcp-secret-manager.js +229 -1
  126. package/dist/integrations/secrets/index.js +8 -1
  127. package/dist/integrations/secrets/manager.js +103 -1
  128. package/dist/integrations/secrets/provider.js +58 -1
  129. package/dist/integrations/secrets/scaleway-secret-manager.js +247 -1
  130. package/dist/integrations/spec.js +39 -1
  131. package/dist/jobs/define-job.js +16 -1
  132. package/dist/jobs/gcp-cloud-tasks.js +53 -1
  133. package/dist/jobs/gcp-pubsub.js +39 -1
  134. package/dist/jobs/handlers/gmail-sync-handler.js +9 -1
  135. package/dist/jobs/handlers/index.js +12 -1
  136. package/dist/jobs/handlers/ping-handler.js +15 -1
  137. package/dist/jobs/handlers/storage-document-handler.js +14 -1
  138. package/dist/jobs/index.js +4 -1
  139. package/dist/jobs/memory-queue.js +71 -1
  140. package/dist/jobs/queue.js +33 -1
  141. package/dist/jobs/scaleway-sqs-queue.js +153 -1
  142. package/dist/jsonschema.d.ts +3 -3
  143. package/dist/jsonschema.js +32 -1
  144. package/dist/knowledge/contracts.d.ts +66 -66
  145. package/dist/knowledge/contracts.js +317 -1
  146. package/dist/knowledge/docs/knowledge.docblock.js +22 -138
  147. package/dist/knowledge/index.js +10 -1
  148. package/dist/knowledge/ingestion/document-processor.js +54 -1
  149. package/dist/knowledge/ingestion/embedding-service.js +25 -1
  150. package/dist/knowledge/ingestion/gmail-adapter.js +50 -5
  151. package/dist/knowledge/ingestion/index.js +7 -1
  152. package/dist/knowledge/ingestion/storage-adapter.js +26 -1
  153. package/dist/knowledge/ingestion/vector-indexer.js +32 -1
  154. package/dist/knowledge/query/index.js +3 -1
  155. package/dist/knowledge/query/service.js +64 -2
  156. package/dist/knowledge/runtime.js +49 -1
  157. package/dist/knowledge/spaces/email-threads.js +38 -1
  158. package/dist/knowledge/spaces/financial-docs.js +38 -1
  159. package/dist/knowledge/spaces/financial-overview.js +42 -1
  160. package/dist/knowledge/spaces/index.js +8 -1
  161. package/dist/knowledge/spaces/product-canon.js +38 -1
  162. package/dist/knowledge/spaces/support-faq.js +41 -1
  163. package/dist/knowledge/spaces/uploaded-docs.js +38 -1
  164. package/dist/knowledge/spec.js +39 -1
  165. package/dist/llm/exporters.js +541 -8
  166. package/dist/llm/index.js +4 -1
  167. package/dist/llm/prompts.js +246 -56
  168. package/dist/markdown.js +116 -3
  169. package/dist/migrations.js +33 -1
  170. package/dist/onboarding-base.d.ts +29 -29
  171. package/dist/onboarding-base.js +196 -1
  172. package/dist/openapi.js +75 -1
  173. package/dist/openbanking/docs/openbanking.docblock.js +22 -109
  174. package/dist/ownership.js +40 -1
  175. package/dist/policy/docs/policy.docblock.js +22 -1
  176. package/dist/policy/engine.js +223 -1
  177. package/dist/policy/opa-adapter.js +71 -1
  178. package/dist/policy/spec.js +33 -1
  179. package/dist/presentations/docs/presentations-conventions.docblock.js +21 -7
  180. package/dist/presentations.backcompat.js +47 -1
  181. package/dist/presentations.d.ts +3 -3
  182. package/dist/presentations.js +66 -1
  183. package/dist/presentations.v2.js +278 -6
  184. package/dist/prompt.js +10 -1
  185. package/dist/promptRegistry.js +34 -1
  186. package/dist/regenerator/docs/regenerator.docblock.js +22 -184
  187. package/dist/regenerator/executor.js +86 -1
  188. package/dist/regenerator/index.js +6 -1
  189. package/dist/regenerator/service.js +92 -1
  190. package/dist/regenerator/sinks.js +32 -1
  191. package/dist/regenerator/utils.js +51 -1
  192. package/dist/registry.js +208 -1
  193. package/dist/resources.js +47 -1
  194. package/dist/schema/dist/EnumType.js +2 -1
  195. package/dist/schema/dist/FieldType.js +49 -1
  196. package/dist/schema/dist/ScalarTypeEnum.js +236 -1
  197. package/dist/schema/dist/SchemaModel.js +39 -1
  198. package/dist/schema/dist/entity/defineEntity.js +1 -1
  199. package/dist/schema/dist/entity/index.js +2 -1
  200. package/dist/schema/dist/entity/types.js +1 -1
  201. package/dist/schema/dist/index.js +6 -1
  202. package/dist/schema-to-markdown.js +214 -10
  203. package/dist/server/graphql-pothos.js +128 -1
  204. package/dist/server/index.js +10 -1
  205. package/dist/server/mcp/createMcpServer.js +28 -1
  206. package/dist/server/mcp/registerPresentations.js +151 -1
  207. package/dist/server/mcp/registerPrompts.js +36 -2
  208. package/dist/server/mcp/registerResources.js +35 -1
  209. package/dist/server/mcp/registerTools.js +22 -1
  210. package/dist/server/provider-mcp.js +3 -1
  211. package/dist/server/rest-elysia.js +20 -1
  212. package/dist/server/rest-express.js +39 -1
  213. package/dist/server/rest-generic.js +125 -1
  214. package/dist/server/rest-next-app.js +38 -1
  215. package/dist/server/rest-next-mcp.js +45 -1
  216. package/dist/server/rest-next-pages.js +25 -1
  217. package/dist/spec.js +35 -1
  218. package/dist/telemetry/anomaly.js +48 -1
  219. package/dist/telemetry/docs/telemetry.docblock.js +22 -139
  220. package/dist/telemetry/index.js +5 -1
  221. package/dist/telemetry/spec.js +69 -1
  222. package/dist/telemetry/tracker.js +76 -1
  223. package/dist/tests/index.js +4 -1
  224. package/dist/tests/runner.js +150 -1
  225. package/dist/tests/spec.js +33 -1
  226. package/dist/themes.js +39 -1
  227. package/dist/workflow/adapters/db-adapter.js +83 -1
  228. package/dist/workflow/adapters/file-adapter.js +11 -1
  229. package/dist/workflow/adapters/index.js +5 -1
  230. package/dist/workflow/adapters/memory-store.js +58 -1
  231. package/dist/workflow/expression.js +98 -1
  232. package/dist/workflow/index.js +9 -1
  233. package/dist/workflow/runner.js +337 -1
  234. package/dist/workflow/sla-monitor.js +47 -1
  235. package/dist/workflow/spec.js +32 -1
  236. package/dist/workflow/validation.js +175 -1
  237. package/package.json +11 -4
@@ -1,7 +1,279 @@
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(`
1
+ import { schemaToMarkdown } from "./schema-to-markdown.js";
2
+ import React from "react";
3
+ import TurndownService from "turndown";
6
4
 
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};
5
+ //#region src/presentations.v2.ts
6
+ /**
7
+ * Pluggable transform engine that renders descriptors to various targets
8
+ * and runs validators (e.g., basic metadata checks, PII redaction policies).
9
+ */
10
+ const turndown = new TurndownService();
11
+ function renderTextNode(node) {
12
+ const text = node.text ?? "";
13
+ if (!node.marks || node.marks.length === 0) return text;
14
+ return node.marks.reduce((acc, mark) => {
15
+ switch (mark.type) {
16
+ case "bold": return `**${acc}**`;
17
+ case "italic": return `*${acc}*`;
18
+ case "underline": return `__${acc}__`;
19
+ case "strike": return `~~${acc}~~`;
20
+ case "code": return `\`${acc}\``;
21
+ case "link": {
22
+ const href = mark.attrs?.href ?? "";
23
+ return href ? `[${acc}](${href})` : acc;
24
+ }
25
+ default: return acc;
26
+ }
27
+ }, text);
28
+ }
29
+ function renderInline(nodes) {
30
+ if (!nodes?.length) return "";
31
+ return nodes.map((child) => renderNode(child)).join("");
32
+ }
33
+ function renderList(nodes, ordered = false) {
34
+ if (!nodes?.length) return "";
35
+ let counter = 1;
36
+ return nodes.map((item) => {
37
+ const body = renderInline(item.content ?? []);
38
+ if (!body) return "";
39
+ return `${ordered ? `${counter++}. ` : "- "}${body}`;
40
+ }).filter(Boolean).join("\n");
41
+ }
42
+ function renderNode(node) {
43
+ switch (node.type) {
44
+ case "doc": return renderInline(node.content);
45
+ case "paragraph": {
46
+ const text = renderInline(node.content);
47
+ return text.trim().length ? text : "";
48
+ }
49
+ case "heading": {
50
+ const level = Math.min(Math.max(node.attrs?.level ?? 1, 1), 6);
51
+ return `${"#".repeat(level)} ${renderInline(node.content)}`.trim();
52
+ }
53
+ case "bullet_list": return renderList(node.content, false);
54
+ case "ordered_list": return renderList(node.content, true);
55
+ case "list_item": return renderInline(node.content);
56
+ case "blockquote": return renderInline(node.content).split("\n").map((line) => `> ${line}`).join("\n");
57
+ case "code_block": {
58
+ const body = renderInline(node.content);
59
+ return body ? `\`\`\`\n${body}\n\`\`\`` : "";
60
+ }
61
+ case "horizontal_rule": return "---";
62
+ case "hard_break": return "\n";
63
+ case "text": return renderTextNode(node);
64
+ default:
65
+ if (node.text) return renderTextNode(node);
66
+ return "";
67
+ }
68
+ }
69
+ function blockNoteToMarkdown(docJson) {
70
+ if (typeof docJson === "string") return docJson;
71
+ if (docJson && typeof docJson === "object" && "html" in docJson) {
72
+ const html = String(docJson.html);
73
+ return turndown.turndown(html);
74
+ }
75
+ const root = docJson;
76
+ if (root?.type === "doc" || root?.content) return (root.content ?? []).map((n) => renderNode(n)).filter(Boolean).join("\n\n").trim();
77
+ try {
78
+ return JSON.stringify(docJson, null, 2);
79
+ } catch {
80
+ return String(docJson);
81
+ }
82
+ }
83
+ var TransformEngine = class {
84
+ renderers = /* @__PURE__ */ new Map();
85
+ validators = [];
86
+ register(renderer) {
87
+ const arr = this.renderers.get(renderer.target) ?? [];
88
+ arr.push(renderer);
89
+ this.renderers.set(renderer.target, arr);
90
+ return this;
91
+ }
92
+ /**
93
+ * Register a renderer that will be tried BEFORE existing renderers for the same target.
94
+ * Useful for custom renderers that should take priority over default ones.
95
+ */
96
+ prependRegister(renderer) {
97
+ const arr = this.renderers.get(renderer.target) ?? [];
98
+ arr.unshift(renderer);
99
+ this.renderers.set(renderer.target, arr);
100
+ return this;
101
+ }
102
+ addValidator(v) {
103
+ this.validators.push(v);
104
+ return this;
105
+ }
106
+ async render(target, desc, ctx) {
107
+ if (!desc.targets.includes(target)) throw new Error(`Target ${target} not declared for ${desc.meta.name}.v${desc.meta.version}`);
108
+ for (const v of this.validators) await v.validate(desc, target, ctx);
109
+ const arr = this.renderers.get(target) ?? [];
110
+ for (const r of arr) try {
111
+ return await r.render(desc, ctx);
112
+ } catch (_e) {}
113
+ throw new Error(`No renderer available for ${target}`);
114
+ }
115
+ };
116
+ /** Create a TransformEngine instance with default markdown/json/xml renderers. */
117
+ function createDefaultTransformEngine() {
118
+ const engine = new TransformEngine();
119
+ const applyPii = (desc, obj) => {
120
+ const clone = JSON.parse(JSON.stringify(obj));
121
+ const paths = desc.policy?.pii ?? [];
122
+ const setAtPath = (root, path) => {
123
+ const segs = path.replace(/^\//, "").replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
124
+ let cur = root;
125
+ for (let i = 0; i < segs.length - 1; i++) {
126
+ const k = segs[i];
127
+ if (cur && typeof cur === "object" && k in cur) cur = cur[k];
128
+ else return;
129
+ }
130
+ const last = segs[segs.length - 1];
131
+ if (cur && typeof cur === "object" && last && last in cur) cur[last] = "[REDACTED]";
132
+ };
133
+ for (const p of paths) setAtPath(clone, p);
134
+ return clone;
135
+ };
136
+ engine.register({
137
+ target: "markdown",
138
+ async render(desc, ctx) {
139
+ let data = ctx?.data;
140
+ if (!data && ctx?.fetchData) data = await ctx.fetchData();
141
+ if (desc.source.type === "component" && desc.source.props && data !== void 0) {
142
+ const isArray = Array.isArray(data);
143
+ const isSimpleObject = !isArray && typeof data === "object" && data !== null && !Object.values(data).some((v) => Array.isArray(v) || typeof v === "object" && v !== null);
144
+ if (isArray || isSimpleObject) return {
145
+ mimeType: "text/markdown",
146
+ body: schemaToMarkdown(desc.source.props, data, {
147
+ title: desc.meta.description ?? desc.meta.name,
148
+ description: `${desc.meta.name} v${desc.meta.version}`
149
+ })
150
+ };
151
+ throw new Error(`Complex data structure for ${desc.meta.name} - expecting custom renderer`);
152
+ }
153
+ if (desc.source.type === "blocknotejs") {
154
+ const redacted = applyPii(desc, { text: blockNoteToMarkdown(desc.source.docJson) });
155
+ return {
156
+ mimeType: "text/markdown",
157
+ body: String(redacted.text)
158
+ };
159
+ }
160
+ if (desc.source.type === "component" && data !== void 0) throw new Error(`No schema (source.props) available for ${desc.meta.name} - expecting custom renderer`);
161
+ if (desc.source.type === "component") return {
162
+ mimeType: "text/markdown",
163
+ body: `${`# ${desc.meta.name} v${desc.meta.version}`}${desc.meta.description ? `\n\n${desc.meta.description}` : ""}${desc.meta.tags && desc.meta.tags.length ? `\n\nTags: ${desc.meta.tags.join(", ")}` : ""}${desc.meta.owners && desc.meta.owners.length ? `\n\nOwners: ${desc.meta.owners.join(", ")}` : ""}${`\n\nComponent: \`${desc.source.componentKey}\``}${desc.policy?.pii?.length ? `\n\nRedacted paths: ${desc.policy.pii.map((p) => `\`${p}\``).join(", ")}` : ""}`
164
+ };
165
+ throw new Error("unsupported");
166
+ }
167
+ });
168
+ engine.register({
169
+ target: "application/json",
170
+ async render(desc) {
171
+ const payload = applyPii(desc, {
172
+ meta: desc.meta,
173
+ source: desc.source
174
+ });
175
+ return {
176
+ mimeType: "application/json",
177
+ body: JSON.stringify(payload, null, 2)
178
+ };
179
+ }
180
+ });
181
+ engine.register({
182
+ target: "application/xml",
183
+ async render(desc) {
184
+ const json = applyPii(desc, {
185
+ meta: desc.meta,
186
+ source: desc.source
187
+ });
188
+ return {
189
+ mimeType: "application/xml",
190
+ body: `<presentation name="${desc.meta.name}" version="${desc.meta.version}"><json>${encodeURIComponent(JSON.stringify(json))}</json></presentation>`
191
+ };
192
+ }
193
+ });
194
+ return engine;
195
+ }
196
+ /** Register a default React target renderer that returns a serializable descriptor. */
197
+ function registerDefaultReactRenderer(engine) {
198
+ engine.register({
199
+ target: "react",
200
+ async render(desc) {
201
+ if (desc.source.type === "component") {
202
+ const props = desc.source.props ? desc.source.props.getZod().safeParse({}).success ? {} : void 0 : void 0;
203
+ return {
204
+ kind: "react_component",
205
+ componentKey: desc.source.componentKey,
206
+ props
207
+ };
208
+ }
209
+ return {
210
+ kind: "blocknotejs",
211
+ docJson: desc.source.docJson,
212
+ blockConfig: desc.source.blockConfig
213
+ };
214
+ }
215
+ });
216
+ return engine;
217
+ }
218
+ /**
219
+ * Add basic validators (e.g., meta.description presence) to the engine.
220
+ */
221
+ function registerBasicValidation(engine) {
222
+ engine.addValidator({ validate(desc) {
223
+ if (!desc.meta.description || desc.meta.description.length < 3) throw new Error(`Presentation ${desc.meta.name}.v${desc.meta.version} missing meta.description`);
224
+ } });
225
+ return engine;
226
+ }
227
+ /**
228
+ * Register a React-to-markdown renderer that renders React components to HTML
229
+ * and converts them to markdown using turndown.
230
+ * This renderer takes priority over the default metadata-only renderer.
231
+ */
232
+ function registerReactToMarkdownRenderer(engine, componentMap) {
233
+ const turndownService = new TurndownService({
234
+ headingStyle: "atx",
235
+ codeBlockStyle: "fenced",
236
+ bulletListMarker: "-"
237
+ });
238
+ turndownService.addRule("link", {
239
+ filter: "a",
240
+ replacement: (content, node) => {
241
+ const href = node.href;
242
+ if (href && content) return `[${content}](${href})`;
243
+ return content || "";
244
+ }
245
+ });
246
+ engine.prependRegister({
247
+ target: "markdown",
248
+ async render(desc, ctx) {
249
+ if (desc.source.type !== "component") throw new Error("React-to-markdown renderer only handles component presentations");
250
+ const { renderToStaticMarkup } = await import("react-dom/server");
251
+ const Component = componentMap[desc.source.componentKey];
252
+ if (!Component) throw new Error(`Component ${desc.source.componentKey} not found in componentMap`);
253
+ let html;
254
+ try {
255
+ html = renderToStaticMarkup(React.createElement(Component, desc.source.props ? {} : void 0));
256
+ } catch (error) {
257
+ throw new Error(`Failed to render component ${desc.source.componentKey}: ${error instanceof Error ? error.message : "Unknown error"}`);
258
+ }
259
+ let markdown;
260
+ try {
261
+ markdown = turndownService.turndown(html);
262
+ } catch (error) {
263
+ throw new Error(`Failed to convert HTML to markdown: ${error instanceof Error ? error.message : "Unknown error"}`);
264
+ }
265
+ if (desc.policy?.pii && desc.policy.pii.length > 0) return {
266
+ mimeType: "text/markdown",
267
+ body: markdown.replace(/\[REDACTED\]/g, "[REDACTED]")
268
+ };
269
+ return {
270
+ mimeType: "text/markdown",
271
+ body: markdown
272
+ };
273
+ }
274
+ });
275
+ return engine;
276
+ }
277
+
278
+ //#endregion
279
+ export { TransformEngine, createDefaultTransformEngine, registerBasicValidation, registerDefaultReactRenderer, registerReactToMarkdownRenderer };
package/dist/prompt.js CHANGED
@@ -1 +1,10 @@
1
- import"zod";function e(e){return e}export{e as definePrompt};
1
+ import "zod";
2
+
3
+ //#region src/prompt.ts
4
+ /** Identity helper that preserves generic inference when declaring prompts. */
5
+ function definePrompt(spec) {
6
+ return spec;
7
+ }
8
+
9
+ //#endregion
10
+ export { definePrompt };
@@ -1 +1,34 @@
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};
1
+ import "zod";
2
+
3
+ //#region src/promptRegistry.ts
4
+ var PromptRegistry = class {
5
+ prompts = /* @__PURE__ */ new Map();
6
+ /** Register a prompt. Throws on duplicate name+version. */
7
+ register(p) {
8
+ const key = `${p.meta.name}.v${p.meta.version}`;
9
+ if (this.prompts.has(key)) throw new Error(`Duplicate prompt ${key}`);
10
+ this.prompts.set(key, p);
11
+ return this;
12
+ }
13
+ /** List all registered prompts. */
14
+ list() {
15
+ return [...this.prompts.values()];
16
+ }
17
+ /** Get prompt by name; when version omitted, returns highest version. */
18
+ get(name, version) {
19
+ if (version != null) return this.prompts.get(`${name}.v${version}`);
20
+ let candidate;
21
+ let max = -Infinity;
22
+ for (const [k, p] of this.prompts.entries()) {
23
+ if (!k.startsWith(`${name}.v`)) continue;
24
+ if (p.meta.version > max) {
25
+ max = p.meta.version;
26
+ candidate = p;
27
+ }
28
+ }
29
+ return candidate;
30
+ }
31
+ };
32
+
33
+ //#endregion
34
+ export { PromptRegistry };
@@ -1,184 +1,22 @@
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};
1
+ import { registerDocBlocks } from "../../docs/registry.js";
2
+ import "../../registry.js";
3
+
4
+ //#region src/regenerator/docs/regenerator.docblock.ts
5
+ const tech_contracts_regenerator_DocBlocks = [{
6
+ id: "docs.tech.contracts.regenerator",
7
+ title: "Regenerator Service",
8
+ 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.",
9
+ kind: "reference",
10
+ visibility: "public",
11
+ route: "/docs/tech/contracts/regenerator",
12
+ tags: [
13
+ "tech",
14
+ "contracts",
15
+ "regenerator"
16
+ ],
17
+ body: "## Regenerator Service\n\nThe 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.\n\n- Runtime entrypoint: `packages/libs/contracts/src/regenerator/service.ts`\n- Types/interfaces: `packages/libs/contracts/src/regenerator/types.ts`\n- Signal adapters: `packages/libs/contracts/src/regenerator/adapters.ts`\n\n### Architecture\n\n```text\nSignal Adapters ──► RegeneratorService ──► Rules ──► ProposalSink\n ▲ │\n │ ▼\n Telemetry / Errors / Behavior Spec change proposals\n```\n\n1. **Signal adapters** pull batches of telemetry, error logs, or behavior metrics for each `RegenerationContext`.\n2. `RegeneratorService` schedules polling (`resolveAppConfig` + `composeAppConfig` provide context).\n3. **Rules** implement domain heuristics and emit `SpecChangeProposal` objects.\n4. **Proposal sinks** persist or forward proposals for human review.\n\n### Key types\n\n```ts\nexport interface RegenerationContext {\n id: string;\n blueprint: AppBlueprintSpec;\n tenantConfig: TenantAppConfig;\n resolved: ResolvedAppConfig;\n}\n\nexport interface RegeneratorRule {\n id: string;\n description: string;\n evaluate(\n context: RegenerationContext,\n signals: RegeneratorSignal[]\n ): Promise<SpecChangeProposal[]>;\n}\n\nexport interface SpecChangeProposal {\n id: string;\n title: string;\n summary: string;\n confidence: 'low' | 'medium' | 'high';\n target: ProposalTarget;\n actions: ProposalAction[];\n blockers?: ProposalBlocker[];\n signalIds: string[];\n createdAt: Date;\n}\n```\n\n- Signals are normalized envelopes: telemetry (`count`, anomaly score), errors, and behavior trends.\n- Proposals reference blueprint or tenant specs via `ProposalTarget`.\n- Actions encode what the automation should perform (update blueprint, run tests/migrations, trigger regeneration).\n\n### Providing signals\n\nImplement `TelemetrySignalProvider`, `ErrorSignalProvider`, or `BehaviorSignalProvider`:\n\n```ts\nconst service = new RegeneratorService({\n contexts,\n adapters: {\n telemetry: new PosthogTelemetryAdapter(),\n errors: new SentryErrorAdapter(),\n },\n rules: [new WorkflowFailureRule(), new DataViewUsageRule()],\n sink: new ProposalQueueSink(),\n pollIntervalMs: 60_000,\n});\n```\n\nAdapters receive the full `RegenerationContext`, making it easy to scope queries per tenant/app.\n\n### Authoring rules\n\nRules focus on signals → proposals:\n\n```ts\nclass WorkflowFailureRule implements RegeneratorRule {\n id = 'workflow-failure';\n description = 'Suggest splitting workflows that exceed failure thresholds';\n\n async evaluate(context, signals) {\n const failures = signals.filter(\n (signal) =>\n signal.type === 'telemetry' &&\n signal.signal.eventName === 'workflow.failure' &&\n signal.signal.count >= 10\n );\n\n if (failures.length === 0) return [];\n\n return [\n {\n id: `${this.id}-${context.id}`,\n title: 'Split onboarding workflow',\n summary: 'Step 3 fails consistently; propose dedicated remediation branch.',\n confidence: 'medium',\n rationale: ['Failure count ≥ 10 within last window'],\n target: {\n specType: 'workflow',\n reference: { name: 'onboarding.workflow', version: 1 },\n tenantScoped: true,\n },\n actions: [\n { kind: 'update_tenant_config', summary: 'Add alternate fallback path' },\n { kind: 'run_tests', tests: ['workflows/onboarding.spec.ts'] },\n ],\n signalIds: failures.map((f) => f.signal.eventName),\n createdAt: new Date(),\n },\n ];\n }\n}\n```\n\n### Reviewing proposals\n\nProposals flow to a `ProposalSink` (queue, DB, messaging bus). The Studio will surface:\n\n1. Signal evidence (telemetry counts, error metadata)\n2. Proposed spec diffs and required actions (tests/migrations)\n3. Approval workflow (approve → write spec diff → run automation)\n\n### CLI driver\n\nRun the regenerator daemon from the CLI:\n\n```bash\nbunx contracts regenerator ./app.blueprint.ts ./tenant.config.ts ./regenerator.rules.ts auto \\\n --executor ./regenerator.executor.ts \\\n --poll-interval 60000 \\\n --batch-duration 300000 \\\n --dry-run\n```\n\n- Expects modules exporting default `AppBlueprintSpec`, `TenantAppConfig`, and one or more `RegenerationRule`s.\n- Pass a sink module path, or use the special `auto` value with `--executor <module>` to instantiate an `ExecutorProposalSink`.\n- Executor modules can export a `ProposalExecutor` instance, a factory, or a plain dependency object for the executor constructor. Optional exports: `sinkOptions`, `logger`, `onResult`, `dryRun`.\n- Optionally provide `--contexts ./contexts.ts` to load custom context arrays (advanced multi-tenant scenarios).\n- Use `--dry-run` to preview actions without mutating specs/configs, and `--once` for CI smoke tests.\n\n### Proposal executor\n\n`ProposalExecutor` + `ExecutorProposalSink` orchestrate follow-up actions once a proposal is approved:\n\n- Interfaces for applying blueprint or tenant-config updates (`BlueprintUpdater`, `TenantConfigUpdater`).\n- Hooks for running contract tests and migrations (`TestExecutor`, `MigrationExecutor`).\n- Optional trigger to recompose the runtime (`RegenerationTrigger`).\n- Built-in `dryRun` mode to preview outcomes.\n- Pluggable result logging/forwarding via `ExecutorSinkOptions`.\n\n```ts\nimport {\n ProposalExecutor,\n ExecutorProposalSink,\n} from '@lssm/lib.contracts/regenerator';\n\nconst executor = new ProposalExecutor({\n tenantConfigUpdater,\n testExecutor,\n migrationExecutor,\n regenerationTrigger,\n});\n\nconst sink = new ExecutorProposalSink(executor, {\n dryRun: false,\n onResult: ({ result }) => console.log(result.status),\n});\n```\n\nExecution 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.\n\n### Next steps\n\n- Build adapters for existing telemetry/error providers.\n- Encode canonical rules (workflow failure, feature under-use, high latency).\n- Integrate with App Studio proposal inbox and automate acceptance (write spec diff, run tests, queue migrations).\n\n"
18
+ }];
19
+ registerDocBlocks(tech_contracts_regenerator_DocBlocks);
20
+
21
+ //#endregion
22
+ export { tech_contracts_regenerator_DocBlocks };
@@ -1 +1,86 @@
1
- var e=class{constructor(e={}){this.deps=e}async execute(e,n,r={}){let i=new Date,a=[];for(let[t,i]of n.actions.entries()){let o=await this.executeAction({index:t,action:i,context:e,proposal:n,options:r});a.push(o)}let o=new Date,s=t(a);return{proposalId:n.id,contextId:e.id,startedAt:i,finishedAt:o,status:s,actions:a}}async executeAction({index:e,action:t,context:n,proposal:r,options:i}){let a=new Date,o=i.dryRun??!1,s=(n,r={})=>({index:e,action:t,status:n,startedAt:a,finishedAt:new Date,reason:r.reason,output:r.output,error:r.error});if(o)return s(`skipped`,{reason:`dry_run`});try{switch(t.kind){case`update_blueprint`:{let e=this.deps.blueprintUpdater;return e?s(`success`,{output:await e.applyBlueprintUpdate(n,r,t)}):s(`skipped`,{reason:`missing_blueprint_updater`})}case`update_tenant_config`:{let e=this.deps.tenantConfigUpdater;return e?s(`success`,{output:await e.applyTenantConfigUpdate(n,r,t)}):s(`skipped`,{reason:`missing_tenant_config_updater`})}case`run_tests`:{let e=this.deps.testExecutor;return e?s(`success`,{output:await e.runTests(n,r,t)}):s(`skipped`,{reason:`missing_test_executor`})}case`run_migrations`:{let e=this.deps.migrationExecutor;return e?s(`success`,{output:await e.runMigrations(n,r,t)}):s(`skipped`,{reason:`missing_migration_executor`})}case`trigger_regeneration`:{let e=this.deps.regenerationTrigger;return e?s(`success`,{output:await e.triggerRegeneration(n,r,t)}):s(`skipped`,{reason:`missing_regeneration_trigger`})}default:return s(`skipped`,{reason:`unknown_action`})}}catch(e){return s(`failed`,{error:e instanceof Error?e:Error(String(e))})}}};function t(e){return e.some(e=>e.status===`failed`)?`failed`:e.some(e=>e.status===`success`)&&e.some(e=>e.status===`skipped`)||e.every(e=>e.status===`skipped`)?`partial`:`success`}export{e as ProposalExecutor};
1
+ //#region src/regenerator/executor.ts
2
+ var ProposalExecutor = class {
3
+ constructor(deps = {}) {
4
+ this.deps = deps;
5
+ }
6
+ async execute(context, proposal, options = {}) {
7
+ const startedAt = /* @__PURE__ */ new Date();
8
+ const actionResults = [];
9
+ for (const [index, action] of proposal.actions.entries()) {
10
+ const result = await this.executeAction({
11
+ index,
12
+ action,
13
+ context,
14
+ proposal,
15
+ options
16
+ });
17
+ actionResults.push(result);
18
+ }
19
+ const finishedAt = /* @__PURE__ */ new Date();
20
+ const summaryStatus = summarizeStatus(actionResults);
21
+ return {
22
+ proposalId: proposal.id,
23
+ contextId: context.id,
24
+ startedAt,
25
+ finishedAt,
26
+ status: summaryStatus,
27
+ actions: actionResults
28
+ };
29
+ }
30
+ async executeAction({ index, action, context, proposal, options }) {
31
+ const startedAt = /* @__PURE__ */ new Date();
32
+ const dryRun = options.dryRun ?? false;
33
+ const complete = (status, params = {}) => ({
34
+ index,
35
+ action,
36
+ status,
37
+ startedAt,
38
+ finishedAt: /* @__PURE__ */ new Date(),
39
+ reason: params.reason,
40
+ output: params.output,
41
+ error: params.error
42
+ });
43
+ if (dryRun) return complete("skipped", { reason: "dry_run" });
44
+ try {
45
+ switch (action.kind) {
46
+ case "update_blueprint": {
47
+ const updater = this.deps.blueprintUpdater;
48
+ if (!updater) return complete("skipped", { reason: "missing_blueprint_updater" });
49
+ return complete("success", { output: await updater.applyBlueprintUpdate(context, proposal, action) });
50
+ }
51
+ case "update_tenant_config": {
52
+ const updater = this.deps.tenantConfigUpdater;
53
+ if (!updater) return complete("skipped", { reason: "missing_tenant_config_updater" });
54
+ return complete("success", { output: await updater.applyTenantConfigUpdate(context, proposal, action) });
55
+ }
56
+ case "run_tests": {
57
+ const executor = this.deps.testExecutor;
58
+ if (!executor) return complete("skipped", { reason: "missing_test_executor" });
59
+ return complete("success", { output: await executor.runTests(context, proposal, action) });
60
+ }
61
+ case "run_migrations": {
62
+ const executor = this.deps.migrationExecutor;
63
+ if (!executor) return complete("skipped", { reason: "missing_migration_executor" });
64
+ return complete("success", { output: await executor.runMigrations(context, proposal, action) });
65
+ }
66
+ case "trigger_regeneration": {
67
+ const trigger = this.deps.regenerationTrigger;
68
+ if (!trigger) return complete("skipped", { reason: "missing_regeneration_trigger" });
69
+ return complete("success", { output: await trigger.triggerRegeneration(context, proposal, action) });
70
+ }
71
+ default: return complete("skipped", { reason: "unknown_action" });
72
+ }
73
+ } catch (error) {
74
+ return complete("failed", { error: error instanceof Error ? error : new Error(String(error)) });
75
+ }
76
+ }
77
+ };
78
+ function summarizeStatus(actionResults) {
79
+ if (actionResults.some((result) => result.status === "failed")) return "failed";
80
+ if (actionResults.some((result) => result.status === "success") && actionResults.some((result) => result.status === "skipped")) return "partial";
81
+ if (actionResults.every((result) => result.status === "skipped")) return "partial";
82
+ return "success";
83
+ }
84
+
85
+ //#endregion
86
+ export { ProposalExecutor };
@@ -1 +1,6 @@
1
- import{behaviorToEnvelope as e,errorToEnvelope as t,telemetryToEnvelope as n}from"./utils.js";import{RegeneratorService as r}from"./service.js";import{ProposalExecutor as i}from"./executor.js";import{ExecutorProposalSink as a}from"./sinks.js";export{a as ExecutorProposalSink,i as ProposalExecutor,r as RegeneratorService,e as behaviorToEnvelope,t as errorToEnvelope,n as telemetryToEnvelope};
1
+ import { behaviorToEnvelope, errorToEnvelope, telemetryToEnvelope } from "./utils.js";
2
+ import { RegeneratorService } from "./service.js";
3
+ import { ProposalExecutor } from "./executor.js";
4
+ import { ExecutorProposalSink } from "./sinks.js";
5
+
6
+ export { ExecutorProposalSink, ProposalExecutor, RegeneratorService, behaviorToEnvelope, errorToEnvelope, telemetryToEnvelope };