@contractspec/bundle.workspace 1.45.4 → 1.45.6

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 (66) hide show
  1. package/dist/adapters/fs.d.ts +2 -1
  2. package/dist/adapters/fs.d.ts.map +1 -1
  3. package/dist/adapters/fs.js +1 -1
  4. package/dist/adapters/fs.js.map +1 -1
  5. package/dist/adapters/git.js +29 -0
  6. package/dist/adapters/git.js.map +1 -1
  7. package/dist/adapters/index.d.ts +1 -1
  8. package/dist/adapters/index.js +1 -1
  9. package/dist/index.d.ts +12 -7
  10. package/dist/index.js +5 -2
  11. package/dist/ports/git.d.ts +14 -1
  12. package/dist/ports/git.d.ts.map +1 -1
  13. package/dist/ports/index.d.ts +3 -2
  14. package/dist/ports/rulesync.d.ts +38 -0
  15. package/dist/ports/rulesync.d.ts.map +1 -0
  16. package/dist/services/doctor/checks/cli.js +9 -0
  17. package/dist/services/doctor/checks/cli.js.map +1 -1
  18. package/dist/services/doctor/checks/config.js +132 -0
  19. package/dist/services/doctor/checks/config.js.map +1 -1
  20. package/dist/services/doctor/checks/deps.js +13 -0
  21. package/dist/services/doctor/checks/deps.js.map +1 -1
  22. package/dist/services/doctor/checks/workspace.js +20 -1
  23. package/dist/services/doctor/checks/workspace.js.map +1 -1
  24. package/dist/services/hooks/hooks-service.d.ts +24 -0
  25. package/dist/services/hooks/hooks-service.d.ts.map +1 -0
  26. package/dist/services/hooks/hooks-service.js +126 -0
  27. package/dist/services/hooks/hooks-service.js.map +1 -0
  28. package/dist/services/hooks/index.d.ts +10 -0
  29. package/dist/services/hooks/index.d.ts.map +1 -0
  30. package/dist/services/hooks/index.js +12 -0
  31. package/dist/services/hooks/index.js.map +1 -0
  32. package/dist/services/hooks/types.d.ts +56 -0
  33. package/dist/services/hooks/types.d.ts.map +1 -0
  34. package/dist/services/index.d.ts +5 -1
  35. package/dist/services/index.js +3 -0
  36. package/dist/services/rulesync.d.ts +17 -0
  37. package/dist/services/rulesync.d.ts.map +1 -0
  38. package/dist/services/rulesync.js +71 -0
  39. package/dist/services/rulesync.js.map +1 -0
  40. package/dist/services/setup/config-generators.d.ts.map +1 -1
  41. package/dist/services/setup/config-generators.js +14 -0
  42. package/dist/services/setup/config-generators.js.map +1 -1
  43. package/dist/services/upgrade/index.d.ts +10 -0
  44. package/dist/services/upgrade/index.d.ts.map +1 -0
  45. package/dist/services/upgrade/index.js +15 -0
  46. package/dist/services/upgrade/index.js.map +1 -0
  47. package/dist/services/upgrade/types.d.ts +78 -0
  48. package/dist/services/upgrade/types.d.ts.map +1 -0
  49. package/dist/services/upgrade/upgrade-service.d.ts +38 -0
  50. package/dist/services/upgrade/upgrade-service.d.ts.map +1 -0
  51. package/dist/services/upgrade/upgrade-service.js +201 -0
  52. package/dist/services/upgrade/upgrade-service.js.map +1 -0
  53. package/dist/services/versioning/conventional-commits.d.ts +95 -0
  54. package/dist/services/versioning/conventional-commits.d.ts.map +1 -0
  55. package/dist/services/versioning/conventional-commits.js +184 -0
  56. package/dist/services/versioning/conventional-commits.js.map +1 -0
  57. package/dist/services/versioning/index.d.ts +4 -3
  58. package/dist/services/versioning/index.js +13 -2
  59. package/dist/services/versioning/index.js.map +1 -1
  60. package/dist/services/versioning/types.d.ts +9 -7
  61. package/dist/services/versioning/types.d.ts.map +1 -1
  62. package/dist/services/versioning/versioning-service.d.ts +43 -1
  63. package/dist/services/versioning/versioning-service.d.ts.map +1 -1
  64. package/dist/services/versioning/versioning-service.js +144 -2
  65. package/dist/services/versioning/versioning-service.js.map +1 -1
  66. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"config-generators.js","names":[],"sources":["../../../src/services/setup/config-generators.ts"],"sourcesContent":["/**\n * Config generators for setup targets.\n *\n * Each generator returns the default configuration for a target.\n */\n\nimport type { SetupOptions } from './types';\n\n/**\n * Generate .contractsrc.json content.\n *\n * Adapts defaults based on monorepo scope.\n */\nexport function generateContractsrcConfig(options: SetupOptions): object {\n // For package-level config in monorepo, use simpler relative paths\n const isPackageLevel = options.isMonorepo && options.scope === 'package';\n\n return {\n $schema: 'https://api.contractspec.io/schemas/contractsrc.json',\n aiProvider: 'claude',\n aiModel: 'claude-sonnet-4-20250514',\n agentMode: 'claude-code',\n // outputDir is relative to the config file location\n outputDir: './src',\n conventions: {\n operations: 'contracts/operations',\n events: 'contracts/events',\n presentations: 'contracts/presentations',\n forms: 'contracts/forms',\n features: 'contracts/features',\n },\n defaultOwners: options.defaultOwners ?? ['@team'],\n defaultTags: [],\n // Add monorepo hint if at package level\n ...(isPackageLevel && options.packageName\n ? { package: options.packageName }\n : {}),\n };\n}\n\n/**\n * Generate .vscode/settings.json ContractSpec settings.\n */\nexport function generateVscodeSettings(): object {\n return {\n 'contractspec.validation.enabled': true,\n 'contractspec.validation.validateOnSave': true,\n 'contractspec.validation.validateOnOpen': true,\n 'contractspec.codeLens.enabled': true,\n 'contractspec.diagnostics.showWarnings': true,\n 'contractspec.diagnostics.showHints': true,\n 'contractspec.integrity.enabled': true,\n 'contractspec.integrity.checkOnSave': true,\n };\n}\n\n/**\n * Generate .cursor/mcp.json content.\n */\nexport function generateCursorMcpConfig(): object {\n return {\n mcpServers: {\n 'contractspec-local': {\n command: 'bunx',\n args: ['contractspec-mcp'],\n },\n },\n };\n}\n\n/**\n * Generate Claude Desktop MCP config.\n * Returns the mcpServers section to merge into claude_desktop_config.json.\n */\nexport function generateClaudeMcpConfig(): object {\n return {\n mcpServers: {\n 'contractspec-local': {\n command: 'bunx',\n args: ['contractspec-mcp'],\n },\n },\n };\n}\n\n/**\n * Generate .cursor/rules/contractspec.mdc content.\n *\n * Adapts paths based on monorepo scope.\n */\nexport function generateCursorRules(options: SetupOptions): string {\n const projectName = options.projectName ?? 'this project';\n const isPackageLevel = options.isMonorepo && options.scope === 'package';\n\n // Base contract path depends on scope\n const basePath =\n isPackageLevel && options.packageRoot\n ? `${options.packageRoot.split('/').slice(-2).join('/')}/src/contracts`\n : 'src/contracts';\n\n const monorepoNote = options.isMonorepo\n ? `\\n## Monorepo Structure\\n\\nThis is a monorepo. Contracts may exist at:\\n- Package level: \\`packages/*/src/contracts/\\`\\n- Workspace level: \\`src/contracts/\\`\\n\\nCheck the appropriate level based on the feature scope.\\n`\n : '';\n\n return `# ContractSpec Development Rules\n\nThis project uses ContractSpec for spec-first development. Follow these guidelines when working with AI agents.\n\n## Spec-First Principle\n\n- **Always update contracts first** before changing implementation code.\n- Contracts are the source of truth for operations, events, and presentations.\n- Implementation code should be generated or derived from contracts.\n${monorepoNote}\n## Contract Locations\n\nContracts are located in:\n- \\`${basePath}/operations/\\` - Command and query specs\n- \\`${basePath}/events/\\` - Event specs\n- \\`${basePath}/presentations/\\` - UI presentation specs\n- \\`${basePath}/features/\\` - Feature module specs\n\n## When Making Changes\n\n1. **Before coding**: Check if a contract exists for the feature.\n2. **If contract exists**: Update the contract first, then regenerate code.\n3. **If no contract**: Create a new contract using \\`contractspec create\\`.\n4. **After changes**: Validate with \\`contractspec validate\\`.\n\n## Key Commands\n\n- \\`contractspec create\\` - Scaffold new specs\n- \\`contractspec validate\\` - Validate specs\n- \\`contractspec build\\` - Generate implementation code\n- \\`contractspec integrity\\` - Check contract health\n\n## Contract Structure\n\nOperations follow this pattern:\n\\`\\`\\`typescript\ndefineCommand({\n meta: { name: 'service.action', version: '1.0.0', ... },\n io: { input: InputSchema, output: OutputSchema },\n policy: { auth: 'user', ... },\n handler: async (args, ctx) => { ... }\n});\n\\`\\`\\`\n\n## Rules for ${projectName}\n\n- All API endpoints must have a corresponding operation contract.\n- Events must be declared in contracts before being emitted.\n- UI components should reference presentation contracts.\n- Feature flags should be defined in feature modules.\n`;\n}\n\n/**\n * Generate AGENTS.md content.\n *\n * Adapts paths and instructions based on monorepo scope.\n */\nexport function generateAgentsMd(options: SetupOptions): string {\n const projectName = options.projectName ?? 'This Project';\n const isPackageLevel = options.isMonorepo && options.scope === 'package';\n\n // Contract path depends on scope\n const contractPath = 'src/contracts/';\n\n const monorepoSection = options.isMonorepo\n ? `\n## Monorepo Structure\n\nThis is a monorepo. Contracts can exist at multiple levels:\n\n| Level | Location | Use Case |\n|-------|----------|----------|\n| Package | \\`packages/*/src/contracts/\\` | Package-specific contracts |\n| Workspace | \\`src/contracts/\\` | Shared cross-package contracts |\n\nWhen adding a contract, consider:\n- Is this specific to one package? → Add at package level\n- Is this shared across packages? → Add at workspace level\n\n### Current Scope\n\n${isPackageLevel ? `You are working at the **package level**: \\`${options.packageName ?? options.packageRoot}\\`` : 'You are working at the **workspace level**.'}\n`\n : '';\n\n return `# AI Agent Guide\n\nThis repository uses **ContractSpec** for spec-first development. AI agents should follow these guidelines.\n\n## Project: ${projectName}\n\n## ContractSpec Overview\n\nContractSpec is a deterministic, spec-first compiler that keeps AI-written software coherent, safe, and regenerable.\n\n### Key Principles\n\n1. **Contracts are the source of truth** - Always check/update contracts before modifying implementation.\n2. **Safe regeneration** - Code can be regenerated from specs without breaking invariants.\n3. **Multi-surface consistency** - API, events, and UI stay in sync via shared contracts.\n${monorepoSection}\n## Working in This Repository\n\n### Before Making Changes\n\n1. Check for existing contracts in \\`${contractPath}\\`\n2. If a contract exists, update it first\n3. Regenerate implementation with \\`contractspec build\\`\n4. Validate with \\`contractspec validate\\`\n\n### Creating New Features\n\n1. Create a feature spec: \\`contractspec create --type=feature\\`\n2. Add operations: \\`contractspec create --type=operation\\`\n3. Add events if needed: \\`contractspec create --type=event\\`\n4. Build implementation: \\`contractspec build\\`\n\n### Contract Locations\n\n| Type | Location |\n|------|----------|\n| Operations | \\`${contractPath}operations/\\` |\n| Events | \\`${contractPath}events/\\` |\n| Presentations | \\`${contractPath}presentations/\\` |\n| Features | \\`${contractPath}features/\\` |\n\n## MCP Tools Available\n\nThe ContractSpec MCP server provides these tools:\n\n- \\`integrity.analyze\\` - Check contract health\n- \\`specs.list\\` - List all specs\n- \\`specs.validate\\` - Validate a spec file\n- \\`specs.create\\` - Create new specs\n- \\`deps.analyze\\` - Analyze dependencies\n\n## Common Tasks\n\n### Add a new API endpoint\n\n\\`\\`\\`bash\ncontractspec create --type=operation --name=myService.newAction\n\\`\\`\\`\n\n### Add a new event\n\n\\`\\`\\`bash\ncontractspec create --type=event --name=entity.changed\n\\`\\`\\`\n\n### Check contract integrity\n\n\\`\\`\\`bash\ncontractspec integrity\n\\`\\`\\`\n\n## Nested AGENTS.md\n\nMore specific instructions may exist in subdirectories. Check for \\`AGENTS.md\\` files in the relevant package or module.\n`;\n}\n\n/**\n * Get the file path for Claude Desktop config based on platform.\n */\nexport function getClaudeDesktopConfigPath(): string {\n const platform = process.platform;\n const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';\n\n switch (platform) {\n case 'darwin':\n return `${homeDir}/Library/Application Support/Claude/claude_desktop_config.json`;\n case 'win32':\n return `${process.env['APPDATA'] ?? homeDir}/Claude/claude_desktop_config.json`;\n default:\n // Linux and others\n return `${homeDir}/.config/claude/claude_desktop_config.json`;\n }\n}\n"],"mappings":";;;;;;AAaA,SAAgB,0BAA0B,SAA+B;CAEvE,MAAM,iBAAiB,QAAQ,cAAc,QAAQ,UAAU;AAE/D,QAAO;EACL,SAAS;EACT,YAAY;EACZ,SAAS;EACT,WAAW;EAEX,WAAW;EACX,aAAa;GACX,YAAY;GACZ,QAAQ;GACR,eAAe;GACf,OAAO;GACP,UAAU;GACX;EACD,eAAe,QAAQ,iBAAiB,CAAC,QAAQ;EACjD,aAAa,EAAE;EAEf,GAAI,kBAAkB,QAAQ,cAC1B,EAAE,SAAS,QAAQ,aAAa,GAChC,EAAE;EACP;;;;;AAMH,SAAgB,yBAAiC;AAC/C,QAAO;EACL,mCAAmC;EACnC,0CAA0C;EAC1C,0CAA0C;EAC1C,iCAAiC;EACjC,yCAAyC;EACzC,sCAAsC;EACtC,kCAAkC;EAClC,sCAAsC;EACvC;;;;;AAMH,SAAgB,0BAAkC;AAChD,QAAO,EACL,YAAY,EACV,sBAAsB;EACpB,SAAS;EACT,MAAM,CAAC,mBAAmB;EAC3B,EACF,EACF;;;;;;AAOH,SAAgB,0BAAkC;AAChD,QAAO,EACL,YAAY,EACV,sBAAsB;EACpB,SAAS;EACT,MAAM,CAAC,mBAAmB;EAC3B,EACF,EACF;;;;;;;AAQH,SAAgB,oBAAoB,SAA+B;CACjE,MAAM,cAAc,QAAQ,eAAe;CAI3C,MAAM,WAHiB,QAAQ,cAAc,QAAQ,UAAU,aAI3C,QAAQ,cACtB,GAAG,QAAQ,YAAY,MAAM,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,IAAI,CAAC,kBACtD;AAMN,QAAO;;;;;;;;;EAJc,QAAQ,aACzB,+NACA,GAWS;;;;MAIT,SAAS;MACT,SAAS;MACT,SAAS;MACT,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;eA4BA,YAAY;;;;;;;;;;;;;AAc3B,SAAgB,iBAAiB,SAA+B;CAC9D,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,iBAAiB,QAAQ,cAAc,QAAQ,UAAU;CAG/D,MAAM,eAAe;AAuBrB,QAAO;;;;cAIK,YAAY;;;;;;;;;;;EAzBA,QAAQ,aAC5B;;;;;;;;;;;;;;;;EAgBJ,iBAAiB,+CAA+C,QAAQ,eAAe,QAAQ,YAAY,MAAM,8CAA8C;IAE3J,GAiBY;;;;;uCAKqB,aAAa;;;;;;;;;;;;;;;;mBAgBjC,aAAa;eACjB,aAAa;sBACN,aAAa;iBAClB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyC9B,SAAgB,6BAAqC;CACnD,MAAM,WAAW,QAAQ;CACzB,MAAM,UAAU,QAAQ,IAAI,WAAW,QAAQ,IAAI,kBAAkB;AAErE,SAAQ,UAAR;EACE,KAAK,SACH,QAAO,GAAG,QAAQ;EACpB,KAAK,QACH,QAAO,GAAG,QAAQ,IAAI,cAAc,QAAQ;EAC9C,QAEE,QAAO,GAAG,QAAQ"}
1
+ {"version":3,"file":"config-generators.js","names":[],"sources":["../../../src/services/setup/config-generators.ts"],"sourcesContent":["/**\n * Config generators for setup targets.\n *\n * Each generator returns the default configuration for a target.\n */\n\nimport type { SetupOptions } from './types';\n\n/**\n * Generate .contractsrc.json content.\n *\n * Adapts defaults based on monorepo scope.\n */\nexport function generateContractsrcConfig(options: SetupOptions): object {\n // For package-level config in monorepo, use simpler relative paths\n const isPackageLevel = options.isMonorepo && options.scope === 'package';\n\n return {\n $schema: 'https://api.contractspec.io/schemas/contractsrc.json',\n aiProvider: 'claude',\n aiModel: 'claude-sonnet-4-20250514',\n agentMode: 'claude-code',\n // outputDir is relative to the config file location\n outputDir: './src',\n conventions: {\n operations: 'contracts/operations',\n events: 'contracts/events',\n presentations: 'contracts/presentations',\n forms: 'contracts/forms',\n features: 'contracts/features',\n },\n defaultOwners: options.defaultOwners ?? ['@team'],\n defaultTags: [],\n // Versioning configuration\n versioning: {\n autoBump: false,\n bumpStrategy: 'impact',\n changelogTiers: ['spec', 'library', 'monorepo'],\n format: 'keep-a-changelog',\n commitChanges: false,\n createTags: false,\n integrateWithChangesets: true, // Enable changesets integration by default\n },\n // Git hooks configuration (Husky compatible)\n hooks: {\n 'pre-commit': [\n 'contractspec validate **/*.operation.ts',\n 'contractspec integrity check',\n ],\n },\n // Add monorepo hint if at package level\n ...(isPackageLevel && options.packageName\n ? { package: options.packageName }\n : {}),\n };\n}\n\n/**\n * Generate .vscode/settings.json ContractSpec settings.\n */\nexport function generateVscodeSettings(): object {\n return {\n 'contractspec.validation.enabled': true,\n 'contractspec.validation.validateOnSave': true,\n 'contractspec.validation.validateOnOpen': true,\n 'contractspec.codeLens.enabled': true,\n 'contractspec.diagnostics.showWarnings': true,\n 'contractspec.diagnostics.showHints': true,\n 'contractspec.integrity.enabled': true,\n 'contractspec.integrity.checkOnSave': true,\n };\n}\n\n/**\n * Generate .cursor/mcp.json content.\n */\nexport function generateCursorMcpConfig(): object {\n return {\n mcpServers: {\n 'contractspec-local': {\n command: 'bunx',\n args: ['contractspec-mcp'],\n },\n },\n };\n}\n\n/**\n * Generate Claude Desktop MCP config.\n * Returns the mcpServers section to merge into claude_desktop_config.json.\n */\nexport function generateClaudeMcpConfig(): object {\n return {\n mcpServers: {\n 'contractspec-local': {\n command: 'bunx',\n args: ['contractspec-mcp'],\n },\n },\n };\n}\n\n/**\n * Generate .cursor/rules/contractspec.mdc content.\n *\n * Adapts paths based on monorepo scope.\n */\nexport function generateCursorRules(options: SetupOptions): string {\n const projectName = options.projectName ?? 'this project';\n const isPackageLevel = options.isMonorepo && options.scope === 'package';\n\n // Base contract path depends on scope\n const basePath =\n isPackageLevel && options.packageRoot\n ? `${options.packageRoot.split('/').slice(-2).join('/')}/src/contracts`\n : 'src/contracts';\n\n const monorepoNote = options.isMonorepo\n ? `\\n## Monorepo Structure\\n\\nThis is a monorepo. Contracts may exist at:\\n- Package level: \\`packages/*/src/contracts/\\`\\n- Workspace level: \\`src/contracts/\\`\\n\\nCheck the appropriate level based on the feature scope.\\n`\n : '';\n\n return `# ContractSpec Development Rules\n\nThis project uses ContractSpec for spec-first development. Follow these guidelines when working with AI agents.\n\n## Spec-First Principle\n\n- **Always update contracts first** before changing implementation code.\n- Contracts are the source of truth for operations, events, and presentations.\n- Implementation code should be generated or derived from contracts.\n${monorepoNote}\n## Contract Locations\n\nContracts are located in:\n- \\`${basePath}/operations/\\` - Command and query specs\n- \\`${basePath}/events/\\` - Event specs\n- \\`${basePath}/presentations/\\` - UI presentation specs\n- \\`${basePath}/features/\\` - Feature module specs\n\n## When Making Changes\n\n1. **Before coding**: Check if a contract exists for the feature.\n2. **If contract exists**: Update the contract first, then regenerate code.\n3. **If no contract**: Create a new contract using \\`contractspec create\\`.\n4. **After changes**: Validate with \\`contractspec validate\\`.\n\n## Key Commands\n\n- \\`contractspec create\\` - Scaffold new specs\n- \\`contractspec validate\\` - Validate specs\n- \\`contractspec build\\` - Generate implementation code\n- \\`contractspec integrity\\` - Check contract health\n\n## Contract Structure\n\nOperations follow this pattern:\n\\`\\`\\`typescript\ndefineCommand({\n meta: { name: 'service.action', version: '1.0.0', ... },\n io: { input: InputSchema, output: OutputSchema },\n policy: { auth: 'user', ... },\n handler: async (args, ctx) => { ... }\n});\n\\`\\`\\`\n\n## Rules for ${projectName}\n\n- All API endpoints must have a corresponding operation contract.\n- Events must be declared in contracts before being emitted.\n- UI components should reference presentation contracts.\n- Feature flags should be defined in feature modules.\n`;\n}\n\n/**\n * Generate AGENTS.md content.\n *\n * Adapts paths and instructions based on monorepo scope.\n */\nexport function generateAgentsMd(options: SetupOptions): string {\n const projectName = options.projectName ?? 'This Project';\n const isPackageLevel = options.isMonorepo && options.scope === 'package';\n\n // Contract path depends on scope\n const contractPath = 'src/contracts/';\n\n const monorepoSection = options.isMonorepo\n ? `\n## Monorepo Structure\n\nThis is a monorepo. Contracts can exist at multiple levels:\n\n| Level | Location | Use Case |\n|-------|----------|----------|\n| Package | \\`packages/*/src/contracts/\\` | Package-specific contracts |\n| Workspace | \\`src/contracts/\\` | Shared cross-package contracts |\n\nWhen adding a contract, consider:\n- Is this specific to one package? → Add at package level\n- Is this shared across packages? → Add at workspace level\n\n### Current Scope\n\n${isPackageLevel ? `You are working at the **package level**: \\`${options.packageName ?? options.packageRoot}\\`` : 'You are working at the **workspace level**.'}\n`\n : '';\n\n return `# AI Agent Guide\n\nThis repository uses **ContractSpec** for spec-first development. AI agents should follow these guidelines.\n\n## Project: ${projectName}\n\n## ContractSpec Overview\n\nContractSpec is a deterministic, spec-first compiler that keeps AI-written software coherent, safe, and regenerable.\n\n### Key Principles\n\n1. **Contracts are the source of truth** - Always check/update contracts before modifying implementation.\n2. **Safe regeneration** - Code can be regenerated from specs without breaking invariants.\n3. **Multi-surface consistency** - API, events, and UI stay in sync via shared contracts.\n${monorepoSection}\n## Working in This Repository\n\n### Before Making Changes\n\n1. Check for existing contracts in \\`${contractPath}\\`\n2. If a contract exists, update it first\n3. Regenerate implementation with \\`contractspec build\\`\n4. Validate with \\`contractspec validate\\`\n\n### Creating New Features\n\n1. Create a feature spec: \\`contractspec create --type=feature\\`\n2. Add operations: \\`contractspec create --type=operation\\`\n3. Add events if needed: \\`contractspec create --type=event\\`\n4. Build implementation: \\`contractspec build\\`\n\n### Contract Locations\n\n| Type | Location |\n|------|----------|\n| Operations | \\`${contractPath}operations/\\` |\n| Events | \\`${contractPath}events/\\` |\n| Presentations | \\`${contractPath}presentations/\\` |\n| Features | \\`${contractPath}features/\\` |\n\n## MCP Tools Available\n\nThe ContractSpec MCP server provides these tools:\n\n- \\`integrity.analyze\\` - Check contract health\n- \\`specs.list\\` - List all specs\n- \\`specs.validate\\` - Validate a spec file\n- \\`specs.create\\` - Create new specs\n- \\`deps.analyze\\` - Analyze dependencies\n\n## Common Tasks\n\n### Add a new API endpoint\n\n\\`\\`\\`bash\ncontractspec create --type=operation --name=myService.newAction\n\\`\\`\\`\n\n### Add a new event\n\n\\`\\`\\`bash\ncontractspec create --type=event --name=entity.changed\n\\`\\`\\`\n\n### Check contract integrity\n\n\\`\\`\\`bash\ncontractspec integrity\n\\`\\`\\`\n\n## Nested AGENTS.md\n\nMore specific instructions may exist in subdirectories. Check for \\`AGENTS.md\\` files in the relevant package or module.\n`;\n}\n\n/**\n * Get the file path for Claude Desktop config based on platform.\n */\nexport function getClaudeDesktopConfigPath(): string {\n const platform = process.platform;\n const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';\n\n switch (platform) {\n case 'darwin':\n return `${homeDir}/Library/Application Support/Claude/claude_desktop_config.json`;\n case 'win32':\n return `${process.env['APPDATA'] ?? homeDir}/Claude/claude_desktop_config.json`;\n default:\n // Linux and others\n return `${homeDir}/.config/claude/claude_desktop_config.json`;\n }\n}\n"],"mappings":";;;;;;AAaA,SAAgB,0BAA0B,SAA+B;CAEvE,MAAM,iBAAiB,QAAQ,cAAc,QAAQ,UAAU;AAE/D,QAAO;EACL,SAAS;EACT,YAAY;EACZ,SAAS;EACT,WAAW;EAEX,WAAW;EACX,aAAa;GACX,YAAY;GACZ,QAAQ;GACR,eAAe;GACf,OAAO;GACP,UAAU;GACX;EACD,eAAe,QAAQ,iBAAiB,CAAC,QAAQ;EACjD,aAAa,EAAE;EAEf,YAAY;GACV,UAAU;GACV,cAAc;GACd,gBAAgB;IAAC;IAAQ;IAAW;IAAW;GAC/C,QAAQ;GACR,eAAe;GACf,YAAY;GACZ,yBAAyB;GAC1B;EAED,OAAO,EACL,cAAc,CACZ,2CACA,+BACD,EACF;EAED,GAAI,kBAAkB,QAAQ,cAC1B,EAAE,SAAS,QAAQ,aAAa,GAChC,EAAE;EACP;;;;;AAMH,SAAgB,yBAAiC;AAC/C,QAAO;EACL,mCAAmC;EACnC,0CAA0C;EAC1C,0CAA0C;EAC1C,iCAAiC;EACjC,yCAAyC;EACzC,sCAAsC;EACtC,kCAAkC;EAClC,sCAAsC;EACvC;;;;;AAMH,SAAgB,0BAAkC;AAChD,QAAO,EACL,YAAY,EACV,sBAAsB;EACpB,SAAS;EACT,MAAM,CAAC,mBAAmB;EAC3B,EACF,EACF;;;;;;AAOH,SAAgB,0BAAkC;AAChD,QAAO,EACL,YAAY,EACV,sBAAsB;EACpB,SAAS;EACT,MAAM,CAAC,mBAAmB;EAC3B,EACF,EACF;;;;;;;AAQH,SAAgB,oBAAoB,SAA+B;CACjE,MAAM,cAAc,QAAQ,eAAe;CAI3C,MAAM,WAHiB,QAAQ,cAAc,QAAQ,UAAU,aAI3C,QAAQ,cACtB,GAAG,QAAQ,YAAY,MAAM,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,IAAI,CAAC,kBACtD;AAMN,QAAO;;;;;;;;;EAJc,QAAQ,aACzB,+NACA,GAWS;;;;MAIT,SAAS;MACT,SAAS;MACT,SAAS;MACT,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;eA4BA,YAAY;;;;;;;;;;;;;AAc3B,SAAgB,iBAAiB,SAA+B;CAC9D,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,iBAAiB,QAAQ,cAAc,QAAQ,UAAU;CAG/D,MAAM,eAAe;AAuBrB,QAAO;;;;cAIK,YAAY;;;;;;;;;;;EAzBA,QAAQ,aAC5B;;;;;;;;;;;;;;;;EAgBJ,iBAAiB,+CAA+C,QAAQ,eAAe,QAAQ,YAAY,MAAM,8CAA8C;IAE3J,GAiBY;;;;;uCAKqB,aAAa;;;;;;;;;;;;;;;;mBAgBjC,aAAa;eACjB,aAAa;sBACN,aAAa;iBAClB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyC9B,SAAgB,6BAAqC;CACnD,MAAM,WAAW,QAAQ;CACzB,MAAM,UAAU,QAAQ,IAAI,WAAW,QAAQ,IAAI,kBAAkB;AAErE,SAAQ,UAAR;EACE,KAAK,SACH,QAAO,GAAG,QAAQ;EACpB,KAAK,QACH,QAAO,GAAG,QAAQ,IAAI,cAAc,QAAQ;EAC9C,QAEE,QAAO,GAAG,QAAQ"}
@@ -0,0 +1,10 @@
1
+ import { ConfigUpgradeInfo, PackageUpgradeInfo, UpgradeAnalysisResult, UpgradeApplyResult, UpgradeOptions } from "./types.js";
2
+ import { analyzeUpgrades, applyConfigUpgrades, getDefaultHooksConfig, getDefaultVersioningConfig, getPackageUpgradeCommand } from "./upgrade-service.js";
3
+
4
+ //#region src/services/upgrade/index.d.ts
5
+ declare namespace index_d_exports {
6
+ export { ConfigUpgradeInfo, PackageUpgradeInfo, UpgradeAnalysisResult, UpgradeApplyResult, UpgradeOptions, analyzeUpgrades, applyConfigUpgrades, getDefaultHooksConfig, getDefaultVersioningConfig, getPackageUpgradeCommand };
7
+ }
8
+ //#endregion
9
+ export { index_d_exports };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/services/upgrade/index.ts"],"sourcesContent":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import { __exportAll } from "../../_virtual/rolldown_runtime.js";
2
+ import { analyzeUpgrades, applyConfigUpgrades, getDefaultHooksConfig, getDefaultVersioningConfig, getPackageUpgradeCommand } from "./upgrade-service.js";
3
+
4
+ //#region src/services/upgrade/index.ts
5
+ var upgrade_exports = /* @__PURE__ */ __exportAll({
6
+ analyzeUpgrades: () => analyzeUpgrades,
7
+ applyConfigUpgrades: () => applyConfigUpgrades,
8
+ getDefaultHooksConfig: () => getDefaultHooksConfig,
9
+ getDefaultVersioningConfig: () => getDefaultVersioningConfig,
10
+ getPackageUpgradeCommand: () => getPackageUpgradeCommand
11
+ });
12
+
13
+ //#endregion
14
+ export { upgrade_exports };
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/services/upgrade/index.ts"],"sourcesContent":["/**\n * Upgrade service module.\n *\n * Provides upgrade analysis and application for ContractSpec SDK and config.\n */\n\nexport * from './types';\nexport {\n analyzeUpgrades,\n applyConfigUpgrades,\n getPackageUpgradeCommand,\n getDefaultVersioningConfig,\n getDefaultHooksConfig,\n} from './upgrade-service';\n"],"mappings":""}
@@ -0,0 +1,78 @@
1
+ //#region src/services/upgrade/types.d.ts
2
+ /**
3
+ * Upgrade service types.
4
+ *
5
+ * Types for upgrading ContractSpec SDK and configuration.
6
+ */
7
+ /**
8
+ * Options for running an upgrade.
9
+ */
10
+ interface UpgradeOptions {
11
+ /** Root directory of the workspace. */
12
+ workspaceRoot: string;
13
+ /** Upgrade SDK packages. */
14
+ upgradePackages?: boolean;
15
+ /** Upgrade configuration. */
16
+ upgradeConfig?: boolean;
17
+ /** Preview changes without applying. */
18
+ dryRun?: boolean;
19
+ /** Use @latest tag instead of caret range. */
20
+ useLatest?: boolean;
21
+ }
22
+ /**
23
+ * Result of a package upgrade check.
24
+ */
25
+ interface PackageUpgradeInfo {
26
+ /** Package name. */
27
+ name: string;
28
+ /** Current version. */
29
+ currentVersion: string;
30
+ /** Latest available version (if known). */
31
+ latestVersion?: string;
32
+ /** Whether this is a dev dependency. */
33
+ isDevDependency: boolean;
34
+ }
35
+ /**
36
+ * Result of a config upgrade check.
37
+ */
38
+ interface ConfigUpgradeInfo {
39
+ /** Config key that needs upgrading. */
40
+ key: string;
41
+ /** Current value (if any). */
42
+ currentValue?: unknown;
43
+ /** Suggested new value. */
44
+ suggestedValue: unknown;
45
+ /** Whether this is a new key. */
46
+ isNew: boolean;
47
+ }
48
+ /**
49
+ * Result of the upgrade analysis.
50
+ */
51
+ interface UpgradeAnalysisResult {
52
+ /** Detected package manager. */
53
+ packageManager: string;
54
+ /** Packages that can be upgraded. */
55
+ packages: PackageUpgradeInfo[];
56
+ /** Config sections that need upgrading. */
57
+ configUpgrades: ConfigUpgradeInfo[];
58
+ /** Whether any upgrades are available. */
59
+ hasUpgrades: boolean;
60
+ }
61
+ /**
62
+ * Result of applying an upgrade.
63
+ */
64
+ interface UpgradeApplyResult {
65
+ /** Whether the upgrade was successful. */
66
+ success: boolean;
67
+ /** Number of packages upgraded. */
68
+ packagesUpgraded: number;
69
+ /** Number of config sections upgraded. */
70
+ configSectionsUpgraded: number;
71
+ /** Error message if failed. */
72
+ error?: string;
73
+ /** Summary message. */
74
+ summary: string;
75
+ }
76
+ //#endregion
77
+ export { ConfigUpgradeInfo, PackageUpgradeInfo, UpgradeAnalysisResult, UpgradeApplyResult, UpgradeOptions };
78
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/services/upgrade/types.ts"],"sourcesContent":[],"mappings":";;AAaA;AAgBA;AAcA;AAcA;AAcA;;;UA1DiB,cAAA;;;;;;;;;;;;;;;UAgBA,kBAAA;;;;;;;;;;;;;UAcA,iBAAA;;;;;;;;;;;;;UAcA,qBAAA;;;;YAIL;;kBAEM;;;;;;;UAQD,kBAAA"}
@@ -0,0 +1,38 @@
1
+ import { FsAdapter } from "../../ports/fs.js";
2
+ import { LoggerAdapter } from "../../ports/logger.js";
3
+ import { PackageUpgradeInfo, UpgradeAnalysisResult, UpgradeApplyResult, UpgradeOptions } from "./types.js";
4
+
5
+ //#region src/services/upgrade/upgrade-service.d.ts
6
+
7
+ interface ServiceAdapters {
8
+ fs: FsAdapter;
9
+ logger: LoggerAdapter;
10
+ }
11
+ /**
12
+ * Analyze what upgrades are available.
13
+ */
14
+ declare function analyzeUpgrades(adapters: ServiceAdapters, options: UpgradeOptions): Promise<UpgradeAnalysisResult>;
15
+ /**
16
+ * Apply configuration upgrades.
17
+ *
18
+ * Note: Package upgrades must be applied by the app layer (CLI, VSCode)
19
+ * since they require running npm/bun/yarn commands which is platform-specific.
20
+ */
21
+ declare function applyConfigUpgrades(adapters: ServiceAdapters, options: UpgradeOptions): Promise<UpgradeApplyResult>;
22
+ /**
23
+ * Get the command to upgrade packages.
24
+ *
25
+ * Returns the shell command string that the app layer should execute.
26
+ */
27
+ declare function getPackageUpgradeCommand(packageManager: string, packages: PackageUpgradeInfo[], useLatest: boolean): string;
28
+ /**
29
+ * Get default versioning configuration.
30
+ */
31
+ declare function getDefaultVersioningConfig(): Record<string, unknown>;
32
+ /**
33
+ * Get default hooks configuration.
34
+ */
35
+ declare function getDefaultHooksConfig(): Record<string, string[]>;
36
+ //#endregion
37
+ export { analyzeUpgrades, applyConfigUpgrades, getDefaultHooksConfig, getDefaultVersioningConfig, getPackageUpgradeCommand };
38
+ //# sourceMappingURL=upgrade-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-service.d.ts","names":[],"sources":["../../../src/services/upgrade/upgrade-service.ts"],"sourcesContent":[],"mappings":";;;;;;UAmCU,eAAA,CAeA;EAoJY,EAAA,EAlKhB,SAkKgB;EACV,MAAA,EAlKF,aAkKE;;;;;AA4FI,iBApPM,eAAA,CAoPkB,QAE5B,EArPA,eAqPkB,EAAA,OAAA,EApPnB,cAoPmB,CAAA,EAnP3B,OAmP2B,CAnPnB,qBAmPmB,CAAA;AA0B9B;AAeA;;;;;iBAxIsB,mBAAA,WACV,0BACD,iBACR,QAAQ;;;;;;iBA0FK,wBAAA,mCAEJ;;;;iBA0BI,0BAAA,CAAA,GAA8B;;;;iBAe9B,qBAAA,CAAA,GAAyB"}
@@ -0,0 +1,201 @@
1
+ import { detectPackageManager, findWorkspaceRoot } from "../../adapters/workspace.js";
2
+
3
+ //#region src/services/upgrade/upgrade-service.ts
4
+ const LATEST_SCHEMA_URL = `https://${process.env["CONTRACTSPEC_API_HOST"] ?? "api.contractspec.io"}/schemas/contractsrc.json`;
5
+ /**
6
+ * Analyze what upgrades are available.
7
+ */
8
+ async function analyzeUpgrades(adapters, options) {
9
+ const { fs, logger } = adapters;
10
+ const workspaceRoot = findWorkspaceRoot(options.workspaceRoot);
11
+ const packageManager = detectPackageManager(workspaceRoot);
12
+ logger.info("Analyzing available upgrades...", {
13
+ workspaceRoot,
14
+ packageManager
15
+ });
16
+ const packages = await analyzePackages(fs, workspaceRoot);
17
+ const configUpgrades = await analyzeConfig(fs, workspaceRoot);
18
+ return {
19
+ packageManager,
20
+ packages,
21
+ configUpgrades,
22
+ hasUpgrades: packages.length > 0 || configUpgrades.length > 0
23
+ };
24
+ }
25
+ /**
26
+ * Analyze installed packages for potential updates.
27
+ * Checks for all packages in the workspace that match ContractSpec patterns.
28
+ */
29
+ async function analyzePackages(fs, workspaceRoot) {
30
+ const packageJsonPath = fs.join(workspaceRoot, "package.json");
31
+ if (!await fs.exists(packageJsonPath)) return [];
32
+ try {
33
+ const content = await fs.readFile(packageJsonPath);
34
+ const packageJson = JSON.parse(content);
35
+ const deps = packageJson.dependencies ?? {};
36
+ const devDeps = packageJson.devDependencies ?? {};
37
+ const packages = [];
38
+ const allDeps = {
39
+ ...deps,
40
+ ...devDeps
41
+ };
42
+ for (const [name, version] of Object.entries(allDeps)) if (name.startsWith("@contractspec/") || name === "contractspec" || name.startsWith("@lssm/")) packages.push({
43
+ name,
44
+ currentVersion: version,
45
+ isDevDependency: !!devDeps[name]
46
+ });
47
+ return packages;
48
+ } catch {
49
+ return [];
50
+ }
51
+ }
52
+ /**
53
+ * Analyze configuration for upgrade opportunities.
54
+ */
55
+ async function analyzeConfig(fs, workspaceRoot) {
56
+ const configPath = fs.join(workspaceRoot, ".contractsrc.json");
57
+ if (!await fs.exists(configPath)) return [];
58
+ try {
59
+ const content = await fs.readFile(configPath);
60
+ const config = JSON.parse(content);
61
+ const upgrades = [];
62
+ const currentSchema = config["$schema"];
63
+ if (!currentSchema || currentSchema !== LATEST_SCHEMA_URL) upgrades.push({
64
+ key: "$schema",
65
+ currentValue: currentSchema,
66
+ suggestedValue: LATEST_SCHEMA_URL,
67
+ isNew: !currentSchema
68
+ });
69
+ if (!config["versioning"]) upgrades.push({
70
+ key: "versioning",
71
+ currentValue: void 0,
72
+ suggestedValue: getDefaultVersioningConfig(),
73
+ isNew: true
74
+ });
75
+ else if (config["versioning"]["integrateWithChangesets"] === void 0) upgrades.push({
76
+ key: "versioning.integrateWithChangesets",
77
+ currentValue: void 0,
78
+ suggestedValue: false,
79
+ isNew: true
80
+ });
81
+ if (!config["hooks"]) upgrades.push({
82
+ key: "hooks",
83
+ currentValue: void 0,
84
+ suggestedValue: getDefaultHooksConfig(),
85
+ isNew: true
86
+ });
87
+ return upgrades;
88
+ } catch {
89
+ return [];
90
+ }
91
+ }
92
+ /**
93
+ * Apply configuration upgrades.
94
+ *
95
+ * Note: Package upgrades must be applied by the app layer (CLI, VSCode)
96
+ * since they require running npm/bun/yarn commands which is platform-specific.
97
+ */
98
+ async function applyConfigUpgrades(adapters, options) {
99
+ const { fs, logger } = adapters;
100
+ const workspaceRoot = findWorkspaceRoot(options.workspaceRoot);
101
+ if (options.dryRun) logger.info("Dry run - no changes will be made");
102
+ const configPath = fs.join(workspaceRoot, ".contractsrc.json");
103
+ if (!await fs.exists(configPath)) return {
104
+ success: false,
105
+ packagesUpgraded: 0,
106
+ configSectionsUpgraded: 0,
107
+ error: "No .contractsrc.json found",
108
+ summary: "No configuration file to upgrade"
109
+ };
110
+ try {
111
+ const content = await fs.readFile(configPath);
112
+ const config = JSON.parse(content);
113
+ let sectionsUpgraded = 0;
114
+ const currentSchema = config["$schema"];
115
+ if (!currentSchema || currentSchema !== LATEST_SCHEMA_URL) {
116
+ config["$schema"] = LATEST_SCHEMA_URL;
117
+ sectionsUpgraded++;
118
+ }
119
+ if (!config["versioning"]) {
120
+ config["versioning"] = getDefaultVersioningConfig();
121
+ sectionsUpgraded++;
122
+ } else {
123
+ const versioning = config["versioning"];
124
+ if (versioning["integrateWithChangesets"] === void 0) {
125
+ versioning["integrateWithChangesets"] = false;
126
+ sectionsUpgraded++;
127
+ }
128
+ }
129
+ if (!config["hooks"]) {
130
+ config["hooks"] = getDefaultHooksConfig();
131
+ sectionsUpgraded++;
132
+ }
133
+ if (sectionsUpgraded === 0) return {
134
+ success: true,
135
+ packagesUpgraded: 0,
136
+ configSectionsUpgraded: 0,
137
+ summary: "Configuration is already up to date"
138
+ };
139
+ if (!options.dryRun) {
140
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
141
+ logger.info("Configuration upgraded", { sectionsUpgraded });
142
+ }
143
+ return {
144
+ success: true,
145
+ packagesUpgraded: 0,
146
+ configSectionsUpgraded: sectionsUpgraded,
147
+ summary: options.dryRun ? `Would upgrade ${sectionsUpgraded} config section(s)` : `Upgraded ${sectionsUpgraded} config section(s)`
148
+ };
149
+ } catch (error) {
150
+ const msg = error instanceof Error ? error.message : String(error);
151
+ return {
152
+ success: false,
153
+ packagesUpgraded: 0,
154
+ configSectionsUpgraded: 0,
155
+ error: msg,
156
+ summary: `Failed to upgrade config: ${msg}`
157
+ };
158
+ }
159
+ }
160
+ /**
161
+ * Get the command to upgrade packages.
162
+ *
163
+ * Returns the shell command string that the app layer should execute.
164
+ */
165
+ function getPackageUpgradeCommand(packageManager, packages, useLatest) {
166
+ const pkgList = useLatest ? packages.map((p) => `${p.name}@latest`).join(" ") : packages.map((p) => p.name).join(" ");
167
+ switch (packageManager) {
168
+ case "bun": return `bun add ${pkgList}`;
169
+ case "pnpm": return `pnpm add ${pkgList}`;
170
+ case "yarn": return `yarn add ${pkgList}`;
171
+ default: return `npm install ${pkgList}`;
172
+ }
173
+ }
174
+ /**
175
+ * Get default versioning configuration.
176
+ */
177
+ function getDefaultVersioningConfig() {
178
+ return {
179
+ autoBump: false,
180
+ bumpStrategy: "impact",
181
+ changelogTiers: [
182
+ "spec",
183
+ "library",
184
+ "monorepo"
185
+ ],
186
+ format: "keep-a-changelog",
187
+ commitChanges: false,
188
+ createTags: false,
189
+ integrateWithChangesets: true
190
+ };
191
+ }
192
+ /**
193
+ * Get default hooks configuration.
194
+ */
195
+ function getDefaultHooksConfig() {
196
+ return { "pre-commit": ["contractspec validate", "contractspec integrity check"] };
197
+ }
198
+
199
+ //#endregion
200
+ export { analyzeUpgrades, applyConfigUpgrades, getDefaultHooksConfig, getDefaultVersioningConfig, getPackageUpgradeCommand };
201
+ //# sourceMappingURL=upgrade-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-service.js","names":["packages: PackageUpgradeInfo[]","upgrades: ConfigUpgradeInfo[]"],"sources":["../../../src/services/upgrade/upgrade-service.ts"],"sourcesContent":["/**\n * Upgrade service.\n *\n * Analyzes and applies upgrades to ContractSpec SDK packages and configuration.\n * This service is platform-agnostic and can be used by CLI, VSCode, or other apps.\n *\n * @module services/upgrade\n */\n\nimport type { FsAdapter } from '../../ports/fs';\nimport type { LoggerAdapter } from '../../ports/logger';\nimport {\n detectPackageManager,\n findWorkspaceRoot,\n} from '../../adapters/workspace';\nimport type {\n UpgradeOptions,\n UpgradeAnalysisResult,\n UpgradeApplyResult,\n PackageUpgradeInfo,\n ConfigUpgradeInfo,\n} from './types';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Latest schema URL. */\nconst API_HOST = process.env['CONTRACTSPEC_API_HOST'] ?? 'api.contractspec.io';\nconst LATEST_SCHEMA_URL = `https://${API_HOST}/schemas/contractsrc.json`;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Adapters Type\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface ServiceAdapters {\n fs: FsAdapter;\n logger: LoggerAdapter;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Analysis\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Analyze what upgrades are available.\n */\nexport async function analyzeUpgrades(\n adapters: ServiceAdapters,\n options: UpgradeOptions\n): Promise<UpgradeAnalysisResult> {\n const { fs, logger } = adapters;\n const workspaceRoot = findWorkspaceRoot(options.workspaceRoot);\n const packageManager = detectPackageManager(workspaceRoot);\n\n logger.info('Analyzing available upgrades...', {\n workspaceRoot,\n packageManager,\n });\n\n const packages = await analyzePackages(fs, workspaceRoot);\n const configUpgrades = await analyzeConfig(fs, workspaceRoot);\n\n const hasUpgrades = packages.length > 0 || configUpgrades.length > 0;\n\n return {\n packageManager,\n packages,\n configUpgrades,\n hasUpgrades,\n };\n}\n\n/**\n * Analyze installed packages for potential updates.\n * Checks for all packages in the workspace that match ContractSpec patterns.\n */\nasync function analyzePackages(\n fs: FsAdapter,\n workspaceRoot: string\n): Promise<PackageUpgradeInfo[]> {\n const packageJsonPath = fs.join(workspaceRoot, 'package.json');\n\n if (!(await fs.exists(packageJsonPath))) {\n return [];\n }\n\n try {\n const content = await fs.readFile(packageJsonPath);\n const packageJson = JSON.parse(content) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const deps = packageJson.dependencies ?? {};\n const devDeps = packageJson.devDependencies ?? {};\n\n const packages: PackageUpgradeInfo[] = [];\n const allDeps = { ...deps, ...devDeps };\n\n for (const [name, version] of Object.entries(allDeps)) {\n // Check for ContractSpec related packages\n // Matches @contractspec/*, contractspec, @lssm/* (if internal)\n if (\n name.startsWith('@contractspec/') ||\n name === 'contractspec' ||\n name.startsWith('@lssm/')\n ) {\n packages.push({\n name,\n currentVersion: version,\n isDevDependency: !!devDeps[name],\n });\n }\n }\n\n return packages;\n } catch {\n return [];\n }\n}\n\n/**\n * Analyze configuration for upgrade opportunities.\n */\nasync function analyzeConfig(\n fs: FsAdapter,\n workspaceRoot: string\n): Promise<ConfigUpgradeInfo[]> {\n const configPath = fs.join(workspaceRoot, '.contractsrc.json');\n\n if (!(await fs.exists(configPath))) {\n return [];\n }\n\n try {\n const content = await fs.readFile(configPath);\n const config = JSON.parse(content) as Record<string, unknown>;\n\n const upgrades: ConfigUpgradeInfo[] = [];\n\n // Check $schema\n const currentSchema = config['$schema'] as string | undefined;\n if (!currentSchema || currentSchema !== LATEST_SCHEMA_URL) {\n upgrades.push({\n key: '$schema',\n currentValue: currentSchema,\n suggestedValue: LATEST_SCHEMA_URL,\n isNew: !currentSchema,\n });\n }\n\n // Check versioning\n if (!config['versioning']) {\n upgrades.push({\n key: 'versioning',\n currentValue: undefined,\n suggestedValue: getDefaultVersioningConfig(),\n isNew: true,\n });\n } else {\n const versioning = config['versioning'] as Record<string, unknown>;\n if (versioning['integrateWithChangesets'] === undefined) {\n upgrades.push({\n key: 'versioning.integrateWithChangesets',\n currentValue: undefined,\n suggestedValue: false,\n isNew: true,\n });\n }\n }\n\n // Check hooks\n if (!config['hooks']) {\n upgrades.push({\n key: 'hooks',\n currentValue: undefined,\n suggestedValue: getDefaultHooksConfig(),\n isNew: true,\n });\n }\n\n return upgrades;\n } catch {\n return [];\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Apply Upgrades\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Apply configuration upgrades.\n *\n * Note: Package upgrades must be applied by the app layer (CLI, VSCode)\n * since they require running npm/bun/yarn commands which is platform-specific.\n */\nexport async function applyConfigUpgrades(\n adapters: ServiceAdapters,\n options: UpgradeOptions\n): Promise<UpgradeApplyResult> {\n const { fs, logger } = adapters;\n const workspaceRoot = findWorkspaceRoot(options.workspaceRoot);\n\n if (options.dryRun) {\n logger.info('Dry run - no changes will be made');\n }\n\n const configPath = fs.join(workspaceRoot, '.contractsrc.json');\n\n if (!(await fs.exists(configPath))) {\n return {\n success: false,\n packagesUpgraded: 0,\n configSectionsUpgraded: 0,\n error: 'No .contractsrc.json found',\n summary: 'No configuration file to upgrade',\n };\n }\n\n try {\n const content = await fs.readFile(configPath);\n const config = JSON.parse(content) as Record<string, unknown>;\n\n let sectionsUpgraded = 0;\n\n // Update $schema\n const currentSchema = config['$schema'] as string | undefined;\n if (!currentSchema || currentSchema !== LATEST_SCHEMA_URL) {\n config['$schema'] = LATEST_SCHEMA_URL;\n sectionsUpgraded++;\n }\n\n // Add versioning if missing\n if (!config['versioning']) {\n config['versioning'] = getDefaultVersioningConfig();\n sectionsUpgraded++;\n } else {\n const versioning = config['versioning'] as Record<string, unknown>;\n if (versioning['integrateWithChangesets'] === undefined) {\n versioning['integrateWithChangesets'] = false;\n sectionsUpgraded++;\n }\n }\n\n // Add hooks if missing\n if (!config['hooks']) {\n config['hooks'] = getDefaultHooksConfig();\n sectionsUpgraded++;\n }\n\n if (sectionsUpgraded === 0) {\n return {\n success: true,\n packagesUpgraded: 0,\n configSectionsUpgraded: 0,\n summary: 'Configuration is already up to date',\n };\n }\n\n if (!options.dryRun) {\n await fs.writeFile(configPath, JSON.stringify(config, null, 2) + '\\n');\n logger.info('Configuration upgraded', { sectionsUpgraded });\n }\n\n return {\n success: true,\n packagesUpgraded: 0,\n configSectionsUpgraded: sectionsUpgraded,\n summary: options.dryRun\n ? `Would upgrade ${sectionsUpgraded} config section(s)`\n : `Upgraded ${sectionsUpgraded} config section(s)`,\n };\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n packagesUpgraded: 0,\n configSectionsUpgraded: 0,\n error: msg,\n summary: `Failed to upgrade config: ${msg}`,\n };\n }\n}\n\n/**\n * Get the command to upgrade packages.\n *\n * Returns the shell command string that the app layer should execute.\n */\nexport function getPackageUpgradeCommand(\n packageManager: string,\n packages: PackageUpgradeInfo[],\n useLatest: boolean\n): string {\n const pkgList = useLatest\n ? packages.map((p) => `${p.name}@latest`).join(' ')\n : packages.map((p) => p.name).join(' ');\n\n switch (packageManager) {\n case 'bun':\n return `bun add ${pkgList}`;\n case 'pnpm':\n return `pnpm add ${pkgList}`;\n case 'yarn':\n return `yarn add ${pkgList}`;\n default:\n return `npm install ${pkgList}`;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Default Configs\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Get default versioning configuration.\n */\nexport function getDefaultVersioningConfig(): Record<string, unknown> {\n return {\n autoBump: false,\n bumpStrategy: 'impact',\n changelogTiers: ['spec', 'library', 'monorepo'],\n format: 'keep-a-changelog',\n commitChanges: false,\n createTags: false,\n integrateWithChangesets: true,\n };\n}\n\n/**\n * Get default hooks configuration.\n */\nexport function getDefaultHooksConfig(): Record<string, string[]> {\n return {\n 'pre-commit': ['contractspec validate', 'contractspec integrity check'],\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import { ChangeEntry, VersionBumpType } from "@contractspec/lib.contracts";
2
+
3
+ //#region src/services/versioning/conventional-commits.d.ts
4
+
5
+ /**
6
+ * Parsed conventional commit message.
7
+ */
8
+ interface ConventionalCommit {
9
+ /** Commit type (feat, fix, chore, etc.) */
10
+ type: string;
11
+ /** Optional scope (e.g., auth, api) */
12
+ scope?: string;
13
+ /** Whether this is a breaking change */
14
+ breaking: boolean;
15
+ /** Commit description */
16
+ description: string;
17
+ /** Commit body (optional) */
18
+ body?: string;
19
+ /** Breaking change description (if any) */
20
+ breakingDescription?: string;
21
+ /** Full original message */
22
+ raw: string;
23
+ }
24
+ /**
25
+ * Commit type to bump type mapping.
26
+ */
27
+ type CommitTypeBumpMap = Record<string, VersionBumpType | null>;
28
+ /**
29
+ * Default mapping of commit types to version bump types.
30
+ *
31
+ * - `feat` → minor (new feature)
32
+ * - `fix` → patch (bug fix)
33
+ * - `perf` → patch (performance improvement)
34
+ * - `refactor` → patch (code refactoring)
35
+ * - `docs` → null (no version bump)
36
+ * - `style` → null (no version bump)
37
+ * - `test` → null (no version bump)
38
+ * - `chore` → null (no version bump)
39
+ * - `ci` → null (no version bump)
40
+ * - `build` → null (no version bump)
41
+ */
42
+ declare const DEFAULT_COMMIT_TYPE_MAP: CommitTypeBumpMap;
43
+ /**
44
+ * Parse a conventional commit message.
45
+ *
46
+ * @param message - Full commit message (may include body)
47
+ * @returns Parsed commit or null if not a valid conventional commit
48
+ */
49
+ declare function parseConventionalCommit(message: string): ConventionalCommit | null;
50
+ /**
51
+ * Check if a commit message follows conventional commit format.
52
+ */
53
+ declare function isConventionalCommit(message: string): boolean;
54
+ /**
55
+ * Determine the version bump type from a conventional commit.
56
+ *
57
+ * @param commit - Parsed conventional commit
58
+ * @param typeMap - Optional custom type-to-bump mapping
59
+ * @returns Version bump type or null if no bump needed
60
+ */
61
+ declare function getBumpTypeFromCommit(commit: ConventionalCommit, typeMap?: CommitTypeBumpMap): VersionBumpType | null;
62
+ /**
63
+ * Determine the highest bump type from multiple commits.
64
+ *
65
+ * @param commits - Array of parsed conventional commits
66
+ * @param typeMap - Optional custom type-to-bump mapping
67
+ * @returns Highest version bump type or null if no bump needed
68
+ */
69
+ declare function getHighestBumpType(commits: ConventionalCommit[], typeMap?: CommitTypeBumpMap): VersionBumpType | null;
70
+ /**
71
+ * Convert a conventional commit to a changelog ChangeEntry.
72
+ *
73
+ * @param commit - Parsed conventional commit
74
+ * @returns ChangeEntry for changelog
75
+ */
76
+ declare function commitToChangeEntry(commit: ConventionalCommit): ChangeEntry;
77
+ /**
78
+ * Convert multiple commits to an array of ChangeEntries.
79
+ */
80
+ declare function commitsToChangeEntries(commits: ConventionalCommit[]): ChangeEntry[];
81
+ /**
82
+ * Filter commits by scope (for spec-level changes).
83
+ *
84
+ * @param commits - Array of parsed conventional commits
85
+ * @param scope - Scope to filter by (e.g., "auth", "api")
86
+ * @returns Commits matching the scope
87
+ */
88
+ declare function filterCommitsByScope(commits: ConventionalCommit[], scope: string): ConventionalCommit[];
89
+ /**
90
+ * Filter commits that trigger version bumps.
91
+ */
92
+ declare function filterBumpableCommits(commits: ConventionalCommit[], typeMap?: CommitTypeBumpMap): ConventionalCommit[];
93
+ //#endregion
94
+ export { CommitTypeBumpMap, ConventionalCommit, DEFAULT_COMMIT_TYPE_MAP, commitToChangeEntry, commitsToChangeEntries, filterBumpableCommits, filterCommitsByScope, getBumpTypeFromCommit, getHighestBumpType, isConventionalCommit, parseConventionalCommit };
95
+ //# sourceMappingURL=conventional-commits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conventional-commits.d.ts","names":[],"sources":["../../../src/services/versioning/conventional-commits.ts"],"sourcesContent":[],"mappings":";;;;;;;AAwLkB,UAjKD,kBAAA,CAiKC;EAqCF;EAoDA,IAAA,EAAA,MAAA;EAiBA;EAUA,KAAA,CAAA,EAAA,MAAA;EACL;EACA,QAAA,EAAA,OAAA;EACR;EAAkB,WAAA,EAAA,MAAA;;;;;;;;;;;KApQT,iBAAA,GAAoB,eAAe;;;;;;;;;;;;;;;cAoBlC,yBAAyB;;;;;;;iBAyCtB,uBAAA,mBAEb;;;;iBAwCa,oBAAA;;;;;;;;iBAeA,qBAAA,SACN,8BACC,oBACR;;;;;;;;iBAiBa,kBAAA,UACL,gCACA,oBACR;;;;;;;iBAqCa,mBAAA,SAA4B,qBAAqB;;;;iBAoDjD,sBAAA,UACL,uBACR;;;;;;;;iBAea,oBAAA,UACL,sCAER;;;;iBAOa,qBAAA,UACL,gCACA,oBACR"}