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,1171 @@
|
|
|
1
|
+
# [TEMPLATE: CUI // SP-CTI]
|
|
2
|
+
"""
|
|
3
|
+
Flask Blueprint for requirements intake chat API.
|
|
4
|
+
|
|
5
|
+
Provides endpoints to create intake sessions, process conversational turns,
|
|
6
|
+
upload documents, check readiness scores, and export requirements.
|
|
7
|
+
|
|
8
|
+
Wraps existing RICOAS backend tools:
|
|
9
|
+
- tools.requirements.intake_engine
|
|
10
|
+
- tools.requirements.document_extractor
|
|
11
|
+
- tools.requirements.readiness_scorer
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import sqlite3
|
|
15
|
+
import sys
|
|
16
|
+
import threading
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from flask import Blueprint, jsonify, request
|
|
21
|
+
from werkzeug.utils import secure_filename
|
|
22
|
+
from icdev._paths import get_project_root
|
|
23
|
+
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
# Path setup
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
BASE_DIR = get_project_root()
|
|
29
|
+
if str(BASE_DIR) not in sys.path:
|
|
30
|
+
sys.path.insert(0, str(BASE_DIR))
|
|
31
|
+
|
|
32
|
+
DB_PATH = BASE_DIR / "data" / "icdev.db"
|
|
33
|
+
UPLOAD_DIR = BASE_DIR / ".tmp" / "uploads"
|
|
34
|
+
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
# Backend imports (graceful)
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
from icdev.tools.requirements.intake_engine import (
|
|
41
|
+
create_session,
|
|
42
|
+
process_turn,
|
|
43
|
+
export_requirements,
|
|
44
|
+
)
|
|
45
|
+
_HAS_INTAKE = True
|
|
46
|
+
except ImportError:
|
|
47
|
+
_HAS_INTAKE = False
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
from icdev.tools.requirements.document_extractor import (
|
|
51
|
+
upload_document,
|
|
52
|
+
extract_requirements as extract_doc_requirements,
|
|
53
|
+
)
|
|
54
|
+
_HAS_EXTRACTOR = True
|
|
55
|
+
except ImportError:
|
|
56
|
+
_HAS_EXTRACTOR = False
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
from icdev.tools.requirements.readiness_scorer import score_readiness
|
|
60
|
+
_HAS_SCORER = True
|
|
61
|
+
except ImportError:
|
|
62
|
+
_HAS_SCORER = False
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
from icdev.tools.simulation.coa_generator import (
|
|
66
|
+
generate_3_coas as _generate_3_coas,
|
|
67
|
+
list_coas as _list_coas,
|
|
68
|
+
select_coa as _select_coa,
|
|
69
|
+
)
|
|
70
|
+
_HAS_COA = True
|
|
71
|
+
except ImportError:
|
|
72
|
+
_HAS_COA = False
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
from icdev.tools.requirements.prd_generator import generate_prd as _generate_prd
|
|
76
|
+
_HAS_PRD = True
|
|
77
|
+
except ImportError:
|
|
78
|
+
_HAS_PRD = False
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
from icdev.tools.requirements.prd_validator import validate_prd as _validate_prd
|
|
82
|
+
_HAS_PRD_VALIDATOR = True
|
|
83
|
+
except ImportError:
|
|
84
|
+
_HAS_PRD_VALIDATOR = False
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
from icdev.tools.requirements.complexity_scorer import score_complexity as _score_complexity
|
|
88
|
+
_HAS_COMPLEXITY = True
|
|
89
|
+
except ImportError:
|
|
90
|
+
_HAS_COMPLEXITY = False
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
from icdev.tools.requirements.elicitation_techniques import (
|
|
94
|
+
list_techniques as _list_techniques,
|
|
95
|
+
get_technique as _get_technique,
|
|
96
|
+
activate_technique as _activate_technique,
|
|
97
|
+
deactivate_technique as _deactivate_technique,
|
|
98
|
+
)
|
|
99
|
+
_HAS_ELICITATION = True
|
|
100
|
+
except ImportError:
|
|
101
|
+
_HAS_ELICITATION = False
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
# Blueprint
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
intake_api = Blueprint("intake_api", __name__)
|
|
108
|
+
|
|
109
|
+
ALLOWED_EXTENSIONS = {
|
|
110
|
+
".txt", ".md", ".pdf", ".docx",
|
|
111
|
+
".png", ".jpg", ".jpeg", ".gif", ".webp", ".tiff", ".bmp",
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _get_db():
|
|
116
|
+
conn = sqlite3.connect(str(DB_PATH))
|
|
117
|
+
conn.row_factory = sqlite3.Row
|
|
118
|
+
return conn
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# ---------------------------------------------------------------------------
|
|
122
|
+
# Endpoints
|
|
123
|
+
# ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
@intake_api.route("/api/intake/session", methods=["POST"])
|
|
126
|
+
def create_intake_session():
|
|
127
|
+
"""Create a new intake session from wizard context."""
|
|
128
|
+
data = request.get_json(silent=True) or {}
|
|
129
|
+
goal = data.get("goal", "build")
|
|
130
|
+
role = data.get("role", "developer")
|
|
131
|
+
classification = data.get("classification", "il4")
|
|
132
|
+
customer_name = data.get("customer_name", "Dashboard User")
|
|
133
|
+
customer_org = data.get("customer_org", "")
|
|
134
|
+
frameworks = data.get("frameworks", [])
|
|
135
|
+
custom_role_name = data.get("custom_role_name", "")
|
|
136
|
+
custom_role_description = data.get("custom_role_description", "")
|
|
137
|
+
|
|
138
|
+
# Map classification to impact level
|
|
139
|
+
il_map = {"il2": "IL2", "il4": "IL4", "il5": "IL5", "il6": "IL6"}
|
|
140
|
+
impact_level = il_map.get(classification, "IL4")
|
|
141
|
+
|
|
142
|
+
if not _HAS_INTAKE:
|
|
143
|
+
return jsonify({"error": "Intake engine not available"}), 503
|
|
144
|
+
|
|
145
|
+
# Pass empty project_id so intake_engine skips project validation.
|
|
146
|
+
# A real project is created later during plan generation.
|
|
147
|
+
project_id = data.get("project_id", "")
|
|
148
|
+
|
|
149
|
+
# For custom roles, use the custom name as the role key
|
|
150
|
+
effective_role = custom_role_name if custom_role_name else role
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
result = create_session(
|
|
154
|
+
project_id=project_id,
|
|
155
|
+
customer_name=customer_name,
|
|
156
|
+
customer_org=customer_org,
|
|
157
|
+
impact_level=impact_level,
|
|
158
|
+
classification=classification.upper(),
|
|
159
|
+
db_path=DB_PATH,
|
|
160
|
+
role=effective_role,
|
|
161
|
+
goal=goal,
|
|
162
|
+
selected_frameworks=frameworks,
|
|
163
|
+
custom_role_description=custom_role_description,
|
|
164
|
+
)
|
|
165
|
+
result["wizard_context"] = {
|
|
166
|
+
"goal": goal, "role": role, "classification": classification,
|
|
167
|
+
"frameworks": frameworks, "custom_role_name": custom_role_name,
|
|
168
|
+
}
|
|
169
|
+
return jsonify(result)
|
|
170
|
+
except Exception as exc:
|
|
171
|
+
return jsonify({"error": str(exc)}), 500
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@intake_api.route("/api/intake/turn", methods=["POST"])
|
|
175
|
+
def process_intake_turn():
|
|
176
|
+
"""Process a customer message turn."""
|
|
177
|
+
data = request.get_json(silent=True) or {}
|
|
178
|
+
session_id = data.get("session_id")
|
|
179
|
+
message = data.get("message", "").strip()
|
|
180
|
+
|
|
181
|
+
if not session_id or not message:
|
|
182
|
+
return jsonify({"error": "session_id and message are required"}), 400
|
|
183
|
+
if not _HAS_INTAKE:
|
|
184
|
+
return jsonify({"error": "Intake engine not available"}), 503
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
result = process_turn(session_id, message, db_path=DB_PATH)
|
|
188
|
+
return jsonify(result)
|
|
189
|
+
except ValueError as exc:
|
|
190
|
+
return jsonify({"error": str(exc)}), 404
|
|
191
|
+
except Exception as exc:
|
|
192
|
+
return jsonify({"error": str(exc)}), 500
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@intake_api.route("/api/intake/upload", methods=["POST"])
|
|
196
|
+
def upload_intake_file():
|
|
197
|
+
"""Upload a document or image for requirement extraction."""
|
|
198
|
+
session_id = request.form.get("session_id")
|
|
199
|
+
if not session_id:
|
|
200
|
+
return jsonify({"error": "session_id is required"}), 400
|
|
201
|
+
if "file" not in request.files:
|
|
202
|
+
return jsonify({"error": "No file provided"}), 400
|
|
203
|
+
if not _HAS_EXTRACTOR:
|
|
204
|
+
return jsonify({"error": "Document extractor not available"}), 503
|
|
205
|
+
|
|
206
|
+
f = request.files["file"]
|
|
207
|
+
if not f.filename:
|
|
208
|
+
return jsonify({"error": "Empty filename"}), 400
|
|
209
|
+
|
|
210
|
+
ext = Path(f.filename).suffix.lower()
|
|
211
|
+
if ext not in ALLOWED_EXTENSIONS:
|
|
212
|
+
return jsonify({"error": f"File type {ext} not supported"}), 400
|
|
213
|
+
|
|
214
|
+
# Save to upload directory
|
|
215
|
+
session_dir = UPLOAD_DIR / session_id
|
|
216
|
+
session_dir.mkdir(parents=True, exist_ok=True)
|
|
217
|
+
safe_name = secure_filename(f.filename)
|
|
218
|
+
file_path = session_dir / safe_name
|
|
219
|
+
f.save(str(file_path))
|
|
220
|
+
|
|
221
|
+
# Determine document type
|
|
222
|
+
image_exts = {".png", ".jpg", ".jpeg", ".gif", ".webp", ".tiff", ".bmp"}
|
|
223
|
+
doc_type = "other" if ext in image_exts else "sow"
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
result = upload_document(
|
|
227
|
+
session_id=session_id,
|
|
228
|
+
file_path=str(file_path),
|
|
229
|
+
document_type=doc_type,
|
|
230
|
+
db_path=DB_PATH,
|
|
231
|
+
)
|
|
232
|
+
# Auto-extract requirements
|
|
233
|
+
doc_id = result.get("document_id")
|
|
234
|
+
extracted = []
|
|
235
|
+
if doc_id:
|
|
236
|
+
try:
|
|
237
|
+
extracted = extract_doc_requirements(doc_id, db_path=DB_PATH)
|
|
238
|
+
except Exception:
|
|
239
|
+
pass
|
|
240
|
+
result["requirements_extracted"] = len(extracted) if extracted else 0
|
|
241
|
+
return jsonify(result)
|
|
242
|
+
except Exception as exc:
|
|
243
|
+
return jsonify({"error": str(exc)}), 500
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@intake_api.route("/api/intake/session/<session_id>", methods=["GET"])
|
|
247
|
+
def get_intake_session(session_id):
|
|
248
|
+
"""Get session info and conversation history."""
|
|
249
|
+
conn = _get_db()
|
|
250
|
+
try:
|
|
251
|
+
session = conn.execute(
|
|
252
|
+
"SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
|
|
253
|
+
).fetchone()
|
|
254
|
+
if not session:
|
|
255
|
+
return jsonify({"error": "Session not found"}), 404
|
|
256
|
+
|
|
257
|
+
messages = conn.execute(
|
|
258
|
+
"SELECT turn_number, role, content, content_type, created_at "
|
|
259
|
+
"FROM intake_conversation WHERE session_id = ? ORDER BY turn_number",
|
|
260
|
+
(session_id,),
|
|
261
|
+
).fetchall()
|
|
262
|
+
|
|
263
|
+
req_count = conn.execute(
|
|
264
|
+
"SELECT COUNT(*) as cnt FROM intake_requirements WHERE session_id = ?",
|
|
265
|
+
(session_id,),
|
|
266
|
+
).fetchone()["cnt"]
|
|
267
|
+
|
|
268
|
+
doc_count = conn.execute(
|
|
269
|
+
"SELECT COUNT(*) as cnt FROM intake_documents WHERE session_id = ?",
|
|
270
|
+
(session_id,),
|
|
271
|
+
).fetchone()["cnt"]
|
|
272
|
+
|
|
273
|
+
return jsonify({
|
|
274
|
+
"session": dict(session),
|
|
275
|
+
"messages": [dict(m) for m in messages],
|
|
276
|
+
"requirements_count": req_count,
|
|
277
|
+
"documents_count": doc_count,
|
|
278
|
+
})
|
|
279
|
+
except Exception as exc:
|
|
280
|
+
return jsonify({"error": str(exc)}), 500
|
|
281
|
+
finally:
|
|
282
|
+
conn.close()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@intake_api.route("/api/intake/readiness/<session_id>", methods=["GET"])
|
|
286
|
+
def get_readiness(session_id):
|
|
287
|
+
"""Get readiness score for a session."""
|
|
288
|
+
if not _HAS_SCORER:
|
|
289
|
+
return jsonify({"error": "Readiness scorer not available"}), 503
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
result = score_readiness(session_id, db_path=DB_PATH)
|
|
293
|
+
return jsonify(result)
|
|
294
|
+
except Exception as exc:
|
|
295
|
+
return jsonify({"error": str(exc)}), 500
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@intake_api.route("/api/intake/complexity/<session_id>", methods=["GET"])
|
|
299
|
+
def get_complexity(session_id):
|
|
300
|
+
"""Get complexity score for a session (scale-adaptive planning)."""
|
|
301
|
+
if not _HAS_COMPLEXITY:
|
|
302
|
+
return jsonify({"error": "Complexity scorer not available"}), 503
|
|
303
|
+
|
|
304
|
+
try:
|
|
305
|
+
result = _score_complexity(session_id, db_path=DB_PATH)
|
|
306
|
+
return jsonify(result)
|
|
307
|
+
except Exception as exc:
|
|
308
|
+
return jsonify({"error": str(exc)}), 500
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
@intake_api.route("/api/intake/techniques", methods=["GET"])
|
|
312
|
+
def list_elicitation_techniques():
|
|
313
|
+
"""List available elicitation techniques."""
|
|
314
|
+
if not _HAS_ELICITATION:
|
|
315
|
+
return jsonify({"error": "Elicitation techniques not available"}), 503
|
|
316
|
+
category = request.args.get("category")
|
|
317
|
+
return jsonify({"techniques": _list_techniques(category=category)})
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
@intake_api.route("/api/intake/techniques/<session_id>/activate", methods=["POST"])
|
|
321
|
+
def activate_elicitation_technique(session_id):
|
|
322
|
+
"""Activate an elicitation technique for a session."""
|
|
323
|
+
if not _HAS_ELICITATION:
|
|
324
|
+
return jsonify({"error": "Elicitation techniques not available"}), 503
|
|
325
|
+
data = request.get_json(silent=True) or {}
|
|
326
|
+
technique_id = data.get("technique_id")
|
|
327
|
+
if not technique_id:
|
|
328
|
+
return jsonify({"error": "technique_id required"}), 400
|
|
329
|
+
result = _activate_technique(session_id, technique_id, db_path=DB_PATH)
|
|
330
|
+
if result.get("status") == "error":
|
|
331
|
+
return jsonify(result), 400
|
|
332
|
+
return jsonify(result)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@intake_api.route("/api/intake/techniques/<session_id>/deactivate", methods=["POST"])
|
|
336
|
+
def deactivate_elicitation_technique(session_id):
|
|
337
|
+
"""Deactivate the current elicitation technique for a session."""
|
|
338
|
+
if not _HAS_ELICITATION:
|
|
339
|
+
return jsonify({"error": "Elicitation techniques not available"}), 503
|
|
340
|
+
result = _deactivate_technique(session_id, db_path=DB_PATH)
|
|
341
|
+
if result.get("status") == "error":
|
|
342
|
+
return jsonify(result), 400
|
|
343
|
+
return jsonify(result)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@intake_api.route("/api/intake/export/<session_id>", methods=["POST"])
|
|
347
|
+
def export_intake_requirements(session_id):
|
|
348
|
+
"""Export all requirements from a session."""
|
|
349
|
+
if not _HAS_INTAKE:
|
|
350
|
+
return jsonify({"error": "Intake engine not available"}), 503
|
|
351
|
+
|
|
352
|
+
try:
|
|
353
|
+
result = export_requirements(session_id, db_path=DB_PATH)
|
|
354
|
+
return jsonify(result)
|
|
355
|
+
except Exception as exc:
|
|
356
|
+
return jsonify({"error": str(exc)}), 500
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@intake_api.route("/api/intake/prd/<session_id>", methods=["GET"])
|
|
360
|
+
def get_prd(session_id):
|
|
361
|
+
"""Generate a PRD (Product Requirements Document) for an intake session."""
|
|
362
|
+
if not _HAS_PRD:
|
|
363
|
+
return jsonify({"error": "PRD generator not available"}), 503
|
|
364
|
+
try:
|
|
365
|
+
result = _generate_prd(session_id, db_path=DB_PATH)
|
|
366
|
+
if result.get("status") != "ok":
|
|
367
|
+
return jsonify(result), 404
|
|
368
|
+
return jsonify(result)
|
|
369
|
+
except Exception as exc:
|
|
370
|
+
return jsonify({"error": str(exc)}), 500
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
@intake_api.route("/api/intake/prd/<session_id>/validate", methods=["GET"])
|
|
374
|
+
def validate_prd_endpoint(session_id):
|
|
375
|
+
"""Run 6-check PRD quality validation (density, leakage, SMART, etc.)."""
|
|
376
|
+
if not _HAS_PRD_VALIDATOR:
|
|
377
|
+
return jsonify({"error": "PRD validator not available"}), 503
|
|
378
|
+
try:
|
|
379
|
+
result = _validate_prd(session_id, db_path=DB_PATH)
|
|
380
|
+
if result.get("status") != "ok":
|
|
381
|
+
return jsonify(result), 404
|
|
382
|
+
return jsonify(result)
|
|
383
|
+
except Exception as exc:
|
|
384
|
+
return jsonify({"error": str(exc)}), 500
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
@intake_api.route("/api/intake/trigger-build/<session_id>", methods=["POST"])
|
|
388
|
+
def trigger_build(session_id):
|
|
389
|
+
"""Prepare build context from an intake session and return next-step info.
|
|
390
|
+
|
|
391
|
+
This endpoint gathers session context (role, goal, frameworks, requirements)
|
|
392
|
+
and returns the information a client needs to kick off the build pipeline.
|
|
393
|
+
"""
|
|
394
|
+
import json as _json
|
|
395
|
+
|
|
396
|
+
conn = _get_db()
|
|
397
|
+
try:
|
|
398
|
+
session = conn.execute(
|
|
399
|
+
"SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
|
|
400
|
+
).fetchone()
|
|
401
|
+
if not session:
|
|
402
|
+
return jsonify({"error": "Session not found"}), 404
|
|
403
|
+
|
|
404
|
+
session_data = dict(session)
|
|
405
|
+
context = {}
|
|
406
|
+
try:
|
|
407
|
+
context = _json.loads(session_data.get("context_summary") or "{}")
|
|
408
|
+
except (ValueError, TypeError):
|
|
409
|
+
pass
|
|
410
|
+
|
|
411
|
+
req_rows = conn.execute(
|
|
412
|
+
"SELECT id, raw_text, requirement_type, priority "
|
|
413
|
+
"FROM intake_requirements WHERE session_id = ? ORDER BY created_at",
|
|
414
|
+
(session_id,),
|
|
415
|
+
).fetchall()
|
|
416
|
+
requirements = [dict(r) for r in req_rows]
|
|
417
|
+
|
|
418
|
+
# Look up selected COA for this session
|
|
419
|
+
selected_coa = None
|
|
420
|
+
try:
|
|
421
|
+
coa_row = conn.execute(
|
|
422
|
+
"SELECT * FROM coa_definitions WHERE session_id = ? AND status = 'selected'",
|
|
423
|
+
(session_id,),
|
|
424
|
+
).fetchone()
|
|
425
|
+
if coa_row:
|
|
426
|
+
selected_coa = dict(coa_row)
|
|
427
|
+
for field in ("architecture_summary", "cost_estimate", "risk_profile",
|
|
428
|
+
"timeline", "compliance_impact", "supply_chain_impact"):
|
|
429
|
+
val = selected_coa.get(field)
|
|
430
|
+
if val and isinstance(val, str):
|
|
431
|
+
try:
|
|
432
|
+
selected_coa[field] = _json.loads(val)
|
|
433
|
+
except (ValueError, TypeError):
|
|
434
|
+
pass
|
|
435
|
+
except Exception:
|
|
436
|
+
pass # coa_definitions table may not exist in older DBs
|
|
437
|
+
|
|
438
|
+
coa_label = ""
|
|
439
|
+
if selected_coa:
|
|
440
|
+
coa_label = f", COA: {selected_coa.get('coa_name', selected_coa.get('coa_type', ''))}"
|
|
441
|
+
|
|
442
|
+
return jsonify({
|
|
443
|
+
"status": "ok",
|
|
444
|
+
"session_id": session_id,
|
|
445
|
+
"goal": context.get("goal", "build"),
|
|
446
|
+
"role": context.get("role", "developer"),
|
|
447
|
+
"frameworks": context.get("selected_frameworks", []),
|
|
448
|
+
"classification": session_data.get("classification", "CUI"),
|
|
449
|
+
"impact_level": session_data.get("impact_level", "IL4"),
|
|
450
|
+
"requirements_count": len(requirements),
|
|
451
|
+
"requirements": requirements,
|
|
452
|
+
"readiness_score": session_data.get("readiness_score", 0),
|
|
453
|
+
"selected_coa": selected_coa,
|
|
454
|
+
"next_steps": [
|
|
455
|
+
"Run /feature or /icdev-build to generate the application",
|
|
456
|
+
],
|
|
457
|
+
"message": (
|
|
458
|
+
f"Build context ready: {len(requirements)} requirements{coa_label}, "
|
|
459
|
+
f"classification {session_data.get('classification', 'CUI')}, "
|
|
460
|
+
f"impact level {session_data.get('impact_level', 'IL4')}."
|
|
461
|
+
),
|
|
462
|
+
})
|
|
463
|
+
except Exception as exc:
|
|
464
|
+
return jsonify({"error": str(exc)}), 500
|
|
465
|
+
finally:
|
|
466
|
+
conn.close()
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
# ---------------------------------------------------------------------------
|
|
470
|
+
# COA Endpoints
|
|
471
|
+
# ---------------------------------------------------------------------------
|
|
472
|
+
|
|
473
|
+
def _parse_coa_json_fields(coa):
|
|
474
|
+
"""Parse JSON string columns in a COA dict for JS consumption."""
|
|
475
|
+
import json as _j
|
|
476
|
+
for field in ("architecture_summary", "cost_estimate", "risk_profile",
|
|
477
|
+
"timeline", "compliance_impact", "supply_chain_impact"):
|
|
478
|
+
val = coa.get(field)
|
|
479
|
+
if val and isinstance(val, str):
|
|
480
|
+
try:
|
|
481
|
+
coa[field] = _j.loads(val)
|
|
482
|
+
except (ValueError, TypeError):
|
|
483
|
+
pass
|
|
484
|
+
return coa
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
@intake_api.route("/api/intake/coas/<session_id>", methods=["GET"])
|
|
488
|
+
def get_session_coas(session_id):
|
|
489
|
+
"""List COAs for an intake session."""
|
|
490
|
+
if _HAS_COA:
|
|
491
|
+
try:
|
|
492
|
+
result = _list_coas(session_id, db_path=DB_PATH)
|
|
493
|
+
for coa in result.get("coas", []):
|
|
494
|
+
_parse_coa_json_fields(coa)
|
|
495
|
+
return jsonify(result)
|
|
496
|
+
except Exception as exc:
|
|
497
|
+
return jsonify({"error": str(exc)}), 500
|
|
498
|
+
|
|
499
|
+
# Fallback: direct DB query
|
|
500
|
+
conn = _get_db()
|
|
501
|
+
try:
|
|
502
|
+
rows = conn.execute(
|
|
503
|
+
"""SELECT id, coa_type, coa_name, description, boundary_tier,
|
|
504
|
+
architecture_summary, cost_estimate, timeline,
|
|
505
|
+
risk_profile, compliance_impact, status,
|
|
506
|
+
selected_by, selected_at, selection_rationale
|
|
507
|
+
FROM coa_definitions
|
|
508
|
+
WHERE session_id = ?
|
|
509
|
+
ORDER BY CASE coa_type
|
|
510
|
+
WHEN 'speed' THEN 1 WHEN 'balanced' THEN 2
|
|
511
|
+
WHEN 'comprehensive' THEN 3 ELSE 4
|
|
512
|
+
END, created_at""",
|
|
513
|
+
(session_id,),
|
|
514
|
+
).fetchall()
|
|
515
|
+
coas = [_parse_coa_json_fields(dict(r)) for r in rows]
|
|
516
|
+
return jsonify({"session_id": session_id, "count": len(coas), "coas": coas})
|
|
517
|
+
except Exception as exc:
|
|
518
|
+
return jsonify({"error": str(exc)}), 500
|
|
519
|
+
finally:
|
|
520
|
+
conn.close()
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
@intake_api.route("/api/intake/coas/<session_id>/generate", methods=["POST"])
|
|
524
|
+
def generate_session_coas(session_id):
|
|
525
|
+
"""Generate 3 COAs (Speed/Balanced/Comprehensive) with simulation."""
|
|
526
|
+
if not _HAS_COA:
|
|
527
|
+
return jsonify({"error": "COA generator not available"}), 503
|
|
528
|
+
|
|
529
|
+
conn = _get_db()
|
|
530
|
+
try:
|
|
531
|
+
session = conn.execute(
|
|
532
|
+
"SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
|
|
533
|
+
).fetchone()
|
|
534
|
+
if not session:
|
|
535
|
+
return jsonify({"error": "Session not found"}), 404
|
|
536
|
+
|
|
537
|
+
session_data = dict(session)
|
|
538
|
+
project_id = session_data.get("project_id", "")
|
|
539
|
+
|
|
540
|
+
# Create temp project if none exists (same pattern as /icdev-simulate)
|
|
541
|
+
if not project_id:
|
|
542
|
+
import uuid
|
|
543
|
+
project_id = f"proj-sim-{uuid.uuid4().hex[:8]}"
|
|
544
|
+
conn.execute(
|
|
545
|
+
"""INSERT OR IGNORE INTO projects
|
|
546
|
+
(id, name, type, classification, status, directory_path, created_at)
|
|
547
|
+
VALUES (?, ?, 'webapp', 'CUI', 'active', '', datetime('now'))""",
|
|
548
|
+
(project_id, f"Simulation for {session_id}"),
|
|
549
|
+
)
|
|
550
|
+
conn.execute(
|
|
551
|
+
"UPDATE intake_sessions SET project_id = ? WHERE id = ?",
|
|
552
|
+
(project_id, session_id),
|
|
553
|
+
)
|
|
554
|
+
conn.commit()
|
|
555
|
+
except Exception as exc:
|
|
556
|
+
return jsonify({"error": str(exc)}), 500
|
|
557
|
+
finally:
|
|
558
|
+
conn.close()
|
|
559
|
+
|
|
560
|
+
try:
|
|
561
|
+
result = _generate_3_coas(session_id, project_id=project_id,
|
|
562
|
+
simulate=True, db_path=DB_PATH)
|
|
563
|
+
# Parse JSON fields for JS
|
|
564
|
+
for coa in result.get("coas", []):
|
|
565
|
+
_parse_coa_json_fields(coa)
|
|
566
|
+
return jsonify(result)
|
|
567
|
+
except Exception as exc:
|
|
568
|
+
return jsonify({"error": str(exc)}), 500
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
@intake_api.route("/api/intake/coas/<session_id>/select", methods=["POST"])
|
|
572
|
+
def select_session_coa(session_id):
|
|
573
|
+
"""Select a COA for an intake session."""
|
|
574
|
+
data = request.get_json(silent=True) or {}
|
|
575
|
+
coa_id = data.get("coa_id")
|
|
576
|
+
selected_by = data.get("selected_by", "Dashboard User")
|
|
577
|
+
rationale = data.get("rationale", "Selected via dashboard")
|
|
578
|
+
|
|
579
|
+
if not coa_id:
|
|
580
|
+
return jsonify({"error": "coa_id is required"}), 400
|
|
581
|
+
|
|
582
|
+
if _HAS_COA:
|
|
583
|
+
try:
|
|
584
|
+
result = _select_coa(
|
|
585
|
+
coa_id=coa_id,
|
|
586
|
+
selected_by=selected_by,
|
|
587
|
+
rationale=rationale,
|
|
588
|
+
db_path=DB_PATH,
|
|
589
|
+
)
|
|
590
|
+
return jsonify(result)
|
|
591
|
+
except ValueError as exc:
|
|
592
|
+
return jsonify({"error": str(exc)}), 404
|
|
593
|
+
except Exception as exc:
|
|
594
|
+
return jsonify({"error": str(exc)}), 500
|
|
595
|
+
|
|
596
|
+
# Fallback: direct DB update
|
|
597
|
+
from datetime import datetime
|
|
598
|
+
conn = _get_db()
|
|
599
|
+
try:
|
|
600
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
601
|
+
row = conn.execute(
|
|
602
|
+
"SELECT id, session_id, coa_type, coa_name FROM coa_definitions WHERE id = ?",
|
|
603
|
+
(coa_id,),
|
|
604
|
+
).fetchone()
|
|
605
|
+
if not row:
|
|
606
|
+
return jsonify({"error": "COA not found"}), 404
|
|
607
|
+
coa = dict(row)
|
|
608
|
+
if coa["session_id"] != session_id:
|
|
609
|
+
return jsonify({"error": "COA does not belong to this session"}), 400
|
|
610
|
+
|
|
611
|
+
conn.execute(
|
|
612
|
+
"UPDATE coa_definitions SET status='rejected', updated_at=? "
|
|
613
|
+
"WHERE session_id=? AND id!=? AND status NOT IN ('rejected','archived')",
|
|
614
|
+
(now, session_id, coa_id),
|
|
615
|
+
)
|
|
616
|
+
conn.execute(
|
|
617
|
+
"UPDATE coa_definitions SET status='selected', selected_by=?, "
|
|
618
|
+
"selected_at=?, selection_rationale=?, updated_at=? WHERE id=?",
|
|
619
|
+
(selected_by, now, rationale, now, coa_id),
|
|
620
|
+
)
|
|
621
|
+
conn.commit()
|
|
622
|
+
return jsonify({
|
|
623
|
+
"status": "ok",
|
|
624
|
+
"coa_id": coa_id,
|
|
625
|
+
"coa_type": coa["coa_type"],
|
|
626
|
+
"coa_name": coa["coa_name"],
|
|
627
|
+
"selection_status": "selected",
|
|
628
|
+
})
|
|
629
|
+
except Exception as exc:
|
|
630
|
+
return jsonify({"error": str(exc)}), 500
|
|
631
|
+
finally:
|
|
632
|
+
conn.close()
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
@intake_api.route("/api/intake/coas/<session_id>/unselect", methods=["POST"])
|
|
636
|
+
def unselect_session_coa(session_id):
|
|
637
|
+
"""Unselect the currently selected COA, resetting all back to presented."""
|
|
638
|
+
conn = _get_db()
|
|
639
|
+
try:
|
|
640
|
+
row = conn.execute(
|
|
641
|
+
"SELECT id, coa_name, coa_type FROM coa_definitions "
|
|
642
|
+
"WHERE session_id = ? AND status = 'selected'",
|
|
643
|
+
(session_id,),
|
|
644
|
+
).fetchone()
|
|
645
|
+
if not row:
|
|
646
|
+
return jsonify({"error": "No selected COA found for this session"}), 404
|
|
647
|
+
|
|
648
|
+
from datetime import datetime
|
|
649
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
650
|
+
conn.execute(
|
|
651
|
+
"UPDATE coa_definitions SET status='presented', selected_by=NULL, "
|
|
652
|
+
"selected_at=NULL, selection_rationale=NULL, updated_at=? "
|
|
653
|
+
"WHERE session_id=? AND status IN ('selected', 'rejected')",
|
|
654
|
+
(now, session_id),
|
|
655
|
+
)
|
|
656
|
+
conn.commit()
|
|
657
|
+
coa = dict(row)
|
|
658
|
+
return jsonify({
|
|
659
|
+
"status": "ok",
|
|
660
|
+
"unselected_coa_id": coa["id"],
|
|
661
|
+
"coa_name": coa["coa_name"] or coa["coa_type"],
|
|
662
|
+
"message": "COA unselected. All COAs reset to presented.",
|
|
663
|
+
})
|
|
664
|
+
except Exception as exc:
|
|
665
|
+
return jsonify({"error": str(exc)}), 500
|
|
666
|
+
finally:
|
|
667
|
+
conn.close()
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
# ---------------------------------------------------------------------------
|
|
671
|
+
# Build Pipeline — background job management
|
|
672
|
+
# ---------------------------------------------------------------------------
|
|
673
|
+
|
|
674
|
+
# Shared state uses builtins to guarantee a single dict instance even if this
|
|
675
|
+
# module is imported under two different sys.path entries by Flask/werkzeug.
|
|
676
|
+
import builtins as _builtins
|
|
677
|
+
if not hasattr(_builtins, '_ICDEV_BUILD_JOBS'):
|
|
678
|
+
_builtins._ICDEV_BUILD_JOBS = {}
|
|
679
|
+
_builtins._ICDEV_BUILD_LOCK = threading.Lock()
|
|
680
|
+
_BUILD_JOBS = _builtins._ICDEV_BUILD_JOBS
|
|
681
|
+
_BUILD_LOCK = _builtins._ICDEV_BUILD_LOCK
|
|
682
|
+
|
|
683
|
+
PIPELINE_PHASES = [
|
|
684
|
+
{"id": "validate", "name": "Validate Requirements"},
|
|
685
|
+
{"id": "architecture", "name": "Architecture Planning"},
|
|
686
|
+
{"id": "scaffold", "name": "Project Scaffolding"},
|
|
687
|
+
{"id": "security", "name": "Security Baseline"},
|
|
688
|
+
{"id": "complete", "name": "Build Ready"},
|
|
689
|
+
]
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def _run_build_pipeline(session_id):
|
|
693
|
+
"""Background worker that executes pipeline phases and updates status."""
|
|
694
|
+
import json as _json
|
|
695
|
+
import subprocess
|
|
696
|
+
import time
|
|
697
|
+
|
|
698
|
+
def _update_phase(phase_id, status, detail=""):
|
|
699
|
+
with _BUILD_LOCK:
|
|
700
|
+
job = _BUILD_JOBS.get(session_id)
|
|
701
|
+
if not job:
|
|
702
|
+
return
|
|
703
|
+
for phase in job["phases"]:
|
|
704
|
+
if phase["id"] == phase_id:
|
|
705
|
+
phase["status"] = status
|
|
706
|
+
phase["detail"] = detail
|
|
707
|
+
if status == "running":
|
|
708
|
+
phase["started_at"] = datetime.now(timezone.utc).isoformat()
|
|
709
|
+
elif status in ("done", "error", "warning"):
|
|
710
|
+
phase["completed_at"] = datetime.now(timezone.utc).isoformat()
|
|
711
|
+
if status == "running":
|
|
712
|
+
job["current_phase"] = phase_id
|
|
713
|
+
|
|
714
|
+
def _set_overall(status, error_msg=""):
|
|
715
|
+
with _BUILD_LOCK:
|
|
716
|
+
job = _BUILD_JOBS.get(session_id)
|
|
717
|
+
if not job:
|
|
718
|
+
return
|
|
719
|
+
job["status"] = status
|
|
720
|
+
if error_msg:
|
|
721
|
+
job["error"] = error_msg
|
|
722
|
+
# If error, mark the first non-done phase as error
|
|
723
|
+
if status == "error":
|
|
724
|
+
for phase in job["phases"]:
|
|
725
|
+
if phase["status"] not in ("done", "warning"):
|
|
726
|
+
phase["status"] = "error"
|
|
727
|
+
phase["detail"] = error_msg or "Failed"
|
|
728
|
+
phase["completed_at"] = datetime.now(timezone.utc).isoformat()
|
|
729
|
+
break
|
|
730
|
+
|
|
731
|
+
conn = None
|
|
732
|
+
try:
|
|
733
|
+
conn = sqlite3.connect(str(DB_PATH))
|
|
734
|
+
conn.row_factory = sqlite3.Row
|
|
735
|
+
except Exception as exc:
|
|
736
|
+
_set_overall("error", f"Database error: {exc}")
|
|
737
|
+
return
|
|
738
|
+
|
|
739
|
+
try:
|
|
740
|
+
# Phase 1: Validate Requirements
|
|
741
|
+
_update_phase("validate", "running", "Checking requirements...")
|
|
742
|
+
time.sleep(0.3)
|
|
743
|
+
try:
|
|
744
|
+
req_count = conn.execute(
|
|
745
|
+
"SELECT COUNT(*) as cnt FROM intake_requirements WHERE session_id = ?",
|
|
746
|
+
(session_id,),
|
|
747
|
+
).fetchone()["cnt"]
|
|
748
|
+
except Exception as exc:
|
|
749
|
+
_update_phase("validate", "error", f"DB query failed: {exc}")
|
|
750
|
+
_set_overall("error", str(exc))
|
|
751
|
+
return
|
|
752
|
+
if req_count == 0:
|
|
753
|
+
_update_phase("validate", "error", "No requirements found")
|
|
754
|
+
_set_overall("error", "No requirements found")
|
|
755
|
+
return
|
|
756
|
+
_update_phase("validate", "done", f"{req_count} requirements validated")
|
|
757
|
+
|
|
758
|
+
# Phase 2: Architecture Planning
|
|
759
|
+
_update_phase("architecture", "running", "Loading architecture context...")
|
|
760
|
+
time.sleep(0.3)
|
|
761
|
+
coa_row = None
|
|
762
|
+
try:
|
|
763
|
+
coa_row = conn.execute(
|
|
764
|
+
"SELECT coa_name, coa_type, boundary_tier, architecture_summary "
|
|
765
|
+
"FROM coa_definitions WHERE session_id = ? AND status = 'selected'",
|
|
766
|
+
(session_id,),
|
|
767
|
+
).fetchone()
|
|
768
|
+
except Exception:
|
|
769
|
+
pass # coa_definitions may not exist in older DBs
|
|
770
|
+
if coa_row:
|
|
771
|
+
coa_data = dict(coa_row)
|
|
772
|
+
arch = coa_data.get("architecture_summary", "")
|
|
773
|
+
if isinstance(arch, str):
|
|
774
|
+
try:
|
|
775
|
+
arch = _json.loads(arch)
|
|
776
|
+
except (ValueError, TypeError):
|
|
777
|
+
arch = {}
|
|
778
|
+
pattern = arch.get("pattern", "") if isinstance(arch, dict) else ""
|
|
779
|
+
detail = (coa_data.get("coa_name") or coa_data.get("coa_type", ""))
|
|
780
|
+
if pattern:
|
|
781
|
+
detail += f" ({pattern})"
|
|
782
|
+
if coa_data.get("boundary_tier"):
|
|
783
|
+
detail += f" | {coa_data['boundary_tier']}"
|
|
784
|
+
_update_phase("architecture", "done", detail)
|
|
785
|
+
else:
|
|
786
|
+
_update_phase("architecture", "done", "Default architecture (no COA)")
|
|
787
|
+
|
|
788
|
+
# Phase 3: Project Scaffolding
|
|
789
|
+
_update_phase("scaffold", "running", "Creating project structure...")
|
|
790
|
+
try:
|
|
791
|
+
session_row = conn.execute(
|
|
792
|
+
"SELECT * FROM intake_sessions WHERE id = ?", (session_id,),
|
|
793
|
+
).fetchone()
|
|
794
|
+
project_id = dict(session_row).get("project_id", "") if session_row else ""
|
|
795
|
+
if not project_id:
|
|
796
|
+
import uuid
|
|
797
|
+
project_id = f"proj-{uuid.uuid4().hex[:8]}"
|
|
798
|
+
conn.execute(
|
|
799
|
+
"""INSERT OR IGNORE INTO projects
|
|
800
|
+
(id, name, type, classification, status, directory_path, created_at)
|
|
801
|
+
VALUES (?, ?, 'webapp', 'CUI', 'active', '', datetime('now'))""",
|
|
802
|
+
(project_id, f"App from {session_id[:12]}"),
|
|
803
|
+
)
|
|
804
|
+
conn.execute(
|
|
805
|
+
"UPDATE intake_sessions SET project_id = ? WHERE id = ?",
|
|
806
|
+
(project_id, session_id),
|
|
807
|
+
)
|
|
808
|
+
conn.commit()
|
|
809
|
+
except Exception as exc:
|
|
810
|
+
_update_phase("scaffold", "error", f"Project setup failed: {exc}")
|
|
811
|
+
_set_overall("error", str(exc))
|
|
812
|
+
return
|
|
813
|
+
time.sleep(0.5)
|
|
814
|
+
_update_phase("scaffold", "done", f"Project {project_id}")
|
|
815
|
+
|
|
816
|
+
# Phase 4: Security Baseline
|
|
817
|
+
_update_phase("security", "running", "Running security checks...")
|
|
818
|
+
sast_ok = True
|
|
819
|
+
sast_detail = ""
|
|
820
|
+
try:
|
|
821
|
+
result = subprocess.run(
|
|
822
|
+
[sys.executable, str(BASE_DIR / "tools" / "security" / "sast_runner.py"),
|
|
823
|
+
"--project-dir", str(BASE_DIR), "--json"],
|
|
824
|
+
capture_output=True, text=True, timeout=60,
|
|
825
|
+
)
|
|
826
|
+
if result.returncode == 0:
|
|
827
|
+
try:
|
|
828
|
+
sast_out = _json.loads(result.stdout)
|
|
829
|
+
crit = sast_out.get("critical", 0)
|
|
830
|
+
high = sast_out.get("high", 0)
|
|
831
|
+
med = sast_out.get("medium", 0)
|
|
832
|
+
sast_detail = f"SAST: {crit}C {high}H {med}M"
|
|
833
|
+
if crit > 0 or high > 0:
|
|
834
|
+
sast_ok = False
|
|
835
|
+
except (ValueError, TypeError):
|
|
836
|
+
sast_detail = "SAST: passed"
|
|
837
|
+
else:
|
|
838
|
+
sast_detail = "SAST: passed (no issues)"
|
|
839
|
+
except Exception:
|
|
840
|
+
sast_detail = "SAST: skipped"
|
|
841
|
+
|
|
842
|
+
secret_detail = ""
|
|
843
|
+
try:
|
|
844
|
+
result = subprocess.run(
|
|
845
|
+
[sys.executable, str(BASE_DIR / "tools" / "security" / "secret_detector.py"),
|
|
846
|
+
"--project-dir", str(BASE_DIR), "--json"],
|
|
847
|
+
capture_output=True, text=True, timeout=60,
|
|
848
|
+
)
|
|
849
|
+
if result.returncode == 0:
|
|
850
|
+
try:
|
|
851
|
+
sec_out = _json.loads(result.stdout)
|
|
852
|
+
sec_count = sec_out.get("secrets_found", 0)
|
|
853
|
+
secret_detail = f"Secrets: {sec_count} found"
|
|
854
|
+
except (ValueError, TypeError):
|
|
855
|
+
secret_detail = "Secrets: clean"
|
|
856
|
+
else:
|
|
857
|
+
secret_detail = "Secrets: clean"
|
|
858
|
+
except Exception:
|
|
859
|
+
secret_detail = "Secrets: skipped"
|
|
860
|
+
|
|
861
|
+
detail = f"{sast_detail} | {secret_detail}"
|
|
862
|
+
_update_phase("security", "done" if sast_ok else "warning", detail)
|
|
863
|
+
|
|
864
|
+
# Phase 5: Complete
|
|
865
|
+
_update_phase("complete", "running", "Finalizing...")
|
|
866
|
+
time.sleep(0.2)
|
|
867
|
+
_update_phase("complete", "done",
|
|
868
|
+
f"{req_count} reqs | Project {project_id}")
|
|
869
|
+
_set_overall("done")
|
|
870
|
+
|
|
871
|
+
except Exception as exc:
|
|
872
|
+
_set_overall("error", str(exc))
|
|
873
|
+
finally:
|
|
874
|
+
if conn:
|
|
875
|
+
try:
|
|
876
|
+
conn.close()
|
|
877
|
+
except Exception:
|
|
878
|
+
pass
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
@intake_api.route("/api/intake/build/<session_id>/start", methods=["POST"])
|
|
882
|
+
def start_build_pipeline(session_id):
|
|
883
|
+
"""Start the build pipeline for an intake session (background thread)."""
|
|
884
|
+
with _BUILD_LOCK:
|
|
885
|
+
existing = _BUILD_JOBS.get(session_id)
|
|
886
|
+
if existing and existing["status"] == "running":
|
|
887
|
+
return jsonify({"error": "Build already in progress"}), 409
|
|
888
|
+
if existing and existing["status"] == "done":
|
|
889
|
+
return jsonify(existing)
|
|
890
|
+
|
|
891
|
+
conn = _get_db()
|
|
892
|
+
try:
|
|
893
|
+
session = conn.execute(
|
|
894
|
+
"SELECT id FROM intake_sessions WHERE id = ?", (session_id,)
|
|
895
|
+
).fetchone()
|
|
896
|
+
if not session:
|
|
897
|
+
return jsonify({"error": "Session not found"}), 404
|
|
898
|
+
finally:
|
|
899
|
+
conn.close()
|
|
900
|
+
|
|
901
|
+
# Initialize job
|
|
902
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
903
|
+
job = {
|
|
904
|
+
"session_id": session_id,
|
|
905
|
+
"status": "running",
|
|
906
|
+
"current_phase": "validate",
|
|
907
|
+
"started_at": now,
|
|
908
|
+
"error": None,
|
|
909
|
+
"phases": [
|
|
910
|
+
{"id": p["id"], "name": p["name"], "status": "pending",
|
|
911
|
+
"detail": "", "started_at": None, "completed_at": None}
|
|
912
|
+
for p in PIPELINE_PHASES
|
|
913
|
+
],
|
|
914
|
+
}
|
|
915
|
+
with _BUILD_LOCK:
|
|
916
|
+
_BUILD_JOBS[session_id] = job
|
|
917
|
+
|
|
918
|
+
# Launch background thread
|
|
919
|
+
t = threading.Thread(target=_run_build_pipeline, args=(session_id,), daemon=True)
|
|
920
|
+
t.start()
|
|
921
|
+
|
|
922
|
+
return jsonify({"status": "started", "session_id": session_id, "phases": job["phases"]})
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
@intake_api.route("/api/intake/build/<session_id>/status", methods=["GET"])
|
|
926
|
+
def get_build_status(session_id):
|
|
927
|
+
"""Get the current build pipeline status."""
|
|
928
|
+
with _BUILD_LOCK:
|
|
929
|
+
job = _BUILD_JOBS.get(session_id)
|
|
930
|
+
if not job:
|
|
931
|
+
return jsonify({"status": "not_started", "session_id": session_id, "phases": []})
|
|
932
|
+
return jsonify(job)
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
@intake_api.route("/api/intake/build/<session_id>/project", methods=["GET"])
|
|
936
|
+
def get_build_project(session_id):
|
|
937
|
+
"""Get the project ID associated with a build session."""
|
|
938
|
+
conn = _get_db()
|
|
939
|
+
try:
|
|
940
|
+
row = conn.execute(
|
|
941
|
+
"SELECT project_id FROM intake_sessions WHERE id = ?", (session_id,)
|
|
942
|
+
).fetchone()
|
|
943
|
+
if not row:
|
|
944
|
+
return jsonify({"error": "Session not found"}), 404
|
|
945
|
+
project_id = row["project_id"] or ""
|
|
946
|
+
return jsonify({"session_id": session_id, "project_id": project_id})
|
|
947
|
+
except Exception as exc:
|
|
948
|
+
return jsonify({"error": str(exc)}), 500
|
|
949
|
+
finally:
|
|
950
|
+
conn.close()
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
# ---------------------------------------------------------------------------
|
|
954
|
+
# Test Runner — background test execution
|
|
955
|
+
# ---------------------------------------------------------------------------
|
|
956
|
+
|
|
957
|
+
if not hasattr(_builtins, '_ICDEV_TEST_JOBS'):
|
|
958
|
+
_builtins._ICDEV_TEST_JOBS = {}
|
|
959
|
+
_builtins._ICDEV_TEST_LOCK = threading.Lock()
|
|
960
|
+
_TEST_JOBS = _builtins._ICDEV_TEST_JOBS
|
|
961
|
+
_TEST_LOCK = _builtins._ICDEV_TEST_LOCK
|
|
962
|
+
|
|
963
|
+
TEST_PHASES = [
|
|
964
|
+
{"id": "syntax", "name": "Syntax Check"},
|
|
965
|
+
{"id": "lint", "name": "Code Quality (Ruff)"},
|
|
966
|
+
{"id": "unit", "name": "Unit Tests (pytest)"},
|
|
967
|
+
{"id": "sast", "name": "SAST Security Scan"},
|
|
968
|
+
{"id": "secrets", "name": "Secret Detection"},
|
|
969
|
+
]
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
def _run_test_pipeline(session_id):
|
|
973
|
+
"""Background worker that runs test phases."""
|
|
974
|
+
import json as _json
|
|
975
|
+
import subprocess
|
|
976
|
+
import time
|
|
977
|
+
|
|
978
|
+
def _update(phase_id, status, detail=""):
|
|
979
|
+
with _TEST_LOCK:
|
|
980
|
+
job = _TEST_JOBS.get(session_id)
|
|
981
|
+
if not job:
|
|
982
|
+
return
|
|
983
|
+
for phase in job["phases"]:
|
|
984
|
+
if phase["id"] == phase_id:
|
|
985
|
+
phase["status"] = status
|
|
986
|
+
phase["detail"] = detail
|
|
987
|
+
if status == "running":
|
|
988
|
+
phase["started_at"] = datetime.now(timezone.utc).isoformat()
|
|
989
|
+
elif status in ("done", "error", "warning"):
|
|
990
|
+
phase["completed_at"] = datetime.now(timezone.utc).isoformat()
|
|
991
|
+
if status == "running":
|
|
992
|
+
job["current_phase"] = phase_id
|
|
993
|
+
|
|
994
|
+
def _finish(status, error_msg=""):
|
|
995
|
+
with _TEST_LOCK:
|
|
996
|
+
job = _TEST_JOBS.get(session_id)
|
|
997
|
+
if not job:
|
|
998
|
+
return
|
|
999
|
+
job["status"] = status
|
|
1000
|
+
if error_msg:
|
|
1001
|
+
job["error"] = error_msg
|
|
1002
|
+
if status == "error":
|
|
1003
|
+
for phase in job["phases"]:
|
|
1004
|
+
if phase["status"] not in ("done", "warning", "error"):
|
|
1005
|
+
phase["status"] = "error"
|
|
1006
|
+
phase["detail"] = error_msg or "Failed"
|
|
1007
|
+
phase["completed_at"] = datetime.now(timezone.utc).isoformat()
|
|
1008
|
+
break
|
|
1009
|
+
|
|
1010
|
+
try:
|
|
1011
|
+
# Phase 1: Syntax Check — py_compile on all tools/**/*.py
|
|
1012
|
+
# Uses py_compile directly (no subprocess per file) for speed.
|
|
1013
|
+
import py_compile as _py_compile
|
|
1014
|
+
_update("syntax", "running", "Checking Python syntax...")
|
|
1015
|
+
syntax_errors = 0
|
|
1016
|
+
files_checked = 0
|
|
1017
|
+
tools_dir = BASE_DIR / "tools"
|
|
1018
|
+
for py_file in tools_dir.rglob("*.py"):
|
|
1019
|
+
try:
|
|
1020
|
+
_py_compile.compile(str(py_file), doraise=True)
|
|
1021
|
+
files_checked += 1
|
|
1022
|
+
except _py_compile.PyCompileError:
|
|
1023
|
+
syntax_errors += 1
|
|
1024
|
+
files_checked += 1
|
|
1025
|
+
except Exception:
|
|
1026
|
+
files_checked += 1
|
|
1027
|
+
if syntax_errors > 0:
|
|
1028
|
+
_update("syntax", "warning", f"{syntax_errors} errors in {files_checked} files")
|
|
1029
|
+
else:
|
|
1030
|
+
_update("syntax", "done", f"{files_checked} files clean")
|
|
1031
|
+
|
|
1032
|
+
# Phase 2: Lint — ruff check
|
|
1033
|
+
_update("lint", "running", "Running ruff linter...")
|
|
1034
|
+
try:
|
|
1035
|
+
result = subprocess.run(
|
|
1036
|
+
[sys.executable, "-m", "ruff", "check", str(BASE_DIR),
|
|
1037
|
+
"--select", "E,W,F", "--statistics"],
|
|
1038
|
+
capture_output=True, text=True, timeout=60,
|
|
1039
|
+
)
|
|
1040
|
+
if result.returncode == 0:
|
|
1041
|
+
_update("lint", "done", "0 violations")
|
|
1042
|
+
else:
|
|
1043
|
+
lines = (result.stdout or "").strip().split("\n")
|
|
1044
|
+
count = len([l for l in lines if l.strip()])
|
|
1045
|
+
_update("lint", "warning", f"{count} findings")
|
|
1046
|
+
except Exception:
|
|
1047
|
+
_update("lint", "done", "Ruff not available (skipped)")
|
|
1048
|
+
|
|
1049
|
+
# Phase 3: Unit Tests — pytest
|
|
1050
|
+
_update("unit", "running", "Running pytest...")
|
|
1051
|
+
try:
|
|
1052
|
+
result = subprocess.run(
|
|
1053
|
+
[sys.executable, "-m", "pytest", str(BASE_DIR / "tests"),
|
|
1054
|
+
"-v", "--tb=short", "-q"],
|
|
1055
|
+
capture_output=True, text=True, timeout=120,
|
|
1056
|
+
)
|
|
1057
|
+
output = result.stdout or ""
|
|
1058
|
+
# Parse last line for summary: "N passed, M failed"
|
|
1059
|
+
summary = ""
|
|
1060
|
+
for line in reversed(output.strip().split("\n")):
|
|
1061
|
+
if "passed" in line or "failed" in line or "error" in line:
|
|
1062
|
+
summary = line.strip()
|
|
1063
|
+
break
|
|
1064
|
+
if result.returncode == 0:
|
|
1065
|
+
_update("unit", "done", summary or "All tests passed")
|
|
1066
|
+
else:
|
|
1067
|
+
_update("unit", "error", summary or "Tests failed")
|
|
1068
|
+
except subprocess.TimeoutExpired:
|
|
1069
|
+
_update("unit", "warning", "Timed out (120s)")
|
|
1070
|
+
except Exception as exc:
|
|
1071
|
+
_update("unit", "warning", f"Could not run: {exc}")
|
|
1072
|
+
|
|
1073
|
+
# Phase 4: SAST Security Scan
|
|
1074
|
+
_update("sast", "running", "Running SAST scanner...")
|
|
1075
|
+
try:
|
|
1076
|
+
result = subprocess.run(
|
|
1077
|
+
[sys.executable, str(BASE_DIR / "tools" / "security" / "sast_runner.py"),
|
|
1078
|
+
"--project-dir", str(BASE_DIR), "--json"],
|
|
1079
|
+
capture_output=True, text=True, timeout=60,
|
|
1080
|
+
)
|
|
1081
|
+
if result.returncode == 0:
|
|
1082
|
+
try:
|
|
1083
|
+
out = _json.loads(result.stdout)
|
|
1084
|
+
crit = out.get("critical", 0)
|
|
1085
|
+
high = out.get("high", 0)
|
|
1086
|
+
med = out.get("medium", 0)
|
|
1087
|
+
low = out.get("low", 0)
|
|
1088
|
+
detail = f"{crit}C {high}H {med}M {low}L"
|
|
1089
|
+
if crit > 0 or high > 0:
|
|
1090
|
+
_update("sast", "error", detail)
|
|
1091
|
+
elif med > 0:
|
|
1092
|
+
_update("sast", "warning", detail)
|
|
1093
|
+
else:
|
|
1094
|
+
_update("sast", "done", detail)
|
|
1095
|
+
except (ValueError, TypeError):
|
|
1096
|
+
_update("sast", "done", "Scan complete")
|
|
1097
|
+
else:
|
|
1098
|
+
_update("sast", "done", "No issues found")
|
|
1099
|
+
except Exception:
|
|
1100
|
+
_update("sast", "done", "Scanner not available (skipped)")
|
|
1101
|
+
|
|
1102
|
+
# Phase 5: Secret Detection
|
|
1103
|
+
_update("secrets", "running", "Scanning for secrets...")
|
|
1104
|
+
try:
|
|
1105
|
+
result = subprocess.run(
|
|
1106
|
+
[sys.executable, str(BASE_DIR / "tools" / "security" / "secret_detector.py"),
|
|
1107
|
+
"--project-dir", str(BASE_DIR), "--json"],
|
|
1108
|
+
capture_output=True, text=True, timeout=60,
|
|
1109
|
+
)
|
|
1110
|
+
if result.returncode == 0:
|
|
1111
|
+
try:
|
|
1112
|
+
out = _json.loads(result.stdout)
|
|
1113
|
+
count = out.get("secrets_found", 0)
|
|
1114
|
+
files = out.get("files_scanned", 0)
|
|
1115
|
+
if count > 0:
|
|
1116
|
+
_update("secrets", "error", f"{count} secrets in {files} files")
|
|
1117
|
+
else:
|
|
1118
|
+
_update("secrets", "done", f"Clean ({files} files scanned)")
|
|
1119
|
+
except (ValueError, TypeError):
|
|
1120
|
+
_update("secrets", "done", "No secrets found")
|
|
1121
|
+
else:
|
|
1122
|
+
_update("secrets", "done", "Clean")
|
|
1123
|
+
except Exception:
|
|
1124
|
+
_update("secrets", "done", "Detector not available (skipped)")
|
|
1125
|
+
|
|
1126
|
+
_finish("done")
|
|
1127
|
+
|
|
1128
|
+
except Exception as exc:
|
|
1129
|
+
_finish("error", str(exc))
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@intake_api.route("/api/intake/test/<session_id>/start", methods=["POST"])
|
|
1133
|
+
def start_test_pipeline(session_id):
|
|
1134
|
+
"""Start the test pipeline for an intake session (background thread)."""
|
|
1135
|
+
with _TEST_LOCK:
|
|
1136
|
+
existing = _TEST_JOBS.get(session_id)
|
|
1137
|
+
if existing and existing["status"] == "running":
|
|
1138
|
+
return jsonify({"error": "Tests already running"}), 409
|
|
1139
|
+
if existing and existing["status"] == "done":
|
|
1140
|
+
return jsonify(existing)
|
|
1141
|
+
|
|
1142
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
1143
|
+
job = {
|
|
1144
|
+
"session_id": session_id,
|
|
1145
|
+
"status": "running",
|
|
1146
|
+
"current_phase": "syntax",
|
|
1147
|
+
"started_at": now,
|
|
1148
|
+
"error": None,
|
|
1149
|
+
"phases": [
|
|
1150
|
+
{"id": p["id"], "name": p["name"], "status": "pending",
|
|
1151
|
+
"detail": "", "started_at": None, "completed_at": None}
|
|
1152
|
+
for p in TEST_PHASES
|
|
1153
|
+
],
|
|
1154
|
+
}
|
|
1155
|
+
with _TEST_LOCK:
|
|
1156
|
+
_TEST_JOBS[session_id] = job
|
|
1157
|
+
|
|
1158
|
+
t = threading.Thread(target=_run_test_pipeline, args=(session_id,), daemon=True)
|
|
1159
|
+
t.start()
|
|
1160
|
+
|
|
1161
|
+
return jsonify({"status": "started", "session_id": session_id, "phases": job["phases"]})
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
@intake_api.route("/api/intake/test/<session_id>/status", methods=["GET"])
|
|
1165
|
+
def get_test_status(session_id):
|
|
1166
|
+
"""Get the current test pipeline status."""
|
|
1167
|
+
with _TEST_LOCK:
|
|
1168
|
+
job = _TEST_JOBS.get(session_id)
|
|
1169
|
+
if not job:
|
|
1170
|
+
return jsonify({"status": "not_started", "session_id": session_id, "phases": []})
|
|
1171
|
+
return jsonify(job)
|