@contractspec/module.workspace 1.45.0 → 1.45.2

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.
@@ -44,7 +44,7 @@ function validateOperationSpec(code, errors, warnings, rulesConfig) {
44
44
  if (!code.includes("io:")) errors.push("Missing io section");
45
45
  if (!code.includes("policy:")) errors.push("Missing policy section");
46
46
  if (!code.match(/key:\s*['"][^'"]+['"]/)) errors.push("Missing or invalid key field");
47
- if (!code.match(/version:\s*\d+/)) errors.push("Missing or invalid version field");
47
+ if (!code.match(/version:\s*(?:\d+|['"][^'"]+['"])/)) errors.push("Missing or invalid version field");
48
48
  const hasDefineCommand = /defineCommand\s*\(/.test(code);
49
49
  const hasDefineQuery = /defineQuery\s*\(/.test(code);
50
50
  const hasExplicitKind = /kind:\s*['"](?:command|query)['"]/.test(code);
@@ -77,7 +77,7 @@ function validateAppConfigSpec(code, errors, warnings, rulesConfig) {
77
77
  function validateEventSpec(code, errors, warnings, rulesConfig) {
78
78
  if (!code.includes("defineEvent")) errors.push("Missing defineEvent call");
79
79
  if (!code.match(/key:\s*['"][^'"]+['"]/)) errors.push("Missing or invalid key field");
80
- if (!code.match(/version:\s*\d+/)) errors.push("Missing or invalid version field");
80
+ if (!code.match(/version:\s*(?:\d+|['"][^'"]+['"])/)) errors.push("Missing or invalid version field");
81
81
  if (!code.includes("payload:")) errors.push("Missing payload field");
82
82
  const nameMatch = code.match(/name:\s*['"]([^'"]+)['"]/);
83
83
  if (nameMatch?.[1]) {
@@ -108,7 +108,7 @@ function validateMigrationSpec(code, errors, warnings, rulesConfig) {
108
108
  if (!code.includes("plan:")) errors.push("Missing plan section");
109
109
  else if (!code.includes("up:")) errors.push("Migration must define at least one up step");
110
110
  if (!code.match(/name:\s*['"][^'"]+['"]/)) errors.push("Missing or invalid migration name");
111
- if (!code.match(/version:\s*\d+/)) errors.push("Missing or invalid migration version");
111
+ if (!code.match(/version:\s*(?:\d+|['"][^'"]+['"])/)) errors.push("Missing or invalid migration version");
112
112
  if (code.includes("TODO")) emitRule("no-todo", "migration", "Contains TODO items that need completion", errors, warnings, rulesConfig);
113
113
  }
114
114
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"spec-structure.js","names":["DEFAULT_RULES_CONFIG: RulesConfig","errors: string[]","warnings: string[]"],"sources":["../../../src/analysis/validate/spec-structure.ts"],"sourcesContent":["/**\n * Spec structure validation utilities.\n * Extracted from cli-contractspec/src/commands/validate/spec-checker.ts\n */\n\nimport type { ValidationResult } from '../../types/analysis-types';\n\nexport type { ValidationResult };\n\n/**\n * Rule severity level for lint rules.\n */\nexport type RuleSeverity = 'off' | 'warn' | 'error';\n\n/**\n * Spec kind for rule overrides mapping.\n */\nexport type SpecKind =\n | 'operation'\n | 'event'\n | 'presentation'\n | 'feature'\n | 'workflow'\n | 'data-view'\n | 'migration'\n | 'telemetry'\n | 'experiment'\n | 'app-config';\n\n/**\n * Interface for resolving rule severity.\n */\nexport interface RulesConfig {\n /**\n * Get the severity for a rule, considering spec kind overrides.\n * Returns 'warn' by default if not configured.\n */\n getRule(ruleName: string, specKind: SpecKind): RuleSeverity;\n}\n\n/**\n * Default rules config that returns 'warn' for all rules.\n */\nconst DEFAULT_RULES_CONFIG: RulesConfig = {\n getRule: () => 'warn',\n};\n\n/**\n * Validate spec structure based on source code and filename.\n */\nexport function validateSpecStructure(\n code: string,\n fileName: string,\n rulesConfig: RulesConfig = DEFAULT_RULES_CONFIG\n): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check for required exports (any export is sufficient for validity check)\n const hasExport = /export\\s/.test(code);\n if (!hasExport) {\n errors.push('No exported spec found');\n }\n\n // Validate operation specs\n if (\n fileName.includes('.contracts.') ||\n fileName.includes('.contract.') ||\n fileName.includes('.operations.') ||\n fileName.includes('.operation.')\n ) {\n validateOperationSpec(code, errors, warnings, rulesConfig);\n }\n\n // Validate event specs\n if (fileName.includes('.event.')) {\n validateEventSpec(code, errors, warnings, rulesConfig);\n }\n\n // Validate presentation specs\n if (fileName.includes('.presentation.')) {\n validatePresentationSpec(code, errors, warnings);\n }\n\n if (fileName.includes('.workflow.')) {\n validateWorkflowSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.data-view.')) {\n validateDataViewSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.migration.')) {\n validateMigrationSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.telemetry.')) {\n validateTelemetrySpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.experiment.')) {\n validateExperimentSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.app-config.')) {\n validateAppConfigSpec(code, errors, warnings, rulesConfig);\n }\n\n // Common validations\n validateCommonFields(code, fileName, errors, warnings, rulesConfig);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Helper to emit a message based on rule severity.\n */\nfunction emitRule(\n ruleName: string,\n specKind: SpecKind,\n message: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n): void {\n const severity = rulesConfig.getRule(ruleName, specKind);\n if (severity === 'off') return;\n if (severity === 'error') {\n errors.push(message);\n } else {\n warnings.push(message);\n }\n}\n\n/**\n * Validate operation spec\n */\nfunction validateOperationSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n // Check for defineCommand or defineQuery\n const hasDefine = /define(Command|Query)/.test(code);\n if (!hasDefine) {\n errors.push('Missing defineCommand or defineQuery call');\n }\n\n // Check for required meta fields\n if (!code.includes('meta:')) {\n errors.push('Missing meta section');\n }\n\n if (!code.includes('io:')) {\n errors.push('Missing io section');\n }\n\n if (!code.includes('policy:')) {\n errors.push('Missing policy section');\n }\n\n // Check for name\n if (!code.match(/key:\\s*['\"][^'\"]+['\"]/)) {\n errors.push('Missing or invalid key field');\n }\n\n // Check for version\n if (!code.match(/version:\\s*\\d+/)) {\n errors.push('Missing or invalid version field');\n }\n\n // Check for kind (defineCommand/defineQuery set it automatically, or explicit kind field)\n const hasDefineCommand = /defineCommand\\s*\\(/.test(code);\n const hasDefineQuery = /defineQuery\\s*\\(/.test(code);\n const hasExplicitKind = /kind:\\s*['\"](?:command|query)['\"]/.test(code);\n if (!hasDefineCommand && !hasDefineQuery && !hasExplicitKind) {\n errors.push(\n 'Missing kind: use defineCommand(), defineQuery(), or explicit kind field'\n );\n }\n\n // Configurable warnings\n if (!code.includes('acceptance:')) {\n emitRule(\n 'require-acceptance',\n 'operation',\n 'No acceptance scenarios defined',\n errors,\n warnings,\n rulesConfig\n );\n }\n\n if (!code.includes('examples:')) {\n emitRule(\n 'require-examples',\n 'operation',\n 'No examples provided',\n errors,\n warnings,\n rulesConfig\n );\n }\n\n if (code.includes('TODO')) {\n emitRule(\n 'no-todo',\n 'operation',\n 'Contains TODO items that need completion',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateTelemetrySpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*TelemetrySpec\\s*=/)) {\n errors.push('Missing TelemetrySpec type annotation');\n }\n\n if (!code.match(/meta:\\s*{[\\s\\S]*name:/)) {\n errors.push('TelemetrySpec.meta is required');\n }\n\n if (!code.includes('events:')) {\n errors.push('TelemetrySpec must declare events');\n }\n\n if (!code.match(/privacy:\\s*'(public|internal|pii|sensitive)'/)) {\n emitRule(\n 'telemetry-privacy',\n 'telemetry',\n 'No explicit privacy classification found',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateExperimentSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*ExperimentSpec\\s*=/)) {\n errors.push('Missing ExperimentSpec type annotation');\n }\n if (!code.includes('controlVariant')) {\n errors.push('ExperimentSpec must declare controlVariant');\n }\n if (!code.includes('variants:')) {\n errors.push('ExperimentSpec must declare variants');\n }\n if (!code.match(/allocation:\\s*{/)) {\n emitRule(\n 'experiment-allocation',\n 'experiment',\n 'ExperimentSpec missing allocation configuration',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateAppConfigSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*AppBlueprintSpec\\s*=/)) {\n errors.push('Missing AppBlueprintSpec type annotation');\n }\n if (!code.includes('meta:')) {\n errors.push('AppBlueprintSpec must define meta');\n }\n if (!code.includes('appId')) {\n emitRule(\n 'app-config-appid',\n 'app-config',\n 'AppBlueprint meta missing appId assignment',\n errors,\n warnings,\n rulesConfig\n );\n }\n if (!code.includes('capabilities')) {\n emitRule(\n 'app-config-capabilities',\n 'app-config',\n 'App blueprint spec does not declare capabilities',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\n/**\n * Validate event spec\n */\nfunction validateEventSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.includes('defineEvent')) {\n errors.push('Missing defineEvent call');\n }\n\n if (!code.match(/key:\\s*['\"][^'\"]+['\"]/)) {\n errors.push('Missing or invalid key field');\n }\n\n if (!code.match(/version:\\s*\\d+/)) {\n errors.push('Missing or invalid version field');\n }\n\n if (!code.includes('payload:')) {\n errors.push('Missing payload field');\n }\n\n // Check for past tense naming convention\n const nameMatch = code.match(/name:\\s*['\"]([^'\"]+)['\"]/);\n if (nameMatch?.[1]) {\n const eventName = nameMatch[1].split('.').pop() ?? '';\n if (!eventName.match(/(ed|created|updated|deleted|completed)$/i)) {\n emitRule(\n 'event-past-tense',\n 'event',\n 'Event name should use past tense (e.g., \"created\", \"updated\")',\n errors,\n warnings,\n rulesConfig\n );\n }\n }\n}\n\n/**\n * Validate presentation spec (V2 format)\n */\nfunction validatePresentationSpec(\n code: string,\n errors: string[],\n _warnings: string[]\n) {\n if (!code.match(/:\\s*PresentationSpec\\s*=/)) {\n errors.push('Missing PresentationSpec type annotation');\n }\n\n if (!code.includes('meta:')) {\n errors.push('Missing meta section');\n }\n\n if (!code.includes('source:')) {\n errors.push('Missing source section');\n }\n\n if (!code.match(/type:\\s*['\"](?:component|blocknotejs)['\"]/)) {\n errors.push('Missing or invalid source.type field');\n }\n\n if (!code.includes('targets:')) {\n errors.push('Missing targets section');\n }\n}\n\nfunction validateWorkflowSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*WorkflowSpec\\s*=/)) {\n errors.push('Missing WorkflowSpec type annotation');\n }\n\n if (!code.includes('definition:')) {\n errors.push('Missing definition section');\n }\n\n if (!code.includes('steps:')) {\n errors.push('Workflow must declare steps');\n }\n\n if (!code.includes('transitions:')) {\n emitRule(\n 'workflow-transitions',\n 'workflow',\n 'No transitions declared; workflow will complete after first step.',\n errors,\n warnings,\n rulesConfig\n );\n }\n\n if (!code.match(/title:\\s*['\"][^'\"]+['\"]/)) {\n warnings.push('Missing workflow title');\n }\n\n if (!code.match(/domain:\\s*['\"][^'\"]+['\"]/)) {\n warnings.push('Missing domain field');\n }\n\n if (code.includes('TODO')) {\n emitRule(\n 'no-todo',\n 'workflow',\n 'Contains TODO items that need completion',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateMigrationSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*MigrationSpec\\s*=/)) {\n errors.push('Missing MigrationSpec type annotation');\n }\n\n if (!code.includes('plan:')) {\n errors.push('Missing plan section');\n } else {\n if (!code.includes('up:')) {\n errors.push('Migration must define at least one up step');\n }\n }\n\n if (!code.match(/name:\\s*['\"][^'\"]+['\"]/)) {\n errors.push('Missing or invalid migration name');\n }\n\n if (!code.match(/version:\\s*\\d+/)) {\n errors.push('Missing or invalid migration version');\n }\n\n if (code.includes('TODO')) {\n emitRule(\n 'no-todo',\n 'migration',\n 'Contains TODO items that need completion',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\n/**\n * Validate common fields across all spec types\n */\nfunction validateCommonFields(\n code: string,\n fileName: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n // Skip import checks for internal library files that define the types\n const isInternalLib =\n fileName.includes('/libs/contracts/') ||\n fileName.includes('/libs/contracts-transformers/') ||\n fileName.includes('/libs/schema/');\n\n // Check for SchemaModel import (skip for internal schema lib)\n if (\n code.includes('SchemaModel') &&\n !/from\\s+['\"]@contractspec\\/lib\\.schema(\\/[^'\"]+)?['\"]/.test(code) &&\n !isInternalLib\n ) {\n errors.push('Missing import for SchemaModel from @contractspec/lib.schema');\n }\n\n // Check for contracts import only if spec types are used\n // Skip for files that define the types themselves (inside lib.contracts)\n const usesSpecTypes =\n code.includes(': OperationSpec') ||\n code.includes(': PresentationSpec') ||\n code.includes(': EventSpec') ||\n code.includes(': FeatureSpec') ||\n code.includes(': WorkflowSpec') ||\n code.includes(': DataViewSpec') ||\n code.includes(': MigrationSpec') ||\n code.includes(': TelemetrySpec') ||\n code.includes(': ExperimentSpec') ||\n code.includes(': AppBlueprintSpec') ||\n code.includes('defineCommand(') ||\n code.includes('defineQuery(') ||\n code.includes('defineEvent(');\n\n if (\n usesSpecTypes &&\n !/from\\s+['\"]@contractspec\\/lib\\.contracts(\\/[^'\"]+)?['\"]/.test(code) &&\n !isInternalLib\n ) {\n errors.push('Missing import from @contractspec/lib.contracts');\n }\n\n // Check owners format\n const ownersMatch = code.match(/owners:\\s*\\[(.*?)\\]/s);\n if (ownersMatch?.[1]) {\n const ownersContent = ownersMatch[1];\n // Allow @ mentions, OwnersEnum usage, or other constants (CAPS/PascalCase)\n if (\n !ownersContent.includes('@') &&\n !ownersContent.includes('Enum') &&\n !ownersContent.match(/[A-Z][a-zA-Z0-9_]+/)\n ) {\n emitRule(\n 'require-owners-format',\n 'operation',\n 'Owners should start with @ or use an Enum/Constant',\n errors,\n warnings,\n rulesConfig\n );\n }\n }\n\n // Check for stability\n // Allow standard string literals, Enum usage (e.g. StabilityEnum.Beta), or Constants\n if (\n !code.match(\n /stability:\\s*(?:['\"](?:experimental|beta|stable|deprecated)['\"]|[A-Z][a-zA-Z0-9_]+(?:\\.[a-zA-Z0-9_]+)?)/\n )\n ) {\n emitRule(\n 'require-stability',\n 'operation',\n 'Missing or invalid stability field',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateDataViewSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*DataViewSpec\\s*=/)) {\n errors.push('Missing DataViewSpec type annotation');\n }\n if (!code.includes('meta:')) {\n errors.push('Missing meta section');\n }\n if (!code.includes('source:')) {\n errors.push('Missing source section');\n }\n if (!code.includes('view:')) {\n errors.push('Missing view section');\n }\n if (!code.match(/kind:\\s*['\"](list|table|detail|grid)['\"]/)) {\n errors.push('Missing or invalid view.kind (list/table/detail/grid)');\n }\n if (!code.match(/fields:\\s*\\[/)) {\n emitRule(\n 'data-view-fields',\n 'data-view',\n 'No fields defined for data view',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"spec-structure.js","names":["DEFAULT_RULES_CONFIG: RulesConfig","errors: string[]","warnings: string[]"],"sources":["../../../src/analysis/validate/spec-structure.ts"],"sourcesContent":["/**\n * Spec structure validation utilities.\n * Extracted from cli-contractspec/src/commands/validate/spec-checker.ts\n */\n\nimport type { ValidationResult } from '../../types/analysis-types';\n\nexport type { ValidationResult };\n\n/**\n * Rule severity level for lint rules.\n */\nexport type RuleSeverity = 'off' | 'warn' | 'error';\n\n/**\n * Spec kind for rule overrides mapping.\n */\nexport type SpecKind =\n | 'operation'\n | 'event'\n | 'presentation'\n | 'feature'\n | 'workflow'\n | 'data-view'\n | 'migration'\n | 'telemetry'\n | 'experiment'\n | 'app-config';\n\n/**\n * Interface for resolving rule severity.\n */\nexport interface RulesConfig {\n /**\n * Get the severity for a rule, considering spec kind overrides.\n * Returns 'warn' by default if not configured.\n */\n getRule(ruleName: string, specKind: SpecKind): RuleSeverity;\n}\n\n/**\n * Default rules config that returns 'warn' for all rules.\n */\nconst DEFAULT_RULES_CONFIG: RulesConfig = {\n getRule: () => 'warn',\n};\n\n/**\n * Validate spec structure based on source code and filename.\n */\nexport function validateSpecStructure(\n code: string,\n fileName: string,\n rulesConfig: RulesConfig = DEFAULT_RULES_CONFIG\n): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check for required exports (any export is sufficient for validity check)\n const hasExport = /export\\s/.test(code);\n if (!hasExport) {\n errors.push('No exported spec found');\n }\n\n // Validate operation specs\n if (\n fileName.includes('.contracts.') ||\n fileName.includes('.contract.') ||\n fileName.includes('.operations.') ||\n fileName.includes('.operation.')\n ) {\n validateOperationSpec(code, errors, warnings, rulesConfig);\n }\n\n // Validate event specs\n if (fileName.includes('.event.')) {\n validateEventSpec(code, errors, warnings, rulesConfig);\n }\n\n // Validate presentation specs\n if (fileName.includes('.presentation.')) {\n validatePresentationSpec(code, errors, warnings);\n }\n\n if (fileName.includes('.workflow.')) {\n validateWorkflowSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.data-view.')) {\n validateDataViewSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.migration.')) {\n validateMigrationSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.telemetry.')) {\n validateTelemetrySpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.experiment.')) {\n validateExperimentSpec(code, errors, warnings, rulesConfig);\n }\n\n if (fileName.includes('.app-config.')) {\n validateAppConfigSpec(code, errors, warnings, rulesConfig);\n }\n\n // Common validations\n validateCommonFields(code, fileName, errors, warnings, rulesConfig);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Helper to emit a message based on rule severity.\n */\nfunction emitRule(\n ruleName: string,\n specKind: SpecKind,\n message: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n): void {\n const severity = rulesConfig.getRule(ruleName, specKind);\n if (severity === 'off') return;\n if (severity === 'error') {\n errors.push(message);\n } else {\n warnings.push(message);\n }\n}\n\n/**\n * Validate operation spec\n */\nfunction validateOperationSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n // Check for defineCommand or defineQuery\n const hasDefine = /define(Command|Query)/.test(code);\n if (!hasDefine) {\n errors.push('Missing defineCommand or defineQuery call');\n }\n\n // Check for required meta fields\n if (!code.includes('meta:')) {\n errors.push('Missing meta section');\n }\n\n if (!code.includes('io:')) {\n errors.push('Missing io section');\n }\n\n if (!code.includes('policy:')) {\n errors.push('Missing policy section');\n }\n\n // Check for name\n if (!code.match(/key:\\s*['\"][^'\"]+['\"]/)) {\n errors.push('Missing or invalid key field');\n }\n\n // Check for version\n if (!code.match(/version:\\s*(?:\\d+|['\"][^'\"]+['\"])/)) {\n errors.push('Missing or invalid version field');\n }\n\n // Check for kind (defineCommand/defineQuery set it automatically, or explicit kind field)\n const hasDefineCommand = /defineCommand\\s*\\(/.test(code);\n const hasDefineQuery = /defineQuery\\s*\\(/.test(code);\n const hasExplicitKind = /kind:\\s*['\"](?:command|query)['\"]/.test(code);\n if (!hasDefineCommand && !hasDefineQuery && !hasExplicitKind) {\n errors.push(\n 'Missing kind: use defineCommand(), defineQuery(), or explicit kind field'\n );\n }\n\n // Configurable warnings\n if (!code.includes('acceptance:')) {\n emitRule(\n 'require-acceptance',\n 'operation',\n 'No acceptance scenarios defined',\n errors,\n warnings,\n rulesConfig\n );\n }\n\n if (!code.includes('examples:')) {\n emitRule(\n 'require-examples',\n 'operation',\n 'No examples provided',\n errors,\n warnings,\n rulesConfig\n );\n }\n\n if (code.includes('TODO')) {\n emitRule(\n 'no-todo',\n 'operation',\n 'Contains TODO items that need completion',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateTelemetrySpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*TelemetrySpec\\s*=/)) {\n errors.push('Missing TelemetrySpec type annotation');\n }\n\n if (!code.match(/meta:\\s*{[\\s\\S]*name:/)) {\n errors.push('TelemetrySpec.meta is required');\n }\n\n if (!code.includes('events:')) {\n errors.push('TelemetrySpec must declare events');\n }\n\n if (!code.match(/privacy:\\s*'(public|internal|pii|sensitive)'/)) {\n emitRule(\n 'telemetry-privacy',\n 'telemetry',\n 'No explicit privacy classification found',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateExperimentSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*ExperimentSpec\\s*=/)) {\n errors.push('Missing ExperimentSpec type annotation');\n }\n if (!code.includes('controlVariant')) {\n errors.push('ExperimentSpec must declare controlVariant');\n }\n if (!code.includes('variants:')) {\n errors.push('ExperimentSpec must declare variants');\n }\n if (!code.match(/allocation:\\s*{/)) {\n emitRule(\n 'experiment-allocation',\n 'experiment',\n 'ExperimentSpec missing allocation configuration',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateAppConfigSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*AppBlueprintSpec\\s*=/)) {\n errors.push('Missing AppBlueprintSpec type annotation');\n }\n if (!code.includes('meta:')) {\n errors.push('AppBlueprintSpec must define meta');\n }\n if (!code.includes('appId')) {\n emitRule(\n 'app-config-appid',\n 'app-config',\n 'AppBlueprint meta missing appId assignment',\n errors,\n warnings,\n rulesConfig\n );\n }\n if (!code.includes('capabilities')) {\n emitRule(\n 'app-config-capabilities',\n 'app-config',\n 'App blueprint spec does not declare capabilities',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\n/**\n * Validate event spec\n */\nfunction validateEventSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.includes('defineEvent')) {\n errors.push('Missing defineEvent call');\n }\n\n if (!code.match(/key:\\s*['\"][^'\"]+['\"]/)) {\n errors.push('Missing or invalid key field');\n }\n\n if (!code.match(/version:\\s*(?:\\d+|['\"][^'\"]+['\"])/)) {\n errors.push('Missing or invalid version field');\n }\n\n if (!code.includes('payload:')) {\n errors.push('Missing payload field');\n }\n\n // Check for past tense naming convention\n const nameMatch = code.match(/name:\\s*['\"]([^'\"]+)['\"]/);\n if (nameMatch?.[1]) {\n const eventName = nameMatch[1].split('.').pop() ?? '';\n if (!eventName.match(/(ed|created|updated|deleted|completed)$/i)) {\n emitRule(\n 'event-past-tense',\n 'event',\n 'Event name should use past tense (e.g., \"created\", \"updated\")',\n errors,\n warnings,\n rulesConfig\n );\n }\n }\n}\n\n/**\n * Validate presentation spec (V2 format)\n */\nfunction validatePresentationSpec(\n code: string,\n errors: string[],\n _warnings: string[]\n) {\n if (!code.match(/:\\s*PresentationSpec\\s*=/)) {\n errors.push('Missing PresentationSpec type annotation');\n }\n\n if (!code.includes('meta:')) {\n errors.push('Missing meta section');\n }\n\n if (!code.includes('source:')) {\n errors.push('Missing source section');\n }\n\n if (!code.match(/type:\\s*['\"](?:component|blocknotejs)['\"]/)) {\n errors.push('Missing or invalid source.type field');\n }\n\n if (!code.includes('targets:')) {\n errors.push('Missing targets section');\n }\n}\n\nfunction validateWorkflowSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*WorkflowSpec\\s*=/)) {\n errors.push('Missing WorkflowSpec type annotation');\n }\n\n if (!code.includes('definition:')) {\n errors.push('Missing definition section');\n }\n\n if (!code.includes('steps:')) {\n errors.push('Workflow must declare steps');\n }\n\n if (!code.includes('transitions:')) {\n emitRule(\n 'workflow-transitions',\n 'workflow',\n 'No transitions declared; workflow will complete after first step.',\n errors,\n warnings,\n rulesConfig\n );\n }\n\n if (!code.match(/title:\\s*['\"][^'\"]+['\"]/)) {\n warnings.push('Missing workflow title');\n }\n\n if (!code.match(/domain:\\s*['\"][^'\"]+['\"]/)) {\n warnings.push('Missing domain field');\n }\n\n if (code.includes('TODO')) {\n emitRule(\n 'no-todo',\n 'workflow',\n 'Contains TODO items that need completion',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateMigrationSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*MigrationSpec\\s*=/)) {\n errors.push('Missing MigrationSpec type annotation');\n }\n\n if (!code.includes('plan:')) {\n errors.push('Missing plan section');\n } else {\n if (!code.includes('up:')) {\n errors.push('Migration must define at least one up step');\n }\n }\n\n if (!code.match(/name:\\s*['\"][^'\"]+['\"]/)) {\n errors.push('Missing or invalid migration name');\n }\n\n if (!code.match(/version:\\s*(?:\\d+|['\"][^'\"]+['\"])/)) {\n errors.push('Missing or invalid migration version');\n }\n\n if (code.includes('TODO')) {\n emitRule(\n 'no-todo',\n 'migration',\n 'Contains TODO items that need completion',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\n/**\n * Validate common fields across all spec types\n */\nfunction validateCommonFields(\n code: string,\n fileName: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n // Skip import checks for internal library files that define the types\n const isInternalLib =\n fileName.includes('/libs/contracts/') ||\n fileName.includes('/libs/contracts-transformers/') ||\n fileName.includes('/libs/schema/');\n\n // Check for SchemaModel import (skip for internal schema lib)\n if (\n code.includes('SchemaModel') &&\n !/from\\s+['\"]@contractspec\\/lib\\.schema(\\/[^'\"]+)?['\"]/.test(code) &&\n !isInternalLib\n ) {\n errors.push('Missing import for SchemaModel from @contractspec/lib.schema');\n }\n\n // Check for contracts import only if spec types are used\n // Skip for files that define the types themselves (inside lib.contracts)\n const usesSpecTypes =\n code.includes(': OperationSpec') ||\n code.includes(': PresentationSpec') ||\n code.includes(': EventSpec') ||\n code.includes(': FeatureSpec') ||\n code.includes(': WorkflowSpec') ||\n code.includes(': DataViewSpec') ||\n code.includes(': MigrationSpec') ||\n code.includes(': TelemetrySpec') ||\n code.includes(': ExperimentSpec') ||\n code.includes(': AppBlueprintSpec') ||\n code.includes('defineCommand(') ||\n code.includes('defineQuery(') ||\n code.includes('defineEvent(');\n\n if (\n usesSpecTypes &&\n !/from\\s+['\"]@contractspec\\/lib\\.contracts(\\/[^'\"]+)?['\"]/.test(code) &&\n !isInternalLib\n ) {\n errors.push('Missing import from @contractspec/lib.contracts');\n }\n\n // Check owners format\n const ownersMatch = code.match(/owners:\\s*\\[(.*?)\\]/s);\n if (ownersMatch?.[1]) {\n const ownersContent = ownersMatch[1];\n // Allow @ mentions, OwnersEnum usage, or other constants (CAPS/PascalCase)\n if (\n !ownersContent.includes('@') &&\n !ownersContent.includes('Enum') &&\n !ownersContent.match(/[A-Z][a-zA-Z0-9_]+/)\n ) {\n emitRule(\n 'require-owners-format',\n 'operation',\n 'Owners should start with @ or use an Enum/Constant',\n errors,\n warnings,\n rulesConfig\n );\n }\n }\n\n // Check for stability\n // Allow standard string literals, Enum usage (e.g. StabilityEnum.Beta), or Constants\n if (\n !code.match(\n /stability:\\s*(?:['\"](?:experimental|beta|stable|deprecated)['\"]|[A-Z][a-zA-Z0-9_]+(?:\\.[a-zA-Z0-9_]+)?)/\n )\n ) {\n emitRule(\n 'require-stability',\n 'operation',\n 'Missing or invalid stability field',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n\nfunction validateDataViewSpec(\n code: string,\n errors: string[],\n warnings: string[],\n rulesConfig: RulesConfig\n) {\n if (!code.match(/:\\s*DataViewSpec\\s*=/)) {\n errors.push('Missing DataViewSpec type annotation');\n }\n if (!code.includes('meta:')) {\n errors.push('Missing meta section');\n }\n if (!code.includes('source:')) {\n errors.push('Missing source section');\n }\n if (!code.includes('view:')) {\n errors.push('Missing view section');\n }\n if (!code.match(/kind:\\s*['\"](list|table|detail|grid)['\"]/)) {\n errors.push('Missing or invalid view.kind (list/table/detail/grid)');\n }\n if (!code.match(/fields:\\s*\\[/)) {\n emitRule(\n 'data-view-fields',\n 'data-view',\n 'No fields defined for data view',\n errors,\n warnings,\n rulesConfig\n );\n }\n}\n"],"mappings":"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"}
@@ -19,7 +19,7 @@ function generateAppBlueprintSpec(data) {
19
19
  export const ${exportName}: AppBlueprintSpec = {
20
20
  meta: {
21
21
  key: '${escapeString(data.name)}',
22
- version: ${data.version},
22
+ version: '${data.version}',
23
23
  title: '${escapeString(data.title)}',
24
24
  description: '${escapeString(data.description)}',
25
25
  domain: '${escapeString(data.domain)}',
@@ -42,24 +42,25 @@ function buildMappingSection(prop, mappings) {
42
42
  if (mappings.length === 0) return "";
43
43
  return ` ${prop}: {\n${mappings.map((mapping) => ` ${mapping.slot}: {
44
44
  name: '${escapeString(mapping.name)}',
45
- ${typeof mapping.version === "number" ? `version: ${mapping.version},` : ""}
45
+ version: '${mapping.version}',
46
46
  }`).join(",\n")}\n },\n`;
47
47
  }
48
48
  function buildPolicySection(data) {
49
49
  if (data.policyRefs.length === 0) return "";
50
50
  return ` policies: [\n${data.policyRefs.map((policy) => ` {
51
- name: '${escapeString(policy.name)}'${typeof policy.version === "number" ? `,\n version: ${policy.version}` : ""}
51
+ name: '${escapeString(policy.name)}',
52
+ version: '${policy.version}',
52
53
  }`).join(",\n")}\n ],\n`;
53
54
  }
54
55
  function buildThemeSection(data) {
55
56
  if (!data.theme) return "";
56
- return ` theme: {\n${` primary: { name: '${escapeString(data.theme.name)}', version: ${data.theme.version} },\n`}${data.themeFallbacks.length > 0 ? ` fallbacks: [${data.themeFallbacks.map((theme) => `{ name: '${escapeString(theme.name)}', version: ${theme.version} }`).join(", ")}],\n` : ""} },\n`;
57
+ return ` theme: {\n${` primary: { name: '${escapeString(data.theme.name)}', version: ${data.theme.version} },\n`}${data.themeFallbacks.length > 0 ? ` fallbacks: [${data.themeFallbacks.map((theme) => `{ name: '${escapeString(theme.name)}', version: '${theme.version}' }`).join(", ")}],\n` : ""} },\n`;
57
58
  }
58
59
  function buildTelemetrySection(data) {
59
60
  if (!data.telemetry) return "";
60
61
  return ` telemetry: {
61
62
  spec: {
62
- name: '${escapeString(data.telemetry.name)}'${typeof data.telemetry.version === "number" ? `,\n version: ${data.telemetry.version}` : ""}
63
+ name: '${escapeString(data.telemetry.name)}'${data.telemetry.version !== void 0 ? `,\n version: '${data.telemetry.version}'` : ""}
63
64
  },
64
65
  },\n`;
65
66
  }
@@ -84,9 +85,9 @@ function buildRoutesSection(data) {
84
85
  route.label ? `label: '${escapeString(route.label)}'` : null,
85
86
  route.dataView ? `dataView: '${escapeString(route.dataView)}'` : null,
86
87
  route.workflow ? `workflow: '${escapeString(route.workflow)}'` : null,
87
- route.guardName ? `guard: { name: '${escapeString(route.guardName)}'${typeof route.guardVersion === "number" ? `, version: ${route.guardVersion}` : ""} }` : null,
88
+ route.guardName ? `guard: { name: '${escapeString(route.guardName)}'${route.guardVersion !== void 0 ? `, version: '${route.guardVersion}'` : ""} }` : null,
88
89
  route.featureFlag ? `featureFlag: '${escapeString(route.featureFlag)}'` : null,
89
- route.experimentName ? `experiment: { name: '${escapeString(route.experimentName)}'${typeof route.experimentVersion === "number" ? `, version: ${route.experimentVersion}` : ""} }` : null
90
+ route.experimentName ? `experiment: { name: '${escapeString(route.experimentName)}'${route.experimentVersion !== void 0 ? `, version: '${route.experimentVersion}'` : ""} }` : null
90
91
  ].filter(Boolean).join(", ")} }`;
91
92
  }).join(",\n")}\n ],\n`;
92
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"app-config.js","names":[],"sources":["../../src/templates/app-config.ts"],"sourcesContent":["import type { AppBlueprintSpecData } from '../types/spec-types';\nimport { toPascalCase } from './utils';\n\nexport function generateAppBlueprintSpec(data: AppBlueprintSpecData): string {\n const exportName =\n toPascalCase(data.name.split('.').pop() ?? 'App') + 'AppConfig';\n\n const capabilitiesSection = buildCapabilitiesSection(data);\n const featuresSection = buildFeaturesSection(data);\n const dataViewsSection = buildMappingSection('dataViews', data.dataViews);\n const workflowsSection = buildMappingSection('workflows', data.workflows);\n const policiesSection = buildPolicySection(data);\n const themeSection = buildThemeSection(data);\n const telemetrySection = buildTelemetrySection(data);\n const experimentsSection = buildExperimentsSection(data);\n const flagsSection = buildFeatureFlagsSection(data);\n const routesSection = buildRoutesSection(data);\n const notesSection = data.notes\n ? ` notes: '${escapeString(data.notes)}',\\n`\n : '';\n\n return `import type { AppBlueprintSpec } from '@contractspec/lib.contracts/app-config';\n\nexport const ${exportName}: AppBlueprintSpec = {\n meta: {\n key: '${escapeString(data.name)}',\n version: ${data.version},\n title: '${escapeString(data.title)}',\n description: '${escapeString(data.description)}',\n domain: '${escapeString(data.domain)}',\n owners: [${data.owners.map((owner) => `'${escapeString(owner)}'`).join(', ')}],\n tags: [${data.tags.map((tag) => `'${escapeString(tag)}'`).join(', ')}],\n stability: '${data.stability}',\n appId: '${escapeString(data.appId)}',\n },\n${capabilitiesSection}${featuresSection}${dataViewsSection}${workflowsSection}${policiesSection}${themeSection}${telemetrySection}${experimentsSection}${flagsSection}${routesSection}${notesSection}};\\n`;\n}\n\nfunction buildCapabilitiesSection(data: AppBlueprintSpecData): string {\n if (\n data.capabilitiesEnabled.length === 0 &&\n data.capabilitiesDisabled.length === 0\n ) {\n return '';\n }\n const enabled =\n data.capabilitiesEnabled.length > 0\n ? ` enabled: [${data.capabilitiesEnabled.map((key) => formatCapabilityRef(key)).join(', ')}],\\n`\n : '';\n const disabled =\n data.capabilitiesDisabled.length > 0\n ? ` disabled: [${data.capabilitiesDisabled.map((key) => formatCapabilityRef(key)).join(', ')}],\\n`\n : '';\n return ` capabilities: {\\n${enabled}${disabled} },\\n`;\n}\n\nfunction buildFeaturesSection(data: AppBlueprintSpecData): string {\n if (data.featureIncludes.length === 0 && data.featureExcludes.length === 0) {\n return '';\n }\n const include =\n data.featureIncludes.length > 0\n ? ` include: [${data.featureIncludes.map((key) => `{ key: '${escapeString(key)}' }`).join(', ')}],\\n`\n : '';\n const exclude =\n data.featureExcludes.length > 0\n ? ` exclude: [${data.featureExcludes.map((key) => `{ key: '${escapeString(key)}' }`).join(', ')}],\\n`\n : '';\n return ` features: {\\n${include}${exclude} },\\n`;\n}\n\nfunction buildMappingSection(\n prop: 'dataViews' | 'workflows',\n mappings: AppBlueprintSpecData['dataViews']\n): string {\n if (mappings.length === 0) return '';\n const body = mappings\n .map(\n (mapping) => ` ${mapping.slot}: {\n name: '${escapeString(mapping.name)}',\n ${typeof mapping.version === 'number' ? `version: ${mapping.version},` : ''}\n }`\n )\n .join(',\\n');\n return ` ${prop}: {\\n${body}\\n },\\n`;\n}\n\nfunction buildPolicySection(data: AppBlueprintSpecData): string {\n if (data.policyRefs.length === 0) return '';\n const entries = data.policyRefs\n .map(\n (policy) => ` {\n name: '${escapeString(policy.name)}'${typeof policy.version === 'number' ? `,\\n version: ${policy.version}` : ''}\n }`\n )\n .join(',\\n');\n return ` policies: [\\n${entries}\\n ],\\n`;\n}\n\nfunction buildThemeSection(data: AppBlueprintSpecData): string {\n if (!data.theme) return '';\n const primary = ` primary: { name: '${escapeString(data.theme.name)}', version: ${data.theme.version} },\\n`;\n const fallbacks =\n data.themeFallbacks.length > 0\n ? ` fallbacks: [${data.themeFallbacks\n .map(\n (theme) =>\n `{ name: '${escapeString(theme.name)}', version: ${theme.version} }`\n )\n .join(', ')}],\\n`\n : '';\n return ` theme: {\\n${primary}${fallbacks} },\\n`;\n}\n\nfunction buildTelemetrySection(data: AppBlueprintSpecData): string {\n if (!data.telemetry) return '';\n return ` telemetry: {\n spec: {\n name: '${escapeString(data.telemetry.name)}'${\n typeof data.telemetry.version === 'number'\n ? `,\\n version: ${data.telemetry.version}`\n : ''\n }\n },\n },\\n`;\n}\n\nfunction buildExperimentsSection(data: AppBlueprintSpecData): string {\n if (\n data.activeExperiments.length === 0 &&\n data.pausedExperiments.length === 0\n ) {\n return '';\n }\n const active =\n data.activeExperiments.length > 0\n ? ` active: [${data.activeExperiments.map((exp) => formatExperimentRef(exp)).join(', ')}],\\n`\n : '';\n const paused =\n data.pausedExperiments.length > 0\n ? ` paused: [${data.pausedExperiments.map((exp) => formatExperimentRef(exp)).join(', ')}],\\n`\n : '';\n return ` experiments: {\\n${active}${paused} },\\n`;\n}\n\nfunction buildFeatureFlagsSection(data: AppBlueprintSpecData): string {\n if (data.featureFlags.length === 0) return '';\n const flags = data.featureFlags\n .map(\n (flag) => ` {\n key: '${escapeString(flag.key)}',\n enabled: ${flag.enabled},\n ${flag.variant ? `variant: '${escapeString(flag.variant)}',` : ''}\n ${flag.description ? `description: '${escapeString(flag.description)}',` : ''}\n }`\n )\n .join(',\\n');\n return ` featureFlags: [\\n${flags}\\n ],\\n`;\n}\n\nfunction buildRoutesSection(data: AppBlueprintSpecData): string {\n if (data.routes.length === 0) return '';\n const routes = data.routes\n .map((route) => {\n const entries = [\n `path: '${escapeString(route.path)}'`,\n route.label ? `label: '${escapeString(route.label)}'` : null,\n route.dataView ? `dataView: '${escapeString(route.dataView)}'` : null,\n route.workflow ? `workflow: '${escapeString(route.workflow)}'` : null,\n route.guardName\n ? `guard: { name: '${escapeString(route.guardName)}'${\n typeof route.guardVersion === 'number'\n ? `, version: ${route.guardVersion}`\n : ''\n } }`\n : null,\n route.featureFlag\n ? `featureFlag: '${escapeString(route.featureFlag)}'`\n : null,\n route.experimentName\n ? `experiment: { name: '${escapeString(route.experimentName)}'${\n typeof route.experimentVersion === 'number'\n ? `, version: ${route.experimentVersion}`\n : ''\n } }`\n : null,\n ].filter(Boolean);\n return ` { ${entries.join(', ')} }`;\n })\n .join(',\\n');\n return ` routes: [\\n${routes}\\n ],\\n`;\n}\n\nfunction formatCapabilityRef(key: string): string {\n return `{ key: '${escapeString(key)}' }`;\n}\n\nfunction formatExperimentRef(exp: { name: string; version?: string }): string {\n const version =\n typeof exp.version === 'string' ? `, version: ${exp.version}` : '';\n return `{ name: '${escapeString(exp.name)}'${version} }`;\n}\n\nfunction escapeString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-config.js","names":[],"sources":["../../src/templates/app-config.ts"],"sourcesContent":["import type { AppBlueprintSpecData } from '../types/spec-types';\nimport { toPascalCase } from './utils';\n\nexport function generateAppBlueprintSpec(data: AppBlueprintSpecData): string {\n const exportName =\n toPascalCase(data.name.split('.').pop() ?? 'App') + 'AppConfig';\n\n const capabilitiesSection = buildCapabilitiesSection(data);\n const featuresSection = buildFeaturesSection(data);\n const dataViewsSection = buildMappingSection('dataViews', data.dataViews);\n const workflowsSection = buildMappingSection('workflows', data.workflows);\n const policiesSection = buildPolicySection(data);\n const themeSection = buildThemeSection(data);\n const telemetrySection = buildTelemetrySection(data);\n const experimentsSection = buildExperimentsSection(data);\n const flagsSection = buildFeatureFlagsSection(data);\n const routesSection = buildRoutesSection(data);\n const notesSection = data.notes\n ? ` notes: '${escapeString(data.notes)}',\\n`\n : '';\n\n return `import type { AppBlueprintSpec } from '@contractspec/lib.contracts/app-config';\n\nexport const ${exportName}: AppBlueprintSpec = {\n meta: {\n key: '${escapeString(data.name)}',\n version: '${data.version}',\n title: '${escapeString(data.title)}',\n description: '${escapeString(data.description)}',\n domain: '${escapeString(data.domain)}',\n owners: [${data.owners.map((owner) => `'${escapeString(owner)}'`).join(', ')}],\n tags: [${data.tags.map((tag) => `'${escapeString(tag)}'`).join(', ')}],\n stability: '${data.stability}',\n appId: '${escapeString(data.appId)}',\n },\n${capabilitiesSection}${featuresSection}${dataViewsSection}${workflowsSection}${policiesSection}${themeSection}${telemetrySection}${experimentsSection}${flagsSection}${routesSection}${notesSection}};\\n`;\n}\n\nfunction buildCapabilitiesSection(data: AppBlueprintSpecData): string {\n if (\n data.capabilitiesEnabled.length === 0 &&\n data.capabilitiesDisabled.length === 0\n ) {\n return '';\n }\n const enabled =\n data.capabilitiesEnabled.length > 0\n ? ` enabled: [${data.capabilitiesEnabled.map((key) => formatCapabilityRef(key)).join(', ')}],\\n`\n : '';\n const disabled =\n data.capabilitiesDisabled.length > 0\n ? ` disabled: [${data.capabilitiesDisabled.map((key) => formatCapabilityRef(key)).join(', ')}],\\n`\n : '';\n return ` capabilities: {\\n${enabled}${disabled} },\\n`;\n}\n\nfunction buildFeaturesSection(data: AppBlueprintSpecData): string {\n if (data.featureIncludes.length === 0 && data.featureExcludes.length === 0) {\n return '';\n }\n const include =\n data.featureIncludes.length > 0\n ? ` include: [${data.featureIncludes.map((key) => `{ key: '${escapeString(key)}' }`).join(', ')}],\\n`\n : '';\n const exclude =\n data.featureExcludes.length > 0\n ? ` exclude: [${data.featureExcludes.map((key) => `{ key: '${escapeString(key)}' }`).join(', ')}],\\n`\n : '';\n return ` features: {\\n${include}${exclude} },\\n`;\n}\n\nfunction buildMappingSection(\n prop: 'dataViews' | 'workflows',\n mappings: AppBlueprintSpecData['dataViews']\n): string {\n if (mappings.length === 0) return '';\n const body = mappings\n .map(\n (mapping) => ` ${mapping.slot}: {\n name: '${escapeString(mapping.name)}',\n version: '${mapping.version}',\n }`\n )\n .join(',\\n');\n return ` ${prop}: {\\n${body}\\n },\\n`;\n}\n\nfunction buildPolicySection(data: AppBlueprintSpecData): string {\n if (data.policyRefs.length === 0) return '';\n const entries = data.policyRefs\n .map(\n (policy) => ` {\n name: '${escapeString(policy.name)}',\n version: '${policy.version}',\n }`\n )\n .join(',\\n');\n return ` policies: [\\n${entries}\\n ],\\n`;\n}\n\nfunction buildThemeSection(data: AppBlueprintSpecData): string {\n if (!data.theme) return '';\n const primary = ` primary: { name: '${escapeString(data.theme.name)}', version: ${data.theme.version} },\\n`;\n const fallbacks =\n data.themeFallbacks.length > 0\n ? ` fallbacks: [${data.themeFallbacks\n .map(\n (theme) =>\n `{ name: '${escapeString(theme.name)}', version: '${theme.version}' }`\n )\n .join(', ')}],\\n`\n : '';\n return ` theme: {\\n${primary}${fallbacks} },\\n`;\n}\n\nfunction buildTelemetrySection(data: AppBlueprintSpecData): string {\n if (!data.telemetry) return '';\n return ` telemetry: {\n spec: {\n name: '${escapeString(data.telemetry.name)}'${\n data.telemetry.version !== undefined\n ? `,\\n version: '${data.telemetry.version}'`\n : ''\n }\n },\n },\\n`;\n}\n\nfunction buildExperimentsSection(data: AppBlueprintSpecData): string {\n if (\n data.activeExperiments.length === 0 &&\n data.pausedExperiments.length === 0\n ) {\n return '';\n }\n const active =\n data.activeExperiments.length > 0\n ? ` active: [${data.activeExperiments.map((exp) => formatExperimentRef(exp)).join(', ')}],\\n`\n : '';\n const paused =\n data.pausedExperiments.length > 0\n ? ` paused: [${data.pausedExperiments.map((exp) => formatExperimentRef(exp)).join(', ')}],\\n`\n : '';\n return ` experiments: {\\n${active}${paused} },\\n`;\n}\n\nfunction buildFeatureFlagsSection(data: AppBlueprintSpecData): string {\n if (data.featureFlags.length === 0) return '';\n const flags = data.featureFlags\n .map(\n (flag) => ` {\n key: '${escapeString(flag.key)}',\n enabled: ${flag.enabled},\n ${flag.variant ? `variant: '${escapeString(flag.variant)}',` : ''}\n ${flag.description ? `description: '${escapeString(flag.description)}',` : ''}\n }`\n )\n .join(',\\n');\n return ` featureFlags: [\\n${flags}\\n ],\\n`;\n}\n\nfunction buildRoutesSection(data: AppBlueprintSpecData): string {\n if (data.routes.length === 0) return '';\n const routes = data.routes\n .map((route) => {\n const entries = [\n `path: '${escapeString(route.path)}'`,\n route.label ? `label: '${escapeString(route.label)}'` : null,\n route.dataView ? `dataView: '${escapeString(route.dataView)}'` : null,\n route.workflow ? `workflow: '${escapeString(route.workflow)}'` : null,\n route.guardName\n ? `guard: { name: '${escapeString(route.guardName)}'${\n route.guardVersion !== undefined\n ? `, version: '${route.guardVersion}'`\n : ''\n } }`\n : null,\n route.featureFlag\n ? `featureFlag: '${escapeString(route.featureFlag)}'`\n : null,\n route.experimentName\n ? `experiment: { name: '${escapeString(route.experimentName)}'${\n route.experimentVersion !== undefined\n ? `, version: '${route.experimentVersion}'`\n : ''\n } }`\n : null,\n ].filter(Boolean);\n return ` { ${entries.join(', ')} }`;\n })\n .join(',\\n');\n return ` routes: [\\n${routes}\\n ],\\n`;\n}\n\nfunction formatCapabilityRef(key: string): string {\n return `{ key: '${escapeString(key)}' }`;\n}\n\nfunction formatExperimentRef(exp: { name: string; version?: string }): string {\n const version =\n typeof exp.version === 'string' ? `, version: ${exp.version}` : '';\n return `{ name: '${escapeString(exp.name)}'${version} }`;\n}\n\nfunction escapeString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n"],"mappings":"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"}
@@ -183,9 +183,9 @@ type ExperimentAllocationData = RandomAllocationData | StickyAllocationData | Ta
183
183
  interface ExperimentMetricData {
184
184
  name: string;
185
185
  eventName: string;
186
- eventVersion: number;
186
+ eventVersion: string;
187
187
  aggregation: 'count' | 'avg' | 'p75' | 'p90' | 'p95' | 'p99';
188
- target?: number;
188
+ target?: string;
189
189
  }
190
190
  interface ExperimentSpecData extends BaseSpecData {
191
191
  domain: string;
@@ -211,10 +211,10 @@ interface AppRouteConfigData {
211
211
  dataView?: string;
212
212
  workflow?: string;
213
213
  guardName?: string;
214
- guardVersion?: number;
214
+ guardVersion?: string | number;
215
215
  featureFlag?: string;
216
216
  experimentName?: string;
217
- experimentVersion?: number;
217
+ experimentVersion?: string | number;
218
218
  }
219
219
  interface AppBlueprintSpecData extends BaseSpecData {
220
220
  title: string;
@@ -331,7 +331,7 @@ interface KnowledgeSpaceSpecData extends BaseSpecData {
331
331
  category: KnowledgeCategoryData;
332
332
  retention: KnowledgeRetentionData;
333
333
  policyName?: string;
334
- policyVersion?: number;
334
+ policyVersion?: string | number;
335
335
  trustLevel: KnowledgeTrustLevel;
336
336
  automationWritable: boolean;
337
337
  embeddingModel?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/module.workspace",
3
- "version": "1.45.0",
3
+ "version": "1.45.2",
4
4
  "description": "Workspace discovery and management module",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -31,14 +31,14 @@
31
31
  "test": "bun run"
32
32
  },
33
33
  "dependencies": {
34
- "@contractspec/lib.contracts": "1.45.0",
35
- "@contractspec/lib.schema": "1.45.0",
34
+ "@contractspec/lib.contracts": "1.45.2",
35
+ "@contractspec/lib.schema": "1.45.2",
36
36
  "compare-versions": "^6.1.1",
37
37
  "zod": "^4.1.13"
38
38
  },
39
39
  "devDependencies": {
40
- "@contractspec/tool.tsdown": "1.45.0",
41
- "@contractspec/tool.typescript": "1.45.0",
40
+ "@contractspec/tool.tsdown": "1.45.2",
41
+ "@contractspec/tool.typescript": "1.45.2",
42
42
  "tsdown": "^0.18.3",
43
43
  "typescript": "^5.9.3"
44
44
  },