devflow-engine 1.0.0__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 (393) hide show
  1. devflow_engine/__init__.py +3 -0
  2. devflow_engine/agentic_prompts.py +100 -0
  3. devflow_engine/agentic_runtime.py +398 -0
  4. devflow_engine/api_key_flow_harness.py +539 -0
  5. devflow_engine/api_keys.py +357 -0
  6. devflow_engine/bootstrap/__init__.py +2 -0
  7. devflow_engine/bootstrap/provision_from_template.py +84 -0
  8. devflow_engine/cli/__init__.py +0 -0
  9. devflow_engine/cli/app.py +7270 -0
  10. devflow_engine/core/__init__.py +0 -0
  11. devflow_engine/core/config.py +86 -0
  12. devflow_engine/core/logging.py +29 -0
  13. devflow_engine/core/paths.py +45 -0
  14. devflow_engine/core/toml_kv.py +33 -0
  15. devflow_engine/devflow_event_worker.py +1292 -0
  16. devflow_engine/devflow_state.py +201 -0
  17. devflow_engine/devin2/__init__.py +9 -0
  18. devflow_engine/devin2/agent_definition.py +120 -0
  19. devflow_engine/devin2/pi_runner.py +204 -0
  20. devflow_engine/devin_orchestration.py +69 -0
  21. devflow_engine/docs/prompts/anti-patterns.md +42 -0
  22. devflow_engine/docs/prompts/devin-agent-prompt.md +55 -0
  23. devflow_engine/docs/prompts/devin2-agent-prompt.md +81 -0
  24. devflow_engine/docs/prompts/examples/devin-vapi-clone-reference-exchange.json +85 -0
  25. devflow_engine/doctor/__init__.py +2 -0
  26. devflow_engine/doctor/triage.py +140 -0
  27. devflow_engine/error/__init__.py +0 -0
  28. devflow_engine/error/remediation.py +21 -0
  29. devflow_engine/errors/error_solver_dag.py +522 -0
  30. devflow_engine/errors/runtime_observability.py +67 -0
  31. devflow_engine/idea/__init__.py +4 -0
  32. devflow_engine/idea/actors.py +481 -0
  33. devflow_engine/idea/agentic.py +465 -0
  34. devflow_engine/idea/analyze.py +93 -0
  35. devflow_engine/idea/devin_chat_dag.py +1 -0
  36. devflow_engine/idea/diff.py +99 -0
  37. devflow_engine/idea/drafts.py +446 -0
  38. devflow_engine/idea/idea_creation_dag.py +643 -0
  39. devflow_engine/idea/ideation_enrichment.py +355 -0
  40. devflow_engine/idea/ideation_enrichment_worker.py +19 -0
  41. devflow_engine/idea/paths.py +28 -0
  42. devflow_engine/idea/promote.py +53 -0
  43. devflow_engine/idea/redaction.py +27 -0
  44. devflow_engine/idea/repo_tools.py +1277 -0
  45. devflow_engine/idea/response_mode.py +30 -0
  46. devflow_engine/idea/story_pipeline.py +1585 -0
  47. devflow_engine/idea/sufficiency.py +376 -0
  48. devflow_engine/idea/traditional_stories.py +1257 -0
  49. devflow_engine/implementation/__init__.py +0 -0
  50. devflow_engine/implementation/alembic_preflight.py +700 -0
  51. devflow_engine/implementation/dag.py +8450 -0
  52. devflow_engine/implementation/green_gate.py +93 -0
  53. devflow_engine/implementation/prompts.py +108 -0
  54. devflow_engine/implementation/test_runtime.py +623 -0
  55. devflow_engine/integration/__init__.py +19 -0
  56. devflow_engine/integration/agentic.py +66 -0
  57. devflow_engine/integration/dag.py +3539 -0
  58. devflow_engine/integration/prompts.py +114 -0
  59. devflow_engine/integration/supabase_schema.sql +31 -0
  60. devflow_engine/integration/supabase_sync.py +177 -0
  61. devflow_engine/llm/__init__.py +1 -0
  62. devflow_engine/llm/cli_one_shot.py +84 -0
  63. devflow_engine/llm/cli_stream.py +371 -0
  64. devflow_engine/llm/execution_context.py +26 -0
  65. devflow_engine/llm/invoke.py +1322 -0
  66. devflow_engine/llm/provider_api.py +304 -0
  67. devflow_engine/llm/repo_knowledge.py +588 -0
  68. devflow_engine/llm_primitives.py +315 -0
  69. devflow_engine/orchestration.py +62 -0
  70. devflow_engine/planning/__init__.py +0 -0
  71. devflow_engine/planning/analyze_repo.py +92 -0
  72. devflow_engine/planning/render_drafts.py +133 -0
  73. devflow_engine/playground/__init__.py +0 -0
  74. devflow_engine/playground/hooks.py +26 -0
  75. devflow_engine/playwright_workflow/__init__.py +5 -0
  76. devflow_engine/playwright_workflow/dag.py +1317 -0
  77. devflow_engine/process/__init__.py +5 -0
  78. devflow_engine/process/dag.py +59 -0
  79. devflow_engine/project_registration/__init__.py +3 -0
  80. devflow_engine/project_registration/dag.py +1581 -0
  81. devflow_engine/project_registry.py +109 -0
  82. devflow_engine/prompts/devin/generic/prompt.md +6 -0
  83. devflow_engine/prompts/devin/ideation/prompt.md +263 -0
  84. devflow_engine/prompts/devin/ideation/scenarios.md +5 -0
  85. devflow_engine/prompts/devin/ideation_loop/prompt.md +6 -0
  86. devflow_engine/prompts/devin/insight/prompt.md +11 -0
  87. devflow_engine/prompts/devin/insight/scenarios.md +5 -0
  88. devflow_engine/prompts/devin/intake/prompt.md +15 -0
  89. devflow_engine/prompts/devin/iterate/prompt.md +12 -0
  90. devflow_engine/prompts/devin/shared/eval_doctrine.md +9 -0
  91. devflow_engine/prompts/devin/shared/principles.md +246 -0
  92. devflow_engine/prompts/devin_eval/assessment/prompt.md +18 -0
  93. devflow_engine/prompts/idea/api_ideation_agent/prompt.md +8 -0
  94. devflow_engine/prompts/idea/api_insight_agent/prompt.md +8 -0
  95. devflow_engine/prompts/idea/response_doctrine/prompt.md +18 -0
  96. devflow_engine/prompts/implementation/dependency_assessment/prompt.md +12 -0
  97. devflow_engine/prompts/implementation/green/green/prompt.md +11 -0
  98. devflow_engine/prompts/implementation/green/node_config/prompt.md +3 -0
  99. devflow_engine/prompts/implementation/green_review/outcome_review/prompt.md +5 -0
  100. devflow_engine/prompts/implementation/green_review/prior_run_review/prompt.md +5 -0
  101. devflow_engine/prompts/implementation/red/prompt.md +27 -0
  102. devflow_engine/prompts/implementation/redreview/prompt.md +23 -0
  103. devflow_engine/prompts/implementation/redreview_repair/prompt.md +16 -0
  104. devflow_engine/prompts/implementation/setupdoc/prompt.md +10 -0
  105. devflow_engine/prompts/implementation/story_planning/prompt.md +13 -0
  106. devflow_engine/prompts/implementation/test_design/prompt.md +27 -0
  107. devflow_engine/prompts/integration/README.md +185 -0
  108. devflow_engine/prompts/integration/green/example.md +67 -0
  109. devflow_engine/prompts/integration/green/green/prompt.md +10 -0
  110. devflow_engine/prompts/integration/green/node_config/prompt.md +42 -0
  111. devflow_engine/prompts/integration/green/past_prompts/20260417T212300/green/prompt.md +15 -0
  112. devflow_engine/prompts/integration/green/past_prompts/20260417T212300/node_config/prompt.md +42 -0
  113. devflow_engine/prompts/integration/green_enrich/example.md +79 -0
  114. devflow_engine/prompts/integration/green_enrich/green_enrich/prompt.md +9 -0
  115. devflow_engine/prompts/integration/green_enrich/node_config/prompt.md +41 -0
  116. devflow_engine/prompts/integration/green_enrich/past_prompts/20260417T212300/green_enrich/prompt.md +14 -0
  117. devflow_engine/prompts/integration/green_enrich/past_prompts/20260417T212300/node_config/prompt.md +41 -0
  118. devflow_engine/prompts/integration/red/code_repair/prompt.md +12 -0
  119. devflow_engine/prompts/integration/red/example.md +152 -0
  120. devflow_engine/prompts/integration/red/node_config/prompt.md +86 -0
  121. devflow_engine/prompts/integration/red/past_prompts/20260417T212300/code_repair/prompt.md +19 -0
  122. devflow_engine/prompts/integration/red/past_prompts/20260417T212300/node_config/prompt.md +84 -0
  123. devflow_engine/prompts/integration/red/past_prompts/20260417T212300/red/prompt.md +16 -0
  124. devflow_engine/prompts/integration/red/past_prompts/20260417T212300/red_repair/prompt.md +15 -0
  125. devflow_engine/prompts/integration/red/past_prompts/20260417T215032/code_repair/prompt.md +10 -0
  126. devflow_engine/prompts/integration/red/past_prompts/20260417T215032/node_config/prompt.md +84 -0
  127. devflow_engine/prompts/integration/red/past_prompts/20260417T215032/red_repair/prompt.md +11 -0
  128. devflow_engine/prompts/integration/red/red/prompt.md +11 -0
  129. devflow_engine/prompts/integration/red/red_repair/prompt.md +12 -0
  130. devflow_engine/prompts/integration/red_review/example.md +71 -0
  131. devflow_engine/prompts/integration/red_review/node_config/prompt.md +41 -0
  132. devflow_engine/prompts/integration/red_review/past_prompts/20260417T212300/node_config/prompt.md +41 -0
  133. devflow_engine/prompts/integration/red_review/past_prompts/20260417T212300/red_review/prompt.md +15 -0
  134. devflow_engine/prompts/integration/red_review/red_review/prompt.md +9 -0
  135. devflow_engine/prompts/integration/resolve/example.md +111 -0
  136. devflow_engine/prompts/integration/resolve/node_config/prompt.md +64 -0
  137. devflow_engine/prompts/integration/resolve/past_prompts/20260417T212300/node_config/prompt.md +64 -0
  138. devflow_engine/prompts/integration/resolve/past_prompts/20260417T212300/resolve_implicated_users/prompt.md +15 -0
  139. devflow_engine/prompts/integration/resolve/past_prompts/20260417T212300/resolve_side_effects/prompt.md +15 -0
  140. devflow_engine/prompts/integration/resolve/resolve_implicated_users/prompt.md +10 -0
  141. devflow_engine/prompts/integration/resolve/resolve_side_effects/prompt.md +10 -0
  142. devflow_engine/prompts/integration/validate/build_idea_acceptance_coverage/prompt.md +12 -0
  143. devflow_engine/prompts/integration/validate/code_repair/prompt.md +13 -0
  144. devflow_engine/prompts/integration/validate/example.md +143 -0
  145. devflow_engine/prompts/integration/validate/node_config/prompt.md +87 -0
  146. devflow_engine/prompts/integration/validate/past_prompts/20260417T212300/code_repair/prompt.md +19 -0
  147. devflow_engine/prompts/integration/validate/past_prompts/20260417T212300/node_config/prompt.md +67 -0
  148. devflow_engine/prompts/integration/validate/past_prompts/20260417T212300/validate_enrich_gate/prompt.md +17 -0
  149. devflow_engine/prompts/integration/validate/past_prompts/20260417T212300/validate_repair/prompt.md +16 -0
  150. devflow_engine/prompts/integration/validate/past_prompts/20260417T215032/code_repair/prompt.md +10 -0
  151. devflow_engine/prompts/integration/validate/past_prompts/20260417T215032/node_config/prompt.md +67 -0
  152. devflow_engine/prompts/integration/validate/past_prompts/20260417T215032/validate_repair/prompt.md +9 -0
  153. devflow_engine/prompts/integration/validate/validate_enrich_gate/prompt.md +10 -0
  154. devflow_engine/prompts/integration/validate/validate_repair/prompt.md +20 -0
  155. devflow_engine/prompts/integration/write_workflows/example.md +100 -0
  156. devflow_engine/prompts/integration/write_workflows/node_config/prompt.md +44 -0
  157. devflow_engine/prompts/integration/write_workflows/past_prompts/20260417T212300/node_config/prompt.md +44 -0
  158. devflow_engine/prompts/integration/write_workflows/past_prompts/20260417T212300/write_workflows/prompt.md +17 -0
  159. devflow_engine/prompts/integration/write_workflows/write_workflows/prompt.md +11 -0
  160. devflow_engine/prompts/iterate/README.md +7 -0
  161. devflow_engine/prompts/iterate/coder/prompt.md +11 -0
  162. devflow_engine/prompts/iterate/framer/prompt.md +11 -0
  163. devflow_engine/prompts/iterate/iterator/prompt.md +13 -0
  164. devflow_engine/prompts/iterate/observer/prompt.md +11 -0
  165. devflow_engine/prompts/recovery/diagnosis/prompt.md +7 -0
  166. devflow_engine/prompts/recovery/execution/prompt.md +8 -0
  167. devflow_engine/prompts/recovery/execution_verification/prompt.md +7 -0
  168. devflow_engine/prompts/recovery/failure_investigation/prompt.md +10 -0
  169. devflow_engine/prompts/recovery/preflight_health_repo_repair/prompt.md +8 -0
  170. devflow_engine/prompts/recovery/remediation_execution/prompt.md +11 -0
  171. devflow_engine/prompts/recovery/root_cause_investigation/prompt.md +12 -0
  172. devflow_engine/prompts/scope_idea/doctrine/prompt.md +7 -0
  173. devflow_engine/prompts/source_doc_eval/document/prompt.md +6 -0
  174. devflow_engine/prompts/source_doc_eval/targeted_mutation/prompt.md +9 -0
  175. devflow_engine/prompts/source_doc_mutation/domain_entities/prompt.md +6 -0
  176. devflow_engine/prompts/source_doc_mutation/product_brief/prompt.md +6 -0
  177. devflow_engine/prompts/source_doc_mutation/project_doc_coherence/prompt.md +7 -0
  178. devflow_engine/prompts/source_doc_mutation/project_doc_render/prompt.md +9 -0
  179. devflow_engine/prompts/source_doc_mutation/source_doc_coherence/prompt.md +5 -0
  180. devflow_engine/prompts/source_doc_mutation/source_doc_enrichment_coherence/prompt.md +6 -0
  181. devflow_engine/prompts/source_doc_mutation/user_workflows/prompt.md +6 -0
  182. devflow_engine/prompts/source_scope/doctrine/prompt.md +10 -0
  183. devflow_engine/prompts/ui_grounding/doctrine/prompt.md +7 -0
  184. devflow_engine/recovery/__init__.py +3 -0
  185. devflow_engine/recovery/dag.py +2609 -0
  186. devflow_engine/recovery/models.py +220 -0
  187. devflow_engine/refactor.py +93 -0
  188. devflow_engine/registry/__init__.py +1 -0
  189. devflow_engine/registry/cards.py +238 -0
  190. devflow_engine/registry/domain_normalize.py +60 -0
  191. devflow_engine/registry/effects.py +65 -0
  192. devflow_engine/registry/enforce_report.py +150 -0
  193. devflow_engine/registry/module_cards_classify.py +164 -0
  194. devflow_engine/registry/module_cards_draft.py +184 -0
  195. devflow_engine/registry/module_cards_gate.py +59 -0
  196. devflow_engine/registry/packages.py +347 -0
  197. devflow_engine/registry/pathways.py +323 -0
  198. devflow_engine/review/__init__.py +11 -0
  199. devflow_engine/review/dag.py +588 -0
  200. devflow_engine/review/review_story.py +67 -0
  201. devflow_engine/scope_idea/__init__.py +3 -0
  202. devflow_engine/scope_idea/agentic.py +39 -0
  203. devflow_engine/scope_idea/dag.py +1069 -0
  204. devflow_engine/scope_idea/models.py +175 -0
  205. devflow_engine/skills/builtins/devflow/queue_failure_investigation/SKILL.md +112 -0
  206. devflow_engine/skills/builtins/devflow/queue_idea_to_story/SKILL.md +120 -0
  207. devflow_engine/skills/builtins/devflow/queue_integration/SKILL.md +105 -0
  208. devflow_engine/skills/builtins/devflow/queue_recovery/SKILL.md +108 -0
  209. devflow_engine/skills/builtins/devflow/queue_runtime_core/SKILL.md +155 -0
  210. devflow_engine/skills/builtins/devflow/queue_story_implementation/SKILL.md +122 -0
  211. devflow_engine/skills/builtins/devin/idea_to_story_handoff/SKILL.md +120 -0
  212. devflow_engine/skills/builtins/devin/ideation/SKILL.md +168 -0
  213. devflow_engine/skills/builtins/devin/ideation/state-and-phrasing-reference.md +18 -0
  214. devflow_engine/skills/builtins/devin/insight/SKILL.md +22 -0
  215. devflow_engine/skills/registry.example.yaml +42 -0
  216. devflow_engine/source_doc_assumptions.py +291 -0
  217. devflow_engine/source_doc_mutation_dag.py +1606 -0
  218. devflow_engine/source_doc_mutation_eval.py +417 -0
  219. devflow_engine/source_doc_mutation_worker.py +25 -0
  220. devflow_engine/source_docs_schema.py +207 -0
  221. devflow_engine/source_docs_updater.py +309 -0
  222. devflow_engine/source_scope/__init__.py +15 -0
  223. devflow_engine/source_scope/agentic.py +45 -0
  224. devflow_engine/source_scope/dag.py +1626 -0
  225. devflow_engine/source_scope/models.py +177 -0
  226. devflow_engine/stores/__init__.py +0 -0
  227. devflow_engine/stores/execution_store.py +3534 -0
  228. devflow_engine/story/__init__.py +0 -0
  229. devflow_engine/story/contracts.py +160 -0
  230. devflow_engine/story/discovery.py +47 -0
  231. devflow_engine/story/evidence.py +118 -0
  232. devflow_engine/story/hashing.py +27 -0
  233. devflow_engine/story/implemented_queue_purge.py +148 -0
  234. devflow_engine/story/indexer.py +105 -0
  235. devflow_engine/story/io.py +20 -0
  236. devflow_engine/story/markdown_contracts.py +298 -0
  237. devflow_engine/story/reconciliation.py +408 -0
  238. devflow_engine/story/validate_stories.py +149 -0
  239. devflow_engine/story/validate_tests_story.py +512 -0
  240. devflow_engine/story/validation.py +133 -0
  241. devflow_engine/ui_grounding/__init__.py +11 -0
  242. devflow_engine/ui_grounding/agentic.py +31 -0
  243. devflow_engine/ui_grounding/dag.py +874 -0
  244. devflow_engine/ui_grounding/models.py +224 -0
  245. devflow_engine/ui_grounding/pencil_bridge.py +247 -0
  246. devflow_engine/vendor/__init__.py +0 -0
  247. devflow_engine/vendor/datalumina_genai/__init__.py +11 -0
  248. devflow_engine/vendor/datalumina_genai/core/__init__.py +0 -0
  249. devflow_engine/vendor/datalumina_genai/core/exceptions.py +9 -0
  250. devflow_engine/vendor/datalumina_genai/core/nodes/__init__.py +0 -0
  251. devflow_engine/vendor/datalumina_genai/core/nodes/agent.py +48 -0
  252. devflow_engine/vendor/datalumina_genai/core/nodes/agent_streaming_node.py +26 -0
  253. devflow_engine/vendor/datalumina_genai/core/nodes/base.py +89 -0
  254. devflow_engine/vendor/datalumina_genai/core/nodes/concurrent.py +30 -0
  255. devflow_engine/vendor/datalumina_genai/core/nodes/router.py +69 -0
  256. devflow_engine/vendor/datalumina_genai/core/schema.py +72 -0
  257. devflow_engine/vendor/datalumina_genai/core/task.py +52 -0
  258. devflow_engine/vendor/datalumina_genai/core/validate.py +139 -0
  259. devflow_engine/vendor/datalumina_genai/core/workflow.py +200 -0
  260. devflow_engine/worker.py +1086 -0
  261. devflow_engine/worker_guard.py +233 -0
  262. devflow_engine-1.0.0.dist-info/METADATA +235 -0
  263. devflow_engine-1.0.0.dist-info/RECORD +393 -0
  264. devflow_engine-1.0.0.dist-info/WHEEL +4 -0
  265. devflow_engine-1.0.0.dist-info/entry_points.txt +3 -0
  266. devin/__init__.py +6 -0
  267. devin/dag.py +58 -0
  268. devin/dag_two_arm.py +138 -0
  269. devin/devin_chat_scenario_catalog.json +588 -0
  270. devin/devin_eval.py +677 -0
  271. devin/nodes/__init__.py +0 -0
  272. devin/nodes/ideation/__init__.py +0 -0
  273. devin/nodes/ideation/node.py +195 -0
  274. devin/nodes/ideation/playground.py +267 -0
  275. devin/nodes/ideation/prompt.md +65 -0
  276. devin/nodes/ideation/scenarios/continue_refinement.py +13 -0
  277. devin/nodes/ideation/scenarios/continue_refinement_evals.py +18 -0
  278. devin/nodes/ideation/scenarios/idea_fits_existing_patterns.py +17 -0
  279. devin/nodes/ideation/scenarios/idea_fits_existing_patterns_evals.py +16 -0
  280. devin/nodes/ideation/scenarios/large_idea_split.py +4 -0
  281. devin/nodes/ideation/scenarios/large_idea_split_evals.py +17 -0
  282. devin/nodes/ideation/scenarios/source_documentation_added.py +4 -0
  283. devin/nodes/ideation/scenarios/source_documentation_added_evals.py +16 -0
  284. devin/nodes/ideation/scenarios/user_says_create_it.py +30 -0
  285. devin/nodes/ideation/scenarios/user_says_create_it_evals.py +23 -0
  286. devin/nodes/ideation/scenarios/vague_idea.py +16 -0
  287. devin/nodes/ideation/scenarios/vague_idea_evals.py +47 -0
  288. devin/nodes/ideation/tools.json +312 -0
  289. devin/nodes/insight/__init__.py +0 -0
  290. devin/nodes/insight/node.py +49 -0
  291. devin/nodes/insight/playground.py +154 -0
  292. devin/nodes/insight/prompt.md +61 -0
  293. devin/nodes/insight/scenarios/architecture_pattern_query.py +15 -0
  294. devin/nodes/insight/scenarios/architecture_pattern_query_evals.py +25 -0
  295. devin/nodes/insight/scenarios/codebase_exploration.py +15 -0
  296. devin/nodes/insight/scenarios/codebase_exploration_evals.py +23 -0
  297. devin/nodes/insight/scenarios/devin_ideation_routing.py +19 -0
  298. devin/nodes/insight/scenarios/devin_ideation_routing_evals.py +39 -0
  299. devin/nodes/insight/scenarios/devin_insight_routing.py +20 -0
  300. devin/nodes/insight/scenarios/devin_insight_routing_evals.py +40 -0
  301. devin/nodes/insight/scenarios/operational_debugging.py +15 -0
  302. devin/nodes/insight/scenarios/operational_debugging_evals.py +23 -0
  303. devin/nodes/insight/scenarios/operational_question.py +9 -0
  304. devin/nodes/insight/scenarios/operational_question_evals.py +8 -0
  305. devin/nodes/insight/scenarios/queue_status.py +15 -0
  306. devin/nodes/insight/scenarios/queue_status_evals.py +23 -0
  307. devin/nodes/insight/scenarios/source_doc_explanation.py +14 -0
  308. devin/nodes/insight/scenarios/source_doc_explanation_evals.py +21 -0
  309. devin/nodes/insight/scenarios/worker_state_check.py +15 -0
  310. devin/nodes/insight/scenarios/worker_state_check_evals.py +22 -0
  311. devin/nodes/insight/tools.json +126 -0
  312. devin/nodes/intake/__init__.py +0 -0
  313. devin/nodes/intake/node.py +27 -0
  314. devin/nodes/intake/playground.py +47 -0
  315. devin/nodes/intake/prompt.md +12 -0
  316. devin/nodes/intake/scenarios/ideation_routing.py +4 -0
  317. devin/nodes/intake/scenarios/ideation_routing_evals.py +5 -0
  318. devin/nodes/intake/scenarios/insight_routing.py +4 -0
  319. devin/nodes/intake/scenarios/insight_routing_evals.py +5 -0
  320. devin/nodes/iterate/README.md +44 -0
  321. devin/nodes/iterate/__init__.py +1 -0
  322. devin/nodes/iterate/_archived_design_stages/01-objectives-requirements.md +112 -0
  323. devin/nodes/iterate/_archived_design_stages/02-evals.md +131 -0
  324. devin/nodes/iterate/_archived_design_stages/03-tools-and-boundaries.md +110 -0
  325. devin/nodes/iterate/_archived_design_stages/04-harness-and-playground.md +32 -0
  326. devin/nodes/iterate/_archived_design_stages/05-prompt-deferred.md +11 -0
  327. devin/nodes/iterate/_archived_design_stages/coder_agent_design/01-objectives-requirements.md +20 -0
  328. devin/nodes/iterate/_archived_design_stages/coder_agent_design/02-evals.md +8 -0
  329. devin/nodes/iterate/_archived_design_stages/coder_agent_design/03-tools-and-boundaries.md +14 -0
  330. devin/nodes/iterate/_archived_design_stages/coder_agent_design/04-harness-and-playground.md +12 -0
  331. devin/nodes/iterate/_archived_design_stages/framer_agent_design/01-objectives-requirements.md +20 -0
  332. devin/nodes/iterate/_archived_design_stages/framer_agent_design/02-evals.md +8 -0
  333. devin/nodes/iterate/_archived_design_stages/framer_agent_design/03-tools-and-boundaries.md +13 -0
  334. devin/nodes/iterate/_archived_design_stages/framer_agent_design/04-harness-and-playground.md +12 -0
  335. devin/nodes/iterate/_archived_design_stages/iterator_agent_design/01-objectives-requirements.md +25 -0
  336. devin/nodes/iterate/_archived_design_stages/iterator_agent_design/02-evals.md +9 -0
  337. devin/nodes/iterate/_archived_design_stages/iterator_agent_design/03-tools-and-boundaries.md +14 -0
  338. devin/nodes/iterate/_archived_design_stages/iterator_agent_design/04-harness-and-playground.md +12 -0
  339. devin/nodes/iterate/_archived_design_stages/observer_agent_design/01-objectives-requirements.md +20 -0
  340. devin/nodes/iterate/_archived_design_stages/observer_agent_design/02-evals.md +8 -0
  341. devin/nodes/iterate/_archived_design_stages/observer_agent_design/03-tools-and-boundaries.md +14 -0
  342. devin/nodes/iterate/_archived_design_stages/observer_agent_design/04-harness-and-playground.md +13 -0
  343. devin/nodes/iterate/agent-roles.md +89 -0
  344. devin/nodes/iterate/agents/README.md +10 -0
  345. devin/nodes/iterate/artifacts.md +504 -0
  346. devin/nodes/iterate/contract.md +100 -0
  347. devin/nodes/iterate/eval-plan.md +74 -0
  348. devin/nodes/iterate/node.py +100 -0
  349. devin/nodes/iterate/pipeline/README.md +13 -0
  350. devin/nodes/iterate/playground-contract.md +76 -0
  351. devin/nodes/iterate/prompt.md +11 -0
  352. devin/nodes/iterate/scenarios/README.md +38 -0
  353. devin/nodes/iterate/scenarios/artifact-and-loop-scenarios.md +101 -0
  354. devin/nodes/iterate/scenarios/coder_artifact_alignment.py +32 -0
  355. devin/nodes/iterate/scenarios/coder_artifact_alignment_evals.py +45 -0
  356. devin/nodes/iterate/scenarios/coder_bounded_fix.py +27 -0
  357. devin/nodes/iterate/scenarios/coder_bounded_fix_evals.py +45 -0
  358. devin/nodes/iterate/scenarios/devin_iterate_routing.py +21 -0
  359. devin/nodes/iterate/scenarios/devin_iterate_routing_evals.py +36 -0
  360. devin/nodes/iterate/scenarios/framer_scope_boundary.py +25 -0
  361. devin/nodes/iterate/scenarios/framer_scope_boundary_evals.py +57 -0
  362. devin/nodes/iterate/scenarios/framer_task_framing.py +25 -0
  363. devin/nodes/iterate/scenarios/framer_task_framing_evals.py +58 -0
  364. devin/nodes/iterate/scenarios/iterate_error_fix.py +21 -0
  365. devin/nodes/iterate/scenarios/iterate_error_fix_evals.py +39 -0
  366. devin/nodes/iterate/scenarios/iterate_quick_change.py +21 -0
  367. devin/nodes/iterate/scenarios/iterate_quick_change_evals.py +35 -0
  368. devin/nodes/iterate/scenarios/iterate_to_idea_promotion.py +23 -0
  369. devin/nodes/iterate/scenarios/iterate_to_idea_promotion_evals.py +53 -0
  370. devin/nodes/iterate/scenarios/iterate_to_insight_reroute.py +23 -0
  371. devin/nodes/iterate/scenarios/iterate_to_insight_reroute_evals.py +53 -0
  372. devin/nodes/iterate/scenarios/observer_evidence_seam.py +28 -0
  373. devin/nodes/iterate/scenarios/observer_evidence_seam_evals.py +55 -0
  374. devin/nodes/iterate/scenarios/observer_repro_creation.py +28 -0
  375. devin/nodes/iterate/scenarios/observer_repro_creation_evals.py +45 -0
  376. devin/nodes/iterate/scenarios/routing-matrix.md +45 -0
  377. devin/nodes/shared/__init__.py +0 -0
  378. devin/nodes/shared/filemaker_expert.md +80 -0
  379. devin/nodes/shared/filemaker_expert.py +354 -0
  380. devin/nodes/shared/filemaker_expert_eval/runner.py +176 -0
  381. devin/nodes/shared/filemaker_expert_eval/scenarios.json +65 -0
  382. devin/nodes/shared/goldilocks_advisor_eval/runner.py +214 -0
  383. devin/nodes/shared/goldilocks_advisor_eval/scenarios.json +58 -0
  384. devin/nodes/shared/helpers.py +156 -0
  385. devin/nodes/shared/idea_compliance_advisor_eval/runner.py +252 -0
  386. devin/nodes/shared/idea_compliance_advisor_eval/scenarios.json +75 -0
  387. devin/nodes/shared/models.py +44 -0
  388. devin/nodes/shared/post.py +40 -0
  389. devin/nodes/shared/router.py +107 -0
  390. devin/nodes/shared/tools.py +191 -0
  391. devin/shared/devin-chat-rubric.md +237 -0
  392. devin/shared/devin-chat-scenario-suite.md +90 -0
  393. devin/shared/eval_doctrine.md +9 -0
@@ -0,0 +1,315 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import dataclass
5
+ from typing import Literal
6
+
7
+ PrimitiveName = Literal["idea", "story"]
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class LlmInputPrimitive:
12
+ name: PrimitiveName
13
+ purpose: str
14
+ use_when: list[str]
15
+ do_not_use_when: list[str]
16
+ required_fields: list[str]
17
+ optional_fields: list[str]
18
+ construction: list[str]
19
+ processing: list[str]
20
+ output_contract: list[str]
21
+
22
+ def as_dict(self) -> dict[str, object]:
23
+ return {
24
+ "name": self.name,
25
+ "purpose": self.purpose,
26
+ "use_when": self.use_when,
27
+ "do_not_use_when": self.do_not_use_when,
28
+ "required_fields": self.required_fields,
29
+ "optional_fields": self.optional_fields,
30
+ "construction": self.construction,
31
+ "processing": self.processing,
32
+ "output_contract": self.output_contract,
33
+ }
34
+
35
+
36
+ IDEA_PRIMITIVE = LlmInputPrimitive(
37
+ name="idea",
38
+ purpose=(
39
+ "Capture product or workflow intent before it becomes executable story work. "
40
+ "An idea is planning truth, not an implementation ticket."
41
+ ),
42
+ use_when=[
43
+ "The request introduces a new capability, workflow, product surface, or meaningful behavior area.",
44
+ "The user is still shaping outcomes, users, constraints, scope, or acceptance boundaries.",
45
+ "Success depends on deciding what should exist before deciding exactly what to change.",
46
+ ],
47
+ do_not_use_when=[
48
+ "The user asks for a bounded fix or small change to an existing surface; use story.",
49
+ "The user only asks for explanation, diagnosis, status, or repo inspection; answer directly.",
50
+ "The request is non-software work or has no DevFlow delivery implication.",
51
+ ],
52
+ required_fields=[
53
+ "idea_id: stable identifier for the idea artifact",
54
+ "problem: what user/business pain should become true or stop happening",
55
+ "target_users: concrete users/operators affected by the change",
56
+ "user_outcomes: observable outcomes those users need",
57
+ "scope: included and excluded behavior boundaries",
58
+ ],
59
+ optional_fields=[
60
+ "constraints: business, compliance, security, timeline, stack, or repo constraints",
61
+ "assumptions: explicit assumptions used to keep momentum when details are thin",
62
+ "source_refs: repo paths, source-doc paths, tickets, screenshots, transcripts, or notes",
63
+ "candidate_planes: delivery planes likely affected, such as api, ui, integrations, ops, auth",
64
+ ],
65
+ construction=[
66
+ "Prefer grounded assumptions over form-style questioning when the missing detail is agent-owned approach.",
67
+ (
68
+ "Ask only for user-owned truth: business outcome, UX intent, risk boundary, "
69
+ "approval rule, or domain constraint."
70
+ ),
71
+ "Keep the idea artifact stable enough that source docs and story generation can consume it later.",
72
+ "Record uncertainty as assumptions instead of hiding it in prose.",
73
+ ],
74
+ processing=[
75
+ "Normalize the user request into the required fields.",
76
+ "Evaluate whether the artifact is sufficient for downstream story creation.",
77
+ "If sufficient, persist or update the idea artifact under .devflow/ideas/<idea_id>/idea.json.",
78
+ "If not sufficient, return the smallest useful question and preserve the partial artifact.",
79
+ "When approved for delivery, feed the idea into the idea-to-story pipeline.",
80
+ ],
81
+ output_contract=[
82
+ "status: ready_for_story_generation | needs_clarification | not_applicable",
83
+ "idea: normalized idea payload",
84
+ "assumptions: explicit assumptions used",
85
+ "next_action: run_start | ask_user | answer_directly",
86
+ ],
87
+ )
88
+
89
+
90
+ STORY_PRIMITIVE = LlmInputPrimitive(
91
+ name="story",
92
+ purpose=(
93
+ "Describe one bounded executable change against an existing or approved target. "
94
+ "A story is implementation input with verification expectations."
95
+ ),
96
+ use_when=[
97
+ "The request is a concrete fix, small behavior change, or narrow improvement on an existing surface.",
98
+ "An approved idea has been decomposed into a delivery-sized unit.",
99
+ "The work can be verified with a scoped test, repro, acceptance check, or artifact review.",
100
+ ],
101
+ do_not_use_when=[
102
+ "The request still needs broad product/workflow shaping; use idea.",
103
+ "The user only wants read-only diagnosis or explanation; answer directly.",
104
+ "The change is too broad to validate as one bounded implementation unit.",
105
+ ],
106
+ required_fields=[
107
+ "story_id: stable identifier for queueing and execution",
108
+ "title: concise implementation-facing title",
109
+ "intent: what must change and why",
110
+ "scope: exact included and excluded work",
111
+ "acceptance_criteria: observable checks that define done",
112
+ "verification: tests, repro steps, commands, or review artifacts to prove completion",
113
+ ],
114
+ optional_fields=[
115
+ "source_idea_id: idea this story came from",
116
+ "plane_oracles: plane-specific verification anchors",
117
+ "repo_refs: paths, symbols, commands, logs, or screenshots grounding the change",
118
+ "risk_notes: security, compliance, migration, data, or ops risks",
119
+ ],
120
+ construction=[
121
+ "Keep one story to one delivery-sized change; split unrelated or multi-surface work.",
122
+ "State success as behavior and evidence, not as vague completion prose.",
123
+ "Include enough repo/source context for an implementation worker to start without reopening product planning.",
124
+ "Preserve ownership boundaries: the story defines target behavior; implementation chooses the local code path.",
125
+ ],
126
+ processing=[
127
+ "Validate the story contract and plane coverage.",
128
+ "Queue or execute the story through the implementation DAG.",
129
+ "Run the implementation stages through red, green, refactor, security, and commit gates as configured.",
130
+ "Record verification evidence and mark implemented only when the acceptance checks pass.",
131
+ "If blocked or too broad, return a blocker or promote back to idea instead of pretending completion.",
132
+ ],
133
+ output_contract=[
134
+ "status: ready_for_implementation | needs_more_story_context | promote_to_idea | not_applicable",
135
+ "story: normalized story payload",
136
+ "verification_plan: concrete proof path",
137
+ "next_action: run_start | ask_user | promote_to_idea | answer_directly",
138
+ ],
139
+ )
140
+
141
+
142
+ PRIMITIVES: dict[PrimitiveName, LlmInputPrimitive] = {
143
+ "idea": IDEA_PRIMITIVE,
144
+ "story": STORY_PRIMITIVE,
145
+ }
146
+
147
+
148
+ def render_llm_primitive_guidance(
149
+ primitive: PrimitiveName | Literal["all"] = "all",
150
+ *,
151
+ json_out: bool = False,
152
+ ) -> str:
153
+ selected = list(PRIMITIVES.values()) if primitive == "all" else [PRIMITIVES[primitive]]
154
+ if json_out:
155
+ payload = {
156
+ "version": "v0.02",
157
+ "agent_command_surface": _agent_command_surface(),
158
+ "input_primitives": [item.as_dict() for item in selected],
159
+ }
160
+ return json.dumps(payload, indent=2, sort_keys=True) + "\n"
161
+
162
+ blocks = [
163
+ "DevFlow LLM input primitives v0.02",
164
+ "",
165
+ "## Agent command surface",
166
+ (
167
+ "Use this small public surface from an agentic harness. Treat lower-level DAG, queue, "
168
+ "integration, review, eval, and worker debugging commands as internal unless the user "
169
+ "is explicitly debugging DevFlow itself."
170
+ ),
171
+ "",
172
+ "Project:",
173
+ "- devflow project add --path <repo> --name <name> --json",
174
+ "- devflow project remove <project_id> --yes",
175
+ "- devflow project status --project <project> --json",
176
+ "",
177
+ "Inputs:",
178
+ "- devflow idea submit --project <project> --from <idea.json> --json",
179
+ "- devflow story submit --project <project> --from <story.json> --json",
180
+ "",
181
+ "Run control:",
182
+ "- devflow run start --project <project> --json",
183
+ "- devflow run status --project <project> --json",
184
+ "- devflow run health --project <project> --json",
185
+ "- devflow doctor --project <project> --json",
186
+ "",
187
+ "Failure triage and repair target surface:",
188
+ "- devflow recovery run --project <project> --json",
189
+ "- devflow error solve --project <project> --json",
190
+ "- devflow error solve --project <project> --repro-command '<cmd>' --json",
191
+ "",
192
+ "Command doctrine:",
193
+ "- Submit idea when the work still needs product/workflow shaping.",
194
+ "- Submit story when the work is already a bounded implementation unit.",
195
+ "- After a ready submit, use run start and poll run health/status until idle, stuck, or ready.",
196
+ "- When run health reports a stuck or failed state, run doctor before attempting repair.",
197
+ "- Recovery owns DevFlow state repair; error solving owns project-code repair.",
198
+ (
199
+ "- Do not call internal queue/DAG commands for normal delivery; the run drain owns "
200
+ "implementation, integration, E2E follow-up, and preview planning."
201
+ ),
202
+ "",
203
+ ]
204
+ for item in selected:
205
+ blocks.extend(
206
+ [
207
+ f"## {item.name}",
208
+ item.purpose,
209
+ "",
210
+ "Use when:",
211
+ *[f"- {line}" for line in item.use_when],
212
+ "",
213
+ "Do not use when:",
214
+ *[f"- {line}" for line in item.do_not_use_when],
215
+ "",
216
+ "Required fields:",
217
+ *[f"- {line}" for line in item.required_fields],
218
+ "",
219
+ "Optional fields:",
220
+ *[f"- {line}" for line in item.optional_fields],
221
+ "",
222
+ "Construction rules:",
223
+ *[f"- {line}" for line in item.construction],
224
+ "",
225
+ "Processing flow:",
226
+ *[f"- {line}" for line in item.processing],
227
+ "",
228
+ "Output contract:",
229
+ *[f"- {line}" for line in item.output_contract],
230
+ "",
231
+ ]
232
+ )
233
+ return "\n".join(blocks).rstrip() + "\n"
234
+
235
+
236
+ def _agent_command_surface() -> dict[str, object]:
237
+ return {
238
+ "public_commands": [
239
+ {
240
+ "command": "devflow project add --path <repo> --name <name> --json",
241
+ "use_when": "Register a repo/project and run knowledge bootstrap.",
242
+ "returns": ["status", "project_id", "repo_root", "next_action"],
243
+ },
244
+ {
245
+ "command": "devflow project remove <project_id> --yes",
246
+ "use_when": "Remove a project registration when the user explicitly asks.",
247
+ "returns": ["ok or non-zero failure"],
248
+ },
249
+ {
250
+ "command": "devflow project status --project <project> --json",
251
+ "use_when": "Inspect registration, queue, worker, and health state for a project.",
252
+ "returns": ["status", "next_action", "queues", "worker"],
253
+ },
254
+ {
255
+ "command": "devflow idea submit --project <project> --from <idea.json> --json",
256
+ "use_when": "Submit a planning-level idea primitive.",
257
+ "returns": ["status", "idea_id", "idea_queue_id", "issues", "next_action"],
258
+ },
259
+ {
260
+ "command": "devflow story submit --project <project> --from <story.json> --json",
261
+ "use_when": "Submit a bounded implementation story primitive.",
262
+ "returns": ["status", "story_id", "story_queue_id", "next_action"],
263
+ },
264
+ {
265
+ "command": "devflow run start --project <project> --json",
266
+ "use_when": "Drain the full delivery workflow after a ready submit.",
267
+ "returns": ["processed_count", "processed", "stopped_reason", "report"],
268
+ },
269
+ {
270
+ "command": "devflow run status --project <project> --json",
271
+ "use_when": "Inspect run position and queue state.",
272
+ "returns": ["status", "next_action", "queued_total", "active_failures", "queues", "worker"],
273
+ },
274
+ {
275
+ "command": "devflow run health --project <project> --json",
276
+ "use_when": "Poll compact health from an agent harness.",
277
+ "returns": ["status", "next_action", "active_failures", "worker_status"],
278
+ },
279
+ {
280
+ "command": "devflow doctor --project <project> --json",
281
+ "use_when": "Triage a stuck or failed run before choosing recovery or error solving.",
282
+ "returns": [
283
+ "classification",
284
+ "system_findings",
285
+ "project_findings",
286
+ "recommended_next_command",
287
+ "handoff_lane",
288
+ ],
289
+ },
290
+ {
291
+ "command": "devflow recovery run --project <project> --json",
292
+ "use_when": "Repair DevFlow queue, worker, run, or artifact state after doctor routes to recovery.",
293
+ "returns": ["outcome", "artifacts", "next_action"],
294
+ },
295
+ {
296
+ "command": "devflow error solve --project <project> --json",
297
+ "use_when": "Repair project-code failures after doctor routes to error solving. Add --repro-command when a deterministic repro is known.",
298
+ "returns": ["outcome", "error_task_id", "artifacts", "next_action"],
299
+ },
300
+ ],
301
+ "internal_by_default": [
302
+ "worker",
303
+ "integration",
304
+ "source-scope",
305
+ "source-docs",
306
+ "ui-grounding",
307
+ "review",
308
+ "impl",
309
+ "registry",
310
+ "play",
311
+ "preflight",
312
+ "idea drafts",
313
+ "idea stories",
314
+ ],
315
+ }
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+ from typing import Any, Callable
6
+
7
+ from .stores.execution_store import ExecutionStore
8
+
9
+ TaskHandler = Callable[[ExecutionStore, Path, dict[str, Any]], dict[str, Any]]
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class WorkerTickResult:
14
+ worker_id: str
15
+ queue_name: str
16
+ task: dict[str, Any] | None
17
+ outcome: dict[str, Any] | None
18
+
19
+
20
+ def process_one_task(
21
+ *,
22
+ store: ExecutionStore,
23
+ repo_root: Path,
24
+ queue_name: str,
25
+ worker_id: str,
26
+ handlers: dict[str, TaskHandler],
27
+ lease_seconds: int = 900,
28
+ ) -> WorkerTickResult:
29
+ task = store.claim_next_task(queue_name=queue_name, worker_id=worker_id, lease_seconds=lease_seconds)
30
+ if task is None:
31
+ return WorkerTickResult(worker_id=worker_id, queue_name=queue_name, task=None, outcome=None)
32
+
33
+ lease_token = str(task.get("lease_token") or "")
34
+ task_id = str(task["task_id"])
35
+ task_kind = str(task["task_kind"])
36
+ handler = handlers.get(task_kind)
37
+ if handler is None:
38
+ outcome = store.complete_task(
39
+ task_id=task_id,
40
+ lease_token=lease_token,
41
+ status="dead_letter",
42
+ error=f"no handler registered for task_kind={task_kind}",
43
+ result={"task_kind": task_kind},
44
+ )
45
+ return WorkerTickResult(worker_id=worker_id, queue_name=queue_name, task=task, outcome=outcome)
46
+
47
+ store.record_task_step(task_id=task_id, step_name="claim", status="leased", payload={"worker_id": worker_id})
48
+ try:
49
+ result = handler(store, repo_root, task)
50
+ store.record_task_step(task_id=task_id, step_name="complete", status="completed", payload=result)
51
+ outcome = store.complete_task(task_id=task_id, lease_token=lease_token, status="completed", result=result)
52
+ return WorkerTickResult(worker_id=worker_id, queue_name=queue_name, task=task, outcome=outcome)
53
+ except Exception as exc:
54
+ store.record_task_step(task_id=task_id, step_name="complete", status="failed", payload={"error": str(exc)})
55
+ outcome = store.complete_task(
56
+ task_id=task_id,
57
+ lease_token=lease_token,
58
+ status="failed",
59
+ error=str(exc),
60
+ result={"error": str(exc)},
61
+ )
62
+ raise
File without changes
@@ -0,0 +1,92 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+
6
+ from ..story.markdown_contracts import ALLOWED_PLANES
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class RepoSignal:
11
+ path: str
12
+ kind: str
13
+
14
+
15
+ def collect_repo_signals(repo_root: Path, *, max_files: int = 500) -> list[RepoSignal]:
16
+ signals: list[RepoSignal] = []
17
+ count = 0
18
+ for p in sorted(repo_root.rglob("*")):
19
+ if count >= max_files:
20
+ break
21
+ if "/.git/" in p.as_posix() or p.name.startswith(".venv"):
22
+ continue
23
+ if p.is_dir():
24
+ continue
25
+ rel = p.relative_to(repo_root).as_posix()
26
+ kind = "file"
27
+ if rel.endswith("pyproject.toml"):
28
+ kind = "pyproject"
29
+ elif rel.endswith(".py"):
30
+ kind = "python"
31
+ elif rel.endswith(".md"):
32
+ kind = "docs"
33
+ elif rel.endswith(".sql"):
34
+ kind = "sql"
35
+ signals.append(RepoSignal(path=rel, kind=kind))
36
+ count += 1
37
+ return signals
38
+
39
+
40
+ def draft_user_stories(repo_root: Path) -> list[dict]:
41
+ """Produce *draft* story skeletons.
42
+
43
+ Drafts are not canonical contracts; they are generated from repo signals and should be
44
+ reviewed/edited into canonical markdown contracts under ai_docs/context/v2/....
45
+
46
+ This returns a dict payload that the CLI can serialize to markdown.
47
+ """
48
+
49
+ signals = collect_repo_signals(repo_root)
50
+ top_kinds = {s.kind for s in signals}
51
+
52
+ # Minimal heuristic: propose one baseline story with evidence anchors taken from repo.
53
+ evidence = sorted({s.path for s in signals if s.kind in {"pyproject", "python", "docs"}})[:10]
54
+
55
+ stories: list[dict] = []
56
+
57
+ def mk(story_id: str, title: str) -> dict:
58
+ required_planes = [p for p in ALLOWED_PLANES if p in {"api", "ops", "integrations", "auth", "ui"}]
59
+ # default: api+ops for code repos
60
+ if "python" in top_kinds or "pyproject" in top_kinds:
61
+ required_planes = ["api", "ops"]
62
+ if "docs" in top_kinds:
63
+ required_planes = sorted(set(required_planes + ["ui"]))
64
+
65
+ plane_oracles = [
66
+ {
67
+ "plane": "ops",
68
+ "oracle": "Green gate passes (tests + typecheck + lint)",
69
+ "anchor": "command:devflow impl gate",
70
+ },
71
+ {
72
+ "plane": "api",
73
+ "oracle": "Primary app entrypoint runs and exposes expected endpoints",
74
+ "anchor": f"evidence:{evidence[0] if evidence else 'repo'}",
75
+ },
76
+ ]
77
+ plane_oracles = [po for po in plane_oracles if po["plane"] in required_planes]
78
+
79
+ return {
80
+ "story_id": story_id,
81
+ "title": title,
82
+ "required_planes": required_planes,
83
+ "evidence_anchors": evidence,
84
+ "plane_oracles": plane_oracles,
85
+ }
86
+
87
+ stories.append(mk("STORY:devflow:planner:baseline", "Establish baseline DevFlow v2 story contracts"))
88
+
89
+ if "python" in top_kinds:
90
+ stories.append(mk("STORY:devflow:planner:python", "Python repo: validate tests/typecheck/lint pipeline"))
91
+
92
+ return stories
@@ -0,0 +1,133 @@
1
+ from __future__ import annotations
2
+
3
+ import uuid
4
+ from typing import Any
5
+
6
+ from ..story.markdown_contracts import MANDATORY_CONTRACT_FORMATION_MODE_LINE
7
+
8
+
9
+ def _as_list(value: Any) -> list[str]:
10
+ if isinstance(value, str):
11
+ text = value.strip()
12
+ return [text] if text else []
13
+ if isinstance(value, list):
14
+ items: list[str] = []
15
+ for item in value:
16
+ if isinstance(item, str):
17
+ text = item.strip()
18
+ if text:
19
+ items.append(text)
20
+ return items
21
+ return []
22
+
23
+
24
+ def render_draft_story_markdown(draft: dict[str, Any]) -> str:
25
+ """Render a *draft* story skeleton as markdown.
26
+
27
+ Drafts are intended to be copied/edited into canonical story contracts.
28
+ """
29
+
30
+ story_uuid = str(draft.get("story_uuid") or uuid.uuid4())
31
+ story_id = str(draft.get("story_id") or "STORY:todo:todo:todo")
32
+ title = str(draft.get("title") or "TODO")
33
+ required_planes = draft.get("required_planes") or []
34
+ rp = ", ".join(required_planes)
35
+
36
+ plane_oracles = draft.get("plane_oracles") or []
37
+ evidence = draft.get("evidence_anchors") or []
38
+ story_statement = str(draft.get("story_statement") or "As a ... I want ... so that ...")
39
+ outcome_oracle = _as_list(draft.get("outcome_oracle")) or ["TODO"]
40
+ preconditions = _as_list(draft.get("preconditions")) or ["TODO"]
41
+ steps = _as_list(draft.get("steps")) or ["TODO"]
42
+ pass_conditions = _as_list(draft.get("pass_conditions")) or ["TODO"]
43
+ fail_conditions = _as_list(draft.get("fail_conditions")) or ["TODO"]
44
+ acceptance_criteria = _as_list(draft.get("acceptance_criteria")) or ["MUST ...", "MUST NOT ..."]
45
+ non_goals = _as_list(draft.get("non_goals")) or ["..."]
46
+ contract_test_spec = _as_list(draft.get("contract_test_spec")) or ["Given ...", "When ...", "Then ..."]
47
+
48
+ draft_story_id = str(draft.get("draft_story_id") or f"draft_{story_uuid}")
49
+ plane = str(draft.get("plane") or "")
50
+ source_analysis_id = str(draft.get("source_analysis_id") or "")
51
+
52
+ lines: list[str] = []
53
+
54
+ # Locked header block for tooling (must be preserved by editors/agents).
55
+ lines.append("DEVFLOW:LOCKED_START")
56
+ lines.append(f"draft_story_id: {draft_story_id}")
57
+ if plane:
58
+ lines.append(f"plane: {plane}")
59
+ if source_analysis_id:
60
+ lines.append(f"source_analysis_id: {source_analysis_id}")
61
+ # Include at least one evidence anchor line when available.
62
+ for a in evidence[:5]:
63
+ lines.append(f"anchor: {a}")
64
+ lines.append("DEVFLOW:LOCKED_END")
65
+ lines.append("")
66
+
67
+ lines.append(f"# {title}")
68
+ lines.append("")
69
+ lines.append(f"story_uuid: {story_uuid}")
70
+ lines.append(f"story_id: {story_id}")
71
+ lines.append(f"title: {title}")
72
+ lines.append(f"required_planes: [{rp}]")
73
+ lines.append("")
74
+ lines.append(MANDATORY_CONTRACT_FORMATION_MODE_LINE)
75
+ lines.append("")
76
+
77
+ lines.append("plane_oracles:")
78
+ for po in plane_oracles:
79
+ lines.append(f"- plane: {po.get('plane','')}")
80
+ lines.append(f" oracle: \"{po.get('oracle','')}\"")
81
+ lines.append(f" anchor: \"{po.get('anchor','')}\"")
82
+ lines.append("")
83
+
84
+ if evidence:
85
+ lines.append("## Evidence anchors (repo signals)")
86
+ for e in evidence:
87
+ lines.append(f"- {e}")
88
+ lines.append("")
89
+
90
+ lines.append("## Story statement")
91
+ lines.append(story_statement)
92
+ lines.append("")
93
+
94
+ lines.append("## Outcome oracle (user-observable)")
95
+ for item in outcome_oracle:
96
+ lines.append(f"- {item}")
97
+ lines.append("")
98
+
99
+ lines.append("## Preconditions")
100
+ for item in preconditions:
101
+ lines.append(f"- {item}")
102
+ lines.append("")
103
+
104
+ lines.append("## Steps")
105
+ for index, item in enumerate(steps, start=1):
106
+ lines.append(f"{index}. {item}")
107
+ lines.append("")
108
+
109
+ lines.append("## Pass/fail conditions")
110
+ lines.append("Pass:")
111
+ for item in pass_conditions:
112
+ lines.append(f"- {item}")
113
+ lines.append("Fail:")
114
+ for item in fail_conditions:
115
+ lines.append(f"- {item}")
116
+ lines.append("")
117
+
118
+ lines.append("## Acceptance criteria")
119
+ for index, item in enumerate(acceptance_criteria, start=1):
120
+ lines.append(f"{index}. {item}")
121
+ lines.append("")
122
+
123
+ lines.append("## Non-goals")
124
+ for item in non_goals:
125
+ lines.append(f"- {item}")
126
+ lines.append("")
127
+
128
+ lines.append("## Contract test spec (Given/When/Then)")
129
+ for item in contract_test_spec:
130
+ lines.append(f"- {item}")
131
+ lines.append("")
132
+
133
+ return "\n".join(lines)
File without changes
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+
6
+
7
+ @dataclass(frozen=True)
8
+ class PreflightResult:
9
+ ok: bool
10
+ message: str
11
+
12
+
13
+ def preflight(repo_root: Path) -> PreflightResult:
14
+ # Minimal: verify .devflow exists.
15
+ df = repo_root / ".devflow"
16
+ if not df.exists():
17
+ return PreflightResult(
18
+ ok=False,
19
+ message=".devflow not initialized. Run `devflow project init`.",
20
+ )
21
+ return PreflightResult(ok=True, message="ok")
22
+
23
+
24
+ def run_scenario(_name: str) -> None:
25
+ # Placeholder hook for future integration.
26
+ return
@@ -0,0 +1,5 @@
1
+ """Post-integration Playwright workflow artifacts."""
2
+
3
+ from .dag import PostIntegrationPlaywrightDagResult, run_post_integration_playwright_dag
4
+
5
+ __all__ = ["PostIntegrationPlaywrightDagResult", "run_post_integration_playwright_dag"]