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,2175 @@
1
+ #!/usr/bin/env python3
2
+ # CUI // SP-CTI
3
+ # Controlled by: Department of Defense
4
+ # CUI Category: CTI
5
+ # Distribution: D
6
+ # POC: SPARKPILOT System Administrator
7
+ """Conversational requirements intake engine.
8
+
9
+ Creates and manages intake sessions, processes customer turns, extracts
10
+ requirements, detects gaps/ambiguities, and scores readiness.
11
+
12
+ Usage:
13
+ # Create new session
14
+ python tools/requirements/intake_engine.py --project-id proj-123 \\
15
+ --customer-name "Jane Smith" --customer-org "PEO IEW&S" --impact-level IL4 --json
16
+
17
+ # Process a customer turn
18
+ python tools/requirements/intake_engine.py --session-id sess-abc \\
19
+ --message "We need a mission planning tool with 200 users" --json
20
+
21
+ # Resume paused session
22
+ python tools/requirements/intake_engine.py --session-id sess-abc --resume --json
23
+
24
+ # Score readiness
25
+ python tools/requirements/intake_engine.py --session-id sess-abc --score-readiness --json
26
+
27
+ # Export requirements
28
+ python tools/requirements/intake_engine.py --session-id sess-abc --export --json
29
+ """
30
+
31
+ import argparse
32
+ import json
33
+ import re
34
+ import uuid
35
+ from datetime import datetime, timezone
36
+ from pathlib import Path
37
+ from tools.db.storage import get_connection
38
+ DB_PATH = None # Storage layer handles path resolution (D-DB-20)
39
+
40
+ BASE_DIR = Path(__file__).resolve().parent.parent.parent
41
+
42
+ # Graceful import of audit logger
43
+ try:
44
+ from tools.audit.audit_logger import log_event
45
+ _HAS_AUDIT = True
46
+ except ImportError:
47
+ _HAS_AUDIT = False
48
+ def log_event(**kwargs) -> int:
49
+ return -1
50
+
51
+
52
+ def _generate_id(prefix="sess"):
53
+ """Generate a unique ID with prefix."""
54
+ return f"{prefix}-{uuid.uuid4().hex[:12]}"
55
+
56
+
57
+ def _load_config():
58
+ """Load RICOAS configuration."""
59
+ config_path = BASE_DIR / "args" / "ricoas_config.yaml"
60
+ if config_path.exists():
61
+ try:
62
+ import yaml
63
+ with open(config_path, "r", encoding="utf-8") as f:
64
+ return yaml.safe_load(f)
65
+ except ImportError:
66
+ pass
67
+ # Fallback defaults
68
+ return {
69
+ "ricoas": {
70
+ "readiness_threshold": 0.7,
71
+ "readiness_weights": {
72
+ "completeness": 0.25,
73
+ "clarity": 0.25,
74
+ "feasibility": 0.20,
75
+ "compliance": 0.15,
76
+ "testability": 0.15,
77
+ },
78
+ "intake_agent": {
79
+ "max_conversation_turns": 200,
80
+ "auto_readiness_score_interval": 3,
81
+ },
82
+ }
83
+ }
84
+
85
+
86
+ def _load_persona(role, custom_role_description=None):
87
+ """Load persona definition for a given role from role_personas.yaml.
88
+
89
+ Args:
90
+ role: The role key (e.g. 'developer', 'pm', 'isso').
91
+ custom_role_description: Optional description for custom roles.
92
+
93
+ Returns:
94
+ dict with persona fields (system_prompt, opening_question, etc.)
95
+ or None if persona file is missing.
96
+ """
97
+ persona_path = BASE_DIR / "args" / "role_personas.yaml"
98
+ if not persona_path.exists():
99
+ return None
100
+ try:
101
+ import yaml
102
+ with open(persona_path, "r", encoding="utf-8") as f:
103
+ data = yaml.safe_load(f) or {}
104
+ except ImportError:
105
+ return None
106
+
107
+ personas = data.get("personas", {})
108
+
109
+ # Check for built-in persona
110
+ if role in personas:
111
+ return personas[role]
112
+
113
+ # Custom role — synthesize persona from meta template
114
+ if custom_role_description:
115
+ custom_cfg = data.get("custom_role", {})
116
+ meta_prompt = custom_cfg.get("meta_system_prompt", "")
117
+ opening_prompt = custom_cfg.get("opening_prompt", "")
118
+ return {
119
+ "display_name": role.replace("_", " ").title(),
120
+ "system_prompt": meta_prompt.replace("{role_name}", role).replace(
121
+ "{role_description}", custom_role_description
122
+ ),
123
+ "opening_question": opening_prompt.replace("{role_name}", role).replace(
124
+ "{role_description}", custom_role_description
125
+ ),
126
+ "priority_topics": [],
127
+ "follow_up_patterns": [],
128
+ }
129
+
130
+ # Fallback to developer persona
131
+ return personas.get("developer")
132
+
133
+
134
+ # ---------------------------------------------------------------------------
135
+ # LLM-powered persona response generation
136
+ # ---------------------------------------------------------------------------
137
+
138
+ # Conditional LLM imports — LLM may not be available in air-gapped envs
139
+ _HAS_LLM = False
140
+ try:
141
+ from tools.llm import get_router
142
+ from tools.llm.provider import LLMRequest as _LLMRequest
143
+ _HAS_LLM = True
144
+ except ImportError:
145
+ pass
146
+
147
+
148
+ def _generate_persona_response(session_data, message, signals, conn):
149
+ """Generate an LLM-powered persona response for the intake conversation.
150
+
151
+ Builds a system prompt from the session's persona, conversation history,
152
+ and current turn signals, then calls the LLM router.
153
+
154
+ Args:
155
+ session_data: dict of the intake_sessions row.
156
+ message: The customer message for this turn.
157
+ signals: dict with keys like extracted_reqs, ambiguities,
158
+ boundary_flags, gap_signals, devsecops_signals,
159
+ zta_signals, mosa_signals, readiness_update.
160
+ conn: Active database connection.
161
+
162
+ Returns:
163
+ str with the persona response, or None if LLM is unavailable
164
+ or any error occurs (caller should fall back to deterministic response).
165
+ """
166
+ if not _HAS_LLM:
167
+ return None
168
+
169
+ try:
170
+ # Load context from session
171
+ context_raw = session_data.get("context_summary") or "{}"
172
+ try:
173
+ ctx = json.loads(context_raw)
174
+ except (json.JSONDecodeError, TypeError):
175
+ ctx = {}
176
+
177
+ role = ctx.get("role", "developer")
178
+ custom_desc = ctx.get("custom_role_description", "")
179
+ persona = _load_persona(role, custom_desc)
180
+ if not persona:
181
+ return None
182
+
183
+ # Build conversation history (last 10 turns)
184
+ session_id = session_data.get("id", "")
185
+ history_rows = conn.execute(
186
+ """SELECT turn_number, role, content
187
+ FROM intake_conversation
188
+ WHERE session_id = ?
189
+ ORDER BY turn_number DESC LIMIT 10""",
190
+ (session_id,),
191
+ ).fetchall()
192
+ history_rows = list(reversed(history_rows))
193
+
194
+ conversation_messages = []
195
+ for row in history_rows:
196
+ r = dict(row)
197
+ msg_role = "assistant" if r["role"] == "analyst" else "user"
198
+ if r["role"] == "system":
199
+ continue
200
+ conversation_messages.append({
201
+ "role": msg_role,
202
+ "content": r["content"],
203
+ })
204
+ # Add current customer message
205
+ conversation_messages.append({
206
+ "role": "user",
207
+ "content": message,
208
+ })
209
+
210
+ # Build system prompt with persona + session context
211
+ goal = ctx.get("goal", "build")
212
+ selected_fw = ctx.get("selected_frameworks", [])
213
+ req_count = signals.get("total_requirements", 0)
214
+ readiness = signals.get("readiness_update")
215
+
216
+ system_parts = [
217
+ persona.get("system_prompt", ""),
218
+ "",
219
+ "--- Session Context ---",
220
+ f"Goal: {goal}",
221
+ f"Classification: {session_data.get('classification', 'CUI')}",
222
+ f"Impact Level: {session_data.get('impact_level', 'IL5')}",
223
+ ]
224
+ if selected_fw:
225
+ system_parts.append(f"Selected Frameworks: {', '.join(selected_fw)}")
226
+ system_parts.append(f"Requirements captured so far: {req_count}")
227
+
228
+ # Inject active elicitation technique (BMAD pattern)
229
+ active_tech_prompt = ctx.get("active_technique_prompt")
230
+ if active_tech_prompt:
231
+ system_parts.append("")
232
+ system_parts.append("--- Active Elicitation Technique ---")
233
+ system_parts.append(active_tech_prompt)
234
+ system_parts.append(
235
+ "IMPORTANT: Frame your response using the active technique above. "
236
+ "Ask questions that align with the technique's approach."
237
+ )
238
+
239
+ if readiness:
240
+ system_parts.append(
241
+ f"Readiness score: {readiness.get('overall', 0):.0%}"
242
+ )
243
+ # Show per-dimension scores so the agent targets weak areas
244
+ dims = {
245
+ "completeness": readiness.get("completeness", 0),
246
+ "clarity": readiness.get("clarity", 0),
247
+ "feasibility": readiness.get("feasibility", 0),
248
+ "compliance": readiness.get("compliance", 0),
249
+ "testability": readiness.get("testability", 0),
250
+ }
251
+ dim_strs = [f" {k}: {v:.0%}" for k, v in dims.items()]
252
+ system_parts.append("Readiness by dimension:")
253
+ system_parts.extend(dim_strs)
254
+ # Identify the weakest dimension and hint what to ask
255
+ weakest = min(dims, key=dims.get)
256
+ dim_probes = {
257
+ "completeness": (
258
+ "Completeness is low — ask about requirement types not yet "
259
+ "covered (e.g., performance, security, data, integration, "
260
+ "usability, deployment). Probe for missing user roles, "
261
+ "workflows, or edge cases."
262
+ ),
263
+ "clarity": (
264
+ "Clarity is low — some requirements use vague language. "
265
+ "Ask the customer to quantify terms (e.g., 'how many users?', "
266
+ "'what response time?', 'what does success look like?')."
267
+ ),
268
+ "feasibility": (
269
+ "Feasibility is low — ask about constraints: available "
270
+ "timeline, team size, technology limitations, existing "
271
+ "systems to integrate with, hosting environment."
272
+ ),
273
+ "compliance": (
274
+ "Compliance is low — ask about security requirements: "
275
+ "authentication (CAC/PIV, MFA), encryption (FIPS 140-2), "
276
+ "audit logging, access controls, data handling rules, "
277
+ "or any specific NIST/STIG/FedRAMP controls."
278
+ ),
279
+ "testability": (
280
+ "Testability is low — ask the customer to define acceptance "
281
+ "criteria: 'How would you verify this works?', 'What does "
282
+ "a successful outcome look like?', 'What are the pass/fail "
283
+ "conditions?'"
284
+ ),
285
+ }
286
+ system_parts.append("")
287
+ system_parts.append(f"PRIORITY: {dim_probes.get(weakest, '')}")
288
+
289
+ # Add conversation coverage analysis
290
+ cov = signals.get("coverage")
291
+ if cov:
292
+ system_parts.append("")
293
+ system_parts.append("--- Conversation Coverage ---")
294
+ system_parts.append(cov["summary"])
295
+ system_parts.append(
296
+ "IMPORTANT: Do NOT ask generic questions. Analyze what the customer "
297
+ "has already told you and ask about a SPECIFIC missing topic from "
298
+ "the list above. Reference what they said to show you were listening."
299
+ )
300
+
301
+ # Add URL content fetched from customer message
302
+ url_contents = signals.get("url_contents", [])
303
+ if url_contents:
304
+ system_parts.append("")
305
+ system_parts.append("--- URLs Referenced by Customer ---")
306
+ for uc in url_contents:
307
+ system_parts.append(f"URL: {uc['url']}")
308
+ if uc.get("title"):
309
+ system_parts.append(f"Title: {uc['title']}")
310
+ system_parts.append(f"Content: {uc['summary']}")
311
+ system_parts.append("")
312
+ system_parts.append(
313
+ "IMPORTANT: The customer shared URL(s). Review the content above and "
314
+ "reference relevant details in your response. Extract any requirements "
315
+ "or context from the linked content. Show the customer you reviewed "
316
+ "their link."
317
+ )
318
+
319
+ # Add uploaded document context
320
+ doc_rows = conn.execute(
321
+ "SELECT file_name, document_type, extracted_requirements_count, "
322
+ "extracted_sections FROM intake_documents WHERE session_id = ?",
323
+ (session_id,),
324
+ ).fetchall()
325
+ if doc_rows:
326
+ system_parts.append("")
327
+ system_parts.append("--- Uploaded Documents ---")
328
+ for dr in doc_rows:
329
+ d = dict(dr)
330
+ system_parts.append(
331
+ f"Document: {d['file_name']} (type: {d['document_type']}, "
332
+ f"{d['extracted_requirements_count']} requirements extracted)"
333
+ )
334
+ if d.get("extracted_sections"):
335
+ try:
336
+ sections = json.loads(d["extracted_sections"])
337
+ if isinstance(sections, dict):
338
+ if sections.get("description"):
339
+ system_parts.append(
340
+ f" Content: {sections['description'][:300]}"
341
+ )
342
+ if sections.get("category"):
343
+ system_parts.append(
344
+ f" Category: {sections['category']}"
345
+ )
346
+ except (json.JSONDecodeError, TypeError):
347
+ pass
348
+ # Include document-extracted requirements as context
349
+ doc_reqs = conn.execute(
350
+ "SELECT raw_text, requirement_type FROM intake_requirements "
351
+ "WHERE session_id = ? AND source_document IS NOT NULL "
352
+ "ORDER BY created_at LIMIT 20",
353
+ (session_id,),
354
+ ).fetchall()
355
+ if doc_reqs:
356
+ system_parts.append("Requirements from documents:")
357
+ for dr in doc_reqs:
358
+ d = dict(dr)
359
+ system_parts.append(
360
+ f" - [{d['requirement_type'].upper()}] {d['raw_text'][:120]}"
361
+ )
362
+ system_parts.append(
363
+ "Reference the uploaded document content when asking follow-up "
364
+ "questions. Use extracted requirements as context to ask deeper, "
365
+ "more specific questions about the customer's needs."
366
+ )
367
+
368
+ # Add signal summary for this turn
369
+ signal_notes = []
370
+ extracted_reqs = signals.get("extracted_reqs", [])
371
+ if extracted_reqs:
372
+ signal_notes.append(
373
+ f"Extracted {len(extracted_reqs)} requirement(s) this turn."
374
+ )
375
+ ambiguities = signals.get("ambiguities", [])
376
+ if ambiguities:
377
+ terms = [a["phrase"] for a in ambiguities]
378
+ signal_notes.append(
379
+ f"Ambiguous terms detected: {', '.join(terms)}"
380
+ )
381
+ boundary_flags = signals.get("boundary_flags", [])
382
+ if boundary_flags:
383
+ tiers = [f["tier"] for f in boundary_flags]
384
+ signal_notes.append(
385
+ f"ATO boundary flags: {', '.join(tiers)}"
386
+ )
387
+ gap_signals = signals.get("gap_signals", [])
388
+ if gap_signals:
389
+ signal_notes.append(
390
+ f"Gap signals: {'; '.join(gap_signals[:3])}"
391
+ )
392
+ if signal_notes:
393
+ system_parts.append("")
394
+ system_parts.append("--- This Turn ---")
395
+ system_parts.extend(signal_notes)
396
+
397
+ # Structured clarification questions (D159, spec-kit Pattern 4)
398
+ clarifications = signals.get("clarification_signals", [])
399
+ if clarifications:
400
+ system_parts.append("")
401
+ system_parts.append("--- Priority Clarification Questions ---")
402
+ for cq in clarifications[:3]:
403
+ system_parts.append(
404
+ f" [P{cq.get('priority', '?')}] {cq.get('question', '')}"
405
+ )
406
+ system_parts.append(
407
+ "IMPORTANT: Weave ONE of these clarification questions into your "
408
+ "response naturally. Do not ask all at once."
409
+ )
410
+
411
+ # Parallel execution opportunities (D161, spec-kit Pattern 7)
412
+ parallel_opps = signals.get("parallel_opportunities", [])
413
+ if parallel_opps:
414
+ system_parts.append("")
415
+ system_parts.append("--- Parallel Execution Opportunities ---")
416
+ system_parts.append(
417
+ f"Detected {len(parallel_opps)} group(s) of independent tasks "
418
+ "that could run concurrently."
419
+ )
420
+ system_parts.append(
421
+ "Mention this when discussing implementation timeline."
422
+ )
423
+
424
+ system_parts.append("")
425
+ system_parts.append(
426
+ "Respond in character. Acknowledge what the customer said, reference "
427
+ "any extracted requirements or issues, and ask a follow-up question "
428
+ "that drives toward completeness. Keep the response concise (2-4 paragraphs)."
429
+ )
430
+
431
+ system_prompt = "\n".join(system_parts)
432
+
433
+ router = get_router()
434
+ request = _LLMRequest(
435
+ messages=conversation_messages,
436
+ system_prompt=system_prompt,
437
+ max_tokens=1024,
438
+ temperature=0.7,
439
+ agent_id="sparkpilot-requirements-analyst",
440
+ project_id=session_data.get("project_id", ""),
441
+ classification=session_data.get("classification", "CUI"),
442
+ )
443
+ response = router.invoke("intake_persona_response", request)
444
+ if response and response.content:
445
+ return response.content.strip()
446
+ return None
447
+ except Exception:
448
+ return None
449
+
450
+
451
+ # ---------------------------------------------------------------------------
452
+ # Session management
453
+ # ---------------------------------------------------------------------------
454
+
455
+ def create_session(
456
+ project_id: str,
457
+ customer_name: str,
458
+ customer_org: str = None,
459
+ impact_level: str = "IL5",
460
+ classification: str = None,
461
+ created_by: str = "sparkpilot-requirements-analyst",
462
+ db_path=None,
463
+ role: str = "developer",
464
+ goal: str = "build",
465
+ selected_frameworks=None,
466
+ custom_role_description: str = "",
467
+ ) -> dict:
468
+ """Create a new intake session. Returns session data dict.
469
+
470
+ Classification is resolved dynamically (ADR D132):
471
+ - If provided explicitly, use that value.
472
+ - If None, resolve from project metadata (classification + impact_level).
473
+ - Public / IL2 -> "PUBLIC" (no marking required).
474
+ - IL4/IL5 -> "CUI", IL6 -> "SECRET" (backward compat per ADR D54).
475
+ """
476
+ session_id = _generate_id("sess")
477
+ conn = get_connection(db_path=db_path)
478
+
479
+ # Validate project exists if provided
480
+ if project_id:
481
+ row = conn.execute(
482
+ "SELECT id, classification, impact_level FROM projects WHERE id = ?",
483
+ (project_id,),
484
+ ).fetchone()
485
+ if not row:
486
+ conn.close()
487
+ raise ValueError(f"Project '{project_id}' not found in database.")
488
+
489
+ # Resolve classification from project if not provided
490
+ if classification is None:
491
+ proj = dict(row) if hasattr(row, "keys") else {"classification": row[1], "impact_level": row[2]}
492
+ cls_val = (proj.get("classification") or "").upper()
493
+ il_val = (proj.get("impact_level") or "").upper()
494
+ if cls_val == "PUBLIC" or il_val == "IL2":
495
+ classification = "PUBLIC"
496
+ elif cls_val in ("SECRET", "TOP SECRET", "TOP_SECRET") or il_val == "IL6":
497
+ classification = "SECRET"
498
+ else:
499
+ classification = "CUI"
500
+ else:
501
+ if classification is None:
502
+ classification = "CUI"
503
+
504
+ conn.execute(
505
+ """INSERT INTO intake_sessions
506
+ (id, project_id, customer_name, customer_org, session_status,
507
+ classification, impact_level, created_by)
508
+ VALUES (?, ?, ?, ?, 'active', ?, ?, ?)""",
509
+ (session_id, project_id, customer_name, customer_org,
510
+ classification, impact_level, created_by),
511
+ )
512
+
513
+ # Store session context (role, goal, frameworks, custom description)
514
+ context = {
515
+ "role": role,
516
+ "goal": goal,
517
+ "selected_frameworks": selected_frameworks or [],
518
+ "custom_role_description": custom_role_description,
519
+ }
520
+ conn.execute("UPDATE intake_sessions SET context_summary = ? WHERE id = ?",
521
+ (json.dumps(context), session_id))
522
+
523
+ # Insert initial system turn
524
+ conn.execute(
525
+ """INSERT INTO intake_conversation
526
+ (session_id, turn_number, role, content, content_type)
527
+ VALUES (?, 0, 'system', ?, 'text')""",
528
+ (session_id, json.dumps({
529
+ "event": "session_created",
530
+ "project_id": project_id,
531
+ "customer_name": customer_name,
532
+ "impact_level": impact_level,
533
+ })),
534
+ )
535
+
536
+ # Generate persona-appropriate welcome message
537
+ default_welcome = (
538
+ f"Session created. Welcome, {customer_name}. "
539
+ f"I'm the SPARKPILOT Requirements Analyst. I'll help capture and "
540
+ f"structure your requirements for a {impact_level} system. "
541
+ f"Let's start with the mission context — what problem does "
542
+ f"this system need to solve?"
543
+ )
544
+ welcome_message = default_welcome
545
+
546
+ persona = _load_persona(role, custom_role_description)
547
+ if persona:
548
+ # Try LLM-powered welcome
549
+ llm_welcome = None
550
+ if _HAS_LLM:
551
+ try:
552
+ fw_text = ""
553
+ if selected_frameworks:
554
+ fw_text = f" Compliance frameworks: {', '.join(selected_frameworks)}."
555
+ opening_system = (
556
+ f"{persona.get('system_prompt', '')}\n\n"
557
+ f"You are starting a requirements intake session with "
558
+ f"{customer_name} from {customer_org or 'their organization'}. "
559
+ f"Impact level: {impact_level}. Classification: {classification}. "
560
+ f"Goal: {goal}.{fw_text}\n\n"
561
+ f"Introduce yourself briefly in your role and ask your opening "
562
+ f"question. Keep it to 2-3 sentences."
563
+ )
564
+ router = get_router()
565
+ request = _LLMRequest(
566
+ messages=[{"role": "user", "content": "Begin the intake session."}],
567
+ system_prompt=opening_system,
568
+ max_tokens=512,
569
+ temperature=0.7,
570
+ agent_id="sparkpilot-requirements-analyst",
571
+ project_id=project_id,
572
+ classification=classification or "CUI",
573
+ )
574
+ resp = router.invoke("intake_persona_response", request)
575
+ if resp and resp.content:
576
+ llm_welcome = resp.content.strip()
577
+ except Exception:
578
+ pass
579
+
580
+ if llm_welcome:
581
+ welcome_message = llm_welcome
582
+ elif persona.get("opening_question"):
583
+ welcome_message = persona["opening_question"].strip()
584
+
585
+ # Store welcome as first analyst turn (turn_number=1)
586
+ conn.execute(
587
+ """INSERT INTO intake_conversation
588
+ (session_id, turn_number, role, content, content_type, classification)
589
+ VALUES (?, 1, 'analyst', ?, 'text', ?)""",
590
+ (session_id, welcome_message, classification or "CUI"),
591
+ )
592
+
593
+ conn.commit()
594
+ conn.close()
595
+
596
+ if _HAS_AUDIT:
597
+ log_event(
598
+ event_type="intake_session_created",
599
+ actor=created_by,
600
+ action=f"Created intake session {session_id} for {customer_name}",
601
+ project_id=project_id,
602
+ details={"session_id": session_id, "impact_level": impact_level},
603
+ )
604
+
605
+ return {
606
+ "status": "ok",
607
+ "session_id": session_id,
608
+ "project_id": project_id,
609
+ "customer_name": customer_name,
610
+ "customer_org": customer_org,
611
+ "impact_level": impact_level,
612
+ "session_status": "active",
613
+ "readiness_score": 0.0,
614
+ "message": welcome_message,
615
+ }
616
+
617
+
618
+ def get_session(session_id: str, db_path=None) -> dict:
619
+ """Get session status and summary."""
620
+ conn = get_connection(db_path=db_path)
621
+ row = conn.execute(
622
+ "SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
623
+ ).fetchone()
624
+ if not row:
625
+ conn.close()
626
+ raise ValueError(f"Session '{session_id}' not found.")
627
+
628
+ session = dict(row)
629
+
630
+ # Get counts
631
+ req_count = conn.execute(
632
+ "SELECT COUNT(*) as cnt FROM intake_requirements WHERE session_id = ?",
633
+ (session_id,),
634
+ ).fetchone()["cnt"]
635
+
636
+ turn_count = conn.execute(
637
+ "SELECT COUNT(*) as cnt FROM intake_conversation WHERE session_id = ?",
638
+ (session_id,),
639
+ ).fetchone()["cnt"]
640
+
641
+ decomp_count = conn.execute(
642
+ "SELECT COUNT(*) as cnt FROM safe_decomposition WHERE session_id = ?",
643
+ (session_id,),
644
+ ).fetchone()["cnt"]
645
+
646
+ doc_count = conn.execute(
647
+ "SELECT COUNT(*) as cnt FROM intake_documents WHERE session_id = ?",
648
+ (session_id,),
649
+ ).fetchone()["cnt"]
650
+
651
+ conn.close()
652
+
653
+ session["requirement_count"] = req_count
654
+ session["turn_count"] = turn_count
655
+ session["decomposition_count"] = decomp_count
656
+ session["document_count"] = doc_count
657
+
658
+ return session
659
+
660
+
661
+ def resume_session(session_id: str, db_path=None) -> dict:
662
+ """Resume a paused session. Returns context summary and last state."""
663
+ conn = get_connection(db_path=db_path)
664
+ row = conn.execute(
665
+ "SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
666
+ ).fetchone()
667
+ if not row:
668
+ conn.close()
669
+ raise ValueError(f"Session '{session_id}' not found.")
670
+
671
+ session = dict(row)
672
+ if session["session_status"] not in ("active", "paused"):
673
+ conn.close()
674
+ raise ValueError(
675
+ f"Session '{session_id}' is {session['session_status']}, cannot resume."
676
+ )
677
+
678
+ # Get last 5 conversation turns for context
679
+ recent_turns = conn.execute(
680
+ """SELECT turn_number, role, content, content_type
681
+ FROM intake_conversation
682
+ WHERE session_id = ?
683
+ ORDER BY turn_number DESC LIMIT 5""",
684
+ (session_id,),
685
+ ).fetchall()
686
+ recent_turns = [dict(t) for t in reversed(recent_turns)]
687
+
688
+ # Get requirement summary
689
+ reqs = conn.execute(
690
+ """SELECT id, raw_text, requirement_type, priority, status
691
+ FROM intake_requirements
692
+ WHERE session_id = ?
693
+ ORDER BY created_at""",
694
+ (session_id,),
695
+ ).fetchall()
696
+ req_summary = [dict(r) for r in reqs]
697
+
698
+ # Update status to active
699
+ conn.execute(
700
+ "UPDATE intake_sessions SET session_status = 'active', updated_at = ? WHERE id = ?",
701
+ (datetime.now(timezone.utc).isoformat(), session_id),
702
+ )
703
+ conn.commit()
704
+ conn.close()
705
+
706
+ if _HAS_AUDIT:
707
+ log_event(
708
+ event_type="intake_session_resumed",
709
+ actor="sparkpilot-requirements-analyst",
710
+ action=f"Resumed intake session {session_id}",
711
+ project_id=session.get("project_id"),
712
+ details={"session_id": session_id},
713
+ )
714
+
715
+ return {
716
+ "status": "ok",
717
+ "session_id": session_id,
718
+ "session_status": "active",
719
+ "readiness_score": session.get("readiness_score", 0.0),
720
+ "context_summary": session.get("context_summary", ""),
721
+ "requirement_count": len(req_summary),
722
+ "recent_turns": recent_turns,
723
+ "requirements": req_summary,
724
+ "message": f"Session resumed. You have {len(req_summary)} requirements captured "
725
+ f"with readiness score {session.get('readiness_score', 0.0):.1%}. "
726
+ f"Where would you like to continue?",
727
+ }
728
+
729
+
730
+ def pause_session(session_id: str, db_path=None) -> dict:
731
+ """Pause a session for later resumption."""
732
+ conn = get_connection(db_path=db_path)
733
+ conn.execute(
734
+ "UPDATE intake_sessions SET session_status = 'paused', updated_at = ? WHERE id = ?",
735
+ (datetime.now(timezone.utc).isoformat(), session_id),
736
+ )
737
+ conn.commit()
738
+ conn.close()
739
+ return {"status": "ok", "session_id": session_id, "session_status": "paused"}
740
+
741
+
742
+ # ---------------------------------------------------------------------------
743
+ # Conversation processing
744
+ # ---------------------------------------------------------------------------
745
+
746
+ def process_turn(
747
+ session_id: str,
748
+ customer_message: str,
749
+ db_path=None,
750
+ ) -> dict:
751
+ """Process a customer message turn. Extracts requirements, detects gaps,
752
+ and generates analyst response.
753
+
754
+ This is the core function that the agent chat calls on each turn.
755
+ It stores the customer message, analyzes it for requirements and issues,
756
+ and returns a structured response.
757
+ """
758
+ conn = get_connection(db_path=db_path)
759
+
760
+ # Verify session exists and is active
761
+ session = conn.execute(
762
+ "SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
763
+ ).fetchone()
764
+ if not session:
765
+ conn.close()
766
+ raise ValueError(f"Session '{session_id}' not found.")
767
+ if dict(session)["session_status"] != "active":
768
+ conn.close()
769
+ raise ValueError(f"Session is {dict(session)['session_status']}, not active.")
770
+
771
+ session_data = dict(session)
772
+
773
+ # Get current turn number
774
+ last_turn = conn.execute(
775
+ "SELECT MAX(turn_number) as max_turn FROM intake_conversation WHERE session_id = ?",
776
+ (session_id,),
777
+ ).fetchone()
778
+ turn_number = (last_turn["max_turn"] or 0) + 1
779
+
780
+ # Store customer turn
781
+ conn.execute(
782
+ """INSERT INTO intake_conversation
783
+ (session_id, turn_number, role, content, content_type, classification)
784
+ VALUES (?, ?, 'customer', ?, 'text', ?)""",
785
+ (session_id, turn_number, customer_message, session_data.get("classification", "CUI")),
786
+ )
787
+
788
+ # --- Requirement extraction (deterministic keyword analysis) ---
789
+ extracted_reqs = _extract_requirements_from_text(
790
+ customer_message, session_id, turn_number, conn
791
+ )
792
+
793
+ # --- URL detection and content fetching ---
794
+ url_contents = _extract_and_fetch_urls(customer_message)
795
+
796
+ # --- Ambiguity detection (with dedup across turns) ---
797
+ raw_ambiguities = _detect_ambiguities_in_text(customer_message)
798
+
799
+ # Load previously flagged terms from context so we don't re-flag them
800
+ context = {}
801
+ try:
802
+ context = json.loads(session_data.get("context_summary") or "{}")
803
+ except (ValueError, TypeError):
804
+ pass
805
+ flagged_terms = set(context.get("flagged_ambiguities", []))
806
+ ambiguities = [a for a in raw_ambiguities if a["phrase"].lower() not in flagged_terms]
807
+
808
+ # Record newly flagged terms so future turns skip them
809
+ if ambiguities:
810
+ for a in ambiguities:
811
+ flagged_terms.add(a["phrase"].lower())
812
+ context["flagged_ambiguities"] = sorted(flagged_terms)
813
+ conn.execute(
814
+ "UPDATE intake_sessions SET context_summary = ? WHERE id = ?",
815
+ (json.dumps(context), session_id),
816
+ )
817
+
818
+ # --- Gap signals ---
819
+ gap_signals = _detect_gap_signals(customer_message, session_id, conn)
820
+
821
+ # --- Boundary flags ---
822
+ boundary_flags = _detect_boundary_signals(customer_message, session_data)
823
+
824
+ # --- DevSecOps / ZTA signals (Phase 24) ---
825
+ devsecops_signals = _detect_devsecops_signals(customer_message)
826
+ zta_signals = _detect_zta_signals(customer_message)
827
+
828
+ # --- MOSA signals (Phase 26, D125) ---
829
+ mosa_signals = _detect_mosa_signals(customer_message, session_data)
830
+
831
+ # --- Dev profile signals (Phase 34, D184-D188) ---
832
+ dev_profile_signals = _detect_dev_profile_signals(customer_message, session_data)
833
+
834
+ # --- AI governance signals (Phase 50, D322) ---
835
+ ai_governance_signals = _detect_ai_governance_signals(customer_message, session_data)
836
+
837
+ # --- Structured clarification (D159, spec-kit Pattern 4) ---
838
+ clarification_signals = []
839
+ try:
840
+ from tools.requirements.clarification_engine import analyze_requirements_clarity
841
+ db_path_resolved = db_path or DB_PATH
842
+ clarity_result = analyze_requirements_clarity(
843
+ session_id, max_questions=3, db_path=db_path_resolved,
844
+ )
845
+ clarification_signals = clarity_result.get("questions", [])
846
+ except (ImportError, Exception):
847
+ pass
848
+
849
+ # --- Detect parallel opportunities (D161, spec-kit Pattern 7) ---
850
+ parallel_opportunities = []
851
+ try:
852
+ from tools.requirements.decomposition_engine import detect_parallel_groups
853
+ db_path_resolved = db_path or DB_PATH
854
+ parallel_opportunities = detect_parallel_groups(session_id, db_path=db_path_resolved)
855
+ except (ImportError, Exception):
856
+ pass
857
+
858
+ # --- Update session counters ---
859
+ req_count = conn.execute(
860
+ "SELECT COUNT(*) as cnt FROM intake_requirements WHERE session_id = ?",
861
+ (session_id,),
862
+ ).fetchone()["cnt"]
863
+
864
+ conn.execute(
865
+ """UPDATE intake_sessions
866
+ SET total_requirements = ?,
867
+ ambiguity_count = ambiguity_count + ?,
868
+ updated_at = ?
869
+ WHERE id = ?""",
870
+ (req_count, len(ambiguities), datetime.now(timezone.utc).isoformat(), session_id),
871
+ )
872
+
873
+ # --- BDD preview generation + store as acceptance criteria ---
874
+ # Must run BEFORE readiness so testability score reflects BDD criteria
875
+ bdd_previews = []
876
+ try:
877
+ from tools.requirements.decomposition_engine import generate_bdd_criteria
878
+ for req in extracted_reqs:
879
+ gherkin = generate_bdd_criteria(req["raw_text"], req["requirement_type"])
880
+ bdd_previews.append({"requirement": req["raw_text"][:80], "gherkin": gherkin})
881
+ # Store BDD as acceptance criteria so testability score reflects it
882
+ if gherkin and req.get("id"):
883
+ conn.execute(
884
+ "UPDATE intake_requirements SET acceptance_criteria = ? WHERE id = ?",
885
+ (gherkin, req["id"]),
886
+ )
887
+ except ImportError:
888
+ pass
889
+
890
+ # Flush BDD + requirement writes so the sidebar readiness poller
891
+ # (which opens its own connection) can see them immediately.
892
+ conn.commit()
893
+
894
+ # --- Conversation coverage analysis (what topics are covered vs missing) ---
895
+ coverage = _analyze_conversation_coverage(session_id, conn)
896
+
897
+ # --- Readiness update (computed every turn, after BDD storage) ---
898
+ readiness_update = _quick_readiness_estimate(session_id, conn)
899
+
900
+ # --- Try LLM-powered persona response ---
901
+ analyst_turn = turn_number + 1
902
+ persona_signals = {
903
+ "extracted_reqs": extracted_reqs,
904
+ "ambiguities": ambiguities,
905
+ "boundary_flags": boundary_flags,
906
+ "gap_signals": gap_signals,
907
+ "devsecops_signals": devsecops_signals,
908
+ "zta_signals": zta_signals,
909
+ "mosa_signals": mosa_signals,
910
+ "ai_governance_signals": ai_governance_signals,
911
+ "readiness_update": readiness_update,
912
+ "total_requirements": req_count,
913
+ "coverage": coverage,
914
+ "url_contents": url_contents,
915
+ "clarification_signals": clarification_signals,
916
+ "parallel_opportunities": parallel_opportunities,
917
+ }
918
+ persona_response = _generate_persona_response(
919
+ session_data, customer_message, persona_signals, conn
920
+ )
921
+
922
+ if persona_response is not None:
923
+ analyst_response = persona_response
924
+ else:
925
+ # --- Fallback: deterministic analyst response ---
926
+ response_parts = []
927
+
928
+ if extracted_reqs:
929
+ response_parts.append(
930
+ f"I captured {len(extracted_reqs)} requirement(s) from what you described."
931
+ )
932
+ for req in extracted_reqs:
933
+ response_parts.append(
934
+ f" - [{req['requirement_type'].upper()}] {req['raw_text'][:100]}"
935
+ )
936
+
937
+ if url_contents:
938
+ response_parts.append("\nI reviewed the link(s) you shared:")
939
+ for uc in url_contents:
940
+ title_part = f" ({uc['title']})" if uc.get("title") else ""
941
+ response_parts.append(f" - {uc['url']}{title_part}")
942
+ if uc.get("summary") and not uc["summary"].startswith("("):
943
+ # Show a brief excerpt of the fetched content
944
+ summary_short = uc["summary"][:300]
945
+ response_parts.append(f" Content: {summary_short}")
946
+
947
+ if ambiguities:
948
+ response_parts.append(
949
+ f"\nI noticed {len(ambiguities)} term(s) that need clarification:"
950
+ )
951
+ for amb in ambiguities:
952
+ response_parts.append(f" - '{amb['phrase']}': {amb['clarification']}")
953
+
954
+ if boundary_flags:
955
+ response_parts.append("\nATO Boundary flags:")
956
+ for flag in boundary_flags:
957
+ response_parts.append(f" - [{flag['tier']}] {flag['description']}")
958
+
959
+ if gap_signals:
960
+ response_parts.append("\nPotential gaps detected:")
961
+ for gap in gap_signals:
962
+ response_parts.append(f" - {gap}")
963
+
964
+ if devsecops_signals.get("detected_stages"):
965
+ stages = devsecops_signals["detected_stages"]
966
+ maturity = devsecops_signals.get("maturity_estimate", "unknown")
967
+ response_parts.append(
968
+ f"\nDevSecOps signals detected: {', '.join(stages)} "
969
+ f"(estimated maturity: {maturity})"
970
+ )
971
+ elif devsecops_signals.get("greenfield"):
972
+ response_parts.append(
973
+ "\nNo existing DevSecOps tooling detected — "
974
+ "SPARKPILOT will configure pipeline security stages based on impact level."
975
+ )
976
+
977
+ if zta_signals.get("zta_detected"):
978
+ pillars = zta_signals.get("detected_pillars", [])
979
+ response_parts.append(
980
+ "\nZero Trust Architecture requirement detected"
981
+ + (f" (pillars: {', '.join(pillars)})" if pillars else "")
982
+ + ". NIST SP 800-207 framework will be included in compliance assessment."
983
+ )
984
+
985
+ if mosa_signals.get("mosa_detected"):
986
+ mosa_pillars = mosa_signals.get("detected_pillars", [])
987
+ if mosa_signals.get("dod_ic_detected"):
988
+ response_parts.append(
989
+ "\nDoD/IC customer detected — MOSA (Modular Open Systems Approach) "
990
+ "is required per 10 U.S.C. §4401. SPARKPILOT will enforce modular architecture, "
991
+ "open standards, and interface control documentation."
992
+ )
993
+ else:
994
+ response_parts.append(
995
+ "\nMOSA (Modular Open Systems Approach) signals detected. "
996
+ "MOSA framework will be included in compliance assessment."
997
+ )
998
+ if mosa_pillars:
999
+ response_parts.append(
1000
+ f" MOSA pillars identified: {', '.join(p.replace('_', ' ') for p in mosa_pillars)}"
1001
+ )
1002
+ # Probe for missing MOSA pillars
1003
+ all_pillars = {"modular_architecture", "open_standards", "open_interfaces",
1004
+ "data_rights", "competitive_sourcing", "continuous_assessment"}
1005
+ missing = all_pillars - set(mosa_pillars)
1006
+ if missing and len(mosa_pillars) < 4:
1007
+ probes = {
1008
+ "open_interfaces": "Do you have existing Interface Control Documents (ICDs) or API specifications?",
1009
+ "data_rights": "What are the government data rights requirements? (GPR, unlimited rights, etc.)",
1010
+ "competitive_sourcing": "Is multi-vendor replaceability a requirement?",
1011
+ "open_standards": "Which standard protocols/data formats will be used? (REST/OpenAPI, gRPC, JSON, Protobuf)",
1012
+ "modular_architecture": "Is the system designed with modular, loosely-coupled components?",
1013
+ "continuous_assessment": "Will there be ongoing architecture reviews and modularity metrics?",
1014
+ }
1015
+ probe_q = [probes[p] for p in sorted(missing) if p in probes][:2]
1016
+ if probe_q:
1017
+ response_parts.append("\nTo complete MOSA assessment, please clarify:")
1018
+ for q in probe_q:
1019
+ response_parts.append(f" - {q}")
1020
+
1021
+ if ai_governance_signals.get("ai_governance_detected"):
1022
+ gov_pillars = ai_governance_signals.get("detected_pillars", [])
1023
+ if ai_governance_signals.get("federal_agency_detected"):
1024
+ response_parts.append(
1025
+ "\nFederal agency detected — AI governance requirements apply per OMB M-25-21. "
1026
+ "SPARKPILOT will track AI inventory, model documentation, human oversight, "
1027
+ "impact assessments, transparency, and accountability."
1028
+ )
1029
+ else:
1030
+ response_parts.append(
1031
+ "\nAI/ML system usage detected. AI governance framework will be "
1032
+ "included in compliance assessment."
1033
+ )
1034
+ if gov_pillars:
1035
+ response_parts.append(
1036
+ f" AI governance pillars identified: {', '.join(p.replace('_', ' ') for p in gov_pillars)}"
1037
+ )
1038
+ # Probe for missing governance pillars
1039
+ all_gov_pillars = {"ai_inventory", "model_documentation", "human_oversight",
1040
+ "impact_assessment", "transparency", "accountability"}
1041
+ missing_gov = all_gov_pillars - set(gov_pillars)
1042
+ if missing_gov and len(gov_pillars) < 4:
1043
+ gov_probes = {
1044
+ "ai_inventory": "Does this system use AI/ML models? If so, what types (classification, NLP, recommendation, generation)?",
1045
+ "model_documentation": "Are there existing model cards or documentation for the AI models used?",
1046
+ "human_oversight": "What human oversight is in place for AI decisions? Is there an appeal process?",
1047
+ "impact_assessment": "Has an algorithmic impact assessment been conducted? Does the AI make rights-impacting decisions?",
1048
+ "transparency": "Are users notified when AI is making or supporting decisions?",
1049
+ "accountability": "Is there a designated Chief AI Officer (CAIO) or responsible official?",
1050
+ }
1051
+ probe_q = [gov_probes[p] for p in sorted(missing_gov) if p in gov_probes][:2]
1052
+ if probe_q:
1053
+ response_parts.append("\nTo complete AI governance assessment, please clarify:")
1054
+ for q in probe_q:
1055
+ response_parts.append(f" - {q}")
1056
+
1057
+ # Add readiness update and targeted follow-up question
1058
+ if readiness_update:
1059
+ response_parts.append(
1060
+ f"\nReadiness: {readiness_update['overall']:.0%} "
1061
+ f"(completeness={readiness_update['completeness']:.0%}, "
1062
+ f"clarity={readiness_update['clarity']:.0%}, "
1063
+ f"feasibility={readiness_update['feasibility']:.0%}, "
1064
+ f"compliance={readiness_update['compliance']:.0%}, "
1065
+ f"testability={readiness_update['testability']:.0%})"
1066
+ )
1067
+
1068
+ # Ask a targeted question to improve the weakest dimension
1069
+ dims = {
1070
+ "completeness": readiness_update.get("completeness", 0),
1071
+ "clarity": readiness_update.get("clarity", 0),
1072
+ "feasibility": readiness_update.get("feasibility", 0),
1073
+ "compliance": readiness_update.get("compliance", 0),
1074
+ "testability": readiness_update.get("testability", 0),
1075
+ }
1076
+ weakest = min(dims, key=dims.get)
1077
+
1078
+ # Use coverage-based targeted questions for completeness
1079
+ # instead of generic "describe user roles, workflows..."
1080
+ cov = persona_signals.get("coverage", {})
1081
+ missing_qs = cov.get("missing_questions", [])
1082
+
1083
+ followup_questions = {
1084
+ "completeness": (
1085
+ missing_qs[0] if missing_qs else
1086
+ "What other capabilities or workflows should this system support?"
1087
+ ),
1088
+ "clarity": (
1089
+ "Could you quantify some of the requirements? "
1090
+ "For example, expected number of users, response times, or data volumes."
1091
+ ),
1092
+ "feasibility": (
1093
+ "What's the target timeline, team size, "
1094
+ "and hosting environment? Any technology constraints?"
1095
+ ),
1096
+ "compliance": (
1097
+ "What security requirements apply? "
1098
+ "For example: authentication method (CAC/PIV, MFA), encryption "
1099
+ "standards, audit logging, or access control policies."
1100
+ ),
1101
+ "testability": (
1102
+ "How would you verify each requirement works? "
1103
+ "What are the pass/fail conditions or acceptance criteria?"
1104
+ ),
1105
+ }
1106
+ if dims[weakest] < 0.7:
1107
+ response_parts.append(f"\n{followup_questions[weakest]}")
1108
+
1109
+ # Structured clarification from Impact × Uncertainty matrix (D159)
1110
+ if clarification_signals:
1111
+ top_q = clarification_signals[0]
1112
+ question_text = top_q.get("question", "")
1113
+ if question_text:
1114
+ response_parts.append(f"\nTo help me clarify: {question_text}")
1115
+
1116
+ # Parallel execution opportunities (D161)
1117
+ if parallel_opportunities:
1118
+ response_parts.append(
1119
+ f"\nNote: I've identified {len(parallel_opportunities)} group(s) of "
1120
+ "independent tasks that could run in parallel to speed up delivery."
1121
+ )
1122
+
1123
+ analyst_response = "\n".join(response_parts) if response_parts else (
1124
+ "Thank you. Could you tell me more about the specific capabilities "
1125
+ "you need? For example, what are the key user workflows?"
1126
+ )
1127
+
1128
+ # Store analyst turn
1129
+ conn.execute(
1130
+ """INSERT INTO intake_conversation
1131
+ (session_id, turn_number, role, content, content_type,
1132
+ extracted_requirements, metadata, classification)
1133
+ VALUES (?, ?, 'analyst', ?, 'text', ?, ?, ?)""",
1134
+ (
1135
+ session_id,
1136
+ analyst_turn,
1137
+ analyst_response,
1138
+ json.dumps([r["id"] for r in extracted_reqs]) if extracted_reqs else None,
1139
+ json.dumps({
1140
+ "ambiguities_found": len(ambiguities),
1141
+ "requirements_extracted": len(extracted_reqs),
1142
+ "boundary_flags": len(boundary_flags),
1143
+ "devsecops_stages_detected": devsecops_signals.get("detected_stages", []),
1144
+ "devsecops_maturity_estimate": devsecops_signals.get("maturity_estimate"),
1145
+ "zta_detected": zta_signals.get("zta_detected", False),
1146
+ "zta_pillars_detected": zta_signals.get("detected_pillars", []),
1147
+ "mosa_detected": mosa_signals.get("mosa_detected", False),
1148
+ "mosa_dod_ic_detected": mosa_signals.get("dod_ic_detected", False),
1149
+ "mosa_pillars_detected": mosa_signals.get("detected_pillars", []),
1150
+ "ai_governance_detected": ai_governance_signals.get("ai_governance_detected", False),
1151
+ "ai_governance_pillars_detected": ai_governance_signals.get("detected_pillars", []),
1152
+ "ai_governance_federal_agency": ai_governance_signals.get("federal_agency_detected", False),
1153
+ "clarification_questions": len(clarification_signals),
1154
+ "parallel_groups": len(parallel_opportunities),
1155
+ }),
1156
+ session_data.get("classification", "CUI"),
1157
+ ),
1158
+ )
1159
+
1160
+ conn.commit()
1161
+ conn.close()
1162
+
1163
+ # Audit log
1164
+ if _HAS_AUDIT and extracted_reqs:
1165
+ log_event(
1166
+ event_type="requirement_captured",
1167
+ actor="sparkpilot-requirements-analyst",
1168
+ action=f"Extracted {len(extracted_reqs)} requirement(s) from turn {turn_number}",
1169
+ project_id=session_data.get("project_id"),
1170
+ details={
1171
+ "session_id": session_id,
1172
+ "turn": turn_number,
1173
+ "count": len(extracted_reqs),
1174
+ },
1175
+ )
1176
+
1177
+ return {
1178
+ "status": "ok",
1179
+ "session_id": session_id,
1180
+ "turn_number": analyst_turn,
1181
+ "analyst_response": analyst_response,
1182
+ "extracted_requirements": extracted_reqs,
1183
+ "ambiguities": ambiguities,
1184
+ "boundary_flags": boundary_flags,
1185
+ "gap_signals": gap_signals,
1186
+ "readiness_update": readiness_update,
1187
+ "total_requirements": req_count + len(extracted_reqs),
1188
+ "bdd_previews": bdd_previews,
1189
+ "url_contents": url_contents,
1190
+ }
1191
+
1192
+
1193
+ # ---------------------------------------------------------------------------
1194
+ # Requirement extraction helpers
1195
+ # ---------------------------------------------------------------------------
1196
+
1197
+ # Requirement type detection keywords
1198
+ _REQ_TYPE_KEYWORDS = {
1199
+ "security": [
1200
+ "authenticate", "authorize", "encrypt", "CAC", "PIV", "MFA",
1201
+ "FIPS", "STIG", "access control", "audit log", "credential",
1202
+ "certificate", "PKI", "RBAC", "permission", "classification",
1203
+ ],
1204
+ "performance": [
1205
+ "response time", "latency", "throughput", "concurrent",
1206
+ "availability", "uptime", "SLA", "load", "capacity",
1207
+ ],
1208
+ "interface": [
1209
+ "integrate", "interface", "API", "REST", "SOAP", "feed",
1210
+ "import", "export", "connect", "external system", "third-party",
1211
+ ],
1212
+ "data": [
1213
+ "database", "data store", "retention", "backup", "archive",
1214
+ "migrate data", "data format", "schema", "CUI data",
1215
+ ],
1216
+ "compliance": [
1217
+ "NIST", "FedRAMP", "CMMC", "ATO", "SSP", "POAM",
1218
+ "STIG", "RMF", "accreditation", "authorization boundary",
1219
+ ],
1220
+ "non_functional": [
1221
+ "scalab", "reliab", "maintainab", "portab", "usab",
1222
+ "accessibility", "WCAG", "Section 508", "i18n", "l10n",
1223
+ ],
1224
+ }
1225
+
1226
+ # Priority detection
1227
+ _PRIORITY_KEYWORDS = {
1228
+ "critical": ["must", "shall", "critical", "mandatory", "required", "essential"],
1229
+ "high": ["should", "important", "needed", "key", "primary"],
1230
+ "medium": ["could", "nice to have", "desirable", "want"],
1231
+ "low": ["may", "optional", "future", "nice", "wish"],
1232
+ }
1233
+
1234
+
1235
+ def _extract_requirements_from_text(text, session_id, turn_number, conn):
1236
+ """Extract structured requirements from customer text using keyword analysis."""
1237
+ extracted = []
1238
+ # Split on sentence boundaries
1239
+ sentences = [s.strip() for s in text.replace("\n", ". ").split(".") if s.strip() and len(s.strip()) > 10]
1240
+
1241
+ for sentence in sentences:
1242
+ lower = sentence.lower()
1243
+
1244
+ # Check if this sentence contains requirement-like language
1245
+ has_req_signal = any(
1246
+ kw in lower
1247
+ for kw in ["need", "want", "must", "shall", "should", "require",
1248
+ "able to", "capability", "feature", "support", "provide",
1249
+ "enable", "allow", "system will", "system shall"]
1250
+ )
1251
+ if not has_req_signal:
1252
+ continue
1253
+
1254
+ # Detect type
1255
+ req_type = "functional" # default
1256
+ for rtype, keywords in _REQ_TYPE_KEYWORDS.items():
1257
+ if any(kw.lower() in lower for kw in keywords):
1258
+ req_type = rtype
1259
+ break
1260
+
1261
+ # Detect priority
1262
+ priority = "medium" # default
1263
+ for prio, keywords in _PRIORITY_KEYWORDS.items():
1264
+ if any(kw in lower for kw in keywords):
1265
+ priority = prio
1266
+ break
1267
+
1268
+ # Create requirement record — classification inherited from session
1269
+ req_id = _generate_id("req")
1270
+ sess_row = conn.execute(
1271
+ "SELECT classification FROM intake_sessions WHERE id = ?",
1272
+ (session_id,),
1273
+ ).fetchone()
1274
+ req_classification = sess_row[0] if sess_row else "CUI"
1275
+ conn.execute(
1276
+ """INSERT INTO intake_requirements
1277
+ (id, session_id, source_turn, raw_text, requirement_type,
1278
+ priority, status, classification)
1279
+ VALUES (?, ?, ?, ?, ?, ?, 'draft', ?)""",
1280
+ (req_id, session_id, turn_number, sentence.strip(), req_type,
1281
+ priority, req_classification),
1282
+ )
1283
+
1284
+ extracted.append({
1285
+ "id": req_id,
1286
+ "raw_text": sentence.strip(),
1287
+ "requirement_type": req_type,
1288
+ "priority": priority,
1289
+ })
1290
+
1291
+ return extracted
1292
+
1293
+
1294
+ def _analyze_conversation_coverage(session_id, conn):
1295
+ """Analyze conversation history to identify covered topics and specific gaps.
1296
+
1297
+ Returns dict with 'covered' (set of topic keys), 'missing' (list of
1298
+ specific gap questions), and 'summary' (string for LLM context).
1299
+ """
1300
+ # Gather all customer messages
1301
+ rows = conn.execute(
1302
+ "SELECT content FROM intake_conversation "
1303
+ "WHERE session_id = ? AND role = 'customer' ORDER BY turn_number",
1304
+ (session_id,),
1305
+ ).fetchall()
1306
+ all_text = " ".join(dict(r)["content"] for r in rows).lower()
1307
+
1308
+ # Also include requirements extracted from uploaded documents
1309
+ doc_reqs = conn.execute(
1310
+ "SELECT raw_text FROM intake_requirements "
1311
+ "WHERE session_id = ? AND source_document IS NOT NULL",
1312
+ (session_id,),
1313
+ ).fetchall()
1314
+ if doc_reqs:
1315
+ doc_text = " ".join(dict(r)["raw_text"] for r in doc_reqs).lower()
1316
+ all_text += " " + doc_text
1317
+
1318
+ # Topic detection with specific follow-up questions
1319
+ topics = {
1320
+ "users_roles": {
1321
+ "keywords": ["user", "role", "agent", "admin", "operator", "analyst",
1322
+ "viewer", "customer", "personnel", "staff"],
1323
+ "covered_question": None,
1324
+ "gap_question": "Who will use this system? What are the distinct user roles and their permissions?",
1325
+ },
1326
+ "workflow": {
1327
+ "keywords": ["workflow", "process", "step", "flow", "sequence",
1328
+ "procedure", "pipeline", "task"],
1329
+ "covered_question": None,
1330
+ "gap_question": "What's the primary user workflow from start to finish?",
1331
+ },
1332
+ "data_model": {
1333
+ "keywords": ["data", "database", "record", "field", "store", "table",
1334
+ "schema", "entity", "model", "input", "output"],
1335
+ "covered_question": None,
1336
+ "gap_question": "What data does the system manage? What are the key entities and their relationships?",
1337
+ },
1338
+ "integration": {
1339
+ "keywords": ["integrate", "api", "rest", "connect", "external",
1340
+ "third-party", "system", "mcp", "soap", "feed"],
1341
+ "covered_question": None,
1342
+ "gap_question": "What external systems does this integrate with? What protocols (REST, MCP, file)?",
1343
+ },
1344
+ "performance": {
1345
+ "keywords": ["performance", "sla", "uptime", "latency", "response time",
1346
+ "concurrent", "throughput", "availability", "99"],
1347
+ "covered_question": None,
1348
+ "gap_question": "What are the performance requirements? (SLA, response times, concurrent users)",
1349
+ },
1350
+ "security_auth": {
1351
+ "keywords": ["security", "auth", "login", "cac", "piv", "mfa",
1352
+ "encrypt", "fips", "access control", "rbac", "permission"],
1353
+ "covered_question": None,
1354
+ "gap_question": "How do users authenticate? (CAC/PIV, MFA, username/password) What access controls are needed?",
1355
+ },
1356
+ "error_handling": {
1357
+ "keywords": ["error", "fail", "exception", "retry", "fallback",
1358
+ "validation", "invalid", "reject", "deny"],
1359
+ "covered_question": None,
1360
+ "gap_question": "What happens when something goes wrong? (validation failures, system errors, invalid inputs)",
1361
+ },
1362
+ "reporting": {
1363
+ "keywords": ["report", "dashboard", "metric", "analytics", "audit",
1364
+ "log", "history", "export", "csv", "pdf"],
1365
+ "covered_question": None,
1366
+ "gap_question": "Does the system need reporting, audit trails, or dashboards? What metrics matter?",
1367
+ },
1368
+ "deployment": {
1369
+ "keywords": ["deploy", "host", "cloud", "aws", "govcloud", "on-prem",
1370
+ "environment", "staging", "production", "docker", "k8s"],
1371
+ "covered_question": None,
1372
+ "gap_question": "Where will this be deployed? (AWS GovCloud, on-prem, hybrid) What environments are needed?",
1373
+ },
1374
+ "ui_ux": {
1375
+ "keywords": ["ui", "ux", "interface", "screen", "page", "form",
1376
+ "button", "design", "mobile", "responsive", "intuitive"],
1377
+ "covered_question": None,
1378
+ "gap_question": "What should the user interface look like? (web app, mobile, desktop) Any specific UX requirements?",
1379
+ },
1380
+ "ai_governance": {
1381
+ "keywords": ["ai system", "machine learning", "ml model", "deep learning",
1382
+ "neural network", "nlp", "computer vision", "recommendation engine",
1383
+ "predictive model", "automated decision", "algorithmic", "chatbot",
1384
+ "generative ai", "llm", "foundation model", "model card",
1385
+ "human oversight", "impact assessment", "ai governance",
1386
+ "responsible ai", "caio", "chief ai officer"],
1387
+ "covered_question": None,
1388
+ "gap_question": "Does this system use AI/ML? If so, what governance is needed (model documentation, human oversight, impact assessments)?",
1389
+ },
1390
+ }
1391
+
1392
+ covered = set()
1393
+ missing_questions = []
1394
+ for topic_key, topic in topics.items():
1395
+ if any(kw in all_text for kw in topic["keywords"]):
1396
+ covered.add(topic_key)
1397
+ else:
1398
+ missing_questions.append(topic["gap_question"])
1399
+
1400
+ # Build summary for LLM context
1401
+ summary_parts = [f"Topics covered ({len(covered)}/{len(topics)}): {', '.join(sorted(covered)) or 'none'}"]
1402
+ if missing_questions:
1403
+ summary_parts.append(f"Topics NOT covered: {', '.join(sorted(set(topics.keys()) - covered))}")
1404
+ summary_parts.append("Ask about ONE of these specific gaps (pick the most important):")
1405
+ for q in missing_questions[:3]:
1406
+ summary_parts.append(f" - {q}")
1407
+
1408
+ return {
1409
+ "covered": covered,
1410
+ "total_topics": len(topics),
1411
+ "missing_questions": missing_questions,
1412
+ "summary": "\n".join(summary_parts),
1413
+ }
1414
+
1415
+
1416
+ def _extract_and_fetch_urls(text):
1417
+ """Detect URLs in customer message and fetch page content/summaries.
1418
+
1419
+ Returns a list of dicts: [{"url": "...", "title": "...", "summary": "..."}]
1420
+ Only fetches HTTP/HTTPS URLs. Best-effort — failures return a note.
1421
+ """
1422
+ url_pattern = re.compile(
1423
+ r'https?://[^\s<>\"\')]+', re.IGNORECASE
1424
+ )
1425
+ urls = url_pattern.findall(text)
1426
+ if not urls:
1427
+ return []
1428
+
1429
+ results = []
1430
+ try:
1431
+ import requests as _requests
1432
+ except ImportError:
1433
+ for u in urls:
1434
+ results.append({"url": u, "title": "", "summary": "(requests library not available)"})
1435
+ return results
1436
+
1437
+ for url in urls[:3]: # limit to 3 URLs per message
1438
+ try:
1439
+ resp = _requests.get(url, timeout=10, headers={
1440
+ "User-Agent": "SPARKPILOT-Intake-Agent/1.0",
1441
+ "Accept": "text/html,application/json,text/plain",
1442
+ })
1443
+ resp.raise_for_status()
1444
+ content_type = resp.headers.get("Content-Type", "")
1445
+
1446
+ if "application/json" in content_type:
1447
+ # JSON API — summarize top-level keys
1448
+ try:
1449
+ data = resp.json()
1450
+ if isinstance(data, dict):
1451
+ summary = f"JSON with keys: {', '.join(list(data.keys())[:15])}"
1452
+ title = data.get("name", data.get("full_name", data.get("title", "")))
1453
+ desc = data.get("description", "")
1454
+ if desc:
1455
+ summary += f". Description: {desc}"
1456
+ elif isinstance(data, list):
1457
+ summary = f"JSON array with {len(data)} items"
1458
+ title = ""
1459
+ else:
1460
+ summary = str(data)[:300]
1461
+ title = ""
1462
+ except (ValueError, TypeError):
1463
+ summary = resp.text[:500]
1464
+ title = ""
1465
+ else:
1466
+ # HTML — extract title and meta description / first text
1467
+ body = resp.text[:50000]
1468
+ title_match = re.search(r'<title[^>]*>([^<]+)</title>', body, re.I)
1469
+ title = title_match.group(1).strip() if title_match else ""
1470
+
1471
+ # Try meta description
1472
+ meta_match = re.search(
1473
+ r'<meta\s+[^>]*name=["\']description["\']\s+content=["\']([^"\']+)',
1474
+ body, re.I
1475
+ )
1476
+ if not meta_match:
1477
+ meta_match = re.search(
1478
+ r'<meta\s+[^>]*content=["\']([^"\']+)["\'][^>]*name=["\']description',
1479
+ body, re.I
1480
+ )
1481
+ desc = meta_match.group(1).strip() if meta_match else ""
1482
+
1483
+ # Try README or about-section text for GitHub-like pages
1484
+ readme_match = re.search(
1485
+ r'<article[^>]*class="[^"]*markdown-body[^"]*"[^>]*>(.*?)</article>',
1486
+ body, re.I | re.S
1487
+ )
1488
+ readme_text = ""
1489
+ if readme_match:
1490
+ # Strip HTML tags for plain text
1491
+ raw = re.sub(r'<[^>]+>', ' ', readme_match.group(1))
1492
+ raw = re.sub(r'\s+', ' ', raw).strip()
1493
+ readme_text = raw[:800]
1494
+
1495
+ if readme_text:
1496
+ summary = f"{desc}. README: {readme_text}" if desc else f"README: {readme_text}"
1497
+ elif desc:
1498
+ summary = desc
1499
+ else:
1500
+ # Fallback: strip tags from first visible text
1501
+ stripped = re.sub(r'<script[^>]*>.*?</script>', '', body, flags=re.S | re.I)
1502
+ stripped = re.sub(r'<style[^>]*>.*?</style>', '', stripped, flags=re.S | re.I)
1503
+ stripped = re.sub(r'<[^>]+>', ' ', stripped)
1504
+ stripped = re.sub(r'\s+', ' ', stripped).strip()
1505
+ summary = stripped[:500] if stripped else "(no readable content)"
1506
+
1507
+ results.append({"url": url, "title": title, "summary": summary[:1000]})
1508
+
1509
+ except Exception as exc:
1510
+ results.append({"url": url, "title": "", "summary": f"(could not fetch: {exc})"})
1511
+
1512
+ return results
1513
+
1514
+
1515
+ def _detect_ambiguities_in_text(text):
1516
+ """Detect ambiguous terms using pattern matching."""
1517
+ ambiguities = []
1518
+ lower = text.lower()
1519
+
1520
+ # Load patterns from context file if available
1521
+ patterns_path = BASE_DIR / "context" / "requirements" / "ambiguity_patterns.json"
1522
+ if patterns_path.exists():
1523
+ with open(patterns_path, "r", encoding="utf-8") as f:
1524
+ data = json.load(f)
1525
+ patterns = data.get("ambiguity_patterns", [])
1526
+ else:
1527
+ # Fallback minimal patterns
1528
+ patterns = [
1529
+ {"phrase": "as needed", "severity": "high",
1530
+ "clarification": "Define specific conditions that trigger this action."},
1531
+ {"phrase": "appropriate", "severity": "high",
1532
+ "clarification": "Define measurable criteria."},
1533
+ {"phrase": "timely", "severity": "high",
1534
+ "clarification": "Specify an exact time threshold."},
1535
+ {"phrase": "user-friendly", "severity": "medium",
1536
+ "clarification": "Define specific usability criteria."},
1537
+ {"phrase": "fast", "severity": "high",
1538
+ "clarification": "Specify a measurable target."},
1539
+ {"phrase": "secure", "severity": "critical",
1540
+ "clarification": "Specify security requirements: FIPS, STIG, controls."},
1541
+ {"phrase": "scalable", "severity": "medium",
1542
+ "clarification": "Define target scale: users, data volume."},
1543
+ ]
1544
+
1545
+ for pattern in patterns:
1546
+ if pattern["phrase"].lower() in lower:
1547
+ ambiguities.append({
1548
+ "phrase": pattern["phrase"],
1549
+ "severity": pattern.get("severity", "medium"),
1550
+ "clarification": pattern.get("clarification", "Please clarify this term."),
1551
+ })
1552
+
1553
+ return ambiguities
1554
+
1555
+
1556
+ def _detect_gap_signals(text, session_id, conn):
1557
+ """Detect signals that may indicate requirement gaps."""
1558
+ signals = []
1559
+ lower = text.lower()
1560
+
1561
+ # Check for external system mentions without interface detail
1562
+ interface_terms = ["integrate", "connect", "interface", "external", "feed", "third-party"]
1563
+ protocol_terms = ["rest", "api", "soap", "message queue", "file", "isa", "mou"]
1564
+ if any(t in lower for t in interface_terms) and not any(t in lower for t in protocol_terms):
1565
+ signals.append(
1566
+ "External system mentioned without interface protocol — "
1567
+ "ask about REST/SOAP/MQ and ISA/MOU requirements"
1568
+ )
1569
+
1570
+ # Check for security without specifics
1571
+ if any(t in lower for t in ["secure", "security", "protect"]) and not any(
1572
+ t in lower for t in ["fips", "stig", "nist", "cac", "piv", "encrypt", "mfa"]
1573
+ ):
1574
+ signals.append(
1575
+ "Security mentioned without specifics — "
1576
+ "ask about FIPS encryption, CAC/PIV auth, STIG compliance"
1577
+ )
1578
+
1579
+ # Check for data mentions without classification
1580
+ if any(t in lower for t in ["data", "information", "records"]) and not any(
1581
+ t in lower for t in ["cui", "classified", "unclassified", "fouo", "secret"]
1582
+ ):
1583
+ signals.append(
1584
+ "Data mentioned without classification — "
1585
+ "ask about CUI categories and data handling requirements"
1586
+ )
1587
+
1588
+ return signals
1589
+
1590
+
1591
+ def _detect_boundary_signals(text, session_data):
1592
+ """Detect potential ATO boundary impact signals."""
1593
+ flags = []
1594
+ lower = text.lower()
1595
+ impact_level = session_data.get("impact_level", "IL5")
1596
+
1597
+ # Classification upgrade signals
1598
+ if impact_level in ("IL4", "IL5") and any(
1599
+ t in lower for t in ["secret", "ts/sci", "top secret", "classified"]
1600
+ ):
1601
+ flags.append({
1602
+ "tier": "RED",
1603
+ "description": f"Classification upgrade detected — current system is {impact_level} "
1604
+ f"but SECRET/TS data mentioned. This would invalidate the current ATO.",
1605
+ })
1606
+
1607
+ # New external interface
1608
+ if any(t in lower for t in ["new system", "new interface", "new connection", "new integration"]):
1609
+ flags.append({
1610
+ "tier": "ORANGE",
1611
+ "description": "New external interface — requires ISA/MOU and SSP Section 9 update.",
1612
+ })
1613
+
1614
+ # BYOD/mobile
1615
+ if any(t in lower for t in ["mobile", "byod", "personal device", "phone", "tablet"]):
1616
+ flags.append({
1617
+ "tier": "ORANGE",
1618
+ "description": "Mobile/BYOD access — requires AC-19, MDM solution, SSP boundary update.",
1619
+ })
1620
+
1621
+ # Cloud service change
1622
+ if any(t in lower for t in ["aws commercial", "azure", "gcp", "public cloud"]):
1623
+ flags.append({
1624
+ "tier": "ORANGE",
1625
+ "description": "Non-GovCloud service mentioned — current boundary is AWS GovCloud only.",
1626
+ })
1627
+
1628
+ return flags
1629
+
1630
+
1631
+ def _detect_devsecops_signals(text):
1632
+ """Detect DevSecOps maturity signals from customer text (Phase 24).
1633
+
1634
+ Uses keyword matching from args/devsecops_config.yaml to identify existing
1635
+ security tooling and estimate maturity level.
1636
+ """
1637
+ try:
1638
+ from tools.devsecops.profile_manager import detect_maturity_from_text
1639
+ return detect_maturity_from_text(text)
1640
+ except (ImportError, Exception):
1641
+ # Fallback: inline minimal detection
1642
+ lower = text.lower()
1643
+ detected = []
1644
+ keyword_map = {
1645
+ "sast": ["static analysis", "code scanning", "bandit", "sonarqube", "fortify"],
1646
+ "sca": ["dependency scan", "pip-audit", "snyk", "npm audit"],
1647
+ "secret_detection": ["secret scanning", "gitleaks", "detect-secrets"],
1648
+ "container_scan": ["container scanning", "trivy", "grype", "image scanning"],
1649
+ "policy_as_code": ["policy as code", "opa", "gatekeeper", "kyverno"],
1650
+ "image_signing": ["image signing", "cosign", "sigstore"],
1651
+ }
1652
+ for stage, keywords in keyword_map.items():
1653
+ if any(kw in lower for kw in keywords):
1654
+ detected.append(stage)
1655
+ greenfield = any(s in lower for s in [
1656
+ "no security scanning", "greenfield", "starting from scratch",
1657
+ ])
1658
+ return {
1659
+ "detected_stages": sorted(set(detected)),
1660
+ "maturity_estimate": "level_1_initial" if greenfield else (
1661
+ "level_3_defined" if len(detected) >= 4 else
1662
+ "level_2_managed" if len(detected) >= 2 else
1663
+ "level_1_initial"
1664
+ ),
1665
+ "zta_detected": False,
1666
+ "greenfield": greenfield,
1667
+ "stage_count": len(detected),
1668
+ }
1669
+
1670
+
1671
+ def _detect_zta_signals(text):
1672
+ """Detect Zero Trust Architecture signals from customer text (Phase 24-25).
1673
+
1674
+ Identifies ZTA-relevant keywords and maps them to ZTA pillars.
1675
+ """
1676
+ lower = text.lower()
1677
+ zta_detected = False
1678
+ detected_pillars = []
1679
+
1680
+ # General ZTA indicators
1681
+ general_keywords = [
1682
+ "zero trust", "nist 800-207", "never trust always verify",
1683
+ "zero trust architecture",
1684
+ ]
1685
+ if any(kw in lower for kw in general_keywords):
1686
+ zta_detected = True
1687
+
1688
+ # Pillar-specific keywords
1689
+ pillar_keywords = {
1690
+ "user_identity": ["mfa", "multi-factor", "cac", "piv", "identity provider",
1691
+ "sso", "single sign-on", "continuous auth", "icam"],
1692
+ "device": ["device posture", "mdm", "endpoint detection", "device trust",
1693
+ "device compliance", "edr"],
1694
+ "network": ["micro-segmentation", "microsegmentation", "mtls", "mutual tls",
1695
+ "service mesh", "istio", "linkerd", "network policy",
1696
+ "software-defined perimeter", "ztna"],
1697
+ "application_workload": ["workload identity", "container hardening",
1698
+ "admission control", "signed images"],
1699
+ "data": ["data classification", "encryption at rest", "dlp",
1700
+ "data loss prevention", "tokenization"],
1701
+ "visibility_analytics": ["siem", "continuous monitoring", "anomaly detection",
1702
+ "threat intelligence", "security analytics"],
1703
+ "automation_orchestration": ["soar", "auto-remediation", "security orchestration",
1704
+ "automated response", "self-healing"],
1705
+ }
1706
+
1707
+ for pillar, keywords in pillar_keywords.items():
1708
+ if any(kw in lower for kw in keywords):
1709
+ detected_pillars.append(pillar)
1710
+ zta_detected = True
1711
+
1712
+ return {
1713
+ "zta_detected": zta_detected,
1714
+ "detected_pillars": sorted(detected_pillars),
1715
+ "pillar_count": len(detected_pillars),
1716
+ }
1717
+
1718
+
1719
+ def _detect_mosa_signals(text, session_data=None):
1720
+ """Detect MOSA (Modular Open Systems Approach) signals (Phase 26, D125).
1721
+
1722
+ Auto-triggers for DoD/IC customers per 10 U.S.C. §4401. Also detects
1723
+ MOSA pillar keywords for targeted follow-up questions.
1724
+ """
1725
+ lower = text.lower()
1726
+ mosa_detected = False
1727
+ detected_pillars = []
1728
+ dod_ic_detected = False
1729
+
1730
+ # DoD/IC customer keywords — auto-trigger MOSA (D125)
1731
+ dod_ic_keywords = [
1732
+ "department of defense", "dod", "air force", "army", "navy",
1733
+ "marine corps", "space force", "intelligence community",
1734
+ "combatant command", "acquisition program", "mdap", "acat",
1735
+ "program of record", "warfighter", "nsa", "dia", "nro", "nga",
1736
+ "military", "defense information systems",
1737
+ ]
1738
+ if any(kw in lower for kw in dod_ic_keywords):
1739
+ dod_ic_detected = True
1740
+ mosa_detected = True
1741
+
1742
+ # Also check session customer_org for DoD/IC indicators
1743
+ if session_data:
1744
+ org = (session_data.get("customer_org") or "").lower()
1745
+ il = (session_data.get("impact_level") or "").upper()
1746
+ if any(kw in org for kw in ["dod", "defense", "military", "ic", "intelligence"]):
1747
+ dod_ic_detected = True
1748
+ mosa_detected = True
1749
+ if il in ("IL4", "IL5", "IL6"):
1750
+ mosa_detected = True
1751
+
1752
+ # MOSA pillar keywords (from mosa_config.yaml intake_detection)
1753
+ pillar_keywords = {
1754
+ "modular_architecture": ["modular", "loosely coupled", "microservice",
1755
+ "component-based", "plugin", "module boundary",
1756
+ "encapsulation"],
1757
+ "open_standards": ["openapi", "rest api", "grpc", "protobuf",
1758
+ "standard protocol", "open standard", "json schema"],
1759
+ "open_interfaces": ["interface control", "icd", "api versioning",
1760
+ "backward compatible", "interface specification",
1761
+ "integration spec"],
1762
+ "data_rights": ["data rights", "government purpose", "license tracking",
1763
+ "source escrow", "intellectual property", "gpr",
1764
+ "unlimited rights"],
1765
+ "competitive_sourcing": ["vendor lock-in", "vendor neutral", "competitive",
1766
+ "replaceability", "build vs buy", "multi-vendor",
1767
+ "plug-and-play"],
1768
+ "continuous_assessment": ["architecture review", "modularity metrics",
1769
+ "design review", "architecture evolution",
1770
+ "technology refresh"],
1771
+ }
1772
+
1773
+ for pillar, keywords in pillar_keywords.items():
1774
+ if any(kw in lower for kw in keywords):
1775
+ detected_pillars.append(pillar)
1776
+ mosa_detected = True
1777
+
1778
+ return {
1779
+ "mosa_detected": mosa_detected,
1780
+ "dod_ic_detected": dod_ic_detected,
1781
+ "detected_pillars": sorted(detected_pillars),
1782
+ "pillar_count": len(detected_pillars),
1783
+ }
1784
+
1785
+
1786
+ def _detect_dev_profile_signals(text, session_data=None):
1787
+ """Detect development profile signals from customer text (Phase 34, D184-D188).
1788
+
1789
+ Identifies coding standards, tooling preferences, and development methodology
1790
+ signals to recommend or auto-apply a development profile template.
1791
+ """
1792
+ try:
1793
+ from tools.builder.profile_detector import detect_from_text
1794
+ raw = detect_from_text(text)
1795
+ # Normalize to expected shape
1796
+ signals = raw.get("detected_signals", {})
1797
+ return {
1798
+ "profile_detected": raw.get("signal_count", 0) > 0,
1799
+ "detected_dimensions": sorted(signals.keys()),
1800
+ "dimension_count": raw.get("signal_count", 0),
1801
+ "suggested_templates": [],
1802
+ "raw_signals": signals,
1803
+ }
1804
+ except (ImportError, Exception):
1805
+ pass
1806
+
1807
+ # Fallback: inline minimal keyword detection
1808
+ lower = text.lower()
1809
+ detected_dimensions = []
1810
+
1811
+ dimension_keywords = {
1812
+ "language": ["python", "java", "go", "golang", "rust", "typescript", "c#",
1813
+ "csharp", ".net", "flask", "fastapi", "spring boot", "express"],
1814
+ "style": ["snake_case", "camelcase", "camel case", "naming convention",
1815
+ "code style", "indent", "line length", "prettier", "black",
1816
+ "eslint", "ruff", "gofmt", "formatting", "linter"],
1817
+ "testing": ["tdd", "bdd", "test driven", "test coverage", "unit test",
1818
+ "e2e test", "cucumber", "behave", "jest", "pytest"],
1819
+ "architecture": ["microservice", "monolith", "api gateway", "rest",
1820
+ "graphql", "event driven", "hexagonal", "layered"],
1821
+ "security": ["fips", "encryption", "secret management", "sast",
1822
+ "container hardening", "stig", "vulnerability"],
1823
+ "operations": ["kubernetes", "k8s", "docker", "docker compose",
1824
+ "gitlab ci", "github actions", "jenkins", "air-gapped"],
1825
+ "git": ["trunk-based", "gitflow", "github flow", "squash merge",
1826
+ "conventional commits", "branch naming"],
1827
+ "ai": ["bedrock", "openai", "ollama", "byok", "token budget",
1828
+ "llm", "ai model", "code generation model"],
1829
+ }
1830
+
1831
+ for dim, keywords in dimension_keywords.items():
1832
+ if any(kw in lower for kw in keywords):
1833
+ detected_dimensions.append(dim)
1834
+
1835
+ # Check for template-matching signals
1836
+ template_signals = {
1837
+ "dod_baseline": ["dod", "department of defense", "il4", "il5", "il6",
1838
+ "cmmc", "stig"],
1839
+ "fedramp_baseline": ["fedramp", "fed ramp", "jab", "3pao"],
1840
+ "healthcare_baseline": ["hipaa", "hitrust", "phi", "health"],
1841
+ "financial_baseline": ["pci dss", "pci", "sox", "financial"],
1842
+ "law_enforcement_baseline": ["cjis", "law enforcement", "fbi"],
1843
+ "startup": ["startup", "mvp", "lean", "fast iteration"],
1844
+ }
1845
+
1846
+ suggested_templates = []
1847
+ for template, keywords in template_signals.items():
1848
+ if any(kw in lower for kw in keywords):
1849
+ suggested_templates.append(template)
1850
+
1851
+ return {
1852
+ "profile_detected": len(detected_dimensions) > 0,
1853
+ "detected_dimensions": sorted(detected_dimensions),
1854
+ "dimension_count": len(detected_dimensions),
1855
+ "suggested_templates": suggested_templates,
1856
+ }
1857
+
1858
+
1859
+ def _detect_ai_governance_signals(text, session_data=None):
1860
+ """Detect AI governance signals from customer text (D322).
1861
+
1862
+ Auto-triggers for federal agencies per OMB M-25-21 and any AI/ML mention.
1863
+ Detects 6 governance pillar keywords for targeted follow-up questions.
1864
+ """
1865
+ lower = text.lower()
1866
+ ai_governance_detected = False
1867
+ detected_pillars = []
1868
+ federal_agency_detected = False
1869
+
1870
+ # AI/ML mention keywords — auto-trigger governance (D322)
1871
+ ai_ml_keywords = [
1872
+ "ai system", "machine learning", "ml model", "deep learning",
1873
+ "neural network", "natural language processing", "nlp",
1874
+ "computer vision", "recommendation engine", "predictive model",
1875
+ "automated decision", "algorithmic", "chatbot", "virtual assistant",
1876
+ "generative ai", "large language model", "llm", "foundation model",
1877
+ ]
1878
+ if any(kw in lower for kw in ai_ml_keywords):
1879
+ ai_governance_detected = True
1880
+
1881
+ # Federal agency keywords — auto-trigger per OMB M-25-21
1882
+ federal_keywords = [
1883
+ "federal agency", "omb", "executive order", "federal government",
1884
+ "government agency", "gsa", "irs", "fda", "epa", "usda",
1885
+ "hhs", "dhs", "dot", "hud", "ed.gov", "va ", "opm",
1886
+ ]
1887
+ if any(kw in lower for kw in federal_keywords):
1888
+ federal_agency_detected = True
1889
+ ai_governance_detected = True
1890
+
1891
+ # Also check session customer_org for federal indicators
1892
+ if session_data:
1893
+ org = (session_data.get("customer_org") or "").lower()
1894
+ if any(kw in org for kw in ["federal", "agency", "government", "gsa",
1895
+ "omb", "dod", "defense", "military"]):
1896
+ federal_agency_detected = True
1897
+ ai_governance_detected = True
1898
+
1899
+ # Governance pillar keywords (from ai_governance_config.yaml)
1900
+ pillar_keywords = {
1901
+ "ai_inventory": [
1902
+ "ai system", "machine learning", "ml model", "deep learning",
1903
+ "neural network", "nlp", "computer vision", "recommendation engine",
1904
+ "predictive model", "automated decision", "algorithmic", "chatbot",
1905
+ "generative ai", "llm", "foundation model",
1906
+ ],
1907
+ "model_documentation": [
1908
+ "model card", "model documentation", "training data",
1909
+ "model performance", "model accuracy", "model bias",
1910
+ "model validation", "model versioning",
1911
+ ],
1912
+ "human_oversight": [
1913
+ "human oversight", "human in the loop", "human on the loop",
1914
+ "manual review", "human approval", "override capability",
1915
+ "escalation", "appeal process",
1916
+ ],
1917
+ "impact_assessment": [
1918
+ "impact assessment", "rights impacting", "safety critical",
1919
+ "high risk ai", "algorithmic impact", "disparate impact",
1920
+ "bias assessment", "fairness",
1921
+ ],
1922
+ "transparency": [
1923
+ "transparency", "explainability", "interpretability",
1924
+ "notice", "disclosure", "ai disclosure",
1925
+ ],
1926
+ "accountability": [
1927
+ "accountability", "responsible ai", "caio",
1928
+ "chief ai officer", "ai governance", "ethics review",
1929
+ "incident response",
1930
+ ],
1931
+ }
1932
+
1933
+ for pillar, keywords in pillar_keywords.items():
1934
+ if any(kw in lower for kw in keywords):
1935
+ detected_pillars.append(pillar)
1936
+ ai_governance_detected = True
1937
+
1938
+ return {
1939
+ "ai_governance_detected": ai_governance_detected,
1940
+ "federal_agency_detected": federal_agency_detected,
1941
+ "detected_pillars": sorted(detected_pillars),
1942
+ "pillar_count": len(detected_pillars),
1943
+ }
1944
+
1945
+
1946
+ def _quick_readiness_estimate(session_id, conn):
1947
+ """Quick readiness estimate based on requirement counts and quality."""
1948
+ reqs = conn.execute(
1949
+ "SELECT * FROM intake_requirements WHERE session_id = ?",
1950
+ (session_id,),
1951
+ ).fetchall()
1952
+
1953
+ total = len(reqs)
1954
+ if total == 0:
1955
+ return {"overall": 0.0, "completeness": 0.0, "clarity": 1.0,
1956
+ "feasibility": 0.5, "compliance": 0.0, "testability": 0.0}
1957
+
1958
+ # Completeness: check if we have multiple types
1959
+ types = set(dict(r)["requirement_type"] for r in reqs)
1960
+ type_coverage = len(types) / 6.0 # 6 major types
1961
+ completeness = min(1.0, type_coverage * (min(total, 20) / 20.0))
1962
+
1963
+ # Clarity: based on unresolved ambiguities vs total requirements
1964
+ # Resolved = flagged but user has continued the conversation (addressed it)
1965
+ sess_row = conn.execute(
1966
+ "SELECT ambiguity_count, context_summary FROM intake_sessions WHERE id = ?",
1967
+ (session_id,),
1968
+ ).fetchone()
1969
+ sess_dict = dict(sess_row) if sess_row else {}
1970
+ amb_count = sess_dict.get("ambiguity_count", 0)
1971
+ ctx = {}
1972
+ try:
1973
+ ctx = json.loads(sess_dict.get("context_summary") or "{}")
1974
+ except (ValueError, TypeError):
1975
+ pass
1976
+ flagged = ctx.get("flagged_ambiguities", [])
1977
+ # Count user turns after ambiguities were first flagged as clarification
1978
+ turn_count = conn.execute(
1979
+ "SELECT COUNT(*) as cnt FROM intake_conversation "
1980
+ "WHERE session_id = ? AND role = 'customer'",
1981
+ (session_id,),
1982
+ ).fetchone()["cnt"]
1983
+ # Each user turn after the first resolves ambiguity somewhat
1984
+ resolved_credit = min(len(flagged), max(0, turn_count - 1)) if flagged else 0
1985
+ unresolved = max(0, len(flagged) - resolved_credit)
1986
+ # Clarity starts at 50% (baseline for having requirements), penalized by
1987
+ # unresolved ambiguities, boosted by conversation depth
1988
+ clarity_base = 0.50
1989
+ penalty = min(0.40, unresolved * 0.15)
1990
+ depth_bonus = min(0.50, turn_count * 0.05) # each turn adds 5%, up to 50%
1991
+ clarity = min(1.0, max(0.0, clarity_base - penalty + depth_bonus))
1992
+
1993
+ # Feasibility: assume 0.5 without architect review
1994
+ feasibility = 0.5
1995
+
1996
+ # Compliance: check selected frameworks + security-type requirements
1997
+ context = {}
1998
+ try:
1999
+ ctx_row = conn.execute(
2000
+ "SELECT context_summary FROM intake_sessions WHERE id = ?",
2001
+ (session_id,),
2002
+ ).fetchone()
2003
+ if ctx_row:
2004
+ context = json.loads(dict(ctx_row).get("context_summary") or "{}")
2005
+ except (ValueError, TypeError):
2006
+ pass
2007
+ selected_fw = context.get("selected_frameworks", [])
2008
+ sec_reqs = sum(1 for r in reqs if dict(r)["requirement_type"] in ("security", "compliance"))
2009
+
2010
+ if selected_fw:
2011
+ # Selecting frameworks IS the compliance declaration — full credit.
2012
+ compliance = 1.0
2013
+ else:
2014
+ compliance = min(1.0, sec_reqs / max(3, 1))
2015
+
2016
+ # Testability: check for acceptance criteria (BDD/Gherkin stored during turn)
2017
+ with_criteria = 0
2018
+ for r in reqs:
2019
+ rd = dict(r)
2020
+ ac = rd.get("acceptance_criteria") or ""
2021
+ if ac.strip():
2022
+ with_criteria += 1
2023
+ testability = with_criteria / max(total, 1)
2024
+
2025
+ config = _load_config()
2026
+ weights = config.get("ricoas", {}).get("readiness_weights", {
2027
+ "completeness": 0.25, "clarity": 0.25, "feasibility": 0.20,
2028
+ "compliance": 0.15, "testability": 0.15,
2029
+ })
2030
+
2031
+ overall = (
2032
+ completeness * weights.get("completeness", 0.25) +
2033
+ clarity * weights.get("clarity", 0.25) +
2034
+ feasibility * weights.get("feasibility", 0.20) +
2035
+ compliance * weights.get("compliance", 0.15) +
2036
+ testability * weights.get("testability", 0.15)
2037
+ )
2038
+
2039
+ return {
2040
+ "overall": round(overall, 3),
2041
+ "completeness": round(completeness, 3),
2042
+ "clarity": round(clarity, 3),
2043
+ "feasibility": round(feasibility, 3),
2044
+ "compliance": round(compliance, 3),
2045
+ "testability": round(testability, 3),
2046
+ }
2047
+
2048
+
2049
+ # ---------------------------------------------------------------------------
2050
+ # Export
2051
+ # ---------------------------------------------------------------------------
2052
+
2053
+ def export_requirements(session_id: str, db_path=None) -> dict:
2054
+ """Export all requirements from a session as structured JSON."""
2055
+ conn = get_connection(db_path=db_path)
2056
+ reqs = conn.execute(
2057
+ "SELECT * FROM intake_requirements WHERE session_id = ? ORDER BY created_at",
2058
+ (session_id,),
2059
+ ).fetchall()
2060
+
2061
+ session = conn.execute(
2062
+ "SELECT * FROM intake_sessions WHERE id = ?", (session_id,)
2063
+ ).fetchone()
2064
+ conn.close()
2065
+
2066
+ if not session:
2067
+ raise ValueError(f"Session '{session_id}' not found.")
2068
+
2069
+ return {
2070
+ "status": "ok",
2071
+ "session_id": session_id,
2072
+ "project_id": dict(session).get("project_id"),
2073
+ "customer_name": dict(session).get("customer_name"),
2074
+ "impact_level": dict(session).get("impact_level"),
2075
+ "readiness_score": dict(session).get("readiness_score", 0.0),
2076
+ "total_requirements": len(reqs),
2077
+ "requirements": [dict(r) for r in reqs],
2078
+ "exported_at": datetime.now(timezone.utc).isoformat(),
2079
+ }
2080
+
2081
+
2082
+ # ---------------------------------------------------------------------------
2083
+ # CLI
2084
+ # ---------------------------------------------------------------------------
2085
+
2086
+ def main():
2087
+ parser = argparse.ArgumentParser(
2088
+ description="SPARKPILOT Requirements Intake Engine"
2089
+ )
2090
+ parser.add_argument("--project-id", help="SPARKPILOT project ID")
2091
+ parser.add_argument("--session-id", help="Existing session ID")
2092
+ parser.add_argument("--customer-name", help="Customer name (for new session)")
2093
+ parser.add_argument("--customer-org", help="Customer organization")
2094
+ parser.add_argument(
2095
+ "--impact-level",
2096
+ choices=["IL2", "IL4", "IL5", "IL6"],
2097
+ default="IL5",
2098
+ help="Classification impact level",
2099
+ )
2100
+ parser.add_argument(
2101
+ "--classification",
2102
+ choices=["CUI", "FOUO", "Public", "SECRET", "TOP_SECRET", "NONE"],
2103
+ default=None,
2104
+ help="Data classification override (default: resolved from project)",
2105
+ )
2106
+ parser.add_argument("--message", help="Customer message (single turn)")
2107
+ parser.add_argument("--resume", action="store_true", help="Resume paused session")
2108
+ parser.add_argument("--pause", action="store_true", help="Pause active session")
2109
+ parser.add_argument("--score-readiness", action="store_true", help="Score readiness")
2110
+ parser.add_argument("--export", action="store_true", help="Export requirements")
2111
+ parser.add_argument("--status", action="store_true", help="Get session status")
2112
+ parser.add_argument("--json", action="store_true", help="JSON output")
2113
+ args = parser.parse_args()
2114
+
2115
+ try:
2116
+ result = None
2117
+
2118
+ if args.session_id and args.resume:
2119
+ result = resume_session(args.session_id)
2120
+
2121
+ elif args.session_id and args.pause:
2122
+ result = pause_session(args.session_id)
2123
+
2124
+ elif args.session_id and args.message:
2125
+ result = process_turn(args.session_id, args.message)
2126
+
2127
+ elif args.session_id and args.score_readiness:
2128
+ conn = get_connection()
2129
+ readiness = _quick_readiness_estimate(args.session_id, conn)
2130
+ conn.close()
2131
+ result = {"status": "ok", "session_id": args.session_id, "readiness": readiness}
2132
+
2133
+ elif args.session_id and args.export:
2134
+ result = export_requirements(args.session_id)
2135
+
2136
+ elif args.session_id and args.status:
2137
+ result = get_session(args.session_id)
2138
+
2139
+ elif args.customer_name and args.project_id:
2140
+ # Resolve classification: NONE -> "PUBLIC", None -> resolve from project
2141
+ cls_override = args.classification
2142
+ if cls_override == "NONE":
2143
+ cls_override = "PUBLIC"
2144
+ result = create_session(
2145
+ project_id=args.project_id,
2146
+ customer_name=args.customer_name,
2147
+ customer_org=args.customer_org,
2148
+ impact_level=args.impact_level,
2149
+ classification=cls_override,
2150
+ )
2151
+
2152
+ else:
2153
+ parser.print_help()
2154
+ return
2155
+
2156
+ if args.json:
2157
+ print(json.dumps(result, indent=2, default=str))
2158
+ else:
2159
+ if "message" in result:
2160
+ print(result["message"])
2161
+ elif "analyst_response" in result:
2162
+ print(result["analyst_response"])
2163
+ else:
2164
+ print(json.dumps(result, indent=2, default=str))
2165
+
2166
+ except (ValueError, FileNotFoundError) as e:
2167
+ if args.json:
2168
+ print(json.dumps({"error": str(e)}, indent=2))
2169
+ else:
2170
+ print(f"Error: {e}")
2171
+ raise SystemExit(1)
2172
+
2173
+
2174
+ if __name__ == "__main__":
2175
+ main()