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.
- package/.claude/hooks/cfn-BACKUP_USAGE.md +243 -243
- package/.claude/hooks/cfn-invoke-security-validation.sh +69 -69
- package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +78 -78
- package/.claude/hooks/cfn-post-edit.config.json +44 -44
- package/.claude/skills/agent-lifecycle/SKILL.md +60 -0
- package/.claude/skills/agent-lifecycle/execute-lifecycle-hook.sh +573 -0
- package/.claude/skills/agent-lifecycle/simple-audit.sh +31 -0
- package/.claude/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
- package/.claude/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
- package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
- package/.claude/skills/cfn-redis-coordination/get-context.sh +112 -112
- package/.claude/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
- package/.claude/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
- package/.claude/skills/cfn-transparency-middleware/test-integration.sh +161 -161
- package/.claude/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
- package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +92 -92
- package/.claude/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
- package/claude-assets/hooks/cfn-BACKUP_USAGE.md +243 -243
- package/claude-assets/hooks/cfn-invoke-security-validation.sh +69 -69
- package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +78 -78
- package/claude-assets/hooks/cfn-post-edit.config.json +44 -44
- package/claude-assets/hooks/cfn-post-execution/memory-cleanup.sh +19 -19
- package/claude-assets/hooks/cfn-pre-execution/memory-check.sh +19 -19
- package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +572 -572
- package/claude-assets/skills/agent-lifecycle/simple-audit.sh +30 -30
- package/claude-assets/skills/cfn-automatic-memory-persistence/persist-agent-output.sh +48 -48
- package/claude-assets/skills/cfn-automatic-memory-persistence/query-agent-history.sh +34 -34
- package/claude-assets/skills/cfn-deliverable-validation/confidence-calculator.sh +261 -261
- package/claude-assets/skills/cfn-expert-update/update-expert.sh +345 -345
- package/claude-assets/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
- package/claude-assets/skills/cfn-intervention-detector/detect-intervention.sh +110 -110
- package/claude-assets/skills/cfn-intervention-orchestrator/execute-intervention.sh +58 -58
- package/claude-assets/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
- package/claude-assets/skills/cfn-loop2-output-processing/process-validator-output.sh +275 -275
- package/claude-assets/skills/cfn-memory-management/check-memory.sh +159 -159
- package/claude-assets/skills/cfn-memory-management/cleanup-memory.sh +196 -196
- package/claude-assets/skills/cfn-node-heap-sizer/task-mode-heap-limiter.sh +325 -325
- package/claude-assets/skills/cfn-playbook-auto-update/auto-update-playbook.sh +85 -85
- package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
- package/claude-assets/skills/cfn-redis-coordination/get-context.sh +112 -112
- package/claude-assets/skills/cfn-scope-simplifier/simplify-scope.sh +67 -67
- package/claude-assets/skills/cfn-specialist-injection/recommend-specialist.sh +56 -56
- package/claude-assets/skills/cfn-standardized-error-handling/capture-agent-error.sh +86 -86
- package/claude-assets/skills/cfn-standardized-error-handling/test-error-handling.sh +165 -165
- package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +264 -264
- package/claude-assets/skills/cfn-task-decomposition/task-decomposer.sh +278 -278
- package/claude-assets/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
- package/claude-assets/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
- package/claude-assets/skills/cfn-transparency-middleware/test-integration.sh +161 -161
- package/claude-assets/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
- package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +92 -92
- package/claude-assets/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
- package/claude-assets/skills/docker-build/SKILL.md +96 -203
- package/claude-assets/skills/docker-build/build.sh +73 -73
- package/claude-assets/skills/integration/agent-handoff.sh +494 -0
- package/claude-assets/skills/integration/file-operations.sh +414 -0
- package/claude-assets/skills/workflow-codification/APPROVAL_WORKFLOW.md +806 -0
- package/claude-assets/skills/workflow-codification/COST_TRACKING.md +637 -0
- package/claude-assets/skills/workflow-codification/EDGE_CASE_TRACKING.md +404 -0
- package/claude-assets/skills/workflow-codification/README_PHASE4.md +457 -0
- package/claude-assets/skills/workflow-codification/SKILL.md +110 -0
- package/claude-assets/skills/workflow-codification/analyze-patterns.sh +899 -0
- package/claude-assets/skills/workflow-codification/approval-workflow.sh +514 -0
- package/claude-assets/skills/workflow-codification/generate-skill-update.sh +525 -0
- package/claude-assets/skills/workflow-codification/review-skill.sh +643 -0
- package/claude-assets/skills/workflow-codification/templates/email-notification.txt +114 -0
- package/claude-assets/skills/workflow-codification/templates/slack-notification.md +85 -0
- package/claude-assets/skills/workflow-codification/test-integration.sh +281 -0
- package/claude-assets/skills/workflow-codification/track-cost-savings.sh +445 -0
- package/claude-assets/skills/workflow-codification/track-edge-case.sh +323 -0
- package/dist/cli/config-manager.js +91 -109
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/integration/DatabaseHandoff.js +507 -0
- package/dist/integration/DatabaseHandoff.js.map +1 -0
- package/dist/integration/StandardAdapter.js +291 -0
- package/dist/integration/StandardAdapter.js.map +1 -0
- package/dist/lib/agent-output-parser.js +518 -0
- package/dist/lib/agent-output-parser.js.map +1 -0
- package/dist/lib/agent-output-validator.js +950 -0
- package/dist/lib/agent-output-validator.js.map +1 -0
- package/dist/lib/artifact-registry.js +443 -0
- package/dist/lib/artifact-registry.js.map +1 -0
- package/dist/lib/config-validator.js +687 -0
- package/dist/lib/config-validator.js.map +1 -0
- package/dist/types/agent-output.js +44 -0
- package/dist/types/agent-output.js.map +1 -0
- package/dist/types/config.js +28 -0
- package/dist/types/config.js.map +1 -0
- package/package.json +2 -1
- package/scripts/artifact-cleanup.sh +392 -0
- package/scripts/deploy-production.sh +355 -355
- package/scripts/docker-playwright-fix.sh +311 -311
- package/scripts/docker-rebuild-all-agents.sh +127 -127
- package/scripts/memory-leak-prevention.sh +305 -305
- package/scripts/migrate-artifacts.sh +563 -0
- package/scripts/migrate-yaml-to-json.sh +465 -0
- package/scripts/run-marketing-tests.sh +42 -42
- package/scripts/update_paths.sh +46 -46
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/agent-output-validator.ts"],"sourcesContent":["/**\r\n * Agent Output Validator\r\n * Zero-dependency validation library for CFN agent outputs\r\n *\r\n * @version 1.0.0\r\n * @description Type-safe validation with detailed error reporting\r\n */\r\n\r\nimport type {\r\n AgentOutput,\r\n Loop3Output,\r\n Loop2Output,\r\n ProductOwnerOutput,\r\n ValidationResult,\r\n ValidationError,\r\n Deliverable,\r\n Issue,\r\n Metrics,\r\n AgentError,\r\n AgentMetadata,\r\n DeliverableType,\r\n DeliverableStatus,\r\n IssueSeverity,\r\n IssueCategory,\r\n ValidationType,\r\n ProductOwnerDecision,\r\n CFNLoopMode,\r\n} from '../types/agent-output';\r\n\r\n// ============================================================================\r\n// Security Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Sanitize values for safe logging (prevents sensitive data leakage)\r\n * @param value - Value to sanitize\r\n * @param path - Field path for sensitive field detection\r\n * @returns Sanitized string representation\r\n */\r\nfunction sanitizeValue(value: unknown, path: string): string {\r\n // List of sensitive field patterns\r\n const sensitivePatterns = [\r\n 'password',\r\n 'passwd',\r\n 'pwd',\r\n 'token',\r\n 'key',\r\n 'secret',\r\n 'api_key',\r\n 'apikey',\r\n 'api-key',\r\n 'auth',\r\n 'credential',\r\n 'private',\r\n ];\r\n\r\n // Check if path contains sensitive field name\r\n const lowerPath = path.toLowerCase();\r\n const isSensitive = sensitivePatterns.some((pattern) =>\r\n lowerPath.includes(pattern)\r\n );\r\n\r\n if (isSensitive) {\r\n return '[REDACTED]';\r\n }\r\n\r\n // Sanitize value for safe display\r\n try {\r\n const str = JSON.stringify(value);\r\n\r\n // Truncate large values to prevent log flooding\r\n const maxLength = 100;\r\n if (str.length > maxLength) {\r\n return str.substring(0, maxLength) + '...[truncated]';\r\n }\r\n\r\n return str;\r\n } catch {\r\n // Handle circular references or non-serializable values\r\n return '[Non-serializable value]';\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Validation Class\r\n// ============================================================================\r\n\r\n/**\r\n * AgentOutputValidator: Main validation class\r\n * Provides schema validation, error reporting, and type checking\r\n */\r\nexport class AgentOutputValidator {\r\n /**\r\n * Validate agent output object\r\n */\r\n public validate(output: unknown): ValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (typeof output !== 'object' || output === null) {\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'root',\r\n message: 'Agent output must be a valid JSON object',\r\n path: '/',\r\n code: 'INVALID_TYPE',\r\n },\r\n ],\r\n warnings,\r\n };\r\n }\r\n\r\n const obj = output as Record<string, unknown>;\r\n\r\n // Validate output_type discriminator\r\n const outputType = obj.output_type;\r\n if (\r\n outputType !== 'loop3' &&\r\n outputType !== 'loop2' &&\r\n outputType !== 'product_owner'\r\n ) {\r\n errors.push({\r\n field: 'output_type',\r\n message:\r\n \"output_type must be one of: 'loop3', 'loop2', 'product_owner'\",\r\n path: '/output_type',\r\n code: 'INVALID_OUTPUT_TYPE',\r\n value: outputType,\r\n });\r\n return { valid: false, errors, warnings };\r\n }\r\n\r\n // Validate base fields common to all outputs\r\n this.validateBaseOutput(obj, errors);\r\n\r\n // Validate type-specific fields\r\n switch (outputType) {\r\n case 'loop3':\r\n this.validateLoop3Output(obj, errors, warnings);\r\n break;\r\n case 'loop2':\r\n this.validateLoop2Output(obj, errors, warnings);\r\n break;\r\n case 'product_owner':\r\n this.validateProductOwnerOutput(obj, errors, warnings);\r\n break;\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n output_type: outputType,\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 output = JSON.parse(jsonString);\r\n return this.validate(output);\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 };\r\n }\r\n }\r\n\r\n /**\r\n * Validate base output fields (common to all types)\r\n */\r\n private validateBaseOutput(\r\n obj: Record<string, unknown>,\r\n errors: ValidationError[]\r\n ): void {\r\n // Validate success (required boolean)\r\n if (typeof obj.success !== 'boolean') {\r\n errors.push({\r\n field: 'success',\r\n message: 'success must be a boolean',\r\n path: '/success',\r\n code: 'INVALID_TYPE',\r\n value: obj.success,\r\n });\r\n }\r\n\r\n // Validate confidence (required number 0.0-1.0)\r\n if (typeof obj.confidence !== 'number') {\r\n errors.push({\r\n field: 'confidence',\r\n message: 'confidence must be a number',\r\n path: '/confidence',\r\n code: 'INVALID_TYPE',\r\n value: obj.confidence,\r\n });\r\n } else if (obj.confidence < 0.0 || obj.confidence > 1.0) {\r\n errors.push({\r\n field: 'confidence',\r\n message: 'confidence must be between 0.0 and 1.0',\r\n path: '/confidence',\r\n code: 'CONSTRAINT_VIOLATION',\r\n value: obj.confidence,\r\n });\r\n }\r\n\r\n // Validate iteration (required positive integer)\r\n if (typeof obj.iteration !== 'number') {\r\n errors.push({\r\n field: 'iteration',\r\n message: 'iteration must be a number',\r\n path: '/iteration',\r\n code: 'INVALID_TYPE',\r\n value: obj.iteration,\r\n });\r\n } else if (!Number.isInteger(obj.iteration) || obj.iteration < 1) {\r\n errors.push({\r\n field: 'iteration',\r\n message: 'iteration must be a positive integer',\r\n path: '/iteration',\r\n code: 'CONSTRAINT_VIOLATION',\r\n value: obj.iteration,\r\n });\r\n }\r\n\r\n // Validate errors (required array)\r\n if (!Array.isArray(obj.errors)) {\r\n errors.push({\r\n field: 'errors',\r\n message: 'errors must be an array',\r\n path: '/errors',\r\n code: 'INVALID_TYPE',\r\n value: obj.errors,\r\n });\r\n } else {\r\n for (let i = 0; i < obj.errors.length; i++) {\r\n this.validateError(obj.errors[i], i, errors);\r\n }\r\n }\r\n\r\n // Validate metadata (required object)\r\n if (typeof obj.metadata !== 'object' || obj.metadata === null) {\r\n errors.push({\r\n field: 'metadata',\r\n message: 'metadata must be an object',\r\n path: '/metadata',\r\n code: 'INVALID_TYPE',\r\n value: obj.metadata,\r\n });\r\n } else {\r\n this.validateMetadata(\r\n obj.metadata as Record<string, unknown>,\r\n errors\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Validate Loop 3 (Implementer) output\r\n */\r\n private validateLoop3Output(\r\n obj: Record<string, unknown>,\r\n errors: ValidationError[],\r\n warnings: string[]\r\n ): void {\r\n // Validate deliverables (required array)\r\n if (!Array.isArray(obj.deliverables)) {\r\n errors.push({\r\n field: 'deliverables',\r\n message: 'deliverables must be an array',\r\n path: '/deliverables',\r\n code: 'INVALID_TYPE',\r\n value: obj.deliverables,\r\n });\r\n } else {\r\n for (let i = 0; i < obj.deliverables.length; i++) {\r\n this.validateDeliverable(obj.deliverables[i], i, errors);\r\n }\r\n\r\n if (obj.deliverables.length === 0) {\r\n warnings.push('Loop 3 output has no deliverables (empty array)');\r\n }\r\n }\r\n\r\n // Validate metrics (optional object)\r\n if (obj.metrics !== undefined) {\r\n if (typeof obj.metrics !== 'object' || obj.metrics === null) {\r\n errors.push({\r\n field: 'metrics',\r\n message: 'metrics must be an object',\r\n path: '/metrics',\r\n code: 'INVALID_TYPE',\r\n value: obj.metrics,\r\n });\r\n } else {\r\n this.validateMetrics(obj.metrics as Record<string, unknown>, errors);\r\n }\r\n }\r\n\r\n // Validate summary (optional string)\r\n if (obj.summary !== undefined && typeof obj.summary !== 'string') {\r\n errors.push({\r\n field: 'summary',\r\n message: 'summary must be a string',\r\n path: '/summary',\r\n code: 'INVALID_TYPE',\r\n value: obj.summary,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Validate Loop 2 (Validator) output\r\n */\r\n private validateLoop2Output(\r\n obj: Record<string, unknown>,\r\n errors: ValidationError[],\r\n warnings: string[]\r\n ): void {\r\n // Validate validation_type (required enum)\r\n const validationTypes: ValidationType[] = [\r\n 'review',\r\n 'test',\r\n 'security',\r\n 'architecture',\r\n 'performance',\r\n 'compliance',\r\n ];\r\n if (!validationTypes.includes(obj.validation_type as ValidationType)) {\r\n errors.push({\r\n field: 'validation_type',\r\n message: `validation_type must be one of: ${validationTypes.join(', ')}`,\r\n path: '/validation_type',\r\n code: 'INVALID_ENUM',\r\n value: obj.validation_type,\r\n });\r\n }\r\n\r\n // Validate issues (optional array, default to empty)\r\n if (obj.issues !== undefined) {\r\n if (!Array.isArray(obj.issues)) {\r\n errors.push({\r\n field: 'issues',\r\n message: 'issues must be an array',\r\n path: '/issues',\r\n code: 'INVALID_TYPE',\r\n value: obj.issues,\r\n });\r\n } else {\r\n for (let i = 0; i < obj.issues.length; i++) {\r\n this.validateIssue(obj.issues[i], i, errors);\r\n }\r\n }\r\n }\r\n\r\n // Validate recommendations (optional array, default to empty)\r\n if (obj.recommendations !== undefined) {\r\n if (!Array.isArray(obj.recommendations)) {\r\n errors.push({\r\n field: 'recommendations',\r\n message: 'recommendations must be an array',\r\n path: '/recommendations',\r\n code: 'INVALID_TYPE',\r\n value: obj.recommendations,\r\n });\r\n } else {\r\n for (let i = 0; i < obj.recommendations.length; i++) {\r\n if (typeof obj.recommendations[i] !== 'string') {\r\n errors.push({\r\n field: `recommendations[${i}]`,\r\n message: 'recommendation must be a string',\r\n path: `/recommendations/${i}`,\r\n code: 'INVALID_TYPE',\r\n value: obj.recommendations[i],\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Validate approved (required boolean)\r\n if (typeof obj.approved !== 'boolean') {\r\n errors.push({\r\n field: 'approved',\r\n message: 'approved must be a boolean',\r\n path: '/approved',\r\n code: 'INVALID_TYPE',\r\n value: obj.approved,\r\n });\r\n }\r\n\r\n // Validate summary (optional string)\r\n if (obj.summary !== undefined && typeof obj.summary !== 'string') {\r\n errors.push({\r\n field: 'summary',\r\n message: 'summary must be a string',\r\n path: '/summary',\r\n code: 'INVALID_TYPE',\r\n value: obj.summary,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Validate Product Owner output\r\n */\r\n private validateProductOwnerOutput(\r\n obj: Record<string, unknown>,\r\n errors: ValidationError[],\r\n warnings: string[]\r\n ): void {\r\n // Validate decision (required enum)\r\n const decisions: ProductOwnerDecision[] = [\r\n 'PROCEED',\r\n 'ITERATE',\r\n 'ABORT',\r\n ];\r\n if (!decisions.includes(obj.decision as ProductOwnerDecision)) {\r\n errors.push({\r\n field: 'decision',\r\n message: `decision must be one of: ${decisions.join(', ')}`,\r\n path: '/decision',\r\n code: 'INVALID_ENUM',\r\n value: obj.decision,\r\n });\r\n }\r\n\r\n // Validate rationale (required non-empty string)\r\n if (typeof obj.rationale !== 'string') {\r\n errors.push({\r\n field: 'rationale',\r\n message: 'rationale must be a string',\r\n path: '/rationale',\r\n code: 'INVALID_TYPE',\r\n value: obj.rationale,\r\n });\r\n } else if ((obj.rationale as string).length === 0) {\r\n errors.push({\r\n field: 'rationale',\r\n message: 'rationale must be a non-empty string',\r\n path: '/rationale',\r\n code: 'CONSTRAINT_VIOLATION',\r\n value: obj.rationale,\r\n });\r\n }\r\n\r\n // Validate deliverables_validated (required boolean)\r\n if (typeof obj.deliverables_validated !== 'boolean') {\r\n errors.push({\r\n field: 'deliverables_validated',\r\n message: 'deliverables_validated must be a boolean',\r\n path: '/deliverables_validated',\r\n code: 'INVALID_TYPE',\r\n value: obj.deliverables_validated,\r\n });\r\n }\r\n\r\n // Validate next_action (required string)\r\n if (typeof obj.next_action !== 'string') {\r\n errors.push({\r\n field: 'next_action',\r\n message: 'next_action must be a string',\r\n path: '/next_action',\r\n code: 'INVALID_TYPE',\r\n value: obj.next_action,\r\n });\r\n }\r\n\r\n // Validate consensus_score (optional number 0.0-1.0)\r\n if (obj.consensus_score !== undefined) {\r\n if (typeof obj.consensus_score !== 'number') {\r\n errors.push({\r\n field: 'consensus_score',\r\n message: 'consensus_score must be a number',\r\n path: '/consensus_score',\r\n code: 'INVALID_TYPE',\r\n value: obj.consensus_score,\r\n });\r\n } else if (\r\n obj.consensus_score < 0.0 ||\r\n obj.consensus_score > 1.0\r\n ) {\r\n errors.push({\r\n field: 'consensus_score',\r\n message: 'consensus_score must be between 0.0 and 1.0',\r\n path: '/consensus_score',\r\n code: 'CONSTRAINT_VIOLATION',\r\n value: obj.consensus_score,\r\n });\r\n }\r\n }\r\n\r\n // Validate gate_score (optional number 0.0-1.0)\r\n if (obj.gate_score !== undefined) {\r\n if (typeof obj.gate_score !== 'number') {\r\n errors.push({\r\n field: 'gate_score',\r\n message: 'gate_score must be a number',\r\n path: '/gate_score',\r\n code: 'INVALID_TYPE',\r\n value: obj.gate_score,\r\n });\r\n } else if (obj.gate_score < 0.0 || obj.gate_score > 1.0) {\r\n errors.push({\r\n field: 'gate_score',\r\n message: 'gate_score must be between 0.0 and 1.0',\r\n path: '/gate_score',\r\n code: 'CONSTRAINT_VIOLATION',\r\n value: obj.gate_score,\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Validate deliverable object\r\n */\r\n private validateDeliverable(\r\n deliverable: unknown,\r\n index: number,\r\n errors: ValidationError[]\r\n ): void {\r\n if (typeof deliverable !== 'object' || deliverable === null) {\r\n errors.push({\r\n field: `deliverables[${index}]`,\r\n message: 'deliverable must be an object',\r\n path: `/deliverables/${index}`,\r\n code: 'INVALID_TYPE',\r\n value: deliverable,\r\n });\r\n return;\r\n }\r\n\r\n const obj = deliverable as Record<string, unknown>;\r\n\r\n // Validate path (required non-empty string)\r\n if (typeof obj.path !== 'string' || obj.path.length === 0) {\r\n errors.push({\r\n field: `deliverables[${index}].path`,\r\n message: 'path must be a non-empty string',\r\n path: `/deliverables/${index}/path`,\r\n code: 'INVALID_TYPE',\r\n value: obj.path,\r\n });\r\n }\r\n\r\n // Validate type (required enum)\r\n const types: 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\n if (!types.includes(obj.type as DeliverableType)) {\r\n errors.push({\r\n field: `deliverables[${index}].type`,\r\n message: `type must be one of: ${types.join(', ')}`,\r\n path: `/deliverables/${index}/type`,\r\n code: 'INVALID_ENUM',\r\n value: obj.type,\r\n });\r\n }\r\n\r\n // Validate status (required enum)\r\n const statuses: DeliverableStatus[] = [\r\n 'created',\r\n 'modified',\r\n 'deleted',\r\n 'validated',\r\n 'pending',\r\n ];\r\n if (!statuses.includes(obj.status as DeliverableStatus)) {\r\n errors.push({\r\n field: `deliverables[${index}].status`,\r\n message: `status must be one of: ${statuses.join(', ')}`,\r\n path: `/deliverables/${index}/status`,\r\n code: 'INVALID_ENUM',\r\n value: obj.status,\r\n });\r\n }\r\n\r\n // Validate optional fields\r\n if (\r\n obj.size_bytes !== undefined &&\r\n (typeof obj.size_bytes !== 'number' ||\r\n !Number.isInteger(obj.size_bytes) ||\r\n obj.size_bytes < 0)\r\n ) {\r\n errors.push({\r\n field: `deliverables[${index}].size_bytes`,\r\n message: 'size_bytes must be a non-negative integer',\r\n path: `/deliverables/${index}/size_bytes`,\r\n code: 'INVALID_TYPE',\r\n value: obj.size_bytes,\r\n });\r\n }\r\n\r\n if (\r\n obj.lines !== undefined &&\r\n (typeof obj.lines !== 'number' ||\r\n !Number.isInteger(obj.lines) ||\r\n obj.lines < 0)\r\n ) {\r\n errors.push({\r\n field: `deliverables[${index}].lines`,\r\n message: 'lines must be a non-negative integer',\r\n path: `/deliverables/${index}/lines`,\r\n code: 'INVALID_TYPE',\r\n value: obj.lines,\r\n });\r\n }\r\n\r\n if (obj.checksum !== undefined && typeof obj.checksum !== 'string') {\r\n errors.push({\r\n field: `deliverables[${index}].checksum`,\r\n message: 'checksum must be a string',\r\n path: `/deliverables/${index}/checksum`,\r\n code: 'INVALID_TYPE',\r\n value: obj.checksum,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Validate issue object\r\n */\r\n private validateIssue(\r\n issue: unknown,\r\n index: number,\r\n errors: ValidationError[]\r\n ): void {\r\n if (typeof issue !== 'object' || issue === null) {\r\n errors.push({\r\n field: `issues[${index}]`,\r\n message: 'issue must be an object',\r\n path: `/issues/${index}`,\r\n code: 'INVALID_TYPE',\r\n value: issue,\r\n });\r\n return;\r\n }\r\n\r\n const obj = issue as Record<string, unknown>;\r\n\r\n // Validate severity (required enum)\r\n const severities: IssueSeverity[] = [\r\n 'critical',\r\n 'high',\r\n 'medium',\r\n 'low',\r\n 'info',\r\n ];\r\n if (!severities.includes(obj.severity as IssueSeverity)) {\r\n errors.push({\r\n field: `issues[${index}].severity`,\r\n message: `severity must be one of: ${severities.join(', ')}`,\r\n path: `/issues/${index}/severity`,\r\n code: 'INVALID_ENUM',\r\n value: obj.severity,\r\n });\r\n }\r\n\r\n // Validate category (required enum)\r\n const categories: 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\n if (!categories.includes(obj.category as IssueCategory)) {\r\n errors.push({\r\n field: `issues[${index}].category`,\r\n message: `category must be one of: ${categories.join(', ')}`,\r\n path: `/issues/${index}/category`,\r\n code: 'INVALID_ENUM',\r\n value: obj.category,\r\n });\r\n }\r\n\r\n // Validate message (required non-empty string)\r\n if (typeof obj.message !== 'string' || obj.message.length === 0) {\r\n errors.push({\r\n field: `issues[${index}].message`,\r\n message: 'message must be a non-empty string',\r\n path: `/issues/${index}/message`,\r\n code: 'INVALID_TYPE',\r\n value: obj.message,\r\n });\r\n }\r\n\r\n // Validate optional fields\r\n if (obj.location !== undefined && typeof obj.location !== 'string') {\r\n errors.push({\r\n field: `issues[${index}].location`,\r\n message: 'location must be a string',\r\n path: `/issues/${index}/location`,\r\n code: 'INVALID_TYPE',\r\n value: obj.location,\r\n });\r\n }\r\n\r\n if (\r\n obj.recommendation !== undefined &&\r\n typeof obj.recommendation !== 'string'\r\n ) {\r\n errors.push({\r\n field: `issues[${index}].recommendation`,\r\n message: 'recommendation must be a string',\r\n path: `/issues/${index}/recommendation`,\r\n code: 'INVALID_TYPE',\r\n value: obj.recommendation,\r\n });\r\n }\r\n\r\n if (obj.code !== undefined && typeof obj.code !== 'string') {\r\n errors.push({\r\n field: `issues[${index}].code`,\r\n message: 'code must be a string',\r\n path: `/issues/${index}/code`,\r\n code: 'INVALID_TYPE',\r\n value: obj.code,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Validate metrics object\r\n */\r\n private validateMetrics(\r\n metrics: Record<string, unknown>,\r\n errors: ValidationError[]\r\n ): void {\r\n // All metrics fields are optional numbers\r\n const knownMetrics = [\r\n 'files_created',\r\n 'files_modified',\r\n 'files_deleted',\r\n 'lines_of_code',\r\n 'test_coverage',\r\n 'tests_passed',\r\n 'tests_failed',\r\n 'execution_time_ms',\r\n 'memory_usage_mb',\r\n ];\r\n\r\n for (const key of knownMetrics) {\r\n if (metrics[key] !== undefined && typeof metrics[key] !== 'number') {\r\n errors.push({\r\n field: `metrics.${key}`,\r\n message: `${key} must be a number`,\r\n path: `/metrics/${key}`,\r\n code: 'INVALID_TYPE',\r\n value: metrics[key],\r\n });\r\n }\r\n }\r\n\r\n // Validate test_coverage range\r\n if (\r\n metrics.test_coverage !== undefined &&\r\n typeof metrics.test_coverage === 'number' &&\r\n (metrics.test_coverage < 0.0 || metrics.test_coverage > 1.0)\r\n ) {\r\n errors.push({\r\n field: 'metrics.test_coverage',\r\n message: 'test_coverage must be between 0.0 and 1.0',\r\n path: '/metrics/test_coverage',\r\n code: 'CONSTRAINT_VIOLATION',\r\n value: metrics.test_coverage,\r\n });\r\n }\r\n\r\n // Validate custom_metrics (if present)\r\n if (metrics.custom_metrics !== undefined) {\r\n if (\r\n typeof metrics.custom_metrics !== 'object' ||\r\n metrics.custom_metrics === null\r\n ) {\r\n errors.push({\r\n field: 'metrics.custom_metrics',\r\n message: 'custom_metrics must be an object',\r\n path: '/metrics/custom_metrics',\r\n code: 'INVALID_TYPE',\r\n value: metrics.custom_metrics,\r\n });\r\n } else {\r\n const customMetrics = metrics.custom_metrics as Record<string, unknown>;\r\n for (const [key, value] of Object.entries(customMetrics)) {\r\n if (typeof value !== 'number') {\r\n errors.push({\r\n field: `metrics.custom_metrics.${key}`,\r\n message: `custom_metrics.${key} must be a number`,\r\n path: `/metrics/custom_metrics/${key}`,\r\n code: 'INVALID_TYPE',\r\n value,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Check for unknown fields (not in known metrics or custom_metrics)\r\n for (const key of Object.keys(metrics)) {\r\n if (key !== 'custom_metrics' && !knownMetrics.includes(key)) {\r\n errors.push({\r\n field: `metrics.${key}`,\r\n message: `Unknown metric field '${key}'. Use 'custom_metrics' for extensibility.`,\r\n path: `/metrics/${key}`,\r\n code: 'UNKNOWN_FIELD',\r\n value: metrics[key],\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Validate error object\r\n */\r\n private validateError(\r\n error: unknown,\r\n index: number,\r\n errors: ValidationError[]\r\n ): void {\r\n if (typeof error !== 'object' || error === null) {\r\n errors.push({\r\n field: `errors[${index}]`,\r\n message: 'error must be an object',\r\n path: `/errors/${index}`,\r\n code: 'INVALID_TYPE',\r\n value: error,\r\n });\r\n return;\r\n }\r\n\r\n const obj = error as Record<string, unknown>;\r\n\r\n // Validate code (required string)\r\n if (typeof obj.code !== 'string') {\r\n errors.push({\r\n field: `errors[${index}].code`,\r\n message: 'code must be a string',\r\n path: `/errors/${index}/code`,\r\n code: 'INVALID_TYPE',\r\n value: obj.code,\r\n });\r\n }\r\n\r\n // Validate message (required non-empty string)\r\n if (typeof obj.message !== 'string' || obj.message.length === 0) {\r\n errors.push({\r\n field: `errors[${index}].message`,\r\n message: 'message must be a non-empty string',\r\n path: `/errors/${index}/message`,\r\n code: 'INVALID_TYPE',\r\n value: obj.message,\r\n });\r\n }\r\n\r\n // Validate optional fields\r\n if (obj.stack !== undefined && typeof obj.stack !== 'string') {\r\n errors.push({\r\n field: `errors[${index}].stack`,\r\n message: 'stack must be a string',\r\n path: `/errors/${index}/stack`,\r\n code: 'INVALID_TYPE',\r\n value: obj.stack,\r\n });\r\n }\r\n\r\n if (\r\n obj.context !== undefined &&\r\n (typeof obj.context !== 'object' || obj.context === null)\r\n ) {\r\n errors.push({\r\n field: `errors[${index}].context`,\r\n message: 'context must be an object',\r\n path: `/errors/${index}/context`,\r\n code: 'INVALID_TYPE',\r\n value: obj.context,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Validate metadata object\r\n */\r\n private validateMetadata(\r\n metadata: Record<string, unknown>,\r\n errors: ValidationError[]\r\n ): void {\r\n // Validate agent_type (required string)\r\n if (typeof metadata.agent_type !== 'string') {\r\n errors.push({\r\n field: 'metadata.agent_type',\r\n message: 'agent_type must be a string',\r\n path: '/metadata/agent_type',\r\n code: 'INVALID_TYPE',\r\n value: metadata.agent_type,\r\n });\r\n }\r\n\r\n // Validate optional fields\r\n if (\r\n metadata.agent_id !== undefined &&\r\n typeof metadata.agent_id !== 'string'\r\n ) {\r\n errors.push({\r\n field: 'metadata.agent_id',\r\n message: 'agent_id must be a string',\r\n path: '/metadata/agent_id',\r\n code: 'INVALID_TYPE',\r\n value: metadata.agent_id,\r\n });\r\n }\r\n\r\n if (\r\n metadata.execution_time_ms !== undefined &&\r\n (typeof metadata.execution_time_ms !== 'number' ||\r\n !Number.isInteger(metadata.execution_time_ms) ||\r\n metadata.execution_time_ms < 0)\r\n ) {\r\n errors.push({\r\n field: 'metadata.execution_time_ms',\r\n message: 'execution_time_ms must be a non-negative integer',\r\n path: '/metadata/execution_time_ms',\r\n code: 'INVALID_TYPE',\r\n value: metadata.execution_time_ms,\r\n });\r\n }\r\n\r\n if (\r\n metadata.timestamp !== undefined &&\r\n typeof metadata.timestamp !== 'string'\r\n ) {\r\n errors.push({\r\n field: 'metadata.timestamp',\r\n message: 'timestamp must be a string (ISO 8601 format)',\r\n path: '/metadata/timestamp',\r\n code: 'INVALID_TYPE',\r\n value: metadata.timestamp,\r\n });\r\n }\r\n\r\n if (\r\n metadata.swarm_id !== undefined &&\r\n typeof metadata.swarm_id !== 'string'\r\n ) {\r\n errors.push({\r\n field: 'metadata.swarm_id',\r\n message: 'swarm_id must be a string',\r\n path: '/metadata/swarm_id',\r\n code: 'INVALID_TYPE',\r\n value: metadata.swarm_id,\r\n });\r\n }\r\n\r\n if (\r\n metadata.iteration !== undefined &&\r\n (typeof metadata.iteration !== 'number' ||\r\n !Number.isInteger(metadata.iteration) ||\r\n metadata.iteration < 1)\r\n ) {\r\n errors.push({\r\n field: 'metadata.iteration',\r\n message: 'iteration must be a positive integer',\r\n path: '/metadata/iteration',\r\n code: 'INVALID_TYPE',\r\n value: metadata.iteration,\r\n });\r\n }\r\n\r\n if (metadata.mode !== undefined) {\r\n const modes: CFNLoopMode[] = ['mvp', 'standard', 'enterprise'];\r\n if (!modes.includes(metadata.mode as CFNLoopMode)) {\r\n errors.push({\r\n field: 'metadata.mode',\r\n message: `mode must be one of: ${modes.join(', ')}`,\r\n path: '/metadata/mode',\r\n code: 'INVALID_ENUM',\r\n value: metadata.mode,\r\n });\r\n }\r\n }\r\n\r\n if (\r\n metadata.context !== undefined &&\r\n (typeof metadata.context !== 'object' || metadata.context === null)\r\n ) {\r\n errors.push({\r\n field: 'metadata.context',\r\n message: 'context must be an object',\r\n path: '/metadata/context',\r\n code: 'INVALID_TYPE',\r\n value: metadata.context,\r\n });\r\n }\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 'Agent output 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}\\n`;\r\n output += ` ${error.message}\\n`;\r\n if (error.value !== undefined) {\r\n // Use sanitizeValue to prevent sensitive data leakage\r\n output += ` Current value: ${sanitizeValue(error.value, error.field)}\\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// ============================================================================\r\n// Singleton Instance and Convenience Functions\r\n// ============================================================================\r\n\r\nlet validatorInstance: AgentOutputValidator | null = null;\r\n\r\n/**\r\n * Get or create validator instance\r\n */\r\nexport function getValidator(): AgentOutputValidator {\r\n if (!validatorInstance) {\r\n validatorInstance = new AgentOutputValidator();\r\n }\r\n return validatorInstance;\r\n}\r\n\r\n/**\r\n * Validate agent output object\r\n */\r\nexport function validateAgentOutput(output: unknown): ValidationResult {\r\n return getValidator().validate(output);\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 * Validate Loop 3 output\r\n */\r\nexport function validateLoop3Output(output: unknown): ValidationResult {\r\n const result = getValidator().validate(output);\r\n if (result.valid && result.output_type !== 'loop3') {\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'output_type',\r\n message: \"Expected output_type 'loop3'\",\r\n path: '/output_type',\r\n code: 'INVALID_OUTPUT_TYPE',\r\n value: result.output_type,\r\n },\r\n ],\r\n warnings: [],\r\n };\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Validate Loop 2 output\r\n */\r\nexport function validateLoop2Output(output: unknown): ValidationResult {\r\n const result = getValidator().validate(output);\r\n if (result.valid && result.output_type !== 'loop2') {\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'output_type',\r\n message: \"Expected output_type 'loop2'\",\r\n path: '/output_type',\r\n code: 'INVALID_OUTPUT_TYPE',\r\n value: result.output_type,\r\n },\r\n ],\r\n warnings: [],\r\n };\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Validate Product Owner output\r\n */\r\nexport function validateProductOwnerOutput(output: unknown): ValidationResult {\r\n const result = getValidator().validate(output);\r\n if (result.valid && result.output_type !== 'product_owner') {\r\n return {\r\n valid: false,\r\n errors: [\r\n {\r\n field: 'output_type',\r\n message: \"Expected output_type 'product_owner'\",\r\n path: '/output_type',\r\n code: 'INVALID_OUTPUT_TYPE',\r\n value: result.output_type,\r\n },\r\n ],\r\n warnings: [],\r\n };\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Check if output is valid (boolean shortcut)\r\n */\r\nexport function isValidOutput(output: unknown): boolean {\r\n return getValidator().validate(output).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\nexport default AgentOutputValidator;\r\n"],"names":["sanitizeValue","value","path","sensitivePatterns","lowerPath","toLowerCase","isSensitive","some","pattern","includes","str","JSON","stringify","maxLength","length","substring","AgentOutputValidator","validate","output","errors","warnings","valid","field","message","code","obj","outputType","output_type","push","validateBaseOutput","validateLoop3Output","validateLoop2Output","validateProductOwnerOutput","validateJSON","jsonString","parse","error","Error","String","success","confidence","iteration","Number","isInteger","Array","isArray","i","validateError","metadata","validateMetadata","deliverables","validateDeliverable","metrics","undefined","validateMetrics","summary","validationTypes","validation_type","join","issues","validateIssue","recommendations","approved","decisions","decision","rationale","deliverables_validated","next_action","consensus_score","gate_score","deliverable","index","types","type","statuses","status","size_bytes","lines","checksum","issue","severities","severity","categories","category","location","recommendation","knownMetrics","key","test_coverage","custom_metrics","customMetrics","Object","entries","keys","stack","context","agent_type","agent_id","execution_time_ms","timestamp","swarm_id","mode","modes","formatErrors","result","warning","validatorInstance","getValidator","validateAgentOutput","isValidOutput","resetValidator"],"mappings":"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"}
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact Registry TypeScript API
|
|
3
|
+
* Provides centralized artifact management with TTL-based cleanup
|
|
4
|
+
* Version: 1.0.0
|
|
5
|
+
*/ import Database from 'better-sqlite3';
|
|
6
|
+
import { createHash } from 'crypto';
|
|
7
|
+
import { readFileSync, existsSync, mkdirSync, statSync } from 'fs';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Error Classes
|
|
11
|
+
// ============================================================================
|
|
12
|
+
export class ArtifactRegistryError extends Error {
|
|
13
|
+
code;
|
|
14
|
+
details;
|
|
15
|
+
constructor(message, code, details){
|
|
16
|
+
super(message), this.code = code, this.details = details;
|
|
17
|
+
this.name = 'ArtifactRegistryError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class ArtifactNotFoundError extends ArtifactRegistryError {
|
|
21
|
+
constructor(id){
|
|
22
|
+
super(`Artifact not found: ${id}`, 'ARTIFACT_NOT_FOUND', {
|
|
23
|
+
id
|
|
24
|
+
});
|
|
25
|
+
this.name = 'ArtifactNotFoundError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class ArtifactValidationError extends ArtifactRegistryError {
|
|
29
|
+
constructor(message, details){
|
|
30
|
+
super(message, 'VALIDATION_ERROR', details);
|
|
31
|
+
this.name = 'ArtifactValidationError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class ArtifactDatabaseError extends ArtifactRegistryError {
|
|
35
|
+
constructor(message, details){
|
|
36
|
+
super(message, 'DATABASE_ERROR', details);
|
|
37
|
+
this.name = 'ArtifactDatabaseError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Artifact Registry Class
|
|
42
|
+
// ============================================================================
|
|
43
|
+
export class ArtifactRegistry {
|
|
44
|
+
db;
|
|
45
|
+
static instance = null;
|
|
46
|
+
constructor(dbPath){
|
|
47
|
+
try {
|
|
48
|
+
// Ensure database directory exists
|
|
49
|
+
const dbDir = dirname(dbPath);
|
|
50
|
+
if (!existsSync(dbDir)) {
|
|
51
|
+
mkdirSync(dbDir, {
|
|
52
|
+
recursive: true
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
this.db = new Database(dbPath);
|
|
56
|
+
this.db.pragma('journal_mode = WAL'); // Write-Ahead Logging for concurrency
|
|
57
|
+
this.db.pragma('foreign_keys = ON');
|
|
58
|
+
this.db.pragma('synchronous = NORMAL');
|
|
59
|
+
this.initializeSchema();
|
|
60
|
+
} catch (error) {
|
|
61
|
+
throw new ArtifactDatabaseError(`Failed to initialize database: ${error instanceof Error ? error.message : String(error)}`, {
|
|
62
|
+
dbPath,
|
|
63
|
+
error
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get singleton instance (optional pattern)
|
|
69
|
+
*/ static getInstance(dbPath) {
|
|
70
|
+
if (!ArtifactRegistry.instance) {
|
|
71
|
+
if (!dbPath) {
|
|
72
|
+
throw new ArtifactDatabaseError('Database path required for first initialization', {});
|
|
73
|
+
}
|
|
74
|
+
ArtifactRegistry.instance = new ArtifactRegistry(dbPath);
|
|
75
|
+
}
|
|
76
|
+
return ArtifactRegistry.instance;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Initialize database schema
|
|
80
|
+
*/ initializeSchema() {
|
|
81
|
+
try {
|
|
82
|
+
const schemaPath = join(__dirname, '../database/artifact-registry-schema.sql');
|
|
83
|
+
if (!existsSync(schemaPath)) {
|
|
84
|
+
throw new Error(`Schema file not found: ${schemaPath}`);
|
|
85
|
+
}
|
|
86
|
+
const schema = readFileSync(schemaPath, 'utf-8');
|
|
87
|
+
// Step 1: Remove multi-line comments FIRST (they can contain semicolons)
|
|
88
|
+
const withoutMultiLineComments = schema.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
89
|
+
// Step 2: Remove single-line comments
|
|
90
|
+
const cleanedSchema = withoutMultiLineComments.split('\n').filter((line)=>{
|
|
91
|
+
const trimmed = line.trim();
|
|
92
|
+
return trimmed.length > 0 && !trimmed.startsWith('--');
|
|
93
|
+
}).join('\n');
|
|
94
|
+
// Step 3: Execute entire schema as one block
|
|
95
|
+
// SQLite's exec() can handle multiple statements including triggers with internal semicolons
|
|
96
|
+
this.db.exec(cleanedSchema);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
throw new ArtifactDatabaseError(`Failed to initialize schema: ${error instanceof Error ? error.message : String(error)}`, {
|
|
99
|
+
error
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Generate unique artifact ID
|
|
105
|
+
*/ generateId() {
|
|
106
|
+
const timestamp = Date.now();
|
|
107
|
+
const random = Math.random().toString(36).substring(2, 15);
|
|
108
|
+
return `artifact-${timestamp}-${random}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Calculate checksum for file
|
|
112
|
+
*/ calculateChecksum(filePath) {
|
|
113
|
+
try {
|
|
114
|
+
const content = readFileSync(filePath);
|
|
115
|
+
return createHash('sha256').update(content).digest('hex');
|
|
116
|
+
} catch (error) {
|
|
117
|
+
throw new ArtifactValidationError(`Failed to calculate checksum: ${error instanceof Error ? error.message : String(error)}`, {
|
|
118
|
+
filePath,
|
|
119
|
+
error
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate artifact metadata
|
|
125
|
+
*/ validateMetadata(metadata) {
|
|
126
|
+
if (!metadata.name || metadata.name.trim().length === 0) {
|
|
127
|
+
throw new ArtifactValidationError('Artifact name is required');
|
|
128
|
+
}
|
|
129
|
+
if (!metadata.type) {
|
|
130
|
+
throw new ArtifactValidationError('Artifact type is required');
|
|
131
|
+
}
|
|
132
|
+
const validTypes = [
|
|
133
|
+
'code',
|
|
134
|
+
'documentation',
|
|
135
|
+
'test',
|
|
136
|
+
'config',
|
|
137
|
+
'binary',
|
|
138
|
+
'data',
|
|
139
|
+
'model',
|
|
140
|
+
'report',
|
|
141
|
+
'other'
|
|
142
|
+
];
|
|
143
|
+
if (!validTypes.includes(metadata.type)) {
|
|
144
|
+
throw new ArtifactValidationError(`Invalid artifact type: ${metadata.type}`, {
|
|
145
|
+
validTypes
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (!metadata.storage_location || metadata.storage_location.trim().length === 0) {
|
|
149
|
+
throw new ArtifactValidationError('Storage location is required');
|
|
150
|
+
}
|
|
151
|
+
if (metadata.acl_level !== undefined && (metadata.acl_level < 1 || metadata.acl_level > 5)) {
|
|
152
|
+
throw new ArtifactValidationError('ACL level must be between 1 and 5', {
|
|
153
|
+
acl_level: metadata.acl_level
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
if (metadata.retention_policy) {
|
|
157
|
+
const validPolicies = [
|
|
158
|
+
'ephemeral',
|
|
159
|
+
'standard',
|
|
160
|
+
'permanent',
|
|
161
|
+
'custom'
|
|
162
|
+
];
|
|
163
|
+
if (!validPolicies.includes(metadata.retention_policy)) {
|
|
164
|
+
throw new ArtifactValidationError(`Invalid retention policy: ${metadata.retention_policy}`, {
|
|
165
|
+
validPolicies
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create new artifact
|
|
172
|
+
*/ createArtifact(metadata) {
|
|
173
|
+
try {
|
|
174
|
+
// Validate metadata
|
|
175
|
+
this.validateMetadata(metadata);
|
|
176
|
+
// Generate ID
|
|
177
|
+
const id = this.generateId();
|
|
178
|
+
// Calculate file-based metadata if storage location exists
|
|
179
|
+
let size_bytes;
|
|
180
|
+
let checksum;
|
|
181
|
+
let content_hash;
|
|
182
|
+
if (existsSync(metadata.storage_location)) {
|
|
183
|
+
const stats = statSync(metadata.storage_location);
|
|
184
|
+
size_bytes = stats.size;
|
|
185
|
+
checksum = this.calculateChecksum(metadata.storage_location);
|
|
186
|
+
if (metadata.content) {
|
|
187
|
+
content_hash = createHash('sha256').update(metadata.content).digest('hex');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Set defaults
|
|
191
|
+
const retention_days = metadata.retention_days ?? (metadata.retention_policy === 'ephemeral' ? 7 : metadata.retention_policy === 'permanent' ? 0 : 30 // standard
|
|
192
|
+
);
|
|
193
|
+
const retention_policy = metadata.retention_policy ?? 'standard';
|
|
194
|
+
// Prepare insert statement
|
|
195
|
+
const stmt = this.db.prepare(`
|
|
196
|
+
INSERT INTO artifacts (
|
|
197
|
+
id, name, type, format, content, content_hash, size_bytes,
|
|
198
|
+
storage_location, checksum, is_compressed, compression_type,
|
|
199
|
+
swarm_id, agent_id, task_id, version, parent_artifact_id,
|
|
200
|
+
artifact_chain, tags, metadata, acl_level,
|
|
201
|
+
retention_days, retention_policy, status
|
|
202
|
+
) VALUES (
|
|
203
|
+
?, ?, ?, ?, ?, ?, ?,
|
|
204
|
+
?, ?, ?, ?,
|
|
205
|
+
?, ?, ?, ?, ?,
|
|
206
|
+
?, ?, ?, ?,
|
|
207
|
+
?, ?, ?
|
|
208
|
+
)
|
|
209
|
+
`);
|
|
210
|
+
// Execute insert
|
|
211
|
+
stmt.run(id, metadata.name, metadata.type, metadata.format ?? null, metadata.content ?? null, content_hash ?? null, size_bytes ?? null, metadata.storage_location, checksum ?? null, metadata.is_compressed ? 1 : 0, metadata.compression_type ?? null, metadata.swarm_id ?? null, metadata.agent_id ?? null, metadata.task_id ?? null, metadata.version ?? 1, metadata.parent_artifact_id ?? null, metadata.artifact_chain ? JSON.stringify(metadata.artifact_chain) : null, metadata.tags ? JSON.stringify(metadata.tags) : null, metadata.metadata ? JSON.stringify(metadata.metadata) : null, metadata.acl_level ?? 2, retention_days, retention_policy, 'active');
|
|
212
|
+
// Retrieve and return created artifact
|
|
213
|
+
const artifact = this.getArtifact(id);
|
|
214
|
+
if (!artifact) {
|
|
215
|
+
throw new ArtifactDatabaseError('Failed to retrieve created artifact', {
|
|
216
|
+
id
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
return artifact;
|
|
220
|
+
} catch (error) {
|
|
221
|
+
if (error instanceof ArtifactRegistryError) {
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
throw new ArtifactDatabaseError(`Failed to create artifact: ${error instanceof Error ? error.message : String(error)}`, {
|
|
225
|
+
metadata,
|
|
226
|
+
error
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Get artifact by ID
|
|
232
|
+
*/ getArtifact(id) {
|
|
233
|
+
try {
|
|
234
|
+
const stmt = this.db.prepare('SELECT * FROM artifacts WHERE id = ?');
|
|
235
|
+
const row = stmt.get(id);
|
|
236
|
+
return row ?? null;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
throw new ArtifactDatabaseError(`Failed to get artifact: ${error instanceof Error ? error.message : String(error)}`, {
|
|
239
|
+
id,
|
|
240
|
+
error
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* List artifacts with optional filters
|
|
246
|
+
*/ listArtifacts(filters) {
|
|
247
|
+
try {
|
|
248
|
+
let query = 'SELECT * FROM artifacts WHERE 1=1';
|
|
249
|
+
const params = [];
|
|
250
|
+
if (filters) {
|
|
251
|
+
if (filters.type) {
|
|
252
|
+
query += ' AND type = ?';
|
|
253
|
+
params.push(filters.type);
|
|
254
|
+
}
|
|
255
|
+
if (filters.status) {
|
|
256
|
+
query += ' AND status = ?';
|
|
257
|
+
params.push(filters.status);
|
|
258
|
+
}
|
|
259
|
+
if (filters.retention_policy) {
|
|
260
|
+
query += ' AND retention_policy = ?';
|
|
261
|
+
params.push(filters.retention_policy);
|
|
262
|
+
}
|
|
263
|
+
if (filters.swarm_id) {
|
|
264
|
+
query += ' AND swarm_id = ?';
|
|
265
|
+
params.push(filters.swarm_id);
|
|
266
|
+
}
|
|
267
|
+
if (filters.agent_id) {
|
|
268
|
+
query += ' AND agent_id = ?';
|
|
269
|
+
params.push(filters.agent_id);
|
|
270
|
+
}
|
|
271
|
+
if (filters.task_id) {
|
|
272
|
+
query += ' AND task_id = ?';
|
|
273
|
+
params.push(filters.task_id);
|
|
274
|
+
}
|
|
275
|
+
if (filters.cleanup_eligible !== undefined) {
|
|
276
|
+
query += ' AND cleanup_eligible = ?';
|
|
277
|
+
params.push(filters.cleanup_eligible ? 1 : 0);
|
|
278
|
+
}
|
|
279
|
+
if (filters.created_after) {
|
|
280
|
+
query += ' AND created_at >= ?';
|
|
281
|
+
params.push(filters.created_after.toISOString());
|
|
282
|
+
}
|
|
283
|
+
if (filters.created_before) {
|
|
284
|
+
query += ' AND created_at <= ?';
|
|
285
|
+
params.push(filters.created_before.toISOString());
|
|
286
|
+
}
|
|
287
|
+
if (filters.expires_before) {
|
|
288
|
+
query += ' AND expires_at IS NOT NULL AND expires_at <= ?';
|
|
289
|
+
params.push(filters.expires_before.toISOString());
|
|
290
|
+
}
|
|
291
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
292
|
+
// JSON search for tags (SQLite JSON support)
|
|
293
|
+
for (const tag of filters.tags){
|
|
294
|
+
query += ` AND tags LIKE ?`;
|
|
295
|
+
params.push(`%"${tag}"%`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
query += ' ORDER BY created_at DESC';
|
|
300
|
+
if (filters?.limit) {
|
|
301
|
+
query += ' LIMIT ?';
|
|
302
|
+
params.push(filters.limit);
|
|
303
|
+
}
|
|
304
|
+
if (filters?.offset) {
|
|
305
|
+
query += ' OFFSET ?';
|
|
306
|
+
params.push(filters.offset);
|
|
307
|
+
}
|
|
308
|
+
const stmt = this.db.prepare(query);
|
|
309
|
+
return stmt.all(...params);
|
|
310
|
+
} catch (error) {
|
|
311
|
+
throw new ArtifactDatabaseError(`Failed to list artifacts: ${error instanceof Error ? error.message : String(error)}`, {
|
|
312
|
+
filters,
|
|
313
|
+
error
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Archive artifact (mark as archived)
|
|
319
|
+
*/ archiveArtifact(id) {
|
|
320
|
+
try {
|
|
321
|
+
const artifact = this.getArtifact(id);
|
|
322
|
+
if (!artifact) {
|
|
323
|
+
throw new ArtifactNotFoundError(id);
|
|
324
|
+
}
|
|
325
|
+
if (artifact.status === 'deleted') {
|
|
326
|
+
throw new ArtifactValidationError('Cannot archive deleted artifact', {
|
|
327
|
+
id,
|
|
328
|
+
status: artifact.status
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const stmt = this.db.prepare(`
|
|
332
|
+
UPDATE artifacts
|
|
333
|
+
SET status = 'archived',
|
|
334
|
+
archived_at = CURRENT_TIMESTAMP,
|
|
335
|
+
updated_at = CURRENT_TIMESTAMP
|
|
336
|
+
WHERE id = ?
|
|
337
|
+
`);
|
|
338
|
+
stmt.run(id);
|
|
339
|
+
const updated = this.getArtifact(id);
|
|
340
|
+
if (!updated) {
|
|
341
|
+
throw new ArtifactDatabaseError('Failed to retrieve archived artifact', {
|
|
342
|
+
id
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return updated;
|
|
346
|
+
} catch (error) {
|
|
347
|
+
if (error instanceof ArtifactRegistryError) {
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
350
|
+
throw new ArtifactDatabaseError(`Failed to archive artifact: ${error instanceof Error ? error.message : String(error)}`, {
|
|
351
|
+
id,
|
|
352
|
+
error
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Delete artifact (soft delete - mark as deleted)
|
|
358
|
+
*/ deleteArtifact(id) {
|
|
359
|
+
try {
|
|
360
|
+
const artifact = this.getArtifact(id);
|
|
361
|
+
if (!artifact) {
|
|
362
|
+
throw new ArtifactNotFoundError(id);
|
|
363
|
+
}
|
|
364
|
+
const stmt = this.db.prepare(`
|
|
365
|
+
UPDATE artifacts
|
|
366
|
+
SET status = 'deleted',
|
|
367
|
+
deleted_at = CURRENT_TIMESTAMP,
|
|
368
|
+
updated_at = CURRENT_TIMESTAMP
|
|
369
|
+
WHERE id = ?
|
|
370
|
+
`);
|
|
371
|
+
stmt.run(id);
|
|
372
|
+
const updated = this.getArtifact(id);
|
|
373
|
+
if (!updated) {
|
|
374
|
+
throw new ArtifactDatabaseError('Failed to retrieve deleted artifact', {
|
|
375
|
+
id
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
return updated;
|
|
379
|
+
} catch (error) {
|
|
380
|
+
if (error instanceof ArtifactRegistryError) {
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
383
|
+
throw new ArtifactDatabaseError(`Failed to delete artifact: ${error instanceof Error ? error.message : String(error)}`, {
|
|
384
|
+
id,
|
|
385
|
+
error
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Get artifact statistics by retention policy
|
|
391
|
+
*/ getStatsByRetentionPolicy() {
|
|
392
|
+
try {
|
|
393
|
+
const stmt = this.db.prepare(`
|
|
394
|
+
SELECT
|
|
395
|
+
retention_policy,
|
|
396
|
+
COUNT(*) as total,
|
|
397
|
+
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active,
|
|
398
|
+
SUM(CASE WHEN status = 'archived' THEN 1 ELSE 0 END) as archived,
|
|
399
|
+
SUM(CASE WHEN status = 'deleted' THEN 1 ELSE 0 END) as deleted,
|
|
400
|
+
SUM(CASE WHEN cleanup_eligible = 1 THEN 1 ELSE 0 END) as cleanup_eligible,
|
|
401
|
+
COALESCE(SUM(size_bytes), 0) as total_size_bytes
|
|
402
|
+
FROM artifacts
|
|
403
|
+
GROUP BY retention_policy
|
|
404
|
+
`);
|
|
405
|
+
const rows = stmt.all();
|
|
406
|
+
const stats = {};
|
|
407
|
+
for (const row of rows){
|
|
408
|
+
const { retention_policy, ...statsData } = row;
|
|
409
|
+
stats[retention_policy] = statsData;
|
|
410
|
+
}
|
|
411
|
+
return stats;
|
|
412
|
+
} catch (error) {
|
|
413
|
+
throw new ArtifactDatabaseError(`Failed to get statistics: ${error instanceof Error ? error.message : String(error)}`, {
|
|
414
|
+
error
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Find expired artifacts eligible for cleanup
|
|
420
|
+
*/ findExpiredArtifacts() {
|
|
421
|
+
try {
|
|
422
|
+
const stmt = this.db.prepare(`
|
|
423
|
+
SELECT * FROM artifacts
|
|
424
|
+
WHERE status = 'active'
|
|
425
|
+
AND expires_at IS NOT NULL
|
|
426
|
+
AND datetime('now') >= expires_at
|
|
427
|
+
ORDER BY created_at ASC
|
|
428
|
+
`);
|
|
429
|
+
return stmt.all();
|
|
430
|
+
} catch (error) {
|
|
431
|
+
throw new ArtifactDatabaseError(`Failed to find expired artifacts: ${error instanceof Error ? error.message : String(error)}`, {
|
|
432
|
+
error
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Close database connection
|
|
438
|
+
*/ close() {
|
|
439
|
+
this.db.close();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
//# sourceMappingURL=artifact-registry.js.map
|