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.
Files changed (1214) hide show
  1. args/agent_config.yaml +113 -0
  2. args/audit_regimes/cisa_sbd.json +381 -0
  3. args/audit_regimes/cmmc_l2.json +906 -0
  4. args/audit_regimes/dod_cssp.json +393 -0
  5. args/audit_regimes/dodi_5000_87.json +297 -0
  6. args/audit_regimes/fedramp_moderate.json +650 -0
  7. args/audit_regimes/ieee_1012.json +373 -0
  8. args/audit_regimes/nist_800_171.json +624 -0
  9. args/audit_regimes/nist_800_53.json +907 -0
  10. args/cloudforge_blueprints/aws_commercial.yaml +29 -0
  11. args/cloudforge_blueprints/aws_govcloud_il4.yaml +34 -0
  12. args/cloudforge_blueprints/aws_govcloud_il5.yaml +38 -0
  13. args/cloudforge_blueprints/azure_commercial.yaml +28 -0
  14. args/cloudforge_blueprints/azure_gov_il4.yaml +32 -0
  15. args/cloudforge_blueprints/azure_gov_il5.yaml +36 -0
  16. args/cloudforge_blueprints/gcp_commercial.yaml +28 -0
  17. args/cloudforge_blueprints/oci_commercial.yaml +28 -0
  18. args/cloudforge_config.yaml +231 -0
  19. args/cloudforge_runbook_templates/backup_verify.yaml +98 -0
  20. args/cloudforge_runbook_templates/dr_failover.yaml +107 -0
  21. args/cloudforge_runbook_templates/health_check.yaml +97 -0
  22. args/cloudforge_runbook_templates/incident_response.yaml +101 -0
  23. args/cloudforge_runbook_templates/migration_cutover.yaml +105 -0
  24. args/cloudforge_runbook_templates/patch_rollout.yaml +92 -0
  25. args/cloudforge_runbook_templates/zone_provision.yaml +93 -0
  26. args/code_pattern_config.yaml +151 -0
  27. args/code_quality_config.yaml +47 -0
  28. args/compliance_config.yaml +17 -0
  29. args/control_inheritance.yaml +177 -0
  30. args/csp_mcp_config.yaml +41 -0
  31. args/cui_markings.yaml +35 -0
  32. args/databridge_config.yaml +232 -0
  33. args/db_config.yaml +116 -0
  34. args/decision_tables/agent_trust_decision.yaml +143 -0
  35. args/decision_tables/ato_boundary_impact.yaml +132 -0
  36. args/decision_tables/deployment_approval.yaml +152 -0
  37. args/degradation_matrix.yaml +163 -0
  38. args/devsecops_config.yaml +286 -0
  39. args/endpoint_security_config.yaml +207 -0
  40. args/exit_criteria.yaml +102 -0
  41. args/feature_flags.yaml +235 -0
  42. args/file_access_tiers.yaml +88 -0
  43. args/forge_studio/blueprint_config.yaml +27 -0
  44. args/forge_studio/component_catalog.json +411 -0
  45. args/forge_studio/workflow_templates.yaml +103 -0
  46. args/govcon_config.yaml +41 -0
  47. args/harness_config.yaml +67 -0
  48. args/innovation_config.yaml +321 -0
  49. args/knowledge_graph_config.yaml +113 -0
  50. args/llm_config.yaml +222 -0
  51. args/marketplace_config.yaml +260 -0
  52. args/monitoring_config.yaml +127 -0
  53. args/mosa_config.yaml +190 -0
  54. args/observability_tracing_config.yaml +170 -0
  55. args/owasp_agentic_config.yaml +171 -0
  56. args/pipeline_gates.yaml +197 -0
  57. args/project_defaults.yaml +235 -0
  58. args/prompt_chains.yaml +163 -0
  59. args/rag_config.yaml +167 -0
  60. args/research_config.yaml +89 -0
  61. args/resilience_config.yaml +197 -0
  62. args/ricoas_config.yaml +191 -0
  63. args/security_gates.yaml +763 -0
  64. args/storage_config.yaml +63 -0
  65. args/writeguard_config.yaml +131 -0
  66. args/zta_config.yaml +247 -0
  67. context/__init__.py +6 -0
  68. context/agent/__init__.py +6 -0
  69. context/agent/response_schemas/__init__.py +6 -0
  70. context/agent/response_schemas/debate_position.json +46 -0
  71. context/agent/response_schemas/fitness_scorecard.json +74 -0
  72. context/agent/response_schemas/review_decision.json +39 -0
  73. context/agent/response_schemas/task_decomposition.json +82 -0
  74. context/agent/response_schemas/veto_decision.json +40 -0
  75. context/agentic/__init__.py +6 -0
  76. context/agentic/architecture_patterns.md +269 -0
  77. context/agentic/capability_registry.yaml +223 -0
  78. context/agentic/csp_integration.md +30 -0
  79. context/agentic/csp_mcp_registry.yaml +280 -0
  80. context/agentic/fitness_rubric.md +56 -0
  81. context/agentic/governance_baseline.md +205 -0
  82. context/ci/__init__.py +6 -0
  83. context/ci/worktree_templates.json +44 -0
  84. context/cloud/__init__.py +6 -0
  85. context/cloud/csp_service_registry.json +739 -0
  86. context/compliance/__init__.py +6 -0
  87. context/compliance/ai_rmf_crosswalk.yaml +226 -0
  88. context/compliance/atlas_mitigations.json +293 -0
  89. context/compliance/atlas_techniques.json +833 -0
  90. context/compliance/cisa_sbd_requirements.json +477 -0
  91. context/compliance/cjis_security_policy.json +522 -0
  92. context/compliance/cmmc_practices.json +2494 -0
  93. context/compliance/cmmc_report_template.md +142 -0
  94. context/compliance/cnssi_1253_overlay.json +109 -0
  95. context/compliance/control_crosswalk.json +1914 -0
  96. context/compliance/control_families/__init__.py +6 -0
  97. context/compliance/csp_certifications.json +251 -0
  98. context/compliance/cssp_report_template.md +193 -0
  99. context/compliance/cui_templates/__init__.py +6 -0
  100. context/compliance/cui_templates/banner_block.txt +4 -0
  101. context/compliance/cui_templates/code_header.txt +8 -0
  102. context/compliance/cui_templates/document_template.md +35 -0
  103. context/compliance/data_type_framework_map.json +321 -0
  104. context/compliance/data_type_registry.json +147 -0
  105. context/compliance/dod_cssp_8530.json +463 -0
  106. context/compliance/eu_ai_act_annex_iii.json +108 -0
  107. context/compliance/export_templates/__init__.py +6 -0
  108. context/compliance/export_templates/emass_controls.csv.j2 +4 -0
  109. context/compliance/export_templates/evidence_package.md.j2 +39 -0
  110. context/compliance/export_templates/executive_summary.md.j2 +55 -0
  111. context/compliance/export_templates/poam_tracking.csv.j2 +4 -0
  112. context/compliance/fedramp_20x_ksi_schemas.json +133 -0
  113. context/compliance/fedramp_high_baseline.json +4370 -0
  114. context/compliance/fedramp_moderate_baseline.json +2183 -0
  115. context/compliance/fedramp_report_template.md +181 -0
  116. context/compliance/fips_200_areas.json +362 -0
  117. context/compliance/gao_ai_accountability.json +262 -0
  118. context/compliance/hipaa_security_rule.json +720 -0
  119. context/compliance/hitrust_csf_v11.json +930 -0
  120. context/compliance/impact_level_profiles.json +251 -0
  121. context/compliance/incident_response_template.md +1110 -0
  122. context/compliance/iso27001_2022_controls.json +750 -0
  123. context/compliance/iso27001_nist_bridge.json +382 -0
  124. context/compliance/iso42001_controls.json +254 -0
  125. context/compliance/ivv_checklist_template.md +80 -0
  126. context/compliance/ivv_report_template.md +116 -0
  127. context/compliance/ivv_requirements.json +372 -0
  128. context/compliance/mosa_crosswalk.json +327 -0
  129. context/compliance/mosa_framework.json +250 -0
  130. context/compliance/narrative_templates/AC.md.j2 +101 -0
  131. context/compliance/narrative_templates/AU.md.j2 +106 -0
  132. context/compliance/narrative_templates/IA.md.j2 +104 -0
  133. context/compliance/narrative_templates/SC.md.j2 +102 -0
  134. context/compliance/narrative_templates/SI.md.j2 +111 -0
  135. context/compliance/narrative_templates/__init__.py +6 -0
  136. context/compliance/narrative_templates/default.md.j2 +50 -0
  137. context/compliance/narrative_templates/executive_summary.j2 +27 -0
  138. context/compliance/narrative_templates/poam_milestone.j2 +19 -0
  139. context/compliance/narrative_templates/ssp_section.j2 +11 -0
  140. context/compliance/nist_800_171_controls.json +1552 -0
  141. context/compliance/nist_800_207_crosswalk.json +399 -0
  142. context/compliance/nist_800_207_zta.json +258 -0
  143. context/compliance/nist_800_53.json +324 -0
  144. context/compliance/nist_ai_600_1_genai.json +326 -0
  145. context/compliance/nist_ai_rmf.json +206 -0
  146. context/compliance/nist_sp_800_60_types.json +1667 -0
  147. context/compliance/omb_m25_21_high_impact_ai.json +248 -0
  148. context/compliance/omb_m26_04_unbiased_ai.json +262 -0
  149. context/compliance/owasp_agentic_asi.json +133 -0
  150. context/compliance/owasp_agentic_threats.json +285 -0
  151. context/compliance/owasp_llm_top10.json +274 -0
  152. context/compliance/pci_dss_v4.json +510 -0
  153. context/compliance/poam_template.md +117 -0
  154. context/compliance/safeai_controls.json +512 -0
  155. context/compliance/sbd_report_template.md +77 -0
  156. context/compliance/siem_config_templates/__init__.py +6 -0
  157. context/compliance/siem_config_templates/filebeat.yml +213 -0
  158. context/compliance/siem_config_templates/log_sources.json +208 -0
  159. context/compliance/soc2_trust_criteria.json +661 -0
  160. context/compliance/ssp_template.md +432 -0
  161. context/compliance/stig_templates/__init__.py +6 -0
  162. context/compliance/stig_templates/webapp_stig.json +139 -0
  163. context/compliance/xai_requirements.json +108 -0
  164. context/dashboard/__init__.py +6 -0
  165. context/dashboard/nlq_examples.json +50 -0
  166. context/dashboard/schema_descriptions.json +23 -0
  167. context/icdev_methodology.md +100 -0
  168. context/integration/__init__.py +6 -0
  169. context/integration/approval_workflows.json +32 -0
  170. context/integration/gitlab_field_mappings.json +33 -0
  171. context/integration/jira_field_mappings.json +32 -0
  172. context/integration/reqif_export_schema.json +23 -0
  173. context/integration/servicenow_field_mappings.json +22 -0
  174. context/languages/__init__.py +6 -0
  175. context/languages/framework_patterns.json +205 -0
  176. context/languages/language_registry.json +279 -0
  177. context/llm/__init__.py +6 -0
  178. context/llm/example_provider.py +89 -0
  179. context/marketplace/assets/writeguard-core.yaml +100 -0
  180. context/marketplace/assets/writeguard-govcon.yaml +45 -0
  181. context/marketplace/assets/writeguard-style-guides.yaml +44 -0
  182. context/mbse/__init__.py +6 -0
  183. context/mbse/des_report_template.md +162 -0
  184. context/mbse/des_requirements.json +411 -0
  185. context/mbse/digital_thread_patterns.json +403 -0
  186. context/mbse/reqif_schema.json +280 -0
  187. context/mbse/sysml_element_types.json +432 -0
  188. context/oscal/NIST_SP-800-53_rev5_catalog.json +254987 -0
  189. context/oscal/README.md +43 -0
  190. context/patterns/__init__.py +6 -0
  191. context/profiles/__init__.py +6 -0
  192. context/profiles/dod_baseline_v1.yaml +145 -0
  193. context/profiles/fedramp_baseline_v1.yaml +143 -0
  194. context/profiles/financial_baseline_v1.yaml +142 -0
  195. context/profiles/healthcare_baseline_v1.yaml +135 -0
  196. context/profiles/law_enforcement_v1.yaml +129 -0
  197. context/profiles/startup_v1.yaml +134 -0
  198. context/rag/source_mappings.json +42 -0
  199. context/requirements/__init__.py +6 -0
  200. context/requirements/ambiguity_patterns.json +97 -0
  201. context/requirements/boundary_impact_rules.json +123 -0
  202. context/requirements/default_constitutions.json +67 -0
  203. context/requirements/document_extraction_rules.json +58 -0
  204. context/requirements/gap_patterns.json +108 -0
  205. context/requirements/readiness_rubric.json +78 -0
  206. context/requirements/red_alternative_patterns.json +210 -0
  207. context/requirements/safe_templates.json +72 -0
  208. context/requirements/spec_quality_checklist.json +122 -0
  209. context/research/regulatory_registry.json +114 -0
  210. context/research/verticals/cybersecurity.json +127 -0
  211. context/research/verticals/defense.json +104 -0
  212. context/research/verticals/fintech.json +125 -0
  213. context/research/verticals/healthcare.json +118 -0
  214. context/research/verticals/logistics.json +117 -0
  215. context/research/verticals/trading.json +145 -0
  216. context/simulation/__init__.py +6 -0
  217. context/simulation/architecture_patterns.json +36 -0
  218. context/simulation/coa_templates.json +38 -0
  219. context/simulation/cost_models.json +23 -0
  220. context/simulation/risk_categories.json +46 -0
  221. context/supply_chain/__init__.py +6 -0
  222. context/supply_chain/isa_templates.json +129 -0
  223. context/supply_chain/nist_800_161_controls.json +247 -0
  224. context/supply_chain/scrm_risk_matrix.json +147 -0
  225. context/templates/__init__.py +6 -0
  226. context/templates/ansible/__init__.py +6 -0
  227. context/templates/ansible/playbooks/__init__.py +6 -0
  228. context/templates/ansible/roles/__init__.py +6 -0
  229. context/templates/gitlab_ci/__init__.py +6 -0
  230. context/templates/grafana/__init__.py +6 -0
  231. context/templates/kubernetes/__init__.py +6 -0
  232. context/templates/project/__init__.py +6 -0
  233. context/templates/project/api/__init__.py +6 -0
  234. context/templates/project/cli/__init__.py +6 -0
  235. context/templates/project/data_pipeline/__init__.py +6 -0
  236. context/templates/project/iac/__init__.py +6 -0
  237. context/templates/project/javascript_frontend/__init__.py +6 -0
  238. context/templates/project/javascript_frontend/src/__init__.py +6 -0
  239. context/templates/project/javascript_frontend/tests/__init__.py +6 -0
  240. context/templates/project/microservice/__init__.py +6 -0
  241. context/templates/project/python_backend/__init__.py +6 -0
  242. context/templates/project/python_backend/src/__init__.py +6 -0
  243. context/templates/project/python_backend/tests/__init__.py +6 -0
  244. context/templates/project/python_backend/tests/features/__init__.py +6 -0
  245. context/templates/project/python_backend/tests/steps/__init__.py +6 -0
  246. context/templates/terraform/__init__.py +6 -0
  247. context/templates/terraform/govcloud_base/__init__.py +6 -0
  248. context/templates/terraform/modules/__init__.py +6 -0
  249. context/tone/__init__.py +6 -0
  250. context/writing/grammar_rules/common_errors.json +306 -0
  251. context/writing/grammar_rules/govcon_vocabulary.json +113 -0
  252. context/writing/style_guides/academic.yaml +43 -0
  253. context/writing/style_guides/business.yaml +42 -0
  254. context/writing/style_guides/government.yaml +59 -0
  255. context/writing/style_guides/proposal.yaml +58 -0
  256. context/writing/style_guides/technical.yaml +43 -0
  257. docs/adr/README.md +66 -0
  258. docs/adr/connector-forge-decisions.md +318 -0
  259. docs/adr/core-decisions.md +289 -0
  260. docs/adr/db-decisions.md +94 -0
  261. docs/adr/harness-decisions.md +122 -0
  262. docs/adr/innovation-decisions.md +262 -0
  263. docs/adr/marketplace-decisions.md +109 -0
  264. docs/adr/sbd-decisions.md +109 -0
  265. docs/adr/scale-engine-decisions.md +108 -0
  266. docs/adr/writeguard-decisions.md +136 -0
  267. docs/architecture/bounded-contexts.md +1032 -0
  268. docs/features/phase-65-writeguard.md +139 -0
  269. docs/features/phase-66-marketplace-commerce.md +79 -0
  270. docs/features/phase-67-knowledge-ingestion-rag-autodraft.md +97 -0
  271. docs/features/phase-68-enhanced-autodraft-pipeline.md +109 -0
  272. docs/features/phase-69-proposalai-marketplace-module.md +131 -0
  273. docs/features/phase-70-databridge.md +214 -0
  274. docs/features/phase-71-databridge-messaging.md +102 -0
  275. docs/implementation-plan-architecture-evolution.md +614 -0
  276. docs/marketplace/CONTRIBUTING.md +124 -0
  277. docs/marketplace/module_manifest_schema.yaml +83 -0
  278. docs/research/ai-architecture-patterns-2024-2026.md +1236 -0
  279. docs/research/app-builder-platform-analysis.md +582 -0
  280. docs/research/architecture-patterns-c4-ddd-agentic.md +871 -0
  281. docs/research/flowable-boat-competitive-analysis.md +426 -0
  282. docs/research/modern-dev-practices-2024-2026.md +1615 -0
  283. docs/research/secure-by-design-cloudyrion-adaptation.md +270 -0
  284. goals/agent_management.md +144 -0
  285. goals/ai_accountability.md +90 -0
  286. goals/ai_narratives.md +79 -0
  287. goals/ai_transparency.md +76 -0
  288. goals/ato_simulator.md +78 -0
  289. goals/audit_engine.md +177 -0
  290. goals/bite_sized_plans.md +225 -0
  291. goals/boundary_supply_chain.md +206 -0
  292. goals/brainstorming_gate.md +186 -0
  293. goals/build_app.md +604 -0
  294. goals/cato_live_evidence.md +77 -0
  295. goals/cloudforge.md +106 -0
  296. goals/code_intelligence.md +197 -0
  297. goals/compliance_workflow.md +858 -0
  298. goals/connector_forge.md +133 -0
  299. goals/databridge.md +128 -0
  300. goals/deploy_workflow.md +390 -0
  301. goals/developer_scorecard.md +78 -0
  302. goals/devsecops_workflow.md +408 -0
  303. goals/firmware_sbom.md +79 -0
  304. goals/forge_hub.md +78 -0
  305. goals/golden_path.md +77 -0
  306. goals/harness_engineering.md +91 -0
  307. goals/integration_testing.md +189 -0
  308. goals/knowledge_graph.md +128 -0
  309. goals/maintenance_audit.md +196 -0
  310. goals/manifest.md +50 -0
  311. goals/monitoring.md +126 -0
  312. goals/mosa_workflow.md +463 -0
  313. goals/multi_agent_orchestration.md +68 -0
  314. goals/observability_traceability_xai.md +154 -0
  315. goals/owasp_agentic_security.md +395 -0
  316. goals/pr_intelligence.md +78 -0
  317. goals/requirements_intake.md +213 -0
  318. goals/secure_by_design.md +135 -0
  319. goals/security_scan.md +381 -0
  320. goals/self_healing.md +120 -0
  321. goals/simulation_engine.md +111 -0
  322. goals/subagent_review.md +205 -0
  323. goals/systematic_debugging.md +257 -0
  324. goals/tdd_workflow.md +403 -0
  325. goals/template_exchange.md +77 -0
  326. goals/thread_heatmap.md +77 -0
  327. goals/threat_modeler.md +77 -0
  328. goals/verification_iron_law.md +192 -0
  329. goals/vsm_dashboard.md +76 -0
  330. goals/writeguard.md +89 -0
  331. goals/zero_trust_architecture.md +403 -0
  332. hardprompts/__init__.py +6 -0
  333. hardprompts/agent/__init__.py +6 -0
  334. hardprompts/agent/agentic_architect.md +100 -0
  335. hardprompts/agent/debate_prompt.md +32 -0
  336. hardprompts/agent/fitness_evaluation.md +48 -0
  337. hardprompts/agent/governance_review.md +214 -0
  338. hardprompts/agent/reviewer_prompt.md +34 -0
  339. hardprompts/agent/skill_design.md +172 -0
  340. hardprompts/agent/task_decomposition.md +275 -0
  341. hardprompts/agent/veto_check_prompt.md +33 -0
  342. hardprompts/architect/__init__.py +6 -0
  343. hardprompts/architect/api_design.md +283 -0
  344. hardprompts/architect/data_model.md +277 -0
  345. hardprompts/architect/system_design.md +180 -0
  346. hardprompts/builder/__init__.py +6 -0
  347. hardprompts/builder/code_generation.md +59 -0
  348. hardprompts/builder/refactor.md +58 -0
  349. hardprompts/builder/scaffold_project.md +69 -0
  350. hardprompts/builder/test_generation.md +87 -0
  351. hardprompts/ci/__init__.py +6 -0
  352. hardprompts/ci/worktree_setup.md +35 -0
  353. hardprompts/compliance/__init__.py +6 -0
  354. hardprompts/compliance/cmmc_assessment.md +63 -0
  355. hardprompts/compliance/cssp_assessment.md +75 -0
  356. hardprompts/compliance/cui_marking.md +86 -0
  357. hardprompts/compliance/fedramp_assessment.md +55 -0
  358. hardprompts/compliance/ivv_assessment.md +96 -0
  359. hardprompts/compliance/poam_generation.md +57 -0
  360. hardprompts/compliance/sbd_assessment.md +101 -0
  361. hardprompts/compliance/security_categorization.md +74 -0
  362. hardprompts/compliance/ssp_generation.md +56 -0
  363. hardprompts/compliance/stig_evaluation.md +63 -0
  364. hardprompts/dashboard/__init__.py +6 -0
  365. hardprompts/dashboard/nlq_system_prompt.md +26 -0
  366. hardprompts/infra/__init__.py +6 -0
  367. hardprompts/infra/k8s_manifests.md +118 -0
  368. hardprompts/infra/pipeline_generation.md +160 -0
  369. hardprompts/infra/terraform_generation.md +92 -0
  370. hardprompts/integration/__init__.py +6 -0
  371. hardprompts/integration/approval_review.md +17 -0
  372. hardprompts/integration/jira_mapping.md +25 -0
  373. hardprompts/integration/servicenow_mapping.md +14 -0
  374. hardprompts/knowledge/__init__.py +6 -0
  375. hardprompts/knowledge/pattern_detection.md +73 -0
  376. hardprompts/knowledge/recommendation_engine.md +90 -0
  377. hardprompts/knowledge/root_cause_analysis.md +91 -0
  378. hardprompts/maintenance/__init__.py +6 -0
  379. hardprompts/maintenance/maintenance_assessment.md +82 -0
  380. hardprompts/mbse/__init__.py +6 -0
  381. hardprompts/mbse/digital_thread.md +67 -0
  382. hardprompts/mbse/model_import.md +62 -0
  383. hardprompts/mbse/model_to_code.md +65 -0
  384. hardprompts/modernization/__init__.py +6 -0
  385. hardprompts/modernization/legacy_analysis.md +93 -0
  386. hardprompts/modernization/migration_planning.md +150 -0
  387. hardprompts/modernization/seven_r_assessment.md +107 -0
  388. hardprompts/proposal_draft.md +53 -0
  389. hardprompts/rag_citation.md +12 -0
  390. hardprompts/rag_rerank.md +31 -0
  391. hardprompts/requirements/__init__.py +6 -0
  392. hardprompts/requirements/bdd_generation.md +35 -0
  393. hardprompts/requirements/clarification_prioritization.md +29 -0
  394. hardprompts/requirements/decomposition.md +60 -0
  395. hardprompts/requirements/document_extraction.md +45 -0
  396. hardprompts/requirements/gap_detection.md +70 -0
  397. hardprompts/requirements/intake_conversation.md +101 -0
  398. hardprompts/requirements/readiness_assessment.md +39 -0
  399. hardprompts/requirements/spec_quality.md +33 -0
  400. hardprompts/requirements/traceability_analysis.md +23 -0
  401. hardprompts/security/__init__.py +6 -0
  402. hardprompts/security/endpoint_security.md +78 -0
  403. hardprompts/security/threat_model.md +70 -0
  404. hardprompts/security/vulnerability_assessment.md +81 -0
  405. hardprompts/simulation/__init__.py +6 -0
  406. hardprompts/simulation/architecture_impact.md +27 -0
  407. hardprompts/simulation/coa_alternative.md +27 -0
  408. hardprompts/simulation/coa_generation.md +25 -0
  409. hardprompts/simulation/compliance_impact.md +28 -0
  410. hardprompts/simulation/cost_estimation.md +33 -0
  411. hardprompts/simulation/risk_assessment.md +28 -0
  412. hardprompts/translation/code_translation.md +68 -0
  413. hardprompts/translation/dependency_suggestion.md +44 -0
  414. hardprompts/translation/test_translation.md +64 -0
  415. hardprompts/translation/translation_repair.md +59 -0
  416. icdev-0.0.3.dist-info/METADATA +909 -0
  417. icdev-0.0.3.dist-info/RECORD +1214 -0
  418. icdev-0.0.3.dist-info/WHEEL +5 -0
  419. icdev-0.0.3.dist-info/entry_points.txt +9 -0
  420. icdev-0.0.3.dist-info/licenses/LICENSE +201 -0
  421. icdev-0.0.3.dist-info/licenses/NOTICE +11 -0
  422. icdev-0.0.3.dist-info/top_level.txt +7 -0
  423. memory/MEMORY.md +52 -0
  424. memory/logs/2026-02-14.md +17 -0
  425. memory/logs/2026-03-03.md +2 -0
  426. memory/logs/__init__.py +1 -0
  427. tools/a2a/icdev_callback_client.py +210 -0
  428. tools/agent/cards/architect_card.json +29 -0
  429. tools/agent/cards/builder_card.json +34 -0
  430. tools/agent/cards/compliance_card.json +29 -0
  431. tools/agent/cards/connector_forge_card.json +49 -0
  432. tools/agent/cards/devsecops_zta_card.json +24 -0
  433. tools/agent/cards/knowledge_card.json +29 -0
  434. tools/agent/cards/monitor_card.json +29 -0
  435. tools/agent/cards/orchestrator_card.json +29 -0
  436. tools/agent/cards/requirements_analyst_card.json +24 -0
  437. tools/agent/cards/security_card.json +29 -0
  438. tools/agent/cards/simulation_card.json +24 -0
  439. tools/agent/cards/supply_chain_card.json +24 -0
  440. tools/analysis/__init__.py +1 -0
  441. tools/analysis/code_analyzer.py +770 -0
  442. tools/analysis/runtime_feedback.py +379 -0
  443. tools/analytics/__init__.py +2 -0
  444. tools/analytics/scorecard.py +538 -0
  445. tools/analytics/vsm_engine.py +612 -0
  446. tools/architecture/__init__.py +2 -0
  447. tools/architecture/adr_extractor.py +393 -0
  448. tools/audit/__init__.py +1 -0
  449. tools/audit/audit_logger.py +199 -0
  450. tools/audit/audit_query.py +153 -0
  451. tools/audit/decision_recorder.py +73 -0
  452. tools/audit_engine/__init__.py +12 -0
  453. tools/audit_engine/ai_advisor.py +906 -0
  454. tools/audit_engine/cli.py +286 -0
  455. tools/audit_engine/comparator.py +305 -0
  456. tools/audit_engine/eject_scaffolder.py +399 -0
  457. tools/audit_engine/engine.py +614 -0
  458. tools/audit_engine/git_fetcher.py +341 -0
  459. tools/audit_engine/regime_loader.py +200 -0
  460. tools/audit_engine/regime_updater.py +325 -0
  461. tools/audit_engine/report_card.py +289 -0
  462. tools/audit_engine/scanner.py +684 -0
  463. tools/audit_engine/self_heal.py +1042 -0
  464. tools/ci/__init__.py +2 -0
  465. tools/ci/connectors/__init__.py +2 -0
  466. tools/ci/connectors/base_connector.py +80 -0
  467. tools/ci/connectors/connector_registry.py +188 -0
  468. tools/ci/connectors/mattermost_connector.py +159 -0
  469. tools/ci/connectors/slack_connector.py +197 -0
  470. tools/ci/core/__init__.py +2 -0
  471. tools/ci/core/air_gap_detector.py +115 -0
  472. tools/ci/core/comment_handler.py +192 -0
  473. tools/ci/core/conversation_manager.py +480 -0
  474. tools/ci/core/event_envelope.py +500 -0
  475. tools/ci/core/event_router.py +444 -0
  476. tools/ci/core/failure_parser.py +397 -0
  477. tools/ci/core/recovery_engine.py +527 -0
  478. tools/ci/gate_enforcer.py +361 -0
  479. tools/ci/modules/__init__.py +2 -0
  480. tools/ci/modules/agent.py +271 -0
  481. tools/ci/modules/git_ops.py +175 -0
  482. tools/ci/modules/state.py +117 -0
  483. tools/ci/modules/vcs.py +303 -0
  484. tools/ci/modules/workflow_ops.py +295 -0
  485. tools/ci/modules/worktree.py +337 -0
  486. tools/ci/pipeline_config_generator.py +558 -0
  487. tools/ci/pr_intelligence.py +485 -0
  488. tools/ci/triggers/__init__.py +2 -0
  489. tools/ci/triggers/gitlab_task_monitor.py +327 -0
  490. tools/ci/triggers/poll_trigger.py +237 -0
  491. tools/ci/triggers/webhook_server.py +356 -0
  492. tools/ci/workflows/__init__.py +2 -0
  493. tools/ci/workflows/icdev_build.py +140 -0
  494. tools/ci/workflows/icdev_comply.py +284 -0
  495. tools/ci/workflows/icdev_document.py +152 -0
  496. tools/ci/workflows/icdev_e2e.py +188 -0
  497. tools/ci/workflows/icdev_patch.py +186 -0
  498. tools/ci/workflows/icdev_plan.py +202 -0
  499. tools/ci/workflows/icdev_plan_build.py +41 -0
  500. tools/ci/workflows/icdev_plan_build_test.py +46 -0
  501. tools/ci/workflows/icdev_plan_build_test_review.py +47 -0
  502. tools/ci/workflows/icdev_review.py +126 -0
  503. tools/ci/workflows/icdev_sdlc.py +261 -0
  504. tools/ci/workflows/icdev_test.py +240 -0
  505. tools/cli/__init__.py +1 -0
  506. tools/cli/output_formatter.py +756 -0
  507. tools/cloudforge/__init__.py +12 -0
  508. tools/cloudforge/airgap/__init__.py +2 -0
  509. tools/cloudforge/airgap/il_classifier.py +70 -0
  510. tools/cloudforge/airgap/offline_validator.py +42 -0
  511. tools/cloudforge/airgap/shift_emulator.py +155 -0
  512. tools/cloudforge/airgap/sneakernet.py +91 -0
  513. tools/cloudforge/cd_hub/__init__.py +2 -0
  514. tools/cloudforge/cd_hub/canary_deployer.py +88 -0
  515. tools/cloudforge/cd_hub/gitops_renderer.py +123 -0
  516. tools/cloudforge/cd_hub/hub_controller.py +143 -0
  517. tools/cloudforge/cd_hub/pipeline_bridge.py +30 -0
  518. tools/cloudforge/cd_hub/rollback_engine.py +29 -0
  519. tools/cloudforge/cd_hub/spoke_agent.py +51 -0
  520. tools/cloudforge/compliance/__init__.py +2 -0
  521. tools/cloudforge/compliance/ato_accelerator.py +272 -0
  522. tools/cloudforge/compliance/control_inheritor.py +127 -0
  523. tools/cloudforge/compliance/evidence_generator.py +129 -0
  524. tools/cloudforge/compliance/poam_bridge.py +41 -0
  525. tools/cloudforge/compliance/ssp_bridge.py +52 -0
  526. tools/cloudforge/compliance/stig_bridge.py +41 -0
  527. tools/cloudforge/container_forge/__init__.py +2 -0
  528. tools/cloudforge/container_forge/bigbang_renderer.py +85 -0
  529. tools/cloudforge/container_forge/hardener.py +169 -0
  530. tools/cloudforge/container_forge/image_scanner_bridge.py +33 -0
  531. tools/cloudforge/container_forge/runtime_policy.py +87 -0
  532. tools/cloudforge/container_forge/sbom_bridge.py +42 -0
  533. tools/cloudforge/finops/__init__.py +2 -0
  534. tools/cloudforge/finops/anomaly_detector.py +78 -0
  535. tools/cloudforge/finops/budget_tracker.py +96 -0
  536. tools/cloudforge/finops/chargeback.py +69 -0
  537. tools/cloudforge/finops/cost_collector.py +141 -0
  538. tools/cloudforge/finops/optimizer.py +55 -0
  539. tools/cloudforge/hybrid/__init__.py +2 -0
  540. tools/cloudforge/hybrid/connection_manager.py +141 -0
  541. tools/cloudforge/hybrid/dns_federator.py +56 -0
  542. tools/cloudforge/hybrid/health_monitor.py +108 -0
  543. tools/cloudforge/hybrid/identity_federator.py +53 -0
  544. tools/cloudforge/hybrid/network_bridge.py +68 -0
  545. tools/cloudforge/hybrid/topology_manager.py +147 -0
  546. tools/cloudforge/hybrid/workload_abstractor.py +92 -0
  547. tools/cloudforge/iac/__init__.py +2 -0
  548. tools/cloudforge/iac/drift_detector.py +154 -0
  549. tools/cloudforge/iac/module_library.py +265 -0
  550. tools/cloudforge/iac/opentofu_adapter.py +89 -0
  551. tools/cloudforge/iac/pulumi_renderer.py +292 -0
  552. tools/cloudforge/iac/state_backend.py +146 -0
  553. tools/cloudforge/iac/terraform_renderer.py +626 -0
  554. tools/cloudforge/landing_zone/__init__.py +2 -0
  555. tools/cloudforge/landing_zone/blueprint_loader.py +98 -0
  556. tools/cloudforge/landing_zone/blueprint_validator.py +113 -0
  557. tools/cloudforge/landing_zone/zone_provisioner.py +306 -0
  558. tools/cloudforge/landing_zone/zone_state.py +143 -0
  559. tools/cloudforge/mbse_thread/__init__.py +2 -0
  560. tools/cloudforge/mbse_thread/ato_thread_weaver.py +111 -0
  561. tools/cloudforge/mbse_thread/control_tracer.py +68 -0
  562. tools/cloudforge/mbse_thread/system_boundary.py +83 -0
  563. tools/cloudforge/metastore/__init__.py +2 -0
  564. tools/cloudforge/metastore/dependency_graph.py +202 -0
  565. tools/cloudforge/metastore/discovery.py +192 -0
  566. tools/cloudforge/metastore/registry.py +185 -0
  567. tools/cloudforge/metastore/rto_tracker.py +92 -0
  568. tools/cloudforge/metastore/runbook_linker.py +82 -0
  569. tools/cloudforge/migration/__init__.py +2 -0
  570. tools/cloudforge/migration/assessor.py +187 -0
  571. tools/cloudforge/migration/cutover_orchestrator.py +117 -0
  572. tools/cloudforge/migration/databridge_bridge.py +92 -0
  573. tools/cloudforge/migration/planner.py +98 -0
  574. tools/cloudforge/migration/risk_scorer.py +97 -0
  575. tools/cloudforge/migration/validation_runner.py +45 -0
  576. tools/cloudforge/migration/workload_inventory.py +107 -0
  577. tools/cloudforge/provider.py +319 -0
  578. tools/cloudforge/providers/__init__.py +2 -0
  579. tools/cloudforge/providers/aws_commercial.py +92 -0
  580. tools/cloudforge/providers/aws_govcloud.py +229 -0
  581. tools/cloudforge/providers/aws_secret.py +83 -0
  582. tools/cloudforge/providers/azure_commercial.py +80 -0
  583. tools/cloudforge/providers/azure_gov.py +91 -0
  584. tools/cloudforge/providers/azure_secret.py +71 -0
  585. tools/cloudforge/providers/gcp.py +102 -0
  586. tools/cloudforge/providers/oci.py +102 -0
  587. tools/cloudforge/registry.py +140 -0
  588. tools/cloudforge/runbooks/__init__.py +2 -0
  589. tools/cloudforge/runbooks/ai_generator.py +119 -0
  590. tools/cloudforge/runbooks/dag_validator.py +219 -0
  591. tools/cloudforge/runbooks/engine.py +470 -0
  592. tools/cloudforge/runbooks/models.py +99 -0
  593. tools/cloudforge/runbooks/snippet_library.py +158 -0
  594. tools/cloudforge/runbooks/template_loader.py +122 -0
  595. tools/cloudforge/runbooks/visualization.py +108 -0
  596. tools/cloudforge/siem/__init__.py +2 -0
  597. tools/cloudforge/siem/alert_rules.py +86 -0
  598. tools/cloudforge/siem/correlation_engine.py +61 -0
  599. tools/cloudforge/siem/log_aggregator.py +113 -0
  600. tools/cloudforge/siem/siem_dashboard_data.py +28 -0
  601. tools/cloudforge/supply_chain/__init__.py +2 -0
  602. tools/cloudforge/supply_chain/bridge.py +33 -0
  603. tools/cloudforge/supply_chain/iac_dependency_scanner.py +36 -0
  604. tools/cloudforge/supply_chain/provider_trust_scorer.py +54 -0
  605. tools/compat/__init__.py +21 -0
  606. tools/compat/cli_harmonizer.py +251 -0
  607. tools/compat/datetime_utils.py +18 -0
  608. tools/compat/db_utils.py +190 -0
  609. tools/compat/platform_utils.py +123 -0
  610. tools/compliance/__init__.py +1 -0
  611. tools/compliance/accountability_manager.py +391 -0
  612. tools/compliance/ai_accountability_audit.py +287 -0
  613. tools/compliance/ai_impact_assessor.py +267 -0
  614. tools/compliance/ai_incident_response.py +295 -0
  615. tools/compliance/ai_inventory_manager.py +233 -0
  616. tools/compliance/ai_reassessment_scheduler.py +250 -0
  617. tools/compliance/ai_transparency_audit.py +247 -0
  618. tools/compliance/atlas_assessor.py +276 -0
  619. tools/compliance/atlas_report_generator.py +1199 -0
  620. tools/compliance/base_assessor.py +591 -0
  621. tools/compliance/cato_live_engine.py +607 -0
  622. tools/compliance/cato_monitor.py +1371 -0
  623. tools/compliance/cato_scheduler.py +698 -0
  624. tools/compliance/cjis_assessor.py +76 -0
  625. tools/compliance/classification_manager.py +1340 -0
  626. tools/compliance/cmmc_assessor.py +1478 -0
  627. tools/compliance/cmmc_report_generator.py +1087 -0
  628. tools/compliance/compliance_detector.py +452 -0
  629. tools/compliance/compliance_exporter.py +418 -0
  630. tools/compliance/compliance_status.py +810 -0
  631. tools/compliance/control_mapper.py +488 -0
  632. tools/compliance/crosswalk_engine.py +1208 -0
  633. tools/compliance/cssp_assessor.py +1032 -0
  634. tools/compliance/cssp_evidence_collector.py +716 -0
  635. tools/compliance/cssp_report_generator.py +1103 -0
  636. tools/compliance/cui_marker.py +387 -0
  637. tools/compliance/diagram_validator.py +599 -0
  638. tools/compliance/emass/__init__.py +2 -0
  639. tools/compliance/emass/emass_client.py +822 -0
  640. tools/compliance/emass/emass_export.py +758 -0
  641. tools/compliance/emass/emass_sync.py +807 -0
  642. tools/compliance/eu_ai_act_classifier.py +193 -0
  643. tools/compliance/evidence_collector.py +459 -0
  644. tools/compliance/fairness_assessor.py +310 -0
  645. tools/compliance/fedramp_20x_ksi_emitter.py +692 -0
  646. tools/compliance/fedramp_assessor.py +1795 -0
  647. tools/compliance/fedramp_authorization_packager.py +137 -0
  648. tools/compliance/fedramp_ksi_generator.py +349 -0
  649. tools/compliance/fedramp_report_generator.py +1115 -0
  650. tools/compliance/fips199_categorizer.py +869 -0
  651. tools/compliance/fips200_validator.py +304 -0
  652. tools/compliance/firmware_sbom.py +646 -0
  653. tools/compliance/gao_ai_assessor.py +228 -0
  654. tools/compliance/gao_evidence_builder.py +302 -0
  655. tools/compliance/hipaa_assessor.py +78 -0
  656. tools/compliance/hitrust_assessor.py +49 -0
  657. tools/compliance/incident_response_plan.py +705 -0
  658. tools/compliance/inheritance_engine.py +693 -0
  659. tools/compliance/iso27001_assessor.py +92 -0
  660. tools/compliance/iso42001_assessor.py +114 -0
  661. tools/compliance/ivv_assessor.py +2314 -0
  662. tools/compliance/ivv_report_generator.py +1649 -0
  663. tools/compliance/model_card_generator.py +291 -0
  664. tools/compliance/mosa_assessor.py +117 -0
  665. tools/compliance/multi_regime_assessor.py +441 -0
  666. tools/compliance/narrative_generator.py +1012 -0
  667. tools/compliance/narrative_quality_gate.py +701 -0
  668. tools/compliance/narrative_workflow.py +814 -0
  669. tools/compliance/nist_800_207_assessor.py +191 -0
  670. tools/compliance/nist_ai_600_1_assessor.py +185 -0
  671. tools/compliance/nist_ai_rmf_assessor.py +110 -0
  672. tools/compliance/nist_lookup.py +244 -0
  673. tools/compliance/omb_m25_21_assessor.py +225 -0
  674. tools/compliance/omb_m26_04_assessor.py +185 -0
  675. tools/compliance/oscal_catalog_adapter.py +395 -0
  676. tools/compliance/oscal_generator.py +2157 -0
  677. tools/compliance/oscal_tools.py +1182 -0
  678. tools/compliance/oscal_validator.py +692 -0
  679. tools/compliance/owasp_agentic_assessor.py +227 -0
  680. tools/compliance/owasp_asi_assessor.py +197 -0
  681. tools/compliance/owasp_llm_assessor.py +245 -0
  682. tools/compliance/pci_dss_assessor.py +80 -0
  683. tools/compliance/pi_compliance_tracker.py +1447 -0
  684. tools/compliance/poam_generator.py +388 -0
  685. tools/compliance/resolve_marking.py +272 -0
  686. tools/compliance/sbd_assessor.py +2070 -0
  687. tools/compliance/sbd_report_generator.py +1223 -0
  688. tools/compliance/sbom_generator.py +993 -0
  689. tools/compliance/siem_config_generator.py +661 -0
  690. tools/compliance/slsa_attestation_generator.py +479 -0
  691. tools/compliance/soc2_assessor.py +77 -0
  692. tools/compliance/ssp_generator.py +556 -0
  693. tools/compliance/stig_checker.py +712 -0
  694. tools/compliance/swft_evidence_bundler.py +326 -0
  695. tools/compliance/system_card_generator.py +303 -0
  696. tools/compliance/template_exchange.py +513 -0
  697. tools/compliance/traceability_matrix.py +1268 -0
  698. tools/compliance/universal_classification_manager.py +1159 -0
  699. tools/compliance/xacta/__init__.py +2 -0
  700. tools/compliance/xacta/xacta_client.py +438 -0
  701. tools/compliance/xacta/xacta_export.py +546 -0
  702. tools/compliance/xacta/xacta_sync.py +322 -0
  703. tools/compliance/xai_assessor.py +231 -0
  704. tools/core/__init__.py +2 -0
  705. tools/core/circuit_breaker.py +353 -0
  706. tools/core/compliance_sidecar.py +344 -0
  707. tools/core/container.py +110 -0
  708. tools/core/errors.py +256 -0
  709. tools/core/feature_flags.py +311 -0
  710. tools/core/task_dlq.py +350 -0
  711. tools/dashboard/__init__.py +2 -0
  712. tools/dashboard/app.py +6288 -0
  713. tools/dashboard/templates/agent_evolution.html +287 -0
  714. tools/dashboard/templates/agents/list.html +71 -0
  715. tools/dashboard/templates/agents.html +132 -0
  716. tools/dashboard/templates/architecture.html +289 -0
  717. tools/dashboard/templates/ato_simulator.html +170 -0
  718. tools/dashboard/templates/audit_engine.html +844 -0
  719. tools/dashboard/templates/base.html +236 -0
  720. tools/dashboard/templates/cato_live.html +116 -0
  721. tools/dashboard/templates/cloudforge.html +195 -0
  722. tools/dashboard/templates/cloudforge_finops.html +111 -0
  723. tools/dashboard/templates/cloudforge_hybrid.html +122 -0
  724. tools/dashboard/templates/cloudforge_metastore.html +234 -0
  725. tools/dashboard/templates/cloudforge_migration.html +87 -0
  726. tools/dashboard/templates/cloudforge_runbooks.html +201 -0
  727. tools/dashboard/templates/cloudforge_siem.html +94 -0
  728. tools/dashboard/templates/compliance_accel.html +292 -0
  729. tools/dashboard/templates/crashes.html +122 -0
  730. tools/dashboard/templates/databridge.html +305 -0
  731. tools/dashboard/templates/databridge_analytics.html +195 -0
  732. tools/dashboard/templates/databridge_mapping.html +345 -0
  733. tools/dashboard/templates/databridge_messaging.html +321 -0
  734. tools/dashboard/templates/decisions.html +258 -0
  735. tools/dashboard/templates/devices.html +151 -0
  736. tools/dashboard/templates/devsecops_maturity.html +278 -0
  737. tools/dashboard/templates/edge_ai.html +128 -0
  738. tools/dashboard/templates/firmware.html +120 -0
  739. tools/dashboard/templates/firmware_sbom.html +193 -0
  740. tools/dashboard/templates/forge_hub.html +196 -0
  741. tools/dashboard/templates/forge_studio.html +379 -0
  742. tools/dashboard/templates/forge_studio_analytics.html +360 -0
  743. tools/dashboard/templates/forge_studio_builder.html +1637 -0
  744. tools/dashboard/templates/forge_studio_compliance.html +310 -0
  745. tools/dashboard/templates/forge_studio_deploy.html +573 -0
  746. tools/dashboard/templates/forge_studio_enterprise.html +888 -0
  747. tools/dashboard/templates/forge_studio_marketplace.html +502 -0
  748. tools/dashboard/templates/forge_studio_workflow.html +696 -0
  749. tools/dashboard/templates/golden_path.html +175 -0
  750. tools/dashboard/templates/govcon.html +280 -0
  751. tools/dashboard/templates/harness.html +148 -0
  752. tools/dashboard/templates/index.html +207 -0
  753. tools/dashboard/templates/intelligence.html +336 -0
  754. tools/dashboard/templates/knowledge/index.html +190 -0
  755. tools/dashboard/templates/knowledge_graph.html +739 -0
  756. tools/dashboard/templates/login.html +51 -0
  757. tools/dashboard/templates/marketplace.html +336 -0
  758. tools/dashboard/templates/marketplace_admin.html +247 -0
  759. tools/dashboard/templates/missions.html +403 -0
  760. tools/dashboard/templates/narratives.html +154 -0
  761. tools/dashboard/templates/pr_intelligence.html +151 -0
  762. tools/dashboard/templates/proposals/detail.html +300 -0
  763. tools/dashboard/templates/proposals/list.html +52 -0
  764. tools/dashboard/templates/proposals/sam_detail.html +132 -0
  765. tools/dashboard/templates/proposals/section_detail.html +375 -0
  766. tools/dashboard/templates/research.html +222 -0
  767. tools/dashboard/templates/resilience.html +300 -0
  768. tools/dashboard/templates/scorecard.html +162 -0
  769. tools/dashboard/templates/simulator.html +131 -0
  770. tools/dashboard/templates/template_exchange.html +147 -0
  771. tools/dashboard/templates/thread_heatmap.html +151 -0
  772. tools/dashboard/templates/threat_model.html +195 -0
  773. tools/dashboard/templates/vsm.html +141 -0
  774. tools/dashboard/templates/writeguard.html +277 -0
  775. tools/databridge/__init__.py +5 -0
  776. tools/databridge/agent/__init__.py +2 -0
  777. tools/databridge/agent/daemon.py +227 -0
  778. tools/databridge/agent/tunnel.py +101 -0
  779. tools/databridge/agent/ws_relay.py +91 -0
  780. tools/databridge/analytics.py +167 -0
  781. tools/databridge/arrow_pipeline.py +327 -0
  782. tools/databridge/connection_manager.py +424 -0
  783. tools/databridge/connector.py +331 -0
  784. tools/databridge/connectors/__init__.py +2 -0
  785. tools/databridge/connectors/argocd_connector.py +160 -0
  786. tools/databridge/connectors/avro_connector.py +203 -0
  787. tools/databridge/connectors/azure_blob.py +63 -0
  788. tools/databridge/connectors/cdc_connector.py +205 -0
  789. tools/databridge/connectors/csv_connector.py +172 -0
  790. tools/databridge/connectors/datadog_connector.py +153 -0
  791. tools/databridge/connectors/discord_messaging.py +215 -0
  792. tools/databridge/connectors/dynamics365.py +151 -0
  793. tools/databridge/connectors/elasticsearch_connector.py +145 -0
  794. tools/databridge/connectors/email_base.py +114 -0
  795. tools/databridge/connectors/excel_connector.py +175 -0
  796. tools/databridge/connectors/fsspec_base.py +300 -0
  797. tools/databridge/connectors/gcs.py +53 -0
  798. tools/databridge/connectors/github_connector.py +138 -0
  799. tools/databridge/connectors/gitlab_connector.py +132 -0
  800. tools/databridge/connectors/gmail_connector.py +182 -0
  801. tools/databridge/connectors/hdfs.py +57 -0
  802. tools/databridge/connectors/health_base.py +401 -0
  803. tools/databridge/connectors/hubspot.py +124 -0
  804. tools/databridge/connectors/imap_connector.py +171 -0
  805. tools/databridge/connectors/jenkins_connector.py +138 -0
  806. tools/databridge/connectors/jira_connector.py +86 -0
  807. tools/databridge/connectors/json_connector.py +184 -0
  808. tools/databridge/connectors/kafka_connector.py +246 -0
  809. tools/databridge/connectors/kinesis_connector.py +238 -0
  810. tools/databridge/connectors/local_fs.py +30 -0
  811. tools/databridge/connectors/matrix.py +197 -0
  812. tools/databridge/connectors/mattermost_messaging.py +184 -0
  813. tools/databridge/connectors/messaging_base.py +172 -0
  814. tools/databridge/connectors/mssql.py +63 -0
  815. tools/databridge/connectors/mysql.py +57 -0
  816. tools/databridge/connectors/netsuite.py +170 -0
  817. tools/databridge/connectors/o365_mail.py +196 -0
  818. tools/databridge/connectors/oracle.py +65 -0
  819. tools/databridge/connectors/pagerduty_connector.py +162 -0
  820. tools/databridge/connectors/parquet_connector.py +131 -0
  821. tools/databridge/connectors/postgresql.py +58 -0
  822. tools/databridge/connectors/s3.py +65 -0
  823. tools/databridge/connectors/saas_base.py +198 -0
  824. tools/databridge/connectors/salesforce.py +126 -0
  825. tools/databridge/connectors/sap.py +89 -0
  826. tools/databridge/connectors/servicenow.py +60 -0
  827. tools/databridge/connectors/signal_messaging.py +150 -0
  828. tools/databridge/connectors/slack_messaging.py +203 -0
  829. tools/databridge/connectors/smtp_connector.py +126 -0
  830. tools/databridge/connectors/soap_base.py +258 -0
  831. tools/databridge/connectors/splunk_connector.py +171 -0
  832. tools/databridge/connectors/sql_base.py +310 -0
  833. tools/databridge/connectors/sqlite_connector.py +76 -0
  834. tools/databridge/connectors/teams.py +148 -0
  835. tools/databridge/connectors/telegram.py +192 -0
  836. tools/databridge/connectors/whatsapp.py +137 -0
  837. tools/databridge/data_profiler.py +99 -0
  838. tools/databridge/forge/__init__.py +6 -0
  839. tools/databridge/forge/base_selector.py +150 -0
  840. tools/databridge/forge/code_generator.py +206 -0
  841. tools/databridge/forge/community_hub.py +539 -0
  842. tools/databridge/forge/forge_agent.py +306 -0
  843. tools/databridge/forge/import_handler.py +133 -0
  844. tools/databridge/forge/integration_tester.py +127 -0
  845. tools/databridge/forge/marketplace_publisher.py +164 -0
  846. tools/databridge/forge/promoter.py +159 -0
  847. tools/databridge/forge/sandbox_manager.py +257 -0
  848. tools/databridge/forge/spec_parser.py +358 -0
  849. tools/databridge/forge/static_validator.py +363 -0
  850. tools/databridge/forge/templates/__init__.py +591 -0
  851. tools/databridge/format_converter.py +188 -0
  852. tools/databridge/mapping_engine.py +348 -0
  853. tools/databridge/messaging/__init__.py +5 -0
  854. tools/databridge/messaging/agent_bridge.py +254 -0
  855. tools/databridge/messaging/message_envelope.py +111 -0
  856. tools/databridge/messaging/message_logger.py +204 -0
  857. tools/databridge/messaging/messaging_daemon.py +326 -0
  858. tools/databridge/messaging/oauth2_manager.py +411 -0
  859. tools/databridge/pii_detector.py +221 -0
  860. tools/databridge/registry.py +352 -0
  861. tools/databridge/relay_server.py +105 -0
  862. tools/databridge/scale/__init__.py +16 -0
  863. tools/databridge/scale/backpressure.py +134 -0
  864. tools/databridge/scale/chunked_pipeline.py +169 -0
  865. tools/databridge/scale/connection_pool.py +293 -0
  866. tools/databridge/scale/engine.py +492 -0
  867. tools/databridge/scale/worker_pool.py +140 -0
  868. tools/databridge/scale/write_batcher.py +250 -0
  869. tools/databridge/schema_engine.py +324 -0
  870. tools/databridge/stream_manager.py +225 -0
  871. tools/databridge/sync_engine.py +411 -0
  872. tools/databridge/transforms.py +302 -0
  873. tools/db/__init__.py +1 -0
  874. tools/db/backup.py +312 -0
  875. tools/db/backup_manager.py +832 -0
  876. tools/db/init_icdev_db.py +7753 -0
  877. tools/db/init_sparkpilot_db.py +431 -0
  878. tools/db/migrate.py +177 -0
  879. tools/db/migrate_innovation_audit.py +165 -0
  880. tools/db/migration_runner.py +548 -0
  881. tools/db/migrations/001_baseline/meta.json +9 -0
  882. tools/db/migrations/001_baseline/up.py +67 -0
  883. tools/db/migrations/002_memory_enhancements/down.sql +8 -0
  884. tools/db/migrations/002_memory_enhancements/meta.json +9 -0
  885. tools/db/migrations/002_memory_enhancements/up.py +119 -0
  886. tools/db/migrations/003_dev_profiles/meta.json +8 -0
  887. tools/db/migrations/003_dev_profiles/up.py +93 -0
  888. tools/db/migrations/004_innovation_engine/down.py +19 -0
  889. tools/db/migrations/004_innovation_engine/up.py +227 -0
  890. tools/db/migrations/005_phase_37_ai_security/down.py +19 -0
  891. tools/db/migrations/005_phase_37_ai_security/up.py +257 -0
  892. tools/db/migrations/006_phase_36_evolution/down.py +21 -0
  893. tools/db/migrations/006_phase_36_evolution/up.py +323 -0
  894. tools/db/migrations/007_phase_38_cloud/down.py +14 -0
  895. tools/db/migrations/007_phase_38_cloud/up.py +110 -0
  896. tools/db/migrations/008_phase36_37_integration/up.py +55 -0
  897. tools/db/migrations/__init__.py +2 -0
  898. tools/db/pg_migrate.py +642 -0
  899. tools/db/storage.py +1080 -0
  900. tools/decisions/__init__.py +2 -0
  901. tools/decisions/dmn_engine.py +695 -0
  902. tools/devsecops/__init__.py +2 -0
  903. tools/devsecops/attestation_manager.py +449 -0
  904. tools/devsecops/network_segmentation_generator.py +604 -0
  905. tools/devsecops/pdp_config_generator.py +1246 -0
  906. tools/devsecops/pipeline_security_generator.py +475 -0
  907. tools/devsecops/policy_generator.py +644 -0
  908. tools/devsecops/profile_manager.py +374 -0
  909. tools/devsecops/service_mesh_generator.py +1063 -0
  910. tools/devsecops/zta_maturity_scorer.py +355 -0
  911. tools/devsecops/zta_terraform_generator.py +1301 -0
  912. tools/edge_ai/__init__.py +2 -0
  913. tools/edge_ai/model_manager.py +200 -0
  914. tools/embedded/__init__.py +2 -0
  915. tools/embedded/cmake_generator.py +318 -0
  916. tools/embedded/crash_analyzer.py +191 -0
  917. tools/embedded/nl_to_firmware.py +277 -0
  918. tools/events/__init__.py +1 -0
  919. tools/events/event_bus.py +199 -0
  920. tools/finetune/pair_generator.py +832 -0
  921. tools/fleet/__init__.py +2 -0
  922. tools/fleet/device_registry.py +148 -0
  923. tools/fleet/ota_manager.py +153 -0
  924. tools/forge_studio/__init__.py +13 -0
  925. tools/forge_studio/analytics/__init__.py +0 -0
  926. tools/forge_studio/analytics/process_miner.py +383 -0
  927. tools/forge_studio/audit.py +183 -0
  928. tools/forge_studio/blueprint/__init__.py +2 -0
  929. tools/forge_studio/blueprint/build_tracker.py +317 -0
  930. tools/forge_studio/blueprint/export_engine.py +441 -0
  931. tools/forge_studio/blueprint/parent_client.py +335 -0
  932. tools/forge_studio/catalog/__init__.py +2 -0
  933. tools/forge_studio/catalog/component_registry.py +176 -0
  934. tools/forge_studio/catalog/schema_validator.py +193 -0
  935. tools/forge_studio/compliance/__init__.py +1 -0
  936. tools/forge_studio/compliance/compliance_wiring.py +554 -0
  937. tools/forge_studio/deploy/__init__.py +1 -0
  938. tools/forge_studio/deploy/airgap_packager.py +466 -0
  939. tools/forge_studio/deploy/deploy_engine.py +1792 -0
  940. tools/forge_studio/deploy/env_manager.py +431 -0
  941. tools/forge_studio/eject/__init__.py +2 -0
  942. tools/forge_studio/eject/docker_compose_generator.py +237 -0
  943. tools/forge_studio/eject/eject_engine.py +230 -0
  944. tools/forge_studio/eject/expo_scaffolder.py +303 -0
  945. tools/forge_studio/eject/nextjs_scaffolder.py +338 -0
  946. tools/forge_studio/enterprise/__init__.py +0 -0
  947. tools/forge_studio/enterprise/custom_frameworks.py +826 -0
  948. tools/forge_studio/enterprise/hardening_engine.py +1530 -0
  949. tools/forge_studio/enterprise/sso_manager.py +718 -0
  950. tools/forge_studio/enterprise/whitelabel_engine.py +887 -0
  951. tools/forge_studio/formula/__init__.py +0 -0
  952. tools/forge_studio/formula/expression_engine.py +562 -0
  953. tools/forge_studio/formula/formula_registry.py +265 -0
  954. tools/forge_studio/generator/__init__.py +2 -0
  955. tools/forge_studio/generator/app_generator.py +584 -0
  956. tools/forge_studio/generator/complexity_detector.py +368 -0
  957. tools/forge_studio/generator/prompt_templates.py +104 -0
  958. tools/forge_studio/generator/spec_builder.py +192 -0
  959. tools/forge_studio/intake_bridge.py +898 -0
  960. tools/forge_studio/marketplace/__init__.py +0 -0
  961. tools/forge_studio/marketplace/component_hub.py +428 -0
  962. tools/forge_studio/models.py +369 -0
  963. tools/forge_studio/renderer/__init__.py +2 -0
  964. tools/forge_studio/renderer/json_render_engine.py +623 -0
  965. tools/forge_studio/renderer/layout_engine.py +214 -0
  966. tools/forge_studio/renderer/rn_component_map.py +182 -0
  967. tools/forge_studio/supabase/__init__.py +2 -0
  968. tools/forge_studio/supabase/auth_generator.py +283 -0
  969. tools/forge_studio/supabase/migration_generator.py +93 -0
  970. tools/forge_studio/supabase/schema_generator.py +281 -0
  971. tools/forge_studio/tenant_manager.py +387 -0
  972. tools/forge_studio/workflow/__init__.py +2 -0
  973. tools/forge_studio/workflow/bpmn_adapter.py +489 -0
  974. tools/govcon/draft_orchestrator.py +1151 -0
  975. tools/govcon/engine_enrichment.py +373 -0
  976. tools/govcon/knowledge_base.py +487 -0
  977. tools/govcon/knowledge_ingestion.py +510 -0
  978. tools/govcon/sam_scanner.py +754 -0
  979. tools/harness/__init__.py +6 -0
  980. tools/harness/exit_criteria_evaluator.py +231 -0
  981. tools/harness/maturity_assessor.py +347 -0
  982. tools/harness/scaffold_harness.py +416 -0
  983. tools/harness/trace_analyzer.py +281 -0
  984. tools/infra/__init__.py +1 -0
  985. tools/infra/ansible_generator.py +867 -0
  986. tools/infra/dockerfile_generator.py +359 -0
  987. tools/infra/infra_status.py +384 -0
  988. tools/infra/ironbank_metadata_generator.py +403 -0
  989. tools/infra/k8s_generator.py +1000 -0
  990. tools/infra/pipeline_generator.py +830 -0
  991. tools/infra/rollback.py +389 -0
  992. tools/infra/terraform_generator.py +1140 -0
  993. tools/infra/terraform_generator_azure.py +1252 -0
  994. tools/infra/terraform_generator_gcp.py +951 -0
  995. tools/infra/terraform_generator_ibm.py +359 -0
  996. tools/infra/terraform_generator_oci.py +918 -0
  997. tools/infra/terraform_generator_onprem.py +318 -0
  998. tools/knowledge/__init__.py +1 -0
  999. tools/knowledge/knowledge_ingest.py +281 -0
  1000. tools/knowledge/pattern_detector.py +681 -0
  1001. tools/knowledge/recommendation_engine.py +449 -0
  1002. tools/knowledge/self_heal_analyzer.py +492 -0
  1003. tools/knowledge_graph/__init__.py +2 -0
  1004. tools/knowledge_graph/graph_rag.py +498 -0
  1005. tools/knowledge_graph/ingester.py +406 -0
  1006. tools/knowledge_graph/insight_generator.py +369 -0
  1007. tools/knowledge_graph/text_network.py +832 -0
  1008. tools/llm/__init__.py +72 -0
  1009. tools/llm/anthropic_provider.py +170 -0
  1010. tools/llm/azure_openai_provider.py +338 -0
  1011. tools/llm/bedrock_provider.py +315 -0
  1012. tools/llm/embedding_provider.py +438 -0
  1013. tools/llm/gemini_provider.py +381 -0
  1014. tools/llm/ibm_watsonx_provider.py +231 -0
  1015. tools/llm/oci_genai_provider.py +462 -0
  1016. tools/llm/ollama_provider.py +350 -0
  1017. tools/llm/openai_provider.py +225 -0
  1018. tools/llm/prompt_registry.py +447 -0
  1019. tools/llm/provider.py +355 -0
  1020. tools/llm/provider_sdk.py +175 -0
  1021. tools/llm/router.py +1124 -0
  1022. tools/llm/semantic_cache.py +394 -0
  1023. tools/llm/vertex_ai_provider.py +374 -0
  1024. tools/maintenance/__init__.py +2 -0
  1025. tools/maintenance/dependency_scanner.py +1016 -0
  1026. tools/maintenance/maintenance_auditor.py +804 -0
  1027. tools/maintenance/remediation_engine.py +957 -0
  1028. tools/maintenance/vulnerability_checker.py +978 -0
  1029. tools/manifest.md +1066 -0
  1030. tools/marketplace/asset_installer.py +639 -0
  1031. tools/marketplace/feedback_validator.py +359 -0
  1032. tools/marketplace/license_client.py +458 -0
  1033. tools/marketplace/module_crypto.py +544 -0
  1034. tools/marketplace/module_runtime.py +236 -0
  1035. tools/marketplace/token_store.py +264 -0
  1036. tools/mbse/__init__.py +3 -0
  1037. tools/mbse/des_assessor.py +1173 -0
  1038. tools/mbse/des_report_generator.py +787 -0
  1039. tools/mbse/diagram_extractor.py +792 -0
  1040. tools/mbse/digital_thread.py +1650 -0
  1041. tools/mbse/model_code_generator.py +1115 -0
  1042. tools/mbse/model_control_mapper.py +410 -0
  1043. tools/mbse/pi_model_tracker.py +1079 -0
  1044. tools/mbse/reqif_parser.py +1468 -0
  1045. tools/mbse/sync_engine.py +1789 -0
  1046. tools/mbse/thread_heatmap.py +445 -0
  1047. tools/mbse/xmi_parser.py +1558 -0
  1048. tools/mcp/builder_server.py +64 -0
  1049. tools/mcp/compliance_server.py +64 -0
  1050. tools/mcp/connector_forge_server.py +155 -0
  1051. tools/mcp/core_server.py +64 -0
  1052. tools/mcp/devsecops_server.py +11 -0
  1053. tools/mcp/devsecops_zta_server.py +64 -0
  1054. tools/mcp/knowledge_server.py +64 -0
  1055. tools/mcp/monitor_server.py +64 -0
  1056. tools/mcp/ops_server.py +300 -0
  1057. tools/mcp/requirements_analyst_server.py +64 -0
  1058. tools/mcp/requirements_server.py +11 -0
  1059. tools/mcp/security_server.py +64 -0
  1060. tools/mcp/simulation_server.py +64 -0
  1061. tools/mcp/supply_chain_server.py +64 -0
  1062. tools/mcp/tool_registry.py +299 -0
  1063. tools/memory/__init__.py +2 -0
  1064. tools/memory/auto_capture.py +346 -0
  1065. tools/memory/embed_memory.py +157 -0
  1066. tools/memory/history_compressor.py +334 -0
  1067. tools/memory/hybrid_search.py +235 -0
  1068. tools/memory/maintenance_cron.py +288 -0
  1069. tools/memory/memory_consolidation.py +439 -0
  1070. tools/memory/memory_db.py +132 -0
  1071. tools/memory/memory_read.py +101 -0
  1072. tools/memory/memory_write.py +221 -0
  1073. tools/memory/semantic_search.py +138 -0
  1074. tools/memory/time_decay.py +434 -0
  1075. tools/missions/__init__.py +2 -0
  1076. tools/missions/mission_engine.py +459 -0
  1077. tools/monitor/__init__.py +1 -0
  1078. tools/monitor/alert_correlator.py +486 -0
  1079. tools/monitor/auto_resolver.py +603 -0
  1080. tools/monitor/health_checker.py +507 -0
  1081. tools/monitor/heartbeat_daemon.py +779 -0
  1082. tools/monitor/log_analyzer.py +507 -0
  1083. tools/monitor/metric_collector.py +484 -0
  1084. tools/mosa/__init__.py +10 -0
  1085. tools/mosa/icd_generator.py +358 -0
  1086. tools/mosa/modular_design_analyzer.py +682 -0
  1087. tools/mosa/mosa_code_enforcer.py +348 -0
  1088. tools/mosa/tsp_generator.py +265 -0
  1089. tools/observability/__init__.py +100 -0
  1090. tools/observability/genai_attributes.py +88 -0
  1091. tools/observability/instrumentation.py +140 -0
  1092. tools/observability/mlflow_exporter.py +193 -0
  1093. tools/observability/otel_tracer.py +168 -0
  1094. tools/observability/provenance/__init__.py +3 -0
  1095. tools/observability/provenance/prov_recorder.py +322 -0
  1096. tools/observability/shap/__init__.py +3 -0
  1097. tools/observability/shap/agent_shap.py +274 -0
  1098. tools/observability/sqlite_tracer.py +360 -0
  1099. tools/observability/trace_context.py +205 -0
  1100. tools/observability/tracer.py +230 -0
  1101. tools/orchestration/__init__.py +1 -0
  1102. tools/orchestration/peer_channels.py +254 -0
  1103. tools/orchestration/saga_coordinator.py +390 -0
  1104. tools/project/__init__.py +1 -0
  1105. tools/project/manifest_loader.py +418 -0
  1106. tools/project/project_create.py +350 -0
  1107. tools/project/project_list.py +171 -0
  1108. tools/project/project_scaffold.py +1715 -0
  1109. tools/project/project_status.py +478 -0
  1110. tools/project/session_context_builder.py +752 -0
  1111. tools/project/validate_manifest.py +54 -0
  1112. tools/rag/corrective_rag.py +582 -0
  1113. tools/rag/source_registry.py +482 -0
  1114. tools/requirements/__init__.py +1 -0
  1115. tools/requirements/ai_governance_scorer.py +207 -0
  1116. tools/requirements/boundary_analyzer.py +1281 -0
  1117. tools/requirements/clarification_engine.py +605 -0
  1118. tools/requirements/complexity_scorer.py +369 -0
  1119. tools/requirements/consistency_analyzer.py +789 -0
  1120. tools/requirements/constitution_manager.py +592 -0
  1121. tools/requirements/decomposition_engine.py +764 -0
  1122. tools/requirements/document_extractor.py +1002 -0
  1123. tools/requirements/elicitation_techniques.py +508 -0
  1124. tools/requirements/gap_detector.py +260 -0
  1125. tools/requirements/intake_engine.py +2175 -0
  1126. tools/requirements/prd_generator.py +839 -0
  1127. tools/requirements/prd_validator.py +584 -0
  1128. tools/requirements/readiness_scorer.py +302 -0
  1129. tools/requirements/spec_organizer.py +1015 -0
  1130. tools/requirements/spec_quality_checker.py +1083 -0
  1131. tools/requirements/traceability_builder.py +566 -0
  1132. tools/research/__init__.py +3 -0
  1133. tools/research/academic_scanner.py +130 -0
  1134. tools/research/build_buy_analyzer.py +229 -0
  1135. tools/research/challenge_scorer.py +280 -0
  1136. tools/research/community_scanner.py +174 -0
  1137. tools/research/cross_engine_bridge.py +124 -0
  1138. tools/research/dossier_generator.py +305 -0
  1139. tools/research/landscape_scanner.py +315 -0
  1140. tools/research/regulatory_scanner.py +248 -0
  1141. tools/research/research_manager.py +469 -0
  1142. tools/research/source_scanner.py +150 -0
  1143. tools/research/vertical_loader.py +118 -0
  1144. tools/saas/__init__.py +0 -0
  1145. tools/saas/licensing/__init__.py +0 -0
  1146. tools/saas/licensing/license_validator.py +345 -0
  1147. tools/scaffold/__init__.py +2 -0
  1148. tools/scaffold/golden_path.py +504 -0
  1149. tools/security/__init__.py +1 -0
  1150. tools/security/agent_output_validator.py +330 -0
  1151. tools/security/agent_trust_scorer.py +652 -0
  1152. tools/security/ai_bom_generator.py +718 -0
  1153. tools/security/ai_telemetry_logger.py +469 -0
  1154. tools/security/atlas_red_team.py +541 -0
  1155. tools/security/code_pattern_scanner.py +382 -0
  1156. tools/security/confabulation_detector.py +265 -0
  1157. tools/security/container_scanner.py +489 -0
  1158. tools/security/dependency_auditor.py +942 -0
  1159. tools/security/endpoint_security_scanner.py +626 -0
  1160. tools/security/mcp_tool_authorizer.py +242 -0
  1161. tools/security/output_verifier.py +427 -0
  1162. tools/security/prompt_injection_detector.py +737 -0
  1163. tools/security/sast_runner.py +946 -0
  1164. tools/security/secret_detector.py +376 -0
  1165. tools/security/threat_modeler.py +678 -0
  1166. tools/security/tool_chain_validator.py +357 -0
  1167. tools/security/vuln_scanner.py +536 -0
  1168. tools/simulation/__init__.py +2 -0
  1169. tools/simulation/ato_simulator.py +517 -0
  1170. tools/simulation/coa_generator.py +1539 -0
  1171. tools/simulation/monte_carlo.py +745 -0
  1172. tools/simulation/scenario_manager.py +1060 -0
  1173. tools/simulation/simulation_engine.py +1091 -0
  1174. tools/simulator/__init__.py +2 -0
  1175. tools/simulator/sim_runner.py +272 -0
  1176. tools/supply_chain/__init__.py +2 -0
  1177. tools/supply_chain/cve_triager.py +690 -0
  1178. tools/supply_chain/dependency_graph.py +630 -0
  1179. tools/supply_chain/isa_manager.py +526 -0
  1180. tools/supply_chain/scrm_assessor.py +531 -0
  1181. tools/supply_chain/slsa_verifier.py +473 -0
  1182. tools/testing/__init__.py +2 -0
  1183. tools/testing/acceptance_validator.py +411 -0
  1184. tools/testing/api_surface_extractor.py +749 -0
  1185. tools/testing/claude_dir_validator.py +831 -0
  1186. tools/testing/data_types.py +199 -0
  1187. tools/testing/e2e_runner.py +715 -0
  1188. tools/testing/fuzz_cli.py +306 -0
  1189. tools/testing/health_check.py +483 -0
  1190. tools/testing/platform_check.py +143 -0
  1191. tools/testing/production_audit.py +1836 -0
  1192. tools/testing/production_remediate.py +803 -0
  1193. tools/testing/screenshot_validator.py +538 -0
  1194. tools/testing/smoke_test.py +283 -0
  1195. tools/testing/test_agent_models.py +117 -0
  1196. tools/testing/test_orchestrator.py +957 -0
  1197. tools/testing/utils.py +229 -0
  1198. tools/writeguard/__init__.py +1 -0
  1199. tools/writeguard/main.py +1 -0
  1200. tools/writing/__init__.py +7 -0
  1201. tools/writing/ai_content_detector.py +316 -0
  1202. tools/writing/analysis_engine.py +454 -0
  1203. tools/writing/batch_analyzer.py +276 -0
  1204. tools/writing/coherence_analyzer.py +221 -0
  1205. tools/writing/govcon_bridge.py +509 -0
  1206. tools/writing/grammar_checker.py +270 -0
  1207. tools/writing/plagiarism_detector.py +106 -0
  1208. tools/writing/readability_scorer.py +201 -0
  1209. tools/writing/rewriter.py +96 -0
  1210. tools/writing/signal_registrar.py +167 -0
  1211. tools/writing/snippet_manager.py +276 -0
  1212. tools/writing/style_enforcer.py +220 -0
  1213. tools/writing/style_guide_manager.py +438 -0
  1214. tools/writing/tone_profiler.py +168 -0
tools/llm/router.py ADDED
@@ -0,0 +1,1124 @@
1
+ # [TEMPLATE: CUI // SP-CTI]
2
+ """Config-driven LLM router.
3
+
4
+ Reads args/llm_config.yaml and resolves each SPARKPILOT function to a
5
+ provider + model via fallback chain. Probes provider availability
6
+ and caches results.
7
+ """
8
+
9
+ import copy
10
+ import logging
11
+ import os
12
+ import re
13
+ import sqlite3
14
+ import time
15
+ from pathlib import Path
16
+ from typing import Dict, Optional, Tuple
17
+
18
+ try:
19
+ import yaml
20
+ except ImportError:
21
+ yaml = None
22
+
23
+ from tools.llm.provider import LLMProvider, LLMRequest, LLMResponse, EmbeddingProvider
24
+
25
+ try:
26
+ from tools.core.circuit_breaker import get_breaker, CircuitOpenError
27
+ except ImportError:
28
+ get_breaker = None # type: ignore[assignment]
29
+ CircuitOpenError = None # type: ignore[assignment,misc]
30
+
31
+ logger = logging.getLogger("icdev.llm.router")
32
+
33
+ BASE_DIR = Path(__file__).resolve().parent.parent.parent
34
+ DEFAULT_CONFIG_PATH = BASE_DIR / "args" / "llm_config.yaml"
35
+
36
+
37
+ def _expand_env(value):
38
+ """Expand ${VAR:-default} patterns in string values."""
39
+ if not isinstance(value, str):
40
+ return value
41
+ pattern = r'\$\{([^}]+)\}'
42
+ def replacer(match):
43
+ expr = match.group(1)
44
+ if ":-" in expr:
45
+ var, default = expr.split(":-", 1)
46
+ return os.environ.get(var, default)
47
+ return os.environ.get(expr, match.group(0))
48
+ return re.sub(pattern, replacer, value)
49
+
50
+
51
+ class LLMRouter:
52
+ """Config-driven router that maps SPARKPILOT functions to LLM providers.
53
+
54
+ Walks fallback chains, probes availability, and returns the first
55
+ responsive provider + model pair.
56
+ """
57
+
58
+ def __init__(self, config_path=None):
59
+ self._config_path = Path(config_path) if config_path else DEFAULT_CONFIG_PATH
60
+ self._config: Dict = {}
61
+ self._providers: Dict[str, LLMProvider] = {}
62
+ self._embedding_providers: Dict[str, EmbeddingProvider] = {}
63
+ self._availability_cache: Dict[str, bool] = {}
64
+ self._availability_cache_time: float = 0.0
65
+ self._cache_ttl: float = 1800.0
66
+
67
+ self._load_config()
68
+
69
+ # -------------------------------------------------------------------
70
+ # Config loading
71
+ # -------------------------------------------------------------------
72
+ def _load_config(self):
73
+ """Load and parse llm_config.yaml."""
74
+ if yaml is None:
75
+ logger.warning("PyYAML not available — using empty LLM config")
76
+ self._config = {}
77
+ return
78
+ if not self._config_path.exists():
79
+ logger.warning("LLM config not found at %s — using empty config", self._config_path)
80
+ self._config = {}
81
+ return
82
+ try:
83
+ with open(self._config_path, "r", encoding="utf-8") as f:
84
+ self._config = yaml.safe_load(f) or {}
85
+ self._cache_ttl = float(
86
+ self._config.get("settings", {}).get(
87
+ "availability_cache_ttl_seconds", 1800
88
+ )
89
+ )
90
+ logger.info(
91
+ "LLM config loaded: %d providers, %d models, %d routes",
92
+ len(self._config.get("providers", {})),
93
+ len(self._config.get("models", {})),
94
+ len(self._config.get("routing", {})),
95
+ )
96
+ except Exception as exc:
97
+ logger.error("Failed to load LLM config: %s", exc)
98
+ self._config = {}
99
+
100
+ # -------------------------------------------------------------------
101
+ # Provider instantiation (lazy)
102
+ # -------------------------------------------------------------------
103
+ def _get_provider(self, provider_name: str) -> Optional[LLMProvider]:
104
+ """Get or create a provider instance by name."""
105
+ if provider_name in self._providers:
106
+ return self._providers[provider_name]
107
+
108
+ provider_cfg = self._config.get("providers", {}).get(provider_name, {})
109
+ if not provider_cfg:
110
+ logger.warning("Provider '%s' not found in config", provider_name)
111
+ return None
112
+
113
+ ptype = provider_cfg.get("type", "")
114
+ instance = None
115
+
116
+ try:
117
+ if ptype == "bedrock":
118
+ from tools.llm.bedrock_provider import BedrockLLMProvider
119
+ region = _expand_env(provider_cfg.get("region", "us-gov-west-1"))
120
+ instance = BedrockLLMProvider(region=region)
121
+
122
+ elif ptype == "anthropic":
123
+ from tools.llm.anthropic_provider import AnthropicLLMProvider
124
+ api_key_env = provider_cfg.get("api_key_env", "ANTHROPIC_API_KEY")
125
+ api_key = os.environ.get(api_key_env, "")
126
+ base_url = provider_cfg.get("base_url", "https://api.anthropic.com")
127
+ instance = AnthropicLLMProvider(api_key=api_key, base_url=base_url)
128
+
129
+ elif ptype == "ollama":
130
+ from tools.llm.ollama_provider import OllamaProvider
131
+ base_url = _expand_env(
132
+ provider_cfg.get("base_url", "http://localhost:11434")
133
+ )
134
+ instance = OllamaProvider(base_url=base_url)
135
+
136
+ elif ptype == "gemini":
137
+ from tools.llm.gemini_provider import GeminiProvider
138
+ api_key = provider_cfg.get("api_key", "")
139
+ if not api_key:
140
+ api_key_env = provider_cfg.get("api_key_env", "GOOGLE_API_KEY")
141
+ if api_key_env:
142
+ api_key = os.environ.get(api_key_env, "")
143
+ instance = GeminiProvider(api_key=api_key)
144
+
145
+ elif ptype in ("openai", "openai_compatible"):
146
+ from tools.llm.openai_provider import OpenAICompatibleProvider
147
+ api_key = provider_cfg.get("api_key", "")
148
+ if not api_key:
149
+ api_key_env = provider_cfg.get("api_key_env", "")
150
+ if api_key_env:
151
+ api_key = os.environ.get(api_key_env, "")
152
+ base_url = _expand_env(provider_cfg.get("base_url", "https://api.openai.com/v1"))
153
+ instance = OpenAICompatibleProvider(
154
+ api_key=api_key,
155
+ base_url=base_url,
156
+ provider_label=provider_name,
157
+ )
158
+
159
+ elif ptype == "azure_openai":
160
+ from tools.llm.azure_openai_provider import AzureOpenAIProvider
161
+ endpoint = _expand_env(provider_cfg.get("endpoint", ""))
162
+ api_key = _expand_env(provider_cfg.get("api_key", ""))
163
+ if not api_key:
164
+ api_key_env = provider_cfg.get("api_key_env", "AZURE_OPENAI_API_KEY")
165
+ api_key = os.environ.get(api_key_env, "")
166
+ api_version = provider_cfg.get("api_version", "2024-06-01")
167
+ instance = AzureOpenAIProvider(
168
+ endpoint=endpoint, api_key=api_key,
169
+ api_version=api_version,
170
+ )
171
+
172
+ elif ptype == "vertex_ai":
173
+ from tools.llm.vertex_ai_provider import VertexAIProvider
174
+ project_id = _expand_env(provider_cfg.get("project_id", ""))
175
+ location = provider_cfg.get("location", "us-east4")
176
+ instance = VertexAIProvider(
177
+ project_id=project_id, location=location,
178
+ )
179
+
180
+ elif ptype == "oci_genai":
181
+ from tools.llm.oci_genai_provider import OCIGenAIProvider
182
+ compartment_id = _expand_env(provider_cfg.get("compartment_id", ""))
183
+ serving_mode = provider_cfg.get("serving_mode", "ON_DEMAND")
184
+ instance = OCIGenAIProvider(
185
+ compartment_id=compartment_id,
186
+ serving_mode=serving_mode,
187
+ )
188
+
189
+ elif ptype == "ibm_watsonx":
190
+ from tools.llm.ibm_watsonx_provider import IBMWatsonxProvider
191
+ api_key = _expand_env(provider_cfg.get("api_key", ""))
192
+ if not api_key:
193
+ api_key_env = provider_cfg.get("api_key_env", "IBM_CLOUD_API_KEY")
194
+ api_key = os.environ.get(api_key_env, "")
195
+ project_id = _expand_env(provider_cfg.get("project_id", ""))
196
+ if not project_id:
197
+ project_id = os.environ.get("IBM_WATSONX_PROJECT_ID", "")
198
+ url = _expand_env(provider_cfg.get("url", ""))
199
+ if not url:
200
+ url = os.environ.get("IBM_WATSONX_URL",
201
+ "https://us-south.ml.cloud.ibm.com")
202
+ instance = IBMWatsonxProvider(
203
+ api_key=api_key, project_id=project_id, url=url,
204
+ )
205
+
206
+ else:
207
+ logger.warning("Unknown provider type: %s", ptype)
208
+ return None
209
+
210
+ except ImportError as exc:
211
+ logger.warning("Could not import provider '%s': %s", provider_name, exc)
212
+ return None
213
+ except Exception as exc:
214
+ logger.warning("Failed to create provider '%s': %s", provider_name, exc)
215
+ return None
216
+
217
+ if instance:
218
+ self._providers[provider_name] = instance
219
+ logger.debug("Created provider instance: %s (%s)", provider_name, ptype)
220
+
221
+ return instance
222
+
223
+ # -------------------------------------------------------------------
224
+ # Model resolution
225
+ # -------------------------------------------------------------------
226
+ def _get_model_config(self, model_name: str) -> dict:
227
+ """Get model configuration by logical name."""
228
+ return self._config.get("models", {}).get(model_name, {})
229
+
230
+ def _get_model_breaker(self, model_name: str):
231
+ """Get or create a circuit breaker for the named model.
232
+
233
+ Returns None if the circuit breaker module is not available.
234
+ """
235
+ if get_breaker is None:
236
+ return None
237
+ return get_breaker(f"llm.{model_name}")
238
+
239
+ def _check_model_available(self, model_name: str) -> bool:
240
+ """Check if a model is available, using cache and circuit breaker."""
241
+ # Circuit breaker fast-path: if breaker is OPEN, skip immediately
242
+ breaker = self._get_model_breaker(model_name)
243
+ if breaker is not None and not breaker.allow_request():
244
+ logger.debug("Circuit breaker OPEN for %s — skipping", model_name)
245
+ return False
246
+
247
+ now = time.time()
248
+ if (now - self._availability_cache_time) > self._cache_ttl:
249
+ self._availability_cache = {}
250
+ self._availability_cache_time = now
251
+
252
+ if model_name in self._availability_cache:
253
+ return self._availability_cache[model_name]
254
+
255
+ model_cfg = self._get_model_config(model_name)
256
+ if not model_cfg:
257
+ self._availability_cache[model_name] = False
258
+ return False
259
+
260
+ provider_name = model_cfg.get("provider", "")
261
+ provider = self._get_provider(provider_name)
262
+ if provider is None:
263
+ self._availability_cache[model_name] = False
264
+ return False
265
+
266
+ prefer_local = self._config.get("settings", {}).get("prefer_local", False)
267
+ if prefer_local:
268
+ ptype = self._config.get("providers", {}).get(provider_name, {}).get("type", "")
269
+ if ptype not in ("openai_compatible",) and provider_name not in ("ollama", "vllm"):
270
+ # In prefer_local mode, skip cloud providers
271
+ self._availability_cache[model_name] = False
272
+ return False
273
+
274
+ try:
275
+ available = provider.check_availability(model_cfg.get("model_id", ""))
276
+ self._availability_cache[model_name] = available
277
+ return available
278
+ except Exception:
279
+ self._availability_cache[model_name] = False
280
+ return False
281
+
282
+ # -------------------------------------------------------------------
283
+ # Routing
284
+ # -------------------------------------------------------------------
285
+ def get_provider_for_function(self, function: str) -> Tuple[Optional[LLMProvider], str, dict]:
286
+ """Resolve function to (provider, model_id, model_config).
287
+
288
+ Walks the fallback chain for the given function.
289
+ Returns (None, "", {}) if no model is available.
290
+ """
291
+ routing = self._config.get("routing", {})
292
+ route = routing.get(function, routing.get("default", {}))
293
+ chain = route.get("chain", [])
294
+
295
+ if not chain:
296
+ logger.warning("No routing chain for function '%s'", function)
297
+ return None, "", {}
298
+
299
+ for model_name in chain:
300
+ if self._check_model_available(model_name):
301
+ model_cfg = self._get_model_config(model_name)
302
+ provider_name = model_cfg.get("provider", "")
303
+ provider = self._get_provider(provider_name)
304
+ if provider:
305
+ logger.debug(
306
+ "Resolved %s -> %s (%s via %s)",
307
+ function, model_name, model_cfg.get("model_id"), provider_name,
308
+ )
309
+ return provider, model_cfg.get("model_id", ""), model_cfg
310
+
311
+ # Fallback: try first model in chain without availability check
312
+ if chain:
313
+ model_name = chain[0]
314
+ model_cfg = self._get_model_config(model_name)
315
+ provider_name = model_cfg.get("provider", "")
316
+ provider = self._get_provider(provider_name)
317
+ if provider:
318
+ logger.warning(
319
+ "No confirmed available model for '%s'; attempting %s anyway",
320
+ function, model_name,
321
+ )
322
+ return provider, model_cfg.get("model_id", ""), model_cfg
323
+
324
+ return None, "", {}
325
+
326
+ def get_effort(self, function: str) -> str:
327
+ """Get configured effort level for a function."""
328
+ routing = self._config.get("routing", {})
329
+ route = routing.get(function, routing.get("default", {}))
330
+ return route.get("effort", "medium")
331
+
332
+ def _get_chain_for_function(self, function: str) -> list:
333
+ """Get the model chain for a function."""
334
+ routing = self._config.get("routing", {})
335
+ route = routing.get(function, routing.get("default", {}))
336
+ return route.get("chain", [])
337
+
338
+ def _scan_for_injection(self, request: LLMRequest) -> Optional[str]:
339
+ """Scan request messages for prompt injection patterns.
340
+
341
+ Returns action string ('block', 'flag', 'warn', 'allow') or None
342
+ if scanner is unavailable. Graceful import — does not fail if
343
+ prompt_injection_detector is not importable.
344
+ """
345
+ try:
346
+ from tools.security.prompt_injection_detector import PromptInjectionDetector
347
+ except ImportError:
348
+ return None
349
+
350
+ detector = PromptInjectionDetector()
351
+ # Scan all user messages in the request
352
+ texts = []
353
+ for msg in (request.messages or []):
354
+ if isinstance(msg, dict):
355
+ content = msg.get("content", "")
356
+ if isinstance(content, str):
357
+ texts.append(content)
358
+
359
+ if not texts:
360
+ return "allow"
361
+
362
+ combined = "\n".join(texts)
363
+ result = detector.scan_text(combined, source="llm_router")
364
+
365
+ if result["detected"]:
366
+ logger.warning(
367
+ "Prompt injection detected in LLM request: confidence=%.2f action=%s findings=%d",
368
+ result["confidence"], result["action"], result["finding_count"],
369
+ )
370
+ # Log to DB (best-effort)
371
+ detector.log_detection(
372
+ result,
373
+ project_id=request.project_id,
374
+ user_id=None,
375
+ )
376
+
377
+ return result["action"]
378
+
379
+ # -------------------------------------------------------------------
380
+ # Two-tier routing helpers (D-TT1: qwen3 worker → Claude planner)
381
+ # -------------------------------------------------------------------
382
+
383
+ @staticmethod
384
+ def _estimate_tokens(request: LLMRequest) -> int:
385
+ """Rough token estimate for a request (~4 chars per token).
386
+
387
+ Used to detect prompts that will exceed a local model's context
388
+ window (e.g. qwen3.5 at 32K) before sending to Ollama.
389
+ """
390
+ total_chars = len(request.system_prompt or "")
391
+ for msg in (request.messages or []):
392
+ content = msg.get("content", "") if isinstance(msg, dict) else str(msg)
393
+ if isinstance(content, str):
394
+ total_chars += len(content)
395
+ elif isinstance(content, list):
396
+ for block in content:
397
+ if isinstance(block, dict):
398
+ total_chars += len(block.get("text", ""))
399
+ return total_chars // 4 # conservative ~4 chars/token estimate
400
+
401
+ def _fit_to_context(self, model_name: str, request: LLMRequest) -> LLMRequest:
402
+ """Truncate request messages if estimated tokens exceed model num_ctx.
403
+
404
+ Trims user message content from the middle, preserving the first and
405
+ last portions so the model sees the task instruction and most recent
406
+ context. Only applies to Ollama models with num_ctx configured.
407
+ """
408
+ model_cfg = self._get_model_config(model_name)
409
+ num_ctx = model_cfg.get("num_ctx", 0)
410
+ if num_ctx <= 0:
411
+ return request
412
+
413
+ estimated = self._estimate_tokens(request)
414
+ # Reserve 20% of context for output tokens
415
+ input_budget = int(num_ctx * 0.80)
416
+
417
+ if estimated <= input_budget:
418
+ return request
419
+
420
+ overshoot = estimated - input_budget
421
+ overshoot_chars = overshoot * 4 # convert back to chars
422
+ logger.warning(
423
+ "Prompt exceeds model context (%s): ~%d tokens vs %d budget. "
424
+ "Truncating %d chars from user messages.",
425
+ model_name, estimated, input_budget, overshoot_chars,
426
+ )
427
+
428
+ req = copy.copy(request)
429
+ req.messages = list(request.messages or [])
430
+
431
+ # Truncate the longest user message from the middle
432
+ for i, msg in enumerate(req.messages):
433
+ if not isinstance(msg, dict) or msg.get("role") != "user":
434
+ continue
435
+ content = msg.get("content", "")
436
+ if not isinstance(content, str) or len(content) < overshoot_chars:
437
+ continue
438
+
439
+ # Keep first and last portions, cut from middle
440
+ keep = len(content) - overshoot_chars
441
+ half = keep // 2
442
+ truncated = (
443
+ content[:half]
444
+ + "\n\n[... content truncated to fit model context window ...]\n\n"
445
+ + content[-half:]
446
+ )
447
+ req.messages[i] = {**msg, "content": truncated}
448
+ logger.info(
449
+ "Truncated user message from %d to %d chars for %s",
450
+ len(content), len(truncated), model_name,
451
+ )
452
+ break
453
+
454
+ return req
455
+
456
+ def _invoke_model_direct(self, model_name: str, request: LLMRequest) -> Optional[LLMResponse]:
457
+ """Invoke a specific named model without chain fallback.
458
+
459
+ Returns None on any error so callers can fall through to chain.
460
+ """
461
+ # Circuit breaker fast-path
462
+ breaker = self._get_model_breaker(model_name)
463
+ if breaker is not None and not breaker.allow_request():
464
+ logger.debug("Two-tier: circuit breaker OPEN for %s — skipping", model_name)
465
+ return None
466
+
467
+ model_cfg = self._get_model_config(model_name)
468
+ if not model_cfg:
469
+ logger.warning("Two-tier: model '%s' not found in config", model_name)
470
+ return None
471
+ provider_name = model_cfg.get("provider", "")
472
+ provider = self._get_provider(provider_name)
473
+ if provider is None:
474
+ logger.warning("Two-tier: provider '%s' unavailable for model '%s'", provider_name, model_name)
475
+ return None
476
+ model_id = model_cfg.get("model_id", "")
477
+
478
+ # Guard: truncate prompt if it exceeds model context window
479
+ fitted_request = self._fit_to_context(model_name, request)
480
+
481
+ try:
482
+ result = provider.invoke(fitted_request, model_id, model_cfg)
483
+ if breaker is not None:
484
+ breaker.record_success()
485
+ return result
486
+ except Exception as exc:
487
+ if breaker is not None:
488
+ breaker.record_failure()
489
+ logger.warning("Two-tier: direct invoke failed for %s/%s: %s", model_name, model_id, exc)
490
+ return None
491
+
492
+ @staticmethod
493
+ def _sanitize_rag_chunk(text: str) -> str:
494
+ """Remove known prompt injection patterns from RAG chunk content.
495
+
496
+ SEC: Mitigates indirect prompt injection — attackers could embed
497
+ instructions in documents that get retrieved and injected into
498
+ the LLM system prompt. This strips common injection patterns.
499
+ """
500
+ import re as _re
501
+ # Patterns that attempt to override system behavior
502
+ _injection_patterns = [
503
+ _re.compile(r"(?i)ignore\s+(all\s+)?previous\s+instructions?"),
504
+ _re.compile(r"(?i)you\s+are\s+now\s+(?:a|an|in)\s+"),
505
+ _re.compile(r"(?i)system\s*:\s*"),
506
+ _re.compile(r"(?i)<<\s*SYS\s*>>"),
507
+ _re.compile(r"(?i)\[INST\]"),
508
+ _re.compile(r"(?i)forget\s+(?:all|everything|your)\s+"),
509
+ _re.compile(r"(?i)new\s+instructions?\s*:"),
510
+ _re.compile(r"(?i)override\s+(?:previous|all|system)"),
511
+ ]
512
+ sanitized = text
513
+ for pattern in _injection_patterns:
514
+ sanitized = pattern.sub("[FILTERED]", sanitized)
515
+ return sanitized
516
+
517
+ def _rag_augment(self, request: LLMRequest, function: str) -> LLMRequest:
518
+ """Prepend RAG context to request system prompt (D-RAG-2, D-RAG-21).
519
+
520
+ Graceful import: does nothing if RAG subsystem unavailable.
521
+ RAG context goes into the system prompt of _draft_request() so
522
+ qwen3 produces a better draft; Claude reviews the draft without
523
+ seeing raw chunks. Maximum token savings.
524
+
525
+ D-RAG-21: When citation_enabled=true, chunks are tagged as [SOURCE-N]
526
+ and a citation instruction is appended from hardprompts/rag_citation.md.
527
+
528
+ Args:
529
+ request: Original LLM request.
530
+ function: SPARKPILOT function name (checked against denylist).
531
+
532
+ Returns:
533
+ Augmented LLMRequest (or original if RAG unavailable/disabled).
534
+ """
535
+ try:
536
+ from tools.rag.retriever import RAGRetriever
537
+ except ImportError:
538
+ return request # RAG subsystem not installed
539
+
540
+ # Check if RAG injection is enabled
541
+ rag_cfg = self._config.get("rag", {})
542
+ injection_cfg = rag_cfg.get("injection", {})
543
+ if not rag_cfg.get("enabled", False) or not injection_cfg.get("enabled", True):
544
+ return request
545
+
546
+ # Check function denylist
547
+ denylist = injection_cfg.get("function_denylist", [])
548
+ if function in denylist:
549
+ return request
550
+
551
+ # Extract user query from messages
552
+ query = ""
553
+ for msg in (request.messages or []):
554
+ if isinstance(msg, dict) and msg.get("role") == "user":
555
+ c = msg.get("content", "")
556
+ query = c if isinstance(c, str) else str(c)
557
+ break
558
+ if not query:
559
+ return request
560
+
561
+ try:
562
+ retriever = RAGRetriever()
563
+ top_k = injection_cfg.get("injection_top_k", 5)
564
+ max_chars = injection_cfg.get("max_injection_chars", 4000)
565
+ citation_enabled = injection_cfg.get("citation_enabled", True)
566
+ citation_instruction = injection_cfg.get("citation_instruction", True)
567
+
568
+ results = retriever.search(query=query, top_k=top_k)
569
+ if not results:
570
+ return request
571
+
572
+ # Build context block with optional [SOURCE-N] tags (D-RAG-21)
573
+ # SEC: Sanitize chunk content to mitigate indirect prompt injection
574
+ context_parts = []
575
+ total_chars = 0
576
+ for i, r in enumerate(results):
577
+ snippet = r.content[:max_chars - total_chars] if total_chars + len(r.content) > max_chars else r.content
578
+ # SEC: Strip known prompt injection patterns from retrieved chunks
579
+ snippet = self._sanitize_rag_chunk(snippet)
580
+ source_label = f"{r.source_type}"
581
+ if r.source_id:
582
+ source_label += f":{r.source_id}"
583
+ if citation_enabled:
584
+ tag = f"[SOURCE-{i + 1}]"
585
+ context_parts.append(f"{tag} ({source_label} | score={r.final_score:.2f})\n{snippet}")
586
+ else:
587
+ context_parts.append(f"[{source_label} | score={r.final_score:.2f}]\n{snippet}")
588
+ total_chars += len(snippet)
589
+ if total_chars >= max_chars:
590
+ break
591
+
592
+ if not context_parts:
593
+ return request
594
+
595
+ context_block = (
596
+ "\n[RELEVANT CONTEXT — retrieved from SPARKPILOT knowledge base]\n"
597
+ + "\n---\n".join(context_parts)
598
+ + "\n[END CONTEXT]\n"
599
+ )
600
+
601
+ # Append citation instruction if enabled (D-RAG-21)
602
+ citation_block = ""
603
+ if citation_enabled and citation_instruction:
604
+ citation_path = Path(__file__).resolve().parent.parent.parent / "hardprompts" / "rag_citation.md"
605
+ if citation_path.exists():
606
+ try:
607
+ citation_block = "\n" + citation_path.read_text(encoding="utf-8") + "\n"
608
+ except Exception:
609
+ pass
610
+
611
+ # Prepend to system prompt
612
+ req = copy.copy(request)
613
+ req.system_prompt = context_block + citation_block + (request.system_prompt or "")
614
+ logger.debug("RAG augment: injected %d chunks (%d chars, citations=%s) for %s",
615
+ len(context_parts), total_chars, citation_enabled, function)
616
+ return req
617
+
618
+ except Exception as exc:
619
+ logger.debug("RAG augment skipped for %s: %s", function, exc)
620
+ return request # Never fail the main pipeline
621
+
622
+ def _draft_request(self, request: LLMRequest) -> LLMRequest:
623
+ """Return a copy of request with a compact-output instruction appended.
624
+
625
+ Instructs qwen3 to produce a short, structured draft — the key to
626
+ keeping Claude's review input token count LOW vs Claude doing the
627
+ full task alone.
628
+ """
629
+ req = copy.copy(request)
630
+ compact = (
631
+ "\n\n[DRAFT MODE] Produce a COMPACT, structured response: bullet points, "
632
+ "short sentences, no step-by-step reasoning chains. Max ~400 words. "
633
+ "This draft will be reviewed and finalized by another model."
634
+ )
635
+ req.system_prompt = (request.system_prompt or "") + compact
636
+ return req
637
+
638
+ def _review_request(self, original: LLMRequest, draft: LLMResponse, function: str) -> LLMRequest:
639
+ """Build a Claude review request from the original task + qwen3 draft.
640
+
641
+ Claude receives: compact review system prompt + original task + draft.
642
+ This is intentionally smaller than Claude handling the full task alone.
643
+ """
644
+ req = copy.copy(original)
645
+ req.system_prompt = (
646
+ f"You are reviewing a draft from a local AI assistant (function: {function}). "
647
+ "Verify correctness, fix errors, fill gaps, and return the final polished response. "
648
+ "Be direct — do not explain what you changed."
649
+ )
650
+ # Extract original user message for context
651
+ original_task = ""
652
+ for msg in (original.messages or []):
653
+ if isinstance(msg, dict) and msg.get("role") == "user":
654
+ c = msg.get("content", "")
655
+ original_task = c if isinstance(c, str) else str(c)
656
+ break
657
+ req.messages = [{"role": "user", "content": (
658
+ f"ORIGINAL TASK:\n{original_task}\n\n"
659
+ f"DRAFT TO REVIEW:\n{draft.content}\n\n"
660
+ "Return the corrected, final response only."
661
+ )}]
662
+ return req
663
+
664
+ # -------------------------------------------------------------------
665
+ # Fine-tuned model override (D-FT-6)
666
+ # -------------------------------------------------------------------
667
+ def _check_finetuned_override(
668
+ self, function: str, tenant_id: str = "", project_id: str = "",
669
+ ) -> Optional[str]:
670
+ """Check if a fine-tuned model is active for this function (D-FT-6).
671
+
672
+ Queries ft_active_models for a promoted model version. Returns
673
+ the Ollama model name if found, else None.
674
+
675
+ This is an additive lookup — if no fine-tuned model is active,
676
+ returns None and caller falls through to default routing.
677
+ """
678
+ db_path = BASE_DIR / "data" / "icdev.db"
679
+ if not db_path.exists():
680
+ return None
681
+
682
+ try:
683
+ conn = sqlite3.connect(str(db_path))
684
+ row = conn.execute(
685
+ """SELECT ollama_model_name FROM ft_active_models
686
+ WHERE function_name = ? AND deactivated_at IS NULL
687
+ AND (tenant_id = ? OR tenant_id = '')
688
+ AND (project_id = ? OR project_id = '')
689
+ ORDER BY id DESC LIMIT 1""",
690
+ (function, tenant_id, project_id),
691
+ ).fetchone()
692
+ conn.close()
693
+ if row and row["ollama_model_name"]:
694
+ logger.info(
695
+ "Fine-tuned override: %s → %s",
696
+ function, row["ollama_model_name"],
697
+ )
698
+ return row["ollama_model_name"]
699
+ except Exception as exc:
700
+ logger.debug("Fine-tuned override check failed: %s", exc)
701
+
702
+ return None
703
+
704
+ def _invoke_finetuned_model(
705
+ self, ollama_model_name: str, request: LLMRequest,
706
+ ) -> Optional[LLMResponse]:
707
+ """Invoke a fine-tuned model via the Ollama provider.
708
+
709
+ Returns None on failure so caller can fall through to default.
710
+ """
711
+ # Find the Ollama provider instance
712
+ provider = self._get_provider("ollama")
713
+ if provider is None:
714
+ # Try to find any ollama-type provider
715
+ for pname, pcfg in self._config.get("providers", {}).items():
716
+ if pcfg.get("type") == "ollama":
717
+ provider = self._get_provider(pname)
718
+ if provider:
719
+ break
720
+ if provider is None:
721
+ logger.warning("Fine-tuned invoke: no Ollama provider available")
722
+ return None
723
+
724
+ try:
725
+ # Use the fine-tuned model name directly as model_id
726
+ model_cfg = {"model_id": ollama_model_name, "provider": "ollama"}
727
+ return provider.invoke(request, ollama_model_name, model_cfg)
728
+ except Exception as exc:
729
+ logger.warning(
730
+ "Fine-tuned invoke failed for %s: %s",
731
+ ollama_model_name, exc,
732
+ )
733
+ return None
734
+
735
+ def _maybe_invoke_two_tier(
736
+ self, function: str, request: LLMRequest
737
+ ) -> Optional[LLMResponse]:
738
+ """Apply two-tier routing if function is configured for it.
739
+
740
+ Returns LLMResponse if two-tier handled the call, else None
741
+ (caller falls through to normal chain-based routing).
742
+
743
+ Three paths:
744
+ planner_functions → Claude directly (no qwen3 pre-step)
745
+ worker_functions → qwen3 compact draft → Claude review
746
+ scanner_functions → qwen3 only (no review)
747
+ """
748
+ cfg = self._config.get("two_tier", {})
749
+ if not cfg.get("enabled", False):
750
+ return None
751
+
752
+ tier1 = cfg.get("tier1_model", "qwen3-local")
753
+ tier2 = cfg.get("tier2_model", "claude-sonnet")
754
+ planners = cfg.get("planner_functions", [])
755
+ workers = cfg.get("worker_functions", [])
756
+ scanners = cfg.get("scanner_functions", [])
757
+
758
+ if function in planners:
759
+ # Claude plans directly
760
+ logger.debug("Two-tier: %s → planner (Claude direct)", function)
761
+ result = self._invoke_model_direct(tier2, request)
762
+ if result is not None:
763
+ return result
764
+ # Fall through to chain on failure
765
+
766
+ elif function in workers:
767
+ # D-FT-6: Check if a fine-tuned model overrides tier1 for this function
768
+ ft_override = self._check_finetuned_override(
769
+ function,
770
+ tenant_id=getattr(request, "tenant_id", "") or "",
771
+ project_id=getattr(request, "project_id", "") or "",
772
+ )
773
+
774
+ # RAG augment: inject relevant context before drafting (D-RAG-2)
775
+ augmented = self._rag_augment(request, function)
776
+
777
+ if ft_override:
778
+ # Fine-tuned model replaces qwen3 as drafter
779
+ logger.debug(
780
+ "Two-tier: %s → worker (fine-tuned %s draft → Claude review)",
781
+ function, ft_override,
782
+ )
783
+ draft = self._invoke_finetuned_model(
784
+ ft_override, self._draft_request(augmented),
785
+ )
786
+ else:
787
+ # Default: qwen3 drafts
788
+ logger.debug("Two-tier: %s → worker (qwen3 draft → Claude review)", function)
789
+ draft = self._invoke_model_direct(tier1, self._draft_request(augmented))
790
+
791
+ if draft is not None:
792
+ review_req = self._review_request(request, draft, function)
793
+ reviewed = self._invoke_model_direct(tier2, review_req)
794
+ if reviewed is not None:
795
+ # Store draft on response for audit/observability
796
+ reviewed.draft_content = draft.content # type: ignore[attr-defined]
797
+ if ft_override:
798
+ reviewed.ft_model_used = ft_override # type: ignore[attr-defined]
799
+ return reviewed
800
+ # Claude unavailable — return draft as fallback
801
+ logger.warning("Two-tier: Claude review unavailable for %s, returning draft", function)
802
+ return draft
803
+ # Drafter unavailable — fall through to chain
804
+
805
+ elif function in scanners:
806
+ # qwen3 only, no review
807
+ logger.debug("Two-tier: %s → scanner (qwen3 only)", function)
808
+ result = self._invoke_model_direct(tier1, request)
809
+ if result is not None:
810
+ return result
811
+ # Fall through to chain on failure
812
+
813
+ return None # Not in two_tier config or model unavailable → use chain
814
+
815
+ def invoke(self, function: str, request: LLMRequest) -> LLMResponse:
816
+ """Resolve provider for function and invoke with fallback.
817
+
818
+ Walks the full fallback chain: if the first provider fails at
819
+ invocation time (e.g. missing credentials, network error), tries
820
+ the next model in the chain rather than raising immediately.
821
+
822
+ Args:
823
+ function: SPARKPILOT function name (e.g. 'code_generation', 'nlq_sql').
824
+ request: Vendor-agnostic LLM request.
825
+
826
+ Returns:
827
+ LLMResponse.
828
+
829
+ Raises:
830
+ RuntimeError: If no provider in the chain can serve the request.
831
+ """
832
+ # Scan for prompt injection before invoking (D217)
833
+ injection_action = self._scan_for_injection(request)
834
+ if injection_action == "block":
835
+ raise RuntimeError(
836
+ "Prompt injection detected with high confidence — request blocked. "
837
+ "Review the input content for injection patterns."
838
+ )
839
+
840
+ # Apply configured effort if not set on request
841
+ if not request.effort or request.effort == "medium":
842
+ request.effort = self.get_effort(function)
843
+
844
+ # Two-tier routing: qwen3 worker → Claude planner/reviewer
845
+ two_tier_result = self._maybe_invoke_two_tier(function, request)
846
+ if two_tier_result is not None:
847
+ return two_tier_result
848
+
849
+ chain = self._get_chain_for_function(function)
850
+ last_error = None
851
+
852
+ # D286: Create trace span for LLM invocation
853
+ try:
854
+ from tools.observability import get_tracer
855
+ tracer = get_tracer()
856
+ except ImportError:
857
+ tracer = None
858
+
859
+ for model_name in chain:
860
+ model_cfg = self._get_model_config(model_name)
861
+ if not model_cfg:
862
+ continue
863
+ provider_name = model_cfg.get("provider", "")
864
+ provider = self._get_provider(provider_name)
865
+ if provider is None:
866
+ continue
867
+ model_id = model_cfg.get("model_id", "")
868
+
869
+ # D286: Span with GenAI semantic conventions
870
+ span = None
871
+ if tracer:
872
+ span = tracer.start_span("gen_ai.invoke", kind="CLIENT", attributes={
873
+ "gen_ai.operation.name": "chat",
874
+ "gen_ai.system": provider_name,
875
+ "gen_ai.request.model": model_id,
876
+ "gen_ai.effort": request.effort or "medium",
877
+ "sparkpilot.llm_function": function,
878
+ })
879
+
880
+ breaker = self._get_model_breaker(model_name)
881
+ try:
882
+ import time as _time
883
+ _start = _time.time()
884
+ # Guard: truncate prompt if it exceeds model context window
885
+ fitted_request = self._fit_to_context(model_name, request)
886
+ response = provider.invoke(fitted_request, model_id, model_cfg)
887
+ _latency = int((_time.time() - _start) * 1000)
888
+
889
+ # Record success in circuit breaker
890
+ if breaker is not None:
891
+ breaker.record_success()
892
+
893
+ if span:
894
+ span.set_attribute("gen_ai.response.model", getattr(response, "model_id", model_id))
895
+ span.set_attribute("gen_ai.usage.input_tokens", getattr(response, "input_tokens", 0))
896
+ span.set_attribute("gen_ai.usage.output_tokens", getattr(response, "output_tokens", 0))
897
+ span.set_attribute("gen_ai.latency_ms", _latency)
898
+ if hasattr(response, "cost_usd"):
899
+ span.set_attribute("gen_ai.usage.cost_usd", response.cost_usd)
900
+ span.set_status("OK")
901
+ span.end()
902
+
903
+ return response
904
+ except Exception as exc:
905
+ # Record failure in circuit breaker
906
+ if breaker is not None:
907
+ breaker.record_failure()
908
+
909
+ logger.warning(
910
+ "Provider %s (%s) failed for %s: %s — trying next in chain",
911
+ provider_name, model_id, function, exc,
912
+ )
913
+ if span:
914
+ span.set_status("ERROR", str(exc))
915
+ span.add_event("provider_fallback", {
916
+ "failed_provider": provider_name,
917
+ "failed_model": model_id,
918
+ "error": str(exc),
919
+ })
920
+ span.end()
921
+ last_error = exc
922
+ # Mark model as unavailable in cache so next call skips it
923
+ self._availability_cache[model_name] = False
924
+ continue
925
+
926
+ raise RuntimeError(
927
+ "All providers in chain {} failed for function '{}'. "
928
+ "Last error: {}".format(chain, function, last_error)
929
+ )
930
+
931
+ def invoke_streaming(self, function: str, request: LLMRequest):
932
+ """Resolve provider and invoke with streaming + fallback."""
933
+ if not request.effort or request.effort == "medium":
934
+ request.effort = self.get_effort(function)
935
+
936
+ chain = self._get_chain_for_function(function)
937
+ last_error = None
938
+
939
+ for model_name in chain:
940
+ model_cfg = self._get_model_config(model_name)
941
+ if not model_cfg:
942
+ continue
943
+ provider_name = model_cfg.get("provider", "")
944
+ provider = self._get_provider(provider_name)
945
+ if provider is None:
946
+ continue
947
+ model_id = model_cfg.get("model_id", "")
948
+ try:
949
+ return provider.invoke_streaming(request, model_id, model_cfg)
950
+ except Exception as exc:
951
+ logger.warning(
952
+ "Streaming provider %s (%s) failed for %s: %s — trying next",
953
+ provider_name, model_id, function, exc,
954
+ )
955
+ last_error = exc
956
+ self._availability_cache[model_name] = False
957
+ continue
958
+
959
+ raise RuntimeError(
960
+ "All streaming providers in chain {} failed for function '{}'. "
961
+ "Last error: {}".format(chain, function, last_error)
962
+ )
963
+
964
+ # -------------------------------------------------------------------
965
+ # Embedding providers
966
+ # -------------------------------------------------------------------
967
+ def get_embedding_provider(self) -> EmbeddingProvider:
968
+ """Get the first available embedding provider.
969
+
970
+ Walks the embeddings.default_chain from config.
971
+
972
+ Raises:
973
+ RuntimeError if no embedding provider is available.
974
+ """
975
+ emb_cfg = self._config.get("embeddings", {})
976
+ chain = emb_cfg.get("default_chain", [])
977
+ models = emb_cfg.get("models", {})
978
+
979
+ for model_name in chain:
980
+ if model_name in self._embedding_providers:
981
+ return self._embedding_providers[model_name]
982
+
983
+ mcfg = models.get(model_name, {})
984
+ if not mcfg:
985
+ continue
986
+
987
+ provider_name = mcfg.get("provider", "")
988
+ ptype = self._config.get("providers", {}).get(provider_name, {}).get("type", "")
989
+
990
+ try:
991
+ emb = None
992
+ if ptype in ("openai", "openai_compatible"):
993
+ from tools.llm.embedding_provider import OpenAIEmbeddingProvider
994
+ pcfg = self._config.get("providers", {}).get(provider_name, {})
995
+ api_key = pcfg.get("api_key", "")
996
+ if not api_key:
997
+ api_key_env = pcfg.get("api_key_env", "")
998
+ if api_key_env:
999
+ api_key = os.environ.get(api_key_env, "")
1000
+ base_url = _expand_env(pcfg.get("base_url", "https://api.openai.com/v1"))
1001
+ emb = OpenAIEmbeddingProvider(
1002
+ api_key=api_key,
1003
+ base_url=base_url,
1004
+ model_id=mcfg.get("model_id", "text-embedding-3-small"),
1005
+ dims=mcfg.get("dimensions", 1536),
1006
+ )
1007
+ elif ptype == "bedrock":
1008
+ from tools.llm.embedding_provider import BedrockEmbeddingProvider
1009
+ pcfg = self._config.get("providers", {}).get(provider_name, {})
1010
+ region = _expand_env(pcfg.get("region", "us-gov-west-1"))
1011
+ emb = BedrockEmbeddingProvider(
1012
+ region=region,
1013
+ model_id=mcfg.get("model_id", "amazon.titan-embed-text-v2:0"),
1014
+ dims=mcfg.get("dimensions", 1024),
1015
+ )
1016
+ elif ptype == "gemini":
1017
+ from tools.llm.embedding_provider import GeminiEmbeddingProvider
1018
+ pcfg = self._config.get("providers", {}).get(provider_name, {})
1019
+ api_key = pcfg.get("api_key", "")
1020
+ if not api_key:
1021
+ api_key_env = pcfg.get("api_key_env", "GOOGLE_API_KEY")
1022
+ api_key = os.environ.get(api_key_env, "")
1023
+ emb = GeminiEmbeddingProvider(
1024
+ api_key=api_key,
1025
+ model_id=mcfg.get("model_id", "text-embedding-004"),
1026
+ dims=mcfg.get("dimensions", 768),
1027
+ )
1028
+
1029
+ elif ptype == "azure_openai":
1030
+ from tools.llm.embedding_provider import AzureEmbeddingProvider
1031
+ pcfg = self._config.get("providers", {}).get(provider_name, {})
1032
+ api_key = _expand_env(pcfg.get("api_key", ""))
1033
+ if not api_key:
1034
+ api_key_env = pcfg.get("api_key_env", "AZURE_OPENAI_API_KEY")
1035
+ api_key = os.environ.get(api_key_env, "")
1036
+ endpoint = _expand_env(pcfg.get("endpoint", ""))
1037
+ if not endpoint:
1038
+ endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT", "")
1039
+ api_version = pcfg.get("api_version", "2024-02-01")
1040
+ emb = AzureEmbeddingProvider(
1041
+ api_key=api_key,
1042
+ endpoint=endpoint,
1043
+ api_version=api_version,
1044
+ deployment=mcfg.get("model_id", "text-embedding-ada-002"),
1045
+ )
1046
+
1047
+ elif ptype == "oci_genai":
1048
+ from tools.llm.embedding_provider import OCIEmbeddingProvider
1049
+ pcfg = self._config.get("providers", {}).get(provider_name, {})
1050
+ compartment_id = _expand_env(pcfg.get("compartment_id", ""))
1051
+ if not compartment_id:
1052
+ compartment_id = os.environ.get("OCI_COMPARTMENT_OCID", "")
1053
+ service_endpoint = _expand_env(pcfg.get("service_endpoint", ""))
1054
+ if not service_endpoint:
1055
+ service_endpoint = os.environ.get(
1056
+ "OCI_GENAI_ENDPOINT",
1057
+ "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com",
1058
+ )
1059
+ emb = OCIEmbeddingProvider(
1060
+ compartment_id=compartment_id,
1061
+ model_id=mcfg.get("model_id", "cohere.embed-english-v3.0"),
1062
+ service_endpoint=service_endpoint,
1063
+ )
1064
+
1065
+ elif ptype == "ibm_watsonx":
1066
+ from tools.llm.embedding_provider import IBMWatsonxEmbeddingProvider
1067
+ pcfg = self._config.get("providers", {}).get(provider_name, {})
1068
+ api_key = _expand_env(pcfg.get("api_key", ""))
1069
+ if not api_key:
1070
+ api_key = os.environ.get(
1071
+ pcfg.get("api_key_env", "IBM_CLOUD_API_KEY"), ""
1072
+ )
1073
+ project_id = _expand_env(pcfg.get("project_id", ""))
1074
+ if not project_id:
1075
+ project_id = os.environ.get("IBM_WATSONX_PROJECT_ID", "")
1076
+ url = _expand_env(pcfg.get("url", ""))
1077
+ if not url:
1078
+ url = os.environ.get("IBM_WATSONX_URL",
1079
+ "https://us-south.ml.cloud.ibm.com")
1080
+ emb = IBMWatsonxEmbeddingProvider(
1081
+ api_key=api_key, project_id=project_id, url=url,
1082
+ )
1083
+
1084
+ if emb and emb.check_availability():
1085
+ self._embedding_providers[model_name] = emb
1086
+ logger.info("Embedding provider ready: %s", model_name)
1087
+ return emb
1088
+ except ImportError as exc:
1089
+ logger.debug("Embedding provider '%s' not importable: %s", model_name, exc)
1090
+ except Exception as exc:
1091
+ logger.debug("Embedding provider '%s' failed: %s", model_name, exc)
1092
+
1093
+ raise RuntimeError(
1094
+ "No embedding provider available. Check llm_config.yaml embeddings section."
1095
+ )
1096
+
1097
+ # -------------------------------------------------------------------
1098
+ # Model pricing lookup
1099
+ # -------------------------------------------------------------------
1100
+ def get_model_pricing(self, model_id: str) -> dict:
1101
+ """Look up pricing for a model_id (searches all models)."""
1102
+ for _name, cfg in self._config.get("models", {}).items():
1103
+ if cfg.get("model_id") == model_id:
1104
+ return cfg.get("pricing", {})
1105
+ # Also check embedding models
1106
+ emb_models = self._config.get("embeddings", {}).get("models", {})
1107
+ for _name, cfg in emb_models.items():
1108
+ if cfg.get("model_id") == model_id:
1109
+ return cfg.get("pricing", {})
1110
+ return {}
1111
+
1112
+ def get_all_model_pricing(self) -> Dict[str, dict]:
1113
+ """Get pricing for all configured models. Returns {model_id: pricing}."""
1114
+ result = {}
1115
+ for _name, cfg in self._config.get("models", {}).items():
1116
+ mid = cfg.get("model_id", "")
1117
+ if mid:
1118
+ result[mid] = cfg.get("pricing", {})
1119
+ emb_models = self._config.get("embeddings", {}).get("models", {})
1120
+ for _name, cfg in emb_models.items():
1121
+ mid = cfg.get("model_id", "")
1122
+ if mid:
1123
+ result[mid] = cfg.get("pricing", {})
1124
+ return result