icdev 1.0.0__py3-none-any.whl
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.
- icdev/__init__.py +18 -0
- icdev/_paths.py +85 -0
- icdev/_version.py +3 -0
- icdev/data/__init__.py +1 -0
- icdev/data/args/__init__.py +1 -0
- icdev/data/args/agent_authority.yaml +61 -0
- icdev/data/args/agent_config.yaml +355 -0
- icdev/data/args/agentic_fitness.yaml +31 -0
- icdev/data/args/ai_governance_config.yaml +137 -0
- icdev/data/args/atlas_critique_config.yaml +66 -0
- icdev/data/args/bedrock_models.yaml +63 -0
- icdev/data/args/cicd_config.yaml +82 -0
- icdev/data/args/classification_config.yaml +232 -0
- icdev/data/args/cli_config.yaml +154 -0
- icdev/data/args/cloud_config.yaml +63 -0
- icdev/data/args/code_pattern_config.yaml +151 -0
- icdev/data/args/code_quality_config.yaml +47 -0
- icdev/data/args/companion_registry.yaml +202 -0
- icdev/data/args/context_config.yaml +82 -0
- icdev/data/args/csp_monitor_config.yaml +268 -0
- icdev/data/args/cui_markings.yaml +35 -0
- icdev/data/args/db_config.yaml +40 -0
- icdev/data/args/deployment_profiles.yaml +248 -0
- icdev/data/args/dev_profile_config.yaml +144 -0
- icdev/data/args/devsecops_config.yaml +286 -0
- icdev/data/args/endpoint_security_config.yaml +137 -0
- icdev/data/args/extension_config.yaml +79 -0
- icdev/data/args/file_access_tiers.yaml +88 -0
- icdev/data/args/framework_registry.yaml +415 -0
- icdev/data/args/innovation_config.yaml +431 -0
- icdev/data/args/installation_manifest.yaml +1087 -0
- icdev/data/args/llm_config.yaml +495 -0
- icdev/data/args/maintenance_config.yaml +55 -0
- icdev/data/args/memory_config.yaml +83 -0
- icdev/data/args/monitoring_config.yaml +127 -0
- icdev/data/args/mosa_config.yaml +190 -0
- icdev/data/args/nlq_config.yaml +35 -0
- icdev/data/args/observability_config.yaml +39 -0
- icdev/data/args/observability_tracing_config.yaml +170 -0
- icdev/data/args/oscal_tools_config.yaml +43 -0
- icdev/data/args/owasp_agentic_config.yaml +171 -0
- icdev/data/args/phase_registry.yaml +618 -0
- icdev/data/args/project_defaults.yaml +235 -0
- icdev/data/args/prompt_chains.yaml +163 -0
- icdev/data/args/resilience_config.yaml +50 -0
- icdev/data/args/ricoas_config.yaml +191 -0
- icdev/data/args/role_personas.yaml +362 -0
- icdev/data/args/scaling_config.yaml +176 -0
- icdev/data/args/security_gates.yaml +685 -0
- icdev/data/args/skill_injection_config.yaml +322 -0
- icdev/data/args/spec_config.yaml +53 -0
- icdev/data/args/supply_chain_config.yaml +76 -0
- icdev/data/args/translation_config.yaml +228 -0
- icdev/data/args/workflow_templates/ato_acceleration.yaml +54 -0
- icdev/data/args/workflow_templates/build_deploy.yaml +63 -0
- icdev/data/args/workflow_templates/full_compliance.yaml +43 -0
- icdev/data/args/workflow_templates/security_hardening.yaml +55 -0
- icdev/data/args/worktree_config.yaml +34 -0
- icdev/data/args/zta_config.yaml +247 -0
- icdev/data/context/__init__.py +1 -0
- icdev/data/context/agent/__init__.py +1 -0
- icdev/data/context/agent/response_schemas/__init__.py +1 -0
- icdev/data/context/agent/response_schemas/debate_position.json +46 -0
- icdev/data/context/agent/response_schemas/fitness_scorecard.json +74 -0
- icdev/data/context/agent/response_schemas/review_decision.json +39 -0
- icdev/data/context/agent/response_schemas/task_decomposition.json +82 -0
- icdev/data/context/agent/response_schemas/veto_decision.json +40 -0
- icdev/data/context/agentic/__init__.py +1 -0
- icdev/data/context/agentic/architecture_patterns.md +269 -0
- icdev/data/context/agentic/capability_registry.yaml +202 -0
- icdev/data/context/agentic/csp_mcp_registry.yaml +280 -0
- icdev/data/context/agentic/fitness_rubric.md +56 -0
- icdev/data/context/agentic/governance_baseline.md +205 -0
- icdev/data/context/ci/__init__.py +1 -0
- icdev/data/context/ci/worktree_templates.json +44 -0
- icdev/data/context/cloud/__init__.py +1 -0
- icdev/data/context/cloud/csp_service_registry.json +739 -0
- icdev/data/context/compliance/__init__.py +1 -0
- icdev/data/context/compliance/atlas_mitigations.json +293 -0
- icdev/data/context/compliance/atlas_techniques.json +833 -0
- icdev/data/context/compliance/cisa_sbd_requirements.json +432 -0
- icdev/data/context/compliance/cjis_security_policy.json +522 -0
- icdev/data/context/compliance/cmmc_practices.json +2494 -0
- icdev/data/context/compliance/cmmc_report_template.md +142 -0
- icdev/data/context/compliance/cnssi_1253_overlay.json +109 -0
- icdev/data/context/compliance/control_crosswalk.json +1914 -0
- icdev/data/context/compliance/control_families/__init__.py +1 -0
- icdev/data/context/compliance/csp_certifications.json +251 -0
- icdev/data/context/compliance/cssp_report_template.md +193 -0
- icdev/data/context/compliance/cui_templates/__init__.py +1 -0
- icdev/data/context/compliance/cui_templates/banner_block.txt +4 -0
- icdev/data/context/compliance/cui_templates/code_header.txt +8 -0
- icdev/data/context/compliance/cui_templates/document_template.md +35 -0
- icdev/data/context/compliance/data_type_framework_map.json +321 -0
- icdev/data/context/compliance/data_type_registry.json +147 -0
- icdev/data/context/compliance/dod_cssp_8530.json +463 -0
- icdev/data/context/compliance/eu_ai_act_annex_iii.json +108 -0
- icdev/data/context/compliance/export_templates/__init__.py +1 -0
- icdev/data/context/compliance/export_templates/emass_controls.csv.j2 +4 -0
- icdev/data/context/compliance/export_templates/evidence_package.md.j2 +39 -0
- icdev/data/context/compliance/export_templates/executive_summary.md.j2 +55 -0
- icdev/data/context/compliance/export_templates/poam_tracking.csv.j2 +4 -0
- icdev/data/context/compliance/fedramp_20x_ksi_schemas.json +133 -0
- icdev/data/context/compliance/fedramp_high_baseline.json +4370 -0
- icdev/data/context/compliance/fedramp_moderate_baseline.json +2183 -0
- icdev/data/context/compliance/fedramp_report_template.md +181 -0
- icdev/data/context/compliance/fips_200_areas.json +362 -0
- icdev/data/context/compliance/gao_ai_accountability.json +262 -0
- icdev/data/context/compliance/hipaa_security_rule.json +720 -0
- icdev/data/context/compliance/hitrust_csf_v11.json +930 -0
- icdev/data/context/compliance/impact_level_profiles.json +251 -0
- icdev/data/context/compliance/incident_response_template.md +1110 -0
- icdev/data/context/compliance/iso27001_2022_controls.json +750 -0
- icdev/data/context/compliance/iso27001_nist_bridge.json +382 -0
- icdev/data/context/compliance/iso42001_controls.json +254 -0
- icdev/data/context/compliance/ivv_checklist_template.md +80 -0
- icdev/data/context/compliance/ivv_report_template.md +116 -0
- icdev/data/context/compliance/ivv_requirements.json +372 -0
- icdev/data/context/compliance/mosa_crosswalk.json +327 -0
- icdev/data/context/compliance/mosa_framework.json +250 -0
- icdev/data/context/compliance/narrative_templates/AC.md.j2 +101 -0
- icdev/data/context/compliance/narrative_templates/AU.md.j2 +106 -0
- icdev/data/context/compliance/narrative_templates/IA.md.j2 +104 -0
- icdev/data/context/compliance/narrative_templates/SC.md.j2 +102 -0
- icdev/data/context/compliance/narrative_templates/SI.md.j2 +111 -0
- icdev/data/context/compliance/narrative_templates/__init__.py +1 -0
- icdev/data/context/compliance/narrative_templates/default.md.j2 +50 -0
- icdev/data/context/compliance/narrative_templates/executive_summary.j2 +27 -0
- icdev/data/context/compliance/narrative_templates/poam_milestone.j2 +19 -0
- icdev/data/context/compliance/narrative_templates/ssp_section.j2 +11 -0
- icdev/data/context/compliance/nist_800_171_controls.json +1552 -0
- icdev/data/context/compliance/nist_800_207_crosswalk.json +399 -0
- icdev/data/context/compliance/nist_800_207_zta.json +258 -0
- icdev/data/context/compliance/nist_800_53.json +324 -0
- icdev/data/context/compliance/nist_ai_600_1_genai.json +326 -0
- icdev/data/context/compliance/nist_ai_rmf.json +206 -0
- icdev/data/context/compliance/nist_sp_800_60_types.json +1667 -0
- icdev/data/context/compliance/omb_m25_21_high_impact_ai.json +248 -0
- icdev/data/context/compliance/omb_m26_04_unbiased_ai.json +262 -0
- icdev/data/context/compliance/owasp_agentic_asi.json +133 -0
- icdev/data/context/compliance/owasp_agentic_threats.json +285 -0
- icdev/data/context/compliance/owasp_llm_top10.json +274 -0
- icdev/data/context/compliance/pci_dss_v4.json +510 -0
- icdev/data/context/compliance/poam_template.md +117 -0
- icdev/data/context/compliance/safeai_controls.json +512 -0
- icdev/data/context/compliance/sbd_report_template.md +77 -0
- icdev/data/context/compliance/siem_config_templates/__init__.py +1 -0
- icdev/data/context/compliance/siem_config_templates/filebeat.yml +213 -0
- icdev/data/context/compliance/siem_config_templates/log_sources.json +208 -0
- icdev/data/context/compliance/soc2_trust_criteria.json +661 -0
- icdev/data/context/compliance/ssp_template.md +432 -0
- icdev/data/context/compliance/stig_templates/__init__.py +1 -0
- icdev/data/context/compliance/stig_templates/webapp_stig.json +139 -0
- icdev/data/context/compliance/xai_requirements.json +108 -0
- icdev/data/context/dashboard/__init__.py +1 -0
- icdev/data/context/dashboard/nlq_examples.json +50 -0
- icdev/data/context/dashboard/schema_descriptions.json +23 -0
- icdev/data/context/integration/__init__.py +1 -0
- icdev/data/context/integration/approval_workflows.json +32 -0
- icdev/data/context/integration/gitlab_field_mappings.json +33 -0
- icdev/data/context/integration/jira_field_mappings.json +32 -0
- icdev/data/context/integration/reqif_export_schema.json +23 -0
- icdev/data/context/integration/servicenow_field_mappings.json +22 -0
- icdev/data/context/languages/__init__.py +1 -0
- icdev/data/context/languages/framework_patterns.json +205 -0
- icdev/data/context/languages/language_registry.json +279 -0
- icdev/data/context/llm/__init__.py +1 -0
- icdev/data/context/llm/example_provider.py +86 -0
- icdev/data/context/mbse/__init__.py +1 -0
- icdev/data/context/mbse/des_report_template.md +162 -0
- icdev/data/context/mbse/des_requirements.json +411 -0
- icdev/data/context/mbse/digital_thread_patterns.json +403 -0
- icdev/data/context/mbse/reqif_schema.json +280 -0
- icdev/data/context/mbse/sysml_element_types.json +432 -0
- icdev/data/context/modernization/__init__.py +1 -0
- icdev/data/context/modernization/db_type_mappings.json +148 -0
- icdev/data/context/modernization/decomposition_patterns.json +284 -0
- icdev/data/context/modernization/framework_migration_patterns.json +359 -0
- icdev/data/context/modernization/migration_report_template.md +168 -0
- icdev/data/context/modernization/seven_rs_catalog.json +369 -0
- icdev/data/context/modernization/version_upgrade_rules.json +279 -0
- icdev/data/context/oscal/NIST_SP-800-53_rev5_catalog.json +254987 -0
- icdev/data/context/oscal/README.md +43 -0
- icdev/data/context/patterns/__init__.py +1 -0
- icdev/data/context/profiles/__init__.py +1 -0
- icdev/data/context/profiles/dod_baseline_v1.yaml +145 -0
- icdev/data/context/profiles/fedramp_baseline_v1.yaml +143 -0
- icdev/data/context/profiles/financial_baseline_v1.yaml +142 -0
- icdev/data/context/profiles/healthcare_baseline_v1.yaml +135 -0
- icdev/data/context/profiles/law_enforcement_v1.yaml +129 -0
- icdev/data/context/profiles/startup_v1.yaml +134 -0
- icdev/data/context/requirements/__init__.py +1 -0
- icdev/data/context/requirements/ambiguity_patterns.json +97 -0
- icdev/data/context/requirements/boundary_impact_rules.json +123 -0
- icdev/data/context/requirements/default_constitutions.json +67 -0
- icdev/data/context/requirements/document_extraction_rules.json +58 -0
- icdev/data/context/requirements/gap_patterns.json +108 -0
- icdev/data/context/requirements/readiness_rubric.json +78 -0
- icdev/data/context/requirements/red_alternative_patterns.json +210 -0
- icdev/data/context/requirements/safe_templates.json +72 -0
- icdev/data/context/requirements/spec_quality_checklist.json +122 -0
- icdev/data/context/simulation/__init__.py +1 -0
- icdev/data/context/simulation/architecture_patterns.json +36 -0
- icdev/data/context/simulation/coa_templates.json +38 -0
- icdev/data/context/simulation/cost_models.json +23 -0
- icdev/data/context/simulation/risk_categories.json +46 -0
- icdev/data/context/supply_chain/__init__.py +1 -0
- icdev/data/context/supply_chain/isa_templates.json +129 -0
- icdev/data/context/supply_chain/nist_800_161_controls.json +247 -0
- icdev/data/context/supply_chain/scrm_risk_matrix.json +147 -0
- icdev/data/context/templates/__init__.py +1 -0
- icdev/data/context/templates/ansible/__init__.py +1 -0
- icdev/data/context/templates/ansible/playbooks/__init__.py +1 -0
- icdev/data/context/templates/ansible/roles/__init__.py +1 -0
- icdev/data/context/templates/gitlab_ci/__init__.py +1 -0
- icdev/data/context/templates/grafana/__init__.py +1 -0
- icdev/data/context/templates/kubernetes/__init__.py +1 -0
- icdev/data/context/templates/project/__init__.py +1 -0
- icdev/data/context/templates/project/api/__init__.py +1 -0
- icdev/data/context/templates/project/cli/__init__.py +1 -0
- icdev/data/context/templates/project/data_pipeline/__init__.py +1 -0
- icdev/data/context/templates/project/iac/__init__.py +1 -0
- icdev/data/context/templates/project/javascript_frontend/__init__.py +1 -0
- icdev/data/context/templates/project/javascript_frontend/src/__init__.py +1 -0
- icdev/data/context/templates/project/javascript_frontend/tests/__init__.py +1 -0
- icdev/data/context/templates/project/microservice/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/src/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/tests/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/tests/features/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/tests/steps/__init__.py +1 -0
- icdev/data/context/templates/terraform/__init__.py +1 -0
- icdev/data/context/templates/terraform/govcloud_base/__init__.py +1 -0
- icdev/data/context/templates/terraform/modules/__init__.py +1 -0
- icdev/data/context/tone/__init__.py +1 -0
- icdev/data/context/translation/dependency_mappings.json +186 -0
- icdev/data/context/translation/type_mappings.json +149 -0
- icdev/data/docs/README.md +187 -0
- icdev/data/docs/__init__.py +1 -0
- icdev/data/docs/admin/gateway-guide.md +338 -0
- icdev/data/docs/admin/marketplace-guide.md +396 -0
- icdev/data/docs/admin/monitoring-guide.md +509 -0
- icdev/data/docs/architecture/compliance-framework.md +764 -0
- icdev/data/docs/architecture/database-schema.md +689 -0
- icdev/data/docs/architecture/gotcha-framework.md +518 -0
- icdev/data/docs/architecture/multi-agent-system.md +603 -0
- icdev/data/docs/dx/README.md +106 -0
- icdev/data/docs/dx/__init__.py +1 -0
- icdev/data/docs/dx/ci-cd-integration.md +378 -0
- icdev/data/docs/dx/claude-code-guide.md +213 -0
- icdev/data/docs/dx/companion-guide.md +232 -0
- icdev/data/docs/dx/dev-profiles.md +309 -0
- icdev/data/docs/dx/icdev-yaml-spec.md +219 -0
- icdev/data/docs/dx/integration-tiers.md +279 -0
- icdev/data/docs/dx/llm-routing-guide.md +456 -0
- icdev/data/docs/dx/quickstart.md +192 -0
- icdev/data/docs/dx/sdk-reference.md +356 -0
- icdev/data/docs/dx/unified-mcp-setup.md +525 -0
- icdev/data/docs/features/__init__.py +1 -0
- icdev/data/docs/features/phase-01-gotcha-framework.md +249 -0
- icdev/data/docs/features/phase-02-atlas-build-workflow.md +223 -0
- icdev/data/docs/features/phase-03-tdd-bdd-testing.md +261 -0
- icdev/data/docs/features/phase-04-nist-compliance.md +255 -0
- icdev/data/docs/features/phase-05-security-scanning.md +229 -0
- icdev/data/docs/features/phase-06-infrastructure-deployment.md +288 -0
- icdev/data/docs/features/phase-07-code-review-gates.md +276 -0
- icdev/data/docs/features/phase-08-self-healing.md +223 -0
- icdev/data/docs/features/phase-09-monitoring-observability.md +230 -0
- icdev/data/docs/features/phase-10-dashboard-web-ui.md +218 -0
- icdev/data/docs/features/phase-11-multi-agent-architecture.md +272 -0
- icdev/data/docs/features/phase-12-integration-testing.md +228 -0
- icdev/data/docs/features/phase-13-cicd-integration.md +257 -0
- icdev/data/docs/features/phase-14-secure-by-design-ivv.md +240 -0
- icdev/data/docs/features/phase-15-maintenance-audit.md +192 -0
- icdev/data/docs/features/phase-16-ato-acceleration.md +228 -0
- icdev/data/docs/features/phase-17-multi-framework-compliance.md +223 -0
- icdev/data/docs/features/phase-18-mbse-integration.md +242 -0
- icdev/data/docs/features/phase-19-agentic-generation.md +202 -0
- icdev/data/docs/features/phase-20-fips-security-categorization.md +198 -0
- icdev/data/docs/features/phase-21-saas-multi-tenancy.md +273 -0
- icdev/data/docs/features/phase-22-federated-gotcha-marketplace.md +242 -0
- icdev/data/docs/features/phase-23-universal-compliance-platform.md +238 -0
- icdev/data/docs/features/phase-24-devsecops-pipeline-security.md +198 -0
- icdev/data/docs/features/phase-25-zero-trust-architecture.md +220 -0
- icdev/data/docs/features/phase-26-dod-mosa.md +205 -0
- icdev/data/docs/features/phase-27-cli-capabilities.md +222 -0
- icdev/data/docs/features/phase-28-remote-command-gateway.md +235 -0
- icdev/data/docs/features/phase-29-proactive-monitoring.md +212 -0
- icdev/data/docs/features/phase-30-dashboard-auth.md +215 -0
- icdev/data/docs/features/phase-31-dashboard-ux-low-impact.md +188 -0
- icdev/data/docs/features/phase-32-dashboard-ux-medium-impact.md +223 -0
- icdev/data/docs/features/phase-33-modular-installation.md +218 -0
- icdev/data/docs/features/phase-34-dev-profiles.md +239 -0
- icdev/data/docs/features/phase-35-innovation-engine.md +257 -0
- icdev/data/docs/features/phase-36-evolutionary-intelligence.md +351 -0
- icdev/data/docs/features/phase-37-mitre-atlas-integration.md +485 -0
- icdev/data/docs/features/phase-38-cloud-agnostic-architecture.md +1033 -0
- icdev/data/docs/features/phase-39-observability-operations.md +178 -0
- icdev/data/docs/features/phase-40-nlq-compliance-queries.md +176 -0
- icdev/data/docs/features/phase-41-parallel-cicd.md +169 -0
- icdev/data/docs/features/phase-42-framework-planning.md +177 -0
- icdev/data/docs/features/phase-43-cross-language-translation.md +225 -0
- icdev/data/docs/features/phase-44-innovation-adaptation.md +227 -0
- icdev/data/docs/features/phase-45-owasp-agentic-security.md +239 -0
- icdev/data/docs/features/phase-46-observability-traceability-xai.md +240 -0
- icdev/data/docs/features/phase-47-unified-mcp-gateway.md +257 -0
- icdev/data/docs/features/phase-48-ai-transparency.md +203 -0
- icdev/data/docs/features/phase-49-ai-accountability.md +243 -0
- icdev/data/docs/features/phase-50-ai-governance-intake-chat.md +195 -0
- icdev/data/docs/features/phase-51-unified-chat-dashboard.md +240 -0
- icdev/data/docs/features/phase-52-code-intelligence.md +244 -0
- icdev/data/docs/features/phase-53-fedramp-20x-owasp-asi.md +359 -0
- icdev/data/docs/features/phase-54-slsa-swft-orchestration.md +379 -0
- icdev/data/docs/features/phase-55-a2a-v03-mcp-oauth.md +322 -0
- icdev/data/docs/features/phase-56-evidence-lineage.md +352 -0
- icdev/data/docs/features/phase-57-eu-ai-act-iron-bank.md +319 -0
- icdev/data/docs/features/phase-58-creative-engine.md +370 -0
- icdev/data/docs/features/phase-59-govcon-intelligence.md +535 -0
- icdev/data/docs/features/phase-60-cpmp.md +528 -0
- icdev/data/docs/features/phase-61-orchestration-improvements.md +534 -0
- icdev/data/docs/operations/dashboard-guide.md +354 -0
- icdev/data/docs/operations/deployment-guide.md +556 -0
- icdev/data/docs/operations/saas-admin-guide.md +439 -0
- icdev/data/docs/operations/security-operations-guide.md +733 -0
- icdev/data/docs/runbooks/backup-restore.md +412 -0
- icdev/data/docs/runbooks/troubleshooting.md +499 -0
- icdev/data/features/__init__.py +1 -0
- icdev/data/features/cicd_integration.feature +41 -0
- icdev/data/features/compliance_gates.feature +46 -0
- icdev/data/features/dashboard.feature +72 -0
- icdev/data/features/environment.py +25 -0
- icdev/data/features/project_management.feature +32 -0
- icdev/data/features/requirements_intake.feature +42 -0
- icdev/data/features/saas_platform.feature +53 -0
- icdev/data/features/security_scanning.feature +36 -0
- icdev/data/features/steps/__init__.py +1 -0
- icdev/data/features/steps/cicd_steps.py +465 -0
- icdev/data/features/steps/compliance_steps.py +308 -0
- icdev/data/features/steps/dashboard_steps.py +88 -0
- icdev/data/features/steps/project_steps.py +126 -0
- icdev/data/features/steps/requirements_intake_steps.py +689 -0
- icdev/data/features/steps/saas_platform_steps.py +572 -0
- icdev/data/features/steps/security_steps.py +236 -0
- icdev/data/features/steps/testing_steps.py +226 -0
- icdev/data/features/testing_pipeline.feature +42 -0
- icdev/data/goals/__init__.py +1 -0
- icdev/data/goals/agent_management.md +144 -0
- icdev/data/goals/agentic_generation.md +345 -0
- icdev/data/goals/agentic_threat_model.md +309 -0
- icdev/data/goals/ai_accountability.md +90 -0
- icdev/data/goals/ai_governance_intake.md +132 -0
- icdev/data/goals/ai_transparency.md +76 -0
- icdev/data/goals/atlas_integration.md +405 -0
- icdev/data/goals/ato_acceleration.md +139 -0
- icdev/data/goals/boundary_supply_chain.md +206 -0
- icdev/data/goals/build_app.md +544 -0
- icdev/data/goals/cicd_integration.md +86 -0
- icdev/data/goals/claude_dir_maintenance.md +77 -0
- icdev/data/goals/cli_capabilities.md +340 -0
- icdev/data/goals/cloud_agnostic.md +312 -0
- icdev/data/goals/code_intelligence.md +197 -0
- icdev/data/goals/code_review.md +94 -0
- icdev/data/goals/compliance_workflow.md +858 -0
- icdev/data/goals/continuous_harmonization.md +140 -0
- icdev/data/goals/cross_language_translation.md +171 -0
- icdev/data/goals/dashboard.md +142 -0
- icdev/data/goals/deploy_workflow.md +390 -0
- icdev/data/goals/devsecops_workflow.md +408 -0
- icdev/data/goals/evolutionary_intelligence.md +305 -0
- icdev/data/goals/external_integration.md +113 -0
- icdev/data/goals/framework_planning.md +63 -0
- icdev/data/goals/init_project.md +235 -0
- icdev/data/goals/innovation_engine.md +199 -0
- icdev/data/goals/integration_testing.md +189 -0
- icdev/data/goals/maintenance_audit.md +196 -0
- icdev/data/goals/manifest.md +56 -0
- icdev/data/goals/mbse_integration.md +504 -0
- icdev/data/goals/modernization_workflow.md +618 -0
- icdev/data/goals/monitoring.md +126 -0
- icdev/data/goals/mosa_workflow.md +463 -0
- icdev/data/goals/multi_agent_orchestration.md +68 -0
- icdev/data/goals/nlq_compliance.md +63 -0
- icdev/data/goals/observability.md +64 -0
- icdev/data/goals/observability_traceability_xai.md +154 -0
- icdev/data/goals/owasp_agentic_security.md +395 -0
- icdev/data/goals/parallel_cicd.md +61 -0
- icdev/data/goals/requirements_intake.md +213 -0
- icdev/data/goals/sbd_ivv_workflow.md +195 -0
- icdev/data/goals/security_categorization.md +133 -0
- icdev/data/goals/security_scan.md +381 -0
- icdev/data/goals/self_healing.md +120 -0
- icdev/data/goals/simulation_engine.md +111 -0
- icdev/data/goals/tdd_workflow.md +403 -0
- icdev/data/goals/zero_trust_architecture.md +403 -0
- icdev/data/hardprompts/__init__.py +1 -0
- icdev/data/hardprompts/agent/__init__.py +1 -0
- icdev/data/hardprompts/agent/agentic_architect.md +100 -0
- icdev/data/hardprompts/agent/debate_prompt.md +32 -0
- icdev/data/hardprompts/agent/fitness_evaluation.md +48 -0
- icdev/data/hardprompts/agent/governance_review.md +214 -0
- icdev/data/hardprompts/agent/reviewer_prompt.md +34 -0
- icdev/data/hardprompts/agent/skill_design.md +172 -0
- icdev/data/hardprompts/agent/task_decomposition.md +275 -0
- icdev/data/hardprompts/agent/veto_check_prompt.md +33 -0
- icdev/data/hardprompts/architect/__init__.py +1 -0
- icdev/data/hardprompts/architect/api_design.md +283 -0
- icdev/data/hardprompts/architect/data_model.md +277 -0
- icdev/data/hardprompts/architect/system_design.md +180 -0
- icdev/data/hardprompts/builder/__init__.py +1 -0
- icdev/data/hardprompts/builder/code_generation.md +59 -0
- icdev/data/hardprompts/builder/refactor.md +58 -0
- icdev/data/hardprompts/builder/scaffold_project.md +69 -0
- icdev/data/hardprompts/builder/test_generation.md +87 -0
- icdev/data/hardprompts/ci/__init__.py +1 -0
- icdev/data/hardprompts/ci/worktree_setup.md +35 -0
- icdev/data/hardprompts/compliance/__init__.py +1 -0
- icdev/data/hardprompts/compliance/cmmc_assessment.md +63 -0
- icdev/data/hardprompts/compliance/cssp_assessment.md +75 -0
- icdev/data/hardprompts/compliance/cui_marking.md +86 -0
- icdev/data/hardprompts/compliance/fedramp_assessment.md +55 -0
- icdev/data/hardprompts/compliance/ivv_assessment.md +96 -0
- icdev/data/hardprompts/compliance/poam_generation.md +57 -0
- icdev/data/hardprompts/compliance/sbd_assessment.md +101 -0
- icdev/data/hardprompts/compliance/security_categorization.md +74 -0
- icdev/data/hardprompts/compliance/ssp_generation.md +56 -0
- icdev/data/hardprompts/compliance/stig_evaluation.md +63 -0
- icdev/data/hardprompts/dashboard/__init__.py +1 -0
- icdev/data/hardprompts/dashboard/nlq_system_prompt.md +26 -0
- icdev/data/hardprompts/infra/__init__.py +1 -0
- icdev/data/hardprompts/infra/k8s_manifests.md +118 -0
- icdev/data/hardprompts/infra/pipeline_generation.md +160 -0
- icdev/data/hardprompts/infra/terraform_generation.md +92 -0
- icdev/data/hardprompts/integration/__init__.py +1 -0
- icdev/data/hardprompts/integration/approval_review.md +17 -0
- icdev/data/hardprompts/integration/jira_mapping.md +25 -0
- icdev/data/hardprompts/integration/servicenow_mapping.md +14 -0
- icdev/data/hardprompts/knowledge/__init__.py +1 -0
- icdev/data/hardprompts/knowledge/pattern_detection.md +73 -0
- icdev/data/hardprompts/knowledge/recommendation_engine.md +90 -0
- icdev/data/hardprompts/knowledge/root_cause_analysis.md +91 -0
- icdev/data/hardprompts/maintenance/__init__.py +1 -0
- icdev/data/hardprompts/maintenance/maintenance_assessment.md +82 -0
- icdev/data/hardprompts/mbse/__init__.py +1 -0
- icdev/data/hardprompts/mbse/digital_thread.md +67 -0
- icdev/data/hardprompts/mbse/model_import.md +62 -0
- icdev/data/hardprompts/mbse/model_to_code.md +65 -0
- icdev/data/hardprompts/modernization/__init__.py +1 -0
- icdev/data/hardprompts/modernization/legacy_analysis.md +93 -0
- icdev/data/hardprompts/modernization/migration_planning.md +150 -0
- icdev/data/hardprompts/modernization/seven_r_assessment.md +107 -0
- icdev/data/hardprompts/requirements/__init__.py +1 -0
- icdev/data/hardprompts/requirements/bdd_generation.md +35 -0
- icdev/data/hardprompts/requirements/clarification_prioritization.md +29 -0
- icdev/data/hardprompts/requirements/decomposition.md +60 -0
- icdev/data/hardprompts/requirements/document_extraction.md +45 -0
- icdev/data/hardprompts/requirements/gap_detection.md +70 -0
- icdev/data/hardprompts/requirements/intake_conversation.md +101 -0
- icdev/data/hardprompts/requirements/readiness_assessment.md +39 -0
- icdev/data/hardprompts/requirements/spec_quality.md +33 -0
- icdev/data/hardprompts/requirements/traceability_analysis.md +23 -0
- icdev/data/hardprompts/security/__init__.py +1 -0
- icdev/data/hardprompts/security/endpoint_security.md +78 -0
- icdev/data/hardprompts/security/threat_model.md +70 -0
- icdev/data/hardprompts/security/vulnerability_assessment.md +81 -0
- icdev/data/hardprompts/simulation/__init__.py +1 -0
- icdev/data/hardprompts/simulation/architecture_impact.md +27 -0
- icdev/data/hardprompts/simulation/coa_alternative.md +27 -0
- icdev/data/hardprompts/simulation/coa_generation.md +25 -0
- icdev/data/hardprompts/simulation/compliance_impact.md +28 -0
- icdev/data/hardprompts/simulation/cost_estimation.md +33 -0
- icdev/data/hardprompts/simulation/risk_assessment.md +28 -0
- icdev/data/hardprompts/translation/code_translation.md +68 -0
- icdev/data/hardprompts/translation/dependency_suggestion.md +44 -0
- icdev/data/hardprompts/translation/test_translation.md +64 -0
- icdev/data/hardprompts/translation/translation_repair.md +59 -0
- icdev/py.typed +0 -0
- icdev/tools/__init__.py +1 -0
- icdev/tools/_gen_formatter.py +12 -0
- icdev/tools/a2a/__init__.py +1 -0
- icdev/tools/a2a/agent_cards/architect.json +43 -0
- icdev/tools/a2a/agent_cards/builder.json +50 -0
- icdev/tools/a2a/agent_cards/compliance.json +57 -0
- icdev/tools/a2a/agent_cards/devsecops.json +71 -0
- icdev/tools/a2a/agent_cards/infra.json +57 -0
- icdev/tools/a2a/agent_cards/integration.json +57 -0
- icdev/tools/a2a/agent_cards/knowledge.json +43 -0
- icdev/tools/a2a/agent_cards/mbse.json +57 -0
- icdev/tools/a2a/agent_cards/modernization.json +50 -0
- icdev/tools/a2a/agent_cards/monitor.json +43 -0
- icdev/tools/a2a/agent_cards/orchestrator.json +36 -0
- icdev/tools/a2a/agent_cards/requirements_analyst.json +64 -0
- icdev/tools/a2a/agent_cards/security.json +50 -0
- icdev/tools/a2a/agent_cards/simulation.json +57 -0
- icdev/tools/a2a/agent_cards/supply_chain.json +50 -0
- icdev/tools/a2a/agent_client.py +349 -0
- icdev/tools/a2a/agent_registry.py +412 -0
- icdev/tools/a2a/agent_server.py +579 -0
- icdev/tools/a2a/task.py +200 -0
- icdev/tools/agent/__init__.py +2 -0
- icdev/tools/agent/a2a_agent_card_generator.py +285 -0
- icdev/tools/agent/a2a_discovery_server.py +250 -0
- icdev/tools/agent/agent_executor.py +529 -0
- icdev/tools/agent/agent_memory.py +557 -0
- icdev/tools/agent/agent_models.py +51 -0
- icdev/tools/agent/atlas_critique.py +908 -0
- icdev/tools/agent/authority.py +443 -0
- icdev/tools/agent/bedrock_client.py +1075 -0
- icdev/tools/agent/collaboration.py +871 -0
- icdev/tools/agent/dispatcher_mode.py +665 -0
- icdev/tools/agent/mailbox.py +575 -0
- icdev/tools/agent/prompt_chain_executor.py +1064 -0
- icdev/tools/agent/session_purpose.py +350 -0
- icdev/tools/agent/skill_router.py +638 -0
- icdev/tools/agent/skill_selector.py +486 -0
- icdev/tools/agent/team_orchestrator.py +1108 -0
- icdev/tools/agent/token_tracker.py +290 -0
- icdev/tools/analysis/__init__.py +1 -0
- icdev/tools/analysis/code_analyzer.py +780 -0
- icdev/tools/analysis/runtime_feedback.py +389 -0
- icdev/tools/audit/__init__.py +1 -0
- icdev/tools/audit/audit_logger.py +196 -0
- icdev/tools/audit/audit_query.py +157 -0
- icdev/tools/audit/decision_recorder.py +72 -0
- icdev/tools/builder/__init__.py +1 -0
- icdev/tools/builder/agentic_fitness.py +534 -0
- icdev/tools/builder/agentic_test_templates/test_a2a_callback.py +117 -0
- icdev/tools/builder/agentic_test_templates/test_a2a_lifecycle.feature +52 -0
- icdev/tools/builder/agentic_test_templates/test_agent_card.feature +37 -0
- icdev/tools/builder/agentic_test_templates/test_agent_health.py +128 -0
- icdev/tools/builder/agentic_test_templates/test_memory_system.feature +50 -0
- icdev/tools/builder/agentic_test_templates/test_skill_execution.feature +40 -0
- icdev/tools/builder/app_blueprint.py +1583 -0
- icdev/tools/builder/child_app_generator.py +2852 -0
- icdev/tools/builder/claude_md_generator.py +1734 -0
- icdev/tools/builder/code_generator.py +3703 -0
- icdev/tools/builder/db_init_generator.py +1709 -0
- icdev/tools/builder/dev_profile_manager.py +954 -0
- icdev/tools/builder/formatter.py +768 -0
- icdev/tools/builder/goal_adapter.py +592 -0
- icdev/tools/builder/gotcha_validator.py +812 -0
- icdev/tools/builder/language_support.py +441 -0
- icdev/tools/builder/linter.py +976 -0
- icdev/tools/builder/profile_detector.py +657 -0
- icdev/tools/builder/profile_md_generator.py +723 -0
- icdev/tools/builder/scaffolder.py +1590 -0
- icdev/tools/builder/scaffolder_extended.py +1771 -0
- icdev/tools/builder/test_writer.py +950 -0
- icdev/tools/ci/__init__.py +2 -0
- icdev/tools/ci/connectors/__init__.py +2 -0
- icdev/tools/ci/connectors/base_connector.py +80 -0
- icdev/tools/ci/connectors/connector_registry.py +188 -0
- icdev/tools/ci/connectors/mattermost_connector.py +159 -0
- icdev/tools/ci/connectors/slack_connector.py +197 -0
- icdev/tools/ci/core/__init__.py +2 -0
- icdev/tools/ci/core/air_gap_detector.py +115 -0
- icdev/tools/ci/core/comment_handler.py +192 -0
- icdev/tools/ci/core/conversation_manager.py +479 -0
- icdev/tools/ci/core/event_envelope.py +500 -0
- icdev/tools/ci/core/event_router.py +443 -0
- icdev/tools/ci/core/failure_parser.py +397 -0
- icdev/tools/ci/core/recovery_engine.py +527 -0
- icdev/tools/ci/modules/__init__.py +2 -0
- icdev/tools/ci/modules/agent.py +271 -0
- icdev/tools/ci/modules/git_ops.py +175 -0
- icdev/tools/ci/modules/state.py +117 -0
- icdev/tools/ci/modules/vcs.py +303 -0
- icdev/tools/ci/modules/workflow_ops.py +295 -0
- icdev/tools/ci/modules/worktree.py +340 -0
- icdev/tools/ci/pipeline_config_generator.py +558 -0
- icdev/tools/ci/triggers/__init__.py +2 -0
- icdev/tools/ci/triggers/gitlab_task_monitor.py +330 -0
- icdev/tools/ci/triggers/poll_trigger.py +237 -0
- icdev/tools/ci/triggers/webhook_server.py +356 -0
- icdev/tools/ci/workflows/__init__.py +2 -0
- icdev/tools/ci/workflows/icdev_build.py +140 -0
- icdev/tools/ci/workflows/icdev_comply.py +284 -0
- icdev/tools/ci/workflows/icdev_document.py +152 -0
- icdev/tools/ci/workflows/icdev_e2e.py +188 -0
- icdev/tools/ci/workflows/icdev_patch.py +186 -0
- icdev/tools/ci/workflows/icdev_plan.py +202 -0
- icdev/tools/ci/workflows/icdev_plan_build.py +41 -0
- icdev/tools/ci/workflows/icdev_plan_build_test.py +46 -0
- icdev/tools/ci/workflows/icdev_plan_build_test_review.py +47 -0
- icdev/tools/ci/workflows/icdev_review.py +126 -0
- icdev/tools/ci/workflows/icdev_sdlc.py +261 -0
- icdev/tools/ci/workflows/icdev_test.py +240 -0
- icdev/tools/cli/__init__.py +1 -0
- icdev/tools/cli/output_formatter.py +756 -0
- icdev/tools/cli_formatter.py +42 -0
- icdev/tools/cloud/__init__.py +11 -0
- icdev/tools/cloud/cloud_mode_manager.py +364 -0
- icdev/tools/cloud/csp_changelog.py +383 -0
- icdev/tools/cloud/csp_health_checker.py +268 -0
- icdev/tools/cloud/csp_monitor.py +951 -0
- icdev/tools/cloud/iam_provider.py +593 -0
- icdev/tools/cloud/kms_provider.py +346 -0
- icdev/tools/cloud/monitoring_provider.py +628 -0
- icdev/tools/cloud/provider_factory.py +376 -0
- icdev/tools/cloud/region_validator.py +345 -0
- icdev/tools/cloud/registry_provider.py +563 -0
- icdev/tools/cloud/secrets_provider.py +486 -0
- icdev/tools/cloud/storage_provider.py +446 -0
- icdev/tools/compat/__init__.py +21 -0
- icdev/tools/compat/cli_harmonizer.py +251 -0
- icdev/tools/compat/datetime_utils.py +18 -0
- icdev/tools/compat/db_utils.py +160 -0
- icdev/tools/compat/platform_utils.py +123 -0
- icdev/tools/compliance/__init__.py +1 -0
- icdev/tools/compliance/accountability_manager.py +397 -0
- icdev/tools/compliance/ai_accountability_audit.py +294 -0
- icdev/tools/compliance/ai_impact_assessor.py +273 -0
- icdev/tools/compliance/ai_incident_response.py +301 -0
- icdev/tools/compliance/ai_inventory_manager.py +239 -0
- icdev/tools/compliance/ai_reassessment_scheduler.py +256 -0
- icdev/tools/compliance/ai_transparency_audit.py +248 -0
- icdev/tools/compliance/atlas_assessor.py +278 -0
- icdev/tools/compliance/atlas_report_generator.py +1211 -0
- icdev/tools/compliance/base_assessor.py +597 -0
- icdev/tools/compliance/cato_monitor.py +1385 -0
- icdev/tools/compliance/cato_scheduler.py +699 -0
- icdev/tools/compliance/cjis_assessor.py +76 -0
- icdev/tools/compliance/classification_manager.py +1353 -0
- icdev/tools/compliance/cmmc_assessor.py +1491 -0
- icdev/tools/compliance/cmmc_report_generator.py +1100 -0
- icdev/tools/compliance/compliance_detector.py +463 -0
- icdev/tools/compliance/compliance_exporter.py +427 -0
- icdev/tools/compliance/compliance_status.py +825 -0
- icdev/tools/compliance/control_mapper.py +505 -0
- icdev/tools/compliance/crosswalk_engine.py +1203 -0
- icdev/tools/compliance/cssp_assessor.py +1045 -0
- icdev/tools/compliance/cssp_evidence_collector.py +729 -0
- icdev/tools/compliance/cssp_report_generator.py +1116 -0
- icdev/tools/compliance/cui_marker.py +388 -0
- icdev/tools/compliance/diagram_validator.py +600 -0
- icdev/tools/compliance/emass/__init__.py +2 -0
- icdev/tools/compliance/emass/emass_client.py +840 -0
- icdev/tools/compliance/emass/emass_export.py +777 -0
- icdev/tools/compliance/emass/emass_sync.py +826 -0
- icdev/tools/compliance/eu_ai_act_classifier.py +194 -0
- icdev/tools/compliance/evidence_collector.py +468 -0
- icdev/tools/compliance/fairness_assessor.py +316 -0
- icdev/tools/compliance/fedramp_assessor.py +1808 -0
- icdev/tools/compliance/fedramp_authorization_packager.py +137 -0
- icdev/tools/compliance/fedramp_ksi_generator.py +355 -0
- icdev/tools/compliance/fedramp_report_generator.py +1128 -0
- icdev/tools/compliance/fips199_categorizer.py +881 -0
- icdev/tools/compliance/fips200_validator.py +315 -0
- icdev/tools/compliance/gao_ai_assessor.py +231 -0
- icdev/tools/compliance/gao_evidence_builder.py +308 -0
- icdev/tools/compliance/hipaa_assessor.py +78 -0
- icdev/tools/compliance/hitrust_assessor.py +49 -0
- icdev/tools/compliance/incident_response_plan.py +718 -0
- icdev/tools/compliance/iso27001_assessor.py +92 -0
- icdev/tools/compliance/iso42001_assessor.py +114 -0
- icdev/tools/compliance/ivv_assessor.py +2327 -0
- icdev/tools/compliance/ivv_report_generator.py +1662 -0
- icdev/tools/compliance/model_card_generator.py +297 -0
- icdev/tools/compliance/mosa_assessor.py +117 -0
- icdev/tools/compliance/multi_regime_assessor.py +451 -0
- icdev/tools/compliance/narrative_generator.py +1013 -0
- icdev/tools/compliance/nist_800_207_assessor.py +191 -0
- icdev/tools/compliance/nist_ai_600_1_assessor.py +188 -0
- icdev/tools/compliance/nist_ai_rmf_assessor.py +110 -0
- icdev/tools/compliance/nist_lookup.py +245 -0
- icdev/tools/compliance/omb_m25_21_assessor.py +228 -0
- icdev/tools/compliance/omb_m26_04_assessor.py +188 -0
- icdev/tools/compliance/oscal_catalog_adapter.py +395 -0
- icdev/tools/compliance/oscal_generator.py +2170 -0
- icdev/tools/compliance/oscal_tools.py +1182 -0
- icdev/tools/compliance/owasp_agentic_assessor.py +226 -0
- icdev/tools/compliance/owasp_asi_assessor.py +200 -0
- icdev/tools/compliance/owasp_llm_assessor.py +244 -0
- icdev/tools/compliance/pci_dss_assessor.py +80 -0
- icdev/tools/compliance/pi_compliance_tracker.py +1461 -0
- icdev/tools/compliance/poam_generator.py +405 -0
- icdev/tools/compliance/resolve_marking.py +283 -0
- icdev/tools/compliance/sbd_assessor.py +2068 -0
- icdev/tools/compliance/sbd_report_generator.py +1236 -0
- icdev/tools/compliance/sbom_generator.py +1008 -0
- icdev/tools/compliance/siem_config_generator.py +674 -0
- icdev/tools/compliance/slsa_attestation_generator.py +490 -0
- icdev/tools/compliance/soc2_assessor.py +77 -0
- icdev/tools/compliance/ssp_generator.py +573 -0
- icdev/tools/compliance/stig_checker.py +727 -0
- icdev/tools/compliance/swft_evidence_bundler.py +337 -0
- icdev/tools/compliance/system_card_generator.py +309 -0
- icdev/tools/compliance/traceability_matrix.py +1281 -0
- icdev/tools/compliance/universal_classification_manager.py +1172 -0
- icdev/tools/compliance/xacta/__init__.py +2 -0
- icdev/tools/compliance/xacta/xacta_client.py +449 -0
- icdev/tools/compliance/xacta/xacta_export.py +557 -0
- icdev/tools/compliance/xacta/xacta_sync.py +333 -0
- icdev/tools/compliance/xai_assessor.py +231 -0
- icdev/tools/dashboard/__init__.py +1 -0
- icdev/tools/dashboard/api/__init__.py +1 -0
- icdev/tools/dashboard/api/_pipeline_state.py +17 -0
- icdev/tools/dashboard/api/activity.py +206 -0
- icdev/tools/dashboard/api/admin.py +176 -0
- icdev/tools/dashboard/api/agents.py +53 -0
- icdev/tools/dashboard/api/ai_accountability.py +163 -0
- icdev/tools/dashboard/api/ai_transparency.py +198 -0
- icdev/tools/dashboard/api/audit.py +58 -0
- icdev/tools/dashboard/api/batch.py +666 -0
- icdev/tools/dashboard/api/chat.py +241 -0
- icdev/tools/dashboard/api/cicd.py +219 -0
- icdev/tools/dashboard/api/code_quality.py +223 -0
- icdev/tools/dashboard/api/compliance.py +171 -0
- icdev/tools/dashboard/api/cpmp.py +915 -0
- icdev/tools/dashboard/api/diagrams.py +65 -0
- icdev/tools/dashboard/api/events.py +250 -0
- icdev/tools/dashboard/api/evidence.py +99 -0
- icdev/tools/dashboard/api/fedramp_20x.py +77 -0
- icdev/tools/dashboard/api/govcon.py +1095 -0
- icdev/tools/dashboard/api/intake.py +1171 -0
- icdev/tools/dashboard/api/lineage.py +163 -0
- icdev/tools/dashboard/api/metrics.py +155 -0
- icdev/tools/dashboard/api/nlq.py +72 -0
- icdev/tools/dashboard/api/orchestration.py +472 -0
- icdev/tools/dashboard/api/oscal.py +183 -0
- icdev/tools/dashboard/api/prod_audit.py +183 -0
- icdev/tools/dashboard/api/projects.py +191 -0
- icdev/tools/dashboard/api/proposals.py +1084 -0
- icdev/tools/dashboard/api/traces.py +363 -0
- icdev/tools/dashboard/api/usage.py +234 -0
- icdev/tools/dashboard/app.py +1986 -0
- icdev/tools/dashboard/auth.py +500 -0
- icdev/tools/dashboard/byok.py +245 -0
- icdev/tools/dashboard/chat_manager.py +675 -0
- icdev/tools/dashboard/config.py +116 -0
- icdev/tools/dashboard/diagram_definitions.py +642 -0
- icdev/tools/dashboard/nlq_processor.py +323 -0
- icdev/tools/dashboard/phase_loader.py +136 -0
- icdev/tools/dashboard/sse_manager.py +89 -0
- icdev/tools/dashboard/state_tracker.py +267 -0
- icdev/tools/dashboard/static/css/style.css +706 -0
- icdev/tools/dashboard/static/css/ux.css +2047 -0
- icdev/tools/dashboard/static/js/activity.js +322 -0
- icdev/tools/dashboard/static/js/api.js +161 -0
- icdev/tools/dashboard/static/js/batch.js +814 -0
- icdev/tools/dashboard/static/js/charts.js +618 -0
- icdev/tools/dashboard/static/js/chat.js +1514 -0
- icdev/tools/dashboard/static/js/kanban.js +113 -0
- icdev/tools/dashboard/static/js/live.js +569 -0
- icdev/tools/dashboard/static/js/mermaid-icdev.js +332 -0
- icdev/tools/dashboard/static/js/proposals.js +588 -0
- icdev/tools/dashboard/static/js/shortcuts.js +544 -0
- icdev/tools/dashboard/static/js/tables.js +652 -0
- icdev/tools/dashboard/static/js/tour.js +524 -0
- icdev/tools/dashboard/static/js/ux.js +942 -0
- icdev/tools/dashboard/templates/404.html +10 -0
- icdev/tools/dashboard/templates/activity.html +80 -0
- icdev/tools/dashboard/templates/admin/users.html +144 -0
- icdev/tools/dashboard/templates/ai_accountability.html +235 -0
- icdev/tools/dashboard/templates/ai_transparency.html +263 -0
- icdev/tools/dashboard/templates/base.html +104 -0
- icdev/tools/dashboard/templates/batch.html +23 -0
- icdev/tools/dashboard/templates/chat.html +332 -0
- icdev/tools/dashboard/templates/children.html +149 -0
- icdev/tools/dashboard/templates/cicd.html +253 -0
- icdev/tools/dashboard/templates/code_quality.html +214 -0
- icdev/tools/dashboard/templates/cpmp/cor_detail.html +220 -0
- icdev/tools/dashboard/templates/cpmp/cor_portal.html +91 -0
- icdev/tools/dashboard/templates/cpmp/deliverable_detail.html +197 -0
- icdev/tools/dashboard/templates/cpmp/detail.html +578 -0
- icdev/tools/dashboard/templates/cpmp/portfolio.html +202 -0
- icdev/tools/dashboard/templates/dev_profiles.html +304 -0
- icdev/tools/dashboard/templates/diagrams.html +224 -0
- icdev/tools/dashboard/templates/events/timeline.html +232 -0
- icdev/tools/dashboard/templates/evidence.html +134 -0
- icdev/tools/dashboard/templates/fedramp_20x.html +207 -0
- icdev/tools/dashboard/templates/gateway.html +244 -0
- icdev/tools/dashboard/templates/govcon/capabilities.html +135 -0
- icdev/tools/dashboard/templates/govcon/pipeline.html +214 -0
- icdev/tools/dashboard/templates/govcon/requirements.html +120 -0
- icdev/tools/dashboard/templates/index.html +254 -0
- icdev/tools/dashboard/templates/lineage.html +141 -0
- icdev/tools/dashboard/templates/login.html +51 -0
- icdev/tools/dashboard/templates/monitoring/overview.html +193 -0
- icdev/tools/dashboard/templates/orchestration/dashboard.html +545 -0
- icdev/tools/dashboard/templates/oscal.html +263 -0
- icdev/tools/dashboard/templates/phases.html +150 -0
- icdev/tools/dashboard/templates/prod_audit.html +280 -0
- icdev/tools/dashboard/templates/profile.html +183 -0
- icdev/tools/dashboard/templates/projects/detail.html +583 -0
- icdev/tools/dashboard/templates/projects/list.html +47 -0
- icdev/tools/dashboard/templates/proposals/detail.html +1253 -0
- icdev/tools/dashboard/templates/proposals/list.html +179 -0
- icdev/tools/dashboard/templates/proposals/section_detail.html +193 -0
- icdev/tools/dashboard/templates/provenance.html +181 -0
- icdev/tools/dashboard/templates/query/nlq.html +234 -0
- icdev/tools/dashboard/templates/quick_paths.html +69 -0
- icdev/tools/dashboard/templates/traces.html +155 -0
- icdev/tools/dashboard/templates/translation_detail.html +199 -0
- icdev/tools/dashboard/templates/translations.html +162 -0
- icdev/tools/dashboard/templates/usage.html +225 -0
- icdev/tools/dashboard/templates/wizard.html +539 -0
- icdev/tools/dashboard/templates/xai.html +208 -0
- icdev/tools/dashboard/ux_helpers.py +962 -0
- icdev/tools/dashboard/websocket.py +81 -0
- icdev/tools/db/__init__.py +1 -0
- icdev/tools/db/backup.py +312 -0
- icdev/tools/db/backup_manager.py +832 -0
- icdev/tools/db/init_icdev_db.py +5900 -0
- icdev/tools/db/migrate.py +178 -0
- icdev/tools/db/migration_runner.py +549 -0
- icdev/tools/db/migrations/001_baseline/meta.json +9 -0
- icdev/tools/db/migrations/001_baseline/up.py +68 -0
- icdev/tools/db/migrations/002_memory_enhancements/down.sql +8 -0
- icdev/tools/db/migrations/002_memory_enhancements/meta.json +9 -0
- icdev/tools/db/migrations/002_memory_enhancements/up.py +118 -0
- icdev/tools/db/migrations/003_dev_profiles/meta.json +8 -0
- icdev/tools/db/migrations/003_dev_profiles/up.py +93 -0
- icdev/tools/db/migrations/004_innovation_engine/down.py +19 -0
- icdev/tools/db/migrations/004_innovation_engine/up.py +227 -0
- icdev/tools/db/migrations/005_phase_37_ai_security/down.py +19 -0
- icdev/tools/db/migrations/005_phase_37_ai_security/up.py +258 -0
- icdev/tools/db/migrations/006_phase_36_evolution/down.py +21 -0
- icdev/tools/db/migrations/006_phase_36_evolution/up.py +323 -0
- icdev/tools/db/migrations/007_phase_38_cloud/down.py +14 -0
- icdev/tools/db/migrations/007_phase_38_cloud/up.py +110 -0
- icdev/tools/db/migrations/008_phase36_37_integration/up.py +55 -0
- icdev/tools/db/migrations/__init__.py +2 -0
- icdev/tools/devsecops/__init__.py +2 -0
- icdev/tools/devsecops/attestation_manager.py +458 -0
- icdev/tools/devsecops/network_segmentation_generator.py +614 -0
- icdev/tools/devsecops/pdp_config_generator.py +1256 -0
- icdev/tools/devsecops/pipeline_security_generator.py +484 -0
- icdev/tools/devsecops/policy_generator.py +653 -0
- icdev/tools/devsecops/profile_manager.py +388 -0
- icdev/tools/devsecops/service_mesh_generator.py +1073 -0
- icdev/tools/devsecops/zta_maturity_scorer.py +368 -0
- icdev/tools/devsecops/zta_terraform_generator.py +1303 -0
- icdev/tools/dx/__init__.py +3 -0
- icdev/tools/dx/companion.py +266 -0
- icdev/tools/dx/instruction_generator.py +753 -0
- icdev/tools/dx/mcp_config_generator.py +282 -0
- icdev/tools/dx/skill_translator.py +425 -0
- icdev/tools/dx/tool_detector.py +144 -0
- icdev/tools/extensions/__init__.py +21 -0
- icdev/tools/extensions/builtins/010_ai_governance_chat.py +277 -0
- icdev/tools/extensions/builtins/__init__.py +2 -0
- icdev/tools/extensions/extension_manager.py +455 -0
- icdev/tools/infra/__init__.py +1 -0
- icdev/tools/infra/ansible_generator.py +869 -0
- icdev/tools/infra/dockerfile_generator.py +361 -0
- icdev/tools/infra/infra_status.py +393 -0
- icdev/tools/infra/ironbank_metadata_generator.py +411 -0
- icdev/tools/infra/k8s_generator.py +1002 -0
- icdev/tools/infra/pipeline_generator.py +832 -0
- icdev/tools/infra/rollback.py +400 -0
- icdev/tools/infra/terraform_generator.py +1142 -0
- icdev/tools/infra/terraform_generator_azure.py +1254 -0
- icdev/tools/infra/terraform_generator_gcp.py +953 -0
- icdev/tools/infra/terraform_generator_ibm.py +360 -0
- icdev/tools/infra/terraform_generator_oci.py +919 -0
- icdev/tools/infra/terraform_generator_onprem.py +319 -0
- icdev/tools/innovation/__init__.py +8 -0
- icdev/tools/innovation/competitive_intel.py +492 -0
- icdev/tools/innovation/innovation_manager.py +681 -0
- icdev/tools/innovation/introspective_analyzer.py +774 -0
- icdev/tools/innovation/register_external_patterns.py +440 -0
- icdev/tools/innovation/signal_ranker.py +1038 -0
- icdev/tools/innovation/solution_generator.py +697 -0
- icdev/tools/innovation/standards_monitor.py +466 -0
- icdev/tools/innovation/trend_detector.py +1046 -0
- icdev/tools/innovation/triage_engine.py +1149 -0
- icdev/tools/innovation/web_scanner.py +894 -0
- icdev/tools/installer/__init__.py +1 -0
- icdev/tools/installer/compliance_configurator.py +637 -0
- icdev/tools/installer/installer.py +1711 -0
- icdev/tools/installer/module_registry.py +805 -0
- icdev/tools/installer/platform_setup.py +961 -0
- icdev/tools/integration/__init__.py +2 -0
- icdev/tools/integration/approval_manager.py +561 -0
- icdev/tools/integration/doors_exporter.py +627 -0
- icdev/tools/integration/gitlab_connector.py +784 -0
- icdev/tools/integration/jira_connector.py +774 -0
- icdev/tools/integration/servicenow_connector.py +693 -0
- icdev/tools/knowledge/__init__.py +1 -0
- icdev/tools/knowledge/knowledge_ingest.py +293 -0
- icdev/tools/knowledge/pattern_detector.py +693 -0
- icdev/tools/knowledge/recommendation_engine.py +461 -0
- icdev/tools/knowledge/self_heal_analyzer.py +504 -0
- icdev/tools/llm/__init__.py +72 -0
- icdev/tools/llm/anthropic_provider.py +170 -0
- icdev/tools/llm/azure_openai_provider.py +338 -0
- icdev/tools/llm/bedrock_provider.py +315 -0
- icdev/tools/llm/embedding_provider.py +438 -0
- icdev/tools/llm/gemini_provider.py +381 -0
- icdev/tools/llm/ibm_watsonx_provider.py +232 -0
- icdev/tools/llm/oci_genai_provider.py +462 -0
- icdev/tools/llm/ollama_provider.py +340 -0
- icdev/tools/llm/openai_provider.py +225 -0
- icdev/tools/llm/provider.py +355 -0
- icdev/tools/llm/provider_sdk.py +175 -0
- icdev/tools/llm/router.py +780 -0
- icdev/tools/llm/vertex_ai_provider.py +374 -0
- icdev/tools/maintenance/__init__.py +2 -0
- icdev/tools/maintenance/dependency_scanner.py +1030 -0
- icdev/tools/maintenance/maintenance_auditor.py +815 -0
- icdev/tools/maintenance/remediation_engine.py +966 -0
- icdev/tools/maintenance/vulnerability_checker.py +987 -0
- icdev/tools/mbse/__init__.py +3 -0
- icdev/tools/mbse/des_assessor.py +1186 -0
- icdev/tools/mbse/des_report_generator.py +800 -0
- icdev/tools/mbse/diagram_extractor.py +811 -0
- icdev/tools/mbse/digital_thread.py +1665 -0
- icdev/tools/mbse/model_code_generator.py +1122 -0
- icdev/tools/mbse/model_control_mapper.py +420 -0
- icdev/tools/mbse/pi_model_tracker.py +1093 -0
- icdev/tools/mbse/reqif_parser.py +1483 -0
- icdev/tools/mbse/sync_engine.py +1805 -0
- icdev/tools/mbse/xmi_parser.py +1573 -0
- icdev/tools/mcp/__init__.py +1 -0
- icdev/tools/mcp/base_server.py +535 -0
- icdev/tools/mcp/builder_server.py +725 -0
- icdev/tools/mcp/compliance_server.py +1407 -0
- icdev/tools/mcp/context_indexer.py +199 -0
- icdev/tools/mcp/context_server.py +305 -0
- icdev/tools/mcp/core_server.py +679 -0
- icdev/tools/mcp/devsecops_server.py +432 -0
- icdev/tools/mcp/gap_handlers.py +1079 -0
- icdev/tools/mcp/gateway_server.py +339 -0
- icdev/tools/mcp/generate_registry.py +623 -0
- icdev/tools/mcp/infra_server.py +264 -0
- icdev/tools/mcp/innovation_server.py +316 -0
- icdev/tools/mcp/integration_server.py +527 -0
- icdev/tools/mcp/knowledge_server.py +429 -0
- icdev/tools/mcp/maintenance_server.py +248 -0
- icdev/tools/mcp/marketplace_server.py +499 -0
- icdev/tools/mcp/mbse_server.py +398 -0
- icdev/tools/mcp/modernization_server.py +496 -0
- icdev/tools/mcp/observability_server.py +354 -0
- icdev/tools/mcp/requirements_server.py +415 -0
- icdev/tools/mcp/simulation_server.py +468 -0
- icdev/tools/mcp/standalone/__init__.py +2 -0
- icdev/tools/mcp/standalone/builder.py +59 -0
- icdev/tools/mcp/standalone/compliance.py +59 -0
- icdev/tools/mcp/standalone/core.py +59 -0
- icdev/tools/mcp/standalone/knowledge.py +59 -0
- icdev/tools/mcp/standalone/maintenance.py +59 -0
- icdev/tools/mcp/supply_chain_server.py +476 -0
- icdev/tools/mcp/tool_registry.py +2008 -0
- icdev/tools/mcp/unified_server.py +158 -0
- icdev/tools/memory/__init__.py +2 -0
- icdev/tools/memory/auto_capture.py +347 -0
- icdev/tools/memory/embed_memory.py +158 -0
- icdev/tools/memory/history_compressor.py +334 -0
- icdev/tools/memory/hybrid_search.py +236 -0
- icdev/tools/memory/maintenance_cron.py +289 -0
- icdev/tools/memory/memory_consolidation.py +444 -0
- icdev/tools/memory/memory_db.py +133 -0
- icdev/tools/memory/memory_read.py +102 -0
- icdev/tools/memory/memory_write.py +222 -0
- icdev/tools/memory/semantic_search.py +139 -0
- icdev/tools/memory/time_decay.py +435 -0
- icdev/tools/modernization/__init__.py +3 -0
- icdev/tools/modernization/architecture_extractor.py +734 -0
- icdev/tools/modernization/compliance_bridge.py +1499 -0
- icdev/tools/modernization/db_migration_planner.py +1385 -0
- icdev/tools/modernization/doc_generator.py +1428 -0
- icdev/tools/modernization/framework_migrator.py +1525 -0
- icdev/tools/modernization/legacy_analyzer.py +1948 -0
- icdev/tools/modernization/migration_code_generator.py +1639 -0
- icdev/tools/modernization/migration_report_generator.py +1653 -0
- icdev/tools/modernization/migration_tracker.py +1726 -0
- icdev/tools/modernization/monolith_decomposer.py +1508 -0
- icdev/tools/modernization/seven_r_assessor.py +1658 -0
- icdev/tools/modernization/strangler_fig_manager.py +1705 -0
- icdev/tools/modernization/ui_analyzer.py +771 -0
- icdev/tools/modernization/version_migrator.py +1392 -0
- icdev/tools/monitor/__init__.py +1 -0
- icdev/tools/monitor/alert_correlator.py +495 -0
- icdev/tools/monitor/auto_resolver.py +612 -0
- icdev/tools/monitor/health_checker.py +509 -0
- icdev/tools/monitor/heartbeat_daemon.py +792 -0
- icdev/tools/monitor/log_analyzer.py +516 -0
- icdev/tools/monitor/metric_collector.py +496 -0
- icdev/tools/mosa/__init__.py +10 -0
- icdev/tools/mosa/icd_generator.py +370 -0
- icdev/tools/mosa/modular_design_analyzer.py +683 -0
- icdev/tools/mosa/mosa_code_enforcer.py +349 -0
- icdev/tools/mosa/tsp_generator.py +265 -0
- icdev/tools/observability/__init__.py +100 -0
- icdev/tools/observability/genai_attributes.py +88 -0
- icdev/tools/observability/instrumentation.py +140 -0
- icdev/tools/observability/mlflow_exporter.py +194 -0
- icdev/tools/observability/otel_tracer.py +168 -0
- icdev/tools/observability/provenance/__init__.py +3 -0
- icdev/tools/observability/provenance/prov_recorder.py +324 -0
- icdev/tools/observability/shap/__init__.py +3 -0
- icdev/tools/observability/shap/agent_shap.py +275 -0
- icdev/tools/observability/sqlite_tracer.py +361 -0
- icdev/tools/observability/trace_context.py +205 -0
- icdev/tools/observability/tracer.py +230 -0
- icdev/tools/orchestration/__init__.py +2 -0
- icdev/tools/orchestration/workflow_composer.py +361 -0
- icdev/tools/project/__init__.py +1 -0
- icdev/tools/project/manifest_loader.py +418 -0
- icdev/tools/project/project_create.py +350 -0
- icdev/tools/project/project_list.py +174 -0
- icdev/tools/project/project_scaffold.py +1715 -0
- icdev/tools/project/project_status.py +479 -0
- icdev/tools/project/session_context_builder.py +757 -0
- icdev/tools/project/validate_manifest.py +55 -0
- icdev/tools/registry/__init__.py +10 -0
- icdev/tools/registry/absorption_engine.py +832 -0
- icdev/tools/registry/capability_evaluator.py +668 -0
- icdev/tools/registry/child_registry.py +617 -0
- icdev/tools/registry/cross_pollinator.py +1065 -0
- icdev/tools/registry/genome_manager.py +671 -0
- icdev/tools/registry/learning_collector.py +912 -0
- icdev/tools/registry/propagation_manager.py +942 -0
- icdev/tools/registry/staging_manager.py +742 -0
- icdev/tools/registry/telemetry_collector.py +423 -0
- icdev/tools/requirements/__init__.py +1 -0
- icdev/tools/requirements/ai_governance_scorer.py +208 -0
- icdev/tools/requirements/boundary_analyzer.py +1293 -0
- icdev/tools/requirements/clarification_engine.py +618 -0
- icdev/tools/requirements/complexity_scorer.py +387 -0
- icdev/tools/requirements/consistency_analyzer.py +803 -0
- icdev/tools/requirements/constitution_manager.py +605 -0
- icdev/tools/requirements/decomposition_engine.py +778 -0
- icdev/tools/requirements/document_extractor.py +1016 -0
- icdev/tools/requirements/elicitation_techniques.py +519 -0
- icdev/tools/requirements/gap_detector.py +271 -0
- icdev/tools/requirements/intake_engine.py +2188 -0
- icdev/tools/requirements/prd_generator.py +847 -0
- icdev/tools/requirements/prd_validator.py +595 -0
- icdev/tools/requirements/readiness_scorer.py +313 -0
- icdev/tools/requirements/spec_organizer.py +1029 -0
- icdev/tools/requirements/spec_quality_checker.py +1097 -0
- icdev/tools/requirements/traceability_builder.py +579 -0
- icdev/tools/resilience/__init__.py +34 -0
- icdev/tools/resilience/circuit_breaker.py +340 -0
- icdev/tools/resilience/correlation.py +150 -0
- icdev/tools/resilience/errors.py +81 -0
- icdev/tools/resilience/retry.py +95 -0
- icdev/tools/schemas/__init__.py +27 -0
- icdev/tools/schemas/chat.py +61 -0
- icdev/tools/schemas/compliance.py +56 -0
- icdev/tools/schemas/core.py +85 -0
- icdev/tools/schemas/innovation.py +37 -0
- icdev/tools/schemas/validation.py +109 -0
- icdev/tools/sdk/__init__.py +3 -0
- icdev/tools/sdk/icdev_client.py +218 -0
- icdev/tools/security/__init__.py +1 -0
- icdev/tools/security/agent_output_validator.py +330 -0
- icdev/tools/security/agent_trust_scorer.py +466 -0
- icdev/tools/security/ai_bom_generator.py +725 -0
- icdev/tools/security/ai_telemetry_logger.py +469 -0
- icdev/tools/security/atlas_red_team.py +543 -0
- icdev/tools/security/code_pattern_scanner.py +378 -0
- icdev/tools/security/confabulation_detector.py +271 -0
- icdev/tools/security/container_scanner.py +491 -0
- icdev/tools/security/dependency_auditor.py +944 -0
- icdev/tools/security/endpoint_security_scanner.py +579 -0
- icdev/tools/security/mcp_tool_authorizer.py +243 -0
- icdev/tools/security/prompt_injection_detector.py +737 -0
- icdev/tools/security/sast_runner.py +948 -0
- icdev/tools/security/secret_detector.py +378 -0
- icdev/tools/security/tool_chain_validator.py +357 -0
- icdev/tools/security/vuln_scanner.py +539 -0
- icdev/tools/simulation/__init__.py +2 -0
- icdev/tools/simulation/coa_generator.py +1552 -0
- icdev/tools/simulation/monte_carlo.py +758 -0
- icdev/tools/simulation/scenario_manager.py +1073 -0
- icdev/tools/simulation/simulation_engine.py +1104 -0
- icdev/tools/supply_chain/__init__.py +2 -0
- icdev/tools/supply_chain/cve_triager.py +705 -0
- icdev/tools/supply_chain/dependency_graph.py +645 -0
- icdev/tools/supply_chain/isa_manager.py +540 -0
- icdev/tools/supply_chain/scrm_assessor.py +546 -0
- icdev/tools/testing/__init__.py +2 -0
- icdev/tools/testing/acceptance_validator.py +411 -0
- icdev/tools/testing/claude_dir_validator.py +831 -0
- icdev/tools/testing/data_types.py +199 -0
- icdev/tools/testing/e2e_runner.py +715 -0
- icdev/tools/testing/fuzz_cli.py +306 -0
- icdev/tools/testing/health_check.py +483 -0
- icdev/tools/testing/platform_check.py +143 -0
- icdev/tools/testing/production_audit.py +1862 -0
- icdev/tools/testing/production_remediate.py +804 -0
- icdev/tools/testing/screenshot_validator.py +539 -0
- icdev/tools/testing/smoke_test.py +283 -0
- icdev/tools/testing/test_agent_models.py +117 -0
- icdev/tools/testing/test_orchestrator.py +957 -0
- icdev/tools/testing/utils.py +229 -0
- icdev/tools/translation/__init__.py +17 -0
- icdev/tools/translation/code_translator.py +550 -0
- icdev/tools/translation/dependency_mapper.py +277 -0
- icdev/tools/translation/feature_map.py +395 -0
- icdev/tools/translation/project_assembler.py +439 -0
- icdev/tools/translation/source_extractor.py +609 -0
- icdev/tools/translation/test_translator.py +333 -0
- icdev/tools/translation/translation_manager.py +582 -0
- icdev/tools/translation/translation_validator.py +662 -0
- icdev/tools/translation/type_checker.py +371 -0
- icdev-1.0.0.dist-info/METADATA +868 -0
- icdev-1.0.0.dist-info/RECORD +1105 -0
- icdev-1.0.0.dist-info/WHEEL +5 -0
- icdev-1.0.0.dist-info/entry_points.txt +9 -0
- icdev-1.0.0.dist-info/licenses/LICENSE +254 -0
- icdev-1.0.0.dist-info/licenses/NOTICE +268 -0
- icdev-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1149 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# CUI // SP-CTI
|
|
3
|
+
# Controlled by: Department of Defense
|
|
4
|
+
# CUI Category: CTI
|
|
5
|
+
# Distribution: D
|
|
6
|
+
# POC: ICDEV System Administrator
|
|
7
|
+
"""Compliance-First Triage Pipeline — 5-stage safety gate for innovation signals.
|
|
8
|
+
|
|
9
|
+
Every innovation signal discovered by the web scanner passes through this
|
|
10
|
+
5-stage pipeline before solution generation is permitted. Each stage can BLOCK
|
|
11
|
+
the signal, preventing unsafe, non-compliant, or duplicate innovations from
|
|
12
|
+
entering the build pipeline.
|
|
13
|
+
|
|
14
|
+
Pipeline Stages:
|
|
15
|
+
1. Classify Signal — Map to signal_categories from innovation_config.yaml
|
|
16
|
+
2. GOTCHA Fit Check — Signal must map to at least one GOTCHA layer
|
|
17
|
+
3. Boundary Impact — Estimate ATO boundary impact (GREEN/YELLOW/ORANGE/RED)
|
|
18
|
+
4. Compliance Pre-Check — Detect compliance-weakening anti-patterns
|
|
19
|
+
5. Duplicate/License — Content-hash dedup + blocked license detection
|
|
20
|
+
|
|
21
|
+
Triage Outcomes:
|
|
22
|
+
- approved — All stages passed, score >= auto_queue threshold (0.80)
|
|
23
|
+
- suggested — All stages passed, score >= suggest threshold (0.50)
|
|
24
|
+
- blocked — One or more stages blocked the signal
|
|
25
|
+
- logged — Score below suggest threshold, logged for trend analysis
|
|
26
|
+
|
|
27
|
+
Architecture:
|
|
28
|
+
- All triage decisions stored in innovation_triage_log (append-only, D6)
|
|
29
|
+
- Signals updated with triage_result, gotcha_layer, boundary_tier columns
|
|
30
|
+
- Status transitions: scored -> triaged (after triage completes)
|
|
31
|
+
- Config-driven thresholds from args/innovation_config.yaml (D26 pattern)
|
|
32
|
+
- Audit trail via audit_logger (NIST AU compliance)
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
# Triage a single signal
|
|
36
|
+
python tools/innovation/triage_engine.py --triage --signal-id "sig-xxx" --json
|
|
37
|
+
|
|
38
|
+
# Triage all scored signals
|
|
39
|
+
python tools/innovation/triage_engine.py --triage-all --json
|
|
40
|
+
|
|
41
|
+
# Get triage summary
|
|
42
|
+
python tools/innovation/triage_engine.py --summary --json
|
|
43
|
+
|
|
44
|
+
# Triage with custom DB path
|
|
45
|
+
python tools/innovation/triage_engine.py --triage-all --db-path /path/to/icdev.db --json
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
import argparse
|
|
49
|
+
import hashlib
|
|
50
|
+
import json
|
|
51
|
+
import os
|
|
52
|
+
import re
|
|
53
|
+
import sqlite3
|
|
54
|
+
import sys
|
|
55
|
+
import uuid
|
|
56
|
+
from datetime import datetime, timezone, timedelta
|
|
57
|
+
from pathlib import Path
|
|
58
|
+
from icdev._paths import get_project_root
|
|
59
|
+
|
|
60
|
+
# =========================================================================
|
|
61
|
+
# PATH SETUP
|
|
62
|
+
# =========================================================================
|
|
63
|
+
BASE_DIR = get_project_root()
|
|
64
|
+
if str(BASE_DIR) not in sys.path:
|
|
65
|
+
sys.path.insert(0, str(BASE_DIR))
|
|
66
|
+
|
|
67
|
+
DB_PATH = Path(os.environ.get("ICDEV_DB_PATH", str(BASE_DIR / "data" / "icdev.db")))
|
|
68
|
+
CONFIG_PATH = BASE_DIR / "args" / "innovation_config.yaml"
|
|
69
|
+
|
|
70
|
+
# =========================================================================
|
|
71
|
+
# GRACEFUL IMPORTS
|
|
72
|
+
# =========================================================================
|
|
73
|
+
try:
|
|
74
|
+
import yaml
|
|
75
|
+
_HAS_YAML = True
|
|
76
|
+
except ImportError:
|
|
77
|
+
_HAS_YAML = False
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
from icdev.tools.audit.audit_logger import log_event as audit_log_event
|
|
81
|
+
_HAS_AUDIT = True
|
|
82
|
+
except ImportError:
|
|
83
|
+
_HAS_AUDIT = False
|
|
84
|
+
|
|
85
|
+
def audit_log_event(**kwargs):
|
|
86
|
+
return -1
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# =========================================================================
|
|
90
|
+
# CONSTANTS
|
|
91
|
+
# =========================================================================
|
|
92
|
+
GOTCHA_LAYERS = ["goal", "tool", "arg", "context", "hardprompt"]
|
|
93
|
+
|
|
94
|
+
BOUNDARY_TIERS = {
|
|
95
|
+
"GREEN": "No ATO boundary change",
|
|
96
|
+
"YELLOW": "Minor adjustment — new component within boundary",
|
|
97
|
+
"ORANGE": "Significant change — cross-boundary data flow",
|
|
98
|
+
"RED": "ATO-invalidating — boundary expansion or classification change",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# Keywords that indicate compliance-weakening intent
|
|
102
|
+
COMPLIANCE_ANTI_PATTERNS = [
|
|
103
|
+
r"\bdisable\s+security\b",
|
|
104
|
+
r"\bskip\s+(checks?|validation|gates?|scans?|tests?)\b",
|
|
105
|
+
r"\bremove\s+(gates?|controls?|guardrails?|restrictions?)\b",
|
|
106
|
+
r"\bbypass\s+(auth|authentication|authorization|mfa|rbac)\b",
|
|
107
|
+
r"\bno\s+(encryption|tls|mtls|audit)\b",
|
|
108
|
+
r"\bweaken\s+(security|compliance|controls?)\b",
|
|
109
|
+
r"\bignore\s+(stig|nist|fedramp|cmmc|cve|vulnerability)\b",
|
|
110
|
+
r"\bhardcode\s+(secret|password|key|credential|token)\b",
|
|
111
|
+
r"\bdisable\s+(logging|audit|monitoring|alerting)\b",
|
|
112
|
+
r"\ballow\s+anonymous\b",
|
|
113
|
+
r"\broot\s+access\b",
|
|
114
|
+
r"\bprivileged\s+container\b",
|
|
115
|
+
r"\bno\s+rbac\b",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
# Keywords indicating new external connections (ORANGE+)
|
|
119
|
+
EXTERNAL_CONNECTION_KEYWORDS = [
|
|
120
|
+
"external api", "third-party", "third party", "new endpoint",
|
|
121
|
+
"outbound connection", "webhook to external", "saas integration",
|
|
122
|
+
"public internet", "cross-boundary", "inter-enclave",
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
# Keywords indicating classification changes (RED)
|
|
126
|
+
CLASSIFICATION_CHANGE_KEYWORDS = [
|
|
127
|
+
"classification change", "upgrade to secret", "downgrade",
|
|
128
|
+
"reclassify", "il6", "sipr", "secret data", "ts/sci",
|
|
129
|
+
"boundary expansion", "new enclave", "new authorization boundary",
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
# Keywords indicating new data flows (YELLOW+)
|
|
133
|
+
DATA_FLOW_KEYWORDS = [
|
|
134
|
+
"new data flow", "data exchange", "new integration",
|
|
135
|
+
"ingest from", "export to", "data pipeline",
|
|
136
|
+
"new database", "new storage", "new queue",
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
# License patterns for detection in signal text
|
|
140
|
+
LICENSE_PATTERNS = {
|
|
141
|
+
"GPL-3.0": [r"\bGPL[\s-]?3", r"\bGPLv3\b", r"\bGNU General Public License.*3\b"],
|
|
142
|
+
"AGPL-3.0": [r"\bAGPL[\s-]?3", r"\bAGPLv3\b", r"\bAffero\b"],
|
|
143
|
+
"SSPL-1.0": [r"\bSSPL\b", r"\bServer Side Public License\b"],
|
|
144
|
+
"BSL-1.1": [r"\bBSL[\s-]?1\.1\b", r"\bBusiness Source License\b"],
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# =========================================================================
|
|
149
|
+
# DATABASE HELPERS
|
|
150
|
+
# =========================================================================
|
|
151
|
+
def _get_db(db_path=None):
|
|
152
|
+
"""Get database connection with dict-like row access."""
|
|
153
|
+
path = db_path or DB_PATH
|
|
154
|
+
if not Path(path).exists():
|
|
155
|
+
raise FileNotFoundError(f"Database not found: {path}")
|
|
156
|
+
conn = sqlite3.connect(str(path))
|
|
157
|
+
conn.row_factory = sqlite3.Row
|
|
158
|
+
return conn
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _now():
|
|
162
|
+
"""ISO-8601 UTC timestamp."""
|
|
163
|
+
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _audit(event_type, actor, action, details=None, project_id=None):
|
|
167
|
+
"""Write audit trail entry."""
|
|
168
|
+
if _HAS_AUDIT:
|
|
169
|
+
try:
|
|
170
|
+
audit_log_event(
|
|
171
|
+
event_type=event_type,
|
|
172
|
+
actor=actor,
|
|
173
|
+
action=action,
|
|
174
|
+
details=json.dumps(details) if details else None,
|
|
175
|
+
project_id=project_id or "innovation-engine",
|
|
176
|
+
)
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _load_config():
|
|
182
|
+
"""Load innovation config from YAML."""
|
|
183
|
+
if not _HAS_YAML:
|
|
184
|
+
return {}
|
|
185
|
+
if not CONFIG_PATH.exists():
|
|
186
|
+
return {}
|
|
187
|
+
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
|
|
188
|
+
return yaml.safe_load(f) or {}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _ensure_triage_tables(conn):
|
|
192
|
+
"""Ensure the innovation_triage_log table exists.
|
|
193
|
+
|
|
194
|
+
Creates the append-only triage log table if it does not already exist.
|
|
195
|
+
Also adds triage columns to innovation_signals if they are missing.
|
|
196
|
+
"""
|
|
197
|
+
conn.execute("""
|
|
198
|
+
CREATE TABLE IF NOT EXISTS innovation_triage_log (
|
|
199
|
+
id TEXT PRIMARY KEY,
|
|
200
|
+
signal_id TEXT NOT NULL,
|
|
201
|
+
stage INTEGER NOT NULL,
|
|
202
|
+
stage_name TEXT NOT NULL,
|
|
203
|
+
result TEXT NOT NULL CHECK(result IN ('pass', 'block', 'warn')),
|
|
204
|
+
details TEXT,
|
|
205
|
+
triaged_at TEXT NOT NULL
|
|
206
|
+
)
|
|
207
|
+
""")
|
|
208
|
+
|
|
209
|
+
# Add triage columns to innovation_signals if not present
|
|
210
|
+
existing_cols = {
|
|
211
|
+
row[1] for row in conn.execute("PRAGMA table_info(innovation_signals)").fetchall()
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
alter_stmts = []
|
|
215
|
+
if "triage_result" not in existing_cols:
|
|
216
|
+
alter_stmts.append(
|
|
217
|
+
"ALTER TABLE innovation_signals ADD COLUMN triage_result TEXT"
|
|
218
|
+
)
|
|
219
|
+
if "gotcha_layer" not in existing_cols:
|
|
220
|
+
alter_stmts.append(
|
|
221
|
+
"ALTER TABLE innovation_signals ADD COLUMN gotcha_layer TEXT"
|
|
222
|
+
)
|
|
223
|
+
if "boundary_tier" not in existing_cols:
|
|
224
|
+
alter_stmts.append(
|
|
225
|
+
"ALTER TABLE innovation_signals ADD COLUMN boundary_tier TEXT"
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
for stmt in alter_stmts:
|
|
229
|
+
try:
|
|
230
|
+
conn.execute(stmt)
|
|
231
|
+
except sqlite3.OperationalError:
|
|
232
|
+
pass # Column may already exist in a concurrent scenario
|
|
233
|
+
|
|
234
|
+
conn.commit()
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _log_triage_stage(conn, signal_id, stage, stage_name, result, details):
|
|
238
|
+
"""Insert a triage log entry (append-only)."""
|
|
239
|
+
log_id = f"tlog-{uuid.uuid4().hex[:12]}"
|
|
240
|
+
conn.execute(
|
|
241
|
+
"""INSERT INTO innovation_triage_log
|
|
242
|
+
(id, signal_id, stage, stage_name, result, details, triaged_at)
|
|
243
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)""",
|
|
244
|
+
(
|
|
245
|
+
log_id,
|
|
246
|
+
signal_id,
|
|
247
|
+
stage,
|
|
248
|
+
stage_name,
|
|
249
|
+
result,
|
|
250
|
+
json.dumps(details) if isinstance(details, dict) else details,
|
|
251
|
+
_now(),
|
|
252
|
+
),
|
|
253
|
+
)
|
|
254
|
+
return log_id
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
# =========================================================================
|
|
258
|
+
# STAGE 1: CLASSIFY SIGNAL
|
|
259
|
+
# =========================================================================
|
|
260
|
+
def _stage_classify_signal(signal, config):
|
|
261
|
+
"""Map signal to signal_categories via keyword matching.
|
|
262
|
+
|
|
263
|
+
Scans signal title + description against each category's keyword list.
|
|
264
|
+
Returns the best-matching category (highest keyword hit count).
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
signal: Dict with at least 'title' and 'description'.
|
|
268
|
+
config: Full innovation config dict.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Tuple of (result, details) where result is 'pass' or 'warn'.
|
|
272
|
+
Never blocks — classification is informational.
|
|
273
|
+
"""
|
|
274
|
+
categories = config.get("signal_categories", {})
|
|
275
|
+
if not categories:
|
|
276
|
+
return "pass", {
|
|
277
|
+
"category": "uncategorized",
|
|
278
|
+
"priority_boost": 1.0,
|
|
279
|
+
"auto_triage": False,
|
|
280
|
+
"note": "No signal_categories in config; defaulting to uncategorized",
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
text = f"{signal.get('title', '')} {signal.get('description', '')}".lower()
|
|
284
|
+
|
|
285
|
+
best_category = None
|
|
286
|
+
best_hits = 0
|
|
287
|
+
best_boost = 1.0
|
|
288
|
+
best_auto = False
|
|
289
|
+
|
|
290
|
+
for cat_name, cat_config in categories.items():
|
|
291
|
+
keywords = cat_config.get("keywords", [])
|
|
292
|
+
hits = sum(1 for kw in keywords if kw.lower() in text)
|
|
293
|
+
if hits > best_hits:
|
|
294
|
+
best_hits = hits
|
|
295
|
+
best_category = cat_name
|
|
296
|
+
best_boost = cat_config.get("priority_boost", 1.0)
|
|
297
|
+
best_auto = cat_config.get("auto_triage", False)
|
|
298
|
+
|
|
299
|
+
if best_category is None:
|
|
300
|
+
best_category = "uncategorized"
|
|
301
|
+
|
|
302
|
+
return "pass", {
|
|
303
|
+
"category": best_category,
|
|
304
|
+
"keyword_hits": best_hits,
|
|
305
|
+
"priority_boost": best_boost,
|
|
306
|
+
"auto_triage": best_auto,
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
# =========================================================================
|
|
311
|
+
# STAGE 2: GOTCHA FIT CHECK
|
|
312
|
+
# =========================================================================
|
|
313
|
+
def _stage_gotcha_fit(signal, config):
|
|
314
|
+
"""Check whether signal maps to at least one GOTCHA layer.
|
|
315
|
+
|
|
316
|
+
Uses triage.gotcha_fit.layer_mapping from config to match keywords
|
|
317
|
+
in the signal title + description against each GOTCHA layer.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
signal: Dict with at least 'title' and 'description'.
|
|
321
|
+
config: Full innovation config dict.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
Tuple of (result, details). Blocks if no GOTCHA layer matches
|
|
325
|
+
and triage.gotcha_fit.required_layer is true.
|
|
326
|
+
"""
|
|
327
|
+
triage_config = config.get("triage", {})
|
|
328
|
+
gotcha_config = triage_config.get("gotcha_fit", {})
|
|
329
|
+
layer_mapping = gotcha_config.get("layer_mapping", {})
|
|
330
|
+
required = gotcha_config.get("required_layer", True)
|
|
331
|
+
|
|
332
|
+
text = f"{signal.get('title', '')} {signal.get('description', '')}".lower()
|
|
333
|
+
|
|
334
|
+
matched_layers = []
|
|
335
|
+
layer_scores = {}
|
|
336
|
+
|
|
337
|
+
for layer, keywords in layer_mapping.items():
|
|
338
|
+
hits = sum(1 for kw in keywords if kw.lower() in text)
|
|
339
|
+
layer_scores[layer] = hits
|
|
340
|
+
if hits > 0:
|
|
341
|
+
matched_layers.append(layer)
|
|
342
|
+
|
|
343
|
+
if not matched_layers and required:
|
|
344
|
+
return "block", {
|
|
345
|
+
"matched_layers": [],
|
|
346
|
+
"layer_scores": layer_scores,
|
|
347
|
+
"reason": "Signal does not map to any GOTCHA layer (goal/tool/arg/context/hardprompt)",
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
# Pick the best-matching layer (most keyword hits)
|
|
351
|
+
best_layer = None
|
|
352
|
+
if matched_layers:
|
|
353
|
+
best_layer = max(matched_layers, key=lambda l: layer_scores.get(l, 0))
|
|
354
|
+
|
|
355
|
+
return "pass", {
|
|
356
|
+
"matched_layers": matched_layers,
|
|
357
|
+
"best_layer": best_layer,
|
|
358
|
+
"layer_scores": layer_scores,
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# =========================================================================
|
|
363
|
+
# STAGE 3: BOUNDARY IMPACT ASSESSMENT
|
|
364
|
+
# =========================================================================
|
|
365
|
+
def _stage_boundary_impact(signal, config):
|
|
366
|
+
"""Estimate ATO boundary impact tier.
|
|
367
|
+
|
|
368
|
+
Analyzes signal text for indicators of boundary change severity:
|
|
369
|
+
- RED: Classification changes, boundary expansion (BLOCKS)
|
|
370
|
+
- ORANGE: Cross-boundary data flows, new external connections (WARN)
|
|
371
|
+
- YELLOW: New data flows within boundary (PASS with note)
|
|
372
|
+
- GREEN: No boundary impact (PASS)
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
signal: Dict with at least 'title' and 'description'.
|
|
376
|
+
config: Full innovation config dict.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
Tuple of (result, details). Blocks on RED if configured.
|
|
380
|
+
"""
|
|
381
|
+
triage_config = config.get("triage", {})
|
|
382
|
+
boundary_config = triage_config.get("boundary_check", {})
|
|
383
|
+
block_on_red = boundary_config.get("block_on_red", True)
|
|
384
|
+
require_coa_orange = boundary_config.get("require_coa_for_orange", True)
|
|
385
|
+
|
|
386
|
+
if not boundary_config.get("enabled", True):
|
|
387
|
+
return "pass", {"tier": "GREEN", "note": "Boundary check disabled in config"}
|
|
388
|
+
|
|
389
|
+
text = f"{signal.get('title', '')} {signal.get('description', '')}".lower()
|
|
390
|
+
|
|
391
|
+
# Check for RED indicators (most severe first)
|
|
392
|
+
red_hits = [kw for kw in CLASSIFICATION_CHANGE_KEYWORDS if kw.lower() in text]
|
|
393
|
+
if red_hits:
|
|
394
|
+
result = "block" if block_on_red else "warn"
|
|
395
|
+
return result, {
|
|
396
|
+
"tier": "RED",
|
|
397
|
+
"indicators": red_hits,
|
|
398
|
+
"reason": "Signal implies ATO-invalidating change (classification or boundary expansion)",
|
|
399
|
+
"blocked": block_on_red,
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
# Check for ORANGE indicators
|
|
403
|
+
orange_hits = [kw for kw in EXTERNAL_CONNECTION_KEYWORDS if kw.lower() in text]
|
|
404
|
+
if orange_hits:
|
|
405
|
+
return "warn", {
|
|
406
|
+
"tier": "ORANGE",
|
|
407
|
+
"indicators": orange_hits,
|
|
408
|
+
"reason": "Signal implies cross-boundary or external connection change",
|
|
409
|
+
"requires_coa": require_coa_orange,
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
# Check for YELLOW indicators
|
|
413
|
+
yellow_hits = [kw for kw in DATA_FLOW_KEYWORDS if kw.lower() in text]
|
|
414
|
+
if yellow_hits:
|
|
415
|
+
return "pass", {
|
|
416
|
+
"tier": "YELLOW",
|
|
417
|
+
"indicators": yellow_hits,
|
|
418
|
+
"reason": "Signal implies new data flow within existing boundary",
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
# Default: GREEN
|
|
422
|
+
return "pass", {
|
|
423
|
+
"tier": "GREEN",
|
|
424
|
+
"indicators": [],
|
|
425
|
+
"reason": "No boundary impact indicators detected",
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
# =========================================================================
|
|
430
|
+
# STAGE 4: COMPLIANCE PRE-CHECK
|
|
431
|
+
# =========================================================================
|
|
432
|
+
def _stage_compliance_precheck(signal, config):
|
|
433
|
+
"""Check whether implementing this signal would weaken compliance posture.
|
|
434
|
+
|
|
435
|
+
Scans signal text for anti-patterns that indicate compliance-weakening
|
|
436
|
+
intent (e.g., "disable security", "skip checks", "bypass auth").
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
signal: Dict with at least 'title' and 'description'.
|
|
440
|
+
config: Full innovation config dict.
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Tuple of (result, details). Blocks if compliance-weakening detected
|
|
444
|
+
and triage.compliance_check.block_on_weakening is true.
|
|
445
|
+
"""
|
|
446
|
+
triage_config = config.get("triage", {})
|
|
447
|
+
compliance_config = triage_config.get("compliance_check", {})
|
|
448
|
+
|
|
449
|
+
if not compliance_config.get("enabled", True):
|
|
450
|
+
return "pass", {"note": "Compliance pre-check disabled in config"}
|
|
451
|
+
|
|
452
|
+
block_on_weakening = compliance_config.get("block_on_weakening", True)
|
|
453
|
+
text = f"{signal.get('title', '')} {signal.get('description', '')}".lower()
|
|
454
|
+
|
|
455
|
+
violations = []
|
|
456
|
+
for pattern in COMPLIANCE_ANTI_PATTERNS:
|
|
457
|
+
matches = re.findall(pattern, text, re.IGNORECASE)
|
|
458
|
+
if matches:
|
|
459
|
+
violations.append({
|
|
460
|
+
"pattern": pattern,
|
|
461
|
+
"matches": matches,
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
if violations:
|
|
465
|
+
result = "block" if block_on_weakening else "warn"
|
|
466
|
+
return result, {
|
|
467
|
+
"compliance_weakening": True,
|
|
468
|
+
"violation_count": len(violations),
|
|
469
|
+
"violations": violations,
|
|
470
|
+
"reason": "Signal contains compliance-weakening anti-patterns",
|
|
471
|
+
"blocked": block_on_weakening,
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
# Also check which frameworks would be validated
|
|
475
|
+
frameworks = compliance_config.get("frameworks_to_validate", [])
|
|
476
|
+
|
|
477
|
+
return "pass", {
|
|
478
|
+
"compliance_weakening": False,
|
|
479
|
+
"violation_count": 0,
|
|
480
|
+
"frameworks_validated": frameworks,
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
# =========================================================================
|
|
485
|
+
# STAGE 5: DUPLICATE / LICENSE CHECK
|
|
486
|
+
# =========================================================================
|
|
487
|
+
def _stage_duplicate_license(signal, config, conn):
|
|
488
|
+
"""Check for duplicate signals and blocked licenses.
|
|
489
|
+
|
|
490
|
+
Deduplication: compares content_hash against existing signals within
|
|
491
|
+
the configured time window (triage.dedup.time_window_days). Uses exact
|
|
492
|
+
hash match (not semantic similarity, which requires embeddings).
|
|
493
|
+
|
|
494
|
+
License: scans signal text for references to blocked licenses
|
|
495
|
+
(GPL-3.0, AGPL-3.0, SSPL-1.0, BSL-1.1 from triage.license_check).
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
signal: Dict with at least 'title', 'description', 'content_hash'.
|
|
499
|
+
config: Full innovation config dict.
|
|
500
|
+
conn: Active database connection.
|
|
501
|
+
|
|
502
|
+
Returns:
|
|
503
|
+
Tuple of (result, details). Blocks on duplicate or blocked license.
|
|
504
|
+
"""
|
|
505
|
+
triage_config = config.get("triage", {})
|
|
506
|
+
dedup_config = triage_config.get("dedup", {})
|
|
507
|
+
license_config = triage_config.get("license_check", {})
|
|
508
|
+
|
|
509
|
+
issues = []
|
|
510
|
+
|
|
511
|
+
# --- Duplicate check ---
|
|
512
|
+
if dedup_config.get("enabled", True):
|
|
513
|
+
time_window = dedup_config.get("time_window_days", 90)
|
|
514
|
+
cutoff = (datetime.now(timezone.utc) - timedelta(days=time_window)).strftime(
|
|
515
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
516
|
+
)
|
|
517
|
+
content_hash = signal.get("content_hash", "")
|
|
518
|
+
|
|
519
|
+
if content_hash:
|
|
520
|
+
existing = conn.execute(
|
|
521
|
+
"""SELECT id, title, discovered_at
|
|
522
|
+
FROM innovation_signals
|
|
523
|
+
WHERE content_hash = ?
|
|
524
|
+
AND id != ?
|
|
525
|
+
AND discovered_at >= ?
|
|
526
|
+
ORDER BY discovered_at DESC
|
|
527
|
+
LIMIT 1""",
|
|
528
|
+
(content_hash, signal.get("id", ""), cutoff),
|
|
529
|
+
).fetchone()
|
|
530
|
+
|
|
531
|
+
if existing:
|
|
532
|
+
issues.append({
|
|
533
|
+
"type": "duplicate",
|
|
534
|
+
"existing_signal_id": existing["id"],
|
|
535
|
+
"existing_title": existing["title"],
|
|
536
|
+
"existing_date": existing["discovered_at"],
|
|
537
|
+
})
|
|
538
|
+
|
|
539
|
+
# Also do a title similarity check (simple exact-prefix match)
|
|
540
|
+
title = signal.get("title", "").strip()
|
|
541
|
+
if title and len(title) > 20:
|
|
542
|
+
title_prefix = title[:50]
|
|
543
|
+
similar = conn.execute(
|
|
544
|
+
"""SELECT id, title
|
|
545
|
+
FROM innovation_signals
|
|
546
|
+
WHERE title LIKE ?
|
|
547
|
+
AND id != ?
|
|
548
|
+
AND discovered_at >= ?
|
|
549
|
+
LIMIT 3""",
|
|
550
|
+
(f"{title_prefix}%", signal.get("id", ""), cutoff),
|
|
551
|
+
).fetchall()
|
|
552
|
+
|
|
553
|
+
if similar:
|
|
554
|
+
issues.append({
|
|
555
|
+
"type": "similar_title",
|
|
556
|
+
"similar_count": len(similar),
|
|
557
|
+
"similar_signals": [
|
|
558
|
+
{"id": s["id"], "title": s["title"]} for s in similar
|
|
559
|
+
],
|
|
560
|
+
})
|
|
561
|
+
|
|
562
|
+
# --- License check ---
|
|
563
|
+
if license_config.get("enabled", True):
|
|
564
|
+
blocked_licenses = license_config.get("blocked_licenses", [])
|
|
565
|
+
text = f"{signal.get('title', '')} {signal.get('description', '')} {signal.get('metadata', '')}"
|
|
566
|
+
|
|
567
|
+
detected_licenses = []
|
|
568
|
+
for license_id, patterns in LICENSE_PATTERNS.items():
|
|
569
|
+
if license_id in blocked_licenses or any(
|
|
570
|
+
bl.replace("-", "").lower() == license_id.replace("-", "").lower()
|
|
571
|
+
for bl in blocked_licenses
|
|
572
|
+
):
|
|
573
|
+
for pat in patterns:
|
|
574
|
+
if re.search(pat, text, re.IGNORECASE):
|
|
575
|
+
detected_licenses.append(license_id)
|
|
576
|
+
break
|
|
577
|
+
|
|
578
|
+
if detected_licenses:
|
|
579
|
+
issues.append({
|
|
580
|
+
"type": "blocked_license",
|
|
581
|
+
"licenses": detected_licenses,
|
|
582
|
+
"allowed_licenses": license_config.get("allowed_licenses", []),
|
|
583
|
+
})
|
|
584
|
+
|
|
585
|
+
# Determine result
|
|
586
|
+
has_duplicate = any(i["type"] == "duplicate" for i in issues)
|
|
587
|
+
has_blocked_license = any(i["type"] == "blocked_license" for i in issues)
|
|
588
|
+
|
|
589
|
+
if has_duplicate or has_blocked_license:
|
|
590
|
+
reasons = []
|
|
591
|
+
if has_duplicate:
|
|
592
|
+
reasons.append("Duplicate signal detected within time window")
|
|
593
|
+
if has_blocked_license:
|
|
594
|
+
lics = [
|
|
595
|
+
i["licenses"]
|
|
596
|
+
for i in issues
|
|
597
|
+
if i["type"] == "blocked_license"
|
|
598
|
+
]
|
|
599
|
+
flat_lics = [l for sublist in lics for l in sublist]
|
|
600
|
+
reasons.append(f"Blocked license(s) detected: {', '.join(flat_lics)}")
|
|
601
|
+
return "block", {
|
|
602
|
+
"issues": issues,
|
|
603
|
+
"reason": "; ".join(reasons),
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
has_similar = any(i["type"] == "similar_title" for i in issues)
|
|
607
|
+
if has_similar:
|
|
608
|
+
return "warn", {
|
|
609
|
+
"issues": issues,
|
|
610
|
+
"reason": "Similar signal titles found (not exact duplicate)",
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return "pass", {
|
|
614
|
+
"issues": [],
|
|
615
|
+
"reason": "No duplicates or license issues detected",
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
# =========================================================================
|
|
620
|
+
# TRIAGE ORCHESTRATOR
|
|
621
|
+
# =========================================================================
|
|
622
|
+
STAGE_REGISTRY = [
|
|
623
|
+
(1, "classify_signal", _stage_classify_signal),
|
|
624
|
+
(2, "gotcha_fit_check", _stage_gotcha_fit),
|
|
625
|
+
(3, "boundary_impact", _stage_boundary_impact),
|
|
626
|
+
(4, "compliance_precheck", _stage_compliance_precheck),
|
|
627
|
+
# Stage 5 handled separately (needs DB connection)
|
|
628
|
+
]
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def triage_signal(signal_id, db_path=None):
|
|
632
|
+
"""Run the full 5-stage compliance-first triage on a single signal.
|
|
633
|
+
|
|
634
|
+
Pipeline stages execute in order. Any stage returning 'block' marks the
|
|
635
|
+
signal as blocked and stops further evaluation (fail-fast). Warnings
|
|
636
|
+
are accumulated but do not block.
|
|
637
|
+
|
|
638
|
+
Args:
|
|
639
|
+
signal_id: ID of the signal in innovation_signals table.
|
|
640
|
+
db_path: Optional database path override.
|
|
641
|
+
|
|
642
|
+
Returns:
|
|
643
|
+
Dict with triage outcome, per-stage results, and final disposition.
|
|
644
|
+
"""
|
|
645
|
+
conn = _get_db(db_path)
|
|
646
|
+
try:
|
|
647
|
+
_ensure_triage_tables(conn)
|
|
648
|
+
|
|
649
|
+
# Fetch the signal
|
|
650
|
+
signal_row = conn.execute(
|
|
651
|
+
"SELECT * FROM innovation_signals WHERE id = ?",
|
|
652
|
+
(signal_id,),
|
|
653
|
+
).fetchone()
|
|
654
|
+
|
|
655
|
+
if not signal_row:
|
|
656
|
+
return {"error": f"Signal not found: {signal_id}"}
|
|
657
|
+
|
|
658
|
+
signal = dict(signal_row)
|
|
659
|
+
config = _load_config()
|
|
660
|
+
|
|
661
|
+
# Load scoring thresholds
|
|
662
|
+
scoring = config.get("scoring", {})
|
|
663
|
+
thresholds = scoring.get("thresholds", {})
|
|
664
|
+
auto_queue_threshold = thresholds.get("auto_queue", 0.80)
|
|
665
|
+
suggest_threshold = thresholds.get("suggest", 0.50)
|
|
666
|
+
|
|
667
|
+
stage_results = []
|
|
668
|
+
blocked = False
|
|
669
|
+
block_stage = None
|
|
670
|
+
warnings = []
|
|
671
|
+
gotcha_layer = None
|
|
672
|
+
boundary_tier = "GREEN"
|
|
673
|
+
category = None
|
|
674
|
+
|
|
675
|
+
# --- Stages 1-4 (signal + config only) ---
|
|
676
|
+
for stage_num, stage_name, stage_fn in STAGE_REGISTRY:
|
|
677
|
+
result, details = stage_fn(signal, config)
|
|
678
|
+
|
|
679
|
+
_log_triage_stage(conn, signal_id, stage_num, stage_name, result, details)
|
|
680
|
+
|
|
681
|
+
stage_results.append({
|
|
682
|
+
"stage": stage_num,
|
|
683
|
+
"name": stage_name,
|
|
684
|
+
"result": result,
|
|
685
|
+
"details": details,
|
|
686
|
+
})
|
|
687
|
+
|
|
688
|
+
if result == "block":
|
|
689
|
+
blocked = True
|
|
690
|
+
block_stage = stage_name
|
|
691
|
+
break
|
|
692
|
+
elif result == "warn":
|
|
693
|
+
warnings.append(stage_name)
|
|
694
|
+
|
|
695
|
+
# Extract metadata from stage results
|
|
696
|
+
if stage_name == "classify_signal":
|
|
697
|
+
category = details.get("category", "uncategorized")
|
|
698
|
+
elif stage_name == "gotcha_fit_check":
|
|
699
|
+
gotcha_layer = details.get("best_layer")
|
|
700
|
+
elif stage_name == "boundary_impact":
|
|
701
|
+
boundary_tier = details.get("tier", "GREEN")
|
|
702
|
+
|
|
703
|
+
# --- Stage 5 (needs DB for dedup) ---
|
|
704
|
+
if not blocked:
|
|
705
|
+
result, details = _stage_duplicate_license(signal, config, conn)
|
|
706
|
+
|
|
707
|
+
_log_triage_stage(conn, signal_id, 5, "duplicate_license_check", result, details)
|
|
708
|
+
|
|
709
|
+
stage_results.append({
|
|
710
|
+
"stage": 5,
|
|
711
|
+
"name": "duplicate_license_check",
|
|
712
|
+
"result": result,
|
|
713
|
+
"details": details,
|
|
714
|
+
})
|
|
715
|
+
|
|
716
|
+
if result == "block":
|
|
717
|
+
blocked = True
|
|
718
|
+
block_stage = "duplicate_license_check"
|
|
719
|
+
elif result == "warn":
|
|
720
|
+
warnings.append("duplicate_license_check")
|
|
721
|
+
|
|
722
|
+
# --- Determine final triage outcome ---
|
|
723
|
+
score = signal.get("community_score", 0.0) or 0.0
|
|
724
|
+
|
|
725
|
+
# Apply priority boost from category classification
|
|
726
|
+
if category and not blocked:
|
|
727
|
+
cat_config = config.get("signal_categories", {}).get(category, {})
|
|
728
|
+
priority_boost = cat_config.get("priority_boost", 1.0)
|
|
729
|
+
score = min(score * priority_boost, 1.0)
|
|
730
|
+
|
|
731
|
+
if blocked:
|
|
732
|
+
triage_result = "blocked"
|
|
733
|
+
elif score >= auto_queue_threshold:
|
|
734
|
+
triage_result = "approved"
|
|
735
|
+
elif score >= suggest_threshold:
|
|
736
|
+
triage_result = "suggested"
|
|
737
|
+
else:
|
|
738
|
+
triage_result = "logged"
|
|
739
|
+
|
|
740
|
+
# --- Update signal record ---
|
|
741
|
+
conn.execute(
|
|
742
|
+
"""UPDATE innovation_signals
|
|
743
|
+
SET status = 'triaged',
|
|
744
|
+
triage_result = ?,
|
|
745
|
+
gotcha_layer = ?,
|
|
746
|
+
boundary_tier = ?,
|
|
747
|
+
category = ?
|
|
748
|
+
WHERE id = ?""",
|
|
749
|
+
(triage_result, gotcha_layer, boundary_tier, category, signal_id),
|
|
750
|
+
)
|
|
751
|
+
conn.commit()
|
|
752
|
+
|
|
753
|
+
outcome = {
|
|
754
|
+
"signal_id": signal_id,
|
|
755
|
+
"title": signal.get("title", ""),
|
|
756
|
+
"triage_result": triage_result,
|
|
757
|
+
"score": round(score, 4),
|
|
758
|
+
"category": category,
|
|
759
|
+
"gotcha_layer": gotcha_layer,
|
|
760
|
+
"boundary_tier": boundary_tier,
|
|
761
|
+
"blocked": blocked,
|
|
762
|
+
"block_stage": block_stage,
|
|
763
|
+
"warnings": warnings,
|
|
764
|
+
"stages": stage_results,
|
|
765
|
+
"thresholds": {
|
|
766
|
+
"auto_queue": auto_queue_threshold,
|
|
767
|
+
"suggest": suggest_threshold,
|
|
768
|
+
},
|
|
769
|
+
"triaged_at": _now(),
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
_audit(
|
|
773
|
+
"innovation.triage",
|
|
774
|
+
"triage-engine",
|
|
775
|
+
f"Triaged signal {signal_id}: {triage_result}",
|
|
776
|
+
{
|
|
777
|
+
"signal_id": signal_id,
|
|
778
|
+
"result": triage_result,
|
|
779
|
+
"blocked": blocked,
|
|
780
|
+
"block_stage": block_stage,
|
|
781
|
+
"category": category,
|
|
782
|
+
"boundary_tier": boundary_tier,
|
|
783
|
+
},
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
return outcome
|
|
787
|
+
|
|
788
|
+
finally:
|
|
789
|
+
conn.close()
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def triage_all_scored(db_path=None):
|
|
793
|
+
"""Triage all signals currently in 'scored' status.
|
|
794
|
+
|
|
795
|
+
Iterates over every signal with status='scored' and runs the full
|
|
796
|
+
5-stage pipeline. Continues on individual signal errors.
|
|
797
|
+
|
|
798
|
+
Args:
|
|
799
|
+
db_path: Optional database path override.
|
|
800
|
+
|
|
801
|
+
Returns:
|
|
802
|
+
Dict with counts per triage outcome and list of individual results.
|
|
803
|
+
"""
|
|
804
|
+
conn = _get_db(db_path)
|
|
805
|
+
try:
|
|
806
|
+
_ensure_triage_tables(conn)
|
|
807
|
+
|
|
808
|
+
signals = conn.execute(
|
|
809
|
+
"""SELECT id FROM innovation_signals
|
|
810
|
+
WHERE status = 'scored'
|
|
811
|
+
ORDER BY community_score DESC""",
|
|
812
|
+
).fetchall()
|
|
813
|
+
finally:
|
|
814
|
+
conn.close()
|
|
815
|
+
|
|
816
|
+
signal_ids = [row["id"] for row in signals]
|
|
817
|
+
|
|
818
|
+
results = []
|
|
819
|
+
counts = {"approved": 0, "suggested": 0, "blocked": 0, "logged": 0, "error": 0}
|
|
820
|
+
|
|
821
|
+
for sid in signal_ids:
|
|
822
|
+
try:
|
|
823
|
+
outcome = triage_signal(sid, db_path=db_path)
|
|
824
|
+
if "error" in outcome:
|
|
825
|
+
counts["error"] += 1
|
|
826
|
+
results.append({"signal_id": sid, "error": outcome["error"]})
|
|
827
|
+
else:
|
|
828
|
+
triage_result = outcome.get("triage_result", "logged")
|
|
829
|
+
counts[triage_result] = counts.get(triage_result, 0) + 1
|
|
830
|
+
results.append({
|
|
831
|
+
"signal_id": sid,
|
|
832
|
+
"title": outcome.get("title", ""),
|
|
833
|
+
"triage_result": triage_result,
|
|
834
|
+
"score": outcome.get("score", 0.0),
|
|
835
|
+
"category": outcome.get("category"),
|
|
836
|
+
"gotcha_layer": outcome.get("gotcha_layer"),
|
|
837
|
+
"boundary_tier": outcome.get("boundary_tier"),
|
|
838
|
+
"blocked": outcome.get("blocked", False),
|
|
839
|
+
"block_stage": outcome.get("block_stage"),
|
|
840
|
+
})
|
|
841
|
+
except Exception as e:
|
|
842
|
+
counts["error"] += 1
|
|
843
|
+
results.append({"signal_id": sid, "error": str(e)})
|
|
844
|
+
|
|
845
|
+
_audit(
|
|
846
|
+
"innovation.triage_batch",
|
|
847
|
+
"triage-engine",
|
|
848
|
+
f"Batch triaged {len(signal_ids)} signals",
|
|
849
|
+
counts,
|
|
850
|
+
)
|
|
851
|
+
|
|
852
|
+
return {
|
|
853
|
+
"total_processed": len(signal_ids),
|
|
854
|
+
"counts": counts,
|
|
855
|
+
"results": results,
|
|
856
|
+
"triaged_at": _now(),
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
def get_triage_summary(db_path=None):
|
|
861
|
+
"""Summarize triage outcomes across all triaged signals.
|
|
862
|
+
|
|
863
|
+
Provides aggregate counts by triage result, category, GOTCHA layer,
|
|
864
|
+
boundary tier, and recent triage log entries.
|
|
865
|
+
|
|
866
|
+
Args:
|
|
867
|
+
db_path: Optional database path override.
|
|
868
|
+
|
|
869
|
+
Returns:
|
|
870
|
+
Dict with summary statistics and recent triage activity.
|
|
871
|
+
"""
|
|
872
|
+
conn = _get_db(db_path)
|
|
873
|
+
try:
|
|
874
|
+
_ensure_triage_tables(conn)
|
|
875
|
+
|
|
876
|
+
# Count by triage result
|
|
877
|
+
by_result = {}
|
|
878
|
+
rows = conn.execute(
|
|
879
|
+
"""SELECT triage_result, COUNT(*) as cnt
|
|
880
|
+
FROM innovation_signals
|
|
881
|
+
WHERE triage_result IS NOT NULL
|
|
882
|
+
GROUP BY triage_result"""
|
|
883
|
+
).fetchall()
|
|
884
|
+
for row in rows:
|
|
885
|
+
by_result[row["triage_result"] or "none"] = row["cnt"]
|
|
886
|
+
|
|
887
|
+
# Count by category
|
|
888
|
+
by_category = {}
|
|
889
|
+
rows = conn.execute(
|
|
890
|
+
"""SELECT category, COUNT(*) as cnt
|
|
891
|
+
FROM innovation_signals
|
|
892
|
+
WHERE status = 'triaged'
|
|
893
|
+
GROUP BY category"""
|
|
894
|
+
).fetchall()
|
|
895
|
+
for row in rows:
|
|
896
|
+
by_category[row["category"] or "uncategorized"] = row["cnt"]
|
|
897
|
+
|
|
898
|
+
# Count by GOTCHA layer
|
|
899
|
+
by_gotcha = {}
|
|
900
|
+
rows = conn.execute(
|
|
901
|
+
"""SELECT gotcha_layer, COUNT(*) as cnt
|
|
902
|
+
FROM innovation_signals
|
|
903
|
+
WHERE gotcha_layer IS NOT NULL
|
|
904
|
+
GROUP BY gotcha_layer"""
|
|
905
|
+
).fetchall()
|
|
906
|
+
for row in rows:
|
|
907
|
+
by_gotcha[row["gotcha_layer"]] = row["cnt"]
|
|
908
|
+
|
|
909
|
+
# Count by boundary tier
|
|
910
|
+
by_boundary = {}
|
|
911
|
+
rows = conn.execute(
|
|
912
|
+
"""SELECT boundary_tier, COUNT(*) as cnt
|
|
913
|
+
FROM innovation_signals
|
|
914
|
+
WHERE boundary_tier IS NOT NULL
|
|
915
|
+
GROUP BY boundary_tier"""
|
|
916
|
+
).fetchall()
|
|
917
|
+
for row in rows:
|
|
918
|
+
by_boundary[row["boundary_tier"]] = row["cnt"]
|
|
919
|
+
|
|
920
|
+
# Pending triage (scored but not yet triaged)
|
|
921
|
+
pending = conn.execute(
|
|
922
|
+
"SELECT COUNT(*) as cnt FROM innovation_signals WHERE status = 'scored'"
|
|
923
|
+
).fetchone()["cnt"]
|
|
924
|
+
|
|
925
|
+
# Recent triage log entries (last 20 blocked)
|
|
926
|
+
recent_blocks = []
|
|
927
|
+
rows = conn.execute(
|
|
928
|
+
"""SELECT tl.signal_id, tl.stage_name, tl.details, tl.triaged_at,
|
|
929
|
+
s.title
|
|
930
|
+
FROM innovation_triage_log tl
|
|
931
|
+
LEFT JOIN innovation_signals s ON s.id = tl.signal_id
|
|
932
|
+
WHERE tl.result = 'block'
|
|
933
|
+
ORDER BY tl.triaged_at DESC
|
|
934
|
+
LIMIT 20"""
|
|
935
|
+
).fetchall()
|
|
936
|
+
for row in rows:
|
|
937
|
+
details = row["details"]
|
|
938
|
+
try:
|
|
939
|
+
details = json.loads(details) if details else {}
|
|
940
|
+
except (json.JSONDecodeError, TypeError):
|
|
941
|
+
details = {"raw": details}
|
|
942
|
+
recent_blocks.append({
|
|
943
|
+
"signal_id": row["signal_id"],
|
|
944
|
+
"title": row["title"],
|
|
945
|
+
"blocked_at_stage": row["stage_name"],
|
|
946
|
+
"details": details,
|
|
947
|
+
"triaged_at": row["triaged_at"],
|
|
948
|
+
})
|
|
949
|
+
|
|
950
|
+
# Total triage log entries
|
|
951
|
+
total_log_entries = conn.execute(
|
|
952
|
+
"SELECT COUNT(*) as cnt FROM innovation_triage_log"
|
|
953
|
+
).fetchone()["cnt"]
|
|
954
|
+
|
|
955
|
+
# Stage pass/block/warn distribution
|
|
956
|
+
stage_stats = {}
|
|
957
|
+
rows = conn.execute(
|
|
958
|
+
"""SELECT stage_name, result, COUNT(*) as cnt
|
|
959
|
+
FROM innovation_triage_log
|
|
960
|
+
GROUP BY stage_name, result"""
|
|
961
|
+
).fetchall()
|
|
962
|
+
for row in rows:
|
|
963
|
+
stage = row["stage_name"]
|
|
964
|
+
if stage not in stage_stats:
|
|
965
|
+
stage_stats[stage] = {}
|
|
966
|
+
stage_stats[stage][row["result"]] = row["cnt"]
|
|
967
|
+
|
|
968
|
+
return {
|
|
969
|
+
"by_triage_result": by_result,
|
|
970
|
+
"by_category": by_category,
|
|
971
|
+
"by_gotcha_layer": by_gotcha,
|
|
972
|
+
"by_boundary_tier": by_boundary,
|
|
973
|
+
"pending_triage": pending,
|
|
974
|
+
"total_triage_log_entries": total_log_entries,
|
|
975
|
+
"stage_stats": stage_stats,
|
|
976
|
+
"recent_blocks": recent_blocks,
|
|
977
|
+
"generated_at": _now(),
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
finally:
|
|
981
|
+
conn.close()
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
# =========================================================================
|
|
985
|
+
# CLI
|
|
986
|
+
# =========================================================================
|
|
987
|
+
def main():
|
|
988
|
+
parser = argparse.ArgumentParser(
|
|
989
|
+
description="ICDEV Compliance-First Triage Pipeline — 5-stage safety gate for innovation signals"
|
|
990
|
+
)
|
|
991
|
+
parser.add_argument("--json", action="store_true", help="JSON output")
|
|
992
|
+
parser.add_argument(
|
|
993
|
+
"--db-path", type=Path, default=None, help="Database path override"
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
group = parser.add_mutually_exclusive_group(required=True)
|
|
997
|
+
group.add_argument(
|
|
998
|
+
"--triage",
|
|
999
|
+
action="store_true",
|
|
1000
|
+
help="Triage a single signal (requires --signal-id)",
|
|
1001
|
+
)
|
|
1002
|
+
group.add_argument(
|
|
1003
|
+
"--triage-all",
|
|
1004
|
+
action="store_true",
|
|
1005
|
+
help="Triage all signals with status='scored'",
|
|
1006
|
+
)
|
|
1007
|
+
group.add_argument(
|
|
1008
|
+
"--summary",
|
|
1009
|
+
action="store_true",
|
|
1010
|
+
help="Show triage outcome summary",
|
|
1011
|
+
)
|
|
1012
|
+
|
|
1013
|
+
parser.add_argument(
|
|
1014
|
+
"--signal-id", type=str, help="Signal ID to triage (with --triage)"
|
|
1015
|
+
)
|
|
1016
|
+
|
|
1017
|
+
args = parser.parse_args()
|
|
1018
|
+
|
|
1019
|
+
try:
|
|
1020
|
+
if args.triage:
|
|
1021
|
+
if not args.signal_id:
|
|
1022
|
+
parser.error("--triage requires --signal-id")
|
|
1023
|
+
result = triage_signal(args.signal_id, db_path=args.db_path)
|
|
1024
|
+
elif args.triage_all:
|
|
1025
|
+
result = triage_all_scored(db_path=args.db_path)
|
|
1026
|
+
elif args.summary:
|
|
1027
|
+
result = get_triage_summary(db_path=args.db_path)
|
|
1028
|
+
else:
|
|
1029
|
+
result = {"error": "No action specified"}
|
|
1030
|
+
|
|
1031
|
+
if args.json:
|
|
1032
|
+
print(json.dumps(result, indent=2, default=str))
|
|
1033
|
+
else:
|
|
1034
|
+
_print_human(args, result)
|
|
1035
|
+
|
|
1036
|
+
except FileNotFoundError as e:
|
|
1037
|
+
error = {"error": str(e)}
|
|
1038
|
+
if args.json:
|
|
1039
|
+
print(json.dumps(error, indent=2))
|
|
1040
|
+
else:
|
|
1041
|
+
print(f"ERROR: {e}", file=sys.stderr)
|
|
1042
|
+
sys.exit(1)
|
|
1043
|
+
except Exception as e:
|
|
1044
|
+
error = {"error": str(e)}
|
|
1045
|
+
if args.json:
|
|
1046
|
+
print(json.dumps(error, indent=2))
|
|
1047
|
+
else:
|
|
1048
|
+
print(f"ERROR: {e}", file=sys.stderr)
|
|
1049
|
+
sys.exit(1)
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
def _print_human(args, result):
|
|
1053
|
+
"""Print human-readable output for CLI."""
|
|
1054
|
+
if "error" in result:
|
|
1055
|
+
print(f"ERROR: {result['error']}")
|
|
1056
|
+
return
|
|
1057
|
+
|
|
1058
|
+
if args.triage:
|
|
1059
|
+
sig = result
|
|
1060
|
+
status_icon = {
|
|
1061
|
+
"approved": "[APPROVED]",
|
|
1062
|
+
"suggested": "[SUGGESTED]",
|
|
1063
|
+
"blocked": "[BLOCKED]",
|
|
1064
|
+
"logged": "[LOGGED]",
|
|
1065
|
+
}.get(sig.get("triage_result", ""), "[?]")
|
|
1066
|
+
|
|
1067
|
+
print(f"Triage Result: {status_icon} {sig.get('triage_result', 'unknown')}")
|
|
1068
|
+
print(f"Signal: {sig.get('signal_id', '')} — {sig.get('title', '')}")
|
|
1069
|
+
print(f"Score: {sig.get('score', 0.0):.4f}")
|
|
1070
|
+
print(f"Category: {sig.get('category', 'N/A')}")
|
|
1071
|
+
print(f"GOTCHA Layer: {sig.get('gotcha_layer', 'N/A')}")
|
|
1072
|
+
print(f"Boundary Tier: {sig.get('boundary_tier', 'N/A')}")
|
|
1073
|
+
|
|
1074
|
+
if sig.get("blocked"):
|
|
1075
|
+
print(f"Blocked at: Stage '{sig.get('block_stage', '?')}'")
|
|
1076
|
+
|
|
1077
|
+
if sig.get("warnings"):
|
|
1078
|
+
print(f"Warnings: {', '.join(sig['warnings'])}")
|
|
1079
|
+
|
|
1080
|
+
print("\nStage Details:")
|
|
1081
|
+
for stage in sig.get("stages", []):
|
|
1082
|
+
icon = {"pass": "OK", "block": "BLOCK", "warn": "WARN"}.get(
|
|
1083
|
+
stage["result"], "?"
|
|
1084
|
+
)
|
|
1085
|
+
print(f" {stage['stage']}. {stage['name']}: [{icon}]")
|
|
1086
|
+
details = stage.get("details", {})
|
|
1087
|
+
if isinstance(details, dict):
|
|
1088
|
+
reason = details.get("reason", "")
|
|
1089
|
+
if reason:
|
|
1090
|
+
print(f" Reason: {reason}")
|
|
1091
|
+
|
|
1092
|
+
elif args.triage_all:
|
|
1093
|
+
counts = result.get("counts", {})
|
|
1094
|
+
total = result.get("total_processed", 0)
|
|
1095
|
+
print(f"Batch Triage Complete — {total} signals processed")
|
|
1096
|
+
print(f" Approved: {counts.get('approved', 0)}")
|
|
1097
|
+
print(f" Suggested: {counts.get('suggested', 0)}")
|
|
1098
|
+
print(f" Blocked: {counts.get('blocked', 0)}")
|
|
1099
|
+
print(f" Logged: {counts.get('logged', 0)}")
|
|
1100
|
+
print(f" Errors: {counts.get('error', 0)}")
|
|
1101
|
+
|
|
1102
|
+
# Show blocked signals
|
|
1103
|
+
blocked = [r for r in result.get("results", []) if r.get("blocked")]
|
|
1104
|
+
if blocked:
|
|
1105
|
+
print(f"\nBlocked Signals ({len(blocked)}):")
|
|
1106
|
+
for b in blocked[:10]:
|
|
1107
|
+
print(f" {b['signal_id']}: {b.get('title', '')[:60]} — blocked at {b.get('block_stage', '?')}")
|
|
1108
|
+
|
|
1109
|
+
elif args.summary:
|
|
1110
|
+
print("Triage Summary")
|
|
1111
|
+
print("=" * 50)
|
|
1112
|
+
|
|
1113
|
+
by_result = result.get("by_triage_result", {})
|
|
1114
|
+
print("\nBy Outcome:")
|
|
1115
|
+
for outcome, count in sorted(by_result.items()):
|
|
1116
|
+
print(f" {outcome:12s}: {count}")
|
|
1117
|
+
|
|
1118
|
+
by_cat = result.get("by_category", {})
|
|
1119
|
+
if by_cat:
|
|
1120
|
+
print("\nBy Category:")
|
|
1121
|
+
for cat, count in sorted(by_cat.items(), key=lambda x: -x[1]):
|
|
1122
|
+
print(f" {cat:25s}: {count}")
|
|
1123
|
+
|
|
1124
|
+
by_gotcha = result.get("by_gotcha_layer", {})
|
|
1125
|
+
if by_gotcha:
|
|
1126
|
+
print("\nBy GOTCHA Layer:")
|
|
1127
|
+
for layer, count in sorted(by_gotcha.items()):
|
|
1128
|
+
print(f" {layer:12s}: {count}")
|
|
1129
|
+
|
|
1130
|
+
by_boundary = result.get("by_boundary_tier", {})
|
|
1131
|
+
if by_boundary:
|
|
1132
|
+
print("\nBy Boundary Tier:")
|
|
1133
|
+
for tier, count in sorted(by_boundary.items()):
|
|
1134
|
+
print(f" {tier:8s}: {count}")
|
|
1135
|
+
|
|
1136
|
+
pending = result.get("pending_triage", 0)
|
|
1137
|
+
print(f"\nPending Triage: {pending}")
|
|
1138
|
+
print(f"Total Log Entries: {result.get('total_triage_log_entries', 0)}")
|
|
1139
|
+
|
|
1140
|
+
blocks = result.get("recent_blocks", [])
|
|
1141
|
+
if blocks:
|
|
1142
|
+
print(f"\nRecent Blocks ({len(blocks)}):")
|
|
1143
|
+
for b in blocks[:5]:
|
|
1144
|
+
title = (b.get("title") or "untitled")[:50]
|
|
1145
|
+
print(f" {b['signal_id']}: {title} — blocked at {b['blocked_at_stage']}")
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
if __name__ == "__main__":
|
|
1149
|
+
main()
|