claude-flow-novice 2.15.2 → 2.15.3

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 (98) hide show
  1. package/.claude/hooks/cfn-BACKUP_USAGE.md +243 -243
  2. package/.claude/hooks/cfn-invoke-security-validation.sh +69 -69
  3. package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +78 -78
  4. package/.claude/hooks/cfn-post-edit.config.json +44 -44
  5. package/.claude/skills/agent-lifecycle/SKILL.md +60 -0
  6. package/.claude/skills/agent-lifecycle/execute-lifecycle-hook.sh +573 -0
  7. package/.claude/skills/agent-lifecycle/simple-audit.sh +31 -0
  8. package/.claude/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
  9. package/.claude/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
  10. package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
  11. package/.claude/skills/cfn-redis-coordination/get-context.sh +112 -112
  12. package/.claude/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
  13. package/.claude/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
  14. package/.claude/skills/cfn-transparency-middleware/test-integration.sh +161 -161
  15. package/.claude/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
  16. package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +92 -92
  17. package/.claude/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
  18. package/claude-assets/hooks/cfn-BACKUP_USAGE.md +243 -243
  19. package/claude-assets/hooks/cfn-invoke-security-validation.sh +69 -69
  20. package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +78 -78
  21. package/claude-assets/hooks/cfn-post-edit.config.json +44 -44
  22. package/claude-assets/hooks/cfn-post-execution/memory-cleanup.sh +19 -19
  23. package/claude-assets/hooks/cfn-pre-execution/memory-check.sh +19 -19
  24. package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +572 -572
  25. package/claude-assets/skills/agent-lifecycle/simple-audit.sh +30 -30
  26. package/claude-assets/skills/cfn-automatic-memory-persistence/persist-agent-output.sh +48 -48
  27. package/claude-assets/skills/cfn-automatic-memory-persistence/query-agent-history.sh +34 -34
  28. package/claude-assets/skills/cfn-deliverable-validation/confidence-calculator.sh +261 -261
  29. package/claude-assets/skills/cfn-expert-update/update-expert.sh +345 -345
  30. package/claude-assets/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
  31. package/claude-assets/skills/cfn-intervention-detector/detect-intervention.sh +110 -110
  32. package/claude-assets/skills/cfn-intervention-orchestrator/execute-intervention.sh +58 -58
  33. package/claude-assets/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
  34. package/claude-assets/skills/cfn-loop2-output-processing/process-validator-output.sh +275 -275
  35. package/claude-assets/skills/cfn-memory-management/check-memory.sh +159 -159
  36. package/claude-assets/skills/cfn-memory-management/cleanup-memory.sh +196 -196
  37. package/claude-assets/skills/cfn-node-heap-sizer/task-mode-heap-limiter.sh +325 -325
  38. package/claude-assets/skills/cfn-playbook-auto-update/auto-update-playbook.sh +85 -85
  39. package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
  40. package/claude-assets/skills/cfn-redis-coordination/get-context.sh +112 -112
  41. package/claude-assets/skills/cfn-scope-simplifier/simplify-scope.sh +67 -67
  42. package/claude-assets/skills/cfn-specialist-injection/recommend-specialist.sh +56 -56
  43. package/claude-assets/skills/cfn-standardized-error-handling/capture-agent-error.sh +86 -86
  44. package/claude-assets/skills/cfn-standardized-error-handling/test-error-handling.sh +165 -165
  45. package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +264 -264
  46. package/claude-assets/skills/cfn-task-decomposition/task-decomposer.sh +278 -278
  47. package/claude-assets/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
  48. package/claude-assets/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
  49. package/claude-assets/skills/cfn-transparency-middleware/test-integration.sh +161 -161
  50. package/claude-assets/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
  51. package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +92 -92
  52. package/claude-assets/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
  53. package/claude-assets/skills/docker-build/SKILL.md +96 -203
  54. package/claude-assets/skills/docker-build/build.sh +73 -73
  55. package/claude-assets/skills/integration/agent-handoff.sh +494 -0
  56. package/claude-assets/skills/integration/file-operations.sh +414 -0
  57. package/claude-assets/skills/workflow-codification/APPROVAL_WORKFLOW.md +806 -0
  58. package/claude-assets/skills/workflow-codification/COST_TRACKING.md +637 -0
  59. package/claude-assets/skills/workflow-codification/EDGE_CASE_TRACKING.md +404 -0
  60. package/claude-assets/skills/workflow-codification/README_PHASE4.md +457 -0
  61. package/claude-assets/skills/workflow-codification/SKILL.md +110 -0
  62. package/claude-assets/skills/workflow-codification/analyze-patterns.sh +899 -0
  63. package/claude-assets/skills/workflow-codification/approval-workflow.sh +514 -0
  64. package/claude-assets/skills/workflow-codification/generate-skill-update.sh +525 -0
  65. package/claude-assets/skills/workflow-codification/review-skill.sh +643 -0
  66. package/claude-assets/skills/workflow-codification/templates/email-notification.txt +114 -0
  67. package/claude-assets/skills/workflow-codification/templates/slack-notification.md +85 -0
  68. package/claude-assets/skills/workflow-codification/test-integration.sh +281 -0
  69. package/claude-assets/skills/workflow-codification/track-cost-savings.sh +445 -0
  70. package/claude-assets/skills/workflow-codification/track-edge-case.sh +323 -0
  71. package/dist/cli/config-manager.js +91 -109
  72. package/dist/cli/config-manager.js.map +1 -1
  73. package/dist/integration/DatabaseHandoff.js +507 -0
  74. package/dist/integration/DatabaseHandoff.js.map +1 -0
  75. package/dist/integration/StandardAdapter.js +291 -0
  76. package/dist/integration/StandardAdapter.js.map +1 -0
  77. package/dist/lib/agent-output-parser.js +518 -0
  78. package/dist/lib/agent-output-parser.js.map +1 -0
  79. package/dist/lib/agent-output-validator.js +950 -0
  80. package/dist/lib/agent-output-validator.js.map +1 -0
  81. package/dist/lib/artifact-registry.js +443 -0
  82. package/dist/lib/artifact-registry.js.map +1 -0
  83. package/dist/lib/config-validator.js +687 -0
  84. package/dist/lib/config-validator.js.map +1 -0
  85. package/dist/types/agent-output.js +44 -0
  86. package/dist/types/agent-output.js.map +1 -0
  87. package/dist/types/config.js +28 -0
  88. package/dist/types/config.js.map +1 -0
  89. package/package.json +2 -1
  90. package/scripts/artifact-cleanup.sh +392 -0
  91. package/scripts/deploy-production.sh +355 -355
  92. package/scripts/docker-playwright-fix.sh +311 -311
  93. package/scripts/docker-rebuild-all-agents.sh +127 -127
  94. package/scripts/memory-leak-prevention.sh +305 -305
  95. package/scripts/migrate-artifacts.sh +563 -0
  96. package/scripts/migrate-yaml-to-json.sh +465 -0
  97. package/scripts/run-marketing-tests.sh +42 -42
  98. package/scripts/update_paths.sh +46 -46
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/config-validator.ts"],"sourcesContent":["/**\r\n * CFN Configuration Validator\r\n * Validates JSON configurations against the CFN schema with detailed error reporting\r\n *\r\n * @version 1.0.0\r\n * @description Type-safe validation library with 95%+ accuracy\r\n */\r\n\r\nimport {\r\n CFNConfig,\r\n ValidationError,\r\n ValidationResult,\r\n EnvVarExportMap,\r\n EnvironmentVariable,\r\n ConfigLoaderOptions,\r\n} from '../types/config';\r\n\r\n/**\r\n * Core validation result from our built-in validator\r\n */\r\ninterface ValidationCheckResult {\r\n valid: boolean;\r\n errors: ValidationError[];\r\n}\r\n\r\n/**\r\n * ConfigValidator: Main validation class\r\n * Provides schema validation, error reporting, and env var export functionality\r\n */\r\nexport class ConfigValidator {\r\n private schema: Record<string, unknown>;\r\n private initialized = true;\r\n\r\n constructor(schema?: Record<string, unknown>) {\r\n if (schema) {\r\n this.schema = schema;\r\n } else {\r\n // Use the default schema embedded below\r\n this.schema = this.getDefaultSchema();\r\n }\r\n }\r\n\r\n /**\r\n * Get default schema definition\r\n */\r\n private getDefaultSchema(): Record<string, unknown> {\r\n return {\r\n $schema: 'https://json-schema.org/draft/2020-12/schema',\r\n $id: 'https://claude-flow-novice.local/schemas/cfn-config-v1.json',\r\n title: 'CFN Configuration Schema v1.0',\r\n description: 'Canonical JSON schema for all Claude Flow Novice configuration files',\r\n version: '1.0.0',\r\n type: 'object',\r\n };\r\n }\r\n\r\n /**\r\n * Main validation method using built-in validators\r\n */\r\n public validate(config: unknown): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (typeof config !== 'object' || config === null) {\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'root',\r\n message: 'Configuration must be a valid JSON object',\r\n path: '/',\r\n code: 'INVALID_TYPE',\r\n },\r\n ],\r\n warnings,\r\n configType: 'unknown',\r\n };\r\n }\r\n\r\n const configObj = config as Record<string, unknown>;\r\n const configType = this.detectConfigType(configObj);\r\n\r\n // Validate based on detected type\r\n switch (configType) {\r\n case 'agent-whitelist':\r\n return this.validateAgentWhitelist(configObj);\r\n case 'mcp-servers':\r\n return this.validateMCPServers(configObj);\r\n case 'skill-requirements':\r\n return this.validateSkillRequirements(configObj);\r\n case 'runtime-contract':\r\n return this.validateRuntimeContract(configObj);\r\n case 'team':\r\n return this.validateTeamConfig(configObj);\r\n default:\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'root',\r\n message:\r\n 'Unknown configuration type. Must include agents, servers, tools, variables, or team',\r\n path: '/',\r\n code: 'UNKNOWN_CONFIG_TYPE',\r\n },\r\n ],\r\n warnings,\r\n configType: 'unknown',\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Validate JSON string\r\n */\r\n public validateJSON(jsonString: string): ValidationResult {\r\n try {\r\n const config = JSON.parse(jsonString);\r\n return this.validate(config);\r\n } catch (error) {\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'json',\r\n message: `Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`,\r\n path: 'root',\r\n code: 'JSON_PARSE_ERROR',\r\n },\r\n ],\r\n warnings: [],\r\n configType: 'unknown',\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Validate Agent Whitelist Configuration\r\n */\r\n private validateAgentWhitelist(config: Record<string, unknown>): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n // Check version\r\n if (!config.version || typeof config.version !== 'string') {\r\n errors.push({\r\n field: 'version',\r\n message: 'Missing required field: version (string)',\r\n path: '/version',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n } else if (!/^\\d+\\.\\d+\\.\\d+$/.test(config.version)) {\r\n errors.push({\r\n field: 'version',\r\n message: 'Invalid version format. Expected X.Y.Z format',\r\n path: '/version',\r\n value: config.version,\r\n code: 'INVALID_FORMAT',\r\n });\r\n }\r\n\r\n // Check agents array\r\n if (!Array.isArray(config.agents)) {\r\n errors.push({\r\n field: 'agents',\r\n message: 'Missing required field: agents (array)',\r\n path: '/agents',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n } else {\r\n for (let i = 0; i < (config.agents as unknown[]).length; i++) {\r\n const agent = (config.agents as Record<string, unknown>[])[i];\r\n if (!agent.type || typeof agent.type !== 'string' || agent.type.length === 0) {\r\n errors.push({\r\n field: `agents[${i}].type`,\r\n message: 'Agent type is required and must be non-empty string',\r\n path: `/agents/${i}/type`,\r\n code: 'INVALID_AGENT',\r\n });\r\n }\r\n if (!agent.displayName || typeof agent.displayName !== 'string') {\r\n errors.push({\r\n field: `agents[${i}].displayName`,\r\n message: 'Agent displayName is required',\r\n path: `/agents/${i}/displayName`,\r\n code: 'INVALID_AGENT',\r\n });\r\n }\r\n if (!Array.isArray(agent.skills)) {\r\n errors.push({\r\n field: `agents[${i}].skills`,\r\n message: 'Agent skills must be an array',\r\n path: `/agents/${i}/skills`,\r\n code: 'INVALID_AGENT',\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!config.lastUpdated) {\r\n warnings.push('Agent configuration missing lastUpdated field (recommended)');\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n configType: 'agent-whitelist',\r\n };\r\n }\r\n\r\n /**\r\n * Validate MCP Servers Configuration\r\n */\r\n private validateMCPServers(config: Record<string, unknown>): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n // Check version\r\n if (!config.version || typeof config.version !== 'string') {\r\n errors.push({\r\n field: 'version',\r\n message: 'Missing required field: version',\r\n path: '/version',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n }\r\n\r\n // Check servers object\r\n if (!config.servers || typeof config.servers !== 'object') {\r\n errors.push({\r\n field: 'servers',\r\n message: 'Missing required field: servers (object)',\r\n path: '/servers',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n } else {\r\n const servers = config.servers as Record<string, Record<string, unknown>>;\r\n for (const serverName in servers) {\r\n if (Object.prototype.hasOwnProperty.call(servers, serverName)) {\r\n const serverConfig = servers[serverName];\r\n if (!serverConfig.endpoint || typeof serverConfig.endpoint !== 'string') {\r\n errors.push({\r\n field: `servers.${serverName}.endpoint`,\r\n message: 'Server endpoint is required',\r\n path: `/servers/${serverName}/endpoint`,\r\n code: 'INVALID_SERVER',\r\n });\r\n } else if (!this.isValidURL(serverConfig.endpoint)) {\r\n errors.push({\r\n field: `servers.${serverName}.endpoint`,\r\n message: 'Server endpoint must be a valid URL',\r\n path: `/servers/${serverName}/endpoint`,\r\n value: serverConfig.endpoint,\r\n code: 'INVALID_URL',\r\n });\r\n }\r\n\r\n if (!Array.isArray(serverConfig.requiredSkills)) {\r\n errors.push({\r\n field: `servers.${serverName}.requiredSkills`,\r\n message: 'Server requiredSkills must be an array',\r\n path: `/servers/${serverName}/requiredSkills`,\r\n code: 'INVALID_SERVER',\r\n });\r\n }\r\n\r\n if (!serverConfig.auth || typeof serverConfig.auth !== 'object') {\r\n errors.push({\r\n field: `servers.${serverName}.auth`,\r\n message: 'Server auth is required',\r\n path: `/servers/${serverName}/auth`,\r\n code: 'INVALID_SERVER',\r\n });\r\n }\r\n\r\n if (serverConfig.timeoutMs !== undefined && typeof serverConfig.timeoutMs !== 'number') {\r\n errors.push({\r\n field: `servers.${serverName}.timeoutMs`,\r\n message: 'timeoutMs must be a number',\r\n path: `/servers/${serverName}/timeoutMs`,\r\n code: 'INVALID_TYPE',\r\n });\r\n } else if (serverConfig.timeoutMs !== undefined && (serverConfig.timeoutMs as number) < 1000) {\r\n errors.push({\r\n field: `servers.${serverName}.timeoutMs`,\r\n message: 'timeoutMs must be at least 1000ms',\r\n path: `/servers/${serverName}/timeoutMs`,\r\n value: serverConfig.timeoutMs,\r\n code: 'CONSTRAINT_VIOLATION',\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n configType: 'mcp-servers',\r\n };\r\n }\r\n\r\n /**\r\n * Validate Skill Requirements Configuration\r\n */\r\n private validateSkillRequirements(config: Record<string, unknown>): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!config.version || typeof config.version !== 'string') {\r\n errors.push({\r\n field: 'version',\r\n message: 'Missing required field: version',\r\n path: '/version',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n }\r\n\r\n if (!config.tools || typeof config.tools !== 'object') {\r\n errors.push({\r\n field: 'tools',\r\n message: 'Missing required field: tools (object)',\r\n path: '/tools',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n } else {\r\n const tools = config.tools as Record<string, Record<string, unknown>>;\r\n for (const toolName in tools) {\r\n if (Object.prototype.hasOwnProperty.call(tools, toolName)) {\r\n const toolConfig = tools[toolName];\r\n if (!toolConfig.displayName || typeof toolConfig.displayName !== 'string') {\r\n errors.push({\r\n field: `tools.${toolName}.displayName`,\r\n message: 'Tool displayName is required',\r\n path: `/tools/${toolName}/displayName`,\r\n code: 'INVALID_TOOL',\r\n });\r\n }\r\n\r\n if (!Array.isArray(toolConfig.requiredSkills) || (toolConfig.requiredSkills as unknown[]).length === 0) {\r\n errors.push({\r\n field: `tools.${toolName}.requiredSkills`,\r\n message: 'Tool requiredSkills must be a non-empty array',\r\n path: `/tools/${toolName}/requiredSkills`,\r\n code: 'INVALID_TOOL',\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n configType: 'skill-requirements',\r\n };\r\n }\r\n\r\n /**\r\n * Validate Runtime Contract Configuration\r\n */\r\n private validateRuntimeContract(config: Record<string, unknown>): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!config.version || typeof config.version !== 'string') {\r\n errors.push({\r\n field: 'version',\r\n message: 'Missing required field: version',\r\n path: '/version',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n }\r\n\r\n if (config.variables && typeof config.variables === 'object') {\r\n const variables = config.variables as Record<string, Record<string, unknown>>;\r\n for (const varName in variables) {\r\n if (Object.prototype.hasOwnProperty.call(variables, varName)) {\r\n const varConfig = variables[varName];\r\n if (!varConfig.description || typeof varConfig.description !== 'string') {\r\n errors.push({\r\n field: `variables.${varName}.description`,\r\n message: 'Variable description is required',\r\n path: `/variables/${varName}/description`,\r\n code: 'INVALID_VARIABLE',\r\n });\r\n }\r\n const varType = varConfig.type as string;\r\n const validTypes = ['string', 'integer', 'number', 'boolean'];\r\n if (!varConfig.type || validTypes.indexOf(varType) === -1) {\r\n errors.push({\r\n field: `variables.${varName}.type`,\r\n message: 'Variable type must be one of: string, integer, number, boolean',\r\n path: `/variables/${varName}/type`,\r\n code: 'INVALID_VARIABLE',\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n configType: 'runtime-contract',\r\n };\r\n }\r\n\r\n /**\r\n * Validate Team Configuration\r\n */\r\n private validateTeamConfig(config: Record<string, unknown>): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!config.team || typeof config.team !== 'object') {\r\n errors.push({\r\n field: 'team',\r\n message: 'Missing required field: team (object)',\r\n path: '/team',\r\n code: 'MISSING_REQUIRED',\r\n });\r\n return { valid: false, errors, warnings, configType: 'team' };\r\n }\r\n\r\n const team = config.team as Record<string, unknown>;\r\n\r\n if (!team.id || typeof team.id !== 'string' || team.id.length === 0) {\r\n errors.push({\r\n field: 'team.id',\r\n message: 'Team id is required and must be non-empty',\r\n path: '/team/id',\r\n code: 'INVALID_TEAM',\r\n });\r\n } else if (!/^[a-z0-9-]+$/.test(team.id as string)) {\r\n errors.push({\r\n field: 'team.id',\r\n message: 'Team id must contain only lowercase letters, numbers, and hyphens',\r\n path: '/team/id',\r\n value: team.id,\r\n code: 'INVALID_FORMAT',\r\n });\r\n }\r\n\r\n if (!team.name || typeof team.name !== 'string') {\r\n errors.push({\r\n field: 'team.name',\r\n message: 'Team name is required',\r\n path: '/team/name',\r\n code: 'INVALID_TEAM',\r\n });\r\n }\r\n\r\n // Validate workspace if present (supports both diskQuota and disk_quota)\r\n if (team.workspace && typeof team.workspace === 'object') {\r\n const workspace = team.workspace as Record<string, unknown>;\r\n const diskQuota = this.getPropertyValue(workspace, 'diskQuota');\r\n if (diskQuota !== undefined && !this.isValidDiskQuota(diskQuota)) {\r\n errors.push({\r\n field: 'team.workspace.diskQuota',\r\n message: 'Invalid disk quota format. Expected format: <number><UNIT> (e.g., 100GB)',\r\n path: '/team/workspace/diskQuota',\r\n value: diskQuota,\r\n code: 'INVALID_FORMAT',\r\n });\r\n }\r\n }\r\n\r\n // Validate resources if present (supports both camelCase and snake_case naming)\r\n if (team.resources && typeof team.resources === 'object') {\r\n const resources = team.resources as Record<string, unknown>;\r\n const cpuCores = this.getPropertyValue(resources, 'cpuCores');\r\n const maxAgents = this.getPropertyValue(resources, 'maxAgents');\r\n\r\n // Validate cpuCores (supports cpuCores and cpu_cores)\r\n if (cpuCores !== undefined) {\r\n if (typeof cpuCores !== 'number' || cpuCores < 0) {\r\n errors.push({\r\n field: 'team.resources.cpuCores',\r\n message: 'cpuCores must be a non-negative number',\r\n path: '/team/resources/cpuCores',\r\n value: cpuCores,\r\n code: 'INVALID_TYPE',\r\n });\r\n }\r\n }\r\n\r\n // Validate maxAgents (supports maxAgents and max_agents)\r\n if (maxAgents !== undefined) {\r\n if (typeof maxAgents !== 'number' || maxAgents < 1 || !Number.isInteger(maxAgents)) {\r\n errors.push({\r\n field: 'team.resources.maxAgents',\r\n message: 'maxAgents must be a positive integer',\r\n path: '/team/resources/maxAgents',\r\n value: maxAgents,\r\n code: 'INVALID_TYPE',\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Validate network if present\r\n if (team.network && typeof team.network === 'object') {\r\n const network = team.network as Record<string, unknown>;\r\n if (network.coordinatorIp && !this.isValidIPv4(network.coordinatorIp)) {\r\n errors.push({\r\n field: 'team.network.coordinatorIp',\r\n message: 'Invalid IPv4 format',\r\n path: '/team/network/coordinatorIp',\r\n value: network.coordinatorIp,\r\n code: 'INVALID_FORMAT',\r\n });\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n configType: 'team',\r\n };\r\n }\r\n\r\n /**\r\n * Detect configuration type\r\n */\r\n private detectConfigType(config: Record<string, unknown>): string {\r\n // Check for agent whitelist (has 'agents' array)\r\n if ('agents' in config && Array.isArray(config.agents)) {\r\n return 'agent-whitelist';\r\n }\r\n\r\n // Check for MCP servers (has 'servers' object)\r\n if ('servers' in config && typeof config.servers === 'object') {\r\n return 'mcp-servers';\r\n }\r\n\r\n // Check for skill requirements (has 'tools' object)\r\n if ('tools' in config && typeof config.tools === 'object') {\r\n return 'skill-requirements';\r\n }\r\n\r\n // Check for runtime contract (has 'variables' object)\r\n if ('variables' in config && typeof config.variables === 'object') {\r\n return 'runtime-contract';\r\n }\r\n\r\n // Check for team config (has 'team' object)\r\n if ('team' in config && typeof config.team === 'object') {\r\n return 'team';\r\n }\r\n\r\n return 'unknown';\r\n }\r\n\r\n /**\r\n * Export configuration as environment variables\r\n * Handles type preservation and validation\r\n */\r\n public exportEnvVars(config: unknown): EnvVarExportMap {\r\n if (typeof config !== 'object' || config === null) {\r\n throw new Error('Configuration must be an object');\r\n }\r\n\r\n const configObj = config as Record<string, unknown>;\r\n if (!('variables' in configObj)) {\r\n throw new Error('Configuration is not a valid runtime contract');\r\n }\r\n\r\n const envMap: EnvVarExportMap = {};\r\n const variables = configObj.variables;\r\n\r\n if (typeof variables !== 'object' || variables === null) {\r\n throw new Error('Variables must be an object');\r\n }\r\n\r\n const varsObj = variables as Record<string, unknown>;\r\n for (const key in varsObj) {\r\n if (Object.prototype.hasOwnProperty.call(varsObj, key)) {\r\n const variable = varsObj[key];\r\n const varObj = variable as Record<string, unknown>;\r\n if (varObj.value !== null && varObj.value !== undefined) {\r\n const varType = varObj.type as string;\r\n envMap[key] = this.coerceToCorrectType(varObj.value, varType);\r\n }\r\n }\r\n }\r\n\r\n return envMap;\r\n }\r\n\r\n /**\r\n * Coerce value to correct type without loss\r\n */\r\n private coerceToCorrectType(\r\n value: unknown,\r\n type: string\r\n ): string | number | boolean {\r\n if (type === 'integer' && typeof value === 'string') {\r\n return parseInt(value, 10);\r\n }\r\n if (type === 'number' && typeof value === 'string') {\r\n return parseFloat(value);\r\n }\r\n if (type === 'boolean' && typeof value === 'string') {\r\n return value.toLowerCase() === 'true';\r\n }\r\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\r\n return value;\r\n }\r\n return String(value);\r\n }\r\n\r\n /**\r\n * Format validation errors for display\r\n */\r\n public formatErrors(result: ValidationResult): string {\r\n if (result.valid) {\r\n return 'Configuration is valid.';\r\n }\r\n\r\n let output = `Validation failed with ${result.errors.length} error(s):\\n\\n`;\r\n\r\n for (const error of result.errors) {\r\n output += `[${error.code}] ${error.field || 'root'}\\n`;\r\n output += ` ${error.message}\\n`;\r\n if (error.value !== undefined) {\r\n output += ` Current value: ${JSON.stringify(error.value)}\\n`;\r\n }\r\n output += '\\n';\r\n }\r\n\r\n if (result.warnings.length > 0) {\r\n output += `\\nWarnings (${result.warnings.length}):\\n`;\r\n for (const warning of result.warnings) {\r\n output += ` - ${warning}\\n`;\r\n }\r\n }\r\n\r\n return output;\r\n }\r\n\r\n /**\r\n * Helper: Validate URL format\r\n */\r\n private isValidURL(url: unknown): boolean {\r\n if (typeof url !== 'string') return false;\r\n try {\r\n new URL(url);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Validate disk quota format\r\n */\r\n private isValidDiskQuota(quota: unknown): boolean {\r\n if (typeof quota !== 'string') return false;\r\n return /^\\d+[KMGTPE]B$/.test(quota);\r\n }\r\n\r\n /**\r\n * Helper: Validate IPv4 format\r\n */\r\n private isValidIPv4(ip: unknown): boolean {\r\n if (typeof ip !== 'string') return false;\r\n const ipv4Pattern = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\r\n if (!ipv4Pattern.test(ip)) return false;\r\n\r\n const parts = ip.split('.');\r\n return parts.every((part) => {\r\n const num = parseInt(part, 10);\r\n return num >= 0 && num <= 255;\r\n });\r\n }\r\n\r\n /**\r\n * Helper: Normalize field name (support both snake_case and camelCase)\r\n * Examples: disk_quota → diskQuota, cpu_cores → cpuCores, maxAgents → maxAgents\r\n */\r\n private normalizeFieldName(name: string): string {\r\n if (!name.includes('_')) return name;\r\n return name.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\r\n }\r\n\r\n /**\r\n * Helper: Get property value supporting both naming conventions\r\n * @param obj Object to search\r\n * @param field Field name in any convention (camelCase or snake_case)\r\n * @returns Value if found, undefined otherwise\r\n */\r\n private getPropertyValue(obj: Record<string, unknown>, field: string): unknown {\r\n // Try camelCase version first\r\n if (field in obj) return obj[field];\r\n\r\n // Try snake_case version\r\n const snakeCase = field.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\r\n if (snakeCase in obj) return obj[snakeCase];\r\n\r\n // Try normalizing if it's snake_case input\r\n const camelCase = this.normalizeFieldName(field);\r\n if (camelCase in obj) return obj[camelCase];\r\n\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Singleton instance for global usage\r\n */\r\nlet validatorInstance: ConfigValidator | null = null;\r\n\r\n/**\r\n * Get or create validator instance\r\n */\r\nexport function getValidator(schema?: Record<string, unknown>): ConfigValidator {\r\n if (!validatorInstance) {\r\n validatorInstance = new ConfigValidator(schema);\r\n }\r\n return validatorInstance;\r\n}\r\n\r\n/**\r\n * Validate configuration object\r\n */\r\nexport function validateConfig(config: unknown): ValidationResult {\r\n return getValidator().validate(config);\r\n}\r\n\r\n/**\r\n * Validate JSON string\r\n */\r\nexport function validateJSON(jsonString: string): ValidationResult {\r\n return getValidator().validateJSON(jsonString);\r\n}\r\n\r\n/**\r\n * Export environment variables from runtime contract\r\n */\r\nexport function exportEnvVars(config: unknown): EnvVarExportMap {\r\n return getValidator().exportEnvVars(config);\r\n}\r\n\r\n/**\r\n * Check if configuration is valid (boolean shortcut)\r\n */\r\nexport function isValidConfig(config: unknown): boolean {\r\n return getValidator().validate(config).valid;\r\n}\r\n\r\n/**\r\n * Reset validator instance (useful for testing)\r\n */\r\nexport function resetValidator(): void {\r\n validatorInstance = null;\r\n}\r\n\r\n/**\r\n * Validate multiple configuration files efficiently\r\n * @param filePaths Array of file paths to validate\r\n * @returns Map of file path to validation result\r\n * @throws Error if file cannot be read\r\n */\r\nexport function validateConfigFiles(\r\n filePaths: string[]\r\n): Record<string, ValidationResult> {\r\n const results: Record<string, ValidationResult> = {};\r\n const validator = getValidator();\r\n\r\n for (const filePath of filePaths) {\r\n try {\r\n // Dynamically import fs module to read file\r\n const fs = require('fs');\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const config = JSON.parse(content);\r\n results[filePath] = validator.validate(config);\r\n } catch (error) {\r\n results[filePath] = {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'file',\r\n message: `Failed to read or parse file: ${error instanceof Error ? error.message : String(error)}`,\r\n path: filePath,\r\n code: 'FILE_READ_ERROR',\r\n },\r\n ],\r\n warnings: [],\r\n configType: 'unknown',\r\n };\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nexport default ConfigValidator;\r\n"],"names":["ConfigValidator","schema","initialized","getDefaultSchema","$schema","$id","title","description","version","type","validate","config","errors","warnings","valid","field","message","path","code","configType","configObj","detectConfigType","validateAgentWhitelist","validateMCPServers","validateSkillRequirements","validateRuntimeContract","validateTeamConfig","validateJSON","jsonString","JSON","parse","error","Error","String","push","test","value","Array","isArray","agents","i","length","agent","displayName","skills","lastUpdated","servers","serverName","Object","prototype","hasOwnProperty","call","serverConfig","endpoint","isValidURL","requiredSkills","auth","timeoutMs","undefined","tools","toolName","toolConfig","variables","varName","varConfig","varType","validTypes","indexOf","team","id","name","workspace","diskQuota","getPropertyValue","isValidDiskQuota","resources","cpuCores","maxAgents","Number","isInteger","network","coordinatorIp","isValidIPv4","exportEnvVars","envMap","varsObj","key","variable","varObj","coerceToCorrectType","parseInt","parseFloat","toLowerCase","formatErrors","result","output","stringify","warning","url","URL","quota","ip","ipv4Pattern","parts","split","every","part","num","normalizeFieldName","includes","replace","_","letter","toUpperCase","obj","snakeCase","camelCase","validatorInstance","getValidator","validateConfig","isValidConfig","resetValidator","validateConfigFiles","filePaths","results","validator","filePath","fs","require","content","readFileSync"],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Agent Output Type Definitions
3
+ * TypeScript interfaces matching agent-output-v1.json schema
4
+ *
5
+ * @version 1.0.0
6
+ * @description Strict type-safe agent output interfaces for CFN Loop
7
+ */ // ============================================================================
8
+ // Enums and Type Aliases
9
+ // ============================================================================
10
+ // ============================================================================
11
+ // Type Guards
12
+ // ============================================================================
13
+ /**
14
+ * Type guard for Loop 3 output
15
+ */ export function isLoop3Output(output) {
16
+ return output.output_type === 'loop3';
17
+ }
18
+ /**
19
+ * Type guard for Loop 2 output
20
+ */ export function isLoop2Output(output) {
21
+ return output.output_type === 'loop2';
22
+ }
23
+ /**
24
+ * Type guard for Product Owner output
25
+ */ export function isProductOwnerOutput(output) {
26
+ return output.output_type === 'product_owner';
27
+ }
28
+ /**
29
+ * Type guard for base agent output
30
+ */ export function isValidAgentOutput(value) {
31
+ if (typeof value !== 'object' || value === null) {
32
+ return false;
33
+ }
34
+ const obj = value;
35
+ // Check required base fields
36
+ if (typeof obj.success !== 'boolean' || typeof obj.confidence !== 'number' || typeof obj.iteration !== 'number' || !Array.isArray(obj.errors) || typeof obj.metadata !== 'object' || obj.metadata === null) {
37
+ return false;
38
+ }
39
+ // Check output_type discriminator
40
+ const outputType = obj.output_type;
41
+ return outputType === 'loop3' || outputType === 'loop2' || outputType === 'product_owner';
42
+ }
43
+
44
+ //# sourceMappingURL=agent-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/agent-output.ts"],"sourcesContent":["/**\r\n * Agent Output Type Definitions\r\n * TypeScript interfaces matching agent-output-v1.json schema\r\n *\r\n * @version 1.0.0\r\n * @description Strict type-safe agent output interfaces for CFN Loop\r\n */\r\n\r\n// ============================================================================\r\n// Enums and Type Aliases\r\n// ============================================================================\r\n\r\nexport type DeliverableType =\r\n | 'implementation'\r\n | 'test'\r\n | 'documentation'\r\n | 'config'\r\n | 'schema'\r\n | 'script'\r\n | 'other';\r\n\r\nexport type DeliverableStatus =\r\n | 'created'\r\n | 'modified'\r\n | 'deleted'\r\n | 'validated'\r\n | 'pending';\r\n\r\nexport type IssueSeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';\r\n\r\nexport type IssueCategory =\r\n | 'security'\r\n | 'performance'\r\n | 'quality'\r\n | 'style'\r\n | 'documentation'\r\n | 'testing'\r\n | 'architecture'\r\n | 'other';\r\n\r\nexport type ValidationType =\r\n | 'review'\r\n | 'test'\r\n | 'security'\r\n | 'architecture'\r\n | 'performance'\r\n | 'compliance';\r\n\r\nexport type ProductOwnerDecision = 'PROCEED' | 'ITERATE' | 'ABORT';\r\n\r\nexport type AgentOutputType = 'loop3' | 'loop2' | 'product_owner';\r\n\r\nexport type CFNLoopMode = 'mvp' | 'standard' | 'enterprise';\r\n\r\n// ============================================================================\r\n// Core Interfaces\r\n// ============================================================================\r\n\r\n/**\r\n * Artifact created or modified by agent\r\n */\r\nexport interface Deliverable {\r\n /** Absolute or relative file path */\r\n path: string;\r\n /** Deliverable type */\r\n type: DeliverableType;\r\n /** Deliverable status */\r\n status: DeliverableStatus;\r\n /** File size in bytes */\r\n size_bytes?: number;\r\n /** Number of lines (for text files) */\r\n lines?: number;\r\n /** SHA-256 checksum for integrity validation */\r\n checksum?: string;\r\n}\r\n\r\n/**\r\n * Issue found during validation\r\n */\r\nexport interface Issue {\r\n /** Issue severity level */\r\n severity: IssueSeverity;\r\n /** Issue category */\r\n category: IssueCategory;\r\n /** Human-readable issue description */\r\n message: string;\r\n /** File path and line number (e.g., 'src/file.ts:45') */\r\n location?: string;\r\n /** Suggested fix or improvement */\r\n recommendation?: string;\r\n /** Error code or rule identifier */\r\n code?: string;\r\n}\r\n\r\n/**\r\n * Quantitative metrics from implementation\r\n */\r\nexport interface Metrics {\r\n /** Number of files created */\r\n files_created?: number;\r\n /** Number of files modified */\r\n files_modified?: number;\r\n /** Number of files deleted */\r\n files_deleted?: number;\r\n /** Total lines of code written */\r\n lines_of_code?: number;\r\n /** Test coverage percentage (0.0-1.0) */\r\n test_coverage?: number;\r\n /** Number of tests passed */\r\n tests_passed?: number;\r\n /** Number of tests failed */\r\n tests_failed?: number;\r\n /** Execution time in milliseconds */\r\n execution_time_ms?: number;\r\n /** Memory usage in megabytes */\r\n memory_usage_mb?: number;\r\n /** Additional custom metrics (extensible numeric values) */\r\n custom_metrics?: Record<string, number>;\r\n}\r\n\r\n/**\r\n * Error encountered during execution\r\n */\r\nexport interface AgentError {\r\n /** Error code */\r\n code: string;\r\n /** Error message */\r\n message: string;\r\n /** Stack trace (optional) */\r\n stack?: string;\r\n /** Additional error context */\r\n context?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Agent execution metadata\r\n */\r\nexport interface AgentMetadata {\r\n /** Type of agent that produced output */\r\n agent_type: string;\r\n /** Unique agent instance ID */\r\n agent_id?: string;\r\n /** Total execution time in milliseconds */\r\n execution_time_ms?: number;\r\n /** ISO 8601 timestamp */\r\n timestamp?: string;\r\n /** Swarm/task identifier */\r\n swarm_id?: string;\r\n /** CFN Loop iteration number */\r\n iteration?: number;\r\n /** CFN Loop execution mode */\r\n mode?: CFNLoopMode;\r\n /** Additional execution context */\r\n context?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Base output common to all agent types\r\n */\r\nexport interface BaseAgentOutput {\r\n /** Whether execution was successful */\r\n success: boolean;\r\n /** Confidence score (0.0-1.0) */\r\n confidence: number;\r\n /** CFN Loop iteration number */\r\n iteration: number;\r\n /** Errors encountered during execution */\r\n errors: AgentError[];\r\n /** Agent execution metadata */\r\n metadata: AgentMetadata;\r\n}\r\n\r\n// ============================================================================\r\n// Discriminated Union Types\r\n// ============================================================================\r\n\r\n/**\r\n * Loop 3 (Implementer) Output\r\n */\r\nexport interface Loop3Output extends BaseAgentOutput {\r\n /** Discriminator for Loop 3 implementer output */\r\n output_type: 'loop3';\r\n /** Artifacts created or modified */\r\n deliverables: Deliverable[];\r\n /** Quantitative metrics */\r\n metrics?: Metrics;\r\n /** Brief summary of implementation work */\r\n summary?: string;\r\n}\r\n\r\n/**\r\n * Loop 2 (Validator) Output\r\n */\r\nexport interface Loop2Output extends BaseAgentOutput {\r\n /** Discriminator for Loop 2 validator output */\r\n output_type: 'loop2';\r\n /** Type of validation performed */\r\n validation_type: ValidationType;\r\n /** Issues found during validation */\r\n issues: Issue[];\r\n /** Recommendations for improvement */\r\n recommendations: string[];\r\n /** Whether work is approved (consensus vote) */\r\n approved: boolean;\r\n /** Brief summary of validation findings */\r\n summary?: string;\r\n}\r\n\r\n/**\r\n * Product Owner Output\r\n */\r\nexport interface ProductOwnerOutput extends BaseAgentOutput {\r\n /** Discriminator for Product Owner output */\r\n output_type: 'product_owner';\r\n /** Product Owner decision */\r\n decision: ProductOwnerDecision;\r\n /** Explanation for decision */\r\n rationale: string;\r\n /** Whether deliverables were validated */\r\n deliverables_validated: boolean;\r\n /** Next action to take */\r\n next_action: string;\r\n /** Consensus score from Loop 2 validators (0.0-1.0) */\r\n consensus_score?: number;\r\n /** Gate score from Loop 3 implementers (0.0-1.0) */\r\n gate_score?: number;\r\n}\r\n\r\n/**\r\n * Union type for all agent outputs\r\n */\r\nexport type AgentOutput = Loop3Output | Loop2Output | ProductOwnerOutput;\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Type guard for Loop 3 output\r\n */\r\nexport function isLoop3Output(output: AgentOutput): output is Loop3Output {\r\n return output.output_type === 'loop3';\r\n}\r\n\r\n/**\r\n * Type guard for Loop 2 output\r\n */\r\nexport function isLoop2Output(output: AgentOutput): output is Loop2Output {\r\n return output.output_type === 'loop2';\r\n}\r\n\r\n/**\r\n * Type guard for Product Owner output\r\n */\r\nexport function isProductOwnerOutput(\r\n output: AgentOutput\r\n): output is ProductOwnerOutput {\r\n return output.output_type === 'product_owner';\r\n}\r\n\r\n/**\r\n * Type guard for base agent output\r\n */\r\nexport function isValidAgentOutput(value: unknown): value is AgentOutput {\r\n if (typeof value !== 'object' || value === null) {\r\n return false;\r\n }\r\n\r\n const obj = value as Record<string, unknown>;\r\n\r\n // Check required base fields\r\n if (\r\n typeof obj.success !== 'boolean' ||\r\n typeof obj.confidence !== 'number' ||\r\n typeof obj.iteration !== 'number' ||\r\n !Array.isArray(obj.errors) ||\r\n typeof obj.metadata !== 'object' ||\r\n obj.metadata === null\r\n ) {\r\n return false;\r\n }\r\n\r\n // Check output_type discriminator\r\n const outputType = obj.output_type;\r\n return (\r\n outputType === 'loop3' ||\r\n outputType === 'loop2' ||\r\n outputType === 'product_owner'\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Validation Result Types\r\n// ============================================================================\r\n\r\n/**\r\n * Validation error details\r\n */\r\nexport interface ValidationError {\r\n /** Field that failed validation */\r\n field: string;\r\n /** Error message */\r\n message: string;\r\n /** JSON path to field */\r\n path: string;\r\n /** Error code */\r\n code: string;\r\n /** Current value (if applicable) */\r\n value?: unknown;\r\n}\r\n\r\n/**\r\n * Validation result\r\n */\r\nexport interface ValidationResult {\r\n /** Whether validation passed */\r\n valid: boolean;\r\n /** Validation errors (if any) */\r\n errors: ValidationError[];\r\n /** Warnings (non-fatal issues) */\r\n warnings: string[];\r\n /** Detected output type */\r\n output_type?: AgentOutputType;\r\n}\r\n\r\n// ============================================================================\r\n// Parser Result Types\r\n// ============================================================================\r\n\r\n/**\r\n * Legacy parser result\r\n */\r\nexport interface ParseResult {\r\n /** Whether parsing was successful */\r\n success: boolean;\r\n /** Parsed agent output (if successful) */\r\n output?: AgentOutput;\r\n /** Parse errors (if unsuccessful) */\r\n errors: string[];\r\n /** Parser confidence (0.0-1.0) */\r\n confidence: number;\r\n}\r\n\r\n// ============================================================================\r\n// Exports\r\n// ============================================================================\r\n\r\nexport default AgentOutput;\r\n"],"names":["isLoop3Output","output","output_type","isLoop2Output","isProductOwnerOutput","isValidAgentOutput","value","obj","success","confidence","iteration","Array","isArray","errors","metadata","outputType"],"mappings":"AAAA;;;;;;CAMC,GAED,+EAA+E;AAC/E,yBAAyB;AACzB,+EAA+E;AA+N/E,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;CAEC,GACD,OAAO,SAASA,cAAcC,MAAmB;IAC/C,OAAOA,OAAOC,WAAW,KAAK;AAChC;AAEA;;CAEC,GACD,OAAO,SAASC,cAAcF,MAAmB;IAC/C,OAAOA,OAAOC,WAAW,KAAK;AAChC;AAEA;;CAEC,GACD,OAAO,SAASE,qBACdH,MAAmB;IAEnB,OAAOA,OAAOC,WAAW,KAAK;AAChC;AAEA;;CAEC,GACD,OAAO,SAASG,mBAAmBC,KAAc;IAC/C,IAAI,OAAOA,UAAU,YAAYA,UAAU,MAAM;QAC/C,OAAO;IACT;IAEA,MAAMC,MAAMD;IAEZ,6BAA6B;IAC7B,IACE,OAAOC,IAAIC,OAAO,KAAK,aACvB,OAAOD,IAAIE,UAAU,KAAK,YAC1B,OAAOF,IAAIG,SAAS,KAAK,YACzB,CAACC,MAAMC,OAAO,CAACL,IAAIM,MAAM,KACzB,OAAON,IAAIO,QAAQ,KAAK,YACxBP,IAAIO,QAAQ,KAAK,MACjB;QACA,OAAO;IACT;IAEA,kCAAkC;IAClC,MAAMC,aAAaR,IAAIL,WAAW;IAClC,OACEa,eAAe,WACfA,eAAe,WACfA,eAAe;AAEnB"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * TypeScript type definitions for CFN Configuration System
3
+ * Derived from schemas/cfn-config-v1.json
4
+ *
5
+ * @version 1.0.0
6
+ * @description Canonical types for all CFN configuration formats
7
+ */ /**
8
+ * Resource allocation limits with explicit property definitions
9
+ * @description All properties are optional but type-safe when present
10
+ */ /**
11
+ * Type guard helpers
12
+ */ export function isAgentWhitelistConfig(config) {
13
+ return 'agents' in config && Array.isArray(config.agents);
14
+ }
15
+ export function isMCPServersConfig(config) {
16
+ return 'servers' in config && typeof config.servers === 'object';
17
+ }
18
+ export function isSkillRequirementsConfig(config) {
19
+ return 'tools' in config && typeof config.tools === 'object';
20
+ }
21
+ export function isRuntimeContractConfig(config) {
22
+ return 'variables' in config && config.variables !== undefined;
23
+ }
24
+ export function isTeamConfig(config) {
25
+ return 'team' in config && config.team !== undefined;
26
+ }
27
+
28
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/config.ts"],"sourcesContent":["/**\r\n * TypeScript type definitions for CFN Configuration System\r\n * Derived from schemas/cfn-config-v1.json\r\n *\r\n * @version 1.0.0\r\n * @description Canonical types for all CFN configuration formats\r\n */\r\n\r\n/**\r\n * Resource allocation limits with explicit property definitions\r\n * @description All properties are optional but type-safe when present\r\n */\r\nexport interface ResourceLimits {\r\n maxMemoryMB?: number;\r\n maxCpuCores?: number;\r\n maxRequestsPerMinute?: number;\r\n maxConcurrentRequests?: number;\r\n maxConnections?: number;\r\n maxCpuPercent?: number;\r\n maxWorkflows?: number;\r\n maxSessions?: number;\r\n}\r\n\r\n/**\r\n * Environment variable definition\r\n */\r\nexport interface EnvironmentVariable {\r\n value?: string | number | boolean | null;\r\n description: string;\r\n type: 'string' | 'integer' | 'number' | 'boolean';\r\n required?: boolean;\r\n default?: string | number | boolean | null;\r\n scope?: string[];\r\n legacyAliases?: string[];\r\n example?: string | number | boolean;\r\n}\r\n\r\n/**\r\n * Health check configuration\r\n */\r\nexport interface HealthCheckConfig {\r\n enabled?: boolean;\r\n path?: string;\r\n interval?: number;\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Authentication configuration\r\n */\r\nexport interface AuthConfig {\r\n type: 'token' | 'oauth2' | 'basic' | 'apikey';\r\n header?: string;\r\n secretName?: string;\r\n required?: boolean;\r\n}\r\n\r\n/**\r\n * Agent whitelist configuration\r\n */\r\nexport interface Agent {\r\n type: string;\r\n displayName: string;\r\n skills: string[];\r\n allowedMcpServers?: string[];\r\n resourceLimits?: ResourceLimits;\r\n description?: string;\r\n}\r\n\r\nexport interface AgentWhitelistConfig {\r\n version: string;\r\n description?: string;\r\n lastUpdated?: string;\r\n agents: Agent[];\r\n}\r\n\r\n/**\r\n * MCP Server configuration\r\n */\r\nexport interface MCPServer {\r\n endpoint: string;\r\n requiredSkills: string[];\r\n auth: AuthConfig;\r\n healthCheck?: string | HealthCheckConfig;\r\n timeoutMs?: number;\r\n retryAttempts?: number;\r\n resourceLimits?: ResourceLimits;\r\n capabilities?: string[];\r\n}\r\n\r\nexport interface MCPServersConfig {\r\n version: string;\r\n description?: string;\r\n lastUpdated?: string;\r\n servers: Record<string, MCPServer>;\r\n}\r\n\r\n/**\r\n * Skill requirements configuration\r\n */\r\nexport interface ResourceImpact {\r\n memoryMB?: number;\r\n cpuUnits?: number;\r\n durationSeconds?: number;\r\n}\r\n\r\nexport interface ToolRequirement {\r\n displayName: string;\r\n requiredSkills: string[];\r\n optionalSkills?: string[];\r\n allowedAgentTypes?: string[];\r\n resourceImpact?: ResourceImpact;\r\n description?: string;\r\n}\r\n\r\nexport interface SkillRequirementsConfig {\r\n version: string;\r\n description?: string;\r\n lastUpdated?: string;\r\n tools: Record<string, ToolRequirement>;\r\n}\r\n\r\n/**\r\n * Runtime contract configuration\r\n */\r\nexport interface RuntimeContractConfig {\r\n version: string;\r\n lastUpdated?: string;\r\n generated?: string;\r\n variables?: Record<string, EnvironmentVariable>;\r\n}\r\n\r\n/**\r\n * Team configuration\r\n */\r\nexport interface TeamWorkspace {\r\n path?: string;\r\n diskQuota?: string;\r\n}\r\n\r\nexport interface TeamResources {\r\n memory?: string;\r\n cpuCores?: number;\r\n maxAgents?: number;\r\n}\r\n\r\nexport interface TeamNetwork {\r\n subnetId?: number;\r\n coordinatorIp?: string;\r\n}\r\n\r\nexport interface Team {\r\n id: string;\r\n name: string;\r\n description?: string;\r\n workspace?: TeamWorkspace;\r\n resources?: TeamResources;\r\n allowedSkills?: string[];\r\n network?: TeamNetwork;\r\n}\r\n\r\nexport interface TeamConfig {\r\n team: Team;\r\n}\r\n\r\n/**\r\n * Union type for all possible CFN configuration types\r\n */\r\nexport type CFNConfig =\r\n | AgentWhitelistConfig\r\n | MCPServersConfig\r\n | SkillRequirementsConfig\r\n | RuntimeContractConfig\r\n | TeamConfig;\r\n\r\n/**\r\n * Validation result type\r\n */\r\nexport interface ValidationError {\r\n field: string;\r\n message: string;\r\n path: string;\r\n value?: unknown;\r\n code: string;\r\n}\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: ValidationError[];\r\n warnings: string[];\r\n configType?: string;\r\n}\r\n\r\n/**\r\n * Environment variable export map\r\n */\r\nexport interface EnvVarExportMap {\r\n [key: string]: string | number | boolean;\r\n}\r\n\r\n/**\r\n * Configuration loader options\r\n */\r\nexport interface ConfigLoaderOptions {\r\n validateSchema?: boolean;\r\n strictMode?: boolean;\r\n resolveEnvVars?: boolean;\r\n warnOnLegacyVars?: boolean;\r\n}\r\n\r\n/**\r\n * Type guard helpers\r\n */\r\nexport function isAgentWhitelistConfig(\r\n config: CFNConfig\r\n): config is AgentWhitelistConfig {\r\n return 'agents' in config && Array.isArray((config as AgentWhitelistConfig).agents);\r\n}\r\n\r\nexport function isMCPServersConfig(\r\n config: CFNConfig\r\n): config is MCPServersConfig {\r\n return (\r\n 'servers' in config &&\r\n typeof (config as MCPServersConfig).servers === 'object'\r\n );\r\n}\r\n\r\nexport function isSkillRequirementsConfig(\r\n config: CFNConfig\r\n): config is SkillRequirementsConfig {\r\n return (\r\n 'tools' in config &&\r\n typeof (config as SkillRequirementsConfig).tools === 'object'\r\n );\r\n}\r\n\r\nexport function isRuntimeContractConfig(\r\n config: CFNConfig\r\n): config is RuntimeContractConfig {\r\n return (\r\n 'variables' in config &&\r\n (config as RuntimeContractConfig).variables !== undefined\r\n );\r\n}\r\n\r\nexport function isTeamConfig(config: CFNConfig): config is TeamConfig {\r\n return 'team' in config && (config as TeamConfig).team !== undefined;\r\n}\r\n"],"names":["isAgentWhitelistConfig","config","Array","isArray","agents","isMCPServersConfig","servers","isSkillRequirementsConfig","tools","isRuntimeContractConfig","variables","undefined","isTeamConfig","team"],"mappings":"AAAA;;;;;;CAMC,GAED;;;CAGC,GAuMD;;CAEC,GACD,OAAO,SAASA,uBACdC,MAAiB;IAEjB,OAAO,YAAYA,UAAUC,MAAMC,OAAO,CAAC,AAACF,OAAgCG,MAAM;AACpF;AAEA,OAAO,SAASC,mBACdJ,MAAiB;IAEjB,OACE,aAAaA,UACb,OAAO,AAACA,OAA4BK,OAAO,KAAK;AAEpD;AAEA,OAAO,SAASC,0BACdN,MAAiB;IAEjB,OACE,WAAWA,UACX,OAAO,AAACA,OAAmCO,KAAK,KAAK;AAEzD;AAEA,OAAO,SAASC,wBACdR,MAAiB;IAEjB,OACE,eAAeA,UACf,AAACA,OAAiCS,SAAS,KAAKC;AAEpD;AAEA,OAAO,SAASC,aAAaX,MAAiB;IAC5C,OAAO,UAAUA,UAAU,AAACA,OAAsBY,IAAI,KAAKF;AAC7D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow-novice",
3
- "version": "2.15.2",
3
+ "version": "2.15.3",
4
4
  "description": "AI agent orchestration framework with namespace-isolated skills, agents, and CFN Loop validation. Safe installation with ~0.01% collision risk.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -18,6 +18,7 @@
18
18
  "files": [
19
19
  "dist/",
20
20
  "claude-assets/",
21
+ ".claude/skills/agent-lifecycle/",
21
22
  ".claude/skills/cfn-ace-system/",
22
23
  ".claude/skills/cfn-agent-discovery/",
23
24
  ".claude/skills/cfn-agent-execution/",
@@ -0,0 +1,392 @@
1
+ #!/usr/bin/env bash
2
+ # Artifact Registry TTL-based Cleanup Script
3
+ # Version: 1.0.0
4
+ # Purpose: Automatically archive/delete expired artifacts based on retention policy
5
+ #
6
+ # Usage:
7
+ # ./artifact-cleanup.sh [OPTIONS]
8
+ #
9
+ # Options:
10
+ # --dry-run Show what would be cleaned up without making changes
11
+ # --policy <policy> Only clean specific retention policy (ephemeral, standard, custom)
12
+ # --archive-days <N> Days before archived artifacts are deleted (default: 90)
13
+ # --db-path <path> Path to SQLite database (default: ./artifacts/database/registry.db)
14
+ # --log-file <path> Path to log file (default: ./artifacts/logs/cleanup.log)
15
+ # --verbose Enable verbose logging
16
+ # --help Show this help message
17
+ #
18
+ # Exit Codes:
19
+ # 0 - Success
20
+ # 1 - General error
21
+ # 2 - Database error
22
+ # 3 - Validation error
23
+
24
+ set -euo pipefail
25
+
26
+ # ============================================================================
27
+ # Configuration and Defaults
28
+ # ============================================================================
29
+
30
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
31
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
32
+
33
+ # Default configuration
34
+ DRY_RUN=false
35
+ POLICY_FILTER=""
36
+ ARCHIVE_DAYS=90
37
+ DB_PATH="${PROJECT_ROOT}/artifacts/database/registry.db"
38
+ LOG_FILE="${PROJECT_ROOT}/artifacts/logs/cleanup.log"
39
+ VERBOSE=false
40
+
41
+ # Counters
42
+ ARTIFACTS_ARCHIVED=0
43
+ ARTIFACTS_DELETED=0
44
+ ERRORS=0
45
+
46
+ # ============================================================================
47
+ # Logging Functions
48
+ # ============================================================================
49
+
50
+ log() {
51
+ local level="$1"
52
+ shift
53
+ local message="$*"
54
+ local timestamp
55
+ timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
56
+
57
+ echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
58
+ }
59
+
60
+ log_info() {
61
+ log "INFO" "$@"
62
+ }
63
+
64
+ log_warn() {
65
+ log "WARN" "$@"
66
+ }
67
+
68
+ log_error() {
69
+ log "ERROR" "$@"
70
+ ((ERRORS++)) || true
71
+ }
72
+
73
+ log_debug() {
74
+ if [[ "$VERBOSE" == "true" ]]; then
75
+ log "DEBUG" "$@"
76
+ fi
77
+ }
78
+
79
+ # ============================================================================
80
+ # Utility Functions
81
+ # ============================================================================
82
+
83
+ show_help() {
84
+ grep '^#' "$0" | grep -v '#!/usr/bin/env' | sed 's/^# //; s/^#//'
85
+ exit 0
86
+ }
87
+
88
+ ensure_directory() {
89
+ local dir="$1"
90
+ if [[ ! -d "$dir" ]]; then
91
+ mkdir -p "$dir"
92
+ log_debug "Created directory: $dir"
93
+ fi
94
+ }
95
+
96
+ validate_database() {
97
+ if [[ ! -f "$DB_PATH" ]]; then
98
+ log_error "Database not found: $DB_PATH"
99
+ exit 2
100
+ fi
101
+
102
+ # Test database connectivity
103
+ if ! sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM artifacts;" &>/dev/null; then
104
+ log_error "Failed to query database or artifacts table does not exist"
105
+ exit 2
106
+ fi
107
+
108
+ log_debug "Database validated: $DB_PATH"
109
+ }
110
+
111
+ # ============================================================================
112
+ # Cleanup Functions
113
+ # ============================================================================
114
+
115
+ find_expired_artifacts() {
116
+ local policy_clause=""
117
+ if [[ -n "$POLICY_FILTER" ]]; then
118
+ policy_clause="AND retention_policy = '$POLICY_FILTER'"
119
+ fi
120
+
121
+ sqlite3 "$DB_PATH" <<EOF
122
+ SELECT id, name, type, storage_location, retention_policy,
123
+ created_at, expires_at, CAST((julianday('now') - julianday(expires_at)) AS INTEGER) as days_expired
124
+ FROM artifacts
125
+ WHERE status = 'active'
126
+ AND expires_at IS NOT NULL
127
+ AND datetime('now') >= expires_at
128
+ $policy_clause
129
+ ORDER BY created_at ASC;
130
+ EOF
131
+ }
132
+
133
+ archive_artifact() {
134
+ local artifact_id="$1"
135
+ local artifact_name="$2"
136
+
137
+ if [[ "$DRY_RUN" == "true" ]]; then
138
+ log_info "[DRY-RUN] Would archive: $artifact_name (ID: $artifact_id)"
139
+ ((ARTIFACTS_ARCHIVED++)) || true
140
+ return 0
141
+ fi
142
+
143
+ local result
144
+ result=$(sqlite3 "$DB_PATH" <<EOF
145
+ UPDATE artifacts
146
+ SET status = 'archived',
147
+ archived_at = CURRENT_TIMESTAMP,
148
+ updated_at = CURRENT_TIMESTAMP
149
+ WHERE id = '$artifact_id';
150
+ SELECT changes();
151
+ EOF
152
+ )
153
+
154
+ if [[ "$result" == "1" ]]; then
155
+ log_info "Archived: $artifact_name (ID: $artifact_id)"
156
+ ((ARTIFACTS_ARCHIVED++)) || true
157
+ return 0
158
+ else
159
+ log_error "Failed to archive: $artifact_name (ID: $artifact_id)"
160
+ return 1
161
+ fi
162
+ }
163
+
164
+ find_archived_for_deletion() {
165
+ local policy_clause=""
166
+ if [[ -n "$POLICY_FILTER" ]]; then
167
+ policy_clause="AND retention_policy = '$POLICY_FILTER'"
168
+ fi
169
+
170
+ sqlite3 "$DB_PATH" <<EOF
171
+ SELECT id, name, type, storage_location, retention_policy,
172
+ archived_at, CAST((julianday('now') - julianday(archived_at)) AS INTEGER) as days_archived
173
+ FROM artifacts
174
+ WHERE status = 'archived'
175
+ AND archived_at IS NOT NULL
176
+ AND datetime('now') >= datetime(archived_at, '+$ARCHIVE_DAYS days')
177
+ $policy_clause
178
+ ORDER BY archived_at ASC;
179
+ EOF
180
+ }
181
+
182
+ delete_artifact() {
183
+ local artifact_id="$1"
184
+ local artifact_name="$2"
185
+
186
+ if [[ "$DRY_RUN" == "true" ]]; then
187
+ log_info "[DRY-RUN] Would delete: $artifact_name (ID: $artifact_id)"
188
+ ((ARTIFACTS_DELETED++)) || true
189
+ return 0
190
+ fi
191
+
192
+ local result
193
+ result=$(sqlite3 "$DB_PATH" <<EOF
194
+ UPDATE artifacts
195
+ SET status = 'deleted',
196
+ deleted_at = CURRENT_TIMESTAMP,
197
+ updated_at = CURRENT_TIMESTAMP
198
+ WHERE id = '$artifact_id';
199
+ SELECT changes();
200
+ EOF
201
+ )
202
+
203
+ if [[ "$result" == "1" ]]; then
204
+ log_info "Deleted: $artifact_name (ID: $artifact_id)"
205
+ ((ARTIFACTS_DELETED++)) || true
206
+ return 0
207
+ else
208
+ log_error "Failed to delete: $artifact_name (ID: $artifact_id)"
209
+ return 1
210
+ fi
211
+ }
212
+
213
+ # ============================================================================
214
+ # Main Cleanup Logic
215
+ # ============================================================================
216
+
217
+ cleanup_expired_artifacts() {
218
+ log_info "=== Starting Artifact Cleanup ==="
219
+ log_info "Configuration:"
220
+ log_info " - Database: $DB_PATH"
221
+ log_info " - Dry Run: $DRY_RUN"
222
+ log_info " - Policy Filter: ${POLICY_FILTER:-all}"
223
+ log_info " - Archive Days: $ARCHIVE_DAYS"
224
+
225
+ # Step 1: Archive expired active artifacts
226
+ log_info "--- Step 1: Finding expired active artifacts ---"
227
+ local expired_artifacts
228
+ expired_artifacts=$(find_expired_artifacts)
229
+
230
+ if [[ -z "$expired_artifacts" ]]; then
231
+ log_info "No expired artifacts found for archival"
232
+ else
233
+ local count
234
+ count=$(echo "$expired_artifacts" | wc -l)
235
+ log_info "Found $count expired artifact(s) to archive"
236
+
237
+ while IFS='|' read -r id name type storage policy created expires days_expired; do
238
+ log_debug "Processing: $name (Type: $type, Policy: $policy, Expired: ${days_expired}d ago)"
239
+ archive_artifact "$id" "$name" || true
240
+ done <<< "$expired_artifacts"
241
+ fi
242
+
243
+ # Step 2: Delete old archived artifacts
244
+ log_info "--- Step 2: Finding old archived artifacts ---"
245
+ local archived_artifacts
246
+ archived_artifacts=$(find_archived_for_deletion)
247
+
248
+ if [[ -z "$archived_artifacts" ]]; then
249
+ log_info "No archived artifacts ready for deletion"
250
+ else
251
+ local count
252
+ count=$(echo "$archived_artifacts" | wc -l)
253
+ log_info "Found $count archived artifact(s) ready for deletion"
254
+
255
+ while IFS='|' read -r id name type storage policy archived days_archived; do
256
+ log_debug "Processing: $name (Type: $type, Policy: $policy, Archived: ${days_archived}d ago)"
257
+ delete_artifact "$id" "$name" || true
258
+ done <<< "$archived_artifacts"
259
+ fi
260
+
261
+ # Summary
262
+ log_info "=== Cleanup Summary ==="
263
+ log_info " - Artifacts Archived: $ARTIFACTS_ARCHIVED"
264
+ log_info " - Artifacts Deleted: $ARTIFACTS_DELETED"
265
+ log_info " - Errors: $ERRORS"
266
+
267
+ if [[ "$DRY_RUN" == "true" ]]; then
268
+ log_info " - Mode: DRY RUN (no changes made)"
269
+ fi
270
+
271
+ if [[ $ERRORS -gt 0 ]]; then
272
+ exit 1
273
+ fi
274
+ }
275
+
276
+ get_cleanup_statistics() {
277
+ log_info "=== Artifact Registry Statistics ==="
278
+
279
+ local stats
280
+ stats=$(sqlite3 -header -column "$DB_PATH" <<EOF
281
+ SELECT
282
+ retention_policy,
283
+ COUNT(*) as total,
284
+ SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active,
285
+ SUM(CASE WHEN status = 'archived' THEN 1 ELSE 0 END) as archived,
286
+ SUM(CASE WHEN status = 'deleted' THEN 1 ELSE 0 END) as deleted,
287
+ SUM(CASE WHEN cleanup_eligible = 1 THEN 1 ELSE 0 END) as cleanup_eligible,
288
+ ROUND(COALESCE(SUM(size_bytes), 0) / 1024.0 / 1024.0, 2) as size_mb
289
+ FROM artifacts
290
+ GROUP BY retention_policy
291
+ ORDER BY retention_policy;
292
+ EOF
293
+ )
294
+
295
+ echo "$stats" | tee -a "$LOG_FILE"
296
+ }
297
+
298
+ # ============================================================================
299
+ # Argument Parsing
300
+ # ============================================================================
301
+
302
+ parse_arguments() {
303
+ while [[ $# -gt 0 ]]; do
304
+ case "$1" in
305
+ --dry-run)
306
+ DRY_RUN=true
307
+ shift
308
+ ;;
309
+ --policy)
310
+ POLICY_FILTER="$2"
311
+ shift 2
312
+ ;;
313
+ --archive-days)
314
+ ARCHIVE_DAYS="$2"
315
+ shift 2
316
+ ;;
317
+ --db-path)
318
+ DB_PATH="$2"
319
+ shift 2
320
+ ;;
321
+ --log-file)
322
+ LOG_FILE="$2"
323
+ shift 2
324
+ ;;
325
+ --verbose)
326
+ VERBOSE=true
327
+ shift
328
+ ;;
329
+ --help)
330
+ show_help
331
+ ;;
332
+ *)
333
+ log_error "Unknown option: $1"
334
+ show_help
335
+ exit 3
336
+ ;;
337
+ esac
338
+ done
339
+
340
+ # Validate policy filter if provided
341
+ if [[ -n "$POLICY_FILTER" ]]; then
342
+ case "$POLICY_FILTER" in
343
+ ephemeral|standard|permanent|custom)
344
+ ;;
345
+ *)
346
+ log_error "Invalid retention policy: $POLICY_FILTER"
347
+ log_error "Valid values: ephemeral, standard, permanent, custom"
348
+ exit 3
349
+ ;;
350
+ esac
351
+ fi
352
+
353
+ # Validate archive days
354
+ if ! [[ "$ARCHIVE_DAYS" =~ ^[0-9]+$ ]] || [[ "$ARCHIVE_DAYS" -lt 0 ]]; then
355
+ log_error "Invalid archive days: $ARCHIVE_DAYS (must be non-negative integer)"
356
+ exit 3
357
+ fi
358
+ }
359
+
360
+ # ============================================================================
361
+ # Main Execution
362
+ # ============================================================================
363
+
364
+ main() {
365
+ parse_arguments "$@"
366
+
367
+ # Ensure log directory exists
368
+ ensure_directory "$(dirname "$LOG_FILE")"
369
+
370
+ log_info "Artifact Cleanup Script - Version 1.0.0"
371
+ log_info "Starting at $(date '+%Y-%m-%d %H:%M:%S')"
372
+
373
+ # Validate database
374
+ validate_database
375
+
376
+ # Show statistics before cleanup
377
+ get_cleanup_statistics
378
+
379
+ # Perform cleanup
380
+ cleanup_expired_artifacts
381
+
382
+ # Show statistics after cleanup
383
+ get_cleanup_statistics
384
+
385
+ log_info "Cleanup completed at $(date '+%Y-%m-%d %H:%M:%S')"
386
+ exit 0
387
+ }
388
+
389
+ # Run main if executed directly
390
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
391
+ main "$@"
392
+ fi