@guanlin4924/devflow-pi 0.1.93 → 0.1.94

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 (156) hide show
  1. package/README.md +6 -6
  2. package/package.json +1 -1
  3. package/plugins/devflow-core/extensions/devflow-core.ts +87 -33
  4. package/plugins/devflow-core/runtime/hooks/context_sync_gate.py +3 -3
  5. package/plugins/devflow-core/runtime/hooks/hook_common.py +65 -11
  6. package/plugins/devflow-core/runtime/hooks/start.py +13 -13
  7. package/plugins/devflow-core/skills/wireframe-proposal/SKILL.md +2 -2
  8. package/plugins/devflow-core/skills/wireframe-validate/SKILL.md +4 -4
  9. package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +19 -19
  10. package/plugins/devflow-core/skills/workflow-orchestrator/agents/openai.yaml +2 -2
  11. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_runner.py +5 -5
  12. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +9 -9
  13. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/api_test_matrix.py +2 -2
  14. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_assessment.rb +1 -1
  15. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_brief.rb +1 -1
  16. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_feasibility.rb +1 -1
  17. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_invalidation.rb +5 -5
  18. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_commit.rb +4 -4
  19. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_validate.py +1 -1
  20. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_source_resolver.rb +4 -4
  21. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/checker_adapter.rb +7 -7
  22. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/control_io.rb +51 -7
  23. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/cross_track_consistency_check.rb +1 -1
  24. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +6 -6
  25. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_runtime.rb +3 -3
  26. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_state.rb +5 -5
  27. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_workflow.rb +5 -5
  28. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +13 -13
  29. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/machine_evidence.rb +3 -3
  30. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/manage_lessons.rb +7 -7
  31. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_recover.rb +2 -2
  32. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_run.rb +3 -3
  33. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/phase_ownership.rb +6 -6
  34. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/repair_control_plane.rb +1 -1
  35. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_coverage.rb +1 -1
  36. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph.rb +3 -3
  37. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/review_preflight.py +3 -3
  38. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/review_run.py +18 -18
  39. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/runtime_context_collector.rb +3 -3
  40. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/session_rollover.rb +4 -4
  41. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/static_runtime_context_collector.rb +2 -2
  42. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/sync_artifacts.rb +5 -5
  43. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/tdd_evidence.py +3 -3
  44. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_command_policy.py +2 -2
  45. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_task_binding_check.py +3 -3
  46. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/update_triage_route.rb +3 -3
  47. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +6 -6
  48. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_commit.rb +5 -5
  49. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_validate.py +1 -1
  50. package/plugins/devflow-core/skills/workflow-orchestrator/templates/acceptance-remediation.yaml +12 -12
  51. package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +205 -205
  52. package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +3 -3
  53. package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +10 -10
  54. package/plugins/devflow-core/skills/workflow-project-context/SKILL.md +14 -14
  55. package/plugins/devflow-core/skills/workflow-project-context/assets/agents-md-template.md +7 -7
  56. package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-backend-spec-template.md +4 -4
  57. package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-frontend-spec-template.md +4 -4
  58. package/plugins/devflow-core/skills/workflow-project-context/assets/codebase-navigation-template.md +1 -1
  59. package/plugins/devflow-core/skills/workflow-project-context/assets/context-domain-index-template.md +4 -4
  60. package/plugins/devflow-core/skills/workflow-project-context/assets/context-spec-index-template.md +10 -10
  61. package/plugins/devflow-core/skills/workflow-project-context/assets/execution-contract-template.md +2 -2
  62. package/plugins/devflow-core/skills/workflow-project-context/assets/navigation-index-template.md +18 -18
  63. package/plugins/devflow-core/skills/workflow-project-context/assets/project-initialization-template.md +32 -32
  64. package/plugins/devflow-core/skills/workflow-project-context/assets/rules-index-template.md +30 -30
  65. package/plugins/devflow-core/skills/workflow-project-context/assets/state-template.md +7 -7
  66. package/plugins/devflow-core/skills/workflow-project-context/references/navigation-guide.md +37 -37
  67. package/plugins/devflow-core/skills/workflow-project-context/scripts/validate_initialization.py +16 -16
  68. package/plugins/devflow-design/skills/workflow-api-call-guide/SKILL.md +4 -4
  69. package/plugins/devflow-design/skills/workflow-api-contract/SKILL.md +8 -8
  70. package/plugins/devflow-design/skills/workflow-api-supplement/SKILL.md +5 -5
  71. package/plugins/devflow-design/skills/workflow-architecture-feasibility/SKILL.md +1 -1
  72. package/plugins/devflow-design/skills/workflow-backend-tech-spec/SKILL.md +39 -39
  73. package/plugins/devflow-design/skills/workflow-backend-tech-spec/assets/backend-spec-template.md +10 -10
  74. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/affected-module-exploration.md +2 -2
  75. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/code-explore-guide.md +1 -1
  76. package/plugins/devflow-design/skills/workflow-backend-tech-spec/references/project-rule-contract.md +20 -20
  77. package/plugins/devflow-design/skills/workflow-design-rule-pack/SKILL.md +8 -8
  78. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/index.md +3 -3
  79. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/accessibility.md +2 -2
  80. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/component-library.md +2 -2
  81. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/design-systems.md +1 -1
  82. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/responsive-grid.md +2 -2
  83. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/stack-guidelines.md +6 -6
  84. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/recommendations/ux-patterns.md +2 -2
  85. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tokens/project-tokens.md +1 -1
  86. package/plugins/devflow-design/skills/workflow-design-rule-pack/assets/design/tools/ui-ux-pro-max/SKILL.md +12 -12
  87. package/plugins/devflow-design/skills/workflow-design-rule-pack/scripts/install.py +2 -2
  88. package/plugins/devflow-design/skills/workflow-feature-breakdown/SKILL.md +30 -30
  89. package/plugins/devflow-design/skills/workflow-feature-breakdown/assets/output-template.md +2 -2
  90. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/SKILL.md +41 -41
  91. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/assets/frontend-spec-template.md +15 -15
  92. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/affected-module-exploration.md +2 -2
  93. package/plugins/devflow-design/skills/workflow-frontend-tech-spec/references/project-rule-contract.md +25 -25
  94. package/plugins/devflow-design/skills/workflow-integration-verify/SKILL.md +13 -13
  95. package/plugins/devflow-design/skills/workflow-ui-spec/SKILL.md +23 -23
  96. package/plugins/devflow-design/skills/workflow-ui-spec/assets/ui-spec-template.md +3 -3
  97. package/plugins/devflow-implementation/agents/implementation-worker.md +2 -2
  98. package/plugins/devflow-implementation/skills/workflow-bug-fix/SKILL.md +9 -9
  99. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/lesson-format.md +2 -2
  100. package/plugins/devflow-implementation/skills/workflow-bug-fix/references/root-cause-ladder.md +1 -1
  101. package/plugins/devflow-implementation/skills/workflow-change-plan/SKILL.md +17 -17
  102. package/plugins/devflow-implementation/skills/workflow-change-plan/references/code-conventions.md +1 -1
  103. package/plugins/devflow-implementation/skills/workflow-change-plan/references/output-template.md +3 -3
  104. package/plugins/devflow-implementation/skills/workflow-change-plan/references/project-rule-contract.md +16 -16
  105. package/plugins/devflow-implementation/skills/workflow-execute-phase/SKILL.md +38 -38
  106. package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md +1 -1
  107. package/plugins/devflow-intel/agents/project-scout.md +1 -1
  108. package/plugins/devflow-intel/extensions/devflow-intel.ts +20 -19
  109. package/plugins/devflow-intel/skills/code-index-query/SKILL.md +6 -6
  110. package/plugins/devflow-intel/skills/workflow-code-index/SKILL.md +12 -12
  111. package/plugins/devflow-intel/skills/workflow-code-index/references/discovery.md +2 -2
  112. package/plugins/devflow-intel/skills/workflow-code-index/references/query-guide.md +1 -1
  113. package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +8 -8
  114. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/discovery.py +2 -2
  115. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/scanner.py +4 -1
  116. package/plugins/devflow-intel/skills/workflow-code-index/scripts/validators/project_binding_check.py +4 -4
  117. package/plugins/devflow-intel/skills/workflow-context-sync/SKILL.md +14 -14
  118. package/plugins/devflow-intel/skills/workflow-context-sync/scripts/context_sync_cursor.py +2 -2
  119. package/plugins/devflow-intel/skills/workflow-update-navigation/SKILL.md +26 -26
  120. package/plugins/devflow-intel/skills/workflow-update-navigation/references/incremental-update-guide.md +2 -2
  121. package/plugins/devflow-quality/skills/code-review/SKILL.md +12 -12
  122. package/plugins/devflow-quality/skills/code-review/references/spec-checklist.md +1 -1
  123. package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +8 -8
  124. package/plugins/devflow-quality/skills/workflow-gen-test-guide/SKILL.md +6 -6
  125. package/plugins/devflow-quality/skills/workflow-gen-test-guide/legacy/SKILL.md +14 -14
  126. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +23 -23
  127. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/codebase-discovery.md +9 -9
  128. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/project-dsl-contract.md +1 -1
  129. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +2 -2
  130. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/discover_codebases.py +2 -2
  131. package/plugins/devflow-quality/skills/workflow-release-closeout/SKILL.md +15 -15
  132. package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +5 -5
  133. package/plugins/devflow-requirements/skills/requirement-feasibility-review/SKILL.md +1 -1
  134. package/plugins/devflow-requirements/skills/workflow-demand-clarify/SKILL.md +10 -10
  135. package/plugins/devflow-requirements/skills/workflow-domain-modeling/SKILL.md +25 -25
  136. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/SKILL.md +49 -49
  137. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/assets/baseline-template.md +22 -22
  138. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/antipatterns.md +3 -3
  139. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/challenge-review-guide.md +3 -3
  140. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/project-context-guide.md +11 -11
  141. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/questioning.md +1 -1
  142. package/plugins/devflow-requirements/skills/workflow-requirement-baseline/references/requirement-review-checklist.md +4 -4
  143. package/plugins/devflow-requirements/skills/workflow-requirement-triage/SKILL.md +16 -16
  144. package/plugins/devflow-requirements/skills/workflow-wayfinder/SKILL.md +6 -6
  145. package/src/cli.ts +15 -0
  146. package/src/constants.ts +1 -1
  147. package/src/initialization-store.ts +3 -2
  148. package/src/project-context.ts +36 -14
  149. package/src/project-documents.ts +61 -61
  150. package/src/project-initializer.ts +9 -8
  151. package/src/project-layout.ts +217 -0
  152. package/src/runtime.ts +3 -3
  153. package/templates/commands/start.md +4 -4
  154. package/templates/omp/AGENTS.md +1 -1
  155. package/templates/omp/hook-config.json +7 -7
  156. package/templates/omp/index-policy.json +8 -8
package/README.md CHANGED
@@ -31,7 +31,7 @@ devflow-pi
31
31
  /usage-stats
32
32
  ```
33
33
 
34
- `/devflow project-init` 会先读取当前项目已有的 `.planning/PROJECT.md` 与 `.planning/navigation/INDEX.md`:仅回填仍存在于项目根目录内的已登记前后端路径,删除或越界的历史路径会被忽略。随后可选择复用已有边界、复用边界并重建索引,或手动覆盖。初始化模式使用选择器提供“只读规划(默认)”和“写入初始化”;选择后者并确认,只会创建 Devflow 的 `.planning/` 与 `.context/` 初始化产物,不会修改业务源码、依赖或项目配置。
34
+ `/devflow project-init` 会先读取当前项目已有的 `.devflow/planning/PROJECT.md` 与 `.devflow/planning/navigation/INDEX.md`:仅回填仍存在于项目根目录内的已登记前后端路径,删除或越界的历史路径会被忽略。随后可选择复用已有边界、复用边界并重建索引,或手动覆盖。初始化模式使用选择器提供“只读规划(默认)”和“写入初始化”;选择后者并确认,只会创建 Devflow 的 `.devflow/planning/` 与 `.devflow/context/` 初始化产物,不会修改业务源码、依赖或项目配置。
35
35
 
36
36
  用量统计默认只读取当前项目的隔离会话:`/usage-stats`。需要明确查看历史 OMP 会话时,使用 `/usage-stats omp`,或加筛选条件:`/usage-stats omp --from 2026-08-01 --to 2026-08-10`。历史统计保留真实会话路径,不再把不同项目的长会话文件合并成 `main`;统计只使用 assistant message 的原始 usage,不虚构工具调用成本分摊。
37
37
 
@@ -40,7 +40,7 @@ devflow-pi
40
40
  专项 Pi 的隔离边界:
41
41
 
42
42
  - 项目身份位于 `<project>/.devflow/project.json`;
43
- - 流程状态和代码索引仍位于 `<project>/.planning/`;
43
+ - 流程状态和代码索引仍位于 `<project>/.devflow/planning/`;
44
44
  - Session 位于 `~/.devflow-pi/sessions/<projectId>/`;
45
45
  - 模型认证默认复用 `~/.omp/agent/`,但不复用官方 OMP Session;
46
46
  - 只显式加载产品内六个插件根,不自动混入用户或项目的环境 Extension;
@@ -92,7 +92,7 @@ skills:
92
92
 
93
93
  Devflow 会在输入框上方显示“当前 Feature 交付链路”:它基于只读状态快照展示已知步骤、当前节点、完成数、工作流/执行状态、当前允许的操作,以及安全恢复方案。使用 `/devflow control` 打开交互式控制台:它只会在状态检查器允许时提供启动当前步骤、审查并批准推进、安全恢复或取消当前 Feature;每个有写入影响的操作都会重新读取状态并沿用已有确认流程。面板不提供重试或重置当前节点,避免破坏 revision、checkpoint 和证据链。
94
94
 
95
- 正式节点经用户批准后,Devflow 会把已校验的状态和产物引用固化为内容校验的 handoff,再自动创建干净 Session 执行下一节点。交接期间工作流冻结;只有新 Session 成功认领并消费同一份 handoff 后才解除冻结。Devflow 不使用 OMP 的模型摘要 handoff,因此 `.planning/STATE.md` 仍是唯一流程事实源。
95
+ 正式节点经用户批准后,Devflow 会把已校验的状态和产物引用固化为内容校验的 handoff,再自动创建干净 Session 执行下一节点。交接期间工作流冻结;只有新 Session 成功认领并消费同一份 handoff 后才解除冻结。Devflow 不使用 OMP 的模型摘要 handoff,因此 `.devflow/planning/STATE.md` 仍是唯一流程事实源。
96
96
 
97
97
  ### 需求验收测试与 TDD 证据链
98
98
 
@@ -110,10 +110,10 @@ Devflow 会在输入框上方显示“当前 Feature 交付链路”:它基于
110
110
  - `tdd_required` 任务必须先由 Core 记录准备快照,再记录 RED(命中预期失败)、同一目标的 GREEN 和回归;缺失或环境失败不算完成。
111
111
  - API、跨数据域、边界、迁移、工作负载与架构风险会派生相应的 `api`、`permission`、`boundary`、`migration`、`performance`、`resilience` TC 义务。
112
112
  - 每个 TC 还要声明证明策略:`replay` 用组件/页面/API/集成的稳定回放;`causal` 用已定位的首个偏差加 HAR、控制台、DOM 快照、截图或日志等受控文件证明,Core 会记录文件哈希;`observation` 用于尚不可复现、也未能证明根因的问题,只能保持阻塞并带观测计划。后两者都不能被“AI 已复现”或 Markdown 自述放行。
113
- - 代码完成后,`workflow-run-acceptance-tests` 只能运行绑定到冻结 TC、且已在初始化 `.planning/toolchain.md` 发现的测试运行器命令。任何失败、未执行、人工待执行或环境阻塞用例都会阻止 CP-4。
113
+ - 代码完成后,`workflow-run-acceptance-tests` 只能运行绑定到冻结 TC、且已在初始化 `.devflow/planning/toolchain.md` 发现的测试运行器命令。任何失败、未执行、人工待执行或环境阻塞用例都会阻止 CP-4。
114
114
  - 验收不是代码完成后的临时手工检查。它是需求基线在编码前派生并冻结的完整测试集,覆盖主流程、异常、边界、权限、迁移、兼容、韧性和工作负载义务;代码只能补充执行适配信息,不能改变测试意图。
115
115
  - 验收失败不会创建另一套人工台账,而是进入 `acceptance-remediation`:诊断 → 修复 → code-index 刷新 → 原冻结 `TC-*` 重跑。
116
- - CP-4 通过后只进入一个 `workflow-release-closeout` 步骤,统一写入 `.planning/milestones/current-CLOSEOUT.md` 并更新项目状态、导航和版本记录。
116
+ - CP-4 通过后只进入一个 `workflow-release-closeout` 步骤,统一写入 `.devflow/planning/milestones/current-CLOSEOUT.md` 并更新项目状态、导航和版本记录。
117
117
 
118
118
  正常使用不需要记忆底层命令:在 Devflow 工作流中按步骤继续即可。需要排查时,可用 `devflow_acceptance_tests` 查看冻结套件,或由工作流调用 `devflow_tdd_evidence` 与 `devflow_run_acceptance_tests` 生成 Core-owned 证据;不要手写“已测试”来替代结果文件。
119
119
 
@@ -146,7 +146,7 @@ npm install -g @guanlin4924/devflow-pi@latest
146
146
 
147
147
  ## 核心不变量
148
148
 
149
- - `.planning/STATE.md`、workflow 和 artifact registry 只允许 Devflow 工具写入。
149
+ - `.devflow/planning/STATE.md`、workflow 和 artifact registry 只允许 Devflow 工具写入。
150
150
  - 子 agent 不更新控制面,只返回证据、结构化审查结果或隔离 patch。
151
151
  - 索引是加速器,不是真相源;过期时回退到 LSP、搜索、源码和测试。
152
152
  - 人工 checkpoint 不得在 headless 模式静默通过。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanlin4924/devflow-pi",
3
- "version": "0.1.93",
3
+ "version": "0.1.94",
4
4
  "type": "module",
5
5
  "description": "Devflow 专项研发 Pi,基于固定版本 OMP Runtime 组装研发状态机、代码智能、设计、实现与质量门禁。",
6
6
  "license": "UNLICENSED",
@@ -16,6 +16,7 @@ import { runProjectInitialization } from "../../../src/project-initializer.ts";
16
16
  import { projectControlDatabasePath } from "../../../src/paths.ts";
17
17
  import { generateProjectDocuments } from "../../../src/project-documents.ts";
18
18
  import { exportInitializationSnapshot, importLegacyInitialization, switchInitializationAuthority } from "../../../src/project-migration.ts";
19
+ import { migrateLegacyProjectLayout } from "../../../src/project-layout.ts";
19
20
 
20
21
 
21
22
  export type DevflowIntent = "idle" | "explain-state" | "project-init" | "requirement-draft" | "workflow-execute";
@@ -351,7 +352,7 @@ export function discoverExistingProjectInitialization(cwd: string, options: { al
351
352
  }
352
353
  }
353
354
  if (!options.allowLegacyImport) return null;
354
- const sources = [".planning/PROJECT.md", ".planning/navigation/INDEX.md"];
355
+ const sources = [".devflow/planning/PROJECT.md", ".devflow/planning/navigation/INDEX.md"];
355
356
  const records: Array<ExistingProjectInitialization> = [];
356
357
  for (const sourcePath of sources) {
357
358
  const absolute = path.join(cwd, sourcePath);
@@ -531,13 +532,13 @@ type DoctorContext = {
531
532
  };
532
533
 
533
534
  const CONTROL_PATHS = [
534
- ".planning/STATE.md",
535
- ".planning/.next-intent",
536
- ".planning/.devflow.lock",
537
- ".planning/artifacts/index.yaml",
535
+ ".devflow/planning/STATE.md",
536
+ ".devflow/planning/.next-intent",
537
+ ".devflow/planning/.devflow.lock",
538
+ ".devflow/planning/artifacts/index.yaml",
538
539
  ];
539
540
 
540
- const CONTROL_PREFIXES = [".planning/workflows/", ".planning/contracts/", ".planning/evidence/", ".planning/review-runs/"];
541
+ const CONTROL_PREFIXES = [".devflow/planning/workflows/", ".devflow/planning/contracts/", ".devflow/planning/evidence/", ".devflow/planning/review-runs/"];
541
542
 
542
543
  const REQUIRED_EXTENSION_TOOLS = [
543
544
  "devflow_doctor",
@@ -703,16 +704,63 @@ function assertRuntimeProjectBoundary(cwd: string): void {
703
704
  if (configured && realpathSync(configured) !== resolvedCwd) {
704
705
  throw new Error(`Devflow project-root mismatch: session=${resolvedCwd}, configured=${configured}`);
705
706
  }
706
- const planningRoot = path.join(resolvedCwd, ".planning");
707
+ const legacyPlanning = path.join(resolvedCwd, ".planning");
708
+ const legacyContext = path.join(resolvedCwd, ".context");
709
+ const planningMarkers = ["STATE.md", "PROJECT.md", ".devflow.lock", "navigation/INDEX.md", "code-index/INDEX.md", "workflows", "contracts", "evidence", "review-runs", "requirements", "features", "handoffs", "artifacts", "phase-ownership.yaml"];
710
+ const contextMarkers = ["spec/index.md", "index.md", "project/index.md", "knowledge/index.md"];
711
+ const legacyMarker = planningMarkers.some(relative => existsSync(path.join(legacyPlanning, relative)))
712
+ || contextMarkers.some(relative => existsSync(path.join(legacyContext, relative)));
713
+ const activeLegacy = ["STATE.md", "workflows", "contracts", "evidence", "review-runs", "requirements", "features", "handoffs", "artifacts", "phase-ownership.yaml"]
714
+ .find(relative => existsSync(path.join(legacyPlanning, relative)));
715
+ if (legacyMarker) {
716
+ const manifestPath = path.join(resolvedCwd, ".devflow", "project.json");
717
+ let manifestValid = false;
718
+ try {
719
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as Record<string, unknown>;
720
+ manifestValid = manifest.schemaVersion === 1
721
+ && typeof manifest.projectId === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(manifest.projectId)
722
+ && typeof manifest.name === "string" && manifest.name.trim().length > 0
723
+ && typeof manifest.createdAt === "string" && Number.isFinite(Date.parse(manifest.createdAt))
724
+ && [undefined, 1, 2].includes(manifest.layoutVersion as undefined | number);
725
+ } catch { /* reported below */ }
726
+ if (!manifestValid) throw new Error("DEVFLOW_LEGACY_LAYOUT_CONFIRMATION_REQUIRED: valid .devflow/project.json is required before legacy layout migration");
727
+ let migrationCompletePrecheck = false;
728
+ try {
729
+ const marker = JSON.parse(readFileSync(path.join(resolvedCwd, ".devflow", "layout-migration.json"), "utf8")) as Record<string, unknown>;
730
+ migrationCompletePrecheck = marker.schemaVersion === 1 && marker.status === "complete" && Array.isArray(marker.migrated);
731
+ } catch { /* reported by the normal conflict checks below */ }
732
+ if (activeLegacy && !migrationCompletePrecheck) {
733
+ throw new Error(`DEVFLOW_ACTIVE_LEGACY_LAYOUT: .planning/${activeLegacy} requires dedicated control-plane migration`);
734
+ }
735
+ const canonicalExists = existsSync(path.join(resolvedCwd, ".devflow", "planning")) || existsSync(path.join(resolvedCwd, ".devflow", "context"));
736
+ const migrationComplete = (() => {
737
+ try {
738
+ const marker = JSON.parse(readFileSync(path.join(resolvedCwd, ".devflow", "layout-migration.json"), "utf8")) as Record<string, unknown>;
739
+ return marker.schemaVersion === 1 && marker.status === "complete" && Array.isArray(marker.migrated);
740
+ } catch { return false; }
741
+ })();
742
+ if (manifestValid && (() => {
743
+ try { return (JSON.parse(readFileSync(manifestPath, "utf8")) as Record<string, unknown>).layoutVersion === 2; } catch { return false; }
744
+ })() && migrationComplete) {
745
+ const planningLegacy = planningMarkers.some(relative => existsSync(path.join(legacyPlanning, relative)));
746
+ const contextLegacy = contextMarkers.some(relative => existsSync(path.join(legacyContext, relative)));
747
+ if ((planningLegacy && !existsSync(path.join(resolvedCwd, ".devflow", "planning"))) || (contextLegacy && !existsSync(path.join(resolvedCwd, ".devflow", "context")))) {
748
+ throw new Error("DEVFLOW_LEGACY_REINTRODUCTION: v2 project will not backfill a missing canonical directory");
749
+ }
750
+ }
751
+ if (canonicalExists && !migrationComplete) throw new Error("DEVFLOW_LAYOUT_CONFLICT: canonical and legacy layouts coexist without a completed migration marker");
752
+ if (!canonicalExists) throw new Error("DEVFLOW_LAYOUT_MIGRATION_REQUIRED: run project initialization to migrate legacy read-only artifacts");
753
+ }
754
+ const planningRoot = path.join(resolvedCwd, ".devflow/planning");
707
755
  if (existsSync(planningRoot) && lstatSync(planningRoot).isSymbolicLink()) {
708
756
  throw new Error(`Refusing symlinked Devflow planning root: ${planningRoot}`);
709
757
  }
710
758
  for (const relative of [
711
- ".planning/STATE.md",
712
- ".planning/.devflow.lock",
713
- ".planning/workflows",
714
- ".planning/artifacts",
715
- ".planning/review-runs",
759
+ ".devflow/planning/STATE.md",
760
+ ".devflow/planning/.devflow.lock",
761
+ ".devflow/planning/workflows",
762
+ ".devflow/planning/artifacts",
763
+ ".devflow/planning/review-runs",
716
764
  ]) {
717
765
  const target = path.join(resolvedCwd, relative);
718
766
  try {
@@ -744,29 +792,29 @@ function safeControlPath(cwd: string, raw: string | undefined, kind: "state" | "
744
792
  const relative = normalizedProjectPath(raw, cwd);
745
793
  const allowed =
746
794
  kind === "state"
747
- ? relative === ".planning/STATE.md"
748
- : Boolean(relative?.startsWith(".planning/workflows/") && relative.endsWith(".yaml"));
795
+ ? relative === ".devflow/planning/STATE.md"
796
+ : Boolean(relative?.startsWith(".devflow/planning/workflows/") && relative.endsWith(".yaml"));
749
797
  if (!relative || !allowed) throw new Error(`Invalid ${kind} control path: ${raw}`);
750
798
  return relative;
751
799
  }
752
800
 
753
801
  function isCanonicalRequirementGraphPath(filePath: string): boolean {
754
- return /^\.planning\/requirements\/[^/\\\x00-\x1F\x7F]+\/(?:governance|evidence|definitions|behavior-graph|requirement-graph|slices|acceptance|tests|traceability|graph\.meta)\.json$/u.test(filePath)
755
- || /^\.planning\/requirements\/[^/\\\x00-\x1F\x7F]+\/(?:context\/[^/\\]+\.json|control-events\.jsonl)$/u.test(filePath);
802
+ return /^\.devflow\/planning\/requirements\/[^/\\\x00-\x1F\x7F]+\/(?:governance|evidence|definitions|behavior-graph|requirement-graph|slices|acceptance|tests|traceability|graph\.meta)\.json$/u.test(filePath)
803
+ || /^\.devflow\/planning\/requirements\/[^/\\\x00-\x1F\x7F]+\/(?:context\/[^/\\]+\.json|control-events\.jsonl)$/u.test(filePath);
756
804
  }
757
805
 
758
806
  function isCoreOwnedGovernancePath(filePath: string): boolean {
759
807
  // 规范需求图谱只能由 Core 的 devflow_requirement_graph writer 写入;the
760
808
  // same ownership extends to its views, machine evidence, and audit records.
761
809
  return isCanonicalRequirementGraphPath(filePath)
762
- || /^\.planning\/evidence\/[^/\\\x00-\x1F\x7F]+\/[^/\\]+\.machine\.json$/u.test(filePath)
763
- || /^\.planning\/contracts\/[^/\\\x00-\x1F\x7F]+\/(?:EC-[A-Fa-f0-9]+\.json|control-events\.jsonl)$/u.test(filePath)
764
- || filePath.startsWith(".planning/review-runs/")
765
- || /^\.planning\/phases\/[^/\\\x00-\x1F\x7F]+\/REVIEW\.md$/u.test(filePath);
810
+ || /^\.devflow\/planning\/evidence\/[^/\\\x00-\x1F\x7F]+\/[^/\\]+\.machine\.json$/u.test(filePath)
811
+ || /^\.devflow\/planning\/contracts\/[^/\\\x00-\x1F\x7F]+\/(?:EC-[A-Fa-f0-9]+\.json|control-events\.jsonl)$/u.test(filePath)
812
+ || filePath.startsWith(".devflow/planning/review-runs/")
813
+ || /^\.devflow\/planning\/phases\/[^/\\\x00-\x1F\x7F]+\/REVIEW\.md$/u.test(filePath);
766
814
  }
767
815
 
768
816
  function planningFeatureFromPath(filePath: string): string | null {
769
- const match = filePath.match(/^\.planning\/(?:requirements|features)\/([^/\\\x00-\x1F\x7F]+)(?:\/|$)/u);
817
+ const match = filePath.match(/^\.devflow\/planning\/(?:requirements|features)\/([^/\\\x00-\x1F\x7F]+)(?:\/|$)/u);
770
818
  return match?.[1] ?? null;
771
819
  }
772
820
 
@@ -1083,8 +1131,8 @@ function projectInitializationDirective(summary: string): string {
1083
1131
  return [
1084
1132
  "<devflow-project-initialization-directive>",
1085
1133
  "用户已批准完整项目初始化。现在处于执行模式;不要再创建 Todo、不要读取或写入 xd://devflow_contract。",
1086
- "执行 skill://workflow-project-context,按已确认的项目边界建立 .planning/PROJECT.md、.planning/navigation/INDEX.md、.context/spec/index.md,并按用户选择建立 full 代码索引。",
1087
- "只写项目初始化所需的 .planning/ 与 .context/ 控制产物;不得改动业务源码、依赖或配置。完成后运行项目初始化校验,报告生成文件和验证结果并停止,等待用户审查。",
1134
+ "执行 skill://workflow-project-context,按已确认的项目边界建立 .devflow/planning/PROJECT.md、.devflow/planning/navigation/INDEX.md、.devflow/context/spec/index.md,并按用户选择建立 full 代码索引。",
1135
+ "只写项目初始化所需的 .devflow/planning/ 与 .devflow/context/ 控制产物;不得改动业务源码、依赖或配置。完成后运行项目初始化校验,报告生成文件和验证结果并停止,等待用户审查。",
1088
1136
  summary,
1089
1137
  "</devflow-project-initialization-directive>",
1090
1138
  ].join("\n");
@@ -1177,7 +1225,7 @@ export function isShellControlMutation(toolName: string, input: unknown): boolea
1177
1225
  /workflow-orchestrator\/scripts\/(?:advance_state|init_state|init_workflow|sync_artifacts|requirement_graph|machine_evidence|execution_contract)\.rb[^\n]*--write/.test(
1178
1226
  command,
1179
1227
  );
1180
- const namesControlPath = [...CONTROL_PATHS, ...CONTROL_PREFIXES].some(item => command.includes(item)) || /\.planning\/requirements\//.test(command);
1228
+ const namesControlPath = [...CONTROL_PATHS, ...CONTROL_PREFIXES].some(item => command.includes(item)) || /\.devflow\/planning\/requirements\//.test(command);
1181
1229
  // `2>` and `2>>` only redirect stderr. They frequently accompany read-only
1182
1230
  // probes of control-plane files and must not be treated as a file mutation.
1183
1231
  // Keep bare `>`/`>>` and explicit stdout `1>`/`1>>` guarded.
@@ -1424,7 +1472,7 @@ export default function devflowCore(pi: ExtensionAPI) {
1424
1472
  const feature = activeContract.feature;
1425
1473
  const step = activeContract.step;
1426
1474
  if (!/^[\p{L}\p{N}._-]{1,160}$/u.test(feature) || !/^[\p{L}\p{N}._-]{1,160}$/u.test(step)) return;
1427
- const directory = path.join(cwd, ".planning", "evidence", feature);
1475
+ const directory = path.join(cwd, ".devflow/planning", "evidence", feature);
1428
1476
  const attempt = typeof extra.attempt === "number" && Number.isInteger(extra.attempt) && extra.attempt >= 0
1429
1477
  ? extra.attempt
1430
1478
  : undefined;
@@ -1619,7 +1667,7 @@ export default function devflowCore(pi: ExtensionAPI) {
1619
1667
  ? (rawStep as { id: string }).id
1620
1668
  : undefined;
1621
1669
  if (!feature || !step) return undefined;
1622
- const contractsDir = path.join(cwd, ".planning", "contracts", feature);
1670
+ const contractsDir = path.join(cwd, ".devflow/planning", "contracts", feature);
1623
1671
  if (!existsSync(contractsDir)) return undefined;
1624
1672
  const candidates = readdirSync(contractsDir)
1625
1673
  .filter(name => name.startsWith("EC-") && name.endsWith(".json"))
@@ -1755,7 +1803,7 @@ export default function devflowCore(pi: ExtensionAPI) {
1755
1803
  `初始化方式:${modeSummary}`,
1756
1804
  ].join("\n");
1757
1805
  const consequence = mode === "apply"
1758
- ? "确认后会创建 Devflow 的 .planning/ 与 .context/ 初始化产物;不会修改业务源码、依赖或项目配置。"
1806
+ ? "确认后会创建 Devflow 的 .devflow/planning/ 与 .devflow/context/ 初始化产物;不会修改业务源码、依赖或项目配置。"
1759
1807
  : "确认后只进入只读规划,不会创建工作流或写入项目文件。";
1760
1808
  const confirmed = await ctx.ui.confirm("确认项目初始化范围", `${summary}\n\n${consequence}`);
1761
1809
  if (!confirmed) {
@@ -2004,7 +2052,7 @@ export default function devflowCore(pi: ExtensionAPI) {
2004
2052
  const runtimeBootstrapAuthorizations = new Set<string>();
2005
2053
 
2006
2054
  async function enqueueControlledRolloverRequest(cwd: string, rolloverId: string, sourceSessionId: string) {
2007
- const requestPath = path.join(cwd, ".planning", "rollover-request.json");
2055
+ const requestPath = path.join(cwd, ".devflow/planning", "rollover-request.json");
2008
2056
  const temporary = `${requestPath}.${randomUUID()}.tmp`;
2009
2057
  await writeFile(temporary, JSON.stringify({ schema_version: 1, rollover_id: rolloverId, source_session_id: sourceSessionId }) + "\n", "utf8");
2010
2058
  await rename(temporary, requestPath);
@@ -2403,6 +2451,12 @@ export default function devflowCore(pi: ExtensionAPI) {
2403
2451
  pi.on("session_start", async (_event, ctx) => {
2404
2452
  projectRoot = ctx.cwd;
2405
2453
  sessionId = randomUUID();
2454
+ try {
2455
+ await migrateLegacyProjectLayout(ctx.cwd);
2456
+ } catch (error) {
2457
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
2458
+ return;
2459
+ }
2406
2460
  const result = await runHook(ctx.cwd, "start.py", {
2407
2461
  session_id: sessionId,
2408
2462
  cwd: ctx.cwd,
@@ -2736,7 +2790,7 @@ export default function devflowCore(pi: ExtensionAPI) {
2736
2790
  text: [
2737
2791
  "<devflow-planner-directive>",
2738
2792
  "用户已确认项目初始化的输入。你现在是 Planner,只允许只读分析和派发 project-scout / requirements-auditor / contract-auditor。",
2739
- "不得创建 .planning 文件、不得调用状态迁移、不得执行实现。",
2793
+ "不得创建 .devflow/planning 文件、不得调用状态迁移、不得执行实现。",
2740
2794
  "先输出:已知事实、待验证点、最少侦察任务和必须由用户决定的问题。没有证据时写 unknown。",
2741
2795
  initialization.summary,
2742
2796
  "</devflow-planner-directive>",
@@ -2841,7 +2895,7 @@ export default function devflowCore(pi: ExtensionAPI) {
2841
2895
  "--root", ctx.cwd,
2842
2896
  "--feature", activeContract.feature,
2843
2897
  "--step", activeContract.step,
2844
- "--contract", `.planning/contracts/${activeContract.feature}/${activeContract.contractId}.json`,
2898
+ "--contract", `.devflow/planning/contracts/${activeContract.feature}/${activeContract.contractId}.json`,
2845
2899
  "--obligations", "[]",
2846
2900
  "--review-agent", "devflow-code-reviewer",
2847
2901
  "--stage", "entry",
@@ -3625,7 +3679,7 @@ export default function devflowCore(pi: ExtensionAPI) {
3625
3679
  async execute(_id, params, _signal, _onUpdate, ctx) {
3626
3680
  const feature = normalizeContractSegment(params.feature, "feature");
3627
3681
  const taskId = normalizeContractSegment(params.taskId, "taskId");
3628
- const root = path.join(ctx.cwd, ".planning", "evidence", feature);
3682
+ const root = path.join(ctx.cwd, ".devflow/planning", "evidence", feature);
3629
3683
  const destination = path.join(root, `${taskId}.json`);
3630
3684
  const validatePack = (pack: unknown): string[] => {
3631
3685
  if (!pack || typeof pack !== "object" || Array.isArray(pack)) return ["pack must be an object"];
@@ -3718,7 +3772,7 @@ export default function devflowCore(pi: ExtensionAPI) {
3718
3772
  const written = await runRuby(ctx.cwd, "workflow-orchestrator/scripts/execution_contract.rb", createArgs);
3719
3773
  if (!controlPlaneSucceeded(written)) return renderResult(written, { action: input.action });
3720
3774
  const writtenPayload = parseJsonResult(written);
3721
- const destination = typeof writtenPayload?.path === "string" ? writtenPayload.path : ".planning/contracts/";
3775
+ const destination = typeof writtenPayload?.path === "string" ? writtenPayload.path : ".devflow/planning/contracts/";
3722
3776
  contract.contractPath = destination;
3723
3777
  activeContract = contract;
3724
3778
  contractAgentCalls = 0;
@@ -4264,7 +4318,7 @@ export default function devflowCore(pi: ExtensionAPI) {
4264
4318
  [
4265
4319
  "<devflow-planner-directive>",
4266
4320
  "用户已确认项目初始化的输入。你现在是 Planner,只允许只读分析和派发 project-scout / requirements-auditor / contract-auditor。",
4267
- "不得创建 .planning 文件、不得调用状态迁移、不得执行实现。",
4321
+ "不得创建 .devflow/planning 文件、不得调用状态迁移、不得执行实现。",
4268
4322
  "先输出:已知事实、待验证点、最少侦察任务和必须由用户决定的问题。没有证据时写 unknown。",
4269
4323
  initialization.summary,
4270
4324
  "</devflow-planner-directive>",
@@ -34,11 +34,11 @@ def _run_light_sync(root: Path, files: list[str], timeout: int) -> tuple[bool, s
34
34
  "--root",
35
35
  str(root),
36
36
  "--output",
37
- ".planning/code-index",
37
+ ".devflow/planning/code-index",
38
38
  "--changed-files",
39
39
  *files,
40
40
  ],
41
- [sys.executable, str(script), "validate", "--index", ".planning/code-index"],
41
+ [sys.executable, str(script), "validate", "--index", ".devflow/planning/code-index"],
42
42
  [
43
43
  sys.executable,
44
44
  str(script),
@@ -46,7 +46,7 @@ def _run_light_sync(root: Path, files: list[str], timeout: int) -> tuple[bool, s
46
46
  "--root",
47
47
  str(root),
48
48
  "--index",
49
- ".planning/code-index",
49
+ ".devflow/planning/code-index",
50
50
  ],
51
51
  ]
52
52
  output = []
@@ -11,6 +11,7 @@ import re
11
11
  import subprocess
12
12
  import tempfile
13
13
  import time
14
+ from datetime import datetime
14
15
  from contextlib import contextmanager
15
16
  from pathlib import Path
16
17
  from typing import Any, Iterator
@@ -26,16 +27,16 @@ DEFAULT_POLICY: dict[str, Any] = {
26
27
  "mode": "strict",
27
28
  "protected_roots": [],
28
29
  "required_evidence": [
29
- ".planning/rules/INDEX.md",
30
- ".context/spec/index.md",
31
- ".planning/navigation/INDEX.md",
30
+ ".devflow/planning/rules/INDEX.md",
31
+ ".devflow/context/spec/index.md",
32
+ ".devflow/planning/navigation/INDEX.md",
32
33
  ],
33
- "optional_evidence": [".planning/code-index/INDEX.md"],
34
+ "optional_evidence": [".devflow/planning/code-index/INDEX.md"],
34
35
  "allowed_before_gate": [
35
36
  "AGENTS.md",
36
37
  "README.md",
37
- ".planning/**",
38
- ".context/**",
38
+ ".devflow/planning/**",
39
+ ".devflow/context/**",
39
40
  ".agent-gates/**",
40
41
  ".omp/**",
41
42
  ".skills/**",
@@ -46,6 +47,8 @@ DEFAULT_POLICY: dict[str, Any] = {
46
47
  "light_timeout_seconds": 120,
47
48
  "full_file_threshold": 30,
48
49
  "ignore": [
50
+ ".devflow/planning/**",
51
+ ".devflow/context/**",
49
52
  ".planning/**",
50
53
  ".context/**",
51
54
  ".agent-gates/**",
@@ -122,18 +125,69 @@ def cli_dir_name() -> str:
122
125
  return ".omp"
123
126
 
124
127
 
128
+ def assert_project_layout_ready(root: Path) -> None:
129
+ legacy_planning = root / ".planning"
130
+ legacy_context = root / ".context"
131
+ planning_markers = ("STATE.md", "PROJECT.md", ".devflow.lock", "navigation/INDEX.md", "code-index/INDEX.md", "workflows", "contracts", "evidence", "review-runs", "requirements", "features", "handoffs", "artifacts", "phase-ownership.yaml")
132
+ context_markers = ("spec/index.md", "index.md", "project/index.md", "knowledge/index.md")
133
+ legacy_markers = [legacy_planning / item for item in planning_markers] + [legacy_context / item for item in context_markers]
134
+ if not any(item.exists() for item in legacy_markers):
135
+ return
136
+ try:
137
+ manifest = json.loads((root / ".devflow/project.json").read_text(encoding="utf-8"))
138
+ created_at = str(manifest.get("createdAt", "")).replace("Z", "+00:00")
139
+ datetime.fromisoformat(created_at)
140
+ valid_manifest = (
141
+ manifest.get("schemaVersion") == 1
142
+ and re.fullmatch(r"[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}", str(manifest.get("projectId", "")), re.I)
143
+ and bool(str(manifest.get("name", "")).strip())
144
+ and manifest.get("layoutVersion") in (None, 1, 2)
145
+ )
146
+ except (OSError, ValueError, TypeError, json.JSONDecodeError):
147
+ valid_manifest = False
148
+ manifest = {}
149
+ if not valid_manifest:
150
+ raise RuntimeError("DEVFLOW_LEGACY_LAYOUT_CONFIRMATION_REQUIRED: valid project manifest required")
151
+ try:
152
+ marker = json.loads((root / ".devflow/layout-migration.json").read_text(encoding="utf-8"))
153
+ migration_complete = marker.get("schemaVersion") == 1 and marker.get("status") == "complete" and isinstance(marker.get("migrated"), list)
154
+ except (OSError, TypeError, json.JSONDecodeError):
155
+ migration_complete = False
156
+ for relative in ("STATE.md", "workflows", "contracts", "evidence", "review-runs", "requirements", "features", "handoffs", "artifacts", "phase-ownership.yaml"):
157
+ if (legacy_planning / relative).exists() and not migration_complete:
158
+ raise RuntimeError(f"DEVFLOW_ACTIVE_LEGACY_LAYOUT: .planning/{relative} requires dedicated control-plane migration")
159
+ canonical_exists = (root / ".devflow/planning").exists() or (root / ".devflow/context").exists()
160
+ if manifest.get("layoutVersion") == 2 and not migration_complete:
161
+ raise RuntimeError("DEVFLOW_LEGACY_REINTRODUCTION: v2 project cannot import legacy layout")
162
+ if manifest.get("layoutVersion") == 2 and migration_complete:
163
+ planning_legacy = any((legacy_planning / item).exists() for item in planning_markers)
164
+ context_legacy = any((legacy_context / item).exists() for item in context_markers)
165
+ if (planning_legacy and not (root / ".devflow/planning").exists()) or (context_legacy and not (root / ".devflow/context").exists()):
166
+ raise RuntimeError("DEVFLOW_LEGACY_REINTRODUCTION: v2 project will not backfill a missing canonical directory")
167
+ if canonical_exists and not migration_complete:
168
+ raise RuntimeError("DEVFLOW_LAYOUT_CONFLICT: canonical and legacy layouts coexist without migration marker")
169
+ if not canonical_exists:
170
+ raise RuntimeError("DEVFLOW_LAYOUT_MIGRATION_REQUIRED: run project initialization")
171
+
172
+
125
173
  def project_root(event: dict[str, Any] | None = None) -> Path:
126
174
  event = event or {}
127
175
  explicit = os.environ.get("OMP_PROJECT_DIR")
128
176
  candidate = Path(explicit or event.get("cwd") or os.getcwd()).expanduser().resolve()
129
177
  if candidate.is_file():
130
178
  candidate = candidate.parent
179
+ # The project manifest is the authoritative root marker. Generated
180
+ # directories are deliberately ignored because a nested business module
181
+ # may legitimately use the same names.
131
182
  for current in (candidate, *candidate.parents):
132
- if any(
133
- (current / marker).exists()
134
- for marker in (".omp", ".agent-gates", ".planning", ".skills")
135
- ):
183
+ if (current / ".devflow" / "project.json").is_file():
184
+ assert_project_layout_ready(current)
185
+ return current
186
+ for current in (candidate, *candidate.parents):
187
+ if (current / ".git").exists():
188
+ assert_project_layout_ready(current)
136
189
  return current
190
+ assert_project_layout_ready(candidate)
137
191
  return candidate
138
192
 
139
193
 
@@ -274,7 +328,7 @@ def path_matches(path: str, patterns: list[str]) -> bool:
274
328
 
275
329
 
276
330
  def _navigation_codebase_roots(root: Path) -> list[str]:
277
- path = root / ".planning/navigation/INDEX.md"
331
+ path = root / ".devflow/planning/navigation/INDEX.md"
278
332
  try:
279
333
  text = path.read_text(encoding="utf-8")
280
334
  except (FileNotFoundError, PermissionError):
@@ -29,15 +29,15 @@ def detect_cli_dir(project_dir: Path) -> str:
29
29
  def load_config(project_dir: Path, cli_dir: str) -> dict:
30
30
  defaults = {
31
31
  "sources": {
32
- "state": ".planning/STATE.md",
33
- "workflow": ".context/workflow.md",
32
+ "state": ".devflow/planning/STATE.md",
33
+ "workflow": ".devflow/context/workflow.md",
34
34
  "indexes": [
35
- ".planning/rules/INDEX.md",
36
- ".context/spec/index.md",
37
- ".planning/navigation/INDEX.md",
38
- ".planning/code-index/INDEX.md",
35
+ ".devflow/planning/rules/INDEX.md",
36
+ ".devflow/context/spec/index.md",
37
+ ".devflow/planning/navigation/INDEX.md",
38
+ ".devflow/planning/code-index/INDEX.md",
39
39
  ],
40
- "lessons": ".context/lessons/README.md",
40
+ "lessons": ".devflow/context/lessons/README.md",
41
41
  "commands": f"{cli_dir}/commands/start.md",
42
42
  }
43
43
  }
@@ -196,7 +196,7 @@ def main():
196
196
 
197
197
  # 项目身份
198
198
  project_name = project_dir.name
199
- project_md = read_file(project_dir / ".planning" / "PROJECT.md")
199
+ project_md = read_file(project_dir / ".devflow/planning" / "PROJECT.md")
200
200
  for line in project_md.split("\n"):
201
201
  if line.startswith("- **Name**:"):
202
202
  project_name = line.split(":")[-1].strip()
@@ -205,13 +205,13 @@ def main():
205
205
  output.write(
206
206
  "<session-context>\n"
207
207
  f"你正在 {project_name} 项目中进行研发工作。\n"
208
- "该项目使用 .planning/ 跟踪研发流水线进度,状态写入和上下文同步由 OMP extension 强制执行。\n"
208
+ "该项目使用 .devflow/planning/ 跟踪研发流水线进度,状态写入和上下文同步由 OMP extension 强制执行。\n"
209
209
  "索引只用于加速定位;发现索引缺失或过期时,直接回退到 LSP、搜索和源码,并报告降级状态。\n"
210
210
  "</session-context>\n\n"
211
211
  )
212
212
 
213
213
  # 跨 clear 意图
214
- intent_path = project_dir / ".planning" / ".next-intent"
214
+ intent_path = project_dir / ".devflow/planning" / ".next-intent"
215
215
  intent = {}
216
216
  if intent_path.exists():
217
217
  try:
@@ -229,7 +229,7 @@ def main():
229
229
  output.write("\n</intent>\n\n")
230
230
 
231
231
  # Pipeline 状态
232
- state_path = sources.get("state", ".planning/STATE.md")
232
+ state_path = sources.get("state", ".devflow/planning/STATE.md")
233
233
  state_text = load_state_section(project_dir, state_path)
234
234
  if state_text:
235
235
  output.write("<pipeline-state>\n")
@@ -237,7 +237,7 @@ def main():
237
237
  output.write("\n</pipeline-state>\n\n")
238
238
 
239
239
  # 研发流程
240
- workflow_path = sources.get("workflow", ".context/workflow.md")
240
+ workflow_path = sources.get("workflow", ".devflow/context/workflow.md")
241
241
  workflow_text = read_file(project_dir / workflow_path)
242
242
  if workflow_text:
243
243
  output.write("<workflow>\n")
@@ -254,7 +254,7 @@ def main():
254
254
  output.write("</index-entrypoints>\n\n")
255
255
 
256
256
  # 经验教训
257
- lessons_path = sources.get("lessons", ".context/lessons/README.md")
257
+ lessons_path = sources.get("lessons", ".devflow/context/lessons/README.md")
258
258
  lessons_text = read_file(project_dir / lessons_path)
259
259
  if lessons_text and lessons_text.strip():
260
260
  output.write("<lessons>\n")
@@ -7,8 +7,8 @@ description: Generate or revise a low-fidelity wireframe proposal from controlle
7
7
 
8
8
  Read the controlled requirement baseline and the wireframe schema/registry. Produce exactly two candidate files:
9
9
 
10
- - .planning/features/{feature}/proposal.yaml
11
- - .planning/features/{feature}/questions.yaml
10
+ - .devflow/planning/features/{feature}/proposal.yaml
11
+ - .devflow/planning/features/{feature}/questions.yaml
12
12
 
13
13
  Use only registered element types and screen-level requirement_refs. Keep IDs stable during revision. Do not add API fields, coordinates, CSS, nested children, or approval fields. Emit valid YAML only and never claim that the proposal is validated or approved. The validator and Core decide legality, fingerprints, and approval.
14
14
 
@@ -11,10 +11,10 @@ Run the bundled validator through Core's `devflow_skill_script` tool:
11
11
  devflow_skill_script(
12
12
  script="wireframe-validate",
13
13
  args=[
14
- "--proposal", ".planning/features/<feature>/proposal.yaml",
15
- "--traceability", ".planning/requirements/<feature>/traceability.json",
16
- "--questions", ".planning/features/<feature>/questions.yaml",
17
- "--canonical-out", ".planning/features/<feature>/canonical.json"
14
+ "--proposal", ".devflow/planning/features/<feature>/proposal.yaml",
15
+ "--traceability", ".devflow/planning/requirements/<feature>/traceability.json",
16
+ "--questions", ".devflow/planning/features/<feature>/questions.yaml",
17
+ "--canonical-out", ".devflow/planning/features/<feature>/canonical.json"
18
18
  ]
19
19
  )
20
20
  ```