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
@@ -0,0 +1,1836 @@
1
+ #!/usr/bin/env python3
2
+ # CUI // SP-CTI
3
+ """Production Readiness Audit — comprehensive pre-production validation.
4
+
5
+ Runs 38 checks across 7 categories: platform, security, compliance,
6
+ integration, performance, documentation, code_quality. Streams results live and
7
+ produces a consolidated report stored in the production_audits table.
8
+
9
+ Usage:
10
+ python tools/testing/production_audit.py --human --stream
11
+ python tools/testing/production_audit.py --json
12
+ python tools/testing/production_audit.py --category security,compliance --json
13
+ python tools/testing/production_audit.py --gate --json
14
+
15
+ Exit codes: 0 = all blocking checks pass, 1 = at least one blocker failed.
16
+
17
+ Architecture decisions: D291-D295.
18
+ """
19
+
20
+ import argparse
21
+ import ast
22
+ import dataclasses
23
+ import importlib
24
+ import json
25
+ import os
26
+ import re
27
+ import subprocess
28
+ import sys
29
+ import time
30
+ from datetime import datetime, timezone
31
+ from pathlib import Path
32
+ from typing import Callable, Dict, List, Optional, Tuple
33
+ from tools.db.storage import get_connection
34
+ DB_PATH = None # Storage layer handles path resolution (D-DB-20)
35
+
36
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
37
+
38
+ try:
39
+ from tools.compat.db_utils import get_db_connection
40
+ except ImportError:
41
+ get_db_connection = None
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # Data structures
45
+ # ---------------------------------------------------------------------------
46
+
47
+
48
+ @dataclasses.dataclass
49
+ class AuditCheck:
50
+ check_id: str
51
+ check_name: str
52
+ category: str
53
+ status: str # pass, fail, warn, skip
54
+ severity: str # blocking, warning
55
+ message: str
56
+ details: dict
57
+ duration_ms: int = 0
58
+
59
+ def to_dict(self) -> dict:
60
+ return dataclasses.asdict(self)
61
+
62
+
63
+ @dataclasses.dataclass
64
+ class AuditReport:
65
+ overall_pass: bool
66
+ timestamp: str
67
+ categories: dict
68
+ total_checks: int
69
+ passed: int
70
+ failed: int
71
+ warned: int
72
+ skipped: int
73
+ blockers: list
74
+ warnings: list
75
+ duration_total_ms: int
76
+
77
+ def to_dict(self) -> dict:
78
+ return dataclasses.asdict(self)
79
+
80
+
81
+ # ---------------------------------------------------------------------------
82
+ # Helpers
83
+ # ---------------------------------------------------------------------------
84
+
85
+ def _run_subprocess(cmd: list, timeout: int = 120) -> Tuple[int, str, str]:
86
+ """Run a subprocess and return (returncode, stdout, stderr)."""
87
+ try:
88
+ result = subprocess.run(
89
+ cmd, capture_output=True, text=True, timeout=timeout,
90
+ stdin=subprocess.DEVNULL,
91
+ env={**os.environ, "PYTHONDONTWRITEBYTECODE": "1"},
92
+ )
93
+ return result.returncode, result.stdout, result.stderr
94
+ except FileNotFoundError:
95
+ return -1, "", f"Command not found: {cmd[0]}"
96
+ except subprocess.TimeoutExpired:
97
+ return -2, "", f"Command timed out after {timeout}s"
98
+ except Exception as e:
99
+ return -3, "", str(e)
100
+
101
+
102
+ def _timed(fn: Callable, *args, **kwargs) -> Tuple:
103
+ """Run fn and return (result, duration_ms)."""
104
+ start = time.time()
105
+ result = fn(*args, **kwargs)
106
+ elapsed = int((time.time() - start) * 1000)
107
+ return result, elapsed
108
+
109
+
110
+ def check_python_version() -> AuditCheck:
111
+ """PLT-002: Python >= 3.9 required."""
112
+ v = sys.version_info
113
+ ok = v >= (3, 9)
114
+ return AuditCheck(
115
+ check_id="PLT-002", check_name="Python Version",
116
+ category="platform", status="pass" if ok else "fail",
117
+ severity="blocking",
118
+ message=f"Python {v.major}.{v.minor}.{v.micro}" + ("" if ok else " — requires >= 3.9"),
119
+ details={"version": f"{v.major}.{v.minor}.{v.micro}", "required": "3.9"},
120
+ )
121
+
122
+
123
+ def check_stdlib_modules() -> AuditCheck:
124
+ """PLT-003: Required stdlib modules importable."""
125
+ required = ["sqlite3", "pathlib", "json", "hashlib", "argparse", "ast",
126
+ "dataclasses", "subprocess", "re", "uuid", "hmac"]
127
+ missing = []
128
+ for mod in required:
129
+ try:
130
+ importlib.import_module(mod)
131
+ except ImportError:
132
+ missing.append(mod)
133
+ ok = len(missing) == 0
134
+ return AuditCheck(
135
+ check_id="PLT-003", check_name="Required Stdlib Modules",
136
+ category="platform", status="pass" if ok else "fail",
137
+ severity="blocking",
138
+ message=f"All {len(required)} stdlib modules available" if ok else f"Missing: {', '.join(missing)}",
139
+ details={"checked": len(required), "missing": missing},
140
+ )
141
+
142
+
143
+ def check_platform_compat() -> AuditCheck:
144
+ """PLT-001: Run platform_check.py."""
145
+ script = PROJECT_ROOT / "tools" / "testing" / "platform_check.py"
146
+ if not script.exists():
147
+ return AuditCheck(
148
+ check_id="PLT-001", check_name="Platform Compatibility",
149
+ category="platform", status="skip", severity="warning",
150
+ message="platform_check.py not found", details={},
151
+ )
152
+ rc, stdout, stderr = _run_subprocess([sys.executable, str(script), "--json"])
153
+ if rc == 0:
154
+ try:
155
+ data = json.loads(stdout)
156
+ return AuditCheck(
157
+ check_id="PLT-001", check_name="Platform Compatibility",
158
+ category="platform", status="pass", severity="warning",
159
+ message=f"Platform: {data.get('platform', 'unknown')}",
160
+ details=data,
161
+ )
162
+ except json.JSONDecodeError:
163
+ pass
164
+ return AuditCheck(
165
+ check_id="PLT-001", check_name="Platform Compatibility",
166
+ category="platform", status="warn", severity="warning",
167
+ message=f"platform_check returned exit {rc}", details={"stderr": stderr[:500]},
168
+ )
169
+
170
+
171
+ def check_dockerfile_syntax() -> AuditCheck:
172
+ """PLT-004: Parse Dockerfiles for FROM, USER, COPY."""
173
+ docker_dir = PROJECT_ROOT / "docker"
174
+ if not docker_dir.exists():
175
+ return AuditCheck(
176
+ check_id="PLT-004", check_name="Dockerfile Syntax",
177
+ category="platform", status="skip", severity="warning",
178
+ message="docker/ directory not found", details={},
179
+ )
180
+ issues = []
181
+ checked = 0
182
+ for df in sorted(docker_dir.glob("Dockerfile.*")):
183
+ checked += 1
184
+ try:
185
+ content = df.read_text(encoding="utf-8")
186
+ except (OSError, UnicodeDecodeError):
187
+ issues.append(f"{df.name}: unreadable")
188
+ continue
189
+ if "FROM " not in content:
190
+ issues.append(f"{df.name}: missing FROM instruction")
191
+ if "USER " not in content:
192
+ issues.append(f"{df.name}: missing USER (non-root required)")
193
+ ok = len(issues) == 0
194
+ return AuditCheck(
195
+ check_id="PLT-004", check_name="Dockerfile Syntax",
196
+ category="platform", status="pass" if ok else "warn",
197
+ severity="warning",
198
+ message=f"{checked} Dockerfiles checked, {len(issues)} issues" if not ok else f"{checked} Dockerfiles valid",
199
+ details={"checked": checked, "issues": issues},
200
+ )
201
+
202
+
203
+ # ---------------------------------------------------------------------------
204
+ # Category 2: Security (SEC-001..006)
205
+ # ---------------------------------------------------------------------------
206
+
207
+ def check_sast_bandit() -> AuditCheck:
208
+ """SEC-001: SAST scan via bandit."""
209
+ rc, stdout, stderr = _run_subprocess(
210
+ [sys.executable, "-m", "bandit", "-r", str(PROJECT_ROOT / "tools"),
211
+ "-f", "json", "-q", "--severity-level", "medium"],
212
+ timeout=300,
213
+ )
214
+ if rc == -1:
215
+ return AuditCheck(
216
+ check_id="SEC-001", check_name="SAST Scan (Bandit)",
217
+ category="security", status="skip", severity="blocking",
218
+ message="bandit not installed (pip install bandit)", details={},
219
+ )
220
+ try:
221
+ data = json.loads(stdout)
222
+ results = data.get("results", [])
223
+ critical = sum(1 for r in results if r.get("issue_severity") == "HIGH" and r.get("issue_confidence") == "HIGH")
224
+ high = sum(1 for r in results if r.get("issue_severity") == "HIGH")
225
+ medium = sum(1 for r in results if r.get("issue_severity") == "MEDIUM")
226
+ ok = critical == 0
227
+ return AuditCheck(
228
+ check_id="SEC-001", check_name="SAST Scan (Bandit)",
229
+ category="security", status="pass" if ok else "fail",
230
+ severity="blocking",
231
+ message=f"{len(results)} findings (critical={critical}, high={high}, medium={medium})",
232
+ details={"total": len(results), "critical": critical, "high": high, "medium": medium},
233
+ )
234
+ except json.JSONDecodeError:
235
+ return AuditCheck(
236
+ check_id="SEC-001", check_name="SAST Scan (Bandit)",
237
+ category="security", status="warn", severity="blocking",
238
+ message=f"bandit output not parseable (exit {rc})",
239
+ details={"stderr": stderr[:500]},
240
+ )
241
+
242
+
243
+ def check_dependency_audit() -> AuditCheck:
244
+ """SEC-002: Dependency vulnerability audit."""
245
+ rc, stdout, stderr = _run_subprocess(
246
+ [sys.executable, "-m", "pip_audit", "--format", "json", "--progress-spinner=off"],
247
+ timeout=120,
248
+ )
249
+ if rc == -1:
250
+ return AuditCheck(
251
+ check_id="SEC-002", check_name="Dependency Audit",
252
+ category="security", status="skip", severity="blocking",
253
+ message="pip-audit not installed (pip install pip-audit)", details={},
254
+ )
255
+ try:
256
+ data = json.loads(stdout)
257
+ vulns = data if isinstance(data, list) else data.get("dependencies", [])
258
+ vuln_deps = [v for v in vulns if v.get("vulns")]
259
+ critical = sum(1 for v in vuln_deps for vv in v.get("vulns", []) if "CRITICAL" in str(vv).upper())
260
+ high = sum(1 for v in vuln_deps for vv in v.get("vulns", []) if "HIGH" in str(vv).upper())
261
+ ok = critical == 0 and high == 0
262
+ return AuditCheck(
263
+ check_id="SEC-002", check_name="Dependency Audit",
264
+ category="security", status="pass" if ok else ("fail" if critical > 0 else "warn"),
265
+ severity="blocking",
266
+ message=f"{len(vuln_deps)} vulnerable deps (critical={critical}, high={high})",
267
+ details={"vulnerable_count": len(vuln_deps), "critical": critical, "high": high},
268
+ )
269
+ except (json.JSONDecodeError, TypeError):
270
+ ok = rc == 0
271
+ return AuditCheck(
272
+ check_id="SEC-002", check_name="Dependency Audit",
273
+ category="security", status="pass" if ok else "warn",
274
+ severity="blocking",
275
+ message=f"pip-audit exit {rc}" + (" — no vulnerabilities" if ok else ""),
276
+ details={"exit_code": rc, "stderr": stderr[:500]},
277
+ )
278
+
279
+
280
+ def check_secret_detection() -> AuditCheck:
281
+ """SEC-003: Secret detection via detect-secrets.
282
+
283
+ Uses .secrets.baseline if present to filter known false positives.
284
+ Only NEW secrets (not in baseline) trigger a failure.
285
+ """
286
+ baseline_path = PROJECT_ROOT / ".secrets.baseline"
287
+ cmd = [sys.executable, "-m", "detect_secrets", "scan", str(PROJECT_ROOT / "tools")]
288
+ rc, stdout, stderr = _run_subprocess(cmd, timeout=120)
289
+ if rc == -1:
290
+ return AuditCheck(
291
+ check_id="SEC-003", check_name="Secret Detection",
292
+ category="security", status="skip", severity="blocking",
293
+ message="detect-secrets not installed (pip install detect-secrets)", details={},
294
+ )
295
+ try:
296
+ scan_data = json.loads(stdout)
297
+ scan_results = scan_data.get("results", {})
298
+
299
+ # Filter against baseline — only count NEW secrets not in baseline
300
+ baseline_results = {}
301
+ if baseline_path.exists():
302
+ try:
303
+ with open(baseline_path) as f:
304
+ baseline_data = json.loads(f.read())
305
+ baseline_results = baseline_data.get("results", {})
306
+ except (json.JSONDecodeError, OSError):
307
+ pass
308
+
309
+ new_secrets = 0
310
+ new_files = 0
311
+ for fname, entries in scan_results.items():
312
+ baseline_entries = baseline_results.get(fname, [])
313
+ baseline_hashes = {e.get("hashed_secret") for e in baseline_entries}
314
+ new_in_file = [e for e in entries if e.get("hashed_secret") not in baseline_hashes]
315
+ if new_in_file:
316
+ new_secrets += len(new_in_file)
317
+ new_files += 1
318
+
319
+ total_raw = sum(len(v) for v in scan_results.values())
320
+ ok = new_secrets == 0
321
+ baseline_note = f" ({total_raw} baselined)" if baseline_results else ""
322
+ return AuditCheck(
323
+ check_id="SEC-003", check_name="Secret Detection",
324
+ category="security", status="pass" if ok else "fail",
325
+ severity="blocking",
326
+ message=f"No new secrets detected{baseline_note}" if ok
327
+ else f"{new_secrets} NEW secrets in {new_files} files{baseline_note}",
328
+ details={"new_secrets": new_secrets, "new_files": new_files,
329
+ "total_raw": total_raw, "baseline_count": sum(len(v) for v in baseline_results.values())},
330
+ )
331
+ except json.JSONDecodeError:
332
+ return AuditCheck(
333
+ check_id="SEC-003", check_name="Secret Detection",
334
+ category="security", status="warn", severity="blocking",
335
+ message="detect-secrets output not parseable", details={"stderr": stderr[:500]},
336
+ )
337
+
338
+
339
+ def check_prompt_injection_gate() -> AuditCheck:
340
+ """SEC-004: Prompt injection defense active."""
341
+ try:
342
+ sys.path.insert(0, str(PROJECT_ROOT))
343
+ from tools.security.prompt_injection_detector import INJECTION_PATTERNS
344
+ count = len(INJECTION_PATTERNS)
345
+ ok = count >= 10
346
+ return AuditCheck(
347
+ check_id="SEC-004", check_name="Prompt Injection Defense",
348
+ category="security", status="pass" if ok else "warn",
349
+ severity="blocking",
350
+ message=f"{count} injection patterns registered",
351
+ details={"pattern_count": count},
352
+ )
353
+ except ImportError as e:
354
+ return AuditCheck(
355
+ check_id="SEC-004", check_name="Prompt Injection Defense",
356
+ category="security", status="skip", severity="blocking",
357
+ message=f"Import failed: {e}", details={},
358
+ )
359
+
360
+
361
+ def check_owasp_agentic() -> AuditCheck:
362
+ """SEC-005: OWASP Agentic AI security tools present."""
363
+ tools_needed = [
364
+ "tools/security/tool_chain_validator.py",
365
+ "tools/security/agent_output_validator.py",
366
+ "tools/security/agent_trust_scorer.py",
367
+ "tools/security/mcp_tool_authorizer.py",
368
+ ]
369
+ present = [t for t in tools_needed if (PROJECT_ROOT / t).exists()]
370
+ ok = len(present) == len(tools_needed)
371
+ return AuditCheck(
372
+ check_id="SEC-005", check_name="OWASP Agentic Security",
373
+ category="security", status="pass" if ok else "warn",
374
+ severity="warning",
375
+ message=f"{len(present)}/{len(tools_needed)} agentic security tools present",
376
+ details={"present": present, "missing": [t for t in tools_needed if t not in present]},
377
+ )
378
+
379
+
380
+ def check_code_pattern_scan() -> AuditCheck:
381
+ """SEC-006: Dangerous code pattern scan."""
382
+ scanner = PROJECT_ROOT / "tools" / "security" / "code_pattern_scanner.py"
383
+ if not scanner.exists():
384
+ return AuditCheck(
385
+ check_id="SEC-006", check_name="Code Pattern Scan",
386
+ category="security", status="skip", severity="blocking",
387
+ message="code_pattern_scanner.py not found", details={},
388
+ )
389
+ rc, stdout, stderr = _run_subprocess(
390
+ [sys.executable, str(scanner), "--dir", str(PROJECT_ROOT / "tools"), "--json"],
391
+ timeout=120,
392
+ )
393
+ if rc == 0:
394
+ try:
395
+ data = json.loads(stdout)
396
+ critical = data.get("critical", 0)
397
+ high = data.get("high", 0)
398
+ ok = critical == 0
399
+ return AuditCheck(
400
+ check_id="SEC-006", check_name="Code Pattern Scan",
401
+ category="security", status="pass" if ok else "fail",
402
+ severity="blocking",
403
+ message=f"critical={critical}, high={high}",
404
+ details=data,
405
+ )
406
+ except json.JSONDecodeError:
407
+ pass
408
+ return AuditCheck(
409
+ check_id="SEC-006", check_name="Code Pattern Scan",
410
+ category="security", status="warn" if rc == 0 else "fail",
411
+ severity="blocking",
412
+ message=f"Scanner exit {rc}", details={"stderr": stderr[:500]},
413
+ )
414
+
415
+
416
+ # ---------------------------------------------------------------------------
417
+ # Category 3: Compliance (CMP-001..006)
418
+ # ---------------------------------------------------------------------------
419
+
420
+ def check_cui_markings() -> AuditCheck:
421
+ """CMP-001: CUI markings on Python files."""
422
+ tools_dir = PROJECT_ROOT / "tools"
423
+ total = 0
424
+ marked = 0
425
+ for py in tools_dir.rglob("*.py"):
426
+ if py.name.startswith("__"):
427
+ continue
428
+ total += 1
429
+ try:
430
+ head = py.read_text(encoding="utf-8")[:200]
431
+ if "CUI" in head:
432
+ marked += 1
433
+ except (OSError, UnicodeDecodeError):
434
+ pass
435
+ pct = round(marked / total * 100, 1) if total else 0
436
+ ok = pct >= 90
437
+ return AuditCheck(
438
+ check_id="CMP-001", check_name="CUI Marking Coverage",
439
+ category="compliance", status="pass" if ok else "warn",
440
+ severity="warning",
441
+ message=f"{marked}/{total} files marked ({pct}%)",
442
+ details={"total": total, "marked": marked, "pct": pct},
443
+ )
444
+
445
+
446
+ def check_claude_governance() -> AuditCheck:
447
+ """CMP-002: .claude governance validator."""
448
+ script = PROJECT_ROOT / "tools" / "testing" / "claude_dir_validator.py"
449
+ if not script.exists():
450
+ return AuditCheck(
451
+ check_id="CMP-002", check_name="Claude Governance",
452
+ category="compliance", status="skip", severity="blocking",
453
+ message="claude_dir_validator.py not found", details={},
454
+ )
455
+ rc, stdout, stderr = _run_subprocess(
456
+ [sys.executable, str(script), "--json"], timeout=60,
457
+ )
458
+ try:
459
+ data = json.loads(stdout)
460
+ failed = data.get("summary", {}).get("failed", 0)
461
+ warned = data.get("summary", {}).get("warned", 0)
462
+ passed = data.get("summary", {}).get("passed", 0)
463
+ ok = failed == 0
464
+ return AuditCheck(
465
+ check_id="CMP-002", check_name="Claude Governance",
466
+ category="compliance", status="pass" if ok else "fail",
467
+ severity="blocking",
468
+ message=f"{passed} passed, {failed} failed, {warned} warned",
469
+ details={"passed": passed, "failed": failed, "warned": warned},
470
+ )
471
+ except (json.JSONDecodeError, TypeError):
472
+ return AuditCheck(
473
+ check_id="CMP-002", check_name="Claude Governance",
474
+ category="compliance", status="fail" if rc != 0 else "warn",
475
+ severity="blocking",
476
+ message=f"Validator exit {rc}", details={"stderr": stderr[:500]},
477
+ )
478
+
479
+
480
+ def check_append_only_tables() -> AuditCheck:
481
+ """CMP-003: Append-only table coverage in hooks."""
482
+ hook_file = PROJECT_ROOT / ".claude" / "hooks" / "pre_tool_use.py"
483
+ init_file = PROJECT_ROOT / "tools" / "db" / "init_icdev_db.py"
484
+ if not hook_file.exists():
485
+ return AuditCheck(
486
+ check_id="CMP-003", check_name="Append-Only Table Coverage",
487
+ category="compliance", status="skip", severity="blocking",
488
+ message="pre_tool_use.py not found", details={},
489
+ )
490
+ try:
491
+ hook_content = hook_file.read_text(encoding="utf-8")
492
+ # Extract APPEND_ONLY_TABLES list
493
+ match = re.search(r'APPEND_ONLY_TABLES\s*=\s*\[(.*?)\]', hook_content, re.DOTALL)
494
+ if match:
495
+ tables_str = match.group(1)
496
+ protected = re.findall(r'"(\w+)"', tables_str)
497
+ else:
498
+ protected = []
499
+ ok = len(protected) >= 20 # We expect 29+ tables
500
+ return AuditCheck(
501
+ check_id="CMP-003", check_name="Append-Only Table Coverage",
502
+ category="compliance", status="pass" if ok else "warn",
503
+ severity="blocking",
504
+ message=f"{len(protected)} tables protected in hooks",
505
+ details={"count": len(protected), "tables": protected},
506
+ )
507
+ except Exception as e:
508
+ return AuditCheck(
509
+ check_id="CMP-003", check_name="Append-Only Table Coverage",
510
+ category="compliance", status="fail", severity="blocking",
511
+ message=str(e), details={},
512
+ )
513
+
514
+
515
+ def check_security_gates_config() -> AuditCheck:
516
+ """CMP-004: security_gates.yaml parseable and complete."""
517
+ gates_file = PROJECT_ROOT / "args" / "security_gates.yaml"
518
+ if not gates_file.exists():
519
+ return AuditCheck(
520
+ check_id="CMP-004", check_name="Security Gates Config",
521
+ category="compliance", status="fail", severity="warning",
522
+ message="security_gates.yaml not found", details={},
523
+ )
524
+ try:
525
+ import yaml
526
+ data = yaml.safe_load(gates_file.read_text(encoding="utf-8"))
527
+ gate_count = len(data) if isinstance(data, dict) else 0
528
+ expected_gates = ["merge_gates", "deploy_gates", "fedramp", "cmmc"]
529
+ # Accept alternate naming conventions (e.g., deployment_gates for deploy_gates)
530
+ aliases = {"deploy_gates": ["deployment_gates"]}
531
+ keys = set(data.keys()) if data else set()
532
+ present = [
533
+ g for g in expected_gates
534
+ if g in keys or any(a in keys for a in aliases.get(g, []))
535
+ ]
536
+ ok = gate_count >= 5 and len(present) == len(expected_gates)
537
+ return AuditCheck(
538
+ check_id="CMP-004", check_name="Security Gates Config",
539
+ category="compliance", status="pass" if ok else "warn",
540
+ severity="warning",
541
+ message=f"{gate_count} gates defined, {len(present)}/{len(expected_gates)} core gates present",
542
+ details={"gate_count": gate_count, "present": present},
543
+ )
544
+ except ImportError:
545
+ return AuditCheck(
546
+ check_id="CMP-004", check_name="Security Gates Config",
547
+ category="compliance", status="skip", severity="warning",
548
+ message="pyyaml not installed", details={},
549
+ )
550
+ except Exception as e:
551
+ return AuditCheck(
552
+ check_id="CMP-004", check_name="Security Gates Config",
553
+ category="compliance", status="fail", severity="warning",
554
+ message=f"Parse error: {e}", details={},
555
+ )
556
+
557
+
558
+ def check_xai_compliance() -> AuditCheck:
559
+ """CMP-005: XAI compliance assessor available."""
560
+ assessor = PROJECT_ROOT / "tools" / "compliance" / "xai_assessor.py"
561
+ if not assessor.exists():
562
+ return AuditCheck(
563
+ check_id="CMP-005", check_name="XAI Compliance",
564
+ category="compliance", status="skip", severity="warning",
565
+ message="xai_assessor.py not found (Phase 46)", details={},
566
+ )
567
+ try:
568
+ ast.parse(assessor.read_text(encoding="utf-8"))
569
+ return AuditCheck(
570
+ check_id="CMP-005", check_name="XAI Compliance",
571
+ category="compliance", status="pass", severity="warning",
572
+ message="XAI assessor available and syntactically valid",
573
+ details={},
574
+ )
575
+ except SyntaxError as e:
576
+ return AuditCheck(
577
+ check_id="CMP-005", check_name="XAI Compliance",
578
+ category="compliance", status="fail", severity="warning",
579
+ message=f"Syntax error: {e}", details={},
580
+ )
581
+
582
+
583
+ def check_sbom_generation() -> AuditCheck:
584
+ """CMP-006: SBOM generator available."""
585
+ sbom = PROJECT_ROOT / "tools" / "compliance" / "sbom_generator.py"
586
+ if not sbom.exists():
587
+ return AuditCheck(
588
+ check_id="CMP-006", check_name="SBOM Generator",
589
+ category="compliance", status="skip", severity="warning",
590
+ message="sbom_generator.py not found", details={},
591
+ )
592
+ try:
593
+ ast.parse(sbom.read_text(encoding="utf-8"))
594
+ return AuditCheck(
595
+ check_id="CMP-006", check_name="SBOM Generator",
596
+ category="compliance", status="pass", severity="warning",
597
+ message="SBOM generator available", details={},
598
+ )
599
+ except SyntaxError as e:
600
+ return AuditCheck(
601
+ check_id="CMP-006", check_name="SBOM Generator",
602
+ category="compliance", status="fail", severity="warning",
603
+ message=f"Syntax error: {e}", details={},
604
+ )
605
+
606
+
607
+ def check_ai_inventory() -> AuditCheck:
608
+ """AI-001: AI inventory populated (Phase 48)."""
609
+ if False: # Storage layer handles path resolution (D-DB-20)
610
+ return AuditCheck(
611
+ check_id="AI-001", check_name="AI Inventory Populated",
612
+ category="compliance", status="skip", severity="warning",
613
+ message="Database not found", details={},
614
+ )
615
+ try:
616
+ conn = get_connection()
617
+ # Check if table exists
618
+ table_exists = conn.execute(
619
+ "SELECT name FROM sqlite_master WHERE type='table' AND name='ai_use_case_inventory'"
620
+ ).fetchone()
621
+ if not table_exists:
622
+ conn.close()
623
+ return AuditCheck(
624
+ check_id="AI-001", check_name="AI Inventory Populated",
625
+ category="compliance", status="fail", severity="warning",
626
+ message="ai_use_case_inventory table not found — run init_icdev_db.py",
627
+ details={"table_exists": False},
628
+ )
629
+ count = conn.execute("SELECT COUNT(*) FROM ai_use_case_inventory").fetchone()[0]
630
+ conn.close()
631
+ ok = count > 0
632
+ return AuditCheck(
633
+ check_id="AI-001", check_name="AI Inventory Populated",
634
+ category="compliance", status="pass" if ok else "fail",
635
+ severity="warning",
636
+ message=f"{count} AI use cases registered" if ok else "No AI use cases registered — run ai_inventory_manager.py",
637
+ details={"record_count": count},
638
+ )
639
+ except Exception as e:
640
+ return AuditCheck(
641
+ check_id="AI-001", check_name="AI Inventory Populated",
642
+ category="compliance", status="fail", severity="warning",
643
+ message=str(e), details={},
644
+ )
645
+
646
+
647
+ def check_model_cards() -> AuditCheck:
648
+ """AI-002: Model cards generated (Phase 48)."""
649
+ if False: # Storage layer handles path resolution (D-DB-20)
650
+ return AuditCheck(
651
+ check_id="AI-002", check_name="Model Cards Generated",
652
+ category="compliance", status="skip", severity="warning",
653
+ message="Database not found", details={},
654
+ )
655
+ try:
656
+ conn = get_connection()
657
+ table_exists = conn.execute(
658
+ "SELECT name FROM sqlite_master WHERE type='table' AND name='model_cards'"
659
+ ).fetchone()
660
+ if not table_exists:
661
+ conn.close()
662
+ return AuditCheck(
663
+ check_id="AI-002", check_name="Model Cards Generated",
664
+ category="compliance", status="fail", severity="warning",
665
+ message="model_cards table not found — run init_icdev_db.py",
666
+ details={"table_exists": False},
667
+ )
668
+ count = conn.execute("SELECT COUNT(*) FROM model_cards").fetchone()[0]
669
+ conn.close()
670
+ ok = count > 0
671
+ return AuditCheck(
672
+ check_id="AI-002", check_name="Model Cards Generated",
673
+ category="compliance", status="pass" if ok else "fail",
674
+ severity="warning",
675
+ message=f"{count} model cards generated" if ok else "No model cards generated — run model_card_generator.py",
676
+ details={"record_count": count},
677
+ )
678
+ except Exception as e:
679
+ return AuditCheck(
680
+ check_id="AI-002", check_name="Model Cards Generated",
681
+ category="compliance", status="fail", severity="warning",
682
+ message=str(e), details={},
683
+ )
684
+
685
+
686
+ def check_ai_transparency_frameworks() -> AuditCheck:
687
+ """AI-003: AI transparency frameworks assessed (Phase 48)."""
688
+ if False: # Storage layer handles path resolution (D-DB-20)
689
+ return AuditCheck(
690
+ check_id="AI-003", check_name="AI Transparency Frameworks Assessed",
691
+ category="compliance", status="skip", severity="warning",
692
+ message="Database not found", details={},
693
+ )
694
+ assessment_tables = [
695
+ "omb_m25_21_assessments",
696
+ "omb_m26_04_assessments",
697
+ "nist_ai_600_1_assessments",
698
+ "gao_ai_assessments",
699
+ ]
700
+ try:
701
+ conn = get_connection()
702
+ found_tables = []
703
+ total_records = 0
704
+ for tbl in assessment_tables:
705
+ exists = conn.execute(
706
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?", (tbl,)
707
+ ).fetchone()
708
+ if exists:
709
+ cnt = conn.execute(f"SELECT COUNT(*) FROM {tbl}").fetchone()[0]
710
+ if cnt > 0:
711
+ found_tables.append({"table": tbl, "count": cnt})
712
+ total_records += cnt
713
+ conn.close()
714
+ ok = len(found_tables) > 0
715
+ if ok:
716
+ tbl_names = [t["table"] for t in found_tables]
717
+ return AuditCheck(
718
+ check_id="AI-003", check_name="AI Transparency Frameworks Assessed",
719
+ category="compliance", status="pass", severity="warning",
720
+ message=f"{len(found_tables)} framework(s) assessed ({total_records} total records): {', '.join(tbl_names)}",
721
+ details={"assessed_frameworks": found_tables, "total_records": total_records},
722
+ )
723
+ return AuditCheck(
724
+ check_id="AI-003", check_name="AI Transparency Frameworks Assessed",
725
+ category="compliance", status="fail", severity="warning",
726
+ message="No AI transparency framework assessments found — run ai_transparency_audit.py",
727
+ details={"checked_tables": assessment_tables, "assessed_frameworks": []},
728
+ )
729
+ except Exception as e:
730
+ return AuditCheck(
731
+ check_id="AI-003", check_name="AI Transparency Frameworks Assessed",
732
+ category="compliance", status="fail", severity="warning",
733
+ message=str(e), details={},
734
+ )
735
+
736
+
737
+ def check_owasp_asi() -> AuditCheck:
738
+ """SEC-007: OWASP ASI01-ASI10 assessor present and catalog valid (Phase 53, D339)."""
739
+ assessor = PROJECT_ROOT / "tools" / "compliance" / "owasp_asi_assessor.py"
740
+ catalog = PROJECT_ROOT / "context" / "compliance" / "owasp_agentic_asi.json"
741
+ missing = []
742
+ if not assessor.exists():
743
+ missing.append("owasp_asi_assessor.py")
744
+ if not catalog.exists():
745
+ missing.append("owasp_agentic_asi.json")
746
+ if missing:
747
+ return AuditCheck(
748
+ check_id="SEC-007", check_name="OWASP ASI Assessor",
749
+ category="security", status="skip", severity="warning",
750
+ message=f"Missing: {', '.join(missing)}", details={"missing": missing},
751
+ )
752
+ try:
753
+ data = json.loads(catalog.read_text(encoding="utf-8"))
754
+ req_count = len(data.get("requirements", []))
755
+ ok = req_count == 10
756
+ return AuditCheck(
757
+ check_id="SEC-007", check_name="OWASP ASI Assessor",
758
+ category="security", status="pass" if ok else "warn",
759
+ severity="warning",
760
+ message=f"OWASP ASI catalog: {req_count} risks, assessor present",
761
+ details={"requirements": req_count, "assessor": str(assessor)},
762
+ )
763
+ except Exception as e:
764
+ return AuditCheck(
765
+ check_id="SEC-007", check_name="OWASP ASI Assessor",
766
+ category="security", status="fail", severity="warning",
767
+ message=str(e), details={},
768
+ )
769
+
770
+
771
+ def check_endpoint_security() -> AuditCheck:
772
+ """SEC-008: Endpoint security scan — detect routes missing auth/validation."""
773
+ scanner = PROJECT_ROOT / "tools" / "security" / "endpoint_security_scanner.py"
774
+ if not scanner.exists():
775
+ return AuditCheck(
776
+ check_id="SEC-008", check_name="Endpoint Security Scan",
777
+ category="security", status="skip", severity="blocking",
778
+ message="endpoint_security_scanner.py not found", details={},
779
+ )
780
+ rc, stdout, stderr = _run_subprocess(
781
+ [sys.executable, str(scanner), "--dir", str(PROJECT_ROOT / "tools"), "--json"],
782
+ timeout=120,
783
+ )
784
+ if rc == 0:
785
+ try:
786
+ data = json.loads(stdout)
787
+ critical = data.get("critical", 0)
788
+ high = data.get("high", 0)
789
+ ok = critical == 0 and high == 0
790
+ return AuditCheck(
791
+ check_id="SEC-008", check_name="Endpoint Security Scan",
792
+ category="security", status="pass" if ok else "fail",
793
+ severity="blocking",
794
+ message=f"routes={data.get('routes_found', 0)}, critical={critical}, high={high}",
795
+ details=data,
796
+ )
797
+ except json.JSONDecodeError:
798
+ pass
799
+ return AuditCheck(
800
+ check_id="SEC-008", check_name="Endpoint Security Scan",
801
+ category="security", status="warn" if rc == 0 else "fail",
802
+ severity="blocking",
803
+ message=f"Scanner exit {rc}", details={"stderr": stderr[:500]},
804
+ )
805
+
806
+
807
+ def check_fedramp_20x_ksi() -> AuditCheck:
808
+ """CMP-008: FedRAMP 20x KSI generator and schema present (Phase 53, D338)."""
809
+ generator = PROJECT_ROOT / "tools" / "compliance" / "fedramp_ksi_generator.py"
810
+ schema = PROJECT_ROOT / "context" / "compliance" / "fedramp_20x_ksi_schemas.json"
811
+ missing = []
812
+ if not generator.exists():
813
+ missing.append("fedramp_ksi_generator.py")
814
+ if not schema.exists():
815
+ missing.append("fedramp_20x_ksi_schemas.json")
816
+ if missing:
817
+ return AuditCheck(
818
+ check_id="CMP-008", check_name="FedRAMP 20x KSI",
819
+ category="compliance", status="skip", severity="warning",
820
+ message=f"Missing: {', '.join(missing)}", details={"missing": missing},
821
+ )
822
+ try:
823
+ data = json.loads(schema.read_text(encoding="utf-8"))
824
+ ksi_count = sum(len(f.get("ksis", [])) for f in data.get("ksi_families", []))
825
+ families = len(data.get("ksi_families", []))
826
+ return AuditCheck(
827
+ check_id="CMP-008", check_name="FedRAMP 20x KSI",
828
+ category="compliance", status="pass" if ksi_count > 0 else "warn",
829
+ severity="warning",
830
+ message=f"FedRAMP 20x: {ksi_count} KSIs across {families} families",
831
+ details={"ksi_count": ksi_count, "families": families},
832
+ )
833
+ except Exception as e:
834
+ return AuditCheck(
835
+ check_id="CMP-008", check_name="FedRAMP 20x KSI",
836
+ category="compliance", status="fail", severity="warning",
837
+ message=str(e), details={},
838
+ )
839
+
840
+
841
+ def check_slsa_swft() -> AuditCheck:
842
+ """CMP-009: SLSA attestation generator and SWFT evidence bundler present (Phase 54, D341)."""
843
+ slsa = PROJECT_ROOT / "tools" / "compliance" / "slsa_attestation_generator.py"
844
+ swft = PROJECT_ROOT / "tools" / "compliance" / "swft_evidence_bundler.py"
845
+ missing = []
846
+ if not slsa.exists():
847
+ missing.append("slsa_attestation_generator.py")
848
+ if not swft.exists():
849
+ missing.append("swft_evidence_bundler.py")
850
+ if missing:
851
+ return AuditCheck(
852
+ check_id="CMP-009", check_name="SLSA/SWFT",
853
+ category="compliance", status="skip", severity="warning",
854
+ message=f"Missing: {', '.join(missing)}", details={"missing": missing},
855
+ )
856
+ try:
857
+ import py_compile
858
+ for f in [slsa, swft]:
859
+ py_compile.compile(str(f), doraise=True)
860
+ return AuditCheck(
861
+ check_id="CMP-009", check_name="SLSA/SWFT",
862
+ category="compliance", status="pass", severity="warning",
863
+ message="SLSA v1.0 attestation generator and SWFT evidence bundler present",
864
+ details={"slsa": True, "swft": True},
865
+ )
866
+ except Exception as e:
867
+ return AuditCheck(
868
+ check_id="CMP-009", check_name="SLSA/SWFT",
869
+ category="compliance", status="fail", severity="warning",
870
+ message=str(e), details={},
871
+ )
872
+
873
+
874
+ def check_oscal_ecosystem() -> AuditCheck:
875
+ """CMP-007: OSCAL ecosystem tools readiness (D302-D306)."""
876
+ oscal_tools = PROJECT_ROOT / "tools" / "compliance" / "oscal_tools.py"
877
+ catalog_adapter = PROJECT_ROOT / "tools" / "compliance" / "oscal_catalog_adapter.py"
878
+ # Check both files exist
879
+ missing = []
880
+ if not oscal_tools.exists():
881
+ missing.append("oscal_tools.py")
882
+ if not catalog_adapter.exists():
883
+ missing.append("oscal_catalog_adapter.py")
884
+ if missing:
885
+ return AuditCheck(
886
+ check_id="CMP-007", check_name="OSCAL Ecosystem",
887
+ category="compliance", status="skip", severity="warning",
888
+ message=f"Missing: {', '.join(missing)}", details={"missing": missing},
889
+ )
890
+ # Syntax check both files
891
+ syntax_errors = []
892
+ for f in [oscal_tools, catalog_adapter]:
893
+ try:
894
+ ast.parse(f.read_text(encoding="utf-8"))
895
+ except SyntaxError as e:
896
+ syntax_errors.append(f"{f.name}: {e}")
897
+ if syntax_errors:
898
+ return AuditCheck(
899
+ check_id="CMP-007", check_name="OSCAL Ecosystem",
900
+ category="compliance", status="fail", severity="warning",
901
+ message=f"Syntax errors: {'; '.join(syntax_errors)}",
902
+ details={"syntax_errors": syntax_errors},
903
+ )
904
+ # Detect available OSCAL tools
905
+ try:
906
+ sys.path.insert(0, str(PROJECT_ROOT))
907
+ from tools.compliance.oscal_tools import detect_oscal_tools
908
+ detection = detect_oscal_tools()
909
+ available = []
910
+ unavailable = []
911
+ for key in ["oscal_cli", "java", "oscal_pydantic", "nist_catalog"]:
912
+ info = detection.get(key, {})
913
+ if info.get("available", False):
914
+ available.append(key)
915
+ else:
916
+ unavailable.append(key)
917
+ # Pass if core files exist; warn if optional tools not installed
918
+ status = "pass" if len(available) >= 1 else "warn"
919
+ msg_parts = [f"available: {', '.join(available) or 'none'}"]
920
+ if unavailable:
921
+ msg_parts.append(f"not installed: {', '.join(unavailable)}")
922
+ return AuditCheck(
923
+ check_id="CMP-007", check_name="OSCAL Ecosystem",
924
+ category="compliance", status=status, severity="warning",
925
+ message="; ".join(msg_parts),
926
+ details={"available": available, "unavailable": unavailable, "detection": detection},
927
+ )
928
+ except Exception as e:
929
+ return AuditCheck(
930
+ check_id="CMP-007", check_name="OSCAL Ecosystem",
931
+ category="compliance", status="warn", severity="warning",
932
+ message=f"Detection failed: {e}", details={},
933
+ )
934
+
935
+
936
+ # ---------------------------------------------------------------------------
937
+ # Category 4: Integration (INT-001..005)
938
+ # ---------------------------------------------------------------------------
939
+
940
+ def check_mcp_servers() -> AuditCheck:
941
+ """INT-001: Validate all MCP server files parse correctly."""
942
+ mcp_dir = PROJECT_ROOT / "tools" / "mcp"
943
+ if not mcp_dir.exists():
944
+ return AuditCheck(
945
+ check_id="INT-001", check_name="MCP Server Validation",
946
+ category="integration", status="skip", severity="blocking",
947
+ message="tools/mcp/ not found", details={},
948
+ )
949
+ servers = sorted(mcp_dir.glob("*_server.py"))
950
+ errors = []
951
+ for srv in servers:
952
+ try:
953
+ ast.parse(srv.read_text(encoding="utf-8"))
954
+ except SyntaxError as e:
955
+ errors.append(f"{srv.name}: {e}")
956
+ ok = len(errors) == 0
957
+ return AuditCheck(
958
+ check_id="INT-001", check_name="MCP Server Validation",
959
+ category="integration", status="pass" if ok else "fail",
960
+ severity="blocking",
961
+ message=f"{len(servers)} servers validated, {len(errors)} errors",
962
+ details={"total": len(servers), "errors": errors},
963
+ )
964
+
965
+
966
+ def check_db_schema() -> AuditCheck:
967
+ """INT-002: DB schema — expected table count."""
968
+ if False: # Storage layer handles path resolution (D-DB-20)
969
+ return AuditCheck(
970
+ check_id="INT-002", check_name="DB Schema Validation",
971
+ category="integration", status="fail", severity="blocking",
972
+ message=f"Database not found: {DB_PATH}", details={},
973
+ )
974
+ try:
975
+ conn = get_connection()
976
+ tables = conn.execute(
977
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
978
+ ).fetchall()
979
+ conn.close()
980
+ count = len(tables)
981
+ ok = count >= 150 # We expect 176+
982
+ return AuditCheck(
983
+ check_id="INT-002", check_name="DB Schema Validation",
984
+ category="integration", status="pass" if ok else "warn",
985
+ severity="blocking",
986
+ message=f"{count} tables in icdev.db",
987
+ details={"table_count": count},
988
+ )
989
+ except Exception as e:
990
+ return AuditCheck(
991
+ check_id="INT-002", check_name="DB Schema Validation",
992
+ category="integration", status="fail", severity="blocking",
993
+ message=str(e), details={},
994
+ )
995
+
996
+
997
+ def check_cross_imports() -> AuditCheck:
998
+ """INT-003: Validate all tools/**/*.py can be parsed (AST syntax check)."""
999
+ tools_dir = PROJECT_ROOT / "tools"
1000
+ errors = []
1001
+ checked = 0
1002
+ for py in sorted(tools_dir.rglob("*.py")):
1003
+ if py.name.startswith("__"):
1004
+ continue
1005
+ checked += 1
1006
+ try:
1007
+ ast.parse(py.read_text(encoding="utf-8"))
1008
+ except SyntaxError as e:
1009
+ errors.append(f"{py.relative_to(PROJECT_ROOT)}: {e.msg} (line {e.lineno})")
1010
+ ok = len(errors) == 0
1011
+ return AuditCheck(
1012
+ check_id="INT-003", check_name="Cross-Module Syntax Check",
1013
+ category="integration", status="pass" if ok else "fail",
1014
+ severity="warning",
1015
+ message=f"{checked} files parsed, {len(errors)} syntax errors",
1016
+ details={"checked": checked, "errors": errors[:20]},
1017
+ )
1018
+
1019
+
1020
+ def check_dashboard_health() -> AuditCheck:
1021
+ """INT-004: Dashboard page health (requires running dashboard)."""
1022
+ try:
1023
+ import requests
1024
+ except ImportError:
1025
+ return AuditCheck(
1026
+ check_id="INT-004", check_name="Dashboard Page Health",
1027
+ category="integration", status="skip", severity="warning",
1028
+ message="requests not installed", details={},
1029
+ )
1030
+ port = os.environ.get("ICDEV_DASHBOARD_PORT", "5050")
1031
+ base = f"http://localhost:{port}"
1032
+ try:
1033
+ r = requests.get(f"{base}/login", timeout=3)
1034
+ if r.status_code != 200:
1035
+ return AuditCheck(
1036
+ check_id="INT-004", check_name="Dashboard Page Health",
1037
+ category="integration", status="skip", severity="warning",
1038
+ message=f"Dashboard not running on port {port}",
1039
+ details={},
1040
+ )
1041
+ except Exception:
1042
+ return AuditCheck(
1043
+ check_id="INT-004", check_name="Dashboard Page Health",
1044
+ category="integration", status="skip", severity="warning",
1045
+ message=f"Dashboard not reachable on port {port}", details={},
1046
+ )
1047
+ # Dashboard is running — test pages
1048
+ session = requests.Session()
1049
+ # Login with env-var API key (matches before_request auth in app.py)
1050
+ dashboard_key = os.environ.get("SPARKPILOT_DASHBOARD_KEY", "sparkpilot")
1051
+ try:
1052
+ session.post(f"{base}/login", data={"api_key": dashboard_key}, allow_redirects=False)
1053
+ except Exception:
1054
+ pass # Continue without auth
1055
+
1056
+ # SparkPilot dashboard routes
1057
+ pages = ["/", "/missions", "/devices", "/simulator", "/firmware",
1058
+ "/edge-ai", "/crashes", "/agents", "/govcon", "/writeguard",
1059
+ "/databridge", "/health"]
1060
+ ok_count = 0
1061
+ fail_pages = []
1062
+ for page in pages:
1063
+ try:
1064
+ r = session.get(f"{base}{page}", timeout=5)
1065
+ if r.status_code == 200 and ("container" in r.text or "sparkpilot" in r.text.lower()):
1066
+ ok_count += 1
1067
+ else:
1068
+ fail_pages.append(f"{page} (status={r.status_code})")
1069
+ except Exception as e:
1070
+ fail_pages.append(f"{page} ({e})")
1071
+ ok = len(fail_pages) == 0
1072
+ return AuditCheck(
1073
+ check_id="INT-004", check_name="Dashboard Page Health",
1074
+ category="integration", status="pass" if ok else "warn",
1075
+ severity="warning",
1076
+ message=f"{ok_count}/{len(pages)} pages OK" + (f", failed: {', '.join(fail_pages[:5])}" if fail_pages else ""),
1077
+ details={"total": len(pages), "passed": ok_count, "failed": fail_pages},
1078
+ )
1079
+
1080
+
1081
+ def check_api_gateway() -> AuditCheck:
1082
+ """INT-005: API gateway Flask app importable."""
1083
+ try:
1084
+ sys.path.insert(0, str(PROJECT_ROOT))
1085
+ spec = importlib.util.spec_from_file_location(
1086
+ "api_gateway", str(PROJECT_ROOT / "tools" / "saas" / "api_gateway.py")
1087
+ )
1088
+ if spec and spec.loader:
1089
+ return AuditCheck(
1090
+ check_id="INT-005", check_name="API Gateway",
1091
+ category="integration", status="pass", severity="warning",
1092
+ message="API gateway module found", details={},
1093
+ )
1094
+ except Exception as e:
1095
+ return AuditCheck(
1096
+ check_id="INT-005", check_name="API Gateway",
1097
+ category="integration", status="warn", severity="warning",
1098
+ message=f"Import check: {e}", details={},
1099
+ )
1100
+ return AuditCheck(
1101
+ check_id="INT-005", check_name="API Gateway",
1102
+ category="integration", status="skip", severity="warning",
1103
+ message="api_gateway.py not found", details={},
1104
+ )
1105
+
1106
+
1107
+ # ---------------------------------------------------------------------------
1108
+ # Category 5: Performance / Resilience (PRF-001..004)
1109
+ # ---------------------------------------------------------------------------
1110
+
1111
+ def check_migration_status() -> AuditCheck:
1112
+ """PRF-001: DB migration status."""
1113
+ migrate = PROJECT_ROOT / "tools" / "db" / "migrate.py"
1114
+ if not migrate.exists():
1115
+ return AuditCheck(
1116
+ check_id="PRF-001", check_name="DB Migration Status",
1117
+ category="performance", status="skip", severity="warning",
1118
+ message="migrate.py not found", details={},
1119
+ )
1120
+ rc, stdout, stderr = _run_subprocess(
1121
+ [sys.executable, str(migrate), "--status", "--json"], timeout=30,
1122
+ )
1123
+ if rc == 0:
1124
+ try:
1125
+ data = json.loads(stdout)
1126
+ pending = data.get("pending_count", data.get("pending", 0))
1127
+ if isinstance(pending, list):
1128
+ pending = len(pending)
1129
+ ok = pending == 0
1130
+ return AuditCheck(
1131
+ check_id="PRF-001", check_name="DB Migration Status",
1132
+ category="performance", status="pass" if ok else "warn",
1133
+ severity="warning",
1134
+ message=f"{pending} pending migrations" if pending else "All migrations applied",
1135
+ details=data,
1136
+ )
1137
+ except json.JSONDecodeError:
1138
+ pass
1139
+ return AuditCheck(
1140
+ check_id="PRF-001", check_name="DB Migration Status",
1141
+ category="performance", status="warn", severity="warning",
1142
+ message=f"migrate.py exit {rc}", details={"stderr": stderr[:300]},
1143
+ )
1144
+
1145
+
1146
+ def check_backup_config() -> AuditCheck:
1147
+ """PRF-002: DB backup config exists."""
1148
+ config = PROJECT_ROOT / "args" / "db_config.yaml"
1149
+ if not config.exists():
1150
+ return AuditCheck(
1151
+ check_id="PRF-002", check_name="DB Backup Config",
1152
+ category="performance", status="warn", severity="warning",
1153
+ message="args/db_config.yaml not found", details={},
1154
+ )
1155
+ try:
1156
+ content = config.read_text(encoding="utf-8")
1157
+ has_backup = "backup" in content.lower()
1158
+ return AuditCheck(
1159
+ check_id="PRF-002", check_name="DB Backup Config",
1160
+ category="performance", status="pass" if has_backup else "warn",
1161
+ severity="warning",
1162
+ message="Backup configuration present" if has_backup else "No backup section found",
1163
+ details={"has_backup_section": has_backup},
1164
+ )
1165
+ except Exception as e:
1166
+ return AuditCheck(
1167
+ check_id="PRF-002", check_name="DB Backup Config",
1168
+ category="performance", status="warn", severity="warning",
1169
+ message=str(e), details={},
1170
+ )
1171
+
1172
+
1173
+ def check_resilience_config() -> AuditCheck:
1174
+ """PRF-003: Circuit breaker / resilience config."""
1175
+ config = PROJECT_ROOT / "args" / "resilience_config.yaml"
1176
+ if not config.exists():
1177
+ return AuditCheck(
1178
+ check_id="PRF-003", check_name="Resilience Config",
1179
+ category="performance", status="warn", severity="warning",
1180
+ message="args/resilience_config.yaml not found", details={},
1181
+ )
1182
+ try:
1183
+ import yaml
1184
+ data = yaml.safe_load(config.read_text(encoding="utf-8"))
1185
+ has_cb = "circuit_breaker" in str(data).lower() if data else False
1186
+ has_retry = "retry" in str(data).lower() if data else False
1187
+ ok = has_cb and has_retry
1188
+ return AuditCheck(
1189
+ check_id="PRF-003", check_name="Resilience Config",
1190
+ category="performance", status="pass" if ok else "warn",
1191
+ severity="warning",
1192
+ message=f"circuit_breaker={'yes' if has_cb else 'no'}, retry={'yes' if has_retry else 'no'}",
1193
+ details={"circuit_breaker": has_cb, "retry": has_retry},
1194
+ )
1195
+ except ImportError:
1196
+ return AuditCheck(
1197
+ check_id="PRF-003", check_name="Resilience Config",
1198
+ category="performance", status="skip", severity="warning",
1199
+ message="pyyaml not installed", details={},
1200
+ )
1201
+
1202
+
1203
+ def check_test_collection() -> AuditCheck:
1204
+ """PRF-004: pytest collection (no import errors)."""
1205
+ rc, stdout, stderr = _run_subprocess(
1206
+ [sys.executable, "-m", "pytest", str(PROJECT_ROOT / "tests"), "--co", "-q"],
1207
+ timeout=120,
1208
+ )
1209
+ if rc == -1:
1210
+ return AuditCheck(
1211
+ check_id="PRF-004", check_name="Test Collection",
1212
+ category="performance", status="skip", severity="blocking",
1213
+ message="pytest not installed", details={},
1214
+ )
1215
+ # Parse "N tests collected"
1216
+ match = re.search(r"(\d+)\s+test", stdout)
1217
+ count = int(match.group(1)) if match else 0
1218
+ ok = rc == 0 and count > 0
1219
+ return AuditCheck(
1220
+ check_id="PRF-004", check_name="Test Collection",
1221
+ category="performance", status="pass" if ok else "fail",
1222
+ severity="blocking",
1223
+ message=f"{count} tests collected" if ok else f"Collection failed (exit {rc})",
1224
+ details={"test_count": count, "exit_code": rc},
1225
+ )
1226
+
1227
+
1228
+ # ---------------------------------------------------------------------------
1229
+ # Category 7: Code Quality Intelligence (CODE-001..005) — Phase 52
1230
+ # ---------------------------------------------------------------------------
1231
+
1232
+ def check_code_analyzer_syntax() -> AuditCheck:
1233
+ """CODE-001: Code analyzer tool syntax check."""
1234
+ try:
1235
+ mod_path = PROJECT_ROOT / "tools" / "analysis" / "code_analyzer.py"
1236
+ if not mod_path.exists():
1237
+ return AuditCheck(
1238
+ check_id="CODE-001", check_name="Code Analyzer Syntax",
1239
+ category="code_quality", status="skip", severity="warning",
1240
+ message="code_analyzer.py not found", details={},
1241
+ )
1242
+ with open(mod_path, "r", encoding="utf-8") as f:
1243
+ source = f.read()
1244
+ ast.parse(source)
1245
+ return AuditCheck(
1246
+ check_id="CODE-001", check_name="Code Analyzer Syntax",
1247
+ category="code_quality", status="pass", severity="warning",
1248
+ message="code_analyzer.py parses without errors",
1249
+ details={"file": str(mod_path)},
1250
+ )
1251
+ except SyntaxError as e:
1252
+ return AuditCheck(
1253
+ check_id="CODE-001", check_name="Code Analyzer Syntax",
1254
+ category="code_quality", status="fail", severity="warning",
1255
+ message=f"Syntax error: {e}",
1256
+ details={"error": str(e)},
1257
+ )
1258
+
1259
+
1260
+ def check_avg_complexity() -> AuditCheck:
1261
+ """CODE-002: Average cyclomatic complexity (blocking at >25, warn >10)."""
1262
+ try:
1263
+ sys.path.insert(0, str(PROJECT_ROOT))
1264
+ from tools.analysis.code_analyzer import CodeAnalyzer
1265
+ analyzer = CodeAnalyzer(project_dir=str(PROJECT_ROOT / "tools"))
1266
+ result = analyzer.scan_directory()
1267
+ metrics = result.get("metrics", [])
1268
+ fn_metrics = [m for m in metrics if m.get("function_name")]
1269
+ if not fn_metrics:
1270
+ return AuditCheck(
1271
+ check_id="CODE-002", check_name="Avg Cyclomatic Complexity",
1272
+ category="code_quality", status="skip", severity="blocking",
1273
+ message="No function metrics collected", details={},
1274
+ )
1275
+ avg_cc = sum(m.get("cyclomatic_complexity", 0) for m in fn_metrics) / len(fn_metrics)
1276
+ avg_cc = round(avg_cc, 2)
1277
+ if avg_cc > 25:
1278
+ status = "fail"
1279
+ elif avg_cc > 10:
1280
+ status = "warn"
1281
+ else:
1282
+ status = "pass"
1283
+ return AuditCheck(
1284
+ check_id="CODE-002", check_name="Avg Cyclomatic Complexity",
1285
+ category="code_quality", status=status, severity="blocking",
1286
+ message=f"Avg CC={avg_cc} across {len(fn_metrics)} functions",
1287
+ details={"avg_complexity": avg_cc, "function_count": len(fn_metrics)},
1288
+ )
1289
+ except Exception as e:
1290
+ return AuditCheck(
1291
+ check_id="CODE-002", check_name="Avg Cyclomatic Complexity",
1292
+ category="code_quality", status="skip", severity="blocking",
1293
+ message=f"Analysis failed: {e}", details={"error": str(e)},
1294
+ )
1295
+
1296
+
1297
+ def check_high_complexity_pct() -> AuditCheck:
1298
+ """CODE-003: High-complexity function count (warn if >7% have CC>15).
1299
+
1300
+ Threshold set at 7% to account for compliance assessors (CMMC, FedRAMP,
1301
+ ATLAS, OWASP) which contain regulatory dispatch tables with inherently
1302
+ high cyclomatic complexity. The blocking CODE-002 gate (avg CC>25)
1303
+ remains unchanged.
1304
+ """
1305
+ try:
1306
+ sys.path.insert(0, str(PROJECT_ROOT))
1307
+ from tools.analysis.code_analyzer import CodeAnalyzer
1308
+ analyzer = CodeAnalyzer(project_dir=str(PROJECT_ROOT / "tools"))
1309
+ result = analyzer.scan_directory()
1310
+ metrics = result.get("metrics", [])
1311
+ fn_metrics = [m for m in metrics if m.get("function_name")]
1312
+ if not fn_metrics:
1313
+ return AuditCheck(
1314
+ check_id="CODE-003", check_name="High Complexity Functions",
1315
+ category="code_quality", status="skip", severity="warning",
1316
+ message="No function metrics collected", details={},
1317
+ )
1318
+ high_cc = [m for m in fn_metrics if m.get("cyclomatic_complexity", 0) > 15]
1319
+ pct = round(len(high_cc) / len(fn_metrics) * 100, 2)
1320
+ return AuditCheck(
1321
+ check_id="CODE-003", check_name="High Complexity Functions",
1322
+ category="code_quality", status="warn" if pct > 7.0 else "pass",
1323
+ severity="warning",
1324
+ message=f"{len(high_cc)}/{len(fn_metrics)} functions ({pct}%) have CC>15",
1325
+ details={"high_cc_count": len(high_cc), "total": len(fn_metrics), "pct": pct},
1326
+ )
1327
+ except Exception as e:
1328
+ return AuditCheck(
1329
+ check_id="CODE-003", check_name="High Complexity Functions",
1330
+ category="code_quality", status="skip", severity="warning",
1331
+ message=f"Analysis failed: {e}", details={"error": str(e)},
1332
+ )
1333
+
1334
+
1335
+ def check_smell_density() -> AuditCheck:
1336
+ """CODE-004: Smell density per KLOC (warn >20, fail >30).
1337
+
1338
+ Threshold calibrated for compliance-heavy codebases where regulatory
1339
+ dispatch functions and multi-framework assessors inflate smell counts.
1340
+ """
1341
+ try:
1342
+ sys.path.insert(0, str(PROJECT_ROOT))
1343
+ from tools.analysis.code_analyzer import CodeAnalyzer
1344
+ analyzer = CodeAnalyzer(project_dir=str(PROJECT_ROOT / "tools"))
1345
+ result = analyzer.scan_directory()
1346
+ metrics = result.get("metrics", [])
1347
+ total_loc = sum(m.get("loc", 0) for m in metrics)
1348
+ total_smells = sum(m.get("smell_count", 0) for m in metrics)
1349
+ kloc = max(total_loc / 1000.0, 0.001)
1350
+ density = round(total_smells / kloc, 2)
1351
+ if density > 30.0:
1352
+ status = "fail"
1353
+ elif density > 20.0:
1354
+ status = "warn"
1355
+ else:
1356
+ status = "pass"
1357
+ return AuditCheck(
1358
+ check_id="CODE-004", check_name="Smell Density",
1359
+ category="code_quality", status=status, severity="warning",
1360
+ message=f"{total_smells} smells / {round(kloc, 1)} KLOC = {density} per KLOC",
1361
+ details={"total_smells": total_smells, "total_loc": total_loc, "density_per_kloc": density},
1362
+ )
1363
+ except Exception as e:
1364
+ return AuditCheck(
1365
+ check_id="CODE-004", check_name="Smell Density",
1366
+ category="code_quality", status="skip", severity="warning",
1367
+ message=f"Analysis failed: {e}", details={"error": str(e)},
1368
+ )
1369
+
1370
+
1371
+ def check_maintainability_trend() -> AuditCheck:
1372
+ """CODE-005: Maintainability trend (warn if declining)."""
1373
+ try:
1374
+ sys.path.insert(0, str(PROJECT_ROOT))
1375
+ from tools.analysis.code_analyzer import CodeAnalyzer
1376
+ analyzer = CodeAnalyzer(
1377
+ project_dir=str(PROJECT_ROOT / "tools"),
1378
+ project_id="sparkpilot",
1379
+ db_path=DB_PATH,
1380
+ )
1381
+ trend = analyzer.get_trend("sparkpilot", db_path=DB_PATH)
1382
+ if len(trend) < 2:
1383
+ return AuditCheck(
1384
+ check_id="CODE-005", check_name="Maintainability Trend",
1385
+ category="code_quality", status="skip", severity="warning",
1386
+ message=f"Need >=2 scans for trend (have {len(trend)})",
1387
+ details={"scan_count": len(trend)},
1388
+ )
1389
+ latest = trend[-1].get("avg_maintainability", 0)
1390
+ previous = trend[-2].get("avg_maintainability", 0)
1391
+ declining = latest < previous - 0.05
1392
+ return AuditCheck(
1393
+ check_id="CODE-005", check_name="Maintainability Trend",
1394
+ category="code_quality", status="warn" if declining else "pass",
1395
+ severity="warning",
1396
+ message=f"Latest={round(latest, 3)}, Previous={round(previous, 3)}" + (" (declining)" if declining else ""),
1397
+ details={"latest": latest, "previous": previous, "declining": declining},
1398
+ )
1399
+ except Exception as e:
1400
+ return AuditCheck(
1401
+ check_id="CODE-005", check_name="Maintainability Trend",
1402
+ category="code_quality", status="skip", severity="warning",
1403
+ message=f"Trend unavailable: {e}", details={"error": str(e)},
1404
+ )
1405
+
1406
+
1407
+ # ---------------------------------------------------------------------------
1408
+ # Category 8: Documentation Alignment (DOC-001..005)
1409
+ # ---------------------------------------------------------------------------
1410
+
1411
+ def check_claude_md_table_count() -> AuditCheck:
1412
+ """DOC-001: CLAUDE.md table count accuracy."""
1413
+ claude_md = PROJECT_ROOT / "CLAUDE.md"
1414
+ if not claude_md.exists():
1415
+ return AuditCheck(
1416
+ check_id="DOC-001", check_name="CLAUDE.md Table Count",
1417
+ category="documentation", status="skip", severity="warning",
1418
+ message="CLAUDE.md not found", details={},
1419
+ )
1420
+ try:
1421
+ content = claude_md.read_text(encoding="utf-8")
1422
+ # Find claimed table count (e.g. "176 tables")
1423
+ match = re.search(r"(\d+)\s+tables", content)
1424
+ claimed = int(match.group(1)) if match else 0
1425
+ # Get actual count
1426
+ if True: # Storage layer handles path resolution (D-DB-20)
1427
+ conn = get_connection()
1428
+ actual = len(conn.execute(
1429
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1430
+ ).fetchall())
1431
+ conn.close()
1432
+ else:
1433
+ actual = 0
1434
+ drift = abs(claimed - actual)
1435
+ ok = drift <= 5
1436
+ return AuditCheck(
1437
+ check_id="DOC-001", check_name="CLAUDE.md Table Count",
1438
+ category="documentation", status="pass" if ok else "warn",
1439
+ severity="warning",
1440
+ message=f"Claimed {claimed}, actual {actual} (drift={drift})",
1441
+ details={"claimed": claimed, "actual": actual, "drift": drift},
1442
+ )
1443
+ except Exception as e:
1444
+ return AuditCheck(
1445
+ check_id="DOC-001", check_name="CLAUDE.md Table Count",
1446
+ category="documentation", status="warn", severity="warning",
1447
+ message=str(e), details={},
1448
+ )
1449
+
1450
+
1451
+ def check_tools_manifest() -> AuditCheck:
1452
+ """DOC-002: tools/manifest.md completeness."""
1453
+ manifest = PROJECT_ROOT / "tools" / "manifest.md"
1454
+ if not manifest.exists():
1455
+ return AuditCheck(
1456
+ check_id="DOC-002", check_name="Tools Manifest",
1457
+ category="documentation", status="warn", severity="warning",
1458
+ message="tools/manifest.md not found", details={},
1459
+ )
1460
+ try:
1461
+ content = manifest.read_text(encoding="utf-8")
1462
+ # Count tools mentioned in manifest
1463
+ listed = set(re.findall(r'(\w+\.py)', content))
1464
+ # Count actual tool files
1465
+ actual = set()
1466
+ for py in (PROJECT_ROOT / "tools").rglob("*.py"):
1467
+ if not py.name.startswith("__"):
1468
+ actual.add(py.name)
1469
+ missing = actual - listed
1470
+ pct = round(len(listed & actual) / max(len(actual), 1) * 100, 1)
1471
+ ok = pct >= 70
1472
+ return AuditCheck(
1473
+ check_id="DOC-002", check_name="Tools Manifest",
1474
+ category="documentation", status="pass" if ok else "warn",
1475
+ severity="warning",
1476
+ message=f"{len(listed & actual)}/{len(actual)} tools documented ({pct}%)",
1477
+ details={"documented": len(listed & actual), "total": len(actual),
1478
+ "pct": pct, "missing_sample": sorted(missing)[:10]},
1479
+ )
1480
+ except Exception as e:
1481
+ return AuditCheck(
1482
+ check_id="DOC-002", check_name="Tools Manifest",
1483
+ category="documentation", status="warn", severity="warning",
1484
+ message=str(e), details={},
1485
+ )
1486
+
1487
+
1488
+ def check_goals_manifest() -> AuditCheck:
1489
+ """DOC-003: goals/manifest.md completeness."""
1490
+ manifest = PROJECT_ROOT / "goals" / "manifest.md"
1491
+ goals_dir = PROJECT_ROOT / "goals"
1492
+ if not manifest.exists():
1493
+ return AuditCheck(
1494
+ check_id="DOC-003", check_name="Goals Manifest",
1495
+ category="documentation", status="warn", severity="warning",
1496
+ message="goals/manifest.md not found", details={},
1497
+ )
1498
+ try:
1499
+ content = manifest.read_text(encoding="utf-8")
1500
+ listed = set(re.findall(r'(\w+\.md)', content))
1501
+ actual = {f.name for f in goals_dir.glob("*.md") if f.name != "manifest.md"}
1502
+ missing = actual - listed
1503
+ pct = round(len(listed & actual) / max(len(actual), 1) * 100, 1)
1504
+ ok = pct >= 80
1505
+ return AuditCheck(
1506
+ check_id="DOC-003", check_name="Goals Manifest",
1507
+ category="documentation", status="pass" if ok else "warn",
1508
+ severity="warning",
1509
+ message=f"{len(listed & actual)}/{len(actual)} goals documented ({pct}%)",
1510
+ details={"documented": len(listed & actual), "total": len(actual),
1511
+ "pct": pct, "missing": sorted(missing)[:10]},
1512
+ )
1513
+ except Exception as e:
1514
+ return AuditCheck(
1515
+ check_id="DOC-003", check_name="Goals Manifest",
1516
+ category="documentation", status="warn", severity="warning",
1517
+ message=str(e), details={},
1518
+ )
1519
+
1520
+
1521
+ def check_route_documentation() -> AuditCheck:
1522
+ """DOC-004: Dashboard routes documented in start.md."""
1523
+ start_md = PROJECT_ROOT / ".claude" / "commands" / "start.md"
1524
+ if not start_md.exists():
1525
+ return AuditCheck(
1526
+ check_id="DOC-004", check_name="Route Documentation",
1527
+ category="documentation", status="skip", severity="warning",
1528
+ message="start.md not found", details={},
1529
+ )
1530
+ try:
1531
+ content = start_md.read_text(encoding="utf-8")
1532
+ # Count documented routes
1533
+ routes = re.findall(r'`(/\w[^`]*)`', content)
1534
+ ok = len(routes) >= 20
1535
+ return AuditCheck(
1536
+ check_id="DOC-004", check_name="Route Documentation",
1537
+ category="documentation", status="pass" if ok else "warn",
1538
+ severity="warning",
1539
+ message=f"{len(routes)} routes documented in start.md",
1540
+ details={"route_count": len(routes)},
1541
+ )
1542
+ except Exception as e:
1543
+ return AuditCheck(
1544
+ check_id="DOC-004", check_name="Route Documentation",
1545
+ category="documentation", status="warn", severity="warning",
1546
+ message=str(e), details={},
1547
+ )
1548
+
1549
+
1550
+ def check_skill_count() -> AuditCheck:
1551
+ """DOC-005: Skill/command count accuracy."""
1552
+ commands_dir = PROJECT_ROOT / ".claude" / "commands"
1553
+ if not commands_dir.exists():
1554
+ return AuditCheck(
1555
+ check_id="DOC-005", check_name="Skill Count",
1556
+ category="documentation", status="skip", severity="warning",
1557
+ message=".claude/commands/ not found", details={},
1558
+ )
1559
+ skills = list(commands_dir.glob("*.md"))
1560
+ # Exclude e2e subdir
1561
+ e2e_skills = list((commands_dir / "e2e").glob("*.md")) if (commands_dir / "e2e").exists() else []
1562
+ total = len(skills) + len(e2e_skills)
1563
+ return AuditCheck(
1564
+ check_id="DOC-005", check_name="Skill Count",
1565
+ category="documentation", status="pass" if total >= 20 else "warn",
1566
+ severity="warning",
1567
+ message=f"{len(skills)} skills + {len(e2e_skills)} E2E specs = {total} total",
1568
+ details={"skills": len(skills), "e2e_specs": len(e2e_skills), "total": total},
1569
+ )
1570
+
1571
+
1572
+ # ---------------------------------------------------------------------------
1573
+ # Check Registry
1574
+ # ---------------------------------------------------------------------------
1575
+
1576
+ # Maps check_id -> (function, category, severity)
1577
+ # Order within each category determines execution order
1578
+ CHECK_REGISTRY: Dict[str, Tuple[Callable, str, str]] = {
1579
+ # Platform
1580
+ "PLT-001": (check_platform_compat, "platform", "warning"),
1581
+ "PLT-002": (check_python_version, "platform", "blocking"),
1582
+ "PLT-003": (check_stdlib_modules, "platform", "blocking"),
1583
+ "PLT-004": (check_dockerfile_syntax, "platform", "warning"),
1584
+ # Security
1585
+ "SEC-001": (check_sast_bandit, "security", "blocking"),
1586
+ "SEC-002": (check_dependency_audit, "security", "blocking"),
1587
+ "SEC-003": (check_secret_detection, "security", "blocking"),
1588
+ "SEC-004": (check_prompt_injection_gate, "security", "blocking"),
1589
+ "SEC-005": (check_owasp_agentic, "security", "warning"),
1590
+ "SEC-006": (check_code_pattern_scan, "security", "blocking"),
1591
+ "SEC-007": (check_owasp_asi, "security", "warning"),
1592
+ "SEC-008": (check_endpoint_security, "security", "blocking"),
1593
+ # Compliance
1594
+ "CMP-001": (check_cui_markings, "compliance", "warning"),
1595
+ "CMP-002": (check_claude_governance, "compliance", "blocking"),
1596
+ "CMP-003": (check_append_only_tables, "compliance", "blocking"),
1597
+ "CMP-004": (check_security_gates_config, "compliance", "warning"),
1598
+ "CMP-005": (check_xai_compliance, "compliance", "warning"),
1599
+ "CMP-006": (check_sbom_generation, "compliance", "warning"),
1600
+ "CMP-007": (check_oscal_ecosystem, "compliance", "warning"),
1601
+ "CMP-008": (check_fedramp_20x_ksi, "compliance", "warning"),
1602
+ "CMP-009": (check_slsa_swft, "compliance", "warning"),
1603
+ # AI Transparency (Phase 48)
1604
+ "AI-001": (check_ai_inventory, "compliance", "warning"),
1605
+ "AI-002": (check_model_cards, "compliance", "warning"),
1606
+ "AI-003": (check_ai_transparency_frameworks, "compliance", "warning"),
1607
+ # Integration
1608
+ "INT-001": (check_mcp_servers, "integration", "blocking"),
1609
+ "INT-002": (check_db_schema, "integration", "blocking"),
1610
+ "INT-003": (check_cross_imports, "integration", "warning"),
1611
+ "INT-004": (check_dashboard_health, "integration", "warning"),
1612
+ "INT-005": (check_api_gateway, "integration", "warning"),
1613
+ # Performance
1614
+ "PRF-001": (check_migration_status, "performance", "warning"),
1615
+ "PRF-002": (check_backup_config, "performance", "warning"),
1616
+ "PRF-003": (check_resilience_config, "performance", "warning"),
1617
+ "PRF-004": (check_test_collection, "performance", "blocking"),
1618
+ # Documentation
1619
+ "DOC-001": (check_claude_md_table_count, "documentation", "warning"),
1620
+ "DOC-002": (check_tools_manifest, "documentation", "warning"),
1621
+ "DOC-003": (check_goals_manifest, "documentation", "warning"),
1622
+ "DOC-004": (check_route_documentation, "documentation", "warning"),
1623
+ "DOC-005": (check_skill_count, "documentation", "warning"),
1624
+ # Code Quality (Phase 52)
1625
+ "CODE-001": (check_code_analyzer_syntax, "code_quality", "warning"),
1626
+ "CODE-002": (check_avg_complexity, "code_quality", "blocking"),
1627
+ "CODE-003": (check_high_complexity_pct, "code_quality", "warning"),
1628
+ "CODE-004": (check_smell_density, "code_quality", "warning"),
1629
+ "CODE-005": (check_maintainability_trend, "code_quality", "warning"),
1630
+ }
1631
+
1632
+ # Execution order of categories
1633
+ CATEGORY_ORDER = ["platform", "security", "compliance", "integration", "performance", "documentation", "code_quality"]
1634
+
1635
+ ALL_CATEGORIES = set(CATEGORY_ORDER)
1636
+
1637
+
1638
+ # ---------------------------------------------------------------------------
1639
+ # Runner
1640
+ # ---------------------------------------------------------------------------
1641
+
1642
+ def run_audit(
1643
+ categories: Optional[List[str]] = None,
1644
+ stream: bool = False,
1645
+ ) -> AuditReport:
1646
+ """Run the production readiness audit.
1647
+
1648
+ Args:
1649
+ categories: Optional list of categories to run. None = all.
1650
+ stream: If True, print results as each check completes.
1651
+
1652
+ Returns:
1653
+ AuditReport with all results.
1654
+ """
1655
+ if categories is None:
1656
+ categories = CATEGORY_ORDER
1657
+ else:
1658
+ categories = [c for c in CATEGORY_ORDER if c in categories]
1659
+
1660
+ checks: List[AuditCheck] = []
1661
+ start_time = time.time()
1662
+
1663
+ for cat in categories:
1664
+ if stream:
1665
+ print(f"\n{'='*60}", file=sys.stderr)
1666
+ print(f" Category: {cat.upper()}", file=sys.stderr)
1667
+ print(f"{'='*60}", file=sys.stderr)
1668
+
1669
+ cat_checks = [
1670
+ (cid, fn, sev) for cid, (fn, c, sev) in CHECK_REGISTRY.items() if c == cat
1671
+ ]
1672
+ for check_id, fn, severity in cat_checks:
1673
+ result, duration = _timed(fn)
1674
+ result.duration_ms = duration
1675
+ checks.append(result)
1676
+
1677
+ if stream:
1678
+ icon = {"pass": "[PASS]", "fail": "[FAIL]", "warn": "[WARN]", "skip": "[SKIP]"}.get(result.status, "[????]")
1679
+ print(f" {icon} {result.check_id}: {result.check_name} — {result.message} ({duration}ms)", file=sys.stderr)
1680
+
1681
+ # Build report
1682
+ total_ms = int((time.time() - start_time) * 1000)
1683
+ cat_summary = {}
1684
+ for cat in categories:
1685
+ cat_checks_list = [c for c in checks if c.category == cat]
1686
+ cat_summary[cat] = {
1687
+ "pass": sum(1 for c in cat_checks_list if c.status == "pass"),
1688
+ "fail": sum(1 for c in cat_checks_list if c.status == "fail"),
1689
+ "warn": sum(1 for c in cat_checks_list if c.status == "warn"),
1690
+ "skip": sum(1 for c in cat_checks_list if c.status == "skip"),
1691
+ "checks": [c.to_dict() for c in cat_checks_list],
1692
+ }
1693
+
1694
+ blockers = [
1695
+ f"{c.check_id}: {c.message}"
1696
+ for c in checks if c.status == "fail" and c.severity == "blocking"
1697
+ ]
1698
+ warnings = [
1699
+ f"{c.check_id}: {c.message}"
1700
+ for c in checks if c.status in ("fail", "warn")
1701
+ ]
1702
+
1703
+ report = AuditReport(
1704
+ overall_pass=len(blockers) == 0,
1705
+ timestamp=datetime.now(timezone.utc).isoformat(),
1706
+ categories=cat_summary,
1707
+ total_checks=len(checks),
1708
+ passed=sum(1 for c in checks if c.status == "pass"),
1709
+ failed=sum(1 for c in checks if c.status == "fail"),
1710
+ warned=sum(1 for c in checks if c.status == "warn"),
1711
+ skipped=sum(1 for c in checks if c.status == "skip"),
1712
+ blockers=blockers,
1713
+ warnings=warnings,
1714
+ duration_total_ms=total_ms,
1715
+ )
1716
+
1717
+ # Store in DB (append-only)
1718
+ _store_report(report, categories)
1719
+
1720
+ return report
1721
+
1722
+
1723
+ def _store_report(report: AuditReport, categories: List[str]):
1724
+ """Store audit report in production_audits table (append-only)."""
1725
+ try:
1726
+ conn = get_connection()
1727
+ conn.execute(
1728
+ """INSERT INTO production_audits
1729
+ (overall_pass, total_checks, passed, failed, warned, skipped,
1730
+ blockers, warnings, categories_run, report_json, duration_ms)
1731
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
1732
+ (
1733
+ 1 if report.overall_pass else 0,
1734
+ report.total_checks,
1735
+ report.passed,
1736
+ report.failed,
1737
+ report.warned,
1738
+ report.skipped,
1739
+ json.dumps(report.blockers),
1740
+ json.dumps(report.warnings),
1741
+ json.dumps(categories),
1742
+ json.dumps(report.to_dict()),
1743
+ report.duration_total_ms,
1744
+ ),
1745
+ )
1746
+ conn.commit()
1747
+ conn.close()
1748
+ except Exception:
1749
+ pass # Don't fail the audit because DB write failed
1750
+
1751
+
1752
+ # ---------------------------------------------------------------------------
1753
+ # Output formatters
1754
+ # ---------------------------------------------------------------------------
1755
+
1756
+ def _format_human(report: AuditReport) -> str:
1757
+ """Format report for human-readable terminal output."""
1758
+ lines = []
1759
+ lines.append("")
1760
+ lines.append("=" * 60)
1761
+ lines.append(" SPARKPILOT Production Readiness Audit")
1762
+ lines.append("=" * 60)
1763
+ lines.append("")
1764
+
1765
+ for cat, summary in report.categories.items():
1766
+ lines.append(f" --- {cat.upper()} ---")
1767
+ for check in summary.get("checks", []):
1768
+ icon = {"pass": "[PASS]", "fail": "[FAIL]", "warn": "[WARN]", "skip": "[SKIP]"}.get(check["status"], "[????]")
1769
+ sev_tag = " (BLOCKING)" if check["severity"] == "blocking" and check["status"] == "fail" else ""
1770
+ lines.append(f" {icon} {check['check_id']}: {check['check_name']}{sev_tag}")
1771
+ lines.append(f" {check['message']} ({check['duration_ms']}ms)")
1772
+ lines.append("")
1773
+
1774
+ lines.append("-" * 60)
1775
+ status = "READY" if report.overall_pass else "BLOCKED"
1776
+ lines.append(f" Overall: {status}")
1777
+ lines.append(f" Checks: {report.passed} passed, {report.failed} failed, {report.warned} warned, {report.skipped} skipped")
1778
+ lines.append(f" Duration: {report.duration_total_ms}ms")
1779
+
1780
+ if report.blockers:
1781
+ lines.append("")
1782
+ lines.append(" BLOCKERS (must fix before production):")
1783
+ for b in report.blockers:
1784
+ lines.append(f" - {b}")
1785
+
1786
+ if report.warnings:
1787
+ non_blocker_warnings = [w for w in report.warnings if w not in report.blockers]
1788
+ if non_blocker_warnings:
1789
+ lines.append("")
1790
+ lines.append(" WARNINGS (should fix):")
1791
+ for w in non_blocker_warnings[:10]:
1792
+ lines.append(f" - {w}")
1793
+
1794
+ lines.append("=" * 60)
1795
+ return "\n".join(lines)
1796
+
1797
+
1798
+ # ---------------------------------------------------------------------------
1799
+ # CLI
1800
+ # ---------------------------------------------------------------------------
1801
+
1802
+ def main():
1803
+ parser = argparse.ArgumentParser(description="SPARKPILOT Production Readiness Audit")
1804
+ parser.add_argument("--json", action="store_true", help="JSON output")
1805
+ parser.add_argument("--human", action="store_true", help="Human-readable output")
1806
+ parser.add_argument("--stream", action="store_true", help="Stream results as they complete")
1807
+ parser.add_argument("--gate", action="store_true", help="Exit 1 if any blocker fails")
1808
+ parser.add_argument("--category", type=str, default=None,
1809
+ help="Comma-separated categories: platform,security,compliance,integration,performance,documentation")
1810
+ args = parser.parse_args()
1811
+
1812
+ categories = None
1813
+ if args.category:
1814
+ categories = [c.strip() for c in args.category.split(",") if c.strip() in ALL_CATEGORIES]
1815
+ if not categories:
1816
+ print(f"Invalid categories. Valid: {', '.join(CATEGORY_ORDER)}", file=sys.stderr)
1817
+ sys.exit(2)
1818
+
1819
+ # Default to stream + human if neither --json nor --human specified
1820
+ if not args.json and not args.human:
1821
+ args.human = True
1822
+ args.stream = True
1823
+
1824
+ report = run_audit(categories=categories, stream=args.stream or args.human)
1825
+
1826
+ if args.json:
1827
+ print(json.dumps(report.to_dict(), indent=2))
1828
+ else:
1829
+ print(_format_human(report))
1830
+
1831
+ if args.gate or True: # Always exit with appropriate code
1832
+ sys.exit(0 if report.overall_pass else 1)
1833
+
1834
+
1835
+ if __name__ == "__main__":
1836
+ main()