icdev 0.0.3__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.
- args/agent_config.yaml +113 -0
- args/audit_regimes/cisa_sbd.json +381 -0
- args/audit_regimes/cmmc_l2.json +906 -0
- args/audit_regimes/dod_cssp.json +393 -0
- args/audit_regimes/dodi_5000_87.json +297 -0
- args/audit_regimes/fedramp_moderate.json +650 -0
- args/audit_regimes/ieee_1012.json +373 -0
- args/audit_regimes/nist_800_171.json +624 -0
- args/audit_regimes/nist_800_53.json +907 -0
- args/cloudforge_blueprints/aws_commercial.yaml +29 -0
- args/cloudforge_blueprints/aws_govcloud_il4.yaml +34 -0
- args/cloudforge_blueprints/aws_govcloud_il5.yaml +38 -0
- args/cloudforge_blueprints/azure_commercial.yaml +28 -0
- args/cloudforge_blueprints/azure_gov_il4.yaml +32 -0
- args/cloudforge_blueprints/azure_gov_il5.yaml +36 -0
- args/cloudforge_blueprints/gcp_commercial.yaml +28 -0
- args/cloudforge_blueprints/oci_commercial.yaml +28 -0
- args/cloudforge_config.yaml +231 -0
- args/cloudforge_runbook_templates/backup_verify.yaml +98 -0
- args/cloudforge_runbook_templates/dr_failover.yaml +107 -0
- args/cloudforge_runbook_templates/health_check.yaml +97 -0
- args/cloudforge_runbook_templates/incident_response.yaml +101 -0
- args/cloudforge_runbook_templates/migration_cutover.yaml +105 -0
- args/cloudforge_runbook_templates/patch_rollout.yaml +92 -0
- args/cloudforge_runbook_templates/zone_provision.yaml +93 -0
- args/code_pattern_config.yaml +151 -0
- args/code_quality_config.yaml +47 -0
- args/compliance_config.yaml +17 -0
- args/control_inheritance.yaml +177 -0
- args/csp_mcp_config.yaml +41 -0
- args/cui_markings.yaml +35 -0
- args/databridge_config.yaml +232 -0
- args/db_config.yaml +116 -0
- args/decision_tables/agent_trust_decision.yaml +143 -0
- args/decision_tables/ato_boundary_impact.yaml +132 -0
- args/decision_tables/deployment_approval.yaml +152 -0
- args/degradation_matrix.yaml +163 -0
- args/devsecops_config.yaml +286 -0
- args/endpoint_security_config.yaml +207 -0
- args/exit_criteria.yaml +102 -0
- args/feature_flags.yaml +235 -0
- args/file_access_tiers.yaml +88 -0
- args/forge_studio/blueprint_config.yaml +27 -0
- args/forge_studio/component_catalog.json +411 -0
- args/forge_studio/workflow_templates.yaml +103 -0
- args/govcon_config.yaml +41 -0
- args/harness_config.yaml +67 -0
- args/innovation_config.yaml +321 -0
- args/knowledge_graph_config.yaml +113 -0
- args/llm_config.yaml +222 -0
- args/marketplace_config.yaml +260 -0
- args/monitoring_config.yaml +127 -0
- args/mosa_config.yaml +190 -0
- args/observability_tracing_config.yaml +170 -0
- args/owasp_agentic_config.yaml +171 -0
- args/pipeline_gates.yaml +197 -0
- args/project_defaults.yaml +235 -0
- args/prompt_chains.yaml +163 -0
- args/rag_config.yaml +167 -0
- args/research_config.yaml +89 -0
- args/resilience_config.yaml +197 -0
- args/ricoas_config.yaml +191 -0
- args/security_gates.yaml +763 -0
- args/storage_config.yaml +63 -0
- args/writeguard_config.yaml +131 -0
- args/zta_config.yaml +247 -0
- context/__init__.py +6 -0
- context/agent/__init__.py +6 -0
- context/agent/response_schemas/__init__.py +6 -0
- context/agent/response_schemas/debate_position.json +46 -0
- context/agent/response_schemas/fitness_scorecard.json +74 -0
- context/agent/response_schemas/review_decision.json +39 -0
- context/agent/response_schemas/task_decomposition.json +82 -0
- context/agent/response_schemas/veto_decision.json +40 -0
- context/agentic/__init__.py +6 -0
- context/agentic/architecture_patterns.md +269 -0
- context/agentic/capability_registry.yaml +223 -0
- context/agentic/csp_integration.md +30 -0
- context/agentic/csp_mcp_registry.yaml +280 -0
- context/agentic/fitness_rubric.md +56 -0
- context/agentic/governance_baseline.md +205 -0
- context/ci/__init__.py +6 -0
- context/ci/worktree_templates.json +44 -0
- context/cloud/__init__.py +6 -0
- context/cloud/csp_service_registry.json +739 -0
- context/compliance/__init__.py +6 -0
- context/compliance/ai_rmf_crosswalk.yaml +226 -0
- context/compliance/atlas_mitigations.json +293 -0
- context/compliance/atlas_techniques.json +833 -0
- context/compliance/cisa_sbd_requirements.json +477 -0
- context/compliance/cjis_security_policy.json +522 -0
- context/compliance/cmmc_practices.json +2494 -0
- context/compliance/cmmc_report_template.md +142 -0
- context/compliance/cnssi_1253_overlay.json +109 -0
- context/compliance/control_crosswalk.json +1914 -0
- context/compliance/control_families/__init__.py +6 -0
- context/compliance/csp_certifications.json +251 -0
- context/compliance/cssp_report_template.md +193 -0
- context/compliance/cui_templates/__init__.py +6 -0
- context/compliance/cui_templates/banner_block.txt +4 -0
- context/compliance/cui_templates/code_header.txt +8 -0
- context/compliance/cui_templates/document_template.md +35 -0
- context/compliance/data_type_framework_map.json +321 -0
- context/compliance/data_type_registry.json +147 -0
- context/compliance/dod_cssp_8530.json +463 -0
- context/compliance/eu_ai_act_annex_iii.json +108 -0
- context/compliance/export_templates/__init__.py +6 -0
- context/compliance/export_templates/emass_controls.csv.j2 +4 -0
- context/compliance/export_templates/evidence_package.md.j2 +39 -0
- context/compliance/export_templates/executive_summary.md.j2 +55 -0
- context/compliance/export_templates/poam_tracking.csv.j2 +4 -0
- context/compliance/fedramp_20x_ksi_schemas.json +133 -0
- context/compliance/fedramp_high_baseline.json +4370 -0
- context/compliance/fedramp_moderate_baseline.json +2183 -0
- context/compliance/fedramp_report_template.md +181 -0
- context/compliance/fips_200_areas.json +362 -0
- context/compliance/gao_ai_accountability.json +262 -0
- context/compliance/hipaa_security_rule.json +720 -0
- context/compliance/hitrust_csf_v11.json +930 -0
- context/compliance/impact_level_profiles.json +251 -0
- context/compliance/incident_response_template.md +1110 -0
- context/compliance/iso27001_2022_controls.json +750 -0
- context/compliance/iso27001_nist_bridge.json +382 -0
- context/compliance/iso42001_controls.json +254 -0
- context/compliance/ivv_checklist_template.md +80 -0
- context/compliance/ivv_report_template.md +116 -0
- context/compliance/ivv_requirements.json +372 -0
- context/compliance/mosa_crosswalk.json +327 -0
- context/compliance/mosa_framework.json +250 -0
- context/compliance/narrative_templates/AC.md.j2 +101 -0
- context/compliance/narrative_templates/AU.md.j2 +106 -0
- context/compliance/narrative_templates/IA.md.j2 +104 -0
- context/compliance/narrative_templates/SC.md.j2 +102 -0
- context/compliance/narrative_templates/SI.md.j2 +111 -0
- context/compliance/narrative_templates/__init__.py +6 -0
- context/compliance/narrative_templates/default.md.j2 +50 -0
- context/compliance/narrative_templates/executive_summary.j2 +27 -0
- context/compliance/narrative_templates/poam_milestone.j2 +19 -0
- context/compliance/narrative_templates/ssp_section.j2 +11 -0
- context/compliance/nist_800_171_controls.json +1552 -0
- context/compliance/nist_800_207_crosswalk.json +399 -0
- context/compliance/nist_800_207_zta.json +258 -0
- context/compliance/nist_800_53.json +324 -0
- context/compliance/nist_ai_600_1_genai.json +326 -0
- context/compliance/nist_ai_rmf.json +206 -0
- context/compliance/nist_sp_800_60_types.json +1667 -0
- context/compliance/omb_m25_21_high_impact_ai.json +248 -0
- context/compliance/omb_m26_04_unbiased_ai.json +262 -0
- context/compliance/owasp_agentic_asi.json +133 -0
- context/compliance/owasp_agentic_threats.json +285 -0
- context/compliance/owasp_llm_top10.json +274 -0
- context/compliance/pci_dss_v4.json +510 -0
- context/compliance/poam_template.md +117 -0
- context/compliance/safeai_controls.json +512 -0
- context/compliance/sbd_report_template.md +77 -0
- context/compliance/siem_config_templates/__init__.py +6 -0
- context/compliance/siem_config_templates/filebeat.yml +213 -0
- context/compliance/siem_config_templates/log_sources.json +208 -0
- context/compliance/soc2_trust_criteria.json +661 -0
- context/compliance/ssp_template.md +432 -0
- context/compliance/stig_templates/__init__.py +6 -0
- context/compliance/stig_templates/webapp_stig.json +139 -0
- context/compliance/xai_requirements.json +108 -0
- context/dashboard/__init__.py +6 -0
- context/dashboard/nlq_examples.json +50 -0
- context/dashboard/schema_descriptions.json +23 -0
- context/icdev_methodology.md +100 -0
- context/integration/__init__.py +6 -0
- context/integration/approval_workflows.json +32 -0
- context/integration/gitlab_field_mappings.json +33 -0
- context/integration/jira_field_mappings.json +32 -0
- context/integration/reqif_export_schema.json +23 -0
- context/integration/servicenow_field_mappings.json +22 -0
- context/languages/__init__.py +6 -0
- context/languages/framework_patterns.json +205 -0
- context/languages/language_registry.json +279 -0
- context/llm/__init__.py +6 -0
- context/llm/example_provider.py +89 -0
- context/marketplace/assets/writeguard-core.yaml +100 -0
- context/marketplace/assets/writeguard-govcon.yaml +45 -0
- context/marketplace/assets/writeguard-style-guides.yaml +44 -0
- context/mbse/__init__.py +6 -0
- context/mbse/des_report_template.md +162 -0
- context/mbse/des_requirements.json +411 -0
- context/mbse/digital_thread_patterns.json +403 -0
- context/mbse/reqif_schema.json +280 -0
- context/mbse/sysml_element_types.json +432 -0
- context/oscal/NIST_SP-800-53_rev5_catalog.json +254987 -0
- context/oscal/README.md +43 -0
- context/patterns/__init__.py +6 -0
- context/profiles/__init__.py +6 -0
- context/profiles/dod_baseline_v1.yaml +145 -0
- context/profiles/fedramp_baseline_v1.yaml +143 -0
- context/profiles/financial_baseline_v1.yaml +142 -0
- context/profiles/healthcare_baseline_v1.yaml +135 -0
- context/profiles/law_enforcement_v1.yaml +129 -0
- context/profiles/startup_v1.yaml +134 -0
- context/rag/source_mappings.json +42 -0
- context/requirements/__init__.py +6 -0
- context/requirements/ambiguity_patterns.json +97 -0
- context/requirements/boundary_impact_rules.json +123 -0
- context/requirements/default_constitutions.json +67 -0
- context/requirements/document_extraction_rules.json +58 -0
- context/requirements/gap_patterns.json +108 -0
- context/requirements/readiness_rubric.json +78 -0
- context/requirements/red_alternative_patterns.json +210 -0
- context/requirements/safe_templates.json +72 -0
- context/requirements/spec_quality_checklist.json +122 -0
- context/research/regulatory_registry.json +114 -0
- context/research/verticals/cybersecurity.json +127 -0
- context/research/verticals/defense.json +104 -0
- context/research/verticals/fintech.json +125 -0
- context/research/verticals/healthcare.json +118 -0
- context/research/verticals/logistics.json +117 -0
- context/research/verticals/trading.json +145 -0
- context/simulation/__init__.py +6 -0
- context/simulation/architecture_patterns.json +36 -0
- context/simulation/coa_templates.json +38 -0
- context/simulation/cost_models.json +23 -0
- context/simulation/risk_categories.json +46 -0
- context/supply_chain/__init__.py +6 -0
- context/supply_chain/isa_templates.json +129 -0
- context/supply_chain/nist_800_161_controls.json +247 -0
- context/supply_chain/scrm_risk_matrix.json +147 -0
- context/templates/__init__.py +6 -0
- context/templates/ansible/__init__.py +6 -0
- context/templates/ansible/playbooks/__init__.py +6 -0
- context/templates/ansible/roles/__init__.py +6 -0
- context/templates/gitlab_ci/__init__.py +6 -0
- context/templates/grafana/__init__.py +6 -0
- context/templates/kubernetes/__init__.py +6 -0
- context/templates/project/__init__.py +6 -0
- context/templates/project/api/__init__.py +6 -0
- context/templates/project/cli/__init__.py +6 -0
- context/templates/project/data_pipeline/__init__.py +6 -0
- context/templates/project/iac/__init__.py +6 -0
- context/templates/project/javascript_frontend/__init__.py +6 -0
- context/templates/project/javascript_frontend/src/__init__.py +6 -0
- context/templates/project/javascript_frontend/tests/__init__.py +6 -0
- context/templates/project/microservice/__init__.py +6 -0
- context/templates/project/python_backend/__init__.py +6 -0
- context/templates/project/python_backend/src/__init__.py +6 -0
- context/templates/project/python_backend/tests/__init__.py +6 -0
- context/templates/project/python_backend/tests/features/__init__.py +6 -0
- context/templates/project/python_backend/tests/steps/__init__.py +6 -0
- context/templates/terraform/__init__.py +6 -0
- context/templates/terraform/govcloud_base/__init__.py +6 -0
- context/templates/terraform/modules/__init__.py +6 -0
- context/tone/__init__.py +6 -0
- context/writing/grammar_rules/common_errors.json +306 -0
- context/writing/grammar_rules/govcon_vocabulary.json +113 -0
- context/writing/style_guides/academic.yaml +43 -0
- context/writing/style_guides/business.yaml +42 -0
- context/writing/style_guides/government.yaml +59 -0
- context/writing/style_guides/proposal.yaml +58 -0
- context/writing/style_guides/technical.yaml +43 -0
- docs/adr/README.md +66 -0
- docs/adr/connector-forge-decisions.md +318 -0
- docs/adr/core-decisions.md +289 -0
- docs/adr/db-decisions.md +94 -0
- docs/adr/harness-decisions.md +122 -0
- docs/adr/innovation-decisions.md +262 -0
- docs/adr/marketplace-decisions.md +109 -0
- docs/adr/sbd-decisions.md +109 -0
- docs/adr/scale-engine-decisions.md +108 -0
- docs/adr/writeguard-decisions.md +136 -0
- docs/architecture/bounded-contexts.md +1032 -0
- docs/features/phase-65-writeguard.md +139 -0
- docs/features/phase-66-marketplace-commerce.md +79 -0
- docs/features/phase-67-knowledge-ingestion-rag-autodraft.md +97 -0
- docs/features/phase-68-enhanced-autodraft-pipeline.md +109 -0
- docs/features/phase-69-proposalai-marketplace-module.md +131 -0
- docs/features/phase-70-databridge.md +214 -0
- docs/features/phase-71-databridge-messaging.md +102 -0
- docs/implementation-plan-architecture-evolution.md +614 -0
- docs/marketplace/CONTRIBUTING.md +124 -0
- docs/marketplace/module_manifest_schema.yaml +83 -0
- docs/research/ai-architecture-patterns-2024-2026.md +1236 -0
- docs/research/app-builder-platform-analysis.md +582 -0
- docs/research/architecture-patterns-c4-ddd-agentic.md +871 -0
- docs/research/flowable-boat-competitive-analysis.md +426 -0
- docs/research/modern-dev-practices-2024-2026.md +1615 -0
- docs/research/secure-by-design-cloudyrion-adaptation.md +270 -0
- goals/agent_management.md +144 -0
- goals/ai_accountability.md +90 -0
- goals/ai_narratives.md +79 -0
- goals/ai_transparency.md +76 -0
- goals/ato_simulator.md +78 -0
- goals/audit_engine.md +177 -0
- goals/bite_sized_plans.md +225 -0
- goals/boundary_supply_chain.md +206 -0
- goals/brainstorming_gate.md +186 -0
- goals/build_app.md +604 -0
- goals/cato_live_evidence.md +77 -0
- goals/cloudforge.md +106 -0
- goals/code_intelligence.md +197 -0
- goals/compliance_workflow.md +858 -0
- goals/connector_forge.md +133 -0
- goals/databridge.md +128 -0
- goals/deploy_workflow.md +390 -0
- goals/developer_scorecard.md +78 -0
- goals/devsecops_workflow.md +408 -0
- goals/firmware_sbom.md +79 -0
- goals/forge_hub.md +78 -0
- goals/golden_path.md +77 -0
- goals/harness_engineering.md +91 -0
- goals/integration_testing.md +189 -0
- goals/knowledge_graph.md +128 -0
- goals/maintenance_audit.md +196 -0
- goals/manifest.md +50 -0
- goals/monitoring.md +126 -0
- goals/mosa_workflow.md +463 -0
- goals/multi_agent_orchestration.md +68 -0
- goals/observability_traceability_xai.md +154 -0
- goals/owasp_agentic_security.md +395 -0
- goals/pr_intelligence.md +78 -0
- goals/requirements_intake.md +213 -0
- goals/secure_by_design.md +135 -0
- goals/security_scan.md +381 -0
- goals/self_healing.md +120 -0
- goals/simulation_engine.md +111 -0
- goals/subagent_review.md +205 -0
- goals/systematic_debugging.md +257 -0
- goals/tdd_workflow.md +403 -0
- goals/template_exchange.md +77 -0
- goals/thread_heatmap.md +77 -0
- goals/threat_modeler.md +77 -0
- goals/verification_iron_law.md +192 -0
- goals/vsm_dashboard.md +76 -0
- goals/writeguard.md +89 -0
- goals/zero_trust_architecture.md +403 -0
- hardprompts/__init__.py +6 -0
- hardprompts/agent/__init__.py +6 -0
- hardprompts/agent/agentic_architect.md +100 -0
- hardprompts/agent/debate_prompt.md +32 -0
- hardprompts/agent/fitness_evaluation.md +48 -0
- hardprompts/agent/governance_review.md +214 -0
- hardprompts/agent/reviewer_prompt.md +34 -0
- hardprompts/agent/skill_design.md +172 -0
- hardprompts/agent/task_decomposition.md +275 -0
- hardprompts/agent/veto_check_prompt.md +33 -0
- hardprompts/architect/__init__.py +6 -0
- hardprompts/architect/api_design.md +283 -0
- hardprompts/architect/data_model.md +277 -0
- hardprompts/architect/system_design.md +180 -0
- hardprompts/builder/__init__.py +6 -0
- hardprompts/builder/code_generation.md +59 -0
- hardprompts/builder/refactor.md +58 -0
- hardprompts/builder/scaffold_project.md +69 -0
- hardprompts/builder/test_generation.md +87 -0
- hardprompts/ci/__init__.py +6 -0
- hardprompts/ci/worktree_setup.md +35 -0
- hardprompts/compliance/__init__.py +6 -0
- hardprompts/compliance/cmmc_assessment.md +63 -0
- hardprompts/compliance/cssp_assessment.md +75 -0
- hardprompts/compliance/cui_marking.md +86 -0
- hardprompts/compliance/fedramp_assessment.md +55 -0
- hardprompts/compliance/ivv_assessment.md +96 -0
- hardprompts/compliance/poam_generation.md +57 -0
- hardprompts/compliance/sbd_assessment.md +101 -0
- hardprompts/compliance/security_categorization.md +74 -0
- hardprompts/compliance/ssp_generation.md +56 -0
- hardprompts/compliance/stig_evaluation.md +63 -0
- hardprompts/dashboard/__init__.py +6 -0
- hardprompts/dashboard/nlq_system_prompt.md +26 -0
- hardprompts/infra/__init__.py +6 -0
- hardprompts/infra/k8s_manifests.md +118 -0
- hardprompts/infra/pipeline_generation.md +160 -0
- hardprompts/infra/terraform_generation.md +92 -0
- hardprompts/integration/__init__.py +6 -0
- hardprompts/integration/approval_review.md +17 -0
- hardprompts/integration/jira_mapping.md +25 -0
- hardprompts/integration/servicenow_mapping.md +14 -0
- hardprompts/knowledge/__init__.py +6 -0
- hardprompts/knowledge/pattern_detection.md +73 -0
- hardprompts/knowledge/recommendation_engine.md +90 -0
- hardprompts/knowledge/root_cause_analysis.md +91 -0
- hardprompts/maintenance/__init__.py +6 -0
- hardprompts/maintenance/maintenance_assessment.md +82 -0
- hardprompts/mbse/__init__.py +6 -0
- hardprompts/mbse/digital_thread.md +67 -0
- hardprompts/mbse/model_import.md +62 -0
- hardprompts/mbse/model_to_code.md +65 -0
- hardprompts/modernization/__init__.py +6 -0
- hardprompts/modernization/legacy_analysis.md +93 -0
- hardprompts/modernization/migration_planning.md +150 -0
- hardprompts/modernization/seven_r_assessment.md +107 -0
- hardprompts/proposal_draft.md +53 -0
- hardprompts/rag_citation.md +12 -0
- hardprompts/rag_rerank.md +31 -0
- hardprompts/requirements/__init__.py +6 -0
- hardprompts/requirements/bdd_generation.md +35 -0
- hardprompts/requirements/clarification_prioritization.md +29 -0
- hardprompts/requirements/decomposition.md +60 -0
- hardprompts/requirements/document_extraction.md +45 -0
- hardprompts/requirements/gap_detection.md +70 -0
- hardprompts/requirements/intake_conversation.md +101 -0
- hardprompts/requirements/readiness_assessment.md +39 -0
- hardprompts/requirements/spec_quality.md +33 -0
- hardprompts/requirements/traceability_analysis.md +23 -0
- hardprompts/security/__init__.py +6 -0
- hardprompts/security/endpoint_security.md +78 -0
- hardprompts/security/threat_model.md +70 -0
- hardprompts/security/vulnerability_assessment.md +81 -0
- hardprompts/simulation/__init__.py +6 -0
- hardprompts/simulation/architecture_impact.md +27 -0
- hardprompts/simulation/coa_alternative.md +27 -0
- hardprompts/simulation/coa_generation.md +25 -0
- hardprompts/simulation/compliance_impact.md +28 -0
- hardprompts/simulation/cost_estimation.md +33 -0
- hardprompts/simulation/risk_assessment.md +28 -0
- hardprompts/translation/code_translation.md +68 -0
- hardprompts/translation/dependency_suggestion.md +44 -0
- hardprompts/translation/test_translation.md +64 -0
- hardprompts/translation/translation_repair.md +59 -0
- icdev-0.0.3.dist-info/METADATA +909 -0
- icdev-0.0.3.dist-info/RECORD +1214 -0
- icdev-0.0.3.dist-info/WHEEL +5 -0
- icdev-0.0.3.dist-info/entry_points.txt +9 -0
- icdev-0.0.3.dist-info/licenses/LICENSE +201 -0
- icdev-0.0.3.dist-info/licenses/NOTICE +11 -0
- icdev-0.0.3.dist-info/top_level.txt +7 -0
- memory/MEMORY.md +52 -0
- memory/logs/2026-02-14.md +17 -0
- memory/logs/2026-03-03.md +2 -0
- memory/logs/__init__.py +1 -0
- tools/a2a/icdev_callback_client.py +210 -0
- tools/agent/cards/architect_card.json +29 -0
- tools/agent/cards/builder_card.json +34 -0
- tools/agent/cards/compliance_card.json +29 -0
- tools/agent/cards/connector_forge_card.json +49 -0
- tools/agent/cards/devsecops_zta_card.json +24 -0
- tools/agent/cards/knowledge_card.json +29 -0
- tools/agent/cards/monitor_card.json +29 -0
- tools/agent/cards/orchestrator_card.json +29 -0
- tools/agent/cards/requirements_analyst_card.json +24 -0
- tools/agent/cards/security_card.json +29 -0
- tools/agent/cards/simulation_card.json +24 -0
- tools/agent/cards/supply_chain_card.json +24 -0
- tools/analysis/__init__.py +1 -0
- tools/analysis/code_analyzer.py +770 -0
- tools/analysis/runtime_feedback.py +379 -0
- tools/analytics/__init__.py +2 -0
- tools/analytics/scorecard.py +538 -0
- tools/analytics/vsm_engine.py +612 -0
- tools/architecture/__init__.py +2 -0
- tools/architecture/adr_extractor.py +393 -0
- tools/audit/__init__.py +1 -0
- tools/audit/audit_logger.py +199 -0
- tools/audit/audit_query.py +153 -0
- tools/audit/decision_recorder.py +73 -0
- tools/audit_engine/__init__.py +12 -0
- tools/audit_engine/ai_advisor.py +906 -0
- tools/audit_engine/cli.py +286 -0
- tools/audit_engine/comparator.py +305 -0
- tools/audit_engine/eject_scaffolder.py +399 -0
- tools/audit_engine/engine.py +614 -0
- tools/audit_engine/git_fetcher.py +341 -0
- tools/audit_engine/regime_loader.py +200 -0
- tools/audit_engine/regime_updater.py +325 -0
- tools/audit_engine/report_card.py +289 -0
- tools/audit_engine/scanner.py +684 -0
- tools/audit_engine/self_heal.py +1042 -0
- tools/ci/__init__.py +2 -0
- tools/ci/connectors/__init__.py +2 -0
- tools/ci/connectors/base_connector.py +80 -0
- tools/ci/connectors/connector_registry.py +188 -0
- tools/ci/connectors/mattermost_connector.py +159 -0
- tools/ci/connectors/slack_connector.py +197 -0
- tools/ci/core/__init__.py +2 -0
- tools/ci/core/air_gap_detector.py +115 -0
- tools/ci/core/comment_handler.py +192 -0
- tools/ci/core/conversation_manager.py +480 -0
- tools/ci/core/event_envelope.py +500 -0
- tools/ci/core/event_router.py +444 -0
- tools/ci/core/failure_parser.py +397 -0
- tools/ci/core/recovery_engine.py +527 -0
- tools/ci/gate_enforcer.py +361 -0
- tools/ci/modules/__init__.py +2 -0
- tools/ci/modules/agent.py +271 -0
- tools/ci/modules/git_ops.py +175 -0
- tools/ci/modules/state.py +117 -0
- tools/ci/modules/vcs.py +303 -0
- tools/ci/modules/workflow_ops.py +295 -0
- tools/ci/modules/worktree.py +337 -0
- tools/ci/pipeline_config_generator.py +558 -0
- tools/ci/pr_intelligence.py +485 -0
- tools/ci/triggers/__init__.py +2 -0
- tools/ci/triggers/gitlab_task_monitor.py +327 -0
- tools/ci/triggers/poll_trigger.py +237 -0
- tools/ci/triggers/webhook_server.py +356 -0
- tools/ci/workflows/__init__.py +2 -0
- tools/ci/workflows/icdev_build.py +140 -0
- tools/ci/workflows/icdev_comply.py +284 -0
- tools/ci/workflows/icdev_document.py +152 -0
- tools/ci/workflows/icdev_e2e.py +188 -0
- tools/ci/workflows/icdev_patch.py +186 -0
- tools/ci/workflows/icdev_plan.py +202 -0
- tools/ci/workflows/icdev_plan_build.py +41 -0
- tools/ci/workflows/icdev_plan_build_test.py +46 -0
- tools/ci/workflows/icdev_plan_build_test_review.py +47 -0
- tools/ci/workflows/icdev_review.py +126 -0
- tools/ci/workflows/icdev_sdlc.py +261 -0
- tools/ci/workflows/icdev_test.py +240 -0
- tools/cli/__init__.py +1 -0
- tools/cli/output_formatter.py +756 -0
- tools/cloudforge/__init__.py +12 -0
- tools/cloudforge/airgap/__init__.py +2 -0
- tools/cloudforge/airgap/il_classifier.py +70 -0
- tools/cloudforge/airgap/offline_validator.py +42 -0
- tools/cloudforge/airgap/shift_emulator.py +155 -0
- tools/cloudforge/airgap/sneakernet.py +91 -0
- tools/cloudforge/cd_hub/__init__.py +2 -0
- tools/cloudforge/cd_hub/canary_deployer.py +88 -0
- tools/cloudforge/cd_hub/gitops_renderer.py +123 -0
- tools/cloudforge/cd_hub/hub_controller.py +143 -0
- tools/cloudforge/cd_hub/pipeline_bridge.py +30 -0
- tools/cloudforge/cd_hub/rollback_engine.py +29 -0
- tools/cloudforge/cd_hub/spoke_agent.py +51 -0
- tools/cloudforge/compliance/__init__.py +2 -0
- tools/cloudforge/compliance/ato_accelerator.py +272 -0
- tools/cloudforge/compliance/control_inheritor.py +127 -0
- tools/cloudforge/compliance/evidence_generator.py +129 -0
- tools/cloudforge/compliance/poam_bridge.py +41 -0
- tools/cloudforge/compliance/ssp_bridge.py +52 -0
- tools/cloudforge/compliance/stig_bridge.py +41 -0
- tools/cloudforge/container_forge/__init__.py +2 -0
- tools/cloudforge/container_forge/bigbang_renderer.py +85 -0
- tools/cloudforge/container_forge/hardener.py +169 -0
- tools/cloudforge/container_forge/image_scanner_bridge.py +33 -0
- tools/cloudforge/container_forge/runtime_policy.py +87 -0
- tools/cloudforge/container_forge/sbom_bridge.py +42 -0
- tools/cloudforge/finops/__init__.py +2 -0
- tools/cloudforge/finops/anomaly_detector.py +78 -0
- tools/cloudforge/finops/budget_tracker.py +96 -0
- tools/cloudforge/finops/chargeback.py +69 -0
- tools/cloudforge/finops/cost_collector.py +141 -0
- tools/cloudforge/finops/optimizer.py +55 -0
- tools/cloudforge/hybrid/__init__.py +2 -0
- tools/cloudforge/hybrid/connection_manager.py +141 -0
- tools/cloudforge/hybrid/dns_federator.py +56 -0
- tools/cloudforge/hybrid/health_monitor.py +108 -0
- tools/cloudforge/hybrid/identity_federator.py +53 -0
- tools/cloudforge/hybrid/network_bridge.py +68 -0
- tools/cloudforge/hybrid/topology_manager.py +147 -0
- tools/cloudforge/hybrid/workload_abstractor.py +92 -0
- tools/cloudforge/iac/__init__.py +2 -0
- tools/cloudforge/iac/drift_detector.py +154 -0
- tools/cloudforge/iac/module_library.py +265 -0
- tools/cloudforge/iac/opentofu_adapter.py +89 -0
- tools/cloudforge/iac/pulumi_renderer.py +292 -0
- tools/cloudforge/iac/state_backend.py +146 -0
- tools/cloudforge/iac/terraform_renderer.py +626 -0
- tools/cloudforge/landing_zone/__init__.py +2 -0
- tools/cloudforge/landing_zone/blueprint_loader.py +98 -0
- tools/cloudforge/landing_zone/blueprint_validator.py +113 -0
- tools/cloudforge/landing_zone/zone_provisioner.py +306 -0
- tools/cloudforge/landing_zone/zone_state.py +143 -0
- tools/cloudforge/mbse_thread/__init__.py +2 -0
- tools/cloudforge/mbse_thread/ato_thread_weaver.py +111 -0
- tools/cloudforge/mbse_thread/control_tracer.py +68 -0
- tools/cloudforge/mbse_thread/system_boundary.py +83 -0
- tools/cloudforge/metastore/__init__.py +2 -0
- tools/cloudforge/metastore/dependency_graph.py +202 -0
- tools/cloudforge/metastore/discovery.py +192 -0
- tools/cloudforge/metastore/registry.py +185 -0
- tools/cloudforge/metastore/rto_tracker.py +92 -0
- tools/cloudforge/metastore/runbook_linker.py +82 -0
- tools/cloudforge/migration/__init__.py +2 -0
- tools/cloudforge/migration/assessor.py +187 -0
- tools/cloudforge/migration/cutover_orchestrator.py +117 -0
- tools/cloudforge/migration/databridge_bridge.py +92 -0
- tools/cloudforge/migration/planner.py +98 -0
- tools/cloudforge/migration/risk_scorer.py +97 -0
- tools/cloudforge/migration/validation_runner.py +45 -0
- tools/cloudforge/migration/workload_inventory.py +107 -0
- tools/cloudforge/provider.py +319 -0
- tools/cloudforge/providers/__init__.py +2 -0
- tools/cloudforge/providers/aws_commercial.py +92 -0
- tools/cloudforge/providers/aws_govcloud.py +229 -0
- tools/cloudforge/providers/aws_secret.py +83 -0
- tools/cloudforge/providers/azure_commercial.py +80 -0
- tools/cloudforge/providers/azure_gov.py +91 -0
- tools/cloudforge/providers/azure_secret.py +71 -0
- tools/cloudforge/providers/gcp.py +102 -0
- tools/cloudforge/providers/oci.py +102 -0
- tools/cloudforge/registry.py +140 -0
- tools/cloudforge/runbooks/__init__.py +2 -0
- tools/cloudforge/runbooks/ai_generator.py +119 -0
- tools/cloudforge/runbooks/dag_validator.py +219 -0
- tools/cloudforge/runbooks/engine.py +470 -0
- tools/cloudforge/runbooks/models.py +99 -0
- tools/cloudforge/runbooks/snippet_library.py +158 -0
- tools/cloudforge/runbooks/template_loader.py +122 -0
- tools/cloudforge/runbooks/visualization.py +108 -0
- tools/cloudforge/siem/__init__.py +2 -0
- tools/cloudforge/siem/alert_rules.py +86 -0
- tools/cloudforge/siem/correlation_engine.py +61 -0
- tools/cloudforge/siem/log_aggregator.py +113 -0
- tools/cloudforge/siem/siem_dashboard_data.py +28 -0
- tools/cloudforge/supply_chain/__init__.py +2 -0
- tools/cloudforge/supply_chain/bridge.py +33 -0
- tools/cloudforge/supply_chain/iac_dependency_scanner.py +36 -0
- tools/cloudforge/supply_chain/provider_trust_scorer.py +54 -0
- tools/compat/__init__.py +21 -0
- tools/compat/cli_harmonizer.py +251 -0
- tools/compat/datetime_utils.py +18 -0
- tools/compat/db_utils.py +190 -0
- tools/compat/platform_utils.py +123 -0
- tools/compliance/__init__.py +1 -0
- tools/compliance/accountability_manager.py +391 -0
- tools/compliance/ai_accountability_audit.py +287 -0
- tools/compliance/ai_impact_assessor.py +267 -0
- tools/compliance/ai_incident_response.py +295 -0
- tools/compliance/ai_inventory_manager.py +233 -0
- tools/compliance/ai_reassessment_scheduler.py +250 -0
- tools/compliance/ai_transparency_audit.py +247 -0
- tools/compliance/atlas_assessor.py +276 -0
- tools/compliance/atlas_report_generator.py +1199 -0
- tools/compliance/base_assessor.py +591 -0
- tools/compliance/cato_live_engine.py +607 -0
- tools/compliance/cato_monitor.py +1371 -0
- tools/compliance/cato_scheduler.py +698 -0
- tools/compliance/cjis_assessor.py +76 -0
- tools/compliance/classification_manager.py +1340 -0
- tools/compliance/cmmc_assessor.py +1478 -0
- tools/compliance/cmmc_report_generator.py +1087 -0
- tools/compliance/compliance_detector.py +452 -0
- tools/compliance/compliance_exporter.py +418 -0
- tools/compliance/compliance_status.py +810 -0
- tools/compliance/control_mapper.py +488 -0
- tools/compliance/crosswalk_engine.py +1208 -0
- tools/compliance/cssp_assessor.py +1032 -0
- tools/compliance/cssp_evidence_collector.py +716 -0
- tools/compliance/cssp_report_generator.py +1103 -0
- tools/compliance/cui_marker.py +387 -0
- tools/compliance/diagram_validator.py +599 -0
- tools/compliance/emass/__init__.py +2 -0
- tools/compliance/emass/emass_client.py +822 -0
- tools/compliance/emass/emass_export.py +758 -0
- tools/compliance/emass/emass_sync.py +807 -0
- tools/compliance/eu_ai_act_classifier.py +193 -0
- tools/compliance/evidence_collector.py +459 -0
- tools/compliance/fairness_assessor.py +310 -0
- tools/compliance/fedramp_20x_ksi_emitter.py +692 -0
- tools/compliance/fedramp_assessor.py +1795 -0
- tools/compliance/fedramp_authorization_packager.py +137 -0
- tools/compliance/fedramp_ksi_generator.py +349 -0
- tools/compliance/fedramp_report_generator.py +1115 -0
- tools/compliance/fips199_categorizer.py +869 -0
- tools/compliance/fips200_validator.py +304 -0
- tools/compliance/firmware_sbom.py +646 -0
- tools/compliance/gao_ai_assessor.py +228 -0
- tools/compliance/gao_evidence_builder.py +302 -0
- tools/compliance/hipaa_assessor.py +78 -0
- tools/compliance/hitrust_assessor.py +49 -0
- tools/compliance/incident_response_plan.py +705 -0
- tools/compliance/inheritance_engine.py +693 -0
- tools/compliance/iso27001_assessor.py +92 -0
- tools/compliance/iso42001_assessor.py +114 -0
- tools/compliance/ivv_assessor.py +2314 -0
- tools/compliance/ivv_report_generator.py +1649 -0
- tools/compliance/model_card_generator.py +291 -0
- tools/compliance/mosa_assessor.py +117 -0
- tools/compliance/multi_regime_assessor.py +441 -0
- tools/compliance/narrative_generator.py +1012 -0
- tools/compliance/narrative_quality_gate.py +701 -0
- tools/compliance/narrative_workflow.py +814 -0
- tools/compliance/nist_800_207_assessor.py +191 -0
- tools/compliance/nist_ai_600_1_assessor.py +185 -0
- tools/compliance/nist_ai_rmf_assessor.py +110 -0
- tools/compliance/nist_lookup.py +244 -0
- tools/compliance/omb_m25_21_assessor.py +225 -0
- tools/compliance/omb_m26_04_assessor.py +185 -0
- tools/compliance/oscal_catalog_adapter.py +395 -0
- tools/compliance/oscal_generator.py +2157 -0
- tools/compliance/oscal_tools.py +1182 -0
- tools/compliance/oscal_validator.py +692 -0
- tools/compliance/owasp_agentic_assessor.py +227 -0
- tools/compliance/owasp_asi_assessor.py +197 -0
- tools/compliance/owasp_llm_assessor.py +245 -0
- tools/compliance/pci_dss_assessor.py +80 -0
- tools/compliance/pi_compliance_tracker.py +1447 -0
- tools/compliance/poam_generator.py +388 -0
- tools/compliance/resolve_marking.py +272 -0
- tools/compliance/sbd_assessor.py +2070 -0
- tools/compliance/sbd_report_generator.py +1223 -0
- tools/compliance/sbom_generator.py +993 -0
- tools/compliance/siem_config_generator.py +661 -0
- tools/compliance/slsa_attestation_generator.py +479 -0
- tools/compliance/soc2_assessor.py +77 -0
- tools/compliance/ssp_generator.py +556 -0
- tools/compliance/stig_checker.py +712 -0
- tools/compliance/swft_evidence_bundler.py +326 -0
- tools/compliance/system_card_generator.py +303 -0
- tools/compliance/template_exchange.py +513 -0
- tools/compliance/traceability_matrix.py +1268 -0
- tools/compliance/universal_classification_manager.py +1159 -0
- tools/compliance/xacta/__init__.py +2 -0
- tools/compliance/xacta/xacta_client.py +438 -0
- tools/compliance/xacta/xacta_export.py +546 -0
- tools/compliance/xacta/xacta_sync.py +322 -0
- tools/compliance/xai_assessor.py +231 -0
- tools/core/__init__.py +2 -0
- tools/core/circuit_breaker.py +353 -0
- tools/core/compliance_sidecar.py +344 -0
- tools/core/container.py +110 -0
- tools/core/errors.py +256 -0
- tools/core/feature_flags.py +311 -0
- tools/core/task_dlq.py +350 -0
- tools/dashboard/__init__.py +2 -0
- tools/dashboard/app.py +6288 -0
- tools/dashboard/templates/agent_evolution.html +287 -0
- tools/dashboard/templates/agents/list.html +71 -0
- tools/dashboard/templates/agents.html +132 -0
- tools/dashboard/templates/architecture.html +289 -0
- tools/dashboard/templates/ato_simulator.html +170 -0
- tools/dashboard/templates/audit_engine.html +844 -0
- tools/dashboard/templates/base.html +236 -0
- tools/dashboard/templates/cato_live.html +116 -0
- tools/dashboard/templates/cloudforge.html +195 -0
- tools/dashboard/templates/cloudforge_finops.html +111 -0
- tools/dashboard/templates/cloudforge_hybrid.html +122 -0
- tools/dashboard/templates/cloudforge_metastore.html +234 -0
- tools/dashboard/templates/cloudforge_migration.html +87 -0
- tools/dashboard/templates/cloudforge_runbooks.html +201 -0
- tools/dashboard/templates/cloudforge_siem.html +94 -0
- tools/dashboard/templates/compliance_accel.html +292 -0
- tools/dashboard/templates/crashes.html +122 -0
- tools/dashboard/templates/databridge.html +305 -0
- tools/dashboard/templates/databridge_analytics.html +195 -0
- tools/dashboard/templates/databridge_mapping.html +345 -0
- tools/dashboard/templates/databridge_messaging.html +321 -0
- tools/dashboard/templates/decisions.html +258 -0
- tools/dashboard/templates/devices.html +151 -0
- tools/dashboard/templates/devsecops_maturity.html +278 -0
- tools/dashboard/templates/edge_ai.html +128 -0
- tools/dashboard/templates/firmware.html +120 -0
- tools/dashboard/templates/firmware_sbom.html +193 -0
- tools/dashboard/templates/forge_hub.html +196 -0
- tools/dashboard/templates/forge_studio.html +379 -0
- tools/dashboard/templates/forge_studio_analytics.html +360 -0
- tools/dashboard/templates/forge_studio_builder.html +1637 -0
- tools/dashboard/templates/forge_studio_compliance.html +310 -0
- tools/dashboard/templates/forge_studio_deploy.html +573 -0
- tools/dashboard/templates/forge_studio_enterprise.html +888 -0
- tools/dashboard/templates/forge_studio_marketplace.html +502 -0
- tools/dashboard/templates/forge_studio_workflow.html +696 -0
- tools/dashboard/templates/golden_path.html +175 -0
- tools/dashboard/templates/govcon.html +280 -0
- tools/dashboard/templates/harness.html +148 -0
- tools/dashboard/templates/index.html +207 -0
- tools/dashboard/templates/intelligence.html +336 -0
- tools/dashboard/templates/knowledge/index.html +190 -0
- tools/dashboard/templates/knowledge_graph.html +739 -0
- tools/dashboard/templates/login.html +51 -0
- tools/dashboard/templates/marketplace.html +336 -0
- tools/dashboard/templates/marketplace_admin.html +247 -0
- tools/dashboard/templates/missions.html +403 -0
- tools/dashboard/templates/narratives.html +154 -0
- tools/dashboard/templates/pr_intelligence.html +151 -0
- tools/dashboard/templates/proposals/detail.html +300 -0
- tools/dashboard/templates/proposals/list.html +52 -0
- tools/dashboard/templates/proposals/sam_detail.html +132 -0
- tools/dashboard/templates/proposals/section_detail.html +375 -0
- tools/dashboard/templates/research.html +222 -0
- tools/dashboard/templates/resilience.html +300 -0
- tools/dashboard/templates/scorecard.html +162 -0
- tools/dashboard/templates/simulator.html +131 -0
- tools/dashboard/templates/template_exchange.html +147 -0
- tools/dashboard/templates/thread_heatmap.html +151 -0
- tools/dashboard/templates/threat_model.html +195 -0
- tools/dashboard/templates/vsm.html +141 -0
- tools/dashboard/templates/writeguard.html +277 -0
- tools/databridge/__init__.py +5 -0
- tools/databridge/agent/__init__.py +2 -0
- tools/databridge/agent/daemon.py +227 -0
- tools/databridge/agent/tunnel.py +101 -0
- tools/databridge/agent/ws_relay.py +91 -0
- tools/databridge/analytics.py +167 -0
- tools/databridge/arrow_pipeline.py +327 -0
- tools/databridge/connection_manager.py +424 -0
- tools/databridge/connector.py +331 -0
- tools/databridge/connectors/__init__.py +2 -0
- tools/databridge/connectors/argocd_connector.py +160 -0
- tools/databridge/connectors/avro_connector.py +203 -0
- tools/databridge/connectors/azure_blob.py +63 -0
- tools/databridge/connectors/cdc_connector.py +205 -0
- tools/databridge/connectors/csv_connector.py +172 -0
- tools/databridge/connectors/datadog_connector.py +153 -0
- tools/databridge/connectors/discord_messaging.py +215 -0
- tools/databridge/connectors/dynamics365.py +151 -0
- tools/databridge/connectors/elasticsearch_connector.py +145 -0
- tools/databridge/connectors/email_base.py +114 -0
- tools/databridge/connectors/excel_connector.py +175 -0
- tools/databridge/connectors/fsspec_base.py +300 -0
- tools/databridge/connectors/gcs.py +53 -0
- tools/databridge/connectors/github_connector.py +138 -0
- tools/databridge/connectors/gitlab_connector.py +132 -0
- tools/databridge/connectors/gmail_connector.py +182 -0
- tools/databridge/connectors/hdfs.py +57 -0
- tools/databridge/connectors/health_base.py +401 -0
- tools/databridge/connectors/hubspot.py +124 -0
- tools/databridge/connectors/imap_connector.py +171 -0
- tools/databridge/connectors/jenkins_connector.py +138 -0
- tools/databridge/connectors/jira_connector.py +86 -0
- tools/databridge/connectors/json_connector.py +184 -0
- tools/databridge/connectors/kafka_connector.py +246 -0
- tools/databridge/connectors/kinesis_connector.py +238 -0
- tools/databridge/connectors/local_fs.py +30 -0
- tools/databridge/connectors/matrix.py +197 -0
- tools/databridge/connectors/mattermost_messaging.py +184 -0
- tools/databridge/connectors/messaging_base.py +172 -0
- tools/databridge/connectors/mssql.py +63 -0
- tools/databridge/connectors/mysql.py +57 -0
- tools/databridge/connectors/netsuite.py +170 -0
- tools/databridge/connectors/o365_mail.py +196 -0
- tools/databridge/connectors/oracle.py +65 -0
- tools/databridge/connectors/pagerduty_connector.py +162 -0
- tools/databridge/connectors/parquet_connector.py +131 -0
- tools/databridge/connectors/postgresql.py +58 -0
- tools/databridge/connectors/s3.py +65 -0
- tools/databridge/connectors/saas_base.py +198 -0
- tools/databridge/connectors/salesforce.py +126 -0
- tools/databridge/connectors/sap.py +89 -0
- tools/databridge/connectors/servicenow.py +60 -0
- tools/databridge/connectors/signal_messaging.py +150 -0
- tools/databridge/connectors/slack_messaging.py +203 -0
- tools/databridge/connectors/smtp_connector.py +126 -0
- tools/databridge/connectors/soap_base.py +258 -0
- tools/databridge/connectors/splunk_connector.py +171 -0
- tools/databridge/connectors/sql_base.py +310 -0
- tools/databridge/connectors/sqlite_connector.py +76 -0
- tools/databridge/connectors/teams.py +148 -0
- tools/databridge/connectors/telegram.py +192 -0
- tools/databridge/connectors/whatsapp.py +137 -0
- tools/databridge/data_profiler.py +99 -0
- tools/databridge/forge/__init__.py +6 -0
- tools/databridge/forge/base_selector.py +150 -0
- tools/databridge/forge/code_generator.py +206 -0
- tools/databridge/forge/community_hub.py +539 -0
- tools/databridge/forge/forge_agent.py +306 -0
- tools/databridge/forge/import_handler.py +133 -0
- tools/databridge/forge/integration_tester.py +127 -0
- tools/databridge/forge/marketplace_publisher.py +164 -0
- tools/databridge/forge/promoter.py +159 -0
- tools/databridge/forge/sandbox_manager.py +257 -0
- tools/databridge/forge/spec_parser.py +358 -0
- tools/databridge/forge/static_validator.py +363 -0
- tools/databridge/forge/templates/__init__.py +591 -0
- tools/databridge/format_converter.py +188 -0
- tools/databridge/mapping_engine.py +348 -0
- tools/databridge/messaging/__init__.py +5 -0
- tools/databridge/messaging/agent_bridge.py +254 -0
- tools/databridge/messaging/message_envelope.py +111 -0
- tools/databridge/messaging/message_logger.py +204 -0
- tools/databridge/messaging/messaging_daemon.py +326 -0
- tools/databridge/messaging/oauth2_manager.py +411 -0
- tools/databridge/pii_detector.py +221 -0
- tools/databridge/registry.py +352 -0
- tools/databridge/relay_server.py +105 -0
- tools/databridge/scale/__init__.py +16 -0
- tools/databridge/scale/backpressure.py +134 -0
- tools/databridge/scale/chunked_pipeline.py +169 -0
- tools/databridge/scale/connection_pool.py +293 -0
- tools/databridge/scale/engine.py +492 -0
- tools/databridge/scale/worker_pool.py +140 -0
- tools/databridge/scale/write_batcher.py +250 -0
- tools/databridge/schema_engine.py +324 -0
- tools/databridge/stream_manager.py +225 -0
- tools/databridge/sync_engine.py +411 -0
- tools/databridge/transforms.py +302 -0
- tools/db/__init__.py +1 -0
- tools/db/backup.py +312 -0
- tools/db/backup_manager.py +832 -0
- tools/db/init_icdev_db.py +7753 -0
- tools/db/init_sparkpilot_db.py +431 -0
- tools/db/migrate.py +177 -0
- tools/db/migrate_innovation_audit.py +165 -0
- tools/db/migration_runner.py +548 -0
- tools/db/migrations/001_baseline/meta.json +9 -0
- tools/db/migrations/001_baseline/up.py +67 -0
- tools/db/migrations/002_memory_enhancements/down.sql +8 -0
- tools/db/migrations/002_memory_enhancements/meta.json +9 -0
- tools/db/migrations/002_memory_enhancements/up.py +119 -0
- tools/db/migrations/003_dev_profiles/meta.json +8 -0
- tools/db/migrations/003_dev_profiles/up.py +93 -0
- tools/db/migrations/004_innovation_engine/down.py +19 -0
- tools/db/migrations/004_innovation_engine/up.py +227 -0
- tools/db/migrations/005_phase_37_ai_security/down.py +19 -0
- tools/db/migrations/005_phase_37_ai_security/up.py +257 -0
- tools/db/migrations/006_phase_36_evolution/down.py +21 -0
- tools/db/migrations/006_phase_36_evolution/up.py +323 -0
- tools/db/migrations/007_phase_38_cloud/down.py +14 -0
- tools/db/migrations/007_phase_38_cloud/up.py +110 -0
- tools/db/migrations/008_phase36_37_integration/up.py +55 -0
- tools/db/migrations/__init__.py +2 -0
- tools/db/pg_migrate.py +642 -0
- tools/db/storage.py +1080 -0
- tools/decisions/__init__.py +2 -0
- tools/decisions/dmn_engine.py +695 -0
- tools/devsecops/__init__.py +2 -0
- tools/devsecops/attestation_manager.py +449 -0
- tools/devsecops/network_segmentation_generator.py +604 -0
- tools/devsecops/pdp_config_generator.py +1246 -0
- tools/devsecops/pipeline_security_generator.py +475 -0
- tools/devsecops/policy_generator.py +644 -0
- tools/devsecops/profile_manager.py +374 -0
- tools/devsecops/service_mesh_generator.py +1063 -0
- tools/devsecops/zta_maturity_scorer.py +355 -0
- tools/devsecops/zta_terraform_generator.py +1301 -0
- tools/edge_ai/__init__.py +2 -0
- tools/edge_ai/model_manager.py +200 -0
- tools/embedded/__init__.py +2 -0
- tools/embedded/cmake_generator.py +318 -0
- tools/embedded/crash_analyzer.py +191 -0
- tools/embedded/nl_to_firmware.py +277 -0
- tools/events/__init__.py +1 -0
- tools/events/event_bus.py +199 -0
- tools/finetune/pair_generator.py +832 -0
- tools/fleet/__init__.py +2 -0
- tools/fleet/device_registry.py +148 -0
- tools/fleet/ota_manager.py +153 -0
- tools/forge_studio/__init__.py +13 -0
- tools/forge_studio/analytics/__init__.py +0 -0
- tools/forge_studio/analytics/process_miner.py +383 -0
- tools/forge_studio/audit.py +183 -0
- tools/forge_studio/blueprint/__init__.py +2 -0
- tools/forge_studio/blueprint/build_tracker.py +317 -0
- tools/forge_studio/blueprint/export_engine.py +441 -0
- tools/forge_studio/blueprint/parent_client.py +335 -0
- tools/forge_studio/catalog/__init__.py +2 -0
- tools/forge_studio/catalog/component_registry.py +176 -0
- tools/forge_studio/catalog/schema_validator.py +193 -0
- tools/forge_studio/compliance/__init__.py +1 -0
- tools/forge_studio/compliance/compliance_wiring.py +554 -0
- tools/forge_studio/deploy/__init__.py +1 -0
- tools/forge_studio/deploy/airgap_packager.py +466 -0
- tools/forge_studio/deploy/deploy_engine.py +1792 -0
- tools/forge_studio/deploy/env_manager.py +431 -0
- tools/forge_studio/eject/__init__.py +2 -0
- tools/forge_studio/eject/docker_compose_generator.py +237 -0
- tools/forge_studio/eject/eject_engine.py +230 -0
- tools/forge_studio/eject/expo_scaffolder.py +303 -0
- tools/forge_studio/eject/nextjs_scaffolder.py +338 -0
- tools/forge_studio/enterprise/__init__.py +0 -0
- tools/forge_studio/enterprise/custom_frameworks.py +826 -0
- tools/forge_studio/enterprise/hardening_engine.py +1530 -0
- tools/forge_studio/enterprise/sso_manager.py +718 -0
- tools/forge_studio/enterprise/whitelabel_engine.py +887 -0
- tools/forge_studio/formula/__init__.py +0 -0
- tools/forge_studio/formula/expression_engine.py +562 -0
- tools/forge_studio/formula/formula_registry.py +265 -0
- tools/forge_studio/generator/__init__.py +2 -0
- tools/forge_studio/generator/app_generator.py +584 -0
- tools/forge_studio/generator/complexity_detector.py +368 -0
- tools/forge_studio/generator/prompt_templates.py +104 -0
- tools/forge_studio/generator/spec_builder.py +192 -0
- tools/forge_studio/intake_bridge.py +898 -0
- tools/forge_studio/marketplace/__init__.py +0 -0
- tools/forge_studio/marketplace/component_hub.py +428 -0
- tools/forge_studio/models.py +369 -0
- tools/forge_studio/renderer/__init__.py +2 -0
- tools/forge_studio/renderer/json_render_engine.py +623 -0
- tools/forge_studio/renderer/layout_engine.py +214 -0
- tools/forge_studio/renderer/rn_component_map.py +182 -0
- tools/forge_studio/supabase/__init__.py +2 -0
- tools/forge_studio/supabase/auth_generator.py +283 -0
- tools/forge_studio/supabase/migration_generator.py +93 -0
- tools/forge_studio/supabase/schema_generator.py +281 -0
- tools/forge_studio/tenant_manager.py +387 -0
- tools/forge_studio/workflow/__init__.py +2 -0
- tools/forge_studio/workflow/bpmn_adapter.py +489 -0
- tools/govcon/draft_orchestrator.py +1151 -0
- tools/govcon/engine_enrichment.py +373 -0
- tools/govcon/knowledge_base.py +487 -0
- tools/govcon/knowledge_ingestion.py +510 -0
- tools/govcon/sam_scanner.py +754 -0
- tools/harness/__init__.py +6 -0
- tools/harness/exit_criteria_evaluator.py +231 -0
- tools/harness/maturity_assessor.py +347 -0
- tools/harness/scaffold_harness.py +416 -0
- tools/harness/trace_analyzer.py +281 -0
- tools/infra/__init__.py +1 -0
- tools/infra/ansible_generator.py +867 -0
- tools/infra/dockerfile_generator.py +359 -0
- tools/infra/infra_status.py +384 -0
- tools/infra/ironbank_metadata_generator.py +403 -0
- tools/infra/k8s_generator.py +1000 -0
- tools/infra/pipeline_generator.py +830 -0
- tools/infra/rollback.py +389 -0
- tools/infra/terraform_generator.py +1140 -0
- tools/infra/terraform_generator_azure.py +1252 -0
- tools/infra/terraform_generator_gcp.py +951 -0
- tools/infra/terraform_generator_ibm.py +359 -0
- tools/infra/terraform_generator_oci.py +918 -0
- tools/infra/terraform_generator_onprem.py +318 -0
- tools/knowledge/__init__.py +1 -0
- tools/knowledge/knowledge_ingest.py +281 -0
- tools/knowledge/pattern_detector.py +681 -0
- tools/knowledge/recommendation_engine.py +449 -0
- tools/knowledge/self_heal_analyzer.py +492 -0
- tools/knowledge_graph/__init__.py +2 -0
- tools/knowledge_graph/graph_rag.py +498 -0
- tools/knowledge_graph/ingester.py +406 -0
- tools/knowledge_graph/insight_generator.py +369 -0
- tools/knowledge_graph/text_network.py +832 -0
- tools/llm/__init__.py +72 -0
- tools/llm/anthropic_provider.py +170 -0
- tools/llm/azure_openai_provider.py +338 -0
- tools/llm/bedrock_provider.py +315 -0
- tools/llm/embedding_provider.py +438 -0
- tools/llm/gemini_provider.py +381 -0
- tools/llm/ibm_watsonx_provider.py +231 -0
- tools/llm/oci_genai_provider.py +462 -0
- tools/llm/ollama_provider.py +350 -0
- tools/llm/openai_provider.py +225 -0
- tools/llm/prompt_registry.py +447 -0
- tools/llm/provider.py +355 -0
- tools/llm/provider_sdk.py +175 -0
- tools/llm/router.py +1124 -0
- tools/llm/semantic_cache.py +394 -0
- tools/llm/vertex_ai_provider.py +374 -0
- tools/maintenance/__init__.py +2 -0
- tools/maintenance/dependency_scanner.py +1016 -0
- tools/maintenance/maintenance_auditor.py +804 -0
- tools/maintenance/remediation_engine.py +957 -0
- tools/maintenance/vulnerability_checker.py +978 -0
- tools/manifest.md +1066 -0
- tools/marketplace/asset_installer.py +639 -0
- tools/marketplace/feedback_validator.py +359 -0
- tools/marketplace/license_client.py +458 -0
- tools/marketplace/module_crypto.py +544 -0
- tools/marketplace/module_runtime.py +236 -0
- tools/marketplace/token_store.py +264 -0
- tools/mbse/__init__.py +3 -0
- tools/mbse/des_assessor.py +1173 -0
- tools/mbse/des_report_generator.py +787 -0
- tools/mbse/diagram_extractor.py +792 -0
- tools/mbse/digital_thread.py +1650 -0
- tools/mbse/model_code_generator.py +1115 -0
- tools/mbse/model_control_mapper.py +410 -0
- tools/mbse/pi_model_tracker.py +1079 -0
- tools/mbse/reqif_parser.py +1468 -0
- tools/mbse/sync_engine.py +1789 -0
- tools/mbse/thread_heatmap.py +445 -0
- tools/mbse/xmi_parser.py +1558 -0
- tools/mcp/builder_server.py +64 -0
- tools/mcp/compliance_server.py +64 -0
- tools/mcp/connector_forge_server.py +155 -0
- tools/mcp/core_server.py +64 -0
- tools/mcp/devsecops_server.py +11 -0
- tools/mcp/devsecops_zta_server.py +64 -0
- tools/mcp/knowledge_server.py +64 -0
- tools/mcp/monitor_server.py +64 -0
- tools/mcp/ops_server.py +300 -0
- tools/mcp/requirements_analyst_server.py +64 -0
- tools/mcp/requirements_server.py +11 -0
- tools/mcp/security_server.py +64 -0
- tools/mcp/simulation_server.py +64 -0
- tools/mcp/supply_chain_server.py +64 -0
- tools/mcp/tool_registry.py +299 -0
- tools/memory/__init__.py +2 -0
- tools/memory/auto_capture.py +346 -0
- tools/memory/embed_memory.py +157 -0
- tools/memory/history_compressor.py +334 -0
- tools/memory/hybrid_search.py +235 -0
- tools/memory/maintenance_cron.py +288 -0
- tools/memory/memory_consolidation.py +439 -0
- tools/memory/memory_db.py +132 -0
- tools/memory/memory_read.py +101 -0
- tools/memory/memory_write.py +221 -0
- tools/memory/semantic_search.py +138 -0
- tools/memory/time_decay.py +434 -0
- tools/missions/__init__.py +2 -0
- tools/missions/mission_engine.py +459 -0
- tools/monitor/__init__.py +1 -0
- tools/monitor/alert_correlator.py +486 -0
- tools/monitor/auto_resolver.py +603 -0
- tools/monitor/health_checker.py +507 -0
- tools/monitor/heartbeat_daemon.py +779 -0
- tools/monitor/log_analyzer.py +507 -0
- tools/monitor/metric_collector.py +484 -0
- tools/mosa/__init__.py +10 -0
- tools/mosa/icd_generator.py +358 -0
- tools/mosa/modular_design_analyzer.py +682 -0
- tools/mosa/mosa_code_enforcer.py +348 -0
- tools/mosa/tsp_generator.py +265 -0
- tools/observability/__init__.py +100 -0
- tools/observability/genai_attributes.py +88 -0
- tools/observability/instrumentation.py +140 -0
- tools/observability/mlflow_exporter.py +193 -0
- tools/observability/otel_tracer.py +168 -0
- tools/observability/provenance/__init__.py +3 -0
- tools/observability/provenance/prov_recorder.py +322 -0
- tools/observability/shap/__init__.py +3 -0
- tools/observability/shap/agent_shap.py +274 -0
- tools/observability/sqlite_tracer.py +360 -0
- tools/observability/trace_context.py +205 -0
- tools/observability/tracer.py +230 -0
- tools/orchestration/__init__.py +1 -0
- tools/orchestration/peer_channels.py +254 -0
- tools/orchestration/saga_coordinator.py +390 -0
- tools/project/__init__.py +1 -0
- tools/project/manifest_loader.py +418 -0
- tools/project/project_create.py +350 -0
- tools/project/project_list.py +171 -0
- tools/project/project_scaffold.py +1715 -0
- tools/project/project_status.py +478 -0
- tools/project/session_context_builder.py +752 -0
- tools/project/validate_manifest.py +54 -0
- tools/rag/corrective_rag.py +582 -0
- tools/rag/source_registry.py +482 -0
- tools/requirements/__init__.py +1 -0
- tools/requirements/ai_governance_scorer.py +207 -0
- tools/requirements/boundary_analyzer.py +1281 -0
- tools/requirements/clarification_engine.py +605 -0
- tools/requirements/complexity_scorer.py +369 -0
- tools/requirements/consistency_analyzer.py +789 -0
- tools/requirements/constitution_manager.py +592 -0
- tools/requirements/decomposition_engine.py +764 -0
- tools/requirements/document_extractor.py +1002 -0
- tools/requirements/elicitation_techniques.py +508 -0
- tools/requirements/gap_detector.py +260 -0
- tools/requirements/intake_engine.py +2175 -0
- tools/requirements/prd_generator.py +839 -0
- tools/requirements/prd_validator.py +584 -0
- tools/requirements/readiness_scorer.py +302 -0
- tools/requirements/spec_organizer.py +1015 -0
- tools/requirements/spec_quality_checker.py +1083 -0
- tools/requirements/traceability_builder.py +566 -0
- tools/research/__init__.py +3 -0
- tools/research/academic_scanner.py +130 -0
- tools/research/build_buy_analyzer.py +229 -0
- tools/research/challenge_scorer.py +280 -0
- tools/research/community_scanner.py +174 -0
- tools/research/cross_engine_bridge.py +124 -0
- tools/research/dossier_generator.py +305 -0
- tools/research/landscape_scanner.py +315 -0
- tools/research/regulatory_scanner.py +248 -0
- tools/research/research_manager.py +469 -0
- tools/research/source_scanner.py +150 -0
- tools/research/vertical_loader.py +118 -0
- tools/saas/__init__.py +0 -0
- tools/saas/licensing/__init__.py +0 -0
- tools/saas/licensing/license_validator.py +345 -0
- tools/scaffold/__init__.py +2 -0
- tools/scaffold/golden_path.py +504 -0
- tools/security/__init__.py +1 -0
- tools/security/agent_output_validator.py +330 -0
- tools/security/agent_trust_scorer.py +652 -0
- tools/security/ai_bom_generator.py +718 -0
- tools/security/ai_telemetry_logger.py +469 -0
- tools/security/atlas_red_team.py +541 -0
- tools/security/code_pattern_scanner.py +382 -0
- tools/security/confabulation_detector.py +265 -0
- tools/security/container_scanner.py +489 -0
- tools/security/dependency_auditor.py +942 -0
- tools/security/endpoint_security_scanner.py +626 -0
- tools/security/mcp_tool_authorizer.py +242 -0
- tools/security/output_verifier.py +427 -0
- tools/security/prompt_injection_detector.py +737 -0
- tools/security/sast_runner.py +946 -0
- tools/security/secret_detector.py +376 -0
- tools/security/threat_modeler.py +678 -0
- tools/security/tool_chain_validator.py +357 -0
- tools/security/vuln_scanner.py +536 -0
- tools/simulation/__init__.py +2 -0
- tools/simulation/ato_simulator.py +517 -0
- tools/simulation/coa_generator.py +1539 -0
- tools/simulation/monte_carlo.py +745 -0
- tools/simulation/scenario_manager.py +1060 -0
- tools/simulation/simulation_engine.py +1091 -0
- tools/simulator/__init__.py +2 -0
- tools/simulator/sim_runner.py +272 -0
- tools/supply_chain/__init__.py +2 -0
- tools/supply_chain/cve_triager.py +690 -0
- tools/supply_chain/dependency_graph.py +630 -0
- tools/supply_chain/isa_manager.py +526 -0
- tools/supply_chain/scrm_assessor.py +531 -0
- tools/supply_chain/slsa_verifier.py +473 -0
- tools/testing/__init__.py +2 -0
- tools/testing/acceptance_validator.py +411 -0
- tools/testing/api_surface_extractor.py +749 -0
- tools/testing/claude_dir_validator.py +831 -0
- tools/testing/data_types.py +199 -0
- tools/testing/e2e_runner.py +715 -0
- tools/testing/fuzz_cli.py +306 -0
- tools/testing/health_check.py +483 -0
- tools/testing/platform_check.py +143 -0
- tools/testing/production_audit.py +1836 -0
- tools/testing/production_remediate.py +803 -0
- tools/testing/screenshot_validator.py +538 -0
- tools/testing/smoke_test.py +283 -0
- tools/testing/test_agent_models.py +117 -0
- tools/testing/test_orchestrator.py +957 -0
- tools/testing/utils.py +229 -0
- tools/writeguard/__init__.py +1 -0
- tools/writeguard/main.py +1 -0
- tools/writing/__init__.py +7 -0
- tools/writing/ai_content_detector.py +316 -0
- tools/writing/analysis_engine.py +454 -0
- tools/writing/batch_analyzer.py +276 -0
- tools/writing/coherence_analyzer.py +221 -0
- tools/writing/govcon_bridge.py +509 -0
- tools/writing/grammar_checker.py +270 -0
- tools/writing/plagiarism_detector.py +106 -0
- tools/writing/readability_scorer.py +201 -0
- tools/writing/rewriter.py +96 -0
- tools/writing/signal_registrar.py +167 -0
- tools/writing/snippet_manager.py +276 -0
- tools/writing/style_enforcer.py +220 -0
- tools/writing/style_guide_manager.py +438 -0
- tools/writing/tone_profiler.py +168 -0
|
@@ -0,0 +1,1002 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# CUI // SP-CTI
|
|
3
|
+
# Controlled by: Department of Defense
|
|
4
|
+
# CUI Category: CTI
|
|
5
|
+
# Distribution: D
|
|
6
|
+
# POC: SPARKPILOT System Administrator
|
|
7
|
+
"""Document upload and requirements extraction tool.
|
|
8
|
+
|
|
9
|
+
Uploads DoD documents (SOW, CDD, CONOPS, SRD, SRS, etc.) and images
|
|
10
|
+
(whiteboard photos, wireframe screenshots, architecture diagrams), extracts
|
|
11
|
+
text content using regex or vision LLM fallback, and identifies requirement
|
|
12
|
+
statements using shall/must/should/will patterns.
|
|
13
|
+
|
|
14
|
+
Supports PDF (with page-by-page vision fallback for scanned docs), DOCX,
|
|
15
|
+
TXT, MD, and image formats (PNG, JPG, GIF, WebP) with graceful fallback
|
|
16
|
+
for optional dependencies.
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
# Upload a document
|
|
20
|
+
python tools/requirements/document_extractor.py --session-id sess-abc \\
|
|
21
|
+
--upload --file-path /path/to/sow.pdf --document-type sow --json
|
|
22
|
+
|
|
23
|
+
# Upload an image (whiteboard photo, wireframe, etc.)
|
|
24
|
+
python tools/requirements/document_extractor.py --session-id sess-abc \\
|
|
25
|
+
--upload --file-path /path/to/whiteboard.png --document-type other --json
|
|
26
|
+
|
|
27
|
+
# Extract requirements from an uploaded document
|
|
28
|
+
python tools/requirements/document_extractor.py --document-id doc-abc \\
|
|
29
|
+
--extract --json
|
|
30
|
+
|
|
31
|
+
# Classify an uploaded image document
|
|
32
|
+
python tools/requirements/document_extractor.py --document-id doc-abc \\
|
|
33
|
+
--classify --json
|
|
34
|
+
|
|
35
|
+
# List all documents for a session
|
|
36
|
+
python tools/requirements/document_extractor.py --session-id sess-abc \\
|
|
37
|
+
--list --json
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
import argparse
|
|
41
|
+
import base64
|
|
42
|
+
import hashlib
|
|
43
|
+
import json
|
|
44
|
+
import logging
|
|
45
|
+
import os
|
|
46
|
+
import re
|
|
47
|
+
import sys
|
|
48
|
+
import uuid
|
|
49
|
+
from datetime import datetime
|
|
50
|
+
from pathlib import Path
|
|
51
|
+
from tools.db.storage import get_connection
|
|
52
|
+
|
|
53
|
+
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
54
|
+
if str(BASE_DIR) not in sys.path:
|
|
55
|
+
sys.path.insert(0, str(BASE_DIR))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
logger = logging.getLogger("sparkpilot.requirements.document_extractor")
|
|
59
|
+
|
|
60
|
+
# Image extensions supported for direct upload
|
|
61
|
+
IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".webp", ".tiff", ".bmp"}
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
from tools.audit.audit_logger import log_event
|
|
65
|
+
_HAS_AUDIT = True
|
|
66
|
+
except ImportError:
|
|
67
|
+
_HAS_AUDIT = False
|
|
68
|
+
def log_event(**kwargs): return -1
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _generate_id(prefix="doc"):
|
|
72
|
+
"""Generate a unique ID with prefix."""
|
|
73
|
+
return f"{prefix}-{uuid.uuid4().hex[:12]}"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
# File reading helpers
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
def _compute_file_hash(file_path):
|
|
81
|
+
"""Compute SHA-256 hash of file content."""
|
|
82
|
+
h = hashlib.sha256()
|
|
83
|
+
with open(file_path, "rb") as f:
|
|
84
|
+
for chunk in iter(lambda: f.read(8192), b""):
|
|
85
|
+
h.update(chunk)
|
|
86
|
+
return h.hexdigest()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ---------------------------------------------------------------------------
|
|
90
|
+
# Vision-based extraction helpers
|
|
91
|
+
# ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
def _check_vision_available():
|
|
94
|
+
"""Check if a vision-capable LLM is available for document extraction."""
|
|
95
|
+
try:
|
|
96
|
+
from tools.llm import get_router
|
|
97
|
+
router = get_router()
|
|
98
|
+
provider, model_id, model_cfg = router.get_provider_for_function("document_vision")
|
|
99
|
+
if provider is None:
|
|
100
|
+
return False, ""
|
|
101
|
+
return model_cfg.get("supports_vision", False), model_id
|
|
102
|
+
except Exception:
|
|
103
|
+
return False, ""
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _extract_text_from_image_via_vision(file_path):
|
|
107
|
+
"""Extract text content from an image using a vision LLM.
|
|
108
|
+
|
|
109
|
+
Sends the image to a vision-capable model with a prompt to extract
|
|
110
|
+
all visible text, preserving structure and formatting.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
file_path: Path to the image file.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Extracted text string, or placeholder if vision unavailable.
|
|
117
|
+
"""
|
|
118
|
+
p = Path(file_path)
|
|
119
|
+
available, model_id = _check_vision_available()
|
|
120
|
+
if not available:
|
|
121
|
+
return f"[Image file: {p.name} -- vision model not available for text extraction]"
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
from tools.testing.screenshot_validator import encode_image
|
|
125
|
+
from tools.llm import get_router
|
|
126
|
+
from tools.llm.provider import LLMRequest
|
|
127
|
+
|
|
128
|
+
b64_data, media_type = encode_image(str(p))
|
|
129
|
+
|
|
130
|
+
user_content = [
|
|
131
|
+
{
|
|
132
|
+
"type": "image",
|
|
133
|
+
"source": {
|
|
134
|
+
"type": "base64",
|
|
135
|
+
"media_type": media_type,
|
|
136
|
+
"data": b64_data,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"type": "text",
|
|
141
|
+
"text": (
|
|
142
|
+
"Extract ALL text content from this document image. "
|
|
143
|
+
"Preserve structure, headings, bullet points, and numbered lists. "
|
|
144
|
+
"If this contains requirement statements (shall/must/should/will), "
|
|
145
|
+
"preserve them exactly. Output only the extracted text."
|
|
146
|
+
),
|
|
147
|
+
},
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
router = get_router()
|
|
151
|
+
request = LLMRequest(
|
|
152
|
+
messages=[{"role": "user", "content": user_content}],
|
|
153
|
+
system_prompt=(
|
|
154
|
+
"You are a document text extraction assistant for a DoD requirements "
|
|
155
|
+
"intake system. Extract all visible text from the provided image accurately. "
|
|
156
|
+
"Preserve document structure, headings, and formatting."
|
|
157
|
+
),
|
|
158
|
+
max_tokens=4096,
|
|
159
|
+
temperature=0.1,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
response = router.invoke("document_vision", request)
|
|
163
|
+
text = response.content.strip()
|
|
164
|
+
if text:
|
|
165
|
+
logger.info("Vision extracted %d chars from image %s", len(text), p.name)
|
|
166
|
+
return text
|
|
167
|
+
return f"[Image file: {p.name} -- vision model returned no text]"
|
|
168
|
+
|
|
169
|
+
except Exception as exc:
|
|
170
|
+
logger.warning("Vision text extraction failed for %s: %s", p.name, exc)
|
|
171
|
+
return f"[Image file: {p.name} -- vision extraction error: {exc}]"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _extract_pdf_pages_via_vision(file_path):
|
|
175
|
+
"""Extract text from PDF pages using vision LLM for pages with no text.
|
|
176
|
+
|
|
177
|
+
Iterates pages via pypdf. For each page, attempts text extraction first.
|
|
178
|
+
If a page yields no text (scanned/image-heavy), renders it and sends to
|
|
179
|
+
the vision model for OCR-like extraction.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
file_path: Path to the PDF file.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Concatenated text from all pages with page markers.
|
|
186
|
+
"""
|
|
187
|
+
p = Path(file_path)
|
|
188
|
+
available, model_id = _check_vision_available()
|
|
189
|
+
if not available:
|
|
190
|
+
return f"[PDF file: {p.name} -- vision model not available for page extraction]"
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
from pypdf import PdfReader
|
|
194
|
+
except ImportError:
|
|
195
|
+
return f"[PDF file: {p.name} -- requires pypdf for page-by-page extraction]"
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
from tools.llm import get_router
|
|
199
|
+
from tools.llm.provider import LLMRequest
|
|
200
|
+
except ImportError as exc:
|
|
201
|
+
return f"[PDF file: {p.name} -- vision dependencies not available: {exc}]"
|
|
202
|
+
|
|
203
|
+
reader = PdfReader(str(p))
|
|
204
|
+
all_pages = []
|
|
205
|
+
vision_pages_used = 0
|
|
206
|
+
|
|
207
|
+
for i, page in enumerate(reader.pages):
|
|
208
|
+
page_num = i + 1
|
|
209
|
+
text = page.extract_text() or ""
|
|
210
|
+
|
|
211
|
+
if len(text.strip()) >= 50:
|
|
212
|
+
# Sufficient text extracted directly
|
|
213
|
+
all_pages.append(f"--- Page {page_num} ---\n{text.strip()}")
|
|
214
|
+
continue
|
|
215
|
+
|
|
216
|
+
# Page has no/little text — try vision extraction via page rendering
|
|
217
|
+
# Attempt to render page to image using pdf2image or fitz
|
|
218
|
+
page_image_b64 = None
|
|
219
|
+
media_type = "image/png"
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
# Try pdf2image (poppler-based)
|
|
223
|
+
from pdf2image import convert_from_path
|
|
224
|
+
images = convert_from_path(
|
|
225
|
+
str(p), first_page=page_num, last_page=page_num, dpi=200,
|
|
226
|
+
)
|
|
227
|
+
if images:
|
|
228
|
+
import io
|
|
229
|
+
buf = io.BytesIO()
|
|
230
|
+
images[0].save(buf, format="PNG")
|
|
231
|
+
page_image_b64 = base64.b64encode(buf.getvalue()).decode("utf-8")
|
|
232
|
+
except ImportError:
|
|
233
|
+
pass
|
|
234
|
+
except Exception as exc:
|
|
235
|
+
logger.debug("pdf2image failed for page %d: %s", page_num, exc)
|
|
236
|
+
|
|
237
|
+
if page_image_b64 is None:
|
|
238
|
+
# No rendering library available — use whatever text we got
|
|
239
|
+
if text.strip():
|
|
240
|
+
all_pages.append(f"--- Page {page_num} ---\n{text.strip()}")
|
|
241
|
+
else:
|
|
242
|
+
all_pages.append(
|
|
243
|
+
f"--- Page {page_num} ---\n"
|
|
244
|
+
f"[No text extractable; pdf2image required for vision fallback]"
|
|
245
|
+
)
|
|
246
|
+
continue
|
|
247
|
+
|
|
248
|
+
# Send rendered page image to vision model
|
|
249
|
+
try:
|
|
250
|
+
user_content = [
|
|
251
|
+
{
|
|
252
|
+
"type": "image",
|
|
253
|
+
"source": {
|
|
254
|
+
"type": "base64",
|
|
255
|
+
"media_type": media_type,
|
|
256
|
+
"data": page_image_b64,
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"type": "text",
|
|
261
|
+
"text": (
|
|
262
|
+
f"Extract ALL text from this PDF page (page {page_num}). "
|
|
263
|
+
"Preserve structure, headings, tables, and bullet points. "
|
|
264
|
+
"Output only the extracted text."
|
|
265
|
+
),
|
|
266
|
+
},
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
router = get_router()
|
|
270
|
+
request = LLMRequest(
|
|
271
|
+
messages=[{"role": "user", "content": user_content}],
|
|
272
|
+
system_prompt=(
|
|
273
|
+
"You are a document OCR assistant. Extract all text from "
|
|
274
|
+
"the provided page image accurately."
|
|
275
|
+
),
|
|
276
|
+
max_tokens=4096,
|
|
277
|
+
temperature=0.1,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
response = router.invoke("document_vision", request)
|
|
281
|
+
page_text = response.content.strip()
|
|
282
|
+
if page_text:
|
|
283
|
+
all_pages.append(f"--- Page {page_num} (vision) ---\n{page_text}")
|
|
284
|
+
vision_pages_used += 1
|
|
285
|
+
else:
|
|
286
|
+
all_pages.append(f"--- Page {page_num} ---\n[Vision returned no text]")
|
|
287
|
+
except Exception as exc:
|
|
288
|
+
logger.warning("Vision extraction failed for page %d: %s", page_num, exc)
|
|
289
|
+
all_pages.append(
|
|
290
|
+
f"--- Page {page_num} ---\n[Vision extraction error: {exc}]"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
if vision_pages_used > 0:
|
|
294
|
+
logger.info(
|
|
295
|
+
"PDF %s: %d pages, %d required vision extraction",
|
|
296
|
+
p.name, len(reader.pages), vision_pages_used,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
if all_pages:
|
|
300
|
+
return "\n\n".join(all_pages)
|
|
301
|
+
return f"[PDF file: {p.name} -- no content extracted from any page]"
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _classify_image(file_path):
|
|
305
|
+
"""Classify an uploaded image using a vision LLM.
|
|
306
|
+
|
|
307
|
+
Determines if the image is a whiteboard, diagram, wireframe, screenshot,
|
|
308
|
+
form, table, flowchart, network diagram, architecture diagram, or other.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
file_path: Path to the image file.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
dict with {category, confidence, description} or None if unavailable.
|
|
315
|
+
"""
|
|
316
|
+
available, model_id = _check_vision_available()
|
|
317
|
+
if not available:
|
|
318
|
+
return None
|
|
319
|
+
|
|
320
|
+
try:
|
|
321
|
+
from tools.testing.screenshot_validator import encode_image
|
|
322
|
+
from tools.llm import get_router
|
|
323
|
+
from tools.llm.provider import LLMRequest
|
|
324
|
+
|
|
325
|
+
b64_data, media_type = encode_image(str(file_path))
|
|
326
|
+
|
|
327
|
+
user_content = [
|
|
328
|
+
{
|
|
329
|
+
"type": "image",
|
|
330
|
+
"source": {
|
|
331
|
+
"type": "base64",
|
|
332
|
+
"media_type": media_type,
|
|
333
|
+
"data": b64_data,
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"type": "text",
|
|
338
|
+
"text": (
|
|
339
|
+
"Classify this image into exactly ONE category from the list: "
|
|
340
|
+
"whiteboard, diagram, wireframe, screenshot, form, table, "
|
|
341
|
+
"flowchart, network_diagram, architecture_diagram, "
|
|
342
|
+
"handwritten_notes, other. "
|
|
343
|
+
"Respond with EXACTLY this JSON (no markdown, no extra text): "
|
|
344
|
+
'{"category": "string", "confidence": 0.0-1.0, '
|
|
345
|
+
'"description": "brief description of what the image shows"}'
|
|
346
|
+
),
|
|
347
|
+
},
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
router = get_router()
|
|
351
|
+
request = LLMRequest(
|
|
352
|
+
messages=[{"role": "user", "content": user_content}],
|
|
353
|
+
system_prompt=(
|
|
354
|
+
"You are an image classifier for a DoD document intake system. "
|
|
355
|
+
"Classify images accurately into the requested categories."
|
|
356
|
+
),
|
|
357
|
+
max_tokens=256,
|
|
358
|
+
temperature=0.1,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
response = router.invoke("document_vision", request)
|
|
362
|
+
text = response.content.strip()
|
|
363
|
+
|
|
364
|
+
# Strip markdown fences
|
|
365
|
+
if text.startswith("```"):
|
|
366
|
+
lines = text.splitlines()
|
|
367
|
+
if lines[0].startswith("```"):
|
|
368
|
+
lines = lines[1:]
|
|
369
|
+
if lines and lines[-1].strip() == "```":
|
|
370
|
+
lines = lines[:-1]
|
|
371
|
+
text = "\n".join(lines).strip()
|
|
372
|
+
|
|
373
|
+
result = json.loads(text)
|
|
374
|
+
return {
|
|
375
|
+
"category": str(result.get("category", "other")),
|
|
376
|
+
"confidence": float(result.get("confidence", 0.0)),
|
|
377
|
+
"description": str(result.get("description", "")),
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
except (json.JSONDecodeError, ValueError) as exc:
|
|
381
|
+
logger.debug("Image classification JSON parse failed: %s", exc)
|
|
382
|
+
return {"category": "other", "confidence": 0.3, "description": "Classification uncertain"}
|
|
383
|
+
except Exception as exc:
|
|
384
|
+
logger.warning("Image classification failed: %s", exc)
|
|
385
|
+
return None
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def classify_document(document_id, db_path=None):
|
|
389
|
+
"""Classify an uploaded image document using vision LLM.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
document_id: ID of the uploaded document.
|
|
393
|
+
db_path: Optional DB path override.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
dict with classification result.
|
|
397
|
+
"""
|
|
398
|
+
conn = get_connection(db_path=db_path)
|
|
399
|
+
doc = conn.execute(
|
|
400
|
+
"SELECT * FROM intake_documents WHERE id = ?", (document_id,)
|
|
401
|
+
).fetchone()
|
|
402
|
+
if not doc:
|
|
403
|
+
conn.close()
|
|
404
|
+
raise ValueError(f"Document '{document_id}' not found.")
|
|
405
|
+
|
|
406
|
+
doc_data = dict(doc)
|
|
407
|
+
file_path = doc_data["file_path"]
|
|
408
|
+
p = Path(file_path)
|
|
409
|
+
|
|
410
|
+
if p.suffix.lower() not in IMAGE_EXTENSIONS:
|
|
411
|
+
conn.close()
|
|
412
|
+
return {
|
|
413
|
+
"status": "skipped",
|
|
414
|
+
"document_id": document_id,
|
|
415
|
+
"reason": f"Not an image file: {p.suffix}",
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
classification = _classify_image(file_path)
|
|
419
|
+
if classification is None:
|
|
420
|
+
conn.close()
|
|
421
|
+
return {
|
|
422
|
+
"status": "skipped",
|
|
423
|
+
"document_id": document_id,
|
|
424
|
+
"reason": "Vision model not available for classification",
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
# Store classification in extracted_sections column
|
|
428
|
+
conn.execute(
|
|
429
|
+
"UPDATE intake_documents SET extracted_sections = ? WHERE id = ?",
|
|
430
|
+
(json.dumps(classification), document_id),
|
|
431
|
+
)
|
|
432
|
+
conn.commit()
|
|
433
|
+
conn.close()
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
"status": "ok",
|
|
437
|
+
"document_id": document_id,
|
|
438
|
+
"classification": classification,
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
# ---------------------------------------------------------------------------
|
|
443
|
+
# File reading helpers
|
|
444
|
+
# ---------------------------------------------------------------------------
|
|
445
|
+
|
|
446
|
+
def _read_file_content(file_path):
|
|
447
|
+
"""Read text content from a file.
|
|
448
|
+
|
|
449
|
+
Supports .txt, .md (direct read), .pdf (pypdf with vision fallback),
|
|
450
|
+
.docx (python-docx with fallback), image files (vision extraction),
|
|
451
|
+
and other text files.
|
|
452
|
+
"""
|
|
453
|
+
p = Path(file_path)
|
|
454
|
+
suffix = p.suffix.lower()
|
|
455
|
+
|
|
456
|
+
if suffix in (".txt", ".md"):
|
|
457
|
+
return p.read_text(encoding="utf-8")
|
|
458
|
+
|
|
459
|
+
elif suffix == ".pdf":
|
|
460
|
+
# Try pypdf (PyPDF2 successor)
|
|
461
|
+
try:
|
|
462
|
+
from pypdf import PdfReader
|
|
463
|
+
reader = PdfReader(str(p))
|
|
464
|
+
pages = []
|
|
465
|
+
for page in reader.pages:
|
|
466
|
+
text = page.extract_text()
|
|
467
|
+
if text:
|
|
468
|
+
pages.append(text)
|
|
469
|
+
if pages:
|
|
470
|
+
return "\n\n".join(pages)
|
|
471
|
+
# No text found — try vision-based page extraction
|
|
472
|
+
logger.info("PDF %s has no extractable text, trying vision fallback", p.name)
|
|
473
|
+
vision_result = _extract_pdf_pages_via_vision(str(p))
|
|
474
|
+
if not vision_result.startswith("[PDF file:"):
|
|
475
|
+
return vision_result
|
|
476
|
+
return f"[PDF file: {p.name} -- no extractable text found]"
|
|
477
|
+
except ImportError:
|
|
478
|
+
return (
|
|
479
|
+
f"[PDF file: {p.name} -- requires pypdf library. "
|
|
480
|
+
f"Install with: pip install pypdf]"
|
|
481
|
+
)
|
|
482
|
+
except Exception as exc:
|
|
483
|
+
return f"[PDF file: {p.name} -- extraction error: {exc}]"
|
|
484
|
+
|
|
485
|
+
elif suffix == ".docx":
|
|
486
|
+
# Try python-docx
|
|
487
|
+
try:
|
|
488
|
+
from docx import Document
|
|
489
|
+
doc = Document(str(p))
|
|
490
|
+
paragraphs = [para.text for para in doc.paragraphs if para.text.strip()]
|
|
491
|
+
if paragraphs:
|
|
492
|
+
return "\n\n".join(paragraphs)
|
|
493
|
+
return f"[DOCX file: {p.name} -- no extractable text found]"
|
|
494
|
+
except ImportError:
|
|
495
|
+
return (
|
|
496
|
+
f"[DOCX file: {p.name} -- requires python-docx library. "
|
|
497
|
+
f"Install with: pip install python-docx]"
|
|
498
|
+
)
|
|
499
|
+
except Exception as exc:
|
|
500
|
+
return f"[DOCX file: {p.name} -- extraction error: {exc}]"
|
|
501
|
+
|
|
502
|
+
elif suffix in IMAGE_EXTENSIONS:
|
|
503
|
+
# Image file — use vision LLM for text extraction
|
|
504
|
+
return _extract_text_from_image_via_vision(str(p))
|
|
505
|
+
|
|
506
|
+
else:
|
|
507
|
+
# Attempt generic text read
|
|
508
|
+
try:
|
|
509
|
+
return p.read_text(encoding="utf-8")
|
|
510
|
+
except UnicodeDecodeError:
|
|
511
|
+
return f"[Binary file: {p.name} -- unable to read as text]"
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
# ---------------------------------------------------------------------------
|
|
515
|
+
# Requirement extraction logic
|
|
516
|
+
# ---------------------------------------------------------------------------
|
|
517
|
+
|
|
518
|
+
# Requirement type detection keywords
|
|
519
|
+
_REQ_TYPE_KEYWORDS = {
|
|
520
|
+
"security": [
|
|
521
|
+
"authenticate", "authorize", "encrypt", "cac", "piv", "mfa",
|
|
522
|
+
"fips", "stig", "access control", "audit log", "credential",
|
|
523
|
+
"certificate", "pki", "rbac", "permission", "classification",
|
|
524
|
+
"clearance", "password", "token", "session timeout",
|
|
525
|
+
],
|
|
526
|
+
"performance": [
|
|
527
|
+
"response time", "latency", "throughput", "concurrent",
|
|
528
|
+
"availability", "uptime", "sla", "load", "capacity",
|
|
529
|
+
"transactions per second", "bandwidth", "millisecond",
|
|
530
|
+
],
|
|
531
|
+
"interface": [
|
|
532
|
+
"integrate", "interface", "api", "rest", "soap", "feed",
|
|
533
|
+
"import", "export", "connect", "external system", "third-party",
|
|
534
|
+
"web service", "message queue", "protocol",
|
|
535
|
+
],
|
|
536
|
+
"data": [
|
|
537
|
+
"database", "data store", "retention", "backup", "archive",
|
|
538
|
+
"migrate data", "data format", "schema", "cui data",
|
|
539
|
+
"record", "table", "storage", "replication",
|
|
540
|
+
],
|
|
541
|
+
"operational": [
|
|
542
|
+
"deployment", "install", "configure", "maintain", "monitor",
|
|
543
|
+
"support", "train", "operate", "documentation", "helpdesk",
|
|
544
|
+
"disaster recovery", "failover", "continuity",
|
|
545
|
+
],
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
def _detect_requirement_type(text):
|
|
550
|
+
"""Determine requirement type from keywords in text."""
|
|
551
|
+
lower = text.lower()
|
|
552
|
+
for rtype, keywords in _REQ_TYPE_KEYWORDS.items():
|
|
553
|
+
if any(kw in lower for kw in keywords):
|
|
554
|
+
return rtype
|
|
555
|
+
return "functional"
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
def _detect_priority(text):
|
|
559
|
+
"""Determine priority based on modal verbs.
|
|
560
|
+
|
|
561
|
+
shall/must -> P1 (critical)
|
|
562
|
+
should -> P2 (high)
|
|
563
|
+
will/may -> P3 (medium)
|
|
564
|
+
"""
|
|
565
|
+
lower = text.lower()
|
|
566
|
+
if any(kw in lower for kw in ["shall", "must", "is required to"]):
|
|
567
|
+
return "critical"
|
|
568
|
+
elif "should" in lower:
|
|
569
|
+
return "high"
|
|
570
|
+
elif any(kw in lower for kw in ["will", "may", "can"]):
|
|
571
|
+
return "medium"
|
|
572
|
+
return "medium"
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def _extract_requirement_sentences(text):
|
|
576
|
+
"""Extract sentences that contain requirement indicator keywords.
|
|
577
|
+
|
|
578
|
+
Matches:
|
|
579
|
+
- "shall" statements (mandatory)
|
|
580
|
+
- "must" statements (mandatory)
|
|
581
|
+
- "should" statements (desired)
|
|
582
|
+
- "will" statements (intent)
|
|
583
|
+
"""
|
|
584
|
+
# Split into sentences
|
|
585
|
+
sentences = re.split(r'(?<=[.!?])\s+', text.replace("\n", " "))
|
|
586
|
+
requirements = []
|
|
587
|
+
|
|
588
|
+
requirement_patterns = [
|
|
589
|
+
re.compile(r'\bshall\b', re.IGNORECASE),
|
|
590
|
+
re.compile(r'\bmust\b', re.IGNORECASE),
|
|
591
|
+
re.compile(r'\bshould\b', re.IGNORECASE),
|
|
592
|
+
re.compile(r'\bwill\b', re.IGNORECASE),
|
|
593
|
+
]
|
|
594
|
+
|
|
595
|
+
for sentence in sentences:
|
|
596
|
+
sentence = sentence.strip()
|
|
597
|
+
if len(sentence) < 10:
|
|
598
|
+
continue
|
|
599
|
+
|
|
600
|
+
for pattern in requirement_patterns:
|
|
601
|
+
if pattern.search(sentence):
|
|
602
|
+
req_type = _detect_requirement_type(sentence)
|
|
603
|
+
priority = _detect_priority(sentence)
|
|
604
|
+
requirements.append({
|
|
605
|
+
"raw_text": sentence,
|
|
606
|
+
"requirement_type": req_type,
|
|
607
|
+
"priority": priority,
|
|
608
|
+
})
|
|
609
|
+
break # Only match once per sentence
|
|
610
|
+
|
|
611
|
+
return requirements
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
# ---------------------------------------------------------------------------
|
|
615
|
+
# Core functions
|
|
616
|
+
# ---------------------------------------------------------------------------
|
|
617
|
+
|
|
618
|
+
def upload_document(session_id, file_path, document_type, db_path=None):
|
|
619
|
+
"""Upload a document for requirement extraction.
|
|
620
|
+
|
|
621
|
+
Args:
|
|
622
|
+
session_id: Intake session ID.
|
|
623
|
+
file_path: Path to the document file.
|
|
624
|
+
document_type: One of sow, cdd, conops, srd, srs, other.
|
|
625
|
+
db_path: Optional DB path override.
|
|
626
|
+
|
|
627
|
+
Returns:
|
|
628
|
+
dict with document_id, session_id, file metadata, and status.
|
|
629
|
+
"""
|
|
630
|
+
p = Path(file_path)
|
|
631
|
+
if not p.exists():
|
|
632
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
633
|
+
|
|
634
|
+
conn = get_connection(db_path=db_path)
|
|
635
|
+
|
|
636
|
+
# Verify session exists
|
|
637
|
+
session = conn.execute(
|
|
638
|
+
"SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
|
|
639
|
+
).fetchone()
|
|
640
|
+
if not session:
|
|
641
|
+
conn.close()
|
|
642
|
+
raise ValueError(f"Session '{session_id}' not found.")
|
|
643
|
+
|
|
644
|
+
session_data = dict(session)
|
|
645
|
+
|
|
646
|
+
# Compute file metadata
|
|
647
|
+
doc_id = _generate_id("doc")
|
|
648
|
+
file_hash = _compute_file_hash(file_path)
|
|
649
|
+
file_size = p.stat().st_size
|
|
650
|
+
file_name = p.name
|
|
651
|
+
|
|
652
|
+
# MIME type mapping
|
|
653
|
+
mime_map = {
|
|
654
|
+
".pdf": "application/pdf",
|
|
655
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
656
|
+
".doc": "application/msword",
|
|
657
|
+
".txt": "text/plain",
|
|
658
|
+
".md": "text/markdown",
|
|
659
|
+
".png": "image/png",
|
|
660
|
+
".jpg": "image/jpeg",
|
|
661
|
+
".jpeg": "image/jpeg",
|
|
662
|
+
".gif": "image/gif",
|
|
663
|
+
".webp": "image/webp",
|
|
664
|
+
".tiff": "image/tiff",
|
|
665
|
+
".bmp": "image/bmp",
|
|
666
|
+
}
|
|
667
|
+
mime_type = mime_map.get(p.suffix.lower(), "application/octet-stream")
|
|
668
|
+
|
|
669
|
+
# Read raw text for storage
|
|
670
|
+
_read_file_content(file_path)
|
|
671
|
+
|
|
672
|
+
# Auto-classify images at upload time
|
|
673
|
+
image_classification = None
|
|
674
|
+
if p.suffix.lower() in IMAGE_EXTENSIONS:
|
|
675
|
+
image_classification = _classify_image(file_path)
|
|
676
|
+
|
|
677
|
+
# Map document_type for DB constraint compatibility
|
|
678
|
+
# DB allows: sow, cdd, conops, srd, icd, ssp, use_case, brd, urd, rfp, rfi, other
|
|
679
|
+
# Spec allows: sow, cdd, conops, srd, srs, other
|
|
680
|
+
# Map srs -> other if not in DB constraint
|
|
681
|
+
db_doc_type = document_type if document_type != "srs" else "other"
|
|
682
|
+
|
|
683
|
+
extracted_sections = None
|
|
684
|
+
if image_classification:
|
|
685
|
+
extracted_sections = json.dumps(image_classification)
|
|
686
|
+
|
|
687
|
+
conn.execute(
|
|
688
|
+
"""INSERT INTO intake_documents
|
|
689
|
+
(id, session_id, document_type, file_name, file_path, file_hash,
|
|
690
|
+
file_size_bytes, mime_type, extraction_status, extracted_sections,
|
|
691
|
+
extracted_requirements_count, classification, uploaded_at)
|
|
692
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, 0, 'CUI', ?)""",
|
|
693
|
+
(
|
|
694
|
+
doc_id, session_id, db_doc_type, file_name, str(p.resolve()),
|
|
695
|
+
file_hash, file_size, mime_type, extracted_sections,
|
|
696
|
+
datetime.now().isoformat(),
|
|
697
|
+
),
|
|
698
|
+
)
|
|
699
|
+
conn.commit()
|
|
700
|
+
conn.close()
|
|
701
|
+
|
|
702
|
+
if _HAS_AUDIT:
|
|
703
|
+
log_event(
|
|
704
|
+
event_type="document_uploaded",
|
|
705
|
+
actor="sparkpilot-requirements-analyst",
|
|
706
|
+
action=f"Uploaded {document_type.upper()} document: {file_name}",
|
|
707
|
+
project_id=session_data.get("project_id"),
|
|
708
|
+
details={
|
|
709
|
+
"session_id": session_id,
|
|
710
|
+
"document_id": doc_id,
|
|
711
|
+
"file_name": file_name,
|
|
712
|
+
"file_hash": file_hash,
|
|
713
|
+
},
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
result = {
|
|
717
|
+
"document_id": doc_id,
|
|
718
|
+
"session_id": session_id,
|
|
719
|
+
"file_path": str(p.resolve()),
|
|
720
|
+
"file_hash": file_hash,
|
|
721
|
+
"file_size": file_size,
|
|
722
|
+
"status": "uploaded",
|
|
723
|
+
}
|
|
724
|
+
if image_classification:
|
|
725
|
+
result["image_classification"] = image_classification
|
|
726
|
+
return result
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
def extract_requirements(document_id, db_path=None):
|
|
730
|
+
"""Extract requirement statements from an uploaded document.
|
|
731
|
+
|
|
732
|
+
Reads the document text from intake_documents, identifies requirement
|
|
733
|
+
sentences using shall/must/should/will patterns, classifies each by
|
|
734
|
+
type and priority, and inserts into intake_requirements.
|
|
735
|
+
|
|
736
|
+
Args:
|
|
737
|
+
document_id: ID of the uploaded document.
|
|
738
|
+
db_path: Optional DB path override.
|
|
739
|
+
|
|
740
|
+
Returns:
|
|
741
|
+
dict with document_id, count of requirements extracted, requirement
|
|
742
|
+
list, and breakdowns by type and priority.
|
|
743
|
+
"""
|
|
744
|
+
conn = get_connection(db_path=db_path)
|
|
745
|
+
|
|
746
|
+
# Load document
|
|
747
|
+
doc = conn.execute(
|
|
748
|
+
"SELECT * FROM intake_documents WHERE id = ?", (document_id,)
|
|
749
|
+
).fetchone()
|
|
750
|
+
if not doc:
|
|
751
|
+
conn.close()
|
|
752
|
+
raise ValueError(f"Document '{document_id}' not found.")
|
|
753
|
+
|
|
754
|
+
doc_data = dict(doc)
|
|
755
|
+
session_id = doc_data["session_id"]
|
|
756
|
+
file_path = doc_data["file_path"]
|
|
757
|
+
|
|
758
|
+
# Update status to extracting
|
|
759
|
+
conn.execute(
|
|
760
|
+
"UPDATE intake_documents SET extraction_status = 'extracting' WHERE id = ?",
|
|
761
|
+
(document_id,),
|
|
762
|
+
)
|
|
763
|
+
conn.commit()
|
|
764
|
+
|
|
765
|
+
# Read file content
|
|
766
|
+
raw_text = _read_file_content(file_path)
|
|
767
|
+
|
|
768
|
+
# Extract requirement sentences
|
|
769
|
+
extracted_stmts = _extract_requirement_sentences(raw_text)
|
|
770
|
+
|
|
771
|
+
# Insert each requirement into intake_requirements
|
|
772
|
+
inserted_reqs = []
|
|
773
|
+
by_type = {}
|
|
774
|
+
by_priority = {}
|
|
775
|
+
|
|
776
|
+
for stmt in extracted_stmts:
|
|
777
|
+
req_id = f"req-{uuid.uuid4().hex[:12]}"
|
|
778
|
+
raw = stmt["raw_text"]
|
|
779
|
+
req_type = stmt["requirement_type"]
|
|
780
|
+
priority = stmt["priority"]
|
|
781
|
+
|
|
782
|
+
conn.execute(
|
|
783
|
+
"""INSERT INTO intake_requirements
|
|
784
|
+
(id, session_id, raw_text, refined_text, requirement_type,
|
|
785
|
+
priority, source_document, clarity_score,
|
|
786
|
+
gaps, acceptance_criteria, status, classification, created_at)
|
|
787
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 0.5, NULL, NULL, 'draft', 'CUI', ?)""",
|
|
788
|
+
(
|
|
789
|
+
req_id, session_id, raw, raw, req_type,
|
|
790
|
+
priority, document_id, datetime.now().isoformat(),
|
|
791
|
+
),
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
inserted_reqs.append({
|
|
795
|
+
"id": req_id,
|
|
796
|
+
"raw_text": raw,
|
|
797
|
+
"requirement_type": req_type,
|
|
798
|
+
"priority": priority,
|
|
799
|
+
"source": "document",
|
|
800
|
+
"source_reference": document_id,
|
|
801
|
+
})
|
|
802
|
+
|
|
803
|
+
# Count by type
|
|
804
|
+
by_type[req_type] = by_type.get(req_type, 0) + 1
|
|
805
|
+
# Count by priority
|
|
806
|
+
by_priority[priority] = by_priority.get(priority, 0) + 1
|
|
807
|
+
|
|
808
|
+
# Update document: extraction complete
|
|
809
|
+
conn.execute(
|
|
810
|
+
"""UPDATE intake_documents
|
|
811
|
+
SET extraction_status = 'extracted', extracted_requirements_count = ?
|
|
812
|
+
WHERE id = ?""",
|
|
813
|
+
(len(inserted_reqs), document_id),
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
# Update session total requirement count
|
|
817
|
+
total_count = conn.execute(
|
|
818
|
+
"SELECT COUNT(*) as cnt FROM intake_requirements WHERE session_id = ?",
|
|
819
|
+
(session_id,),
|
|
820
|
+
).fetchone()["cnt"]
|
|
821
|
+
conn.execute(
|
|
822
|
+
"UPDATE intake_sessions SET total_requirements = ?, updated_at = ? WHERE id = ?",
|
|
823
|
+
(total_count, datetime.now().isoformat(), session_id),
|
|
824
|
+
)
|
|
825
|
+
|
|
826
|
+
conn.commit()
|
|
827
|
+
conn.close()
|
|
828
|
+
|
|
829
|
+
if _HAS_AUDIT:
|
|
830
|
+
log_event(
|
|
831
|
+
event_type="document_extracted",
|
|
832
|
+
actor="sparkpilot-requirements-analyst",
|
|
833
|
+
action=f"Extracted {len(inserted_reqs)} requirements from document {document_id}",
|
|
834
|
+
details={
|
|
835
|
+
"document_id": document_id,
|
|
836
|
+
"session_id": session_id,
|
|
837
|
+
"count": len(inserted_reqs),
|
|
838
|
+
"by_type": by_type,
|
|
839
|
+
},
|
|
840
|
+
)
|
|
841
|
+
|
|
842
|
+
return {
|
|
843
|
+
"status": "ok",
|
|
844
|
+
"document_id": document_id,
|
|
845
|
+
"requirements_extracted": len(inserted_reqs),
|
|
846
|
+
"requirements": inserted_reqs,
|
|
847
|
+
"by_type": by_type,
|
|
848
|
+
"by_priority": by_priority,
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
def list_documents(session_id, db_path=None):
|
|
853
|
+
"""List all documents uploaded to a session.
|
|
854
|
+
|
|
855
|
+
Args:
|
|
856
|
+
session_id: Intake session ID.
|
|
857
|
+
db_path: Optional DB path override.
|
|
858
|
+
|
|
859
|
+
Returns:
|
|
860
|
+
dict with session_id and list of document records.
|
|
861
|
+
"""
|
|
862
|
+
conn = get_connection(db_path=db_path)
|
|
863
|
+
|
|
864
|
+
session = conn.execute(
|
|
865
|
+
"SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
|
|
866
|
+
).fetchone()
|
|
867
|
+
if not session:
|
|
868
|
+
conn.close()
|
|
869
|
+
raise ValueError(f"Session '{session_id}' not found.")
|
|
870
|
+
|
|
871
|
+
rows = conn.execute(
|
|
872
|
+
"SELECT * FROM intake_documents WHERE session_id = ? ORDER BY uploaded_at",
|
|
873
|
+
(session_id,),
|
|
874
|
+
).fetchall()
|
|
875
|
+
documents = [dict(r) for r in rows]
|
|
876
|
+
conn.close()
|
|
877
|
+
|
|
878
|
+
return {
|
|
879
|
+
"status": "ok",
|
|
880
|
+
"session_id": session_id,
|
|
881
|
+
"total_documents": len(documents),
|
|
882
|
+
"documents": documents,
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
# ---------------------------------------------------------------------------
|
|
887
|
+
# CLI
|
|
888
|
+
# ---------------------------------------------------------------------------
|
|
889
|
+
|
|
890
|
+
def main():
|
|
891
|
+
parser = argparse.ArgumentParser(
|
|
892
|
+
description="SPARKPILOT Document Requirements Extractor"
|
|
893
|
+
)
|
|
894
|
+
parser.add_argument("--session-id", help="Intake session ID")
|
|
895
|
+
parser.add_argument("--document-id", help="Document ID (for extraction)")
|
|
896
|
+
parser.add_argument(
|
|
897
|
+
"--upload", action="store_true",
|
|
898
|
+
help="Upload a document",
|
|
899
|
+
)
|
|
900
|
+
parser.add_argument("--file-path", help="Path to the document file")
|
|
901
|
+
parser.add_argument(
|
|
902
|
+
"--document-type",
|
|
903
|
+
choices=["sow", "cdd", "conops", "srd", "srs", "other"],
|
|
904
|
+
default="other",
|
|
905
|
+
help="Type of the document",
|
|
906
|
+
)
|
|
907
|
+
parser.add_argument(
|
|
908
|
+
"--extract", action="store_true",
|
|
909
|
+
help="Extract requirements from an uploaded document",
|
|
910
|
+
)
|
|
911
|
+
parser.add_argument(
|
|
912
|
+
"--list", action="store_true",
|
|
913
|
+
help="List all documents for a session",
|
|
914
|
+
)
|
|
915
|
+
parser.add_argument(
|
|
916
|
+
"--classify", action="store_true",
|
|
917
|
+
help="Classify an uploaded image document using vision LLM",
|
|
918
|
+
)
|
|
919
|
+
parser.add_argument("--json", action="store_true", help="JSON output")
|
|
920
|
+
args = parser.parse_args()
|
|
921
|
+
|
|
922
|
+
try:
|
|
923
|
+
result = None
|
|
924
|
+
|
|
925
|
+
if args.upload and args.session_id and args.file_path:
|
|
926
|
+
# Upload document
|
|
927
|
+
result = upload_document(
|
|
928
|
+
args.session_id, args.file_path, args.document_type,
|
|
929
|
+
)
|
|
930
|
+
|
|
931
|
+
elif args.extract and args.document_id:
|
|
932
|
+
# Extract requirements from document
|
|
933
|
+
result = extract_requirements(args.document_id)
|
|
934
|
+
|
|
935
|
+
elif args.classify and args.document_id:
|
|
936
|
+
# Classify image document
|
|
937
|
+
result = classify_document(args.document_id)
|
|
938
|
+
|
|
939
|
+
elif args.list and args.session_id:
|
|
940
|
+
# List documents
|
|
941
|
+
result = list_documents(args.session_id)
|
|
942
|
+
|
|
943
|
+
else:
|
|
944
|
+
parser.print_help()
|
|
945
|
+
return
|
|
946
|
+
|
|
947
|
+
if args.json:
|
|
948
|
+
print(json.dumps(result, indent=2, default=str))
|
|
949
|
+
else:
|
|
950
|
+
if args.upload:
|
|
951
|
+
print(
|
|
952
|
+
f"Document uploaded: {result.get('document_id')} "
|
|
953
|
+
f"({result.get('file_size', 0)} bytes, "
|
|
954
|
+
f"hash: {result.get('file_hash', '?')[:12]}...)"
|
|
955
|
+
)
|
|
956
|
+
elif args.extract:
|
|
957
|
+
print(
|
|
958
|
+
f"Extracted {result.get('requirements_extracted', 0)} "
|
|
959
|
+
f"requirements from document {result.get('document_id')}"
|
|
960
|
+
)
|
|
961
|
+
by_type = result.get("by_type", {})
|
|
962
|
+
if by_type:
|
|
963
|
+
print(" By type: " + ", ".join(
|
|
964
|
+
f"{k}={v}" for k, v in sorted(by_type.items())
|
|
965
|
+
))
|
|
966
|
+
by_priority = result.get("by_priority", {})
|
|
967
|
+
if by_priority:
|
|
968
|
+
print(" By priority: " + ", ".join(
|
|
969
|
+
f"{k}={v}" for k, v in sorted(by_priority.items())
|
|
970
|
+
))
|
|
971
|
+
elif args.classify:
|
|
972
|
+
cls = result.get("classification", {})
|
|
973
|
+
if cls:
|
|
974
|
+
print(f"Image classification for {result.get('document_id')}:")
|
|
975
|
+
print(f" Category: {cls.get('category', '?')}")
|
|
976
|
+
print(f" Confidence: {cls.get('confidence', 0):.2f}")
|
|
977
|
+
print(f" Description: {cls.get('description', '')}")
|
|
978
|
+
else:
|
|
979
|
+
print(f"Classification: {result.get('reason', result.get('status', '?'))}")
|
|
980
|
+
elif args.list:
|
|
981
|
+
docs = result.get("documents", [])
|
|
982
|
+
print(f"Documents for session {args.session_id}: {len(docs)}")
|
|
983
|
+
for doc in docs:
|
|
984
|
+
print(
|
|
985
|
+
f" [{doc.get('document_type', '?').upper()}] "
|
|
986
|
+
f"{doc.get('file_name', '?')} "
|
|
987
|
+
f"({doc.get('extraction_status', '?')})"
|
|
988
|
+
)
|
|
989
|
+
else:
|
|
990
|
+
print(json.dumps(result, indent=2, default=str))
|
|
991
|
+
|
|
992
|
+
except (ValueError, FileNotFoundError) as e:
|
|
993
|
+
if args.json:
|
|
994
|
+
print(json.dumps({"error": str(e)}, indent=2))
|
|
995
|
+
else:
|
|
996
|
+
print(f"Error: {e}")
|
|
997
|
+
raise SystemExit(1)
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
if __name__ == "__main__":
|
|
1001
|
+
main()
|
|
1002
|
+
# [TEMPLATE: CUI // SP-CTI]
|