@lssm/bundle.contractspec-workspace 0.0.0-canary-20251216030333 → 0.0.0-canary-20251216033905

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.
@@ -1 +1 @@
1
- import{access as e,mkdir as t,readFile as n,rm as r,stat as i,writeFile as a}from"node:fs/promises";import{basename as o,dirname as s,isAbsolute as c,join as l,relative as u,resolve as d}from"node:path";import{glob as f}from"glob";const p=[`**/*.contracts.ts`,`**/*.event.ts`,`**/*.presentation.ts`,`**/*.feature.ts`,`**/*.capability.ts`,`**/*.workflow.ts`,`**/*.data-view.ts`,`**/*.form.ts`,`**/*.migration.ts`,`**/*.telemetry.ts`,`**/*.experiment.ts`,`**/*.app-config.ts`,`**/*.integration.ts`,`**/*.knowledge.ts`,`**/*.policy.ts`,`**/*.test-spec.ts`],m=[`node_modules/**`,`dist/**`,`.turbo/**`];function h(h){let g=h??process.cwd();return{async exists(t){try{return await e(_(t)),!0}catch{return!1}},async readFile(e){return n(_(e),`utf-8`)},async writeFile(e,n){let r=_(e);await t(s(r),{recursive:!0}),await a(r,n,`utf-8`)},async remove(e){await r(_(e),{recursive:!0,force:!0})},async stat(e){let t=await i(_(e));return{size:t.size,isFile:t.isFile(),isDirectory:t.isDirectory(),mtime:t.mtime}},async mkdir(e){await t(_(e),{recursive:!0})},async glob(e){let t=e.patterns??(e.pattern?[e.pattern]:p),n=e.ignore??m,r=[];for(let e of t){let t=await f(e,{cwd:g,ignore:n});r.push(...t)}return Array.from(new Set(r)).sort((e,t)=>e.localeCompare(t))},resolve(...e){let[t,...n]=e;return t?d(g,t,...n):g},dirname(e){return s(e)},basename(e){return o(e)},join(...e){return l(...e)},relative(e,t){return u(e,t)}};function _(e){return c(e)?e:d(g,e)}}export{h as createNodeFsAdapter};
1
+ import{access as e,mkdir as t,readFile as n,rm as r,stat as i,writeFile as a}from"node:fs/promises";import{basename as o,dirname as s,isAbsolute as c,join as l,relative as u,resolve as d}from"node:path";import{glob as f}from"glob";const p=[`**/*.contracts.ts`,`**/*.event.ts`,`**/*.presentation.ts`,`**/*.feature.ts`,`**/*.capability.ts`,`**/*.workflow.ts`,`**/*.data-view.ts`,`**/*.form.ts`,`**/*.migration.ts`,`**/*.telemetry.ts`,`**/*.experiment.ts`,`**/*.app-config.ts`,`**/*.integration.ts`,`**/*.knowledge.ts`,`**/*.policy.ts`,`**/*.test-spec.ts`],m=[`node_modules/**`,`dist/**`,`.turbo/**`];function h(h){let g=h??process.cwd();return{async exists(t){try{return await e(_(t)),!0}catch{return!1}},async readFile(e){return n(_(e),`utf-8`)},async writeFile(e,n){let r=_(e);await t(s(r),{recursive:!0}),await a(r,n,`utf-8`)},async remove(e){await r(_(e),{recursive:!0,force:!0})},async stat(e){let t=await i(_(e));return{size:t.size,isFile:t.isFile(),isDirectory:t.isDirectory(),mtime:t.mtime}},async mkdir(e){await t(_(e),{recursive:!0})},async glob(e){let t=e.patterns??(e.pattern?[e.pattern]:p),n=e.ignore??m,r=e.cwd??g,i=[];for(let e of t){let t=await f(e,{cwd:r,ignore:n});i.push(...t)}return Array.from(new Set(i)).sort((e,t)=>e.localeCompare(t))},resolve(...e){let[t,...n]=e;return t?d(g,t,...n):g},dirname(e){return s(e)},basename(e){return o(e)},join(...e){return l(...e)},relative(e,t){return u(e,t)}};function _(e){return c(e)?e:d(g,e)}}export{h as createNodeFsAdapter};
@@ -1 +1 @@
1
- async function e(e,a){let o=[];return o.push(await t(e,a)),o.push(await n(e,a)),o.push(await r(e,a)),o.push(await i(e,a)),o}async function t(e,t){let n=e.join(t.workspaceRoot,`package.json`);return await e.exists(n)?{category:`workspace`,name:`Valid Workspace`,status:`pass`,message:`package.json found`}:{category:`workspace`,name:`Valid Workspace`,status:`fail`,message:`No package.json found`,details:`This does not appear to be a Node.js/TypeScript project`}}async function n(e,t){for(let n of[`src/contracts`,`contracts`,`src/specs`,`specs`]){let r=e.join(t.workspaceRoot,n);if(await e.exists(r))return{category:`workspace`,name:`Contracts Directory`,status:`pass`,message:`Contracts directory found: ${n}`}}return{category:`workspace`,name:`Contracts Directory`,status:`warn`,message:`No contracts directory found`,details:`Create src/contracts/ to organize your specs`,fix:{description:`Create src/contracts/ directory`,apply:async()=>{try{let n=e.join(t.workspaceRoot,`src`,`contracts`);return await e.mkdir(n),{success:!0,message:`Created src/contracts/`}}catch(e){return{success:!1,message:`Failed: ${e instanceof Error?e.message:String(e)}`}}}}}}async function r(e,t){try{let n=await e.glob({patterns:[`**/*.contracts.ts`,`**/*.event.ts`,`**/*.presentation.ts`,`**/*.feature.ts`],ignore:[`node_modules/**`,`dist/**`]});return n.length>0?{category:`workspace`,name:`Contract Files`,status:`pass`,message:`Found ${n.length} contract file(s)`,details:t.verbose?n.slice(0,5).join(`, `):void 0}:{category:`workspace`,name:`Contract Files`,status:`warn`,message:`No contract files found`,details:`Create specs using "contractspec create" or VS Code command`}}catch{return{category:`workspace`,name:`Contract Files`,status:`skip`,message:`Could not search for contract files`}}}async function i(e,t){let n=e.join(t.workspaceRoot,`.contractsrc.json`);try{if(!await e.exists(n))return{category:`workspace`,name:`Output Directory`,status:`skip`,message:`No config file to check output directory`};let r=await e.readFile(n),i=JSON.parse(r).outputDir??`./src`,a=e.join(t.workspaceRoot,i);return await e.exists(a)?{category:`workspace`,name:`Output Directory`,status:`pass`,message:`Output directory exists: ${i}`}:{category:`workspace`,name:`Output Directory`,status:`warn`,message:`Output directory not found: ${i}`,fix:{description:`Create ${i} directory`,apply:async()=>{try{return await e.mkdir(a),{success:!0,message:`Created ${i}`}}catch(e){return{success:!1,message:`Failed: ${e instanceof Error?e.message:String(e)}`}}}}}}catch{return{category:`workspace`,name:`Output Directory`,status:`skip`,message:`Could not check output directory`}}}export{e as runWorkspaceChecks};
1
+ const e=[`src/contracts`,`contracts`,`src/specs`,`specs`];async function t(e,t){let o=[];return o.push(n(t)),o.push(await r(e,t)),o.push(await i(e,t)),o.push(await a(e,t)),o.push(await s(e,t)),o}function n(e){if(e.isMonorepo){let t=e.packageName?` in package "${e.packageName}"`:``,n=e.packageRoot===e.workspaceRoot?``:` (package root: ${e.packageRoot})`;return{category:`workspace`,name:`Monorepo Detection`,status:`pass`,message:`Monorepo detected${t}`,details:e.verbose?`Workspace root: ${e.workspaceRoot}${n}`:void 0}}return{category:`workspace`,name:`Monorepo Detection`,status:`pass`,message:`Single project (not a monorepo)`}}async function r(e,t){let n=t.isMonorepo?[t.packageRoot,t.workspaceRoot]:[t.workspaceRoot];for(let r of n){let n=e.join(r,`package.json`);if(await e.exists(n))return{category:`workspace`,name:`Valid Workspace`,status:`pass`,message:`package.json found`,details:t.verbose&&t.isMonorepo?`Found at: ${r}`:void 0}}return{category:`workspace`,name:`Valid Workspace`,status:`fail`,message:`No package.json found`,details:`This does not appear to be a Node.js/TypeScript project`}}async function i(t,n){let r=n.isMonorepo?[n.packageRoot,n.workspaceRoot]:[n.workspaceRoot],i=n.isMonorepo?n.packageRoot:n.workspaceRoot;for(let i of r)for(let r of e){let e=t.join(i,r);if(await t.exists(e)){let e=i===n.packageRoot?`package`:`workspace`;return{category:`workspace`,name:`Contracts Directory`,status:`pass`,message:`Contracts directory found: ${r}`,details:n.isMonorepo?`Found at ${e} level`:void 0}}}let a=(n.isMonorepo,`src/contracts`),o=n.isMonorepo?` in package "${n.packageName??n.packageRoot}"`:``;return{category:`workspace`,name:`Contracts Directory`,status:`warn`,message:`No contracts directory found`,details:`Create ${a}/${o} to organize your specs`,fix:{description:`Create ${a}/ directory${o}`,apply:async()=>{try{let e=t.join(i,`src`,`contracts`);return await t.mkdir(e),{success:!0,message:`Created ${a}/`}}catch(e){return{success:!1,message:`Failed: ${e instanceof Error?e.message:String(e)}`}}}}}}async function a(e,t){try{let n=[`**/*.contracts.ts`,`**/*.event.ts`,`**/*.presentation.ts`,`**/*.feature.ts`],r=t.isMonorepo?t.packageRoot:t.workspaceRoot,i=await e.glob({patterns:n,ignore:[`node_modules/**`,`dist/**`],cwd:r});if(i.length>0){let e=t.isMonorepo?` (in current package)`:``;return{category:`workspace`,name:`Contract Files`,status:`pass`,message:`Found ${i.length} contract file(s)${e}`,details:t.verbose?i.slice(0,5).join(`, `):void 0}}return{category:`workspace`,name:`Contract Files`,status:`warn`,message:t.isMonorepo?`No contract files found in package "${t.packageName??`current`}"`:`No contract files found`,details:`Create specs using "contractspec create" or VS Code command`}}catch{return{category:`workspace`,name:`Contract Files`,status:`skip`,message:`Could not search for contract files`}}}async function o(e,t){if(t.isMonorepo&&t.packageRoot!==t.workspaceRoot){let n=e.join(t.packageRoot,`.contractsrc.json`);if(await e.exists(n))return{path:n,root:t.packageRoot,level:`package`}}let n=e.join(t.workspaceRoot,`.contractsrc.json`);return await e.exists(n)?{path:n,root:t.workspaceRoot,level:`workspace`}:null}async function s(e,t){try{let n=await o(e,t);if(!n)return{category:`workspace`,name:`Output Directory`,status:`skip`,message:t.isMonorepo?`No config file found at package or workspace level`:`No config file to check output directory`};let r=await e.readFile(n.path),i=JSON.parse(r).outputDir??`./src`,a=e.join(n.root,i),s=t.isMonorepo?` (${n.level} level)`:``;return await e.exists(a)?{category:`workspace`,name:`Output Directory`,status:`pass`,message:`Output directory exists: ${i}${s}`,details:t.verbose?`Resolved to: ${a}`:void 0}:{category:`workspace`,name:`Output Directory`,status:`warn`,message:`Output directory not found: ${i}${s}`,details:t.verbose?`Expected at: ${a}`:void 0,fix:{description:`Create ${i} directory`,apply:async()=>{try{return await e.mkdir(a),{success:!0,message:`Created ${i}`}}catch(e){return{success:!1,message:`Failed: ${e instanceof Error?e.message:String(e)}`}}}}}}catch{return{category:`workspace`,name:`Output Directory`,status:`skip`,message:`Could not check output directory`}}}export{t as runWorkspaceChecks};
@@ -1,2 +1,2 @@
1
- import{ALL_CHECK_CATEGORIES as e,CHECK_CATEGORY_LABELS as t}from"./types.js";import{runCliChecks as n}from"./checks/cli.js";import{runConfigChecks as r}from"./checks/config.js";import{runMcpChecks as i}from"./checks/mcp.js";import{runDepsChecks as a}from"./checks/deps.js";import{runWorkspaceChecks as o}from"./checks/workspace.js";import{runAiChecks as s}from"./checks/ai.js";import"./checks/index.js";const c={confirm:async()=>!1,input:async()=>``};async function l(n,r,i=c){let{fs:a,logger:o}=n,s=r.categories??e,l={workspaceRoot:r.workspaceRoot,verbose:r.verbose??!1},d=[];for(let e of s){if(r.skipAi&&e===`ai`)continue;o.info(`Checking ${t[e]}...`);let n=await u(e,a,l,i);for(let e of n){if(e.fix&&(e.status===`fail`||e.status===`warn`)&&(r.autoFix||await i.confirm(`Fix "${e.name}"? ${e.fix.description}`))){o.info(`Applying fix: ${e.fix.description}`);let t=await e.fix.apply();t.success?(o.info(`✓ ${t.message}`),e.status=`pass`,e.message=`Fixed: ${t.message}`,e.fix=void 0):o.warn(`✗ ${t.message}`)}d.push(e)}}let f=d.filter(e=>e.status===`pass`).length,p=d.filter(e=>e.status===`warn`).length,m=d.filter(e=>e.status===`fail`).length;return{checks:d,passed:f,warnings:p,failures:m,skipped:d.filter(e=>e.status===`skip`).length,healthy:m===0}}async function u(e,t,c,l){switch(e){case`cli`:return n(t,c);case`config`:return r(t,c);case`mcp`:return i(t,c);case`deps`:return a(t,c);case`workspace`:return o(t,c);case`ai`:return s(t,c,l);default:return[]}}function d(e){let t=[];return t.push(``),t.push(`=== Health Check Summary ===`),t.push(``),e.healthy?t.push(`✓ All checks passed!`):t.push(`✗ Some issues found`),t.push(``),t.push(` Passed: ${e.passed}`),t.push(` Warnings: ${e.warnings}`),t.push(` Failures: ${e.failures}`),t.push(` Skipped: ${e.skipped}`),t.join(`
2
- `)}function f(e){let t=`${e.status===`pass`?`✓`:e.status===`warn`?`⚠`:e.status===`fail`?`✗`:`○`} ${e.name}: ${e.message}`;return e.details&&(t+=`\n ${e.details}`),e.fix&&(t+=`\n Fix available: ${e.fix.description}`),t}export{f as formatCheckResult,d as formatDoctorSummary,l as runDoctor};
1
+ import{findPackageRoot as e,findWorkspaceRoot as t,getPackageName as n,isMonorepo as r}from"../../adapters/workspace.js";import{ALL_CHECK_CATEGORIES as i,CHECK_CATEGORY_LABELS as a}from"./types.js";import{runCliChecks as o}from"./checks/cli.js";import{runConfigChecks as s}from"./checks/config.js";import{runMcpChecks as c}from"./checks/mcp.js";import{runDepsChecks as l}from"./checks/deps.js";import{runWorkspaceChecks as u}from"./checks/workspace.js";import{runAiChecks as d}from"./checks/ai.js";import"./checks/index.js";const f={confirm:async()=>!1,input:async()=>``};async function p(o,s,c=f){let{fs:l,logger:u}=o,d=s.categories??i,p=t(s.workspaceRoot),h=e(s.workspaceRoot),g=r(p),_=g?n(h):void 0,v={workspaceRoot:p,packageRoot:h,isMonorepo:g,packageName:_,verbose:s.verbose??!1};if(g){let e=_?` (package: ${_})`:``;u.info(`Detected monorepo${e}`)}let y=[];for(let e of d){if(s.skipAi&&e===`ai`)continue;u.info(`Checking ${a[e]}...`);let t=await m(e,l,v,c);for(let e of t){if(e.fix&&(e.status===`fail`||e.status===`warn`)&&(s.autoFix||await c.confirm(`Fix "${e.name}"? ${e.fix.description}`))){u.info(`Applying fix: ${e.fix.description}`);let t=await e.fix.apply();t.success?(u.info(`✓ ${t.message}`),e.status=`pass`,e.message=`Fixed: ${t.message}`,e.fix=void 0):u.warn(`✗ ${t.message}`)}y.push(e)}}let b=y.filter(e=>e.status===`pass`).length,x=y.filter(e=>e.status===`warn`).length,S=y.filter(e=>e.status===`fail`).length;return{checks:y,passed:b,warnings:x,failures:S,skipped:y.filter(e=>e.status===`skip`).length,healthy:S===0}}async function m(e,t,n,r){switch(e){case`cli`:return o(t,n);case`config`:return s(t,n);case`mcp`:return c(t,n);case`deps`:return l(t,n);case`workspace`:return u(t,n);case`ai`:return d(t,n,r);default:return[]}}function h(e){let t=[];return t.push(``),t.push(`=== Health Check Summary ===`),t.push(``),e.healthy?t.push(`✓ All checks passed!`):t.push(`✗ Some issues found`),t.push(``),t.push(` Passed: ${e.passed}`),t.push(` Warnings: ${e.warnings}`),t.push(` Failures: ${e.failures}`),t.push(` Skipped: ${e.skipped}`),t.join(`
2
+ `)}function g(e){let t=`${e.status===`pass`?`✓`:e.status===`warn`?`⚠`:e.status===`fail`?`✗`:`○`} ${e.name}: ${e.message}`;return e.details&&(t+=`\n ${e.details}`),e.fix&&(t+=`\n Fix available: ${e.fix.description}`),t}export{g as formatCheckResult,h as formatDoctorSummary,p as runDoctor};
@@ -1 +1 @@
1
- import{detectPackageManager as e,findPackageRoot as t,findWorkspaceRoot as n,getWorkspaceInfo as r}from"../adapters/workspace.js";import{validateSpec as i,validateSpecs as a}from"./validate.js";import{validateImplementationFiles as o}from"./validate-implementation.js";import{compareSpecs as s}from"./diff.js";import{analyzeDeps as c,exportGraphAsDot as l,getContractNode as u,getGraphStats as d}from"./deps.js";import{groupSpecsByType as f,listSpecs as p}from"./list.js";import{getApiKey as m,loadWorkspaceConfig as h,mergeWorkspaceConfig as g}from"./config.js";import{buildSpec as _}from"./build.js";import{exportOpenApi as v}from"./openapi.js";import{RegistryClient as y,addToRegistry as b,listFromRegistry as x,resolveRegistryUrl as S,searchRegistry as C}from"./registry.js";import{syncSpecs as w}from"./sync.js";import{watchSpecs as T}from"./watch.js";import{cleanArtifacts as E}from"./clean.js";import{runTests as D}from"./test.js";import{createRegeneratorService as O}from"./regenerator.js";import{findAllConfigFiles as k,formatWorkspaceInfo as A,getExtendedWorkspaceInfo as j,mergeMonorepoConfigs as M}from"./workspace-info.js";import{analyzeIntegrity as N,filterIssuesBySeverity as P,filterIssuesByType as F,getAllSpecs as I}from"./integrity.js";import{generateMermaidDiagram as L}from"./integrity-diagram.js";import{ALL_SETUP_TARGETS as R,SETUP_TARGET_LABELS as z}from"./setup/types.js";import{generateAgentsMd as B,generateClaudeMcpConfig as V,generateContractsrcConfig as H,generateCursorMcpConfig as U,generateCursorRules as W,generateVscodeSettings as G,getClaudeDesktopConfigPath as K}from"./setup/config-generators.js";import{deepMergeOverwrite as q,deepMergePreserve as J,formatJson as Y,safeParseJson as X}from"./setup/file-merger.js";import{runSetup as Z}from"./setup/setup-service.js";import{ALL_CHECK_CATEGORIES as Q,CHECK_CATEGORY_LABELS as $}from"./doctor/types.js";import{formatCheckResult as ee,formatDoctorSummary as te,runDoctor as ne}from"./doctor/doctor-service.js";import"./doctor/index.js";
1
+ import{detectPackageManager as e,findPackageRoot as t,findWorkspaceRoot as n,getWorkspaceInfo as r}from"../adapters/workspace.js";import{validateSpec as i,validateSpecs as a}from"./validate.js";import{validateImplementationFiles as o}from"./validate-implementation.js";import{compareSpecs as s}from"./diff.js";import{analyzeDeps as c,exportGraphAsDot as l,getContractNode as u,getGraphStats as d}from"./deps.js";import{groupSpecsByType as f,listSpecs as p}from"./list.js";import{getApiKey as m,loadWorkspaceConfig as h,mergeWorkspaceConfig as g}from"./config.js";import{buildSpec as _}from"./build.js";import{exportOpenApi as v}from"./openapi.js";import{RegistryClient as y,addToRegistry as b,listFromRegistry as x,resolveRegistryUrl as S,searchRegistry as C}from"./registry.js";import{syncSpecs as w}from"./sync.js";import{watchSpecs as T}from"./watch.js";import{cleanArtifacts as E}from"./clean.js";import{runTests as D}from"./test.js";import{createRegeneratorService as O}from"./regenerator.js";import{findAllConfigFiles as k,formatWorkspaceInfo as A,getExtendedWorkspaceInfo as j,mergeMonorepoConfigs as M}from"./workspace-info.js";import{analyzeIntegrity as N,filterIssuesBySeverity as P,filterIssuesByType as F,getAllSpecs as I}from"./integrity.js";import{generateMermaidDiagram as L}from"./integrity-diagram.js";import{ALL_SETUP_TARGETS as R,SETUP_TARGET_LABELS as z}from"./setup/types.js";import{generateAgentsMd as B,generateClaudeMcpConfig as V,generateContractsrcConfig as H,generateCursorMcpConfig as U,generateCursorRules as W,generateVscodeSettings as G,getClaudeDesktopConfigPath as K}from"./setup/config-generators.js";import{deepMergeOverwrite as q,deepMergePreserve as J,formatJson as Y,safeParseJson as X}from"./setup/file-merger.js";import{runSetup as Z}from"./setup/setup-service.js";import"./setup/index.js";import{ALL_CHECK_CATEGORIES as Q,CHECK_CATEGORY_LABELS as $}from"./doctor/types.js";import{formatCheckResult as ee,formatDoctorSummary as te,runDoctor as ne}from"./doctor/doctor-service.js";import"./doctor/index.js";
@@ -1,4 +1,4 @@
1
- function e(e){return{$schema:`https://contractspec.dev/schemas/contractsrc.json`,aiProvider:`claude`,aiModel:`claude-sonnet-4-20250514`,agentMode:`claude-code`,outputDir:`./src`,conventions:{operations:`contracts/operations`,events:`contracts/events`,presentations:`contracts/presentations`,forms:`contracts/forms`,features:`contracts/features`},defaultOwners:e.defaultOwners??[`@team`],defaultTags:[]}}function t(){return{"contractspec.validation.enabled":!0,"contractspec.validation.validateOnSave":!0,"contractspec.validation.validateOnOpen":!0,"contractspec.codeLens.enabled":!0,"contractspec.diagnostics.showWarnings":!0,"contractspec.diagnostics.showHints":!0,"contractspec.integrity.enabled":!0,"contractspec.integrity.checkOnSave":!0}}function n(){return{mcpServers:{"contractspec-local":{command:`bunx`,args:[`contractspec-mcp`]}}}}function r(){return{mcpServers:{"contractspec-local":{command:`bunx`,args:[`contractspec-mcp`]}}}}function i(e){return`# ContractSpec Development Rules
1
+ function e(e){let t=e.isMonorepo&&e.scope===`package`;return{$schema:`https://contractspec.dev/schemas/contractsrc.json`,aiProvider:`claude`,aiModel:`claude-sonnet-4-20250514`,agentMode:`claude-code`,outputDir:`./src`,conventions:{operations:`contracts/operations`,events:`contracts/events`,presentations:`contracts/presentations`,forms:`contracts/forms`,features:`contracts/features`},defaultOwners:e.defaultOwners??[`@team`],defaultTags:[],...t&&e.packageName?{package:e.packageName}:{}}}function t(){return{"contractspec.validation.enabled":!0,"contractspec.validation.validateOnSave":!0,"contractspec.validation.validateOnOpen":!0,"contractspec.codeLens.enabled":!0,"contractspec.diagnostics.showWarnings":!0,"contractspec.diagnostics.showHints":!0,"contractspec.integrity.enabled":!0,"contractspec.integrity.checkOnSave":!0}}function n(){return{mcpServers:{"contractspec-local":{command:`bunx`,args:[`contractspec-mcp`]}}}}function r(){return{mcpServers:{"contractspec-local":{command:`bunx`,args:[`contractspec-mcp`]}}}}function i(e){let t=e.projectName??`this project`,n=e.isMonorepo&&e.scope===`package`&&e.packageRoot?`${e.packageRoot.split(`/`).slice(-2).join(`/`)}/src/contracts`:`src/contracts`;return`# ContractSpec Development Rules
2
2
 
3
3
  This project uses ContractSpec for spec-first development. Follow these guidelines when working with AI agents.
4
4
 
@@ -7,14 +7,22 @@ This project uses ContractSpec for spec-first development. Follow these guidelin
7
7
  - **Always update contracts first** before changing implementation code.
8
8
  - Contracts are the source of truth for operations, events, and presentations.
9
9
  - Implementation code should be generated or derived from contracts.
10
+ ${e.isMonorepo?`
11
+ ## Monorepo Structure
10
12
 
13
+ This is a monorepo. Contracts may exist at:
14
+ - Package level: \`packages/*/src/contracts/\`
15
+ - Workspace level: \`src/contracts/\`
16
+
17
+ Check the appropriate level based on the feature scope.
18
+ `:``}
11
19
  ## Contract Locations
12
20
 
13
21
  Contracts are located in:
14
- - \`src/contracts/operations/\` - Command and query specs
15
- - \`src/contracts/events/\` - Event specs
16
- - \`src/contracts/presentations/\` - UI presentation specs
17
- - \`src/contracts/features/\` - Feature module specs
22
+ - \`${n}/operations/\` - Command and query specs
23
+ - \`${n}/events/\` - Event specs
24
+ - \`${n}/presentations/\` - UI presentation specs
25
+ - \`${n}/features/\` - Feature module specs
18
26
 
19
27
  ## When Making Changes
20
28
 
@@ -42,17 +50,17 @@ defineCommand({
42
50
  });
43
51
  \`\`\`
44
52
 
45
- ## Rules for ${e.projectName??`this project`}
53
+ ## Rules for ${t}
46
54
 
47
55
  - All API endpoints must have a corresponding operation contract.
48
56
  - Events must be declared in contracts before being emitted.
49
57
  - UI components should reference presentation contracts.
50
58
  - Feature flags should be defined in feature modules.
51
- `}function a(e){return`# AI Agent Guide
59
+ `}function a(e){let t=e.projectName??`This Project`,n=e.isMonorepo&&e.scope===`package`,r=`src/contracts/`;return`# AI Agent Guide
52
60
 
53
61
  This repository uses **ContractSpec** for spec-first development. AI agents should follow these guidelines.
54
62
 
55
- ## Project: ${e.projectName??`This Project`}
63
+ ## Project: ${t}
56
64
 
57
65
  ## ContractSpec Overview
58
66
 
@@ -63,12 +71,29 @@ ContractSpec is a deterministic, spec-first compiler that keeps AI-written softw
63
71
  1. **Contracts are the source of truth** - Always check/update contracts before modifying implementation.
64
72
  2. **Safe regeneration** - Code can be regenerated from specs without breaking invariants.
65
73
  3. **Multi-surface consistency** - API, events, and UI stay in sync via shared contracts.
74
+ ${e.isMonorepo?`
75
+ ## Monorepo Structure
76
+
77
+ This is a monorepo. Contracts can exist at multiple levels:
78
+
79
+ | Level | Location | Use Case |
80
+ |-------|----------|----------|
81
+ | Package | \`packages/*/src/contracts/\` | Package-specific contracts |
82
+ | Workspace | \`src/contracts/\` | Shared cross-package contracts |
83
+
84
+ When adding a contract, consider:
85
+ - Is this specific to one package? → Add at package level
86
+ - Is this shared across packages? → Add at workspace level
87
+
88
+ ### Current Scope
66
89
 
90
+ ${n?`You are working at the **package level**: \`${e.packageName??e.packageRoot}\``:`You are working at the **workspace level**.`}
91
+ `:``}
67
92
  ## Working in This Repository
68
93
 
69
94
  ### Before Making Changes
70
95
 
71
- 1. Check for existing contracts in \`src/contracts/\`
96
+ 1. Check for existing contracts in \`${r}\`
72
97
  2. If a contract exists, update it first
73
98
  3. Regenerate implementation with \`contractspec build\`
74
99
  4. Validate with \`contractspec validate\`
@@ -84,10 +109,10 @@ ContractSpec is a deterministic, spec-first compiler that keeps AI-written softw
84
109
 
85
110
  | Type | Location |
86
111
  |------|----------|
87
- | Operations | \`src/contracts/operations/\` |
88
- | Events | \`src/contracts/events/\` |
89
- | Presentations | \`src/contracts/presentations/\` |
90
- | Features | \`src/contracts/features/\` |
112
+ | Operations | \`${r}operations/\` |
113
+ | Events | \`${r}events/\` |
114
+ | Presentations | \`${r}presentations/\` |
115
+ | Features | \`${r}features/\` |
91
116
 
92
117
  ## MCP Tools Available
93
118
 
@@ -0,0 +1 @@
1
+ import{ALL_SETUP_TARGETS as e,SETUP_TARGET_LABELS as t}from"./types.js";import{generateAgentsMd as n,generateClaudeMcpConfig as r,generateContractsrcConfig as i,generateCursorMcpConfig as a,generateCursorRules as o,generateVscodeSettings as s,getClaudeDesktopConfigPath as c}from"./config-generators.js";import{deepMergeOverwrite as l,deepMergePreserve as u,formatJson as d,safeParseJson as f}from"./file-merger.js";import{runSetup as p}from"./setup-service.js";
@@ -1 +1 @@
1
- import{ALL_SETUP_TARGETS as e,SETUP_TARGET_LABELS as t}from"./types.js";import{setupCliConfig as n}from"./targets/cli-config.js";import{setupVscodeSettings as r}from"./targets/vscode-settings.js";import{setupMcpCursor as i}from"./targets/mcp-cursor.js";import{setupMcpClaude as a}from"./targets/mcp-claude.js";import{setupCursorRules as o}from"./targets/cursor-rules.js";import{setupAgentsMd as s}from"./targets/agents-md.js";const c={confirm:async()=>!0,multiSelect:async(e,t)=>t.filter(e=>e.selected!==!1).map(e=>e.value),input:async(e,t)=>t??``};async function l(n,r,i=c){let a=[],o=r.targets.length>0?r.targets:e,s=o;r.interactive&&(s=await i.multiSelect(`Select components to configure:`,e.map(e=>({value:e,label:t[e],selected:o.includes(e)}))));let l=r.projectName;if(r.interactive&&!l){let e=r.workspaceRoot.split(`/`).pop()??`my-project`;l=await i.input(`Project name:`,e)}let d={...r,projectName:l,targets:s};for(let e of s){let t=await u(n,e,d,i);a.push(t)}let f=a.filter(e=>e.action!==`error`).length,p=a.filter(e=>e.action===`error`).length;return{success:p===0,files:a,summary:`Setup complete: ${f} configured, ${p} failed.`}}async function u(e,t,c,l){switch(t){case`cli-config`:return n(e,c,l);case`vscode-settings`:return r(e,c,l);case`mcp-cursor`:return i(e,c,l);case`mcp-claude`:return a(e,c,l);case`cursor-rules`:return o(e,c,l);case`agents-md`:return s(e,c,l);default:return{target:t,filePath:``,action:`error`,message:`Unknown target: ${t}`}}}export{l as runSetup};
1
+ import{findPackageRoot as e,findWorkspaceRoot as t,getPackageName as n,isMonorepo as r}from"../../adapters/workspace.js";import{ALL_SETUP_TARGETS as i,SETUP_TARGET_LABELS as a}from"./types.js";import{setupCliConfig as o}from"./targets/cli-config.js";import{setupVscodeSettings as s}from"./targets/vscode-settings.js";import{setupMcpCursor as c}from"./targets/mcp-cursor.js";import{setupMcpClaude as l}from"./targets/mcp-claude.js";import{setupCursorRules as u}from"./targets/cursor-rules.js";import{setupAgentsMd as d}from"./targets/agents-md.js";const f={confirm:async()=>!0,multiSelect:async(e,t)=>t.filter(e=>e.selected!==!1).map(e=>e.value),input:async(e,t)=>t??``};async function p(o,s,c=f){let l=[],u=s.targets.length>0?s.targets:i,d=s.workspaceRoot,p=t(d),h=s.packageRoot??e(d),g=s.isMonorepo??r(p),_=s.packageName??(g?n(h):void 0),v=s.scope??`workspace`,y=h!==p;g&&s.interactive&&y&&(v=(await c.multiSelect(`Monorepo detected. Configure at which level?`,[{value:`package`,label:`Package level (${_??h})`,selected:!0},{value:`workspace`,label:`Workspace level (${p})`}]))[0]??`package`);let b=u;s.interactive&&(b=await c.multiSelect(`Select components to configure:`,i.map(e=>({value:e,label:a[e],selected:u.includes(e)}))));let x=s.projectName;if(s.interactive&&!x){let e=v===`package`&&_?_:d.split(`/`).pop()??`my-project`;x=await c.input(`Project name:`,e)}let S={...s,workspaceRoot:p,packageRoot:h,isMonorepo:g,scope:v,packageName:_,projectName:x,targets:b};for(let e of b){let t=await m(o,e,S,c);l.push(t)}let C=l.filter(e=>e.action!==`error`).length,w=l.filter(e=>e.action===`error`).length,T=g?` (${v} level)`:``;return{success:w===0,files:l,summary:`Setup complete${T}: ${C} configured, ${w} failed.`}}async function m(e,t,n,r){switch(t){case`cli-config`:return o(e,n,r);case`vscode-settings`:return s(e,n,r);case`mcp-cursor`:return c(e,n,r);case`mcp-claude`:return l(e,n,r);case`cursor-rules`:return u(e,n,r);case`agents-md`:return d(e,n,r);default:return{target:t,filePath:``,action:`error`,message:`Unknown target: ${t}`}}}export{p as runSetup};
@@ -1 +1 @@
1
- import{generateAgentsMd as e}from"../config-generators.js";async function t(t,n,r){let i=t.join(n.workspaceRoot,`AGENTS.md`);try{let a=await t.exists(i),o=e(n);if(a)if(n.interactive){if(!await r.confirm(`${i} exists. Overwrite?`))return{target:`agents-md`,filePath:i,action:`skipped`,message:`User kept existing AGENTS.md`}}else return{target:`agents-md`,filePath:i,action:`skipped`,message:`File already exists`};return await t.writeFile(i,o),{target:`agents-md`,filePath:i,action:a?`merged`:`created`,message:a?`Updated AGENTS.md`:`Created AGENTS.md`}}catch(e){return{target:`agents-md`,filePath:i,action:`error`,message:e instanceof Error?e.message:`Unknown error`}}}export{t as setupAgentsMd};
1
+ import{generateAgentsMd as e}from"../config-generators.js";async function t(t,n,r){let i=n.isMonorepo&&n.scope===`package`?n.packageRoot??n.workspaceRoot:n.workspaceRoot,a=t.join(i,`AGENTS.md`);try{let i=await t.exists(a),o=e(n);if(i)if(n.interactive){if(!await r.confirm(`${a} exists. Overwrite?`))return{target:`agents-md`,filePath:a,action:`skipped`,message:`User kept existing AGENTS.md`}}else return{target:`agents-md`,filePath:a,action:`skipped`,message:`File already exists`};return await t.writeFile(a,o),{target:`agents-md`,filePath:a,action:i?`merged`:`created`,message:i?`Updated AGENTS.md`:`Created AGENTS.md`}}catch(e){return{target:`agents-md`,filePath:a,action:`error`,message:e instanceof Error?e.message:`Unknown error`}}}export{t as setupAgentsMd};
@@ -1 +1 @@
1
- import{generateContractsrcConfig as e}from"../config-generators.js";import{deepMergePreserve as t,formatJson as n,safeParseJson as r}from"../file-merger.js";async function i(i,a,o){let s=i.join(a.workspaceRoot,`.contractsrc.json`);try{let c=await i.exists(s),l=e(a);if(c){let e=r(await i.readFile(s));if(!e)return{target:`cli-config`,filePath:s,action:`error`,message:`Existing file is not valid JSON`};if(a.interactive&&!await o.confirm(`${s} exists. Merge ContractSpec defaults?`))return{target:`cli-config`,filePath:s,action:`skipped`,message:`User skipped merge`};let c=t(e,l);return await i.writeFile(s,n(c)),{target:`cli-config`,filePath:s,action:`merged`,message:`Merged with existing configuration`}}return await i.writeFile(s,n(l)),{target:`cli-config`,filePath:s,action:`created`,message:`Created CLI configuration`}}catch(e){return{target:`cli-config`,filePath:s,action:`error`,message:e instanceof Error?e.message:`Unknown error`}}}export{i as setupCliConfig};
1
+ import{generateContractsrcConfig as e}from"../config-generators.js";import{deepMergePreserve as t,formatJson as n,safeParseJson as r}from"../file-merger.js";async function i(i,a,o){let s=a.isMonorepo&&a.scope===`package`?a.packageRoot??a.workspaceRoot:a.workspaceRoot,c=i.join(s,`.contractsrc.json`);try{let s=await i.exists(c),l=e(a);if(s){let e=r(await i.readFile(c));if(!e)return{target:`cli-config`,filePath:c,action:`error`,message:`Existing file is not valid JSON`};if(a.interactive&&!await o.confirm(`${c} exists. Merge ContractSpec defaults?`))return{target:`cli-config`,filePath:c,action:`skipped`,message:`User skipped merge`};let s=t(e,l);return await i.writeFile(c,n(s)),{target:`cli-config`,filePath:c,action:`merged`,message:`Merged with existing configuration`}}return await i.writeFile(c,n(l)),{target:`cli-config`,filePath:c,action:`created`,message:`Created CLI configuration`}}catch(e){return{target:`cli-config`,filePath:c,action:`error`,message:e instanceof Error?e.message:`Unknown error`}}}export{i as setupCliConfig};
@@ -1 +1 @@
1
- import{generateVscodeSettings as e}from"../config-generators.js";import{deepMergePreserve as t,formatJson as n,safeParseJson as r}from"../file-merger.js";async function i(i,a,o){let s=i.join(a.workspaceRoot,`.vscode`),c=i.join(s,`settings.json`);try{await i.exists(s)||await i.mkdir(s);let l=await i.exists(c),u=e();if(l){let e=r(await i.readFile(c));if(!e)return{target:`vscode-settings`,filePath:c,action:`error`,message:`Existing file is not valid JSON`};if(a.interactive&&!await o.confirm(`${c} exists. Add ContractSpec settings?`))return{target:`vscode-settings`,filePath:c,action:`skipped`,message:`User skipped merge`};let s=t(e,u);return await i.writeFile(c,n(s)),{target:`vscode-settings`,filePath:c,action:`merged`,message:`Added ContractSpec settings`}}return await i.writeFile(c,n(u)),{target:`vscode-settings`,filePath:c,action:`created`,message:`Created VS Code settings`}}catch(e){return{target:`vscode-settings`,filePath:c,action:`error`,message:e instanceof Error?e.message:`Unknown error`}}}export{i as setupVscodeSettings};
1
+ import{generateVscodeSettings as e}from"../config-generators.js";import{deepMergePreserve as t,formatJson as n,safeParseJson as r}from"../file-merger.js";async function i(i,a,o){let s=a.isMonorepo&&a.scope===`package`?a.packageRoot??a.workspaceRoot:a.workspaceRoot,c=i.join(s,`.vscode`),l=i.join(c,`settings.json`);try{await i.exists(c)||await i.mkdir(c);let s=await i.exists(l),u=e();if(s){let e=r(await i.readFile(l));if(!e)return{target:`vscode-settings`,filePath:l,action:`error`,message:`Existing file is not valid JSON`};if(a.interactive&&!await o.confirm(`${l} exists. Add ContractSpec settings?`))return{target:`vscode-settings`,filePath:l,action:`skipped`,message:`User skipped merge`};let s=t(e,u);return await i.writeFile(l,n(s)),{target:`vscode-settings`,filePath:l,action:`merged`,message:`Added ContractSpec settings`}}return await i.writeFile(l,n(u)),{target:`vscode-settings`,filePath:l,action:`created`,message:`Created VS Code settings`}}catch(e){return{target:`vscode-settings`,filePath:l,action:`error`,message:e instanceof Error?e.message:`Unknown error`}}}export{i as setupVscodeSettings};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/bundle.contractspec-workspace",
3
- "version": "0.0.0-canary-20251216030333",
3
+ "version": "0.0.0-canary-20251216033905",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",