@lssm/bundle.contractspec-workspace 1.42.7 → 1.42.9
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
CHANGED
package/dist/formatters/sarif.js
CHANGED
|
@@ -56,7 +56,7 @@ const RULE_METADATA = {
|
|
|
56
56
|
* Format CI check results as SARIF.
|
|
57
57
|
*/
|
|
58
58
|
function formatAsSarif(result, options = {}) {
|
|
59
|
-
const { toolName = "ContractSpec", toolVersion = "1.0.0", toolUri = "https://contractspec.
|
|
59
|
+
const { toolName = "ContractSpec", toolVersion = "1.0.0", toolUri = "https://contractspec.io", repositoryUri, workingDirectory } = options;
|
|
60
60
|
const ruleMap = /* @__PURE__ */ new Map();
|
|
61
61
|
const ruleIndexMap = /* @__PURE__ */ new Map();
|
|
62
62
|
const issuesWithFiles = result.issues.filter((issue) => issue.file);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sarif.js","names":["RULE_METADATA: Record<\n string,\n { name: string; description: string; helpUri?: string }\n>","rule: SarifRule","results: SarifResult[]","sarifResult: SarifResult","location: SarifLocation","versionControlProvenance: SarifVersionControl[]","run: SarifRun"],"sources":["../../src/formatters/sarif.ts"],"sourcesContent":["/**\n * SARIF output formatter.\n *\n * Formats CI check results as SARIF (Static Analysis Results Interchange Format)\n * for integration with GitHub Code Scanning and other security tools.\n *\n * SARIF Specification: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n */\n\nimport type {\n CICheckResult,\n CIIssue,\n CIIssueSeverity,\n} from '../services/ci-check/types';\n\n/**\n * SARIF v2.1.0 output structure.\n */\nexport interface SarifOutput {\n $schema: string;\n version: string;\n runs: SarifRun[];\n}\n\ninterface SarifRun {\n tool: {\n driver: {\n name: string;\n version: string;\n informationUri: string;\n rules: SarifRule[];\n };\n };\n results: SarifResult[];\n invocations: SarifInvocation[];\n versionControlProvenance?: SarifVersionControl[];\n}\n\ninterface SarifRule {\n id: string;\n name: string;\n shortDescription: { text: string };\n fullDescription?: { text: string };\n defaultConfiguration: {\n level: 'error' | 'warning' | 'note' | 'none';\n };\n helpUri?: string;\n}\n\ninterface SarifResult {\n ruleId: string;\n ruleIndex: number;\n level: 'error' | 'warning' | 'note' | 'none';\n message: { text: string };\n locations?: SarifLocation[];\n partialFingerprints?: Record<string, string>;\n}\n\ninterface SarifLocation {\n physicalLocation: {\n artifactLocation: {\n uri: string;\n uriBaseId?: string;\n };\n region?: {\n startLine?: number;\n startColumn?: number;\n endLine?: number;\n endColumn?: number;\n };\n };\n}\n\ninterface SarifInvocation {\n executionSuccessful: boolean;\n endTimeUtc: string;\n workingDirectory?: { uri: string };\n}\n\ninterface SarifVersionControl {\n repositoryUri?: string;\n revisionId?: string;\n branch?: string;\n}\n\n/**\n * Options for SARIF formatting.\n */\nexport interface SarifFormatOptions {\n /** Tool name. */\n toolName?: string;\n /** Tool version. */\n toolVersion?: string;\n /** Tool information URI. */\n toolUri?: string;\n /** Repository URI for version control provenance. */\n repositoryUri?: string;\n /** Working directory. */\n workingDirectory?: string;\n}\n\n/**\n * Map of rule IDs to their metadata.\n */\nconst RULE_METADATA: Record<\n string,\n { name: string; description: string; helpUri?: string }\n> = {\n 'spec-structure-error': {\n name: 'Spec Structure Error',\n description:\n 'Contract specification is missing required structure elements',\n },\n 'spec-structure-warning': {\n name: 'Spec Structure Warning',\n description: 'Contract specification has recommended but missing elements',\n },\n 'integrity-orphaned': {\n name: 'Orphaned Spec',\n description: 'Contract specification is not linked to any feature',\n },\n 'integrity-unresolved-ref': {\n name: 'Unresolved Reference',\n description: 'Contract specification references a non-existent spec',\n },\n 'integrity-missing-feature': {\n name: 'Missing Feature',\n description: 'Feature referenced by spec does not exist',\n },\n 'integrity-broken-link': {\n name: 'Broken Link',\n description: 'Link between specs is broken',\n },\n 'deps-circular': {\n name: 'Circular Dependency',\n description: 'Circular dependency detected between contracts',\n },\n 'deps-missing': {\n name: 'Missing Dependency',\n description: 'Contract depends on a non-existent contract',\n },\n 'handler-missing': {\n name: 'Missing Handler',\n description: 'Handler implementation file does not exist for this contract',\n },\n 'handler-warning': {\n name: 'Handler Warning',\n description: 'Handler implementation has potential issues',\n },\n 'test-missing': {\n name: 'Missing Test',\n description: 'Test file does not exist for this contract',\n },\n 'test-warning': {\n name: 'Test Warning',\n description: 'Test implementation has potential issues',\n },\n};\n\n/**\n * Format CI check results as SARIF.\n */\nexport function formatAsSarif(\n result: CICheckResult,\n options: SarifFormatOptions = {}\n): SarifOutput {\n const {\n toolName = 'ContractSpec',\n toolVersion = '1.0.0',\n toolUri = 'https://contractspec.lssm.tech',\n repositoryUri,\n workingDirectory,\n } = options;\n\n // Collect unique rules from issues (only from issues with files)\n const ruleMap = new Map<string, SarifRule>();\n const ruleIndexMap = new Map<string, number>();\n\n // Only collect rules from issues that have files (these are the ones that will be in results)\n const issuesWithFiles = result.issues.filter((issue) => issue.file);\n\n for (const issue of issuesWithFiles) {\n if (!ruleMap.has(issue.ruleId)) {\n const metadata = RULE_METADATA[issue.ruleId] ?? {\n name: issue.ruleId,\n description: `Rule: ${issue.ruleId}`,\n };\n\n const rule: SarifRule = {\n id: issue.ruleId,\n name: metadata.name,\n shortDescription: { text: metadata.description },\n defaultConfiguration: {\n level: mapSeverityToLevel(issue.severity),\n },\n };\n\n if (metadata.helpUri) {\n rule.helpUri = metadata.helpUri;\n }\n\n ruleIndexMap.set(issue.ruleId, ruleMap.size);\n ruleMap.set(issue.ruleId, rule);\n }\n }\n\n // Convert issues to SARIF results (only issues with file locations)\n // GitHub Code Scanning requires every result to have at least one location\n const results: SarifResult[] = issuesWithFiles.map((issue) => {\n const sarifResult: SarifResult = {\n ruleId: issue.ruleId,\n ruleIndex: ruleIndexMap.get(issue.ruleId) ?? 0,\n level: mapSeverityToLevel(issue.severity),\n message: { text: issue.message },\n };\n\n // issue.file is guaranteed to be defined due to the filter above\n const location: SarifLocation = {\n physicalLocation: {\n artifactLocation: {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n uri: normalizeUri(issue.file!),\n uriBaseId: '%SRCROOT%',\n },\n },\n };\n\n if (issue.line !== undefined) {\n location.physicalLocation.region = {\n startLine: issue.line,\n startColumn: issue.column ?? 1,\n endLine: issue.endLine ?? issue.line,\n endColumn: issue.endColumn,\n };\n }\n\n sarifResult.locations = [location];\n\n // Add fingerprint for deduplication\n sarifResult.partialFingerprints = {\n primaryLocationLineHash: createFingerprint(issue),\n };\n\n return sarifResult;\n });\n\n // Build version control provenance (only if repositoryUri is provided, as it's required by SARIF schema)\n const versionControlProvenance: SarifVersionControl[] = [];\n if (repositoryUri) {\n versionControlProvenance.push({\n repositoryUri,\n revisionId: result.commitSha,\n branch: result.branch,\n });\n }\n\n const run: SarifRun = {\n tool: {\n driver: {\n name: toolName,\n version: toolVersion,\n informationUri: toolUri,\n rules: Array.from(ruleMap.values()),\n },\n },\n results,\n invocations: [\n {\n executionSuccessful: result.success,\n endTimeUtc: result.timestamp,\n ...(workingDirectory && {\n workingDirectory: { uri: workingDirectory },\n }),\n },\n ],\n };\n\n if (versionControlProvenance.length > 0) {\n run.versionControlProvenance = versionControlProvenance;\n }\n\n return {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [run],\n };\n}\n\n/**\n * Map CI severity to SARIF level.\n */\nfunction mapSeverityToLevel(\n severity: CIIssueSeverity\n): 'error' | 'warning' | 'note' {\n switch (severity) {\n case 'error':\n return 'error';\n case 'warning':\n return 'warning';\n case 'note':\n return 'note';\n default:\n return 'warning';\n }\n}\n\n/**\n * Normalize file path to SARIF URI format.\n */\nfunction normalizeUri(filePath: string): string {\n // Remove leading ./ and normalize path separators\n return filePath.replace(/^\\.\\//, '').replace(/\\\\/g, '/');\n}\n\n/**\n * Create a fingerprint for issue deduplication.\n */\nfunction createFingerprint(issue: CIIssue): string {\n const parts = [issue.ruleId, issue.file ?? '', issue.message];\n return Buffer.from(parts.join('|')).toString('base64').slice(0, 16);\n}\n\n/**\n * Serialize SARIF output to JSON string.\n */\nexport function sarifToJson(sarif: SarifOutput): string {\n return JSON.stringify(sarif, null, 2);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sarif.js","names":["RULE_METADATA: Record<\n string,\n { name: string; description: string; helpUri?: string }\n>","rule: SarifRule","results: SarifResult[]","sarifResult: SarifResult","location: SarifLocation","versionControlProvenance: SarifVersionControl[]","run: SarifRun"],"sources":["../../src/formatters/sarif.ts"],"sourcesContent":["/**\n * SARIF output formatter.\n *\n * Formats CI check results as SARIF (Static Analysis Results Interchange Format)\n * for integration with GitHub Code Scanning and other security tools.\n *\n * SARIF Specification: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n */\n\nimport type {\n CICheckResult,\n CIIssue,\n CIIssueSeverity,\n} from '../services/ci-check/types';\n\n/**\n * SARIF v2.1.0 output structure.\n */\nexport interface SarifOutput {\n $schema: string;\n version: string;\n runs: SarifRun[];\n}\n\ninterface SarifRun {\n tool: {\n driver: {\n name: string;\n version: string;\n informationUri: string;\n rules: SarifRule[];\n };\n };\n results: SarifResult[];\n invocations: SarifInvocation[];\n versionControlProvenance?: SarifVersionControl[];\n}\n\ninterface SarifRule {\n id: string;\n name: string;\n shortDescription: { text: string };\n fullDescription?: { text: string };\n defaultConfiguration: {\n level: 'error' | 'warning' | 'note' | 'none';\n };\n helpUri?: string;\n}\n\ninterface SarifResult {\n ruleId: string;\n ruleIndex: number;\n level: 'error' | 'warning' | 'note' | 'none';\n message: { text: string };\n locations?: SarifLocation[];\n partialFingerprints?: Record<string, string>;\n}\n\ninterface SarifLocation {\n physicalLocation: {\n artifactLocation: {\n uri: string;\n uriBaseId?: string;\n };\n region?: {\n startLine?: number;\n startColumn?: number;\n endLine?: number;\n endColumn?: number;\n };\n };\n}\n\ninterface SarifInvocation {\n executionSuccessful: boolean;\n endTimeUtc: string;\n workingDirectory?: { uri: string };\n}\n\ninterface SarifVersionControl {\n repositoryUri?: string;\n revisionId?: string;\n branch?: string;\n}\n\n/**\n * Options for SARIF formatting.\n */\nexport interface SarifFormatOptions {\n /** Tool name. */\n toolName?: string;\n /** Tool version. */\n toolVersion?: string;\n /** Tool information URI. */\n toolUri?: string;\n /** Repository URI for version control provenance. */\n repositoryUri?: string;\n /** Working directory. */\n workingDirectory?: string;\n}\n\n/**\n * Map of rule IDs to their metadata.\n */\nconst RULE_METADATA: Record<\n string,\n { name: string; description: string; helpUri?: string }\n> = {\n 'spec-structure-error': {\n name: 'Spec Structure Error',\n description:\n 'Contract specification is missing required structure elements',\n },\n 'spec-structure-warning': {\n name: 'Spec Structure Warning',\n description: 'Contract specification has recommended but missing elements',\n },\n 'integrity-orphaned': {\n name: 'Orphaned Spec',\n description: 'Contract specification is not linked to any feature',\n },\n 'integrity-unresolved-ref': {\n name: 'Unresolved Reference',\n description: 'Contract specification references a non-existent spec',\n },\n 'integrity-missing-feature': {\n name: 'Missing Feature',\n description: 'Feature referenced by spec does not exist',\n },\n 'integrity-broken-link': {\n name: 'Broken Link',\n description: 'Link between specs is broken',\n },\n 'deps-circular': {\n name: 'Circular Dependency',\n description: 'Circular dependency detected between contracts',\n },\n 'deps-missing': {\n name: 'Missing Dependency',\n description: 'Contract depends on a non-existent contract',\n },\n 'handler-missing': {\n name: 'Missing Handler',\n description: 'Handler implementation file does not exist for this contract',\n },\n 'handler-warning': {\n name: 'Handler Warning',\n description: 'Handler implementation has potential issues',\n },\n 'test-missing': {\n name: 'Missing Test',\n description: 'Test file does not exist for this contract',\n },\n 'test-warning': {\n name: 'Test Warning',\n description: 'Test implementation has potential issues',\n },\n};\n\n/**\n * Format CI check results as SARIF.\n */\nexport function formatAsSarif(\n result: CICheckResult,\n options: SarifFormatOptions = {}\n): SarifOutput {\n const {\n toolName = 'ContractSpec',\n toolVersion = '1.0.0',\n toolUri = 'https://contractspec.io',\n repositoryUri,\n workingDirectory,\n } = options;\n\n // Collect unique rules from issues (only from issues with files)\n const ruleMap = new Map<string, SarifRule>();\n const ruleIndexMap = new Map<string, number>();\n\n // Only collect rules from issues that have files (these are the ones that will be in results)\n const issuesWithFiles = result.issues.filter((issue) => issue.file);\n\n for (const issue of issuesWithFiles) {\n if (!ruleMap.has(issue.ruleId)) {\n const metadata = RULE_METADATA[issue.ruleId] ?? {\n name: issue.ruleId,\n description: `Rule: ${issue.ruleId}`,\n };\n\n const rule: SarifRule = {\n id: issue.ruleId,\n name: metadata.name,\n shortDescription: { text: metadata.description },\n defaultConfiguration: {\n level: mapSeverityToLevel(issue.severity),\n },\n };\n\n if (metadata.helpUri) {\n rule.helpUri = metadata.helpUri;\n }\n\n ruleIndexMap.set(issue.ruleId, ruleMap.size);\n ruleMap.set(issue.ruleId, rule);\n }\n }\n\n // Convert issues to SARIF results (only issues with file locations)\n // GitHub Code Scanning requires every result to have at least one location\n const results: SarifResult[] = issuesWithFiles.map((issue) => {\n const sarifResult: SarifResult = {\n ruleId: issue.ruleId,\n ruleIndex: ruleIndexMap.get(issue.ruleId) ?? 0,\n level: mapSeverityToLevel(issue.severity),\n message: { text: issue.message },\n };\n\n // issue.file is guaranteed to be defined due to the filter above\n const location: SarifLocation = {\n physicalLocation: {\n artifactLocation: {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n uri: normalizeUri(issue.file!),\n uriBaseId: '%SRCROOT%',\n },\n },\n };\n\n if (issue.line !== undefined) {\n location.physicalLocation.region = {\n startLine: issue.line,\n startColumn: issue.column ?? 1,\n endLine: issue.endLine ?? issue.line,\n endColumn: issue.endColumn,\n };\n }\n\n sarifResult.locations = [location];\n\n // Add fingerprint for deduplication\n sarifResult.partialFingerprints = {\n primaryLocationLineHash: createFingerprint(issue),\n };\n\n return sarifResult;\n });\n\n // Build version control provenance (only if repositoryUri is provided, as it's required by SARIF schema)\n const versionControlProvenance: SarifVersionControl[] = [];\n if (repositoryUri) {\n versionControlProvenance.push({\n repositoryUri,\n revisionId: result.commitSha,\n branch: result.branch,\n });\n }\n\n const run: SarifRun = {\n tool: {\n driver: {\n name: toolName,\n version: toolVersion,\n informationUri: toolUri,\n rules: Array.from(ruleMap.values()),\n },\n },\n results,\n invocations: [\n {\n executionSuccessful: result.success,\n endTimeUtc: result.timestamp,\n ...(workingDirectory && {\n workingDirectory: { uri: workingDirectory },\n }),\n },\n ],\n };\n\n if (versionControlProvenance.length > 0) {\n run.versionControlProvenance = versionControlProvenance;\n }\n\n return {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [run],\n };\n}\n\n/**\n * Map CI severity to SARIF level.\n */\nfunction mapSeverityToLevel(\n severity: CIIssueSeverity\n): 'error' | 'warning' | 'note' {\n switch (severity) {\n case 'error':\n return 'error';\n case 'warning':\n return 'warning';\n case 'note':\n return 'note';\n default:\n return 'warning';\n }\n}\n\n/**\n * Normalize file path to SARIF URI format.\n */\nfunction normalizeUri(filePath: string): string {\n // Remove leading ./ and normalize path separators\n return filePath.replace(/^\\.\\//, '').replace(/\\\\/g, '/');\n}\n\n/**\n * Create a fingerprint for issue deduplication.\n */\nfunction createFingerprint(issue: CIIssue): string {\n const parts = [issue.ruleId, issue.file ?? '', issue.message];\n return Buffer.from(parts.join('|')).toString('base64').slice(0, 16);\n}\n\n/**\n * Serialize SARIF output to JSON string.\n */\nexport function sarifToJson(sarif: SarifOutput): string {\n return JSON.stringify(sarif, null, 2);\n}\n"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
function generateContractsrcConfig(options) {
|
|
8
8
|
const isPackageLevel = options.isMonorepo && options.scope === "package";
|
|
9
9
|
return {
|
|
10
|
-
$schema: "https://api.contractspec.
|
|
10
|
+
$schema: "https://api.contractspec.io/schemas/contractsrc.json",
|
|
11
11
|
aiProvider: "claude",
|
|
12
12
|
aiModel: "claude-sonnet-4-20250514",
|
|
13
13
|
agentMode: "claude-code",
|
|
@@ -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.lssm.tech/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, ... },\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 // 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, ... },\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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lssm/bundle.contractspec-workspace",
|
|
3
|
-
"version": "1.42.
|
|
3
|
+
"version": "1.42.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,20 +28,20 @@
|
|
|
28
28
|
"@ai-sdk/mistral": "3.0.1",
|
|
29
29
|
"@ai-sdk/openai": "3.0.1",
|
|
30
30
|
"ollama-ai-provider": "^1.2.0",
|
|
31
|
-
"@lssm/module.contractspec-workspace": "1.42.
|
|
32
|
-
"@lssm/lib.contracts": "1.42.
|
|
33
|
-
"@lssm/lib.contracts-transformers": "1.42.
|
|
34
|
-
"@lssm/lib.ai-providers": "1.42.
|
|
35
|
-
"@lssm/lib.schema": "1.42.
|
|
36
|
-
"@lssm/lib.testing": "1.42.
|
|
31
|
+
"@lssm/module.contractspec-workspace": "1.42.9",
|
|
32
|
+
"@lssm/lib.contracts": "1.42.9",
|
|
33
|
+
"@lssm/lib.contracts-transformers": "1.42.9",
|
|
34
|
+
"@lssm/lib.ai-providers": "1.42.9",
|
|
35
|
+
"@lssm/lib.schema": "1.42.9",
|
|
36
|
+
"@lssm/lib.testing": "1.42.9",
|
|
37
37
|
"ai": "6.0.3",
|
|
38
38
|
"zod": "^4.1.13",
|
|
39
39
|
"glob": "^13.0.0",
|
|
40
40
|
"chokidar": "^5.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@lssm/tool.tsdown": "1.42.
|
|
44
|
-
"@lssm/tool.typescript": "1.42.
|
|
43
|
+
"@lssm/tool.tsdown": "1.42.9",
|
|
44
|
+
"@lssm/tool.typescript": "1.42.9",
|
|
45
45
|
"@types/node": "^22.10.2",
|
|
46
46
|
"tsdown": "^0.18.3",
|
|
47
47
|
"typescript": "^5.9.3"
|