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,1151 @@
|
|
|
1
|
+
# CUI // SP-CTI
|
|
2
|
+
# ICDEV Draft Orchestrator — Phase 67 (D-KB-3, D-KB-4) + Phase 68 (D-P68-1..8)
|
|
3
|
+
# RAG-assisted auto-draft generation for proposal sections.
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Draft Orchestrator — Generate proposal section drafts using RAG + LLM.
|
|
7
|
+
|
|
8
|
+
v1 Pipeline (Phase 67):
|
|
9
|
+
1. Load section metadata + opportunity context + shall-statements
|
|
10
|
+
2. Search knowledge base for relevant blocks (hybrid keyword + RAG semantic)
|
|
11
|
+
3. Fill hardprompts/proposal_draft.md template with context
|
|
12
|
+
4. Route through LLM (fine-tuned override → two-tier → chain fallback)
|
|
13
|
+
5. Save draft to proposal_section_drafts with provenance
|
|
14
|
+
|
|
15
|
+
v2 Pipeline (Phase 68):
|
|
16
|
+
1. KB Retrieval — search_blocks() + methodology blocks
|
|
17
|
+
2. Engine Enrichment — enrich_from_engines() (DB keyword queries)
|
|
18
|
+
3. SMART Solutioning — LLM generates structured SMART plan using ICDEV methodology
|
|
19
|
+
4. Content Generation — LLM draft with all context + WriteGuard post-check + auto-rewrite
|
|
20
|
+
|
|
21
|
+
Batch Generation:
|
|
22
|
+
- Kahn's topological sort on proposal_section_dependencies
|
|
23
|
+
- Sequential generation with prior_sections_context injection
|
|
24
|
+
- Background thread with job progress tracking
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
python tools/govcon/draft_orchestrator.py --generate --section-id <id> --opportunity-id <id> --json
|
|
28
|
+
python tools/govcon/draft_orchestrator.py --generate-v2 --section-id <id> --opportunity-id <id> --json
|
|
29
|
+
python tools/govcon/draft_orchestrator.py --preview --section-id <id> --opportunity-id <id> --json
|
|
30
|
+
python tools/govcon/draft_orchestrator.py --batch --opportunity-id <id> --json
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
import argparse
|
|
34
|
+
import collections
|
|
35
|
+
import json
|
|
36
|
+
import os
|
|
37
|
+
import sqlite3
|
|
38
|
+
import sys
|
|
39
|
+
import threading
|
|
40
|
+
import uuid
|
|
41
|
+
from datetime import datetime, timezone
|
|
42
|
+
from pathlib import Path
|
|
43
|
+
from tools.db.storage import get_connection
|
|
44
|
+
DB_PATH = None # Storage layer handles path resolution (D-DB-20)
|
|
45
|
+
|
|
46
|
+
_ROOT = Path(__file__).resolve().parent.parent.parent
|
|
47
|
+
sys.path.insert(0, str(_ROOT))
|
|
48
|
+
|
|
49
|
+
from tools.govcon.knowledge_base import search_blocks, increment_usage # noqa: E402
|
|
50
|
+
from tools.govcon.engine_enrichment import enrich_from_engines # noqa: E402
|
|
51
|
+
|
|
52
|
+
_DB_PATH = Path(os.environ.get("ICDEV_DB_PATH", str(_ROOT / "data" / "icdev.db")))
|
|
53
|
+
_PROMPT_PATH = _ROOT / "hardprompts" / "proposal_draft.md"
|
|
54
|
+
_METHODOLOGY_PATH = _ROOT / "context" / "icdev_methodology.md"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _get_db():
|
|
58
|
+
conn = sqlite3.connect(str(_DB_PATH))
|
|
59
|
+
conn.row_factory = sqlite3.Row
|
|
60
|
+
return conn
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _now():
|
|
64
|
+
return datetime.now(timezone.utc).isoformat()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ── Data loaders ─────────────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
def _load_section(conn, section_id):
|
|
70
|
+
row = conn.execute(
|
|
71
|
+
"SELECT * FROM proposal_sections WHERE id = ?", (section_id,)
|
|
72
|
+
).fetchone()
|
|
73
|
+
return dict(row) if row else None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _load_opportunity(conn, opportunity_id):
|
|
77
|
+
row = conn.execute(
|
|
78
|
+
"SELECT * FROM proposal_opportunities WHERE id = ?", (opportunity_id,)
|
|
79
|
+
).fetchone()
|
|
80
|
+
return dict(row) if row else None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _load_shall_statements(conn, opportunity_id, limit=20):
|
|
84
|
+
rows = conn.execute(
|
|
85
|
+
"SELECT statement_text AS shall_text, domain_category AS domain, "
|
|
86
|
+
"statement_type AS priority_level "
|
|
87
|
+
"FROM rfp_shall_statements WHERE proposal_opportunity_id = ? "
|
|
88
|
+
"ORDER BY extracted_at DESC LIMIT ?",
|
|
89
|
+
(opportunity_id, limit),
|
|
90
|
+
).fetchall()
|
|
91
|
+
return [dict(r) for r in rows]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _load_prompt_template():
|
|
95
|
+
if _PROMPT_PATH.exists():
|
|
96
|
+
return _PROMPT_PATH.read_text(encoding="utf-8")
|
|
97
|
+
return (
|
|
98
|
+
"You are a federal government proposal writer for ICDEV. "
|
|
99
|
+
"Draft the following proposal section.\n\n"
|
|
100
|
+
"## Opportunity: {opportunity_context}\n"
|
|
101
|
+
"## Requirements: {shall_statements}\n"
|
|
102
|
+
"## Reference: {knowledge_blocks}\n"
|
|
103
|
+
"## Section: {section_title} ({volume_type})\n"
|
|
104
|
+
"## Engine Enrichments: {engine_enrichments}\n"
|
|
105
|
+
"## SMART Plan: {smart_plan}\n"
|
|
106
|
+
"## Prior Sections: {prior_sections}\n"
|
|
107
|
+
"## Style: {style_hints}\n"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _load_methodology():
|
|
112
|
+
if _METHODOLOGY_PATH.exists():
|
|
113
|
+
text = _METHODOLOGY_PATH.read_text(encoding="utf-8")
|
|
114
|
+
return text[:3000]
|
|
115
|
+
return ""
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ── Formatters ───────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
def _build_search_query(section, opportunity):
|
|
121
|
+
parts = []
|
|
122
|
+
if section:
|
|
123
|
+
parts.append(section.get("title", ""))
|
|
124
|
+
if opportunity:
|
|
125
|
+
parts.append(opportunity.get("title", ""))
|
|
126
|
+
desc = opportunity.get("description", "")
|
|
127
|
+
if desc:
|
|
128
|
+
parts.append(desc[:200])
|
|
129
|
+
return " ".join(parts)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _format_opportunity_context(opp):
|
|
133
|
+
if not opp:
|
|
134
|
+
return "No opportunity context available."
|
|
135
|
+
lines = [
|
|
136
|
+
f"Title: {opp.get('title', 'N/A')}",
|
|
137
|
+
f"Solicitation: {opp.get('solicitation_number', 'N/A')}",
|
|
138
|
+
f"Agency: {opp.get('agency', 'N/A')}",
|
|
139
|
+
f"NAICS: {opp.get('naics_code', 'N/A')}",
|
|
140
|
+
f"Due Date: {opp.get('due_date', 'TBD')}",
|
|
141
|
+
f"Set-Aside: {opp.get('set_aside_type', 'None')}",
|
|
142
|
+
]
|
|
143
|
+
desc = opp.get("description", "")
|
|
144
|
+
if desc:
|
|
145
|
+
lines.append(f"\nDescription: {desc[:500]}")
|
|
146
|
+
return "\n".join(lines)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _format_shall_statements(shalls):
|
|
150
|
+
if not shalls:
|
|
151
|
+
return "No specific shall-statements extracted for this opportunity."
|
|
152
|
+
lines = []
|
|
153
|
+
for i, s in enumerate(shalls, 1):
|
|
154
|
+
priority = s.get("priority_level", "medium")
|
|
155
|
+
lines.append(f"{i}. [{priority.upper()}] {s['shall_text']}")
|
|
156
|
+
return "\n".join(lines)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _format_knowledge_blocks(blocks):
|
|
160
|
+
if not blocks:
|
|
161
|
+
return "No relevant knowledge base content found."
|
|
162
|
+
lines = []
|
|
163
|
+
for i, b in enumerate(blocks, 1):
|
|
164
|
+
lines.append(f"--- Reference {i}: {b.get('title', 'Untitled')} ---")
|
|
165
|
+
lines.append(f"Category: {b.get('category', 'N/A')} | Domain: {b.get('domain', 'N/A')}")
|
|
166
|
+
lines.append(b.get("content", ""))
|
|
167
|
+
lines.append("")
|
|
168
|
+
return "\n".join(lines)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _format_engine_enrichments(enrichment: dict) -> str:
|
|
172
|
+
if not enrichment or enrichment.get("total_results", 0) == 0:
|
|
173
|
+
return "No engine enrichment data available."
|
|
174
|
+
lines = [f"Keywords searched: {', '.join(enrichment.get('keywords', [])[:10])}"]
|
|
175
|
+
for engine in ("innovation", "creative", "research"):
|
|
176
|
+
items = enrichment.get(engine, [])
|
|
177
|
+
if items:
|
|
178
|
+
lines.append(f"\n### {engine.title()} Engine ({len(items)} results)")
|
|
179
|
+
for item in items:
|
|
180
|
+
lines.append(f"- **{item.get('title', 'N/A')}** [{item.get('source', '')}]")
|
|
181
|
+
desc = item.get("description", "")
|
|
182
|
+
if desc:
|
|
183
|
+
lines.append(f" {desc[:200]}")
|
|
184
|
+
return "\n".join(lines)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _format_prior_sections(prior_sections: list[dict]) -> str:
|
|
188
|
+
if not prior_sections:
|
|
189
|
+
return "This is the first section being drafted."
|
|
190
|
+
lines = []
|
|
191
|
+
for ps in prior_sections:
|
|
192
|
+
title = ps.get("title", "Untitled")
|
|
193
|
+
content = ps.get("draft_content", "")[:400]
|
|
194
|
+
lines.append(f"### {title}")
|
|
195
|
+
lines.append(content)
|
|
196
|
+
lines.append("")
|
|
197
|
+
return "\n".join(lines)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# ── v1 Pipeline (Phase 67 — preserved as fallback) ──────────────────────
|
|
201
|
+
|
|
202
|
+
def get_draft_context(section_id, opportunity_id, top_k=5):
|
|
203
|
+
"""Preview what context would be used for draft generation."""
|
|
204
|
+
conn = _get_db()
|
|
205
|
+
try:
|
|
206
|
+
section = _load_section(conn, section_id)
|
|
207
|
+
opportunity = _load_opportunity(conn, opportunity_id)
|
|
208
|
+
shalls = _load_shall_statements(conn, opportunity_id)
|
|
209
|
+
finally:
|
|
210
|
+
conn.close()
|
|
211
|
+
|
|
212
|
+
if not section:
|
|
213
|
+
return {"status": "error", "message": f"Section {section_id} not found"}
|
|
214
|
+
|
|
215
|
+
query = _build_search_query(section, opportunity)
|
|
216
|
+
volume_type = section.get("volume_type") or "technical"
|
|
217
|
+
domain_hint = "management" if volume_type == "management" else None
|
|
218
|
+
|
|
219
|
+
kb_result = search_blocks(query, domain=domain_hint, top_k=top_k)
|
|
220
|
+
kb_blocks = kb_result.get("results", []) if kb_result.get("status") == "ok" else []
|
|
221
|
+
|
|
222
|
+
template = _load_prompt_template()
|
|
223
|
+
filled = template.format(
|
|
224
|
+
opportunity_context=_format_opportunity_context(opportunity),
|
|
225
|
+
shall_statements=_format_shall_statements(shalls),
|
|
226
|
+
knowledge_blocks=_format_knowledge_blocks(kb_blocks),
|
|
227
|
+
section_title=section.get("title", "Untitled Section"),
|
|
228
|
+
volume_type=volume_type,
|
|
229
|
+
engine_enrichments="(preview only)",
|
|
230
|
+
smart_plan="(preview only)",
|
|
231
|
+
prior_sections="(preview only)",
|
|
232
|
+
style_hints="(preview only)",
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
"status": "ok",
|
|
237
|
+
"section": section,
|
|
238
|
+
"opportunity": opportunity,
|
|
239
|
+
"shall_statements": shalls,
|
|
240
|
+
"knowledge_blocks": kb_blocks,
|
|
241
|
+
"knowledge_block_ids": [b["id"] for b in kb_blocks],
|
|
242
|
+
"prompt_preview": filled[:2000],
|
|
243
|
+
"prompt_length": len(filled),
|
|
244
|
+
"classification": "CUI // SP-CTI",
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def generate_draft(section_id, opportunity_id, top_k=5, force_regenerate=False):
|
|
249
|
+
"""v1 RAG-assisted draft generation (Phase 67 — kept as fallback)."""
|
|
250
|
+
conn = _get_db()
|
|
251
|
+
try:
|
|
252
|
+
section = _load_section(conn, section_id)
|
|
253
|
+
opportunity = _load_opportunity(conn, opportunity_id)
|
|
254
|
+
shalls = _load_shall_statements(conn, opportunity_id)
|
|
255
|
+
finally:
|
|
256
|
+
conn.close()
|
|
257
|
+
|
|
258
|
+
if not section:
|
|
259
|
+
return {"status": "error", "message": f"Section {section_id} not found"}
|
|
260
|
+
|
|
261
|
+
if not force_regenerate:
|
|
262
|
+
conn = _get_db()
|
|
263
|
+
existing = conn.execute(
|
|
264
|
+
"SELECT id, draft_content FROM proposal_section_drafts "
|
|
265
|
+
"WHERE section_id = ? AND status != 'rejected'",
|
|
266
|
+
(section_id,),
|
|
267
|
+
).fetchone()
|
|
268
|
+
conn.close()
|
|
269
|
+
if existing and existing["draft_content"]:
|
|
270
|
+
return {
|
|
271
|
+
"status": "ok",
|
|
272
|
+
"draft_content": existing["draft_content"],
|
|
273
|
+
"draft_id": existing["id"],
|
|
274
|
+
"message": "Existing draft found. Use force_regenerate=True to overwrite.",
|
|
275
|
+
"was_cached": True,
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
query = _build_search_query(section, opportunity)
|
|
279
|
+
volume_type = section.get("volume_type") or "technical"
|
|
280
|
+
domain_hint = "management" if volume_type == "management" else None
|
|
281
|
+
|
|
282
|
+
kb_result = search_blocks(query, domain=domain_hint, top_k=top_k)
|
|
283
|
+
kb_blocks = kb_result.get("results", []) if kb_result.get("status") == "ok" else []
|
|
284
|
+
kb_ids = [b["id"] for b in kb_blocks]
|
|
285
|
+
|
|
286
|
+
template = _load_prompt_template()
|
|
287
|
+
system_prompt = template.format(
|
|
288
|
+
opportunity_context=_format_opportunity_context(opportunity),
|
|
289
|
+
shall_statements=_format_shall_statements(shalls),
|
|
290
|
+
knowledge_blocks=_format_knowledge_blocks(kb_blocks),
|
|
291
|
+
section_title=section.get("title", "Untitled Section"),
|
|
292
|
+
volume_type=volume_type,
|
|
293
|
+
engine_enrichments="N/A (v1 pipeline)",
|
|
294
|
+
smart_plan="N/A (v1 pipeline)",
|
|
295
|
+
prior_sections="N/A (v1 pipeline)",
|
|
296
|
+
style_hints="N/A (v1 pipeline)",
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
generation_model = "none"
|
|
300
|
+
draft_content = ""
|
|
301
|
+
|
|
302
|
+
try:
|
|
303
|
+
from tools.llm.router import LLMRouter
|
|
304
|
+
from tools.llm.provider import LLMRequest
|
|
305
|
+
|
|
306
|
+
router = LLMRouter()
|
|
307
|
+
request = LLMRequest(
|
|
308
|
+
messages=[{"role": "user", "content": f"Draft the '{section.get('title', '')}' section."}],
|
|
309
|
+
system_prompt=system_prompt,
|
|
310
|
+
max_tokens=4096,
|
|
311
|
+
temperature=0.7,
|
|
312
|
+
effort="high",
|
|
313
|
+
classification="CUI // SP-CTI",
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
response = router.invoke("proposal_drafting", request)
|
|
317
|
+
draft_content = response.content
|
|
318
|
+
generation_model = response.model_id or response.provider or "unknown"
|
|
319
|
+
|
|
320
|
+
except Exception:
|
|
321
|
+
draft_content = _generate_placeholder_draft(section, opportunity, shalls, kb_blocks)
|
|
322
|
+
generation_model = "placeholder_no_llm"
|
|
323
|
+
|
|
324
|
+
if not draft_content:
|
|
325
|
+
return {"status": "error", "message": "Draft generation produced empty content"}
|
|
326
|
+
|
|
327
|
+
conn = _get_db()
|
|
328
|
+
try:
|
|
329
|
+
draft_id = str(uuid.uuid4())
|
|
330
|
+
now = _now()
|
|
331
|
+
|
|
332
|
+
existing = conn.execute(
|
|
333
|
+
"SELECT id FROM proposal_section_drafts WHERE section_id = ?",
|
|
334
|
+
(section_id,),
|
|
335
|
+
).fetchone()
|
|
336
|
+
|
|
337
|
+
if existing:
|
|
338
|
+
conn.execute(
|
|
339
|
+
"UPDATE proposal_section_drafts "
|
|
340
|
+
"SET draft_content = ?, generation_model = ?, "
|
|
341
|
+
"knowledge_block_ids = ?, status = 'draft', confidence = 0.7 "
|
|
342
|
+
"WHERE id = ?",
|
|
343
|
+
(draft_content, generation_model, json.dumps(kb_ids), existing["id"]),
|
|
344
|
+
)
|
|
345
|
+
draft_id = existing["id"]
|
|
346
|
+
else:
|
|
347
|
+
conn.execute(
|
|
348
|
+
"INSERT INTO proposal_section_drafts "
|
|
349
|
+
"(id, section_id, opportunity_id, draft_content, "
|
|
350
|
+
"generation_model, knowledge_block_ids, status, confidence, "
|
|
351
|
+
"classification, created_at) "
|
|
352
|
+
"VALUES (?, ?, ?, ?, ?, ?, 'draft', 0.7, 'CUI // SP-CTI', ?)",
|
|
353
|
+
(draft_id, section_id, opportunity_id, draft_content,
|
|
354
|
+
generation_model, json.dumps(kb_ids), now),
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
conn.commit()
|
|
358
|
+
finally:
|
|
359
|
+
conn.close()
|
|
360
|
+
|
|
361
|
+
for block_id in kb_ids:
|
|
362
|
+
try:
|
|
363
|
+
increment_usage(block_id)
|
|
364
|
+
except Exception:
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
"status": "ok",
|
|
369
|
+
"draft_id": draft_id,
|
|
370
|
+
"draft_content": draft_content,
|
|
371
|
+
"generation_model": generation_model,
|
|
372
|
+
"knowledge_blocks_used": len(kb_ids),
|
|
373
|
+
"knowledge_block_ids": kb_ids,
|
|
374
|
+
"shall_statements_count": len(shalls),
|
|
375
|
+
"draft_method": "rag_assisted",
|
|
376
|
+
"pipeline_version": "v1",
|
|
377
|
+
"was_cached": False,
|
|
378
|
+
"classification": "CUI // SP-CTI",
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
# ── v2 Pipeline (Phase 68 — Enhanced 4-Step) ────────────────────────────
|
|
383
|
+
|
|
384
|
+
def generate_draft_v2(section_id, opportunity_id, top_k=5,
|
|
385
|
+
force_regenerate=False, job_id=None,
|
|
386
|
+
prior_sections_context=None):
|
|
387
|
+
"""Enhanced 4-step pipeline:
|
|
388
|
+
|
|
389
|
+
1. KB Retrieval — search_blocks() + methodology blocks
|
|
390
|
+
2. Engine Enrichment — enrich_from_engines() (DB queries only)
|
|
391
|
+
3. SMART Solutioning — LLM generates structured SMART plan
|
|
392
|
+
4. Content Generation — LLM draft + WriteGuard post-check + auto-rewrite
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
section_id: Proposal section ID
|
|
396
|
+
opportunity_id: Opportunity ID
|
|
397
|
+
top_k: Number of KB blocks to retrieve
|
|
398
|
+
force_regenerate: Skip existing draft check
|
|
399
|
+
job_id: Optional batch job ID for progress tracking
|
|
400
|
+
prior_sections_context: List of prior section dicts for coherence
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
dict with draft_content, pipeline steps, quality score, etc.
|
|
404
|
+
"""
|
|
405
|
+
steps_log = []
|
|
406
|
+
|
|
407
|
+
def _log_step(step_name, detail, status="completed"):
|
|
408
|
+
entry = {"step": step_name, "detail": detail, "status": status, "ts": _now()}
|
|
409
|
+
steps_log.append(entry)
|
|
410
|
+
if job_id:
|
|
411
|
+
_update_job_step(job_id, section_id, step_name, detail, status)
|
|
412
|
+
|
|
413
|
+
# Load context
|
|
414
|
+
conn = _get_db()
|
|
415
|
+
try:
|
|
416
|
+
section = _load_section(conn, section_id)
|
|
417
|
+
opportunity = _load_opportunity(conn, opportunity_id)
|
|
418
|
+
shalls = _load_shall_statements(conn, opportunity_id)
|
|
419
|
+
finally:
|
|
420
|
+
conn.close()
|
|
421
|
+
|
|
422
|
+
if not section:
|
|
423
|
+
return {"status": "error", "message": f"Section {section_id} not found"}
|
|
424
|
+
|
|
425
|
+
section_title = section.get("title", "Untitled Section")
|
|
426
|
+
|
|
427
|
+
# Check existing draft
|
|
428
|
+
if not force_regenerate:
|
|
429
|
+
conn = _get_db()
|
|
430
|
+
existing = conn.execute(
|
|
431
|
+
"SELECT id, draft_content, pipeline_version FROM proposal_section_drafts "
|
|
432
|
+
"WHERE section_id = ? AND status != 'rejected'",
|
|
433
|
+
(section_id,),
|
|
434
|
+
).fetchone()
|
|
435
|
+
conn.close()
|
|
436
|
+
if existing and existing["draft_content"]:
|
|
437
|
+
return {
|
|
438
|
+
"status": "ok",
|
|
439
|
+
"draft_content": existing["draft_content"],
|
|
440
|
+
"draft_id": existing["id"],
|
|
441
|
+
"message": "Existing draft found. Use force_regenerate=True to overwrite.",
|
|
442
|
+
"was_cached": True,
|
|
443
|
+
"pipeline_version": existing["pipeline_version"] or "v1",
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
# ── Step 1: KB Retrieval ─────────────────────────────────────────────
|
|
447
|
+
_log_step("kb_retrieval", f"Searching knowledge base for '{section_title}'", "running")
|
|
448
|
+
|
|
449
|
+
query = _build_search_query(section, opportunity)
|
|
450
|
+
volume_type = section.get("volume_type") or "technical"
|
|
451
|
+
domain_hint = "management" if volume_type == "management" else None
|
|
452
|
+
|
|
453
|
+
kb_result = search_blocks(query, domain=domain_hint, top_k=top_k)
|
|
454
|
+
kb_blocks = kb_result.get("results", []) if kb_result.get("status") == "ok" else []
|
|
455
|
+
kb_ids = [b["id"] for b in kb_blocks]
|
|
456
|
+
|
|
457
|
+
# Also search for methodology blocks
|
|
458
|
+
meth_result = search_blocks("GOTCHA ATLAS methodology framework", top_k=3)
|
|
459
|
+
meth_blocks = meth_result.get("results", []) if meth_result.get("status") == "ok" else []
|
|
460
|
+
|
|
461
|
+
_log_step("kb_retrieval", f"Found {len(kb_blocks)} KB blocks, {len(meth_blocks)} methodology blocks")
|
|
462
|
+
|
|
463
|
+
# ── Step 2: Engine Enrichment ────────────────────────────────────────
|
|
464
|
+
_log_step("engine_enrichment", "Querying Innovation, Creative, Research engines", "running")
|
|
465
|
+
|
|
466
|
+
enrichment = enrich_from_engines(section, opportunity, shalls, top_k=top_k)
|
|
467
|
+
enrichment_ids = enrichment.get("enrichment_ids", [])
|
|
468
|
+
|
|
469
|
+
_log_step("engine_enrichment",
|
|
470
|
+
f"Found {enrichment.get('total_results', 0)} results across 3 engines")
|
|
471
|
+
|
|
472
|
+
# ── Step 3: SMART Solutioning ────────────────────────────────────────
|
|
473
|
+
_log_step("smart_solutioning", "Generating SMART plan", "running")
|
|
474
|
+
|
|
475
|
+
methodology_text = _load_methodology()
|
|
476
|
+
smart_plan = _generate_smart_plan(
|
|
477
|
+
section, opportunity, shalls, kb_blocks, meth_blocks,
|
|
478
|
+
enrichment, methodology_text
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
_log_step("smart_solutioning",
|
|
482
|
+
f"SMART plan generated ({len(smart_plan)} chars)")
|
|
483
|
+
|
|
484
|
+
# ── Step 4: Content Generation + Quality Gate ────────────────────────
|
|
485
|
+
_log_step("content_generation", "Generating draft content", "running")
|
|
486
|
+
|
|
487
|
+
# Build style hints
|
|
488
|
+
style_hints = (
|
|
489
|
+
"- Write in active voice, direct and authoritative\n"
|
|
490
|
+
"- Reference ICDEV frameworks by name when the SMART plan calls for them\n"
|
|
491
|
+
"- Include measurable outcomes (KPIs, metrics) from the SMART plan\n"
|
|
492
|
+
"- Maintain terminology consistency with prior sections"
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
# Fill enhanced prompt template
|
|
496
|
+
template = _load_prompt_template()
|
|
497
|
+
system_prompt = template.format(
|
|
498
|
+
opportunity_context=_format_opportunity_context(opportunity),
|
|
499
|
+
shall_statements=_format_shall_statements(shalls),
|
|
500
|
+
knowledge_blocks=_format_knowledge_blocks(kb_blocks + meth_blocks),
|
|
501
|
+
engine_enrichments=_format_engine_enrichments(enrichment),
|
|
502
|
+
smart_plan=smart_plan,
|
|
503
|
+
prior_sections=_format_prior_sections(prior_sections_context or []),
|
|
504
|
+
section_title=section_title,
|
|
505
|
+
volume_type=volume_type,
|
|
506
|
+
style_hints=style_hints,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
generation_model = "none"
|
|
510
|
+
draft_content = ""
|
|
511
|
+
|
|
512
|
+
try:
|
|
513
|
+
from tools.llm.router import LLMRouter
|
|
514
|
+
from tools.llm.provider import LLMRequest
|
|
515
|
+
|
|
516
|
+
router = LLMRouter()
|
|
517
|
+
request = LLMRequest(
|
|
518
|
+
messages=[{"role": "user", "content": f"Draft the '{section_title}' section."}],
|
|
519
|
+
system_prompt=system_prompt,
|
|
520
|
+
max_tokens=4096,
|
|
521
|
+
temperature=0.7,
|
|
522
|
+
effort="high",
|
|
523
|
+
classification="CUI // SP-CTI",
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
response = router.invoke("proposal_drafting", request)
|
|
527
|
+
draft_content = response.content
|
|
528
|
+
generation_model = response.model_id or response.provider or "unknown"
|
|
529
|
+
|
|
530
|
+
except Exception:
|
|
531
|
+
draft_content = _generate_placeholder_draft_v2(
|
|
532
|
+
section, opportunity, shalls, kb_blocks, enrichment, smart_plan
|
|
533
|
+
)
|
|
534
|
+
generation_model = "placeholder_no_llm"
|
|
535
|
+
|
|
536
|
+
if not draft_content:
|
|
537
|
+
return {"status": "error", "message": "Draft generation produced empty content"}
|
|
538
|
+
|
|
539
|
+
_log_step("content_generation",
|
|
540
|
+
f"Draft generated ({len(draft_content)} chars) via {generation_model}")
|
|
541
|
+
|
|
542
|
+
# ── WriteGuard post-check ────────────────────────────────────────────
|
|
543
|
+
writeguard_score = None
|
|
544
|
+
writeguard_result_id = None
|
|
545
|
+
was_auto_rewritten = False
|
|
546
|
+
|
|
547
|
+
try:
|
|
548
|
+
from tools.writeguard.analyzer import analyze as wg_analyze
|
|
549
|
+
|
|
550
|
+
wg_result = wg_analyze(draft_content, skip_llm=True)
|
|
551
|
+
if wg_result and wg_result.get("status") == "ok":
|
|
552
|
+
writeguard_score = wg_result.get("overall_quality_score", 0)
|
|
553
|
+
writeguard_result_id = wg_result.get("result_id")
|
|
554
|
+
|
|
555
|
+
_log_step("quality_check",
|
|
556
|
+
f"WriteGuard score: {writeguard_score}")
|
|
557
|
+
|
|
558
|
+
# Auto-rewrite if score < 60
|
|
559
|
+
if writeguard_score and writeguard_score < 60:
|
|
560
|
+
_log_step("auto_rewrite", "Quality below 60, attempting rewrite", "running")
|
|
561
|
+
try:
|
|
562
|
+
from tools.writeguard.rewriter import rewrite as wg_rewrite
|
|
563
|
+
|
|
564
|
+
rewrite_result = wg_rewrite(
|
|
565
|
+
draft_content,
|
|
566
|
+
findings=wg_result.get("findings", []),
|
|
567
|
+
skip_llm=True,
|
|
568
|
+
)
|
|
569
|
+
if rewrite_result and rewrite_result.get("status") == "ok":
|
|
570
|
+
rewritten = rewrite_result.get("rewritten_text", "")
|
|
571
|
+
if rewritten:
|
|
572
|
+
draft_content = rewritten
|
|
573
|
+
was_auto_rewritten = True
|
|
574
|
+
# Re-check score
|
|
575
|
+
wg2 = wg_analyze(draft_content, skip_llm=True)
|
|
576
|
+
if wg2 and wg2.get("status") == "ok":
|
|
577
|
+
writeguard_score = wg2.get("overall_quality_score", writeguard_score)
|
|
578
|
+
_log_step("auto_rewrite",
|
|
579
|
+
f"Rewritten. New score: {writeguard_score}")
|
|
580
|
+
except Exception:
|
|
581
|
+
_log_step("auto_rewrite", "Rewriter unavailable, keeping original", "skipped")
|
|
582
|
+
except ImportError:
|
|
583
|
+
_log_step("quality_check", "WriteGuard not available, skipping", "skipped")
|
|
584
|
+
|
|
585
|
+
# ── Save draft ───────────────────────────────────────────────────────
|
|
586
|
+
conn = _get_db()
|
|
587
|
+
try:
|
|
588
|
+
draft_id = str(uuid.uuid4())
|
|
589
|
+
now = _now()
|
|
590
|
+
|
|
591
|
+
existing = conn.execute(
|
|
592
|
+
"SELECT id FROM proposal_section_drafts WHERE section_id = ?",
|
|
593
|
+
(section_id,),
|
|
594
|
+
).fetchone()
|
|
595
|
+
|
|
596
|
+
if existing:
|
|
597
|
+
conn.execute(
|
|
598
|
+
"UPDATE proposal_section_drafts "
|
|
599
|
+
"SET draft_content = ?, generation_model = ?, "
|
|
600
|
+
"knowledge_block_ids = ?, engine_enrichment_ids = ?, "
|
|
601
|
+
"smart_plan = ?, writeguard_score = ?, writeguard_result_id = ?, "
|
|
602
|
+
"was_auto_rewritten = ?, pipeline_version = 'v2', "
|
|
603
|
+
"status = 'draft', confidence = 0.8 "
|
|
604
|
+
"WHERE id = ?",
|
|
605
|
+
(draft_content, generation_model,
|
|
606
|
+
json.dumps(kb_ids), json.dumps(enrichment_ids),
|
|
607
|
+
smart_plan, writeguard_score, writeguard_result_id,
|
|
608
|
+
1 if was_auto_rewritten else 0,
|
|
609
|
+
existing["id"]),
|
|
610
|
+
)
|
|
611
|
+
draft_id = existing["id"]
|
|
612
|
+
else:
|
|
613
|
+
conn.execute(
|
|
614
|
+
"INSERT INTO proposal_section_drafts "
|
|
615
|
+
"(id, section_id, opportunity_id, draft_content, "
|
|
616
|
+
"generation_model, knowledge_block_ids, engine_enrichment_ids, "
|
|
617
|
+
"smart_plan, writeguard_score, writeguard_result_id, "
|
|
618
|
+
"was_auto_rewritten, pipeline_version, "
|
|
619
|
+
"status, confidence, classification, created_at) "
|
|
620
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'v2', 'draft', 0.8, 'CUI // SP-CTI', ?)",
|
|
621
|
+
(draft_id, section_id, opportunity_id, draft_content,
|
|
622
|
+
generation_model, json.dumps(kb_ids), json.dumps(enrichment_ids),
|
|
623
|
+
smart_plan, writeguard_score, writeguard_result_id,
|
|
624
|
+
1 if was_auto_rewritten else 0, now),
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
# Flag needs_review if still low quality after rewrite
|
|
628
|
+
if writeguard_score is not None and writeguard_score < 60:
|
|
629
|
+
conn.execute(
|
|
630
|
+
"UPDATE proposal_section_drafts SET status = 'draft' "
|
|
631
|
+
"WHERE id = ? AND status = 'draft'",
|
|
632
|
+
(draft_id,),
|
|
633
|
+
)
|
|
634
|
+
_log_step("quality_gate", "Score still < 60 after rewrite. Flagged for human review.")
|
|
635
|
+
|
|
636
|
+
conn.commit()
|
|
637
|
+
finally:
|
|
638
|
+
conn.close()
|
|
639
|
+
|
|
640
|
+
for block_id in kb_ids:
|
|
641
|
+
try:
|
|
642
|
+
increment_usage(block_id)
|
|
643
|
+
except Exception:
|
|
644
|
+
pass
|
|
645
|
+
|
|
646
|
+
return {
|
|
647
|
+
"status": "ok",
|
|
648
|
+
"draft_id": draft_id,
|
|
649
|
+
"draft_content": draft_content,
|
|
650
|
+
"generation_model": generation_model,
|
|
651
|
+
"knowledge_blocks_used": kb_blocks,
|
|
652
|
+
"knowledge_block_ids": kb_ids,
|
|
653
|
+
"engine_enrichments": enrichment,
|
|
654
|
+
"smart_plan": smart_plan,
|
|
655
|
+
"writeguard_score": writeguard_score,
|
|
656
|
+
"was_auto_rewritten": was_auto_rewritten,
|
|
657
|
+
"pipeline_version": "v2",
|
|
658
|
+
"pipeline_steps": steps_log,
|
|
659
|
+
"shall_statements_count": len(shalls),
|
|
660
|
+
"was_cached": False,
|
|
661
|
+
"classification": "CUI // SP-CTI",
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
# ── SMART Plan Generator ────────────────────────────────────────────────
|
|
666
|
+
|
|
667
|
+
def _generate_smart_plan(section, opportunity, shalls, kb_blocks,
|
|
668
|
+
meth_blocks, enrichment, methodology_text):
|
|
669
|
+
"""Generate a SMART plan using LLM or deterministic fallback."""
|
|
670
|
+
section_title = section.get("title", "Section") if section else "Section"
|
|
671
|
+
|
|
672
|
+
# Build SMART prompt
|
|
673
|
+
smart_context = [
|
|
674
|
+
"Generate a SMART solution plan for this proposal section.\n",
|
|
675
|
+
f"Section: {section_title}",
|
|
676
|
+
f"Opportunity: {opportunity.get('title', 'N/A') if opportunity else 'N/A'}",
|
|
677
|
+
]
|
|
678
|
+
|
|
679
|
+
if shalls:
|
|
680
|
+
smart_context.append("\nRequirements to address:")
|
|
681
|
+
for i, s in enumerate(shalls[:5], 1):
|
|
682
|
+
smart_context.append(f" {i}. {s['shall_text'][:150]}")
|
|
683
|
+
|
|
684
|
+
if methodology_text:
|
|
685
|
+
smart_context.append(f"\nICDEV Methodology Reference:\n{methodology_text[:1500]}")
|
|
686
|
+
|
|
687
|
+
if enrichment and enrichment.get("total_results", 0) > 0:
|
|
688
|
+
smart_context.append("\nEngine insights available:")
|
|
689
|
+
for engine in ("innovation", "creative", "research"):
|
|
690
|
+
items = enrichment.get(engine, [])
|
|
691
|
+
for item in items[:2]:
|
|
692
|
+
smart_context.append(f" - [{engine}] {item.get('title', '')}")
|
|
693
|
+
|
|
694
|
+
smart_context.append(
|
|
695
|
+
"\nOutput a SMART plan with these sections:\n"
|
|
696
|
+
"- **Specific:** What ICDEV tools/frameworks address each requirement?\n"
|
|
697
|
+
"- **Measurable:** What KPIs/evidence demonstrate compliance?\n"
|
|
698
|
+
"- **Achievable:** What proven patterns enable delivery?\n"
|
|
699
|
+
"- **Relevant:** How does this align with the customer's mission?\n"
|
|
700
|
+
"- **Time-bound:** What is the phased delivery approach?\n"
|
|
701
|
+
)
|
|
702
|
+
|
|
703
|
+
smart_prompt = "\n".join(smart_context)
|
|
704
|
+
|
|
705
|
+
# Try LLM
|
|
706
|
+
try:
|
|
707
|
+
from tools.llm.router import LLMRouter
|
|
708
|
+
from tools.llm.provider import LLMRequest
|
|
709
|
+
|
|
710
|
+
router = LLMRouter()
|
|
711
|
+
request = LLMRequest(
|
|
712
|
+
messages=[{"role": "user", "content": smart_prompt}],
|
|
713
|
+
system_prompt=(
|
|
714
|
+
"You are an ICDEV solution architect. Generate a concise SMART plan "
|
|
715
|
+
"that maps ICDEV frameworks (GOTCHA, ATLAS, RICOAS, ZTA) to the "
|
|
716
|
+
"proposal requirements. Be specific about tools and deliverables. "
|
|
717
|
+
"Keep it under 800 words."
|
|
718
|
+
),
|
|
719
|
+
max_tokens=2048,
|
|
720
|
+
temperature=0.5,
|
|
721
|
+
effort="high",
|
|
722
|
+
classification="CUI // SP-CTI",
|
|
723
|
+
)
|
|
724
|
+
|
|
725
|
+
response = router.invoke("proposal_drafting", request)
|
|
726
|
+
return response.content or _deterministic_smart_plan(section, shalls, kb_blocks)
|
|
727
|
+
|
|
728
|
+
except Exception:
|
|
729
|
+
return _deterministic_smart_plan(section, shalls, kb_blocks)
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
def _deterministic_smart_plan(section, shalls, kb_blocks):
|
|
733
|
+
"""Deterministic SMART plan when LLM is unavailable."""
|
|
734
|
+
title = section.get("title", "Section") if section else "Section"
|
|
735
|
+
lines = [
|
|
736
|
+
f"## SMART Plan: {title}\n",
|
|
737
|
+
"### Specific",
|
|
738
|
+
"- ICDEV addresses each requirement using the GOTCHA 6-layer framework",
|
|
739
|
+
"- Deterministic Python tools execute compliance checks, code generation, and security scans",
|
|
740
|
+
"- ATLAS workflow (Architect→Trace→Link→Assemble→Stress-test) ensures structured delivery",
|
|
741
|
+
]
|
|
742
|
+
|
|
743
|
+
if shalls:
|
|
744
|
+
lines.append("")
|
|
745
|
+
for i, s in enumerate(shalls[:3], 1):
|
|
746
|
+
lines.append(f"- Requirement {i}: Addressed via GOTCHA Tools layer + ATLAS Assemble phase")
|
|
747
|
+
|
|
748
|
+
lines.extend([
|
|
749
|
+
"\n### Measurable",
|
|
750
|
+
"- 100% traceability: every requirement mapped to implementation via digital thread",
|
|
751
|
+
"- Compliance crosswalk: single NIST 800-53 control auto-populates 8 frameworks",
|
|
752
|
+
"- Code quality: cyclomatic complexity < 25, zero CAT1 STIG findings",
|
|
753
|
+
"\n### Achievable",
|
|
754
|
+
"- Proven patterns from knowledge base with >60 reusable content blocks",
|
|
755
|
+
"- 11 specialized agents handle domain-specific tasks autonomously",
|
|
756
|
+
"- Two-tier LLM architecture ensures 95%+ accuracy across multi-step workflows",
|
|
757
|
+
"\n### Relevant",
|
|
758
|
+
"- Zero Trust Architecture aligned with DoD 7-pillar strategy",
|
|
759
|
+
"- CUI markings at generation time (not post-processing)",
|
|
760
|
+
"- Air-gap safe: all tools run on local SQLite, no external dependencies required",
|
|
761
|
+
"\n### Time-bound",
|
|
762
|
+
"- Sprint 1-2: Architecture and requirements decomposition (ATLAS A/T phases)",
|
|
763
|
+
"- Sprint 3-4: Implementation with TDD (ATLAS L/A phases)",
|
|
764
|
+
"- Sprint 5: Stress testing, compliance gates, ATO evidence collection (ATLAS S phase)",
|
|
765
|
+
])
|
|
766
|
+
|
|
767
|
+
return "\n".join(lines)
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
# ── Placeholder v2 ──────────────────────────────────────────────────────
|
|
771
|
+
|
|
772
|
+
def _generate_placeholder_draft(section, opportunity, shalls, kb_blocks):
|
|
773
|
+
"""v1 placeholder when no LLM is available."""
|
|
774
|
+
lines = ["CUI // SP-CTI\n"]
|
|
775
|
+
title = section.get("title", "Section") if section else "Section"
|
|
776
|
+
lines.append(f"# {title}\n")
|
|
777
|
+
|
|
778
|
+
if opportunity:
|
|
779
|
+
lines.append(f"**Solicitation:** {opportunity.get('solicitation_number', 'N/A')}")
|
|
780
|
+
lines.append(f"**Agency:** {opportunity.get('agency', 'N/A')}\n")
|
|
781
|
+
|
|
782
|
+
if shalls:
|
|
783
|
+
lines.append("## Requirements Addressed\n")
|
|
784
|
+
for i, s in enumerate(shalls[:5], 1):
|
|
785
|
+
lines.append(f"{i}. {s['shall_text'][:200]}")
|
|
786
|
+
lines.append("")
|
|
787
|
+
|
|
788
|
+
if kb_blocks:
|
|
789
|
+
lines.append("## Relevant Capabilities\n")
|
|
790
|
+
for b in kb_blocks[:3]:
|
|
791
|
+
lines.append(f"### {b.get('title', 'Capability')}\n")
|
|
792
|
+
lines.append(b.get("content", "")[:500])
|
|
793
|
+
lines.append("")
|
|
794
|
+
|
|
795
|
+
lines.append(
|
|
796
|
+
"\n*[NOTE: This is a placeholder draft assembled from knowledge base content. "
|
|
797
|
+
"An LLM-generated version will provide better prose when a language model is available.]*"
|
|
798
|
+
)
|
|
799
|
+
|
|
800
|
+
return "\n".join(lines)
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
def _generate_placeholder_draft_v2(section, opportunity, shalls,
|
|
804
|
+
kb_blocks, enrichment, smart_plan):
|
|
805
|
+
"""v2 placeholder with enrichment and SMART plan context."""
|
|
806
|
+
lines = ["CUI // SP-CTI\n"]
|
|
807
|
+
title = section.get("title", "Section") if section else "Section"
|
|
808
|
+
lines.append(f"# {title}\n")
|
|
809
|
+
|
|
810
|
+
if opportunity:
|
|
811
|
+
lines.append(f"**Solicitation:** {opportunity.get('solicitation_number', 'N/A')}")
|
|
812
|
+
lines.append(f"**Agency:** {opportunity.get('agency', 'N/A')}\n")
|
|
813
|
+
|
|
814
|
+
if smart_plan:
|
|
815
|
+
lines.append("## Solution Approach\n")
|
|
816
|
+
lines.append(smart_plan[:1000])
|
|
817
|
+
lines.append("")
|
|
818
|
+
|
|
819
|
+
if shalls:
|
|
820
|
+
lines.append("## Requirements Addressed\n")
|
|
821
|
+
for i, s in enumerate(shalls[:5], 1):
|
|
822
|
+
lines.append(f"{i}. {s['shall_text'][:200]}")
|
|
823
|
+
lines.append("")
|
|
824
|
+
|
|
825
|
+
if kb_blocks:
|
|
826
|
+
lines.append("## Relevant Capabilities\n")
|
|
827
|
+
for b in kb_blocks[:3]:
|
|
828
|
+
lines.append(f"### {b.get('title', 'Capability')}\n")
|
|
829
|
+
lines.append(b.get("content", "")[:500])
|
|
830
|
+
lines.append("")
|
|
831
|
+
|
|
832
|
+
if enrichment and enrichment.get("total_results", 0) > 0:
|
|
833
|
+
lines.append("## Market & Technical Context\n")
|
|
834
|
+
for engine in ("innovation", "creative", "research"):
|
|
835
|
+
for item in enrichment.get(engine, [])[:2]:
|
|
836
|
+
lines.append(f"- **{item.get('title', '')}**: {item.get('description', '')[:150]}")
|
|
837
|
+
lines.append("")
|
|
838
|
+
|
|
839
|
+
lines.append(
|
|
840
|
+
"\n*[NOTE: This is an enhanced placeholder draft (v2 pipeline). "
|
|
841
|
+
"An LLM-generated version will provide better prose when a language model is available.]*"
|
|
842
|
+
)
|
|
843
|
+
|
|
844
|
+
return "\n".join(lines)
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
# ── Batch Generation ─────────────────────────────────────────────────────
|
|
848
|
+
|
|
849
|
+
def _resolve_generation_order(conn, opportunity_id):
|
|
850
|
+
"""Kahn's topological sort on proposal_section_dependencies.
|
|
851
|
+
|
|
852
|
+
Falls back to sort_order if no dependencies exist or cycle detected.
|
|
853
|
+
"""
|
|
854
|
+
# Get all sections for this opportunity
|
|
855
|
+
sections = conn.execute(
|
|
856
|
+
"SELECT ps.id, ps.title, ps.sort_order, ps.volume_id "
|
|
857
|
+
"FROM proposal_sections ps "
|
|
858
|
+
"JOIN proposal_volumes pv ON ps.volume_id = pv.id "
|
|
859
|
+
"WHERE pv.opportunity_id = ? "
|
|
860
|
+
"ORDER BY pv.volume_number, ps.sort_order",
|
|
861
|
+
(opportunity_id,),
|
|
862
|
+
).fetchall()
|
|
863
|
+
sections = [dict(s) for s in sections]
|
|
864
|
+
|
|
865
|
+
if not sections:
|
|
866
|
+
return []
|
|
867
|
+
|
|
868
|
+
section_ids = {s["id"] for s in sections}
|
|
869
|
+
section_map = {s["id"]: s for s in sections}
|
|
870
|
+
|
|
871
|
+
# Load dependencies
|
|
872
|
+
deps = conn.execute(
|
|
873
|
+
"SELECT section_id, depends_on_section_id "
|
|
874
|
+
"FROM proposal_section_dependencies "
|
|
875
|
+
"WHERE section_id IN ({})".format(",".join("?" * len(section_ids))),
|
|
876
|
+
list(section_ids),
|
|
877
|
+
).fetchall()
|
|
878
|
+
|
|
879
|
+
if not deps:
|
|
880
|
+
# No dependencies — use sort_order
|
|
881
|
+
return sections
|
|
882
|
+
|
|
883
|
+
# Build adjacency list and in-degree count
|
|
884
|
+
in_degree = {s["id"]: 0 for s in sections}
|
|
885
|
+
adjacency = {s["id"]: [] for s in sections}
|
|
886
|
+
|
|
887
|
+
for d in deps:
|
|
888
|
+
src = d["depends_on_section_id"]
|
|
889
|
+
dst = d["section_id"]
|
|
890
|
+
if src in section_ids and dst in section_ids:
|
|
891
|
+
adjacency[src].append(dst)
|
|
892
|
+
in_degree[dst] = in_degree.get(dst, 0) + 1
|
|
893
|
+
|
|
894
|
+
# Kahn's algorithm
|
|
895
|
+
queue = collections.deque()
|
|
896
|
+
for sid in in_degree:
|
|
897
|
+
if in_degree[sid] == 0:
|
|
898
|
+
queue.append(sid)
|
|
899
|
+
|
|
900
|
+
ordered = []
|
|
901
|
+
while queue:
|
|
902
|
+
node = queue.popleft()
|
|
903
|
+
ordered.append(section_map[node])
|
|
904
|
+
for neighbor in adjacency.get(node, []):
|
|
905
|
+
in_degree[neighbor] -= 1
|
|
906
|
+
if in_degree[neighbor] == 0:
|
|
907
|
+
queue.append(neighbor)
|
|
908
|
+
|
|
909
|
+
if len(ordered) != len(sections):
|
|
910
|
+
# Cycle detected — fallback to sort_order
|
|
911
|
+
return sections
|
|
912
|
+
|
|
913
|
+
return ordered
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
def _update_job_step(job_id, section_id, step_name, detail, status="running"):
|
|
917
|
+
"""Append step progress to draft_generation_jobs."""
|
|
918
|
+
try:
|
|
919
|
+
conn = _get_db()
|
|
920
|
+
row = conn.execute(
|
|
921
|
+
"SELECT steps_completed FROM draft_generation_jobs WHERE id = ?",
|
|
922
|
+
(job_id,),
|
|
923
|
+
).fetchone()
|
|
924
|
+
if row:
|
|
925
|
+
steps = json.loads(row["steps_completed"] or "[]")
|
|
926
|
+
steps.append({
|
|
927
|
+
"section_id": section_id,
|
|
928
|
+
"step": step_name,
|
|
929
|
+
"detail": detail,
|
|
930
|
+
"status": status,
|
|
931
|
+
"ts": _now(),
|
|
932
|
+
})
|
|
933
|
+
conn.execute(
|
|
934
|
+
"UPDATE draft_generation_jobs "
|
|
935
|
+
"SET steps_completed = ?, current_step = ?, current_section_id = ? "
|
|
936
|
+
"WHERE id = ?",
|
|
937
|
+
(json.dumps(steps), step_name, section_id, job_id),
|
|
938
|
+
)
|
|
939
|
+
conn.commit()
|
|
940
|
+
conn.close()
|
|
941
|
+
except Exception:
|
|
942
|
+
pass # Non-critical — don't break generation
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
def generate_batch(opportunity_id, force_regenerate=False):
|
|
946
|
+
"""Create a batch generation job and return job_id.
|
|
947
|
+
|
|
948
|
+
Actual generation runs in a background thread.
|
|
949
|
+
"""
|
|
950
|
+
conn = _get_db()
|
|
951
|
+
|
|
952
|
+
# Create job
|
|
953
|
+
job_id = str(uuid.uuid4())
|
|
954
|
+
now = _now()
|
|
955
|
+
|
|
956
|
+
ordered_sections = _resolve_generation_order(conn, opportunity_id)
|
|
957
|
+
total = len(ordered_sections)
|
|
958
|
+
|
|
959
|
+
if total == 0:
|
|
960
|
+
conn.close()
|
|
961
|
+
return {"status": "error", "message": "No sections found for this opportunity"}
|
|
962
|
+
|
|
963
|
+
conn.execute(
|
|
964
|
+
"INSERT INTO draft_generation_jobs "
|
|
965
|
+
"(id, opportunity_id, job_type, total_sections, completed_sections, "
|
|
966
|
+
"status, created_at, classification) "
|
|
967
|
+
"VALUES (?, ?, 'batch', ?, 0, 'pending', ?, 'CUI // SP-CTI')",
|
|
968
|
+
(job_id, opportunity_id, total, now),
|
|
969
|
+
)
|
|
970
|
+
conn.commit()
|
|
971
|
+
conn.close()
|
|
972
|
+
|
|
973
|
+
# Launch background thread
|
|
974
|
+
thread = threading.Thread(
|
|
975
|
+
target=_run_batch_generation,
|
|
976
|
+
args=(job_id, opportunity_id, ordered_sections, force_regenerate),
|
|
977
|
+
daemon=True,
|
|
978
|
+
)
|
|
979
|
+
thread.start()
|
|
980
|
+
|
|
981
|
+
return {
|
|
982
|
+
"status": "ok",
|
|
983
|
+
"job_id": job_id,
|
|
984
|
+
"total_sections": total,
|
|
985
|
+
"section_order": [{"id": s["id"], "title": s["title"]} for s in ordered_sections],
|
|
986
|
+
"message": "Batch generation started",
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
def _run_batch_generation(job_id, opportunity_id, ordered_sections, force_regenerate):
|
|
991
|
+
"""Background thread: generate each section sequentially."""
|
|
992
|
+
conn = _get_db()
|
|
993
|
+
conn.execute(
|
|
994
|
+
"UPDATE draft_generation_jobs SET status = 'running', started_at = ? WHERE id = ?",
|
|
995
|
+
(_now(), job_id),
|
|
996
|
+
)
|
|
997
|
+
conn.commit()
|
|
998
|
+
conn.close()
|
|
999
|
+
|
|
1000
|
+
prior_sections = []
|
|
1001
|
+
completed = 0
|
|
1002
|
+
|
|
1003
|
+
for section_info in ordered_sections:
|
|
1004
|
+
section_id = section_info["id"]
|
|
1005
|
+
section_title = section_info["title"]
|
|
1006
|
+
|
|
1007
|
+
# Update current section
|
|
1008
|
+
conn = _get_db()
|
|
1009
|
+
conn.execute(
|
|
1010
|
+
"UPDATE draft_generation_jobs "
|
|
1011
|
+
"SET current_section_id = ?, current_section_title = ? "
|
|
1012
|
+
"WHERE id = ?",
|
|
1013
|
+
(section_id, section_title, job_id),
|
|
1014
|
+
)
|
|
1015
|
+
conn.commit()
|
|
1016
|
+
conn.close()
|
|
1017
|
+
|
|
1018
|
+
try:
|
|
1019
|
+
result = generate_draft_v2(
|
|
1020
|
+
section_id=section_id,
|
|
1021
|
+
opportunity_id=opportunity_id,
|
|
1022
|
+
top_k=5,
|
|
1023
|
+
force_regenerate=force_regenerate,
|
|
1024
|
+
job_id=job_id,
|
|
1025
|
+
prior_sections_context=prior_sections[-3:], # Last 3 sections for context
|
|
1026
|
+
)
|
|
1027
|
+
|
|
1028
|
+
if result.get("status") == "ok" and not result.get("was_cached"):
|
|
1029
|
+
prior_sections.append({
|
|
1030
|
+
"title": section_title,
|
|
1031
|
+
"draft_content": result.get("draft_content", "")[:400],
|
|
1032
|
+
})
|
|
1033
|
+
|
|
1034
|
+
completed += 1
|
|
1035
|
+
|
|
1036
|
+
except Exception as e:
|
|
1037
|
+
_update_job_step(job_id, section_id, "error",
|
|
1038
|
+
f"Generation failed: {str(e)[:200]}", "failed")
|
|
1039
|
+
completed += 1 # Count as completed (failed) to keep progress moving
|
|
1040
|
+
|
|
1041
|
+
# Update completed count
|
|
1042
|
+
conn = _get_db()
|
|
1043
|
+
conn.execute(
|
|
1044
|
+
"UPDATE draft_generation_jobs SET completed_sections = ? WHERE id = ?",
|
|
1045
|
+
(completed, job_id),
|
|
1046
|
+
)
|
|
1047
|
+
conn.commit()
|
|
1048
|
+
conn.close()
|
|
1049
|
+
|
|
1050
|
+
# Mark job complete
|
|
1051
|
+
conn = _get_db()
|
|
1052
|
+
conn.execute(
|
|
1053
|
+
"UPDATE draft_generation_jobs "
|
|
1054
|
+
"SET status = 'completed', completed_at = ?, "
|
|
1055
|
+
"current_step = 'done', current_section_id = NULL "
|
|
1056
|
+
"WHERE id = ?",
|
|
1057
|
+
(_now(), job_id),
|
|
1058
|
+
)
|
|
1059
|
+
conn.commit()
|
|
1060
|
+
conn.close()
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
def get_job_progress(job_id):
|
|
1064
|
+
"""Get batch job progress for polling."""
|
|
1065
|
+
conn = _get_db()
|
|
1066
|
+
row = conn.execute(
|
|
1067
|
+
"SELECT * FROM draft_generation_jobs WHERE id = ?", (job_id,),
|
|
1068
|
+
).fetchone()
|
|
1069
|
+
conn.close()
|
|
1070
|
+
|
|
1071
|
+
if not row:
|
|
1072
|
+
return {"status": "error", "message": f"Job {job_id} not found"}
|
|
1073
|
+
|
|
1074
|
+
job = dict(row)
|
|
1075
|
+
steps = json.loads(job.get("steps_completed") or "[]")
|
|
1076
|
+
|
|
1077
|
+
return {
|
|
1078
|
+
"status": "ok",
|
|
1079
|
+
"job_id": job_id,
|
|
1080
|
+
"job_status": job["status"],
|
|
1081
|
+
"total_sections": job["total_sections"],
|
|
1082
|
+
"completed_sections": job["completed_sections"],
|
|
1083
|
+
"current_section_id": job.get("current_section_id"),
|
|
1084
|
+
"current_section_title": job.get("current_section_title"),
|
|
1085
|
+
"current_step": job.get("current_step"),
|
|
1086
|
+
"steps": steps[-20:], # Last 20 steps for UI
|
|
1087
|
+
"started_at": job.get("started_at"),
|
|
1088
|
+
"completed_at": job.get("completed_at"),
|
|
1089
|
+
"error_message": job.get("error_message"),
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
# ── CLI ──────────────────────────────────────────────────────────────────
|
|
1094
|
+
|
|
1095
|
+
def main():
|
|
1096
|
+
parser = argparse.ArgumentParser(description="Draft Orchestrator — RAG-assisted proposal drafting")
|
|
1097
|
+
parser.add_argument("--generate", action="store_true", help="Generate draft (v1 pipeline)")
|
|
1098
|
+
parser.add_argument("--generate-v2", action="store_true", help="Generate draft (v2 enhanced pipeline)")
|
|
1099
|
+
parser.add_argument("--preview", action="store_true", help="Preview context without generating")
|
|
1100
|
+
parser.add_argument("--batch", action="store_true", help="Batch generate all sections")
|
|
1101
|
+
parser.add_argument("--section-id", type=str, help="Section ID")
|
|
1102
|
+
parser.add_argument("--opportunity-id", type=str, help="Opportunity ID")
|
|
1103
|
+
parser.add_argument("--top-k", type=int, default=5, help="Number of knowledge blocks")
|
|
1104
|
+
parser.add_argument("--force", action="store_true", help="Force regenerate")
|
|
1105
|
+
parser.add_argument("--json", action="store_true", help="JSON output")
|
|
1106
|
+
args = parser.parse_args()
|
|
1107
|
+
|
|
1108
|
+
if args.preview:
|
|
1109
|
+
if not args.section_id or not args.opportunity_id:
|
|
1110
|
+
parser.error("--preview requires --section-id and --opportunity-id")
|
|
1111
|
+
result = get_draft_context(args.section_id, args.opportunity_id, args.top_k)
|
|
1112
|
+
elif args.generate:
|
|
1113
|
+
if not args.section_id or not args.opportunity_id:
|
|
1114
|
+
parser.error("--generate requires --section-id and --opportunity-id")
|
|
1115
|
+
result = generate_draft(args.section_id, args.opportunity_id, args.top_k, args.force)
|
|
1116
|
+
elif args.generate_v2:
|
|
1117
|
+
if not args.section_id or not args.opportunity_id:
|
|
1118
|
+
parser.error("--generate-v2 requires --section-id and --opportunity-id")
|
|
1119
|
+
result = generate_draft_v2(args.section_id, args.opportunity_id, args.top_k, args.force)
|
|
1120
|
+
elif args.batch:
|
|
1121
|
+
if not args.opportunity_id:
|
|
1122
|
+
parser.error("--batch requires --opportunity-id")
|
|
1123
|
+
result = generate_batch(args.opportunity_id, args.force)
|
|
1124
|
+
else:
|
|
1125
|
+
parser.print_help()
|
|
1126
|
+
sys.exit(0)
|
|
1127
|
+
|
|
1128
|
+
if args.json:
|
|
1129
|
+
print(json.dumps(result, indent=2, default=str))
|
|
1130
|
+
else:
|
|
1131
|
+
if result.get("status") == "ok":
|
|
1132
|
+
if args.preview:
|
|
1133
|
+
print(f"Knowledge blocks: {len(result.get('knowledge_blocks', []))}")
|
|
1134
|
+
print(f"Shall-statements: {len(result.get('shall_statements', []))}")
|
|
1135
|
+
print(f"Prompt length: {result.get('prompt_length', 0)} chars")
|
|
1136
|
+
elif args.batch:
|
|
1137
|
+
print(f"Batch job started: {result.get('job_id')}")
|
|
1138
|
+
print(f"Total sections: {result.get('total_sections')}")
|
|
1139
|
+
else:
|
|
1140
|
+
content = result.get("draft_content", "")
|
|
1141
|
+
print(f"Draft generated ({len(content)} chars) via {result.get('generation_model', '?')}")
|
|
1142
|
+
print(f"Pipeline: {result.get('pipeline_version', 'v1')}")
|
|
1143
|
+
if result.get("writeguard_score") is not None:
|
|
1144
|
+
print(f"WriteGuard score: {result.get('writeguard_score')}")
|
|
1145
|
+
else:
|
|
1146
|
+
print(f"Error: {result.get('message')}", file=sys.stderr)
|
|
1147
|
+
sys.exit(1)
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
if __name__ == "__main__":
|
|
1151
|
+
main()
|