@lssm/module.contractspec-workspace 0.0.0-canary-20251213172311

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.
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @lssm/module.contractspec-workspace
2
+
3
+ Pure, deterministic domain logic and static analysis utilities for ContractSpec workspace operations.
4
+
5
+ ## Purpose
6
+
7
+ This module contains platform-agnostic logic used by ContractSpec tooling:
8
+
9
+ - **Types**: Shared type definitions for specs, templates, and analysis results
10
+ - **Analysis**: Static code analysis (spec scanning, dependency graphs, semantic diff)
11
+ - **Templates**: Code generation templates for specs and handlers
12
+ - **AI Prompts**: Prompt builders for AI-assisted spec creation and code generation
13
+
14
+ ## Design Principles
15
+
16
+ - **No side effects**: All functions are pure and deterministic
17
+ - **No CLI dependencies**: No `chalk`, `ora`, `commander`, or `inquirer`
18
+ - **No filesystem access**: Operations take code/data as input, return results
19
+ - **Reusable**: Can be used by CLI, web apps, VS Code extensions, etc.
20
+
21
+ ## Usage
22
+
23
+ ```typescript
24
+ import {
25
+ scanSpecSource,
26
+ computeSemanticDiff,
27
+ buildDependencyGraph,
28
+ validateSpecStructure,
29
+ generateOperationSpec,
30
+ } from '@lssm/module.contractspec-workspace';
31
+ ```
32
+
33
+ ## Exports
34
+
35
+ - `analysis/` - Static analysis utilities
36
+ - `templates/` - Code generation templates
37
+ - `ai/` - AI prompt builders
38
+ - `types/` - Shared type definitions
39
+
@@ -0,0 +1,100 @@
1
+ function e(e){return`You are a senior TypeScript developer implementing a handler for a contract specification.
2
+
3
+ Here is the contract spec:
4
+
5
+ \`\`\`typescript
6
+ ${e}
7
+ \`\`\`
8
+
9
+ Generate a complete handler implementation that:
10
+
11
+ 1. **Matches the spec signature**: Input/output types from the spec
12
+ 2. **Handles errors**: Implement error cases defined in spec.io.errors
13
+ 3. **Emits events**: Use the events declared in spec.sideEffects.emits
14
+ 4. **Validates input**: Use zod validation from the schema
15
+ 5. **Follows best practices**: Clean, type-safe TypeScript
16
+ 6. **Includes comments**: Explain business logic
17
+
18
+ The handler should be production-ready with proper error handling, logging points, and clear structure.
19
+
20
+ Return only the TypeScript code for the handler function.`}function t(e){return`You are a senior React developer creating a component for a presentation specification.
21
+
22
+ Here is the presentation spec:
23
+
24
+ \`\`\`typescript
25
+ ${e}
26
+ \`\`\`
27
+
28
+ Generate a complete React component that:
29
+
30
+ 1. **Props interface**: Typed props from the spec
31
+ 2. **Accessibility**: Proper ARIA labels, roles, keyboard navigation
32
+ 3. **Mobile-first**: Optimized for small screens and touch
33
+ 4. **Clean UI**: Simple, intuitive interface
34
+ 5. **Type-safe**: Full TypeScript with no 'any' types
35
+ 6. **Best practices**: React hooks, proper state management
36
+
37
+ The component should follow Atomic Design principles and be reusable.
38
+
39
+ Return only the TypeScript/TSX code for the component.`}function n(e){return`You are a senior React developer creating a form component from a form specification.
40
+
41
+ Here is the form spec:
42
+
43
+ \`\`\`typescript
44
+ ${e}
45
+ \`\`\`
46
+
47
+ Generate a complete form component using react-hook-form that:
48
+
49
+ 1. **Form validation**: Use zod schema for validation
50
+ 2. **Field types**: Proper inputs for each field type
51
+ 3. **Conditional logic**: Support visibleWhen, enabledWhen, requiredWhen predicates
52
+ 4. **Error handling**: Clear, user-friendly error messages
53
+ 5. **Accessibility**: Labels, hints, ARIA attributes
54
+ 6. **Mobile-optimized**: Touch-friendly, appropriate input types
55
+ 7. **Type-safe**: Full TypeScript
56
+
57
+ The form should provide excellent UX with real-time validation and helpful feedback.
58
+
59
+ Return only the TypeScript/TSX code for the form component.`}function r(e,t,n){return`You are a senior developer writing comprehensive tests.
60
+
61
+ Spec:
62
+ \`\`\`typescript
63
+ ${e}
64
+ \`\`\`
65
+
66
+ Implementation:
67
+ \`\`\`typescript
68
+ ${t}
69
+ \`\`\`
70
+
71
+ Generate complete test suite using Vitest that:
72
+ ${n===`handler`?`
73
+ - Test all acceptance scenarios from the spec
74
+ - Test error cases defined in spec.io.errors
75
+ - Verify events are emitted correctly
76
+ - Test input validation
77
+ - Test happy path and edge cases`:`
78
+ - Test rendering with various props
79
+ - Test user interactions
80
+ - Test accessibility (a11y)
81
+ - Test responsive behavior
82
+ - Test error states`}
83
+
84
+ Use clear test descriptions and follow AAA pattern (Arrange, Act, Assert).
85
+
86
+ Return only the TypeScript test code.`}function i(){return`You are an expert TypeScript developer with deep knowledge of:
87
+ - Type-safe API design
88
+ - React and modern hooks
89
+ - Test-driven development
90
+ - Accessibility best practices
91
+ - Clean code principles
92
+
93
+ Generate production-ready code that is:
94
+ - Fully typed (no 'any' or type assertions unless absolutely necessary)
95
+ - Well-documented with TSDoc comments
96
+ - Following project conventions
97
+ - Defensive and error-safe
98
+ - Easy to maintain and extend
99
+
100
+ Always prioritize code quality, safety, and user experience.`}export{t as buildComponentPrompt,n as buildFormPrompt,e as buildHandlerPrompt,r as buildTestPrompt,i as getCodeGenSystemPrompt};
@@ -0,0 +1,69 @@
1
+ function e(e,t){return`You are a senior software architect creating a contract specification for an operation.
2
+
3
+ The operation is a ${t} (${t===`command`?`changes state, has side effects`:`read-only, idempotent`}).
4
+
5
+ User description: ${e}
6
+
7
+ Create a complete contract specification following these guidelines:
8
+
9
+ 1. **Name**: Use dot notation like "domain.operationName" (e.g., "user.signup", "payment.charge")
10
+ 2. **Version**: Start at 1
11
+ 3. **Description**: Clear, concise summary (1-2 sentences)
12
+ 4. **Goal**: Business purpose - why this operation exists
13
+ 5. **Context**: Background, constraints, scope (what it does and doesn't do)
14
+ 6. **Input/Output**: Describe the shape (we'll create schemas separately)
15
+ 7. **Auth**: Who can call this - anonymous, user, or admin
16
+ 8. **Feature Flags**: Any flags that gate this operation
17
+ 9. **Side Effects**: What events might be emitted, analytics to track
18
+
19
+ Respond with a structured spec.`}function t(e){return`You are a senior software architect creating an event specification.
20
+
21
+ User description: ${e}
22
+
23
+ Create a complete event specification following these guidelines:
24
+
25
+ 1. **Name**: Use dot notation like "domain.event_name" (e.g., "user.signup_completed", "payment.charged")
26
+ 2. **Version**: Start at 1
27
+ 3. **Description**: Clear description of when this event is emitted
28
+ 4. **Payload**: Describe what data the event carries
29
+ 5. **PII Fields**: List any personally identifiable information fields (e.g., ["email", "name"])
30
+
31
+ Events represent things that have already happened and should use past tense.
32
+
33
+ Respond with a structured spec.`}function n(e,t){return`You are a senior software architect creating a presentation specification.
34
+
35
+ This is a ${t} presentation - ${{web_component:`a React component with props schema`,markdown:`markdown/MDX documentation or guide`,data:`structured data export (JSON/XML)`}[t]}.
36
+
37
+ User description: ${e}
38
+
39
+ Create a complete presentation specification following these guidelines:
40
+
41
+ 1. **Name**: Use dot notation like "domain.presentation_name" (e.g., "user.profile_card", "docs.api_guide")
42
+ 2. **Version**: Start at 1
43
+ 3. **Description**: What this presentation shows/provides
44
+ 4. **Kind-specific details**:
45
+ ${t===`web_component`?`- Component key (symbolic, resolved by host app)
46
+ - Props structure
47
+ - Analytics events to track`:t===`markdown`?`- Content or resource URI
48
+ - Target audience`:`- MIME type (e.g., application/json)
49
+ - Data structure description`}
50
+
51
+ Respond with a structured spec.`}function r(){return`You are an expert software architect specializing in API design and contract-driven development.
52
+
53
+ You create clear, well-documented specifications that serve as the single source of truth for operations, events, and presentations.
54
+
55
+ Your specs are:
56
+ - Precise and unambiguous
57
+ - Following TypeScript conventions
58
+ - Business-oriented (capturing the "why" not just "what")
59
+ - Designed for both humans and AI agents to understand
60
+
61
+ Always use proper dot notation for names and ensure all metadata is meaningful and accurate.`}function i(e,t){return t.length===0?e:`${e}
62
+
63
+ Here are some good examples for reference:
64
+
65
+ ${t.join(`
66
+
67
+ `)}
68
+
69
+ Follow this structure and quality level.`}export{i as addExampleContext,t as buildEventSpecPrompt,e as buildOperationSpecPrompt,n as buildPresentationSpecPrompt,r as getSystemPrompt};
@@ -0,0 +1,2 @@
1
+ function e(e){for(let t of e.values())t.dependents=[];for(let[t,n]of e)for(let r of n.dependencies){let n=e.get(r);n&&n.dependents.push(t)}for(let t of e.values())t.dependents.sort((e,t)=>e.localeCompare(t))}function t(e){let t=new Set,n=new Set,r=[];function i(a,o){if(n.has(a)){let e=o.indexOf(a);e>=0&&r.push([...o.slice(e),a]);return}if(t.has(a))return;t.add(a),n.add(a);let s=e.get(a);if(s)for(let e of s.dependencies)i(e,[...o,a]);n.delete(a)}for(let n of e.keys())t.has(n)||i(n,[]);return r}function n(e){let t=[];for(let[n,r]of e){let i=r.dependencies.filter(t=>!e.has(t));i.length>0&&t.push({contract:n,missing:i})}return t}function r(e){let t=[];t.push(`digraph ContractDependencies {`),t.push(` rankdir=LR;`),t.push(` node [shape=box];`);for(let[n,r]of e){for(let e of r.dependencies)t.push(` "${n}" -> "${e}";`);r.dependencies.length===0&&t.push(` "${n}";`)}return t.push(`}`),t.join(`
2
+ `)}function i(){return new Map}function a(e,t,n,r){e.set(t,{name:t,file:n,dependencies:r,dependents:[]})}export{a as addContractNode,e as buildReverseEdges,i as createContractGraph,t as detectCycles,n as findMissingDependencies,r as toDot};
@@ -0,0 +1 @@
1
+ function e(e,t){let n=[],r=/import\s+.*?\s+from\s+['"]([^'"]+\.(?:contracts|event|presentation|workflow|data-view|migration|telemetry|experiment|app-config|integration|knowledge)(?:\.[jt]s)?)['"]/g,i;for(;(i=r.exec(e))!==null;){let e=i[1];if(!e||!e.startsWith(`.`)&&!e.startsWith(`/`))continue;let t=e.split(`/`),r=(t[t.length-1]??``).replace(/\.(ts|js)$/,``).replace(/\.(contracts|event|presentation|workflow|data-view|migration|telemetry|experiment|app-config|integration|knowledge)$/,``);r.length>0&&n.push(r)}return Array.from(new Set(n)).sort((e,t)=>e.localeCompare(t))}export{e as parseImportedSpecNames};
@@ -0,0 +1 @@
1
+ import{scanSpecSource as e}from"../spec-scan.js";function t(t,o,s,c,l={}){let u=e(t,o),d=e(s,c),f=[];return n(f,`specType`,u.specType,d.specType,{breaking:!0,label:`Spec type`}),n(f,`name`,u.name,d.name,{breaking:!0,label:`Name`}),n(f,`version`,u.version,d.version,{breaking:!0,label:`Version`}),n(f,`kind`,u.kind,d.kind,{breaking:!0,label:`Kind`}),n(f,`stability`,u.stability,d.stability,{breaking:i(u,d),label:`Stability`}),r(f,`owners`,u.owners??[],d.owners??[],{label:`Owners`}),r(f,`tags`,u.tags??[],d.tags??[],{label:`Tags`}),a(f,u,d),l.breakingOnly?f.filter(e=>e.type===`breaking`):f}function n(e,t,n,r,i){n!==r&&e.push({type:i.breaking?`breaking`:`changed`,path:t,oldValue:n,newValue:r,description:`${i.label} changed`})}function r(e,t,n,r,i){let a=[...n].sort(),o=[...r].sort();JSON.stringify(a)!==JSON.stringify(o)&&e.push({type:`changed`,path:t,oldValue:a,newValue:o,description:`${i.label} changed`})}function i(e,t){let n={experimental:0,beta:1,stable:2,deprecated:3},r=e.stability?n[e.stability]??0:0;return(t.stability?n[t.stability]??0:0)>r}function a(e,t,r){n(e,`hasMeta`,t.hasMeta,r.hasMeta,{breaking:t.specType===`operation`||r.specType===`operation`,label:`meta section presence`}),n(e,`hasIo`,t.hasIo,r.hasIo,{breaking:t.specType===`operation`||r.specType===`operation`,label:`io section presence`}),n(e,`hasPolicy`,t.hasPolicy,r.hasPolicy,{breaking:t.specType===`operation`||r.specType===`operation`,label:`policy section presence`}),n(e,`hasPayload`,t.hasPayload,r.hasPayload,{breaking:t.specType===`event`||r.specType===`event`,label:`payload section presence`}),n(e,`hasContent`,t.hasContent,r.hasContent,{breaking:t.specType===`presentation`||r.specType===`presentation`,label:`content section presence`}),n(e,`hasDefinition`,t.hasDefinition,r.hasDefinition,{breaking:t.specType===`workflow`||r.specType===`workflow`,label:`definition section presence`})}export{t as computeSemanticDiff};
@@ -0,0 +1 @@
1
+ function e(e){return e.includes(`.contracts.`)?`operation`:e.includes(`.event.`)?`event`:e.includes(`.presentation.`)?`presentation`:e.includes(`.workflow.`)?`workflow`:e.includes(`.data-view.`)?`data-view`:e.includes(`.migration.`)?`migration`:e.includes(`.telemetry.`)?`telemetry`:e.includes(`.experiment.`)?`experiment`:e.includes(`.app-config.`)?`app-config`:e.includes(`.integration.`)?`integration`:e.includes(`.knowledge.`)?`knowledge`:`unknown`}function t(t,o){let s=e(o),c=n(t,`name`),l=n(t,`description`),u=n(t,`stability`),d=a(u)?u:void 0,f=i(t,`owners`),p=i(t,`tags`),m=r(t,`version`),h=n(t,`kind`),g=h===`command`||h===`query`?h:`unknown`,_=/meta\s*:\s*{/.test(t),v=/\bio\s*:\s*{/.test(t),y=/\bpolicy\s*:\s*{/.test(t),b=/\bpayload\s*:\s*{/.test(t),x=/\bcontent\s*:\s*{/.test(t),S=/\bdefinition\s*:\s*{/.test(t);return{filePath:o,specType:s,name:c??void 0,description:l??void 0,stability:d,owners:f,tags:p,version:m??void 0,kind:g,hasMeta:_,hasIo:v,hasPolicy:y,hasPayload:b,hasContent:x,hasDefinition:S}}function n(e,t){let n=RegExp(`${o(t)}\\s*:\\s*['"]([^'"]+)['"]`);return e.match(n)?.[1]??null}function r(e,t){let n=RegExp(`${o(t)}\\s*:\\s*(\\d+)`),r=e.match(n);if(!r?.[1])return null;let i=Number(r[1]);return Number.isFinite(i)?i:null}function i(e,t){let n=RegExp(`${o(t)}\\s*:\\s*\\[([\\s\\S]*?)\\]`),r=e.match(n);if(!r?.[1])return;let i=r[1],a=Array.from(i.matchAll(/['"]([^'"]+)['"]/g)).map(e=>e[1]).filter(e=>typeof e==`string`&&e.length>0);return a.length>0?a:void 0}function a(e){return e===`experimental`||e===`beta`||e===`stable`||e===`deprecated`}function o(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}export{e as inferSpecTypeFromFilePath,t as scanSpecSource};
@@ -0,0 +1 @@
1
+ function e(e,d){let f=[],p=[];return/export\s+(const|let)\s+\w+/.test(e)||f.push(`No exported spec found`),d.includes(`.contracts.`)&&t(e,f,p),d.includes(`.event.`)&&a(e,f,p),d.includes(`.presentation.`)&&o(e,f,p),d.includes(`.workflow.`)&&s(e,f,p),d.includes(`.data-view.`)&&u(e,f,p),d.includes(`.migration.`)&&c(e,f,p),d.includes(`.telemetry.`)&&n(e,f,p),d.includes(`.experiment.`)&&r(e,f,p),d.includes(`.app-config.`)&&i(e,f,p),l(e,f,p),{valid:f.length===0,errors:f,warnings:p}}function t(e,t,n){/define(Command|Query)/.test(e)||t.push(`Missing defineCommand or defineQuery call`),e.includes(`meta:`)||t.push(`Missing meta section`),e.includes(`io:`)||t.push(`Missing io section`),e.includes(`policy:`)||t.push(`Missing policy section`),e.match(/name:\s*['"][^'"]+['"]/)||t.push(`Missing or invalid name field`),e.match(/version:\s*\d+/)||t.push(`Missing or invalid version field`),e.match(/kind:\s*['"](?:command|query)['"]/)||t.push(`Missing or invalid kind field (must be "command" or "query")`),e.includes(`acceptance:`)||n.push(`No acceptance scenarios defined`),e.includes(`examples:`)||n.push(`No examples provided`),e.includes(`TODO`)&&n.push(`Contains TODO items that need completion`)}function n(e,t,n){e.match(/:\s*TelemetrySpec\s*=/)||t.push(`Missing TelemetrySpec type annotation`),e.match(/meta:\s*{[\s\S]*name:/)||t.push(`TelemetrySpec.meta is required`),e.includes(`events:`)||t.push(`TelemetrySpec must declare events`),e.match(/privacy:\s*'(public|internal|pii|sensitive)'/)||n.push(`No explicit privacy classification found`)}function r(e,t,n){e.match(/:\s*ExperimentSpec\s*=/)||t.push(`Missing ExperimentSpec type annotation`),e.includes(`controlVariant`)||t.push(`ExperimentSpec must declare controlVariant`),e.includes(`variants:`)||t.push(`ExperimentSpec must declare variants`),e.match(/allocation:\s*{/)||n.push(`ExperimentSpec missing allocation configuration`)}function i(e,t,n){e.match(/:\s*AppBlueprintSpec\s*=/)||t.push(`Missing AppBlueprintSpec type annotation`),e.includes(`meta:`)||t.push(`AppBlueprintSpec must define meta`),e.includes(`appId`)||n.push(`AppBlueprint meta missing appId assignment`),e.includes(`capabilities`)||n.push(`App blueprint spec does not declare capabilities`)}function a(e,t,n){e.includes(`defineEvent`)||t.push(`Missing defineEvent call`),e.match(/name:\s*['"][^'"]+['"]/)||t.push(`Missing or invalid name field`),e.match(/version:\s*\d+/)||t.push(`Missing or invalid version field`),e.includes(`payload:`)||t.push(`Missing payload field`);let r=e.match(/name:\s*['"]([^'"]+)['"]/);r?.[1]&&((r[1].split(`.`).pop()??``).match(/(ed|created|updated|deleted|completed)$/i)||n.push(`Event name should use past tense (e.g., "created", "updated")`))}function o(e,t,n){e.match(/:\s*PresentationSpec\s*=/)||t.push(`Missing PresentationSpec type annotation`),e.includes(`meta:`)||t.push(`Missing meta section`),e.includes(`content:`)||t.push(`Missing content section`),e.match(/kind:\s*['"](?:web_component|markdown|data)['"]/)||t.push(`Missing or invalid kind field`)}function s(e,t,n){e.match(/:\s*WorkflowSpec\s*=/)||t.push(`Missing WorkflowSpec type annotation`),e.includes(`definition:`)||t.push(`Missing definition section`),e.includes(`steps:`)||t.push(`Workflow must declare steps`),e.includes(`transitions:`)||n.push(`No transitions declared; workflow will complete after first step.`),e.match(/title:\s*['"][^'"]+['"]/)||n.push(`Missing workflow title`),e.match(/domain:\s*['"][^'"]+['"]/)||n.push(`Missing domain field`),e.includes(`TODO`)&&n.push(`Contains TODO items that need completion`)}function c(e,t,n){e.match(/:\s*MigrationSpec\s*=/)||t.push(`Missing MigrationSpec type annotation`),e.includes(`plan:`)?e.includes(`up:`)||t.push(`Migration must define at least one up step`):t.push(`Missing plan section`),e.match(/name:\s*['"][^'"]+['"]/)||t.push(`Missing or invalid migration name`),e.match(/version:\s*\d+/)||t.push(`Missing or invalid migration version`),e.includes(`TODO`)&&n.push(`Contains TODO items that need completion`)}function l(e,t,n){e.includes(`SchemaModel`)&&!e.includes(`from '@lssm/lib.schema'`)&&t.push(`Missing import for SchemaModel from @lssm/lib.schema`),e.includes(`from '@lssm/lib.contracts'`)||t.push(`Missing import from @lssm/lib.contracts`);let r=e.match(/owners:\s*\[(.*?)\]/s);r?.[1]&&(r[1].includes(`@`)||n.push(`Owners should start with @ (e.g., "@team")`)),e.match(/stability:\s*['"](?:experimental|beta|stable|deprecated)['"]/)||n.push(`Missing or invalid stability field`)}function u(e,t,n){e.match(/:\s*DataViewSpec\s*=/)||t.push(`Missing DataViewSpec type annotation`),e.includes(`meta:`)||t.push(`Missing meta section`),e.includes(`source:`)||t.push(`Missing source section`),e.includes(`view:`)||t.push(`Missing view section`),e.match(/kind:\s*['"](list|table|detail|grid)['"]/)||t.push(`Missing or invalid view.kind (list/table/detail/grid)`),e.match(/fields:\s*\[/)||t.push(`No fields defined for data view`)}export{e as validateSpecStructure};
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{DEFAULT_WORKSPACE_CONFIG as e}from"./types/generation-types.js";import{inferSpecTypeFromFilePath as t,scanSpecSource as n}from"./analysis/spec-scan.js";import{computeSemanticDiff as r}from"./analysis/diff/semantic.js";import{addContractNode as i,buildReverseEdges as a,createContractGraph as o,detectCycles as s,findMissingDependencies as c,toDot as l}from"./analysis/deps/graph.js";import{parseImportedSpecNames as u}from"./analysis/deps/parse-imports.js";import{validateSpecStructure as d}from"./analysis/validate/spec-structure.js";import{capitalize as f,escapeString as p,toCamelCase as m,toKebabCase as h,toPascalCase as g}from"./templates/utils.js";import{generateOperationSpec as _}from"./templates/operation.js";import{generateEventSpec as v}from"./templates/event.js";import{generatePresentationSpec as y}from"./templates/presentation.js";import{generateWorkflowSpec as b}from"./templates/workflow.js";import{generateWorkflowRunnerTemplate as x}from"./templates/workflow-runner.js";import{generateDataViewSpec as S}from"./templates/data-view.js";import{generateTelemetrySpec as C}from"./templates/telemetry.js";import{generateExperimentSpec as w}from"./templates/experiment.js";import{generateAppBlueprintSpec as T}from"./templates/app-config.js";import{generateMigrationSpec as E}from"./templates/migration.js";import{generateIntegrationSpec as D}from"./templates/integration.js";import{generateKnowledgeSpaceSpec as O}from"./templates/knowledge.js";import{generateComponentTemplate as k,generateHandlerTemplate as A,generateTestTemplate as j}from"./templates/handler.js";import{addExampleContext as M,buildEventSpecPrompt as N,buildOperationSpecPrompt as P,buildPresentationSpecPrompt as F,getSystemPrompt as I}from"./ai/spec-creation.js";import{buildComponentPrompt as L,buildFormPrompt as R,buildHandlerPrompt as z,buildTestPrompt as B,getCodeGenSystemPrompt as V}from"./ai/code-generation.js";export{e as DEFAULT_WORKSPACE_CONFIG,i as addContractNode,M as addExampleContext,L as buildComponentPrompt,N as buildEventSpecPrompt,R as buildFormPrompt,z as buildHandlerPrompt,P as buildOperationSpecPrompt,F as buildPresentationSpecPrompt,a as buildReverseEdges,B as buildTestPrompt,f as capitalize,r as computeSemanticDiff,o as createContractGraph,s as detectCycles,p as escapeString,c as findMissingDependencies,T as generateAppBlueprintSpec,k as generateComponentTemplate,S as generateDataViewSpec,v as generateEventSpec,w as generateExperimentSpec,A as generateHandlerTemplate,D as generateIntegrationSpec,O as generateKnowledgeSpaceSpec,E as generateMigrationSpec,_ as generateOperationSpec,y as generatePresentationSpec,C as generateTelemetrySpec,j as generateTestTemplate,x as generateWorkflowRunnerTemplate,b as generateWorkflowSpec,V as getCodeGenSystemPrompt,I as getSystemPrompt,t as inferSpecTypeFromFilePath,u as parseImportedSpecNames,n as scanSpecSource,m as toCamelCase,l as toDot,h as toKebabCase,g as toPascalCase,d as validateSpecStructure};
@@ -0,0 +1,33 @@
1
+ import{toPascalCase as e}from"./utils.js";function t(t){let d=e(t.name.split(`.`).pop()??`App`)+`AppConfig`,f=n(t),m=r(t),h=i(`dataViews`,t.dataViews),g=i(`workflows`,t.workflows),_=a(t),v=o(t),y=s(t),b=c(t),x=l(t),S=u(t),C=t.notes?` notes: '${p(t.notes)}',\n`:``;return`import type { AppBlueprintSpec } from '@lssm/lib.contracts/app-config';
2
+
3
+ export const ${d}: AppBlueprintSpec = {
4
+ meta: {
5
+ name: '${p(t.name)}',
6
+ version: ${t.version},
7
+ title: '${p(t.title)}',
8
+ description: '${p(t.description)}',
9
+ domain: '${p(t.domain)}',
10
+ owners: [${t.owners.map(e=>`'${p(e)}'`).join(`, `)}],
11
+ tags: [${t.tags.map(e=>`'${p(e)}'`).join(`, `)}],
12
+ stability: '${t.stability}',
13
+ appId: '${p(t.appId)}',
14
+ },
15
+ ${f}${m}${h}${g}${_}${v}${y}${b}${x}${S}${C}};\n`}function n(e){return e.capabilitiesEnabled.length===0&&e.capabilitiesDisabled.length===0?``:` capabilities: {\n${e.capabilitiesEnabled.length>0?` enabled: [${e.capabilitiesEnabled.map(e=>d(e)).join(`, `)}],\n`:``}${e.capabilitiesDisabled.length>0?` disabled: [${e.capabilitiesDisabled.map(e=>d(e)).join(`, `)}],\n`:``} },\n`}function r(e){return e.featureIncludes.length===0&&e.featureExcludes.length===0?``:` features: {\n${e.featureIncludes.length>0?` include: [${e.featureIncludes.map(e=>`{ key: '${p(e)}' }`).join(`, `)}],\n`:``}${e.featureExcludes.length>0?` exclude: [${e.featureExcludes.map(e=>`{ key: '${p(e)}' }`).join(`, `)}],\n`:``} },\n`}function i(e,t){return t.length===0?``:` ${e}: {\n${t.map(e=>` ${e.slot}: {
16
+ name: '${p(e.name)}',
17
+ ${typeof e.version==`number`?`version: ${e.version},`:``}
18
+ }`).join(`,
19
+ `)}\n },\n`}function a(e){return e.policyRefs.length===0?``:` policies: [\n${e.policyRefs.map(e=>` {
20
+ name: '${p(e.name)}'${typeof e.version==`number`?`,\n version: ${e.version}`:``}
21
+ }`).join(`,
22
+ `)}\n ],\n`}function o(e){return e.theme?` theme: {\n${` primary: { name: '${p(e.theme.name)}', version: ${e.theme.version} },\n`}${e.themeFallbacks.length>0?` fallbacks: [${e.themeFallbacks.map(e=>`{ name: '${p(e.name)}', version: ${e.version} }`).join(`, `)}],\n`:``} },\n`:``}function s(e){return e.telemetry?` telemetry: {
23
+ spec: {
24
+ name: '${p(e.telemetry.name)}'${typeof e.telemetry.version==`number`?`,\n version: ${e.telemetry.version}`:``}
25
+ },
26
+ },\n`:``}function c(e){return e.activeExperiments.length===0&&e.pausedExperiments.length===0?``:` experiments: {\n${e.activeExperiments.length>0?` active: [${e.activeExperiments.map(e=>f(e)).join(`, `)}],\n`:``}${e.pausedExperiments.length>0?` paused: [${e.pausedExperiments.map(e=>f(e)).join(`, `)}],\n`:``} },\n`}function l(e){return e.featureFlags.length===0?``:` featureFlags: [\n${e.featureFlags.map(e=>` {
27
+ key: '${p(e.key)}',
28
+ enabled: ${e.enabled},
29
+ ${e.variant?`variant: '${p(e.variant)}',`:``}
30
+ ${e.description?`description: '${p(e.description)}',`:``}
31
+ }`).join(`,
32
+ `)}\n ],\n`}function u(e){return e.routes.length===0?``:` routes: [\n${e.routes.map(e=>` { ${[`path: '${p(e.path)}'`,e.label?`label: '${p(e.label)}'`:null,e.dataView?`dataView: '${p(e.dataView)}'`:null,e.workflow?`workflow: '${p(e.workflow)}'`:null,e.guardName?`guard: { name: '${p(e.guardName)}'${typeof e.guardVersion==`number`?`, version: ${e.guardVersion}`:``} }`:null,e.featureFlag?`featureFlag: '${p(e.featureFlag)}'`:null,e.experimentName?`experiment: { name: '${p(e.experimentName)}'${typeof e.experimentVersion==`number`?`, version: ${e.experimentVersion}`:``} }`:null].filter(Boolean).join(`, `)} }`).join(`,
33
+ `)}\n ],\n`}function d(e){return`{ key: '${p(e)}' }`}function f(e){let t=typeof e.version==`number`?`, version: ${e.version}`:``;return`{ name: '${p(e.name)}'${t} }`}function p(e){return e.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`)}export{t as generateAppBlueprintSpec};
@@ -0,0 +1,54 @@
1
+ import{escapeString as e,toPascalCase as t}from"./utils.js";function n(n){let i=t(n.name.split(`.`).pop()??`DataView`)+`DataView`,a=n.fields.map(t=>` {
2
+ key: '${e(t.key)}',
3
+ label: '${r(t.label)}',
4
+ dataPath: '${e(t.dataPath)}',
5
+ ${t.format?`format: '${e(t.format)}',`:``}
6
+ ${t.sortable?`sortable: true,`:``}
7
+ ${t.filterable?`filterable: true,`:``}
8
+ }`).join(`,
9
+ `),o=n.secondaryFields?.length?`secondaryFields: [${n.secondaryFields.map(t=>`'${e(t)}'`).join(`, `)}],`:``,s=n.itemOperation?`item: { name: '${e(n.itemOperation.name)}', version: ${n.itemOperation.version} },`:``;return`import type { DataViewSpec } from '@lssm/lib.contracts/data-views';
10
+
11
+ export const ${i}: DataViewSpec = {
12
+ meta: {
13
+ name: '${e(n.name)}',
14
+ version: ${n.version},
15
+ entity: '${e(n.entity)}',
16
+ title: '${r(n.title)}',
17
+ description: '${r(n.description||`Describe the purpose of this data view.`)}',
18
+ domain: '${r(n.domain||n.entity)}',
19
+ owners: [${n.owners.map(t=>`'${e(t)}'`).join(`, `)}],
20
+ tags: [${n.tags.map(t=>`'${e(t)}'`).join(`, `)}],
21
+ stability: '${n.stability}',
22
+ },
23
+ source: {
24
+ primary: {
25
+ name: '${e(n.primaryOperation.name)}',
26
+ version: ${n.primaryOperation.version},
27
+ },
28
+ ${s}
29
+ refreshEvents: [
30
+ // { name: 'entity.updated', version: 1 },
31
+ ],
32
+ },
33
+ view: {
34
+ kind: '${n.kind}',
35
+ fields: [
36
+ ${a}
37
+ ],
38
+ ${n.primaryField?`primaryField: '${e(n.primaryField)}',`:``}
39
+ ${o}
40
+ filters: [
41
+ // Example filter:
42
+ // { key: 'search', label: 'Search', field: 'fullName', type: 'search' },
43
+ ],
44
+ actions: [
45
+ // Example action:
46
+ // { key: 'open', label: 'Open', kind: 'navigation' },
47
+ ],
48
+ },
49
+ states: {
50
+ // empty: { name: 'app.data.empty', version: 1 },
51
+ // error: { name: 'app.data.error', version: 1 },
52
+ },
53
+ };
54
+ `}function r(e){return e.replace(/'/g,`\\'`)}export{n as generateDataViewSpec};
@@ -0,0 +1,24 @@
1
+ import{toPascalCase as e}from"./utils.js";function t(t){let{name:n,version:r,description:i,stability:a,owners:o,tags:s,piiFields:c}=t,l=e(n.replace(/\./g,`_`))+`V`+r,u=l+`Payload`;return`import { defineEvent } from '@lssm/lib.contracts';
2
+ import { ScalarTypeEnum, SchemaModel } from '@lssm/lib.schema';
3
+
4
+ // TODO: Define event payload schema
5
+ export const ${u} = new SchemaModel({
6
+ name: '${u}',
7
+ description: 'Payload for ${n}',
8
+ fields: {
9
+ // Add your payload fields here
10
+ // example: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
11
+ },
12
+ });
13
+
14
+ export const ${l} = defineEvent({
15
+ name: '${n}',
16
+ version: ${r},
17
+ description: '${i}',
18
+ stability: '${a}',
19
+ owners: [${o.map(e=>`'${e}'`).join(`, `)}],
20
+ tags: [${s.map(e=>`'${e}'`).join(`, `)}],
21
+ ${c.length>0?`pii: [${c.map(e=>`'${e}'`).join(`, `)}],`:`// pii: [],`}
22
+ payload: ${u},
23
+ });
24
+ `}export{t as generateEventSpec};
@@ -0,0 +1,62 @@
1
+ import{toPascalCase as e}from"./utils.js";function t(t){let i=e(t.name.split(`.`).pop()??`Experiment`)+`Experiment`,a=t.variants.map(e=>{let t=e.overrides?.length?` overrides: [
2
+ ${e.overrides.map(e=>` {
3
+ type: '${e.type}',
4
+ target: '${r(e.target)}',
5
+ ${typeof e.version==`number`?`version: ${e.version},`:``}
6
+ }`).join(`,
7
+ `)}
8
+ ],`:``;return` {
9
+ id: '${r(e.id)}',
10
+ name: '${r(e.name)}',
11
+ ${e.description?`description: '${r(e.description)}',`:``}
12
+ ${typeof e.weight==`number`?`weight: ${e.weight},`:``}
13
+ ${t}
14
+ }`}).join(`,
15
+ `),o=n(t.allocation),s=t.successMetrics?.length?` successMetrics: [
16
+ ${t.successMetrics.map(e=>` {
17
+ name: '${r(e.name)}',
18
+ telemetryEvent: { name: '${r(e.eventName)}', version: ${e.eventVersion} },
19
+ aggregation: '${e.aggregation}',
20
+ ${typeof e.target==`number`?`target: ${e.target},`:``}
21
+ }`).join(`,
22
+ `)}
23
+ ],`:``;return`import type { ExperimentSpec } from '@lssm/lib.contracts/experiments';
24
+
25
+ export const ${i}: ExperimentSpec = {
26
+ meta: {
27
+ name: '${r(t.name)}',
28
+ version: ${t.version},
29
+ title: '${r(t.name)} experiment',
30
+ description: '${r(t.description||`Describe the experiment goal.`)}',
31
+ domain: '${r(t.domain)}',
32
+ owners: [${t.owners.map(e=>`'${r(e)}'`).join(`, `)}],
33
+ tags: [${t.tags.map(e=>`'${r(e)}'`).join(`, `)}],
34
+ stability: '${t.stability}',
35
+ },
36
+ controlVariant: '${r(t.controlVariant)}',
37
+ variants: [
38
+ ${a}
39
+ ],
40
+ allocation: ${o},
41
+ ${s}
42
+ };
43
+ `}function n(e){switch(e.type){case`random`:return`{
44
+ type: 'random',
45
+ ${e.salt?`salt: '${r(e.salt)}',`:``}
46
+ }`;case`sticky`:return`{
47
+ type: 'sticky',
48
+ attribute: '${e.attribute}',
49
+ ${e.salt?`salt: '${r(e.salt)}',`:``}
50
+ }`;case`targeted`:return`{
51
+ type: 'targeted',
52
+ rules: [
53
+ ${e.rules.map(e=>` {
54
+ variantId: '${r(e.variantId)}',
55
+ ${typeof e.percentage==`number`?`percentage: ${e.percentage},`:``}
56
+ ${e.policy?`policy: { name: '${r(e.policy.name)}'${typeof e.policy.version==`number`?`, version: ${e.policy.version}`:``} },`:``}
57
+ ${e.expression?`expression: '${r(e.expression)}',`:``}
58
+ }`).join(`,
59
+ `)}
60
+ ],
61
+ fallback: '${e.fallback??`control`}',
62
+ }`;default:return i(e)}}function r(e){return e.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`)}function i(e){throw Error(`Unsupported allocation type ${e}`)}export{t as generateExperimentSpec};
@@ -0,0 +1,63 @@
1
+ import{toCamelCase as e,toKebabCase as t,toPascalCase as n}from"./utils.js";function r(r,i){let a=e(r.split(`.`).pop()??`unknown`)+`Handler`,o=n(r.split(`.`).pop()??`Unknown`)+`Spec`;return`import type { ContractHandler } from '@lssm/lib.contracts';
2
+ import { ${o} } from '../contracts/${t(r)}.contracts';
3
+
4
+ /**
5
+ * Handler for ${r}
6
+ */
7
+ export const ${a}: ContractHandler<typeof ${o}> = async (
8
+ input,
9
+ context
10
+ ) => {
11
+ // TODO: Implement ${i} logic
12
+
13
+ try {
14
+ // 1. Validate prerequisites
15
+ // 2. Perform business logic
16
+ // 3. Emit events if needed
17
+ // 4. Return result
18
+
19
+ return {
20
+ ok: true,
21
+ };
22
+ } catch (error) {
23
+ // Handle and map errors to spec.io.errors
24
+ throw error;
25
+ }
26
+ };
27
+ `}function i(e,t){let r=n(e);return`import React from 'react';
28
+
29
+ interface ${r}Props {
30
+ // TODO: Define props based on presentation spec
31
+ }
32
+
33
+ /**
34
+ * ${t}
35
+ */
36
+ export const ${r}: React.FC<${r}Props> = (props) => {
37
+ return (
38
+ <div>
39
+ {/* TODO: Implement component UI */}
40
+ <p>Component: ${r}</p>
41
+ </div>
42
+ );
43
+ };
44
+ `}function a(e,r){let i=r===`handler`?`../handlers`:`../components`,a=n(e);return`import { describe, it, expect } from 'bun:test';
45
+ import { ${a} } from '${i}/${t(e)}';
46
+
47
+ describe('${a}', () => {
48
+ it('should ${r===`handler`?`handle valid input`:`render correctly`}', async () => {
49
+ // TODO: Implement test
50
+ expect(true).toBe(true);
51
+ });
52
+
53
+ it('should handle edge cases', async () => {
54
+ // TODO: Test edge cases
55
+ });
56
+
57
+ ${r===`handler`?`it('should handle errors appropriately', async () => {
58
+ // TODO: Test error scenarios
59
+ });`:`it('should be accessible', async () => {
60
+ // TODO: Test accessibility
61
+ });`}
62
+ });
63
+ `}export{i as generateComponentTemplate,r as generateHandlerTemplate,a as generateTestTemplate};
@@ -0,0 +1,33 @@
1
+ function e(e){let t=e.filter(e=>e.required);return` schema: {
2
+ type: 'object',
3
+ ${t.length>0?` required: [${t.map(e=>`'${e.key}'`).join(`, `)}],
4
+ `:``} properties: {
5
+ ${(e.length?e.map(e=>{let t=e.description?`, description: '${u(e.description)}'`:``;return` ${e.key}: { type: '${o(e.type)}'${t} }`}).join(`,
6
+ `):``)||` `}
7
+ },
8
+ },\n`}function t(e){let t=e.filter(e=>e.required);return` schema: {
9
+ type: 'object',
10
+ ${t.length>0?` required: [${t.map(e=>`'${e.key}'`).join(`, `)}],
11
+ `:``} properties: {
12
+ ${(e.length?e.map(e=>{let t=e.description?`, description: '${u(e.description)}'`:``;return` ${e.key}: { type: 'string'${t} }`}).join(`,
13
+ `):``)||` `}
14
+ },
15
+ },\n`}function n(e){return e.length===0?`{}`:`{
16
+ ${e.map(e=>{switch(e.type){case`number`:return` ${e.key}: 0`;case`boolean`:return` ${e.key}: true`;case`string`:default:return` ${e.key}: '${e.key.toUpperCase()}_VALUE'`}}).join(`,
17
+ `)}
18
+ }`}function r(e){return e.length===0?`{}`:`{
19
+ ${e.map(e=>` ${e.key}: '${e.key.toUpperCase()}_SECRET'`).join(`,
20
+ `)}
21
+ }`}function i(e,t){if(e==null&&t==null)return``;let n=[];return e!=null&&n.push(` rpm: ${e}`),t!=null&&n.push(` rph: ${t}`),` constraints: {
22
+ rateLimit: {
23
+ ${n.join(`,
24
+ `)}
25
+ },
26
+ },
27
+ `}function a(e,t,n){if(!e.includes(`byok`))return``;let r=t?` setupInstructions: '${u(t)}',\n`:``,i=n&&n.length?` requiredScopes: [${n.map(e=>`'${u(e)}'`).join(`, `)}],\n`:``;return!r&&!i?``:` byokSetup: {
28
+ ${r}${i} },
29
+ `}function o(e){switch(e){case`number`:return`number`;case`boolean`:return`boolean`;case`string`:default:return`string`}}function s(e){switch(e){case`beta`:return`Beta`;case`stable`:return`Stable`;case`deprecated`:return`Deprecated`;case`experimental`:default:return`Experimental`}}function c(e){return e.capabilitiesProvided.map(e=>` { key: '${e.key}', version: ${e.version} }`).join(`,
30
+ `)}function l(e){return e.capabilitiesRequired.length===0?``:` requires: [
31
+ ${e.capabilitiesRequired.map(e=>{let t=typeof e.version==`number`?`, version: ${e.version}`:``,n=e.optional?`, optional: true`:``,r=e.reason?`, reason: '${u(e.reason)}'`:``;return` { key: '${e.key}'${t}${n}${r} }`}).join(`,
32
+ `)}
33
+ ],`}function u(e){return e.replace(/`/g,"\\`").replace(/'/g,`\\'`)}export{u as escape,a as renderByokSetup,n as renderConfigExample,e as renderConfigSchema,i as renderConstraints,c as renderProvides,l as renderRequires,r as renderSecretExample,t as renderSecretSchema,s as stabilityToEnum};
@@ -0,0 +1,39 @@
1
+ import{toPascalCase as e}from"./utils.js";import{escape as t,renderByokSetup as n,renderConfigExample as r,renderConfigSchema as i,renderConstraints as a,renderProvides as o,renderRequires as s,renderSecretExample as c,renderSecretSchema as l,stabilityToEnum as u}from"./integration-utils.js";function d(d){let f=e(d.name.split(`.`).pop()??`Integration`),p=`${f}IntegrationSpec`,m=`register${f}Integration`,h=d.supportedModes.length?d.supportedModes:[`managed`],g=h.map(e=>`'${e}'`).join(`, `),_=o(d),v=s(d),y=i(d.configFields),b=r(d.configFields),x=l(d.secretFields),S=c(d.secretFields),C=d.docsUrl?` docsUrl: '${t(d.docsUrl)}',\n`:``,w=a(d.rateLimitRpm,d.rateLimitRph),T=n(h,d.byokSetupInstructions,d.byokRequiredScopes);return`import { StabilityEnum } from '@lssm/lib.contracts/ownership';
2
+ import type { IntegrationSpec } from '@lssm/lib.contracts/integrations/spec';
3
+ import type { IntegrationSpecRegistry } from '@lssm/lib.contracts/integrations/spec';
4
+
5
+ export const ${p}: IntegrationSpec = {
6
+ meta: {
7
+ key: '${t(d.name)}',
8
+ version: ${d.version},
9
+ category: '${d.category}',
10
+ displayName: '${t(d.displayName)}',
11
+ title: '${t(d.title)}',
12
+ description: '${t(d.description)}',
13
+ domain: '${t(d.domain)}',
14
+ owners: [${d.owners.map(e=>`'${t(e)}'`).join(`, `)}],
15
+ tags: [${d.tags.map(e=>`'${t(e)}'`).join(`, `)}],
16
+ stability: StabilityEnum.${u(d.stability)},
17
+ },
18
+ supportedModes: [${g}],
19
+ capabilities: {
20
+ provides: [
21
+ ${_}
22
+ ],
23
+ ${v.length>0?`${v}\n`:``} },
24
+ configSchema: {
25
+ ${y} example: ${b},
26
+ },
27
+ secretSchema: {
28
+ ${x} example: ${S},
29
+ },
30
+ ${C}${w}${T} healthCheck: {
31
+ method: '${d.healthCheckMethod}',
32
+ timeoutMs: ${d.healthCheckTimeoutMs??5e3},
33
+ },
34
+ };
35
+
36
+ export function ${m}(registry: IntegrationSpecRegistry): IntegrationSpecRegistry {
37
+ return registry.register(${p});
38
+ }
39
+ `}export{d as generateIntegrationSpec};
@@ -0,0 +1,28 @@
1
+ import{escapeString as e,toPascalCase as t}from"./utils.js";function n(n){let c=t(n.name.split(`.`).pop()??`KnowledgeSpace`),l=`${c}KnowledgeSpace`,u=`register${c}KnowledgeSpace`,d=r(n),f=i(n),p=a(n),m=n.policyName&&!n.policyVersion?` // defaults to latest version`:``;return`import { StabilityEnum } from '@lssm/lib.contracts/ownership';
2
+ import type { KnowledgeSpaceSpec } from '@lssm/lib.contracts/knowledge/spec';
3
+ import type { KnowledgeSpaceRegistry } from '@lssm/lib.contracts/knowledge/spec';
4
+
5
+ export const ${l}: KnowledgeSpaceSpec = {
6
+ meta: {
7
+ key: '${e(n.name)}',
8
+ version: ${n.version},
9
+ category: '${n.category}',
10
+ displayName: '${s(n.displayName)}',
11
+ title: '${s(n.title)}',
12
+ description: '${s(n.description)}',
13
+ domain: '${s(n.domain)}',
14
+ owners: [${n.owners.map(t=>`'${e(t)}'`).join(`, `)}],
15
+ tags: [${n.tags.map(t=>`'${e(t)}'`).join(`, `)}],
16
+ stability: StabilityEnum.${o(n.stability)},
17
+ },
18
+ retention: ${d},
19
+ access: {
20
+ ${f}${n.policyName?` policy: { name: '${e(n.policyName)}',${n.policyVersion?` version: ${n.policyVersion}`:``} },${m}\n`:``} },
21
+ ${p} description: '${s(n.description||n.displayName)}',
22
+ };
23
+
24
+ export function ${u}(registry: KnowledgeSpaceRegistry): KnowledgeSpaceRegistry {
25
+ return registry.register(${l});
26
+ }
27
+ `}function r(e){return`{ ttlDays: ${e.retention.ttlDays===null?`null`:typeof e.retention.ttlDays==`number`?String(e.retention.ttlDays):`null`}${typeof e.retention.archiveAfterDays==`number`?`, archiveAfterDays: ${e.retention.archiveAfterDays}`:``} }`}function i(e){return`${` trustLevel: '${e.trustLevel}',\n`}${` automationWritable: ${e.automationWritable},\n`}`}function a(e){let t=[];return e.embeddingModel&&t.push(` embeddingModel: '${s(e.embeddingModel)}'`),typeof e.chunkSize==`number`&&t.push(` chunkSize: ${e.chunkSize}`),e.vectorDbIntegration&&t.push(` vectorDbIntegration: '${s(e.vectorDbIntegration)}'`),t.length===0?``:` indexing: {\n${t.join(`,
28
+ `)}\n },\n`}function o(e){switch(e){case`beta`:return`Beta`;case`stable`:return`Stable`;case`deprecated`:return`Deprecated`;case`experimental`:default:return`Experimental`}}function s(e){return e.replace(/`/g,"\\`").replace(/'/g,`\\'`)}export{n as generateKnowledgeSpaceSpec};
@@ -0,0 +1,37 @@
1
+ import{escapeString as e,toPascalCase as t}from"./utils.js";function n(n){let a=`${t(n.name.split(`.`).pop()??`Migration`)}Migration`,o=n.dependencies.length>0?`dependencies: [${n.dependencies.map(t=>`'${e(t)}'`).join(`, `)}],`:``;return`import type { MigrationSpec } from '@lssm/lib.contracts/migrations';
2
+
3
+ export const ${a}: MigrationSpec = {
4
+ meta: {
5
+ name: '${e(n.name)}',
6
+ version: ${n.version},
7
+ title: '${i(n.title)}',
8
+ description: '${i(n.description??``)}',
9
+ domain: '${i(n.domain)}',
10
+ owners: [${n.owners.map(t=>`'${e(t)}'`).join(`, `)}],
11
+ tags: [${n.tags.map(t=>`'${e(t)}'`).join(`, `)}],
12
+ stability: '${n.stability}',
13
+ },
14
+ plan: {
15
+ up: [
16
+ ${r(n.up)}
17
+ ],${n.down&&n.down.length?`
18
+ down: [
19
+ ${r(n.down)}
20
+ ],`:``}
21
+ },
22
+ ${o}
23
+ };
24
+ `}function r(e){return e.map(e=>{let t=e.description?`description: '${i(e.description)}',`:``;switch(e.kind){case`schema`:return` {
25
+ kind: 'schema',
26
+ ${t}
27
+ sql: \`${i(e.sql??``)}\`,
28
+ }`;case`data`:return` {
29
+ kind: 'data',
30
+ ${t}
31
+ script: \`${i(e.script??``)}\`,
32
+ }`;case`validation`:default:return` {
33
+ kind: 'validation',
34
+ ${t}
35
+ assertion: \`${i(e.assertion??``)}\`,
36
+ }`}}).join(`,
37
+ `)}function i(e){return e.replace(/`/g,"\\`").replace(/'/g,`\\'`)}export{n as generateMigrationSpec};
@@ -0,0 +1,88 @@
1
+ import{capitalize as e,toPascalCase as t}from"./utils.js";function n(n){let{name:r,version:i,kind:a,description:o,goal:s,context:c,stability:l,owners:u,tags:d,auth:f,flags:p}=n,m=t(r.split(`.`).pop()??`Unknown`)+`Spec`,h=m.replace(`Spec`,`Input`),g=m.replace(`Spec`,`Output`);return`import { define${e(a)} } from '@lssm/lib.contracts';
2
+ import { ScalarTypeEnum, SchemaModel } from '@lssm/lib.schema';
3
+
4
+ // TODO: Define input schema
5
+ export const ${h} = new SchemaModel({
6
+ name: '${h}',
7
+ description: 'Input for ${r}',
8
+ fields: {
9
+ // Add your fields here
10
+ // example: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
11
+ },
12
+ });
13
+
14
+ // TODO: Define output schema
15
+ export const ${g} = new SchemaModel({
16
+ name: '${g}',
17
+ description: 'Output for ${r}',
18
+ fields: {
19
+ // Add your fields here
20
+ ok: { type: ScalarTypeEnum.Boolean(), isOptional: false },
21
+ },
22
+ });
23
+
24
+ export const ${m} = define${e(a)}({
25
+ meta: {
26
+ name: '${r}',
27
+ version: ${i},
28
+ stability: '${l}',
29
+ owners: [${u.map(e=>`'${e}'`).join(`, `)}],
30
+ tags: [${d.map(e=>`'${e}'`).join(`, `)}],
31
+ description: '${o}',
32
+ goal: '${s}',
33
+ context: '${c}',
34
+ },
35
+
36
+ io: {
37
+ input: ${h},
38
+ output: ${g},
39
+ errors: {
40
+ // Define possible errors
41
+ // EXAMPLE_ERROR: {
42
+ // description: 'Example error description',
43
+ // http: 400,
44
+ // when: 'When this error occurs',
45
+ // },
46
+ },
47
+ },
48
+
49
+ policy: {
50
+ auth: '${f}',
51
+ ${p.length>0?`flags: [${p.map(e=>`'${e}'`).join(`, `)}],`:`// flags: [],`}
52
+ },
53
+
54
+ sideEffects: {
55
+ ${n.emitsEvents?`emits: [
56
+ // Define events to emit
57
+ // { ref: SomeEventSpec, when: 'always' }
58
+ ],`:`// emits: [],`}
59
+ analytics: [
60
+ // Define analytics events
61
+ ],
62
+ },
63
+
64
+ transport: {
65
+ rest: { method: '${a===`command`?`POST`:`GET`}' },
66
+ gql: { field: '${r.replace(/\./g,`_`)}' },
67
+ mcp: { toolName: '${r}.v${i}' },
68
+ },
69
+
70
+ acceptance: {
71
+ scenarios: [
72
+ {
73
+ name: 'Happy path',
74
+ given: ['preconditions'],
75
+ when: ['action taken'],
76
+ then: ['expected outcome'],
77
+ },
78
+ ],
79
+ examples: [
80
+ {
81
+ name: 'Example usage',
82
+ input: { /* example input */ },
83
+ output: { ok: true },
84
+ },
85
+ ],
86
+ },
87
+ });
88
+ `}export{n as generateOperationSpec};
@@ -0,0 +1,53 @@
1
+ import{toPascalCase as e}from"./utils.js";function t(t){let{name:n,version:r,description:i,stability:a,owners:o,tags:s,presentationKind:c}=t,l=e(n.replace(/\./g,`_`))+`Presentation`,u=``;switch(c){case`web_component`:u=` content: {
2
+ kind: 'web_component',
3
+ framework: 'react',
4
+ componentKey: '${n.replace(/\./g,`_`)}',
5
+ props: new SchemaModel({
6
+ name: '${l}Props',
7
+ description: 'Props for ${n}',
8
+ fields: {
9
+ // TODO: Define component props
10
+ },
11
+ }),
12
+ analytics: [
13
+ // TODO: Define analytics events
14
+ ],
15
+ },`;break;case`markdown`:u=` content: {
16
+ kind: 'markdown',
17
+ content: \`
18
+ # ${i}
19
+
20
+ TODO: Add markdown content here
21
+ \`,
22
+ // Or use resourceUri: 'feature://${n}/guide.md'
23
+ },`;break;case`data`:u=` content: {
24
+ kind: 'data',
25
+ mimeType: 'application/json',
26
+ model: new SchemaModel({
27
+ name: '${l}Data',
28
+ description: 'Data structure for ${n}',
29
+ fields: {
30
+ // TODO: Define data structure
31
+ },
32
+ }),
33
+ },`;break}return`import type { PresentationSpec } from '@lssm/lib.contracts/presentations';
34
+ import { SchemaModel, ScalarTypeEnum } from '@lssm/lib.schema';
35
+
36
+ export const ${l}: PresentationSpec = {
37
+ meta: {
38
+ name: '${n}',
39
+ version: ${r},
40
+ stability: '${a}',
41
+ owners: [${o.map(e=>`'${e}'`).join(`, `)}],
42
+ tags: [${s.map(e=>`'${e}'`).join(`, `)}],
43
+ description: '${i}',
44
+ },
45
+
46
+ policy: {
47
+ // flags: [],
48
+ // pii: [],
49
+ },
50
+
51
+ ${u}
52
+ };
53
+ `}export{t as generatePresentationSpec};
@@ -0,0 +1,69 @@
1
+ import{toPascalCase as e}from"./utils.js";function t(t){let i=e(t.name.split(`.`).pop()??`Telemetry`)+`Telemetry`,a=t.providers?.length?`providers: [
2
+ ${t.providers.map(e=>` {
3
+ type: '${e.type}',
4
+ config: ${r(e.config)},
5
+ }`).join(`,
6
+ `)}
7
+ ],`:``,o=t.events.map(e=>{let t=e.properties.map(e=>` '${e.name}': {
8
+ type: '${e.type}',
9
+ ${e.required?`required: true,`:``}
10
+ ${e.pii?`pii: true,`:``}
11
+ ${e.redact?`redact: true,`:``}
12
+ ${e.description?`description: '${n(e.description)}',`:``}
13
+ }`).join(`,
14
+ `),r=e.anomalyRules?.length?` anomalyDetection: {
15
+ enabled: true,
16
+ ${typeof e.anomalyMinimumSample==`number`?`minimumSample: ${e.anomalyMinimumSample},`:``}
17
+ thresholds: [
18
+ ${e.anomalyRules.map(e=>` {
19
+ metric: '${n(e.metric)}',
20
+ ${typeof e.min==`number`?`min: ${e.min},`:``}
21
+ ${typeof e.max==`number`?`max: ${e.max},`:``}
22
+ }`).join(`,
23
+ `)}
24
+ ],
25
+ actions: [${(e.anomalyActions??[]).map(e=>`'${e}'`).join(`, `)}],
26
+ },`:e.anomalyEnabled?` anomalyDetection: {
27
+ enabled: true,
28
+ ${typeof e.anomalyMinimumSample==`number`?`minimumSample: ${e.anomalyMinimumSample},`:``}
29
+ },`:``;return` {
30
+ name: '${n(e.name)}',
31
+ version: ${e.version},
32
+ semantics: {
33
+ what: '${n(e.what)}',
34
+ ${e.who?`who: '${n(e.who)}',`:``}
35
+ ${e.why?`why: '${n(e.why)}',`:``}
36
+ },
37
+ privacy: '${e.privacy}',
38
+ properties: {
39
+ ${t}
40
+ },
41
+ ${typeof e.retentionDays==`number`?`retention: { days: ${e.retentionDays}, ${e.retentionPolicy?`policy: '${e.retentionPolicy}'`:``} },`:``}
42
+ ${typeof e.samplingRate==`number`?`sampling: { rate: ${e.samplingRate}${e.samplingConditions?`, conditions: ['${n(e.samplingConditions)}']`:``} },`:``}
43
+ ${r}
44
+ ${e.tags?.length?`tags: [${e.tags.map(e=>`'${n(e)}'`).join(`, `)}],`:``}
45
+ }`}).join(`,
46
+ `);return`import type { TelemetrySpec } from '@lssm/lib.contracts/telemetry';
47
+
48
+ export const ${i}: TelemetrySpec = {
49
+ meta: {
50
+ name: '${n(t.name)}',
51
+ version: ${t.version},
52
+ title: '${n(t.name)} telemetry',
53
+ description: '${n(t.description||`Describe the purpose of this telemetry spec.`)}',
54
+ domain: '${n(t.domain)}',
55
+ owners: [${t.owners.map(e=>`'${n(e)}'`).join(`, `)}],
56
+ tags: [${t.tags.map(e=>`'${n(e)}'`).join(`, `)}],
57
+ stability: '${t.stability}',
58
+ },
59
+ config: {
60
+ ${typeof t.defaultRetentionDays==`number`?`defaultRetentionDays: ${t.defaultRetentionDays},`:``}
61
+ ${typeof t.defaultSamplingRate==`number`?`defaultSamplingRate: ${t.defaultSamplingRate},`:``}
62
+ ${t.anomalyEnabled?`anomalyDetection: { enabled: true${typeof t.anomalyCheckIntervalMs==`number`?`, checkIntervalMs: ${t.anomalyCheckIntervalMs}`:``} },`:``}
63
+ ${a}
64
+ },
65
+ events: [
66
+ ${o}
67
+ ],
68
+ };
69
+ `}function n(e){return e.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`)}function r(e){let t=e.trim();return t?t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)?t:`'${n(t)}'`:`{}`}export{t as generateTelemetrySpec};
@@ -0,0 +1 @@
1
+ function e(e){let n=t(e);return n.charAt(0).toLowerCase()+n.slice(1)}function t(e){return e.split(/[-_.]/).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)}function n(e){return e.replace(/\./g,`-`).replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function r(e){return e.charAt(0).toUpperCase()+e.slice(1)}function i(e){return e.replace(/'/g,`\\'`)}export{r as capitalize,i as escapeString,e as toCamelCase,n as toKebabCase,t as toPascalCase};
@@ -0,0 +1,42 @@
1
+ function e({exportName:e,specImportPath:t,runnerName:n,workflowName:r}){return`import {
2
+ InMemoryStateStore,
3
+ WorkflowRegistry,
4
+ WorkflowRunner,
5
+ } from '@lssm/lib.contracts/workflow';
6
+ import { ${e} } from '${t}';
7
+
8
+ /**
9
+ * Runner wiring for ${r}.
10
+ *
11
+ * TODO:
12
+ * - Replace the in-memory state store with a persistent adapter if needed.
13
+ * - Implement opExecutor to invoke the correct contract handlers.
14
+ * - Wire eventEmitter to telemetry sinks.
15
+ */
16
+ const registry = new WorkflowRegistry();
17
+ registry.register(${e});
18
+
19
+ const stateStore = new InMemoryStateStore();
20
+
21
+ export const ${n} = new WorkflowRunner({
22
+ registry,
23
+ stateStore,
24
+ opExecutor: async (operation, input, ctx) => {
25
+ // TODO: route to the appropriate contract handler
26
+ // Example: return contractRegistry.execute(operation.name, operation.version, input, ctx);
27
+ throw new Error(
28
+ \`opExecutor for \${operation.name}.v\${operation.version} is not implemented\`
29
+ );
30
+ },
31
+ // appConfigProvider: async (state) => {
32
+ // // TODO: return the ResolvedAppConfig for this workflow run (tenant/environment)
33
+ // return undefined;
34
+ // },
35
+ // enforceCapabilities: async (operation, context) => {
36
+ // // TODO: ensure required capabilities are satisfied using context.integrations/context.resolvedAppConfig
37
+ // },
38
+ eventEmitter: (_event, _payload) => {
39
+ // TODO: forward workflow events to telemetry or logging sinks
40
+ },
41
+ });
42
+ `}export{e as generateWorkflowRunnerTemplate};
@@ -0,0 +1,41 @@
1
+ import{escapeString as e,toPascalCase as t}from"./utils.js";function n(n){let i=t(n.name.split(`.`).pop()??`Workflow`)+`Workflow`,a=n.steps.map(e=>r(e)).join(`,
2
+ `),o=n.transitions.map(t=>` {
3
+ from: '${t.from}',
4
+ to: '${t.to}',
5
+ ${t.condition?` condition: '${e(t.condition)}',`:``}
6
+ }`).join(`,
7
+ `);return`import type { WorkflowSpec } from '@lssm/lib.contracts/workflow';
8
+
9
+ /**
10
+ * Workflow generated via contractspec CLI.
11
+ * TODO:
12
+ * - Review step definitions and descriptions.
13
+ * - Wire automation steps to actual operations.
14
+ * - Provide form renderers for human steps.
15
+ * - Add guards/conditions as needed.
16
+ */
17
+ export const ${i}: WorkflowSpec = {
18
+ meta: {
19
+ name: '${n.name}',
20
+ version: ${n.version},
21
+ title: '${e(n.title)}',
22
+ description: '${e(n.description)}',
23
+ domain: '${e(n.domain)}',
24
+ stability: '${n.stability}',
25
+ owners: [${n.owners.map(e=>`'${e}'`).join(`, `)}],
26
+ tags: [${n.tags.map(e=>`'${e}'`).join(`, `)}],
27
+ },
28
+ definition: {
29
+ ${n.entryStepId?` entryStepId: '${n.entryStepId}',\n`:``} steps: [
30
+ ${a}
31
+ ],
32
+ transitions: [
33
+ ${o}
34
+ ],
35
+ },
36
+ ${n.policyFlags.length>0?`policy: {
37
+ flags: [${n.policyFlags.map(e=>`'${e}'`).join(`, `)}],
38
+ },`:`// policy: { flags: [] },`}
39
+ };
40
+ `}function r(t){let n=[` {`,` id: '${t.id}',`,` type: '${t.type}',`,` label: '${e(t.label)}',`];t.description&&n.push(` description: '${e(t.description)}',`);let r=[];return t.operation&&r.push(`operation: { name: '${t.operation.name}', version: ${t.operation.version} }`),t.form&&r.push(`form: { key: '${t.form.key}', version: ${t.form.version} }`),r.length&&n.push(` action: { ${r.join(`, `)} },`),n.push(` }`),n.join(`
41
+ `)}export{n as generateWorkflowSpec};
@@ -0,0 +1 @@
1
+ const e={aiProvider:`claude`,agentMode:`simple`,outputDir:`./src`,conventions:{operations:`interactions/commands|queries`,events:`events`,presentations:`presentations`,forms:`forms`},defaultOwners:[],defaultTags:[]};export{e as DEFAULT_WORKSPACE_CONFIG};
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@lssm/module.contractspec-workspace",
3
+ "version": "0.0.0-canary-20251213172311",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
14
+ "build": "bun build:bundle && bun build:types",
15
+ "build:bundle": "tsdown",
16
+ "build:types": "tsc --noEmit",
17
+ "dev": "bun build:bundle --watch",
18
+ "clean": "rimraf dist .turbo",
19
+ "lint": "bun lint:fix",
20
+ "lint:fix": "eslint src --fix",
21
+ "lint:check": "eslint src",
22
+ "test": "bun run"
23
+ },
24
+ "dependencies": {
25
+ "@lssm/lib.contracts": "workspace:*",
26
+ "@lssm/lib.schema": "workspace:*",
27
+ "zod": "^4.1.13"
28
+ },
29
+ "devDependencies": {
30
+ "@lssm/tool.tsdown": "workspace:*",
31
+ "@lssm/tool.typescript": "workspace:*",
32
+ "tsdown": "^0.17.0",
33
+ "typescript": "^5.9.3"
34
+ },
35
+ "exports": {
36
+ ".": "./src/index.ts",
37
+ "./*": "./*"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public",
41
+ "exports": {
42
+ ".": "./dist/index.js",
43
+ "./*": "./*"
44
+ }
45
+ }
46
+ }