@pzy560117/codex-harness 0.1.4 → 0.1.6

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 (463) hide show
  1. package/README.md +1 -1
  2. package/package-source/AGENTS.md +48 -0
  3. package/package-source/PACKAGE.md +49 -0
  4. package/package-source/README.md +85 -0
  5. package/package-source/docs/codex-harness-engineering/templates/AGENTS.md +51 -0
  6. package/package-source/docs/codex-harness-engineering/templates/bootstrap-codex-harness.ps1 +780 -0
  7. package/package-source/docs/codex-harness-engineering/templates/ci/AGENTS.md +15 -0
  8. package/package-source/docs/codex-harness-engineering/templates/ci/github-action-codex-review.yml +110 -0
  9. package/package-source/docs/codex-harness-engineering/templates/ci/github-action-codex-task.yml +46 -0
  10. package/package-source/docs/codex-harness-engineering/templates/config/AGENTS.md +19 -0
  11. package/package-source/docs/codex-harness-engineering/templates/config/agents/architect.toml +18 -0
  12. package/package-source/docs/codex-harness-engineering/templates/config/agents/backend-worker.toml +15 -0
  13. package/package-source/docs/codex-harness-engineering/templates/config/agents/docs-researcher.toml +14 -0
  14. package/package-source/docs/codex-harness-engineering/templates/config/agents/docs-worker.toml +16 -0
  15. package/package-source/docs/codex-harness-engineering/templates/config/agents/explorer.toml +15 -0
  16. package/package-source/docs/codex-harness-engineering/templates/config/agents/failure-triage.toml +19 -0
  17. package/package-source/docs/codex-harness-engineering/templates/config/agents/frontend-worker.toml +15 -0
  18. package/package-source/docs/codex-harness-engineering/templates/config/agents/harness-writer.toml +16 -0
  19. package/package-source/docs/codex-harness-engineering/templates/config/agents/planner.toml +16 -0
  20. package/package-source/docs/codex-harness-engineering/templates/config/agents/readonly-research.toml +14 -0
  21. package/package-source/docs/codex-harness-engineering/templates/config/agents/reviewer.toml +14 -0
  22. package/package-source/docs/codex-harness-engineering/templates/config/agents/security-reviewer.toml +16 -0
  23. package/package-source/docs/codex-harness-engineering/templates/config/agents/stage1-reviewer.toml +16 -0
  24. package/package-source/docs/codex-harness-engineering/templates/config/agents/stage2-reviewer.toml +17 -0
  25. package/package-source/docs/codex-harness-engineering/templates/config/agents/test-planner.toml +18 -0
  26. package/package-source/docs/codex-harness-engineering/templates/config/agents/test-runner.toml +15 -0
  27. package/package-source/docs/codex-harness-engineering/templates/config/agents/visual-reviewer.toml +16 -0
  28. package/package-source/docs/codex-harness-engineering/templates/config/codex-agent-roles.md +24 -0
  29. package/package-source/docs/codex-harness-engineering/templates/config/codex-config.toml +38 -0
  30. package/package-source/docs/codex-harness-engineering/templates/config/codex-readme.md +67 -0
  31. package/package-source/docs/codex-harness-engineering/templates/config/env-check.ps1 +44 -0
  32. package/package-source/docs/codex-harness-engineering/templates/config/env.example +13 -0
  33. package/package-source/docs/codex-harness-engineering/templates/config/global-AGENTS.md +40 -0
  34. package/package-source/docs/codex-harness-engineering/templates/config/global-config.toml +19 -0
  35. package/package-source/docs/codex-harness-engineering/templates/config/mcp-config.toml +38 -0
  36. package/package-source/docs/codex-harness-engineering/templates/config/rules/agents.md +118 -0
  37. package/package-source/docs/codex-harness-engineering/templates/config/rules/coding-style.md +57 -0
  38. package/package-source/docs/codex-harness-engineering/templates/config/rules/constitution.md +290 -0
  39. package/package-source/docs/codex-harness-engineering/templates/config/rules/git.rules +41 -0
  40. package/package-source/docs/codex-harness-engineering/templates/config/rules/harness.rules +29 -0
  41. package/package-source/docs/codex-harness-engineering/templates/config/rules/patterns.md +59 -0
  42. package/package-source/docs/codex-harness-engineering/templates/config/rules/safety.rules +35 -0
  43. package/package-source/docs/codex-harness-engineering/templates/config/rules/testing.md +34 -0
  44. package/package-source/docs/codex-harness-engineering/templates/context/AGENTS.md +19 -0
  45. package/package-source/docs/codex-harness-engineering/templates/context/API_MAP.md +18 -0
  46. package/package-source/docs/codex-harness-engineering/templates/context/CHANGELOG_AI.md +11 -0
  47. package/package-source/docs/codex-harness-engineering/templates/context/CURRENT_TASK.md +114 -0
  48. package/package-source/docs/codex-harness-engineering/templates/context/DB_SCHEMA.md +14 -0
  49. package/package-source/docs/codex-harness-engineering/templates/context/DECISIONS.md +12 -0
  50. package/package-source/docs/codex-harness-engineering/templates/context/KNOWN_ISSUES.md +12 -0
  51. package/package-source/docs/codex-harness-engineering/templates/context/PROJECT_CONTEXT.md +14 -0
  52. package/package-source/docs/codex-harness-engineering/templates/context/architecture-brief.md +58 -0
  53. package/package-source/docs/codex-harness-engineering/templates/context/dev-plan.md +166 -0
  54. package/package-source/docs/codex-harness-engineering/templates/context/feature-pack.md +101 -0
  55. package/package-source/docs/codex-harness-engineering/templates/context/repo-map.md +102 -0
  56. package/package-source/docs/codex-harness-engineering/templates/context/service-dependency-matrix.yaml +25 -0
  57. package/package-source/docs/codex-harness-engineering/templates/contracts/AGENTS.md +17 -0
  58. package/package-source/docs/codex-harness-engineering/templates/contracts/README.md +24 -0
  59. package/package-source/docs/codex-harness-engineering/templates/contracts/openapi.yaml +182 -0
  60. package/package-source/docs/codex-harness-engineering/templates/contracts/orval.config.ts +20 -0
  61. package/package-source/docs/codex-harness-engineering/templates/contracts/prism-usage.md +41 -0
  62. package/package-source/docs/codex-harness-engineering/templates/design/AGENTS.md +21 -0
  63. package/package-source/docs/codex-harness-engineering/templates/design/ai-image-brief.md +122 -0
  64. package/package-source/docs/codex-harness-engineering/templates/design/assets/README.md +24 -0
  65. package/package-source/docs/codex-harness-engineering/templates/design/component-map.md +45 -0
  66. package/package-source/docs/codex-harness-engineering/templates/design/design-brief.md +183 -0
  67. package/package-source/docs/codex-harness-engineering/templates/design/design-tokens.json +88 -0
  68. package/package-source/docs/codex-harness-engineering/templates/design/frontend-architecture.md +165 -0
  69. package/package-source/docs/codex-harness-engineering/templates/design/image-to-frontend-spec.md +120 -0
  70. package/package-source/docs/codex-harness-engineering/templates/design/screen-states.md +157 -0
  71. package/package-source/docs/codex-harness-engineering/templates/design/ui-image-review.md +60 -0
  72. package/package-source/docs/codex-harness-engineering/templates/design/visual-parity-review.md +124 -0
  73. package/package-source/docs/codex-harness-engineering/templates/docs/AGENTS.md +19 -0
  74. package/package-source/docs/codex-harness-engineering/templates/docs/architecture-constraints.md +97 -0
  75. package/package-source/docs/codex-harness-engineering/templates/docs/code-semantics-and-navigation.md +54 -0
  76. package/package-source/docs/codex-harness-engineering/templates/docs/code-style-and-naming.md +116 -0
  77. package/package-source/docs/codex-harness-engineering/templates/docs/demo-readme.md +73 -0
  78. package/package-source/docs/codex-harness-engineering/templates/docs/directory-structure-template.md +88 -0
  79. package/package-source/docs/codex-harness-engineering/templates/docs/env-and-deployment-template.md +60 -0
  80. package/package-source/docs/codex-harness-engineering/templates/docs/frontend-quality-rules.md +165 -0
  81. package/package-source/docs/codex-harness-engineering/templates/docs/governance-auto-repair.md +82 -0
  82. package/package-source/docs/codex-harness-engineering/templates/docs/harness-architecture.md +78 -0
  83. package/package-source/docs/codex-harness-engineering/templates/docs/install-manifest-governance.md +307 -0
  84. package/package-source/docs/codex-harness-engineering/templates/docs/knowledge-architecture.md +241 -0
  85. package/package-source/docs/codex-harness-engineering/templates/docs/knowledge-import.md +108 -0
  86. package/package-source/docs/codex-harness-engineering/templates/docs/knowledge-lint.md +98 -0
  87. package/package-source/docs/codex-harness-engineering/templates/docs/mcp-knowledge-governance.md +24 -0
  88. package/package-source/docs/codex-harness-engineering/templates/docs/new-project-checklist.md +7 -0
  89. package/package-source/docs/codex-harness-engineering/templates/docs/new-project-usage.md +216 -0
  90. package/package-source/docs/codex-harness-engineering/templates/docs/project-agents-template.md +211 -0
  91. package/package-source/docs/codex-harness-engineering/templates/docs/prompt-knowledge-integration.md +100 -0
  92. package/package-source/docs/codex-harness-engineering/templates/docs/regression-rules.md +47 -0
  93. package/package-source/docs/codex-harness-engineering/templates/docs/requirement-prep-kit/README.md +3 -0
  94. package/package-source/docs/codex-harness-engineering/templates/docs/rule-governance.md +98 -0
  95. package/package-source/docs/codex-harness-engineering/templates/docs/service-dependency-matrix.md +70 -0
  96. package/package-source/docs/codex-harness-engineering/templates/docs/spec-to-ui-to-code-workflow.md +196 -0
  97. package/package-source/docs/codex-harness-engineering/templates/docs/task-session-strategy.md +133 -0
  98. package/package-source/docs/codex-harness-engineering/templates/docs/team-knowledge-sync.md +187 -0
  99. package/package-source/docs/codex-harness-engineering/templates/docs/trace-format.md +86 -0
  100. package/package-source/docs/codex-harness-engineering/templates/governance/AGENTS.md +18 -0
  101. package/package-source/docs/codex-harness-engineering/templates/governance/branch-protection-checklist.md +50 -0
  102. package/package-source/docs/codex-harness-engineering/templates/governance/feedback-evolution-loop.md +55 -0
  103. package/package-source/docs/codex-harness-engineering/templates/governance/retry-budget.yaml +30 -0
  104. package/package-source/docs/codex-harness-engineering/templates/governance/risk-levels.yaml +53 -0
  105. package/package-source/docs/codex-harness-engineering/templates/governance/sandbox-policy.md +13 -0
  106. package/package-source/docs/codex-harness-engineering/templates/hooks/AGENTS.md +15 -0
  107. package/package-source/docs/codex-harness-engineering/templates/hooks/hook-stop-verify.ps1 +871 -0
  108. package/package-source/docs/codex-harness-engineering/templates/hooks/hooks.json +40 -0
  109. package/package-source/docs/codex-harness-engineering/templates/knowledge/AGENTS.md +16 -0
  110. package/package-source/docs/codex-harness-engineering/templates/knowledge/catalog.md +6 -0
  111. package/package-source/docs/codex-harness-engineering/templates/knowledge/decisions/DECISION-HARNESS-001.md +39 -0
  112. package/package-source/docs/codex-harness-engineering/templates/knowledge/guidelines/GUIDELINE-RULES-001.md +30 -0
  113. package/package-source/docs/codex-harness-engineering/templates/knowledge/knowledge-catalog.md +41 -0
  114. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/memory/constitution.md +72 -0
  115. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/scripts/powershell/check-prerequisites.ps1 +148 -0
  116. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/scripts/powershell/common.ps1 +137 -0
  117. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/scripts/powershell/create-new-feature.ps1 +279 -0
  118. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/scripts/powershell/setup-plan.ps1 +61 -0
  119. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/scripts/powershell/update-agent-context.ps1 +448 -0
  120. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/templates/agent-file-template.md +28 -0
  121. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/templates/checklist-template.md +40 -0
  122. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/templates/e2e-plan-template.md +38 -0
  123. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/templates/plan-template.md +393 -0
  124. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/templates/spec-template.md +307 -0
  125. package/package-source/docs/codex-harness-engineering/templates/package-assets/.specify/templates/tasks-template.md +244 -0
  126. package/package-source/docs/codex-harness-engineering/templates/package-assets/AGENTS.md +19 -0
  127. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/architecture/constraints.md +98 -0
  128. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/AGENTS.md +25 -0
  129. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/README.md +198 -0
  130. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/START-HERE.md +66 -0
  131. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/agent-ecosystem-practices.md +140 -0
  132. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/best-practices.md +267 -0
  133. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/codex-global-rules-example.md +292 -0
  134. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/AGENTS.md +14 -0
  135. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/goal-templates.md +380 -0
  136. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/AGENTS.md +14 -0
  137. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/README.md +64 -0
  138. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/contracts/openapi.yaml +25 -0
  139. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/contracts/orval.config.ts +20 -0
  140. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/ai-image-brief.md +44 -0
  141. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/component-map.md +17 -0
  142. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/design-brief.md +58 -0
  143. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/frontend-architecture.md +107 -0
  144. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/image-to-frontend-spec.md +72 -0
  145. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/screen-states.md +25 -0
  146. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/design/ui-image-review.md +38 -0
  147. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/product/difficulty-research.md +39 -0
  148. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/product/page-inventory.md +5 -0
  149. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/product/prd-lite.md +41 -0
  150. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/product/requirement-interface-matrix.md +32 -0
  151. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/docs/product/state-matrix.yaml +14 -0
  152. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/packages/api-client/generated/model/Ticket.ts +6 -0
  153. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/packages/api-client/generated/ticket-api.ts +35 -0
  154. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/packages/api-client/http-client.ts +8 -0
  155. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/packages/ui/TicketFilterBar.tsx +72 -0
  156. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/plans/features/ticket-filter.dev-plan.md +48 -0
  157. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/progress.txt +1 -0
  158. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/stories/TicketFilterBar.stories.tsx +33 -0
  159. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/task.json +54 -0
  160. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/traces/DEMO-TICKET-FILTER-001-20260422-120000.json +74 -0
  161. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/ticket-filter-demo/verify.ps1 +42 -0
  162. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/global-rules-and-bootstrap.md +415 -0
  163. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/goal-harness-integration-guide.md +364 -0
  164. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/implementation-flow.md +290 -0
  165. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/implementation-guide.md +25 -0
  166. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/knowledge-surface-map.md +186 -0
  167. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/mode-matrix.md +57 -0
  168. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/new-project-usage.md +176 -0
  169. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/project-agents-template.md +168 -0
  170. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/spec-to-ui-to-code-workflow.md +196 -0
  171. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/superpowers-codex-solo-builder-playbook.md +676 -0
  172. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/AGENTS.md +22 -0
  173. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/context/AGENTS.md +14 -0
  174. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/context/API_MAP.md +18 -0
  175. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/context/CURRENT_TASK.md +89 -0
  176. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/context/dev-plan.md +166 -0
  177. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/contracts/AGENTS.md +14 -0
  178. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/contracts/README.md +24 -0
  179. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/contracts/prism-usage.md +41 -0
  180. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/AGENTS.md +14 -0
  181. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/component-map.md +45 -0
  182. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/design-brief.md +183 -0
  183. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/design-tokens.json +88 -0
  184. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/frontend-architecture.md +165 -0
  185. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/image-to-frontend-spec.md +120 -0
  186. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/screen-states.md +157 -0
  187. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/design/visual-parity-review.md +124 -0
  188. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/docs/AGENTS.md +14 -0
  189. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/docs/env-and-deployment-template.md +60 -0
  190. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/docs/frontend-quality-rules.md +161 -0
  191. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/docs/regression-rules.md +47 -0
  192. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/docs/trace-format.md +86 -0
  193. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/product/AGENTS.md +14 -0
  194. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/product/prd-lite.md +166 -0
  195. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/product/state-matrix.yaml +116 -0
  196. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/prompts/AGENTS.md +14 -0
  197. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/prompts/implement-one-task.md +150 -0
  198. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/prompts/repair-one-finding.md +70 -0
  199. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/spec/11-security-design.md +43 -0
  200. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/spec/AGENTS.md +14 -0
  201. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/AGENTS.md +14 -0
  202. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/EVIDENCE_PROTOCOL.md +54 -0
  203. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/NATURAL_LANGUAGE_TEST_CASES.md +690 -0
  204. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/REGRESSION_PLAN.md +28 -0
  205. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/TEST_STRATEGY.md +98 -0
  206. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/TRACEABILITY_MATRIX.md +23 -0
  207. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/templates/testing/verify-matrix.md +51 -0
  208. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/AGENTS.md +165 -0
  209. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/CHANGELOG.md +149 -0
  210. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/CLAUDE.md +61 -0
  211. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/CODE_OF_CONDUCT.md +83 -0
  212. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/CONTRIBUTING.md +465 -0
  213. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/README.md +1390 -0
  214. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/SECURITY.md +53 -0
  215. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/SPONSORING.md +43 -0
  216. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/SPONSORS.md +59 -0
  217. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/TROUBLESHOOTING.md +446 -0
  218. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/architect.md +232 -0
  219. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/build-error-resolver.md +119 -0
  220. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/chief-of-staff.md +155 -0
  221. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/code-reviewer.md +238 -0
  222. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/cpp-build-resolver.md +91 -0
  223. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/cpp-reviewer.md +79 -0
  224. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/database-reviewer.md +94 -0
  225. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/doc-updater.md +110 -0
  226. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/docs-lookup.md +68 -0
  227. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/e2e-runner.md +110 -0
  228. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/go-build-resolver.md +95 -0
  229. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/go-reviewer.md +83 -0
  230. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/harness-optimizer.md +35 -0
  231. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/java-build-resolver.md +154 -0
  232. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/java-reviewer.md +105 -0
  233. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/kotlin-build-resolver.md +119 -0
  234. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/loop-operator.md +37 -0
  235. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/planner.md +215 -0
  236. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/python-reviewer.md +106 -0
  237. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/pytorch-build-resolver.md +122 -0
  238. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/refactor-cleaner.md +92 -0
  239. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/rust-build-resolver.md +149 -0
  240. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/rust-reviewer.md +95 -0
  241. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/security-reviewer.md +112 -0
  242. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/tdd-guide.md +96 -0
  243. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/agents/typescript-reviewer.md +122 -0
  244. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/aside.md +173 -0
  245. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/build-fix.md +64 -0
  246. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/checkpoint.md +78 -0
  247. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/claw.md +51 -0
  248. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/code-review.md +43 -0
  249. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/context-budget.md +29 -0
  250. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/cpp-build.md +173 -0
  251. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/cpp-review.md +140 -0
  252. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/cpp-test.md +257 -0
  253. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/docs.md +32 -0
  254. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/e2e.md +389 -0
  255. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/eval.md +122 -0
  256. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/evolve.md +194 -0
  257. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/go-build.md +183 -0
  258. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/go-review.md +156 -0
  259. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/go-test.md +274 -0
  260. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/gradle-build.md +72 -0
  261. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/harness-audit.md +72 -0
  262. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/instinct-export.md +67 -0
  263. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/instinct-import.md +117 -0
  264. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/instinct-status.md +59 -0
  265. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/kotlin-build.md +176 -0
  266. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/kotlin-review.md +144 -0
  267. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/kotlin-test.md +315 -0
  268. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/learn-eval.md +117 -0
  269. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/learn.md +70 -0
  270. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/loop-start.md +33 -0
  271. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/loop-status.md +25 -0
  272. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/model-route.md +27 -0
  273. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/multi-backend.md +162 -0
  274. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/multi-execute.md +321 -0
  275. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/multi-frontend.md +162 -0
  276. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/multi-plan.md +278 -0
  277. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/plan.md +118 -0
  278. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/pm2.md +283 -0
  279. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/projects.md +39 -0
  280. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/promote.md +41 -0
  281. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/prompt-optimize.md +37 -0
  282. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/prune.md +31 -0
  283. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/python-review.md +319 -0
  284. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/quality-gate.md +30 -0
  285. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/refactor-clean.md +83 -0
  286. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/resume-session.md +154 -0
  287. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/rules-distill.md +11 -0
  288. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/rust-build.md +189 -0
  289. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/rust-review.md +146 -0
  290. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/rust-test.md +311 -0
  291. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/setup-pm.md +83 -0
  292. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/skill-create.md +176 -0
  293. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/skill-health.md +54 -0
  294. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/tdd.md +330 -0
  295. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/test-coverage.md +69 -0
  296. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/update-codemaps.md +73 -0
  297. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/update-docs.md +86 -0
  298. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/verify.md +60 -0
  299. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/contexts/dev.md +23 -0
  300. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/contexts/research.md +30 -0
  301. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/contexts/review.md +25 -0
  302. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/examples/CLAUDE.md +100 -0
  303. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/examples/django-api-CLAUDE.md +308 -0
  304. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/examples/go-microservice-CLAUDE.md +267 -0
  305. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/examples/rust-api-CLAUDE.md +285 -0
  306. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/examples/saas-nextjs-CLAUDE.md +166 -0
  307. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/examples/user-CLAUDE.md +118 -0
  308. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/hooks/README.md +220 -0
  309. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/plugins/README.md +89 -0
  310. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/the-openclaw-guide.md +471 -0
  311. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/the-security-guide.md +206 -0
  312. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/README.md +60 -0
  313. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/app/Mobile_App_Production_Readiness_Framework_/347/247/273/345/212/250/347/253/257/345/205/250/345/271/263/345/217/260/347/224/237/344/272/247/345/217/257/344/270/212/347/272/277/350/247/204/350/214/203.md +2457 -0
  314. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/app/catalog.md +33 -0
  315. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/architecture.md +358 -0
  316. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/common/AI_Coding_Production_Control_Framework_AI/345/206/231/345/256/214/347/232/204/344/273/243/347/240/201/345/246/202/344/275/225/344/270/215/345/244/261/346/216/247.md +2055 -0
  317. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/common/catalog.md +34 -0
  318. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/initial-content.md +296 -0
  319. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/external-knowledge/integration-roadmap.md +221 -0
  320. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/architecture-constraints.md +95 -0
  321. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/code-semantics-and-navigation.md +17 -0
  322. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/code-style-and-naming.md +116 -0
  323. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/frontend-quality-rules.md +138 -0
  324. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/governance-auto-repair.md +82 -0
  325. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/mcp-knowledge-governance.md +24 -0
  326. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/service-dependency-matrix.md +55 -0
  327. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/harness/speckit-requirements-gate.md +260 -0
  328. package/package-source/docs/codex-harness-engineering/templates/package-assets/root/PACKAGE.md +49 -0
  329. package/package-source/docs/codex-harness-engineering/templates/package-assets/root/README.md +52 -0
  330. package/package-source/docs/codex-harness-engineering/templates/package-assets/root/init-project.ps1 +51 -0
  331. package/package-source/docs/codex-harness-engineering/templates/package-assets/root/install-agent-here.ps1 +57 -0
  332. package/package-source/docs/codex-harness-engineering/templates/package-assets/root/install-agent.ps1 +2506 -0
  333. package/package-source/docs/codex-harness-engineering/templates/package-assets/root/install-user.ps1 +29 -0
  334. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/agents.md +115 -0
  335. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/coding-style.md +57 -0
  336. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/constitution.md +290 -0
  337. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/git.rules +41 -0
  338. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/harness.rules +29 -0
  339. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/patterns.md +59 -0
  340. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/safety.rules +35 -0
  341. package/package-source/docs/codex-harness-engineering/templates/package-assets/rules/testing.md +34 -0
  342. package/package-source/docs/codex-harness-engineering/templates/package-assets/scripts/ai-workflow/check-ai-sync-drift.ps1 +205 -0
  343. package/package-source/docs/codex-harness-engineering/templates/package-assets/scripts/ai-workflow/sync-ai-config-to-targets.ps1 +826 -0
  344. package/package-source/docs/codex-harness-engineering/templates/package-assets/scripts/ai-workflow/sync-targets.example.json +35 -0
  345. package/package-source/docs/codex-harness-engineering/templates/package-assets/scripts/harness/harness-governance-check.ps1 +864 -0
  346. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/HOW_TO_USE_SKILLS.md +91 -0
  347. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/academic-mermaid-diagrams/SKILL.md +172 -0
  348. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/ai-config-git-sync/SKILL.md +152 -0
  349. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/ai-config-git-sync/references/command-recipes.md +92 -0
  350. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/ai-ui-prompts/SKILL.md +350 -0
  351. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/allure-report/SKILL.md +230 -0
  352. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/allure-report/examples/usage.md +99 -0
  353. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/allure-report/scripts/view-allure.ps1 +28 -0
  354. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/api-auto-testing/SKILL.md +329 -0
  355. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/api-contract-template/SKILL.md +88 -0
  356. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/api-design/SKILL.md +139 -0
  357. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/api-integration/SKILL.md +302 -0
  358. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/architect/SKILL.md +211 -0
  359. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/auto-commit/SKILL.md +324 -0
  360. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/backend-patterns/SKILL.md +582 -0
  361. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/baseline-ui/SKILL.md +85 -0
  362. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/better-icons/SKILL.md +129 -0
  363. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/brand-design-md/README.md +215 -0
  364. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/brand-design-md/SKILL.md +191 -0
  365. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/browser-e2e-testing/SKILL.md +305 -0
  366. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/build-error-resolver/SKILL.md +532 -0
  367. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/build-fix/SKILL.md +34 -0
  368. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/business-rule-spec/SKILL.md +99 -0
  369. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/celery-tasks/SKILL.md +95 -0
  370. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/checkpoint/SKILL.md +79 -0
  371. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/cicd/SKILL.md +167 -0
  372. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/claude-openrouter-clash-debug/SKILL.md +100 -0
  373. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/claude-openrouter-clash-debug/references/windows-openrouter-clash-playbook.md +94 -0
  374. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/claude-openrouter-clash-debug/scripts/diagnose-openrouter-route.ps1 +282 -0
  375. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/claude-openrouter-clash-debug/scripts/ensure-openrouter-rule.ps1 +101 -0
  376. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/clickhouse-io/SKILL.md +429 -0
  377. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/code-review/SKILL.md +171 -0
  378. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/code-reviewer/SKILL.md +104 -0
  379. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/coding-standards/SKILL.md +520 -0
  380. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/consistency-checklist/SKILL.md +57 -0
  381. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/continuous-learning/SKILL.md +80 -0
  382. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/continuous-learning/config.json +18 -0
  383. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/continuous-learning/evaluate-session.sh +60 -0
  384. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/core-rules/SKILL.md +78 -0
  385. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/data-flow-spec/SKILL.md +63 -0
  386. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/database/SKILL.md +147 -0
  387. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/deep-interview/SKILL.md +154 -0
  388. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/django-drf/SKILL.md +97 -0
  389. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/doc-updater/SKILL.md +452 -0
  390. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/docker/SKILL.md +216 -0
  391. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/docx/SKILL.md +105 -0
  392. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/e2e/SKILL.md +364 -0
  393. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/e2e-runner/SKILL.md +708 -0
  394. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/error-handling/SKILL.md +245 -0
  395. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/eval/SKILL.md +125 -0
  396. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/eval-harness/SKILL.md +226 -0
  397. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/example-skill/README.md +37 -0
  398. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/example-skill/SKILL.md +141 -0
  399. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/example-skill/examples/usage.md +76 -0
  400. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/example-skill/resources/config.json +21 -0
  401. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/example-skill/scripts/helper.py +24 -0
  402. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/exception-handling-spec/SKILL.md +88 -0
  403. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/find-skill/SKILL.md +95 -0
  404. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/fixing-accessibility/SKILL.md +136 -0
  405. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/fixing-metadata/SKILL.md +111 -0
  406. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/fixing-motion-performance/SKILL.md +151 -0
  407. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/frontend-design/SKILL.md +58 -0
  408. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/frontend-first-workflow/SKILL.md +187 -0
  409. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/frontend-patterns/SKILL.md +631 -0
  410. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/fullstack-workflow/SKILL.md +85 -0
  411. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/git-workflow/SKILL.md +108 -0
  412. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/git-xianyu-analyzer/SKILL.md +346 -0
  413. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/git-xianyu-analyzer/scripts/download_images.py +112 -0
  414. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/github-research/SKILL.md +213 -0
  415. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/glue-coding/SKILL.md +389 -0
  416. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/glue-coding-workflow/SKILL.md +230 -0
  417. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/harness-surface-sync/SKILL.md +204 -0
  418. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/harness-surface-sync/references/current-repo-sync-matrix.md +150 -0
  419. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/harness-surface-sync/references/stale-patterns.md +65 -0
  420. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/agents/openai.yaml +4 -0
  421. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/adapt.md +190 -0
  422. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/animate.md +173 -0
  423. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/audit.md +134 -0
  424. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/bolder.md +113 -0
  425. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/brand.md +104 -0
  426. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/clarify.md +174 -0
  427. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/cognitive-load.md +106 -0
  428. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/color-and-contrast.md +105 -0
  429. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/colorize.md +154 -0
  430. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/craft.md +138 -0
  431. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/critique.md +213 -0
  432. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/delight.md +302 -0
  433. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/distill.md +111 -0
  434. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/document.md +427 -0
  435. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/extract.md +70 -0
  436. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/harden.md +347 -0
  437. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/heuristics-scoring.md +234 -0
  438. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/interaction-design.md +195 -0
  439. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/layout.md +141 -0
  440. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/live.md +513 -0
  441. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/motion-design.md +99 -0
  442. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/onboard.md +234 -0
  443. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/optimize.md +258 -0
  444. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/overdrive.md +130 -0
  445. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/personas.md +178 -0
  446. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/polish.md +232 -0
  447. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/product.md +62 -0
  448. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/quieter.md +99 -0
  449. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/responsive-design.md +114 -0
  450. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/shape.md +136 -0
  451. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/impeccable/reference/spatial-design.md +100 -0
  452. package/package-source/install-manifest.json +523 -0
  453. package/package-source/install-manifest.schema.json +80 -0
  454. package/package-source/tools/install/ai-workflow/check-ai-sync-drift.ps1 +205 -0
  455. package/package-source/tools/install/ai-workflow/sync-ai-config-to-targets.ps1 +826 -0
  456. package/package-source/tools/install/ai-workflow/sync-targets.example.json +35 -0
  457. package/package-source/tools/install/bootstrap-codex-harness.ps1 +776 -0
  458. package/package-source/tools/install/env-check.ps1 +40 -0
  459. package/package-source/tools/install/init-project.ps1 +51 -0
  460. package/package-source/tools/install/install-agent-here.ps1 +57 -0
  461. package/package-source/tools/install/install-agent.ps1 +2513 -0
  462. package/package-source/tools/install/install-user.ps1 +29 -0
  463. package/package.json +1 -1
@@ -0,0 +1,2513 @@
1
+ param(
2
+ [string]$ProjectRoot = "",
3
+ [ValidateSet("full", "user", "project", "vendor")]
4
+ [string]$Mode = "full",
5
+ [ValidateSet("user", "project", "vendor")]
6
+ [string]$Scope = "",
7
+ [Alias("DryRun")]
8
+ [switch]$Plan,
9
+ [switch]$UpgradePlan,
10
+ [switch]$UninstallPlan,
11
+ [switch]$MigratePlan,
12
+ [switch]$MigrateApply,
13
+ [switch]$Upgrade,
14
+ [switch]$Uninstall,
15
+ [switch]$Confirm,
16
+ [switch]$Force,
17
+ [switch]$InitSmoke,
18
+ [switch]$CommitBaseline,
19
+ [switch]$SkipBaselineCommit,
20
+ [switch]$InitGitIfNeeded
21
+ )
22
+
23
+ Set-StrictMode -Version Latest
24
+ $ErrorActionPreference = "Stop"
25
+
26
+ function Get-PackageRoot {
27
+ return [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\.."))
28
+ }
29
+
30
+ function Write-Step {
31
+ param([string]$Message)
32
+ Write-Host ("[install-agent] {0}" -f $Message)
33
+ }
34
+
35
+ function Normalize-ManifestPath {
36
+ param(
37
+ [string]$Path,
38
+ [string]$Label,
39
+ [switch]$AllowEnvironmentPath
40
+ )
41
+
42
+ $raw = if ($null -eq $Path) { "" } else { [string]$Path }
43
+ $normalized = $raw.Trim().Replace('\', '/')
44
+ while ($normalized.StartsWith('./', [System.StringComparison]::Ordinal)) {
45
+ $normalized = $normalized.Substring(2)
46
+ }
47
+
48
+ if (-not $AllowEnvironmentPath) {
49
+ $normalized = $normalized.TrimStart('/')
50
+ }
51
+
52
+ if ([string]::IsNullOrWhiteSpace($normalized)) {
53
+ throw "$Label 不能为空。"
54
+ }
55
+
56
+ if ((-not $AllowEnvironmentPath) -and ([System.IO.Path]::IsPathRooted($normalized) -or $normalized -match '^[A-Za-z]:')) {
57
+ throw "$Label 不能是 rooted path: $normalized"
58
+ }
59
+
60
+ $pathBody = $normalized.TrimEnd('/')
61
+ foreach ($segment in ($pathBody -split '/')) {
62
+ if ($segment -eq '..') {
63
+ throw "$Label 不能包含 .. 段: $normalized"
64
+ }
65
+ }
66
+
67
+ return $normalized
68
+ }
69
+
70
+ function Resolve-ManifestSourcePath {
71
+ param(
72
+ [string]$SourceRoot,
73
+ [string]$SourceRelativePath
74
+ )
75
+
76
+ $normalizedSource = Normalize-ManifestPath -Path $SourceRelativePath -Label "install manifest source"
77
+ if ($normalizedSource.StartsWith('templates/', [System.StringComparison]::OrdinalIgnoreCase)) {
78
+ return Join-Path (Join-Path $SourceRoot "docs\codex-harness-engineering") $normalizedSource
79
+ }
80
+
81
+ return Join-Path $SourceRoot $normalizedSource
82
+ }
83
+
84
+ function Resolve-ManifestTargetPath {
85
+ param(
86
+ [string]$ProjectRoot,
87
+ [string]$DestinationRelativePath,
88
+ [string]$Scope
89
+ )
90
+
91
+ $normalizedDestination = Normalize-ManifestPath -Path $DestinationRelativePath -Label "install manifest destination" -AllowEnvironmentPath
92
+ if ($Scope -eq "user") {
93
+ $expanded = [Environment]::ExpandEnvironmentVariables($normalizedDestination.Replace('/', '\'))
94
+ return [System.IO.Path]::GetFullPath($expanded)
95
+ }
96
+
97
+ return [System.IO.Path]::GetFullPath((Join-Path $ProjectRoot $normalizedDestination))
98
+ }
99
+
100
+ function Read-InstallManifest {
101
+ param(
102
+ [string]$SourceRoot,
103
+ [string]$ProjectRoot
104
+ )
105
+
106
+ $manifestPath = Join-Path $SourceRoot "install-manifest.json"
107
+ if (-not (Test-Path -LiteralPath $manifestPath -PathType Leaf)) {
108
+ throw "找不到 install manifest: $manifestPath"
109
+ }
110
+
111
+ try {
112
+ $manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json
113
+ }
114
+ catch {
115
+ throw "install manifest 不是合法 JSON: $manifestPath"
116
+ }
117
+
118
+ if ([string]$manifest.package -ne "codex-harness") {
119
+ throw "install manifest package 必须是 codex-harness。"
120
+ }
121
+
122
+ if ([string]::IsNullOrWhiteSpace([string]$manifest.version)) {
123
+ throw "install manifest version 不能为空。"
124
+ }
125
+
126
+ $installModes = @($manifest.installModes)
127
+ if ($installModes.Count -eq 0) {
128
+ throw "install manifest 缺少 installModes。"
129
+ }
130
+
131
+ $modeNames = @($installModes | ForEach-Object { [string]$_.name })
132
+ foreach ($requiredMode in @("user", "project", "vendor")) {
133
+ if ($modeNames -notcontains $requiredMode) {
134
+ throw "install manifest 缺少 install mode: $requiredMode"
135
+ }
136
+ }
137
+
138
+ $entries = @($manifest.entries)
139
+ if ($entries.Count -eq 0) {
140
+ throw "install manifest 缺少 entries。"
141
+ }
142
+
143
+ $scopes = @("project", "user", "vendor")
144
+ $validatedEntries = New-Object System.Collections.Generic.List[object]
145
+ for ($index = 0; $index -lt $entries.Count; $index++) {
146
+ $entry = $entries[$index]
147
+ $source = Normalize-ManifestPath -Path ([string]$entry.source) -Label "install manifest entries[$index].source"
148
+ $destination = Normalize-ManifestPath -Path ([string]$entry.destination) -Label "install manifest entries[$index].destination" -AllowEnvironmentPath
149
+ $scope = [string]$entry.scope
150
+ $kind = [string]$entry.kind
151
+
152
+ if ($scopes -notcontains $scope) {
153
+ throw "install manifest entries[$index].scope 不支持: $scope"
154
+ }
155
+
156
+ if ([string]::IsNullOrWhiteSpace($kind)) {
157
+ throw "install manifest entries[$index].kind 不能为空。"
158
+ }
159
+
160
+ $sourcePath = Resolve-ManifestSourcePath -SourceRoot $SourceRoot -SourceRelativePath $source
161
+ $sourceKind = ""
162
+ if (Test-Path -LiteralPath $sourcePath -PathType Leaf) {
163
+ $sourceKind = "file"
164
+ }
165
+ elseif (Test-Path -LiteralPath $sourcePath -PathType Container) {
166
+ $sourceKind = "directory"
167
+ }
168
+ else {
169
+ throw "install manifest entries[$index].source 指向不存在路径: $source"
170
+ }
171
+
172
+ $validatedEntries.Add([pscustomobject]@{
173
+ Source = $source
174
+ SourcePath = [System.IO.Path]::GetFullPath($sourcePath)
175
+ SourceKind = $sourceKind
176
+ Destination = $destination
177
+ TargetPath = Resolve-ManifestTargetPath -ProjectRoot $ProjectRoot -DestinationRelativePath $destination -Scope $scope
178
+ Scope = $scope
179
+ Kind = $kind
180
+ Mutable = [bool]$entry.mutable
181
+ })
182
+ }
183
+
184
+ return [pscustomobject]@{
185
+ Path = $manifestPath
186
+ Manifest = $manifest
187
+ Entries = [object[]]$validatedEntries.ToArray()
188
+ }
189
+ }
190
+
191
+ function Write-InstallPlan {
192
+ param(
193
+ [object]$ManifestInfo,
194
+ [string]$ProjectRoot,
195
+ [string]$AgentsRoot,
196
+ [string]$InstallMode,
197
+ [switch]$ThinProjectProfile
198
+ )
199
+
200
+ Write-Output "Install plan."
201
+ Write-Output "PlanOnly: True"
202
+ Write-Output "No files will be changed."
203
+ Write-Output ("ProjectRoot: {0}" -f $ProjectRoot)
204
+ Write-Output ("AgentsRoot: {0}" -f $AgentsRoot)
205
+ Write-Output ("Mode: {0}" -f $InstallMode)
206
+ Write-Output ("Manifest: {0}" -f $ManifestInfo.Path)
207
+ Write-Output ("Package: {0}" -f [string]$ManifestInfo.Manifest.package)
208
+ Write-Output ("SchemaVersion: {0}" -f [string]$ManifestInfo.Manifest.schemaVersion)
209
+ Write-Output ("Status: {0}" -f [string]$ManifestInfo.Manifest.status)
210
+ $plannedEntries = Get-ManifestEntriesForMode -ManifestInfo $ManifestInfo -InstallMode $InstallMode -ThinProjectProfile:$ThinProjectProfile.IsPresent
211
+ Write-Output ("Entries: {0}" -f @($plannedEntries).Count)
212
+
213
+ foreach ($entry in @($plannedEntries)) {
214
+ Write-Output ("- scope={0} kind={1} mutable={2} sourceKind={3}" -f $entry.Scope, $entry.Kind, $entry.Mutable, $entry.SourceKind)
215
+ Write-Output (" source: {0}" -f $entry.Source)
216
+ Write-Output (" destination: {0}" -f $entry.Destination)
217
+ Write-Output (" target: {0}" -f $entry.TargetPath)
218
+ }
219
+ }
220
+
221
+ function Get-ManifestEntriesForMode {
222
+ param(
223
+ [object]$ManifestInfo,
224
+ [string]$InstallMode,
225
+ [switch]$ThinProjectProfile
226
+ )
227
+
228
+ $entries = @($ManifestInfo.Entries)
229
+ if ($InstallMode -eq "full") {
230
+ return $entries
231
+ }
232
+
233
+ $modeEntries = @($entries | Where-Object { [string]$_.Scope -eq $InstallMode })
234
+ if ($InstallMode -eq "project" -and $ThinProjectProfile.IsPresent) {
235
+ $legacyProjectDestinations = @(
236
+ "docs/testing/",
237
+ "docs/harness/",
238
+ "docs/requirement-prep-kit/",
239
+ "docs/knowledge/"
240
+ )
241
+
242
+ return @($modeEntries | Where-Object {
243
+ $destination = ([string]$_.Destination).Replace('\', '/')
244
+ $isLegacyProjectDestination = $false
245
+ foreach ($legacyDestination in $legacyProjectDestinations) {
246
+ if ($destination.StartsWith($legacyDestination, [System.StringComparison]::OrdinalIgnoreCase)) {
247
+ $isLegacyProjectDestination = $true
248
+ break
249
+ }
250
+ }
251
+
252
+ -not $isLegacyProjectDestination
253
+ })
254
+ }
255
+
256
+ return $modeEntries
257
+ }
258
+
259
+ function Get-InstallManifestVersion {
260
+ param([object]$ManifestInfo)
261
+
262
+ $version = [string]$ManifestInfo.Manifest.version
263
+ if ([string]::IsNullOrWhiteSpace($version)) {
264
+ throw "install manifest version 不能为空。"
265
+ }
266
+
267
+ return $version
268
+ }
269
+
270
+ function Get-PackageSourceCommit {
271
+ param([string]$PackageRoot)
272
+
273
+ $aiKitManifestPath = Join-Path $PackageRoot "ai-sync\ai-kit-manifest.json"
274
+ if (-not (Test-Path -LiteralPath $aiKitManifestPath -PathType Leaf)) {
275
+ return ""
276
+ }
277
+
278
+ try {
279
+ $aiKitManifest = Get-Content -LiteralPath $aiKitManifestPath -Raw | ConvertFrom-Json
280
+ return [string]$aiKitManifest.source.commit
281
+ }
282
+ catch {
283
+ return ""
284
+ }
285
+ }
286
+
287
+ function Read-PackageLockOrNull {
288
+ param([string]$ProjectRoot)
289
+
290
+ $lockPath = Join-Path $ProjectRoot ".codex-harness\locks\package.lock.json"
291
+ if (-not (Test-Path -LiteralPath $lockPath -PathType Leaf)) {
292
+ return $null
293
+ }
294
+
295
+ try {
296
+ $lockDocument = Get-Content -LiteralPath $lockPath -Raw | ConvertFrom-Json
297
+ }
298
+ catch {
299
+ throw "package lock 不是合法 JSON: $lockPath"
300
+ }
301
+
302
+ return [pscustomobject]@{
303
+ Path = $lockPath
304
+ Document = $lockDocument
305
+ }
306
+ }
307
+
308
+ function Get-InstallFileSystemPath {
309
+ param([string]$Path)
310
+ $fullPath = [System.IO.Path]::GetFullPath($Path)
311
+ if ($env:OS -eq "Windows_NT" -and -not $fullPath.StartsWith("\\?\", [System.StringComparison]::Ordinal)) {
312
+ if ($fullPath.StartsWith("\\", [System.StringComparison]::Ordinal)) {
313
+ return "\\?\UNC\" + $fullPath.Substring(2)
314
+ }
315
+
316
+ return "\\?\" + $fullPath
317
+ }
318
+
319
+ return $fullPath
320
+ }
321
+
322
+ function ConvertFrom-InstallFileSystemPath {
323
+ param([string]$Path)
324
+
325
+ if ($Path.StartsWith("\\?\UNC\", [System.StringComparison]::Ordinal)) {
326
+ return "\\" + $Path.Substring(8)
327
+ }
328
+
329
+ if ($Path.StartsWith("\\?\", [System.StringComparison]::Ordinal)) {
330
+ return $Path.Substring(4)
331
+ }
332
+
333
+ return $Path
334
+ }
335
+
336
+ function Get-InstallChildFiles {
337
+ param([string]$Directory)
338
+
339
+ $directoryInfo = [System.IO.DirectoryInfo]::new((Get-InstallFileSystemPath -Path $Directory))
340
+ return @(
341
+ $directoryInfo.EnumerateFiles("*", [System.IO.SearchOption]::AllDirectories) |
342
+ ForEach-Object {
343
+ [pscustomobject]@{
344
+ FullName = ConvertFrom-InstallFileSystemPath -Path $_.FullName
345
+ }
346
+ }
347
+ )
348
+ }
349
+
350
+ function Get-InstallFileSha256 {
351
+ param([string]$Path)
352
+
353
+ $fileSystemPath = Get-InstallFileSystemPath -Path $Path
354
+ $hashAlgorithm = [System.Security.Cryptography.SHA256]::Create()
355
+ $stream = $null
356
+ try {
357
+ $stream = [System.IO.File]::OpenRead($fileSystemPath)
358
+ $hashBytes = $hashAlgorithm.ComputeHash($stream)
359
+ return (($hashBytes | ForEach-Object { $_.ToString("x2") }) -join "")
360
+ }
361
+ finally {
362
+ if ($null -ne $stream) {
363
+ $stream.Dispose()
364
+ }
365
+
366
+ $hashAlgorithm.Dispose()
367
+ }
368
+ }
369
+
370
+ function Get-LockManagedFileByPath {
371
+ param(
372
+ [object]$LockDocument,
373
+ [string]$Destination
374
+ )
375
+
376
+ $normalizedDestination = Normalize-ManifestPath -Path $Destination -Label "managed file destination" -AllowEnvironmentPath
377
+ foreach ($managedFile in @($LockDocument.managedFiles)) {
378
+ $managedPath = Normalize-ManifestPath -Path ([string]$managedFile.path) -Label "managed file path" -AllowEnvironmentPath
379
+ if ($managedPath.Equals($normalizedDestination, [System.StringComparison]::OrdinalIgnoreCase)) {
380
+ return $managedFile
381
+ }
382
+ }
383
+
384
+ return $null
385
+ }
386
+
387
+ function Get-UpgradePlanFileDecision {
388
+ param(
389
+ [object]$LockDocument,
390
+ [string]$Destination,
391
+ [string]$SourcePath,
392
+ [string]$TargetPath
393
+ )
394
+
395
+ $lockManagedFile = Get-LockManagedFileByPath -LockDocument $LockDocument -Destination $Destination
396
+ if ($null -eq $lockManagedFile) {
397
+ return [pscustomobject]@{
398
+ Action = "no-lock-entry"
399
+ Reason = "lock 中缺少 managedFiles 记录。"
400
+ }
401
+ }
402
+
403
+ if (-not (Test-Path -LiteralPath $TargetPath -PathType Leaf)) {
404
+ return [pscustomobject]@{
405
+ Action = "install-missing"
406
+ Reason = "目标文件缺失,可从当前包补齐。"
407
+ }
408
+ }
409
+
410
+ $actualSha256 = Get-InstallFileSha256 -Path $TargetPath
411
+ $lockedSha256 = ([string]$lockManagedFile.sha256).ToLowerInvariant()
412
+ $packageSha256 = Get-InstallFileSha256 -Path $SourcePath
413
+ if ($actualSha256 -ne $lockedSha256) {
414
+ return [pscustomobject]@{
415
+ Action = "blocked-user-drift"
416
+ Reason = "目标文件已偏离 lock,升级前需要人工确认。"
417
+ }
418
+ }
419
+
420
+ if ($actualSha256 -eq $packageSha256) {
421
+ return [pscustomobject]@{
422
+ Action = "keep"
423
+ Reason = "目标文件与当前包一致。"
424
+ }
425
+ }
426
+
427
+ return [pscustomobject]@{
428
+ Action = "update-immutable"
429
+ Reason = "目标文件未被用户改动,可由升级命令覆盖。"
430
+ }
431
+ }
432
+
433
+ function Write-UpgradePlanItem {
434
+ param(
435
+ [object]$Entry,
436
+ [string]$Action,
437
+ [string]$Source,
438
+ [string]$Destination,
439
+ [string]$Target,
440
+ [string]$Reason
441
+ )
442
+
443
+ Write-Output ("- action={0} scope={1} kind={2} mutable={3}" -f $Action, $Entry.Scope, $Entry.Kind, $Entry.Mutable)
444
+ Write-Output (" source: {0}" -f $Source)
445
+ Write-Output (" destination: {0}" -f $Destination)
446
+ Write-Output (" target: {0}" -f $Target)
447
+ Write-Output (" reason: {0}" -f $Reason)
448
+ }
449
+
450
+ function Write-UpgradePlan {
451
+ param(
452
+ [object]$ManifestInfo,
453
+ [string]$ProjectRoot,
454
+ [string]$AgentsRoot,
455
+ [string]$RequestedMode
456
+ )
457
+
458
+ Write-Output "Upgrade plan."
459
+ Write-Output "PlanOnly: True"
460
+ Write-Output "No files will be changed."
461
+ Write-Output ("ProjectRoot: {0}" -f $ProjectRoot)
462
+ Write-Output ("AgentsRoot: {0}" -f $AgentsRoot)
463
+ Write-Output ("RequestedMode: {0}" -f $RequestedMode)
464
+ Write-Output ("Manifest: {0}" -f $ManifestInfo.Path)
465
+
466
+ $lockInfo = Read-PackageLockOrNull -ProjectRoot $ProjectRoot
467
+ if ($null -eq $lockInfo) {
468
+ Write-Output "Status: missing-lock"
469
+ Write-Output "Reason: .codex-harness/locks/package.lock.json 不存在,无法安全区分包管理文件和用户文件。"
470
+ return
471
+ }
472
+
473
+ $lockDocument = $lockInfo.Document
474
+ $installedMode = [string]$lockDocument.installMode
475
+ if ([string]::IsNullOrWhiteSpace($installedMode)) {
476
+ $installedMode = $RequestedMode
477
+ }
478
+
479
+ Write-Output ("Status: ready")
480
+ Write-Output ("Lock: {0}" -f $lockInfo.Path)
481
+ Write-Output ("InstalledMode: {0}" -f $installedMode)
482
+ Write-Output ("InstalledVendor: {0}" -f ([bool]$lockDocument.vendor))
483
+
484
+ $plannedEntries = Get-ManifestEntriesForMode -ManifestInfo $ManifestInfo -InstallMode $installedMode
485
+ Write-Output ("Entries: {0}" -f @($plannedEntries).Count)
486
+ foreach ($entry in @($plannedEntries)) {
487
+ if ([bool]$entry.Mutable) {
488
+ Write-UpgradePlanItem `
489
+ -Entry $entry `
490
+ -Action "manual-review" `
491
+ -Source ([string]$entry.Source) `
492
+ -Destination ([string]$entry.Destination) `
493
+ -Target ([string]$entry.TargetPath) `
494
+ -Reason "mutable=true,升级计划不会直接覆盖用户可编辑文件。"
495
+ continue
496
+ }
497
+
498
+ if ($entry.SourceKind -eq "directory") {
499
+ $sourceDirectory = [System.IO.Path]::GetFullPath($entry.SourcePath).TrimEnd('\', '/')
500
+ $sourceRoot = ([string]$entry.Source).TrimEnd('/')
501
+ $destinationRoot = ([string]$entry.Destination).TrimEnd('/')
502
+ foreach ($sourceFile in @(Get-InstallChildFiles -Directory $sourceDirectory | Sort-Object FullName)) {
503
+ $relativeFilePath = $sourceFile.FullName.Substring($sourceDirectory.Length).TrimStart('\', '/').Replace('\', '/')
504
+ $fileSource = $sourceRoot + "/" + $relativeFilePath
505
+ $fileDestination = $destinationRoot + "/" + $relativeFilePath
506
+ $fileTargetPath = Join-Path $entry.TargetPath ($relativeFilePath.Replace('/', '\'))
507
+ $decision = Get-UpgradePlanFileDecision `
508
+ -LockDocument $lockDocument `
509
+ -Destination $fileDestination `
510
+ -SourcePath $sourceFile.FullName `
511
+ -TargetPath $fileTargetPath
512
+
513
+ Write-UpgradePlanItem `
514
+ -Entry $entry `
515
+ -Action $decision.Action `
516
+ -Source $fileSource `
517
+ -Destination $fileDestination `
518
+ -Target $fileTargetPath `
519
+ -Reason $decision.Reason
520
+ }
521
+
522
+ continue
523
+ }
524
+
525
+ $decision = Get-UpgradePlanFileDecision `
526
+ -LockDocument $lockDocument `
527
+ -Destination ([string]$entry.Destination) `
528
+ -SourcePath ([string]$entry.SourcePath) `
529
+ -TargetPath ([string]$entry.TargetPath)
530
+
531
+ Write-UpgradePlanItem `
532
+ -Entry $entry `
533
+ -Action $decision.Action `
534
+ -Source ([string]$entry.Source) `
535
+ -Destination ([string]$entry.Destination) `
536
+ -Target ([string]$entry.TargetPath) `
537
+ -Reason $decision.Reason
538
+ }
539
+ }
540
+
541
+ function Write-UninstallPlan {
542
+ param(
543
+ [object]$ManifestInfo,
544
+ [string]$ProjectRoot,
545
+ [string]$AgentsRoot,
546
+ [string]$RequestedMode
547
+ )
548
+
549
+ Write-Output "Uninstall plan."
550
+ Write-Output "PlanOnly: True"
551
+ Write-Output "No files will be changed."
552
+ Write-Output ("ProjectRoot: {0}" -f $ProjectRoot)
553
+ Write-Output ("AgentsRoot: {0}" -f $AgentsRoot)
554
+ Write-Output ("RequestedMode: {0}" -f $RequestedMode)
555
+ Write-Output ("Manifest: {0}" -f $ManifestInfo.Path)
556
+
557
+ $lockInfo = Read-PackageLockOrNull -ProjectRoot $ProjectRoot
558
+ $installedMode = $RequestedMode
559
+ if ($null -ne $lockInfo) {
560
+ $lockedMode = [string]$lockInfo.Document.installMode
561
+ if (-not [string]::IsNullOrWhiteSpace($lockedMode)) {
562
+ $installedMode = $lockedMode
563
+ }
564
+
565
+ Write-Output ("Lock: {0}" -f $lockInfo.Path)
566
+ }
567
+ else {
568
+ Write-Output "Lock: missing"
569
+ }
570
+
571
+ Write-Output ("InstalledMode: {0}" -f $installedMode)
572
+ $plannedEntries = Get-ManifestEntriesForMode -ManifestInfo $ManifestInfo -InstallMode $installedMode
573
+ Write-Output ("Entries: {0}" -f @($plannedEntries).Count)
574
+ foreach ($entry in @($plannedEntries)) {
575
+ $action = "retain-project"
576
+ $reason = "project scope 默认保留,避免删除 task/progress/docs 等 truth source。"
577
+
578
+ if ($entry.Scope -eq "vendor") {
579
+ $action = "remove-vendor"
580
+ $reason = "vendor scope 可在执行阶段删除 manifest 管理的 .agents 内容。"
581
+ }
582
+ elseif ($entry.Scope -eq "user") {
583
+ $action = "manual-user-cleanup"
584
+ $reason = "user scope 位于共享用户目录,执行阶段必须逐项确认。"
585
+ }
586
+
587
+ Write-Output ("- action={0} scope={1} kind={2} mutable={3}" -f $action, $entry.Scope, $entry.Kind, $entry.Mutable)
588
+ Write-Output (" destination: {0}" -f $entry.Destination)
589
+ Write-Output (" target: {0}" -f $entry.TargetPath)
590
+ Write-Output (" reason: {0}" -f $reason)
591
+ }
592
+ }
593
+
594
+ function Get-VendorManifestFileRecords {
595
+ param(
596
+ [object]$ManifestInfo,
597
+ [string]$ProjectRoot
598
+ )
599
+
600
+ $records = New-Object System.Collections.Generic.List[object]
601
+ $packageRoot = Split-Path -Parent ([string]$ManifestInfo.Path)
602
+ $templateRoot = Join-Path $packageRoot "docs\codex-harness-engineering\templates"
603
+ $fullPackageRootMappings = @(
604
+ @{ SourceRoot = $templateRoot; Source = "runtime\AGENTS.md"; Destination = ".agents/AGENTS.md"; Kind = "runtime" },
605
+ @{ SourceRoot = $templateRoot; Source = "bootstrap-codex-harness.ps1"; Destination = ".agents/bootstrap-codex-harness.ps1"; Kind = "runtime" },
606
+ @{ SourceRoot = $templateRoot; Source = "runtime\codex-loop.ps1"; Destination = ".agents/codex-loop.ps1"; Kind = "runtime" },
607
+ @{ SourceRoot = $templateRoot; Source = "config\env-check.ps1"; Destination = ".agents/env-check.ps1"; Kind = "runtime" },
608
+ @{ SourceRoot = $templateRoot; Source = "runtime\verify.ps1"; Destination = ".agents/verify.ps1"; Kind = "runtime" },
609
+ @{ SourceRoot = $templateRoot; Source = "trace\trace.schema.json"; Destination = ".agents/trace.schema.json"; Kind = "runtime" }
610
+ )
611
+
612
+ foreach ($mapping in $fullPackageRootMappings) {
613
+ $sourcePath = Join-Path ([string]$mapping.SourceRoot) ([string]$mapping.Source)
614
+ if (-not (Test-Path -LiteralPath $sourcePath -PathType Leaf)) {
615
+ continue
616
+ }
617
+
618
+ $destination = Normalize-ManifestPath -Path ([string]$mapping.Destination) -Label "vendor migration destination"
619
+ $records.Add([pscustomobject]@{
620
+ Source = "templates/" + ([string]$mapping.Source).Replace('\', '/')
621
+ SourcePath = [System.IO.Path]::GetFullPath($sourcePath)
622
+ Destination = $destination
623
+ TargetPath = Resolve-ManifestTargetPath -ProjectRoot $ProjectRoot -DestinationRelativePath $destination -Scope "vendor"
624
+ Scope = "vendor"
625
+ Kind = [string]$mapping.Kind
626
+ })
627
+ }
628
+
629
+ foreach ($entry in @($ManifestInfo.Entries | Where-Object { [string]$_.Scope -eq "vendor" })) {
630
+ if ($entry.SourceKind -eq "file") {
631
+ $records.Add([pscustomobject]@{
632
+ Source = [string]$entry.Source
633
+ SourcePath = [string]$entry.SourcePath
634
+ Destination = Normalize-ManifestPath -Path ([string]$entry.Destination) -Label "vendor migration destination"
635
+ TargetPath = [string]$entry.TargetPath
636
+ Scope = [string]$entry.Scope
637
+ Kind = [string]$entry.Kind
638
+ })
639
+ continue
640
+ }
641
+
642
+ if ($entry.SourceKind -ne "directory") {
643
+ continue
644
+ }
645
+
646
+ $sourceDirectory = [System.IO.Path]::GetFullPath($entry.SourcePath).TrimEnd('\', '/')
647
+ $sourceRoot = ([string]$entry.Source).TrimEnd('/')
648
+ $destinationRoot = ([string]$entry.Destination).TrimEnd('/')
649
+ foreach ($sourceFile in @(Get-InstallChildFiles -Directory $sourceDirectory | Sort-Object FullName)) {
650
+ $relativeFilePath = $sourceFile.FullName.Substring($sourceDirectory.Length).TrimStart('\', '/').Replace('\', '/')
651
+ $records.Add([pscustomobject]@{
652
+ Source = $sourceRoot + "/" + $relativeFilePath
653
+ SourcePath = $sourceFile.FullName
654
+ Destination = Normalize-ManifestPath -Path ($destinationRoot + "/" + $relativeFilePath) -Label "vendor migration destination"
655
+ TargetPath = Join-Path $entry.TargetPath ($relativeFilePath.Replace('/', '\'))
656
+ Scope = [string]$entry.Scope
657
+ Kind = [string]$entry.Kind
658
+ })
659
+ }
660
+ }
661
+
662
+ return @($records.ToArray())
663
+ }
664
+
665
+ function Write-MigrationPlanItem {
666
+ param(
667
+ [string]$Action,
668
+ [string]$Scope,
669
+ [string]$Kind,
670
+ [string]$Path,
671
+ [string]$Target,
672
+ [string]$Reason
673
+ )
674
+
675
+ Write-Output ("- action={0} scope={1} kind={2} path={3}" -f $Action, $Scope, $Kind, $Path)
676
+ if (-not [string]::IsNullOrWhiteSpace($Target)) {
677
+ Write-Output (" target: {0}" -f $Target)
678
+ }
679
+ Write-Output (" reason: {0}" -f $Reason)
680
+ }
681
+
682
+ function New-MigrationPlanRecord {
683
+ param(
684
+ [string]$Action,
685
+ [string]$Scope,
686
+ [string]$Kind,
687
+ [string]$Path,
688
+ [string]$Target,
689
+ [string]$Reason,
690
+ [string]$Source = "",
691
+ [string]$SourcePath = ""
692
+ )
693
+
694
+ return [pscustomobject]@{
695
+ Action = $Action
696
+ Scope = $Scope
697
+ Kind = $Kind
698
+ Path = $Path
699
+ Target = $Target
700
+ Reason = $Reason
701
+ Source = $Source
702
+ SourcePath = $SourcePath
703
+ }
704
+ }
705
+
706
+ function Get-MigrationPlanRecords {
707
+ param(
708
+ [object]$ManifestInfo,
709
+ [string]$ProjectRoot,
710
+ [string]$AgentsRoot
711
+ )
712
+
713
+ $agentsExists = Test-Path -LiteralPath $AgentsRoot -PathType Container
714
+ $records = New-Object System.Collections.Generic.List[object]
715
+
716
+ $legacyResiduePaths = @(
717
+ "docs/harness",
718
+ "docs/testing",
719
+ "docs/knowledge",
720
+ "docs/requirement-prep-kit"
721
+ )
722
+
723
+ foreach ($relativePath in $legacyResiduePaths) {
724
+ $candidate = Join-Path $ProjectRoot ($relativePath.Replace('/', '\'))
725
+ if (Test-Path -LiteralPath $candidate) {
726
+ $records.Add((New-MigrationPlanRecord `
727
+ -Action "manual-review" `
728
+ -Scope "legacy" `
729
+ -Kind "legacy-residue" `
730
+ -Path $relativePath `
731
+ -Target $candidate `
732
+ -Reason "legacy/vendor 残留需要人工确认,迁移计划不会自动删除。"))
733
+ }
734
+ }
735
+
736
+ if (-not $agentsExists) {
737
+ return [pscustomobject]@{
738
+ AgentsExists = $false
739
+ Records = @($records.ToArray())
740
+ }
741
+ }
742
+
743
+ $vendorRecords = @(Get-VendorManifestFileRecords -ManifestInfo $ManifestInfo -ProjectRoot $ProjectRoot)
744
+ $knownVendorPaths = New-Object 'System.Collections.Generic.HashSet[string]' ([System.StringComparer]::OrdinalIgnoreCase)
745
+ foreach ($record in $vendorRecords) {
746
+ [void]$knownVendorPaths.Add([string]$record.Destination)
747
+ $targetPath = [string]$record.TargetPath
748
+ if (-not (Test-Path -LiteralPath $targetPath -PathType Leaf)) {
749
+ $records.Add((New-MigrationPlanRecord `
750
+ -Action "missing-vendor-file" `
751
+ -Scope "vendor" `
752
+ -Kind ([string]$record.Kind) `
753
+ -Path ([string]$record.Destination) `
754
+ -Target $targetPath `
755
+ -Reason "当前 manifest 声明 vendor 文件,但目标项目中不存在。" `
756
+ -Source ([string]$record.Source) `
757
+ -SourcePath ([string]$record.SourcePath)))
758
+ continue
759
+ }
760
+
761
+ $actualSha256 = Get-InstallFileSha256 -Path $targetPath
762
+ $packageSha256 = Get-InstallFileSha256 -Path ([string]$record.SourcePath)
763
+ if ($actualSha256 -eq $packageSha256) {
764
+ $records.Add((New-MigrationPlanRecord `
765
+ -Action "adopt-vendor-managed" `
766
+ -Scope "vendor" `
767
+ -Kind ([string]$record.Kind) `
768
+ -Path ([string]$record.Destination) `
769
+ -Target $targetPath `
770
+ -Reason "目标 vendor 文件与当前 package 一致,可安全纳入 managedFiles。" `
771
+ -Source ([string]$record.Source) `
772
+ -SourcePath ([string]$record.SourcePath)))
773
+ }
774
+ else {
775
+ $records.Add((New-MigrationPlanRecord `
776
+ -Action "blocked-user-drift" `
777
+ -Scope "vendor" `
778
+ -Kind ([string]$record.Kind) `
779
+ -Path ([string]$record.Destination) `
780
+ -Target $targetPath `
781
+ -Reason "目标 vendor 文件与当前 package 不一致,需要人工确认。" `
782
+ -Source ([string]$record.Source) `
783
+ -SourcePath ([string]$record.SourcePath)))
784
+ }
785
+ }
786
+
787
+ $agentsFullPath = [System.IO.Path]::GetFullPath($AgentsRoot).TrimEnd('\', '/')
788
+ foreach ($legacyFile in @(Get-InstallChildFiles -Directory $agentsFullPath | Sort-Object FullName)) {
789
+ $relativeFilePath = $legacyFile.FullName.Substring($agentsFullPath.Length).TrimStart('\', '/').Replace('\', '/')
790
+ $destination = ".agents/" + $relativeFilePath
791
+ if ($knownVendorPaths.Contains($destination)) {
792
+ continue
793
+ }
794
+
795
+ $records.Add((New-MigrationPlanRecord `
796
+ -Action "unknown-legacy-file" `
797
+ -Scope "legacy" `
798
+ -Kind "unknown-file" `
799
+ -Path $destination `
800
+ -Target $legacyFile.FullName `
801
+ -Reason ".agents/ 内存在当前 manifest 未声明的文件,需要人工确认。"))
802
+ }
803
+
804
+ return [pscustomobject]@{
805
+ AgentsExists = $true
806
+ Records = @($records.ToArray())
807
+ }
808
+ }
809
+
810
+ function Write-MigrationPlanHeader {
811
+ param(
812
+ [object]$ManifestInfo,
813
+ [string]$ProjectRoot,
814
+ [string]$AgentsRoot,
815
+ [string]$RequestedMode,
816
+ [string]$Title,
817
+ [bool]$PlanOnly
818
+ )
819
+
820
+ Write-Output $Title
821
+ Write-Output ("PlanOnly: {0}" -f $PlanOnly)
822
+ if ($PlanOnly) {
823
+ Write-Output "No files will be changed."
824
+ }
825
+
826
+ Write-Output ("ProjectRoot: {0}" -f $ProjectRoot)
827
+ Write-Output ("AgentsRoot: {0}" -f $AgentsRoot)
828
+ Write-Output ("RequestedMode: {0}" -f $RequestedMode)
829
+ Write-Output ("Manifest: {0}" -f $ManifestInfo.Path)
830
+
831
+ $lockInfo = Read-PackageLockOrNull -ProjectRoot $ProjectRoot
832
+ if ($null -ne $lockInfo) {
833
+ $lockDocument = $lockInfo.Document
834
+ Write-Output ("Lock: {0}" -f $lockInfo.Path)
835
+ Write-Output ("InstalledMode: {0}" -f [string]$lockDocument.installMode)
836
+ Write-Output ("InstalledVendor: {0}" -f [bool]$lockDocument.vendor)
837
+ Write-Output ("InstalledVersion: {0}" -f [string]$lockDocument.version)
838
+ Write-Output ("InstalledSourceCommit: {0}" -f [string]$lockDocument.sourceCommit)
839
+ }
840
+ else {
841
+ Write-Output "Lock: missing"
842
+ }
843
+ }
844
+
845
+ function Write-MigrationSummaryCounts {
846
+ param([object[]]$Records)
847
+
848
+ foreach ($action in @("adopt-vendor-managed", "missing-vendor-file", "blocked-user-drift", "unknown-legacy-file", "manual-review")) {
849
+ $count = @($Records | Where-Object { [string]$_.Action -eq $action }).Count
850
+ Write-Output ("summaryCounts.{0}: {1}" -f $action, $count)
851
+ }
852
+ }
853
+
854
+ function Write-MigrationPlan {
855
+ param(
856
+ [object]$ManifestInfo,
857
+ [string]$ProjectRoot,
858
+ [string]$AgentsRoot,
859
+ [string]$RequestedMode
860
+ )
861
+
862
+ Write-MigrationPlanHeader `
863
+ -ManifestInfo $ManifestInfo `
864
+ -ProjectRoot $ProjectRoot `
865
+ -AgentsRoot $AgentsRoot `
866
+ -RequestedMode $RequestedMode `
867
+ -Title "Migration plan." `
868
+ -PlanOnly $true
869
+
870
+ $plan = Get-MigrationPlanRecords -ManifestInfo $ManifestInfo -ProjectRoot $ProjectRoot -AgentsRoot $AgentsRoot
871
+ if (-not [bool]$plan.AgentsExists) {
872
+ Write-Output "Status: no-legacy-vendor"
873
+ }
874
+ else {
875
+ Write-Output "Status: ready"
876
+ }
877
+
878
+ foreach ($record in @($plan.Records)) {
879
+ Write-MigrationPlanItem `
880
+ -Action ([string]$record.Action) `
881
+ -Scope ([string]$record.Scope) `
882
+ -Kind ([string]$record.Kind) `
883
+ -Path ([string]$record.Path) `
884
+ -Target ([string]$record.Target) `
885
+ -Reason ([string]$record.Reason)
886
+ }
887
+ }
888
+
889
+ function Write-MigrationAdoptPackageLock {
890
+ param(
891
+ [object]$ManifestInfo,
892
+ [string]$ProjectRoot,
893
+ [string]$PackageRoot,
894
+ [object[]]$AdoptRecords
895
+ )
896
+
897
+ $lockDirectory = Join-Path $ProjectRoot ".codex-harness\locks"
898
+ if (-not (Test-Path -LiteralPath $lockDirectory -PathType Container)) {
899
+ New-Item -ItemType Directory -Force -Path $lockDirectory | Out-Null
900
+ }
901
+
902
+ $sourceCommit = Get-PackageSourceCommit -PackageRoot $PackageRoot
903
+ $packageVersion = Get-InstallManifestVersion -ManifestInfo $ManifestInfo
904
+ $aiKitManifestPath = Join-Path $PackageRoot "ai-sync\ai-kit-manifest.json"
905
+ $managedFiles = New-Object System.Collections.Generic.List[object]
906
+ foreach ($record in @($AdoptRecords | Sort-Object Path)) {
907
+ Add-InstallLockManagedFile `
908
+ -ManagedFiles $managedFiles `
909
+ -Path ([string]$record.Path) `
910
+ -Source ([string]$record.Source) `
911
+ -Scope "vendor" `
912
+ -Kind ([string]$record.Kind) `
913
+ -TargetPath ([string]$record.Target)
914
+ }
915
+
916
+ $lockDocument = [pscustomobject]@{
917
+ lockVersion = "0.1"
918
+ package = "codex-harness"
919
+ version = $packageVersion
920
+ sourceCommit = $sourceCommit
921
+ installMode = "vendor"
922
+ vendor = $true
923
+ installedAt = (Get-Date).ToString("o")
924
+ source = [pscustomobject]@{
925
+ packageRoot = $PackageRoot
926
+ commit = $sourceCommit
927
+ }
928
+ manifests = [pscustomobject]@{
929
+ aiKit = if (Test-Path -LiteralPath $aiKitManifestPath -PathType Leaf) { "ai-sync/ai-kit-manifest.json" } else { "" }
930
+ install = "install-manifest.json"
931
+ }
932
+ managedFiles = @($managedFiles.ToArray())
933
+ }
934
+
935
+ $lockPath = Join-Path $lockDirectory "package.lock.json"
936
+ $lockDocument | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $lockPath -Encoding UTF8
937
+ return $lockPath
938
+ }
939
+
940
+ function Invoke-MigrationApply {
941
+ param(
942
+ [object]$ManifestInfo,
943
+ [string]$ProjectRoot,
944
+ [string]$AgentsRoot,
945
+ [string]$RequestedMode,
946
+ [string]$PackageRoot,
947
+ [bool]$Confirmed
948
+ )
949
+
950
+ Write-MigrationPlanHeader `
951
+ -ManifestInfo $ManifestInfo `
952
+ -ProjectRoot $ProjectRoot `
953
+ -AgentsRoot $AgentsRoot `
954
+ -RequestedMode $RequestedMode `
955
+ -Title "Migration apply." `
956
+ -PlanOnly (-not $Confirmed)
957
+
958
+ $plan = Get-MigrationPlanRecords -ManifestInfo $ManifestInfo -ProjectRoot $ProjectRoot -AgentsRoot $AgentsRoot
959
+ $records = @($plan.Records)
960
+ $adoptRecords = @($records | Where-Object { [string]$_.Action -eq "adopt-vendor-managed" })
961
+ $blockedRecords = @($records | Where-Object { @("blocked-user-drift", "unknown-legacy-file", "manual-review") -contains [string]$_.Action })
962
+ $plannedWrites = @()
963
+ if ($adoptRecords.Count -gt 0) {
964
+ $plannedWrites = @(".codex-harness/locks/package.lock.json", ".codex-harness/state/config.json")
965
+ }
966
+
967
+ if (-not [bool]$plan.AgentsExists) {
968
+ Write-Output "status=no-op"
969
+ Write-Output "reason: no-legacy-vendor"
970
+ Write-MigrationSummaryCounts -Records $records
971
+ Write-Output "plannedWrites: 0"
972
+ Write-Output "actualWrites: 0"
973
+ Write-Output "nextSteps: 无 legacy vendor 内容需要迁移。"
974
+ return
975
+ }
976
+
977
+ foreach ($record in $records) {
978
+ Write-MigrationPlanItem `
979
+ -Action ([string]$record.Action) `
980
+ -Scope ([string]$record.Scope) `
981
+ -Kind ([string]$record.Kind) `
982
+ -Path ([string]$record.Path) `
983
+ -Target ([string]$record.Target) `
984
+ -Reason ([string]$record.Reason)
985
+ }
986
+
987
+ Write-MigrationSummaryCounts -Records $records
988
+ if ($blockedRecords.Count -gt 0) {
989
+ Write-Output "status=blocked"
990
+ foreach ($record in $blockedRecords) {
991
+ Write-Output ("blockedReasons: action={0} path={1} reason={2}" -f $record.Action, $record.Path, $record.Reason)
992
+ }
993
+
994
+ Write-Output ("plannedWrites: {0}" -f @($plannedWrites).Count)
995
+ Write-Output "actualWrites: 0"
996
+ Write-Output "nextSteps: 先人工处理 blockedReasons 中的 drift、unknown 或 legacy docs,再重新运行 -MigratePlan。"
997
+ exit 1
998
+ }
999
+
1000
+ if ($adoptRecords.Count -eq 0) {
1001
+ Write-Output "status=no-op"
1002
+ Write-Output "reason: 没有可写入的 adopt-vendor-managed 文件。"
1003
+ Write-Output "plannedWrites: 0"
1004
+ Write-Output "actualWrites: 0"
1005
+ Write-Output "nextSteps: 复核 missing-vendor-file 报告;需要 vendor 管理时先恢复对应 package 文件。"
1006
+ return
1007
+ }
1008
+
1009
+ foreach ($plannedWrite in $plannedWrites) {
1010
+ Write-Output ("plannedWrites: {0}" -f $plannedWrite)
1011
+ }
1012
+
1013
+ if (-not $Confirmed) {
1014
+ Write-Output "status=dry-run"
1015
+ Write-Output "actualWrites: 0"
1016
+ Write-Output "nextSteps: 确认只采纳 adopt-vendor-managed 后,重新运行 -MigrateApply -Confirm。"
1017
+ return
1018
+ }
1019
+
1020
+ $actualWrites = New-Object System.Collections.Generic.List[string]
1021
+ $lockPath = Write-MigrationAdoptPackageLock `
1022
+ -ManifestInfo $ManifestInfo `
1023
+ -ProjectRoot $ProjectRoot `
1024
+ -PackageRoot $PackageRoot `
1025
+ -AdoptRecords $adoptRecords
1026
+ $actualWrites.Add($lockPath)
1027
+
1028
+ $configPath = Write-ProjectHarnessConfig `
1029
+ -ManifestInfo $ManifestInfo `
1030
+ -ProjectRoot $ProjectRoot `
1031
+ -InstallScope "vendor" `
1032
+ -VendorInstalled:$true `
1033
+ -PackageRoot $PackageRoot
1034
+ $actualWrites.Add($configPath)
1035
+
1036
+ Write-Output "status=confirmed-write"
1037
+ foreach ($actualWrite in @($actualWrites.ToArray())) {
1038
+ Write-Output ("actualWrites: {0}" -f $actualWrite)
1039
+ }
1040
+
1041
+ Write-Output ("WrittenManagedFiles: {0}" -f $adoptRecords.Count)
1042
+ Write-Output "nextSteps: 运行 doctor.ps1 和 refresh-agent-package.ps1 -CheckOnly 验证迁移后的 lock。"
1043
+ }
1044
+
1045
+ function Get-InstalledModeFromLock {
1046
+ param(
1047
+ [object]$LockDocument,
1048
+ [string]$RequestedMode
1049
+ )
1050
+
1051
+ $installedMode = [string]$LockDocument.installMode
1052
+ if ([string]::IsNullOrWhiteSpace($installedMode)) {
1053
+ return $RequestedMode
1054
+ }
1055
+
1056
+ return $installedMode
1057
+ }
1058
+
1059
+ function Copy-InstallManagedFile {
1060
+ param(
1061
+ [string]$SourcePath,
1062
+ [string]$TargetPath
1063
+ )
1064
+
1065
+ $targetParent = Split-Path -Parent $TargetPath
1066
+ if (-not (Test-Path -LiteralPath $targetParent -PathType Container)) {
1067
+ New-Item -ItemType Directory -Force -Path $targetParent | Out-Null
1068
+ }
1069
+
1070
+ Copy-Item -LiteralPath $SourcePath -Destination $TargetPath -Force
1071
+ }
1072
+
1073
+ function Add-InstallLockManagedFile {
1074
+ param(
1075
+ [System.Collections.Generic.List[object]]$ManagedFiles,
1076
+ [string]$Path,
1077
+ [string]$Source,
1078
+ [string]$Scope,
1079
+ [string]$Kind,
1080
+ [string]$TargetPath
1081
+ )
1082
+
1083
+ $ManagedFiles.Add([pscustomobject]@{
1084
+ path = Normalize-ManifestPath -Path $Path -Label "lock managed file path" -AllowEnvironmentPath
1085
+ source = Normalize-ManifestPath -Path $Source -Label "lock managed file source"
1086
+ scope = $Scope
1087
+ kind = $Kind
1088
+ mutable = $false
1089
+ sha256 = Get-InstallFileSha256 -Path $TargetPath
1090
+ })
1091
+ }
1092
+
1093
+ function Add-AbsoluteManagedFile {
1094
+ param(
1095
+ [System.Collections.Generic.List[object]]$ManagedFiles,
1096
+ [string]$Path,
1097
+ [string]$Source,
1098
+ [string]$Scope,
1099
+ [string]$Kind,
1100
+ [string]$TargetPath
1101
+ )
1102
+
1103
+ $ManagedFiles.Add([pscustomobject]@{
1104
+ path = $Path
1105
+ source = Normalize-ManifestPath -Path $Source -Label "package lock managed file source"
1106
+ scope = $Scope
1107
+ kind = $Kind
1108
+ mutable = $false
1109
+ sha256 = Get-InstallFileSha256 -Path $TargetPath
1110
+ })
1111
+ }
1112
+
1113
+ function Get-InstalledPackageManagedFiles {
1114
+ param(
1115
+ [string]$PackageRoot,
1116
+ [string]$InstallRoot
1117
+ )
1118
+
1119
+ $managedFiles = New-Object System.Collections.Generic.List[object]
1120
+ $packageFullPath = [System.IO.Path]::GetFullPath($PackageRoot).TrimEnd('\', '/')
1121
+ foreach ($file in @(Get-InstallChildFiles -Directory $packageFullPath | Sort-Object FullName)) {
1122
+ $relativeFilePath = $file.FullName.Substring($packageFullPath.Length).TrimStart('\', '/').Replace('\', '/')
1123
+ $targetFilePath = Join-Path $InstallRoot ($relativeFilePath.Replace('/', '\'))
1124
+ if (-not (Test-Path -LiteralPath $targetFilePath -PathType Leaf)) {
1125
+ continue
1126
+ }
1127
+
1128
+ Add-AbsoluteManagedFile `
1129
+ -ManagedFiles $managedFiles `
1130
+ -Path $relativeFilePath `
1131
+ -Source $relativeFilePath `
1132
+ -Scope "package" `
1133
+ -Kind "package-file" `
1134
+ -TargetPath $targetFilePath
1135
+ }
1136
+
1137
+ return @($managedFiles.ToArray())
1138
+ }
1139
+
1140
+ function Get-InstallLockManagedFiles {
1141
+ param(
1142
+ [object]$ManifestInfo,
1143
+ [string]$InstallMode,
1144
+ [bool]$VendorInstalled
1145
+ )
1146
+
1147
+ $includedScopes = @("project")
1148
+ if ($InstallMode -eq "user") {
1149
+ $includedScopes = @("user")
1150
+ }
1151
+ elseif ($InstallMode -eq "vendor") {
1152
+ $includedScopes = @("vendor")
1153
+ }
1154
+ elseif ($VendorInstalled) {
1155
+ $includedScopes += "vendor"
1156
+ }
1157
+
1158
+ $managedFiles = New-Object System.Collections.Generic.List[object]
1159
+ foreach ($entry in @($ManifestInfo.Entries)) {
1160
+ if ($includedScopes -notcontains [string]$entry.Scope) {
1161
+ continue
1162
+ }
1163
+
1164
+ if ([bool]$entry.Mutable) {
1165
+ continue
1166
+ }
1167
+
1168
+ if ([string]$entry.Kind -eq "generated-lock" -or [string]$entry.Destination -eq ".codex-harness/locks/package.lock.json") {
1169
+ continue
1170
+ }
1171
+
1172
+ if ($entry.SourceKind -eq "file") {
1173
+ if (-not (Test-Path -LiteralPath $entry.TargetPath -PathType Leaf)) {
1174
+ continue
1175
+ }
1176
+
1177
+ Add-InstallLockManagedFile `
1178
+ -ManagedFiles $managedFiles `
1179
+ -Path ([string]$entry.Destination) `
1180
+ -Source ([string]$entry.Source) `
1181
+ -Scope ([string]$entry.Scope) `
1182
+ -Kind ([string]$entry.Kind) `
1183
+ -TargetPath ([string]$entry.TargetPath)
1184
+ continue
1185
+ }
1186
+
1187
+ if ($entry.SourceKind -ne "directory") {
1188
+ continue
1189
+ }
1190
+
1191
+ if (-not (Test-Path -LiteralPath $entry.TargetPath -PathType Container)) {
1192
+ continue
1193
+ }
1194
+
1195
+ $sourceDirectory = [System.IO.Path]::GetFullPath($entry.SourcePath).TrimEnd('\', '/')
1196
+ $sourceRoot = ([string]$entry.Source).TrimEnd('/')
1197
+ $destinationRoot = ([string]$entry.Destination).TrimEnd('/')
1198
+ foreach ($sourceFile in @(Get-InstallChildFiles -Directory $sourceDirectory | Sort-Object FullName)) {
1199
+ $relativeFilePath = $sourceFile.FullName.Substring($sourceDirectory.Length).TrimStart('\', '/').Replace('\', '/')
1200
+ $targetFilePath = Join-Path $entry.TargetPath ($relativeFilePath.Replace('/', '\'))
1201
+ if (-not (Test-Path -LiteralPath $targetFilePath -PathType Leaf)) {
1202
+ continue
1203
+ }
1204
+
1205
+ Add-InstallLockManagedFile `
1206
+ -ManagedFiles $managedFiles `
1207
+ -Path ($destinationRoot + "/" + $relativeFilePath) `
1208
+ -Source ($sourceRoot + "/" + $relativeFilePath) `
1209
+ -Scope ([string]$entry.Scope) `
1210
+ -Kind ([string]$entry.Kind) `
1211
+ -TargetPath $targetFilePath
1212
+ }
1213
+ }
1214
+
1215
+ return @($managedFiles.ToArray())
1216
+ }
1217
+
1218
+ function Write-InstalledPackageLock {
1219
+ param(
1220
+ [object]$ManifestInfo,
1221
+ [string]$ProjectRoot,
1222
+ [string]$InstallMode,
1223
+ [bool]$VendorInstalled,
1224
+ [string]$PackageRoot
1225
+ )
1226
+
1227
+ $sourceCommit = Get-PackageSourceCommit -PackageRoot $PackageRoot
1228
+ $packageVersion = Get-InstallManifestVersion -ManifestInfo $ManifestInfo
1229
+ $aiKitManifestPath = Join-Path $PackageRoot "ai-sync\ai-kit-manifest.json"
1230
+
1231
+ $lockDirectory = Join-Path $ProjectRoot ".codex-harness\locks"
1232
+ if (-not (Test-Path -LiteralPath $lockDirectory -PathType Container)) {
1233
+ New-Item -ItemType Directory -Force -Path $lockDirectory | Out-Null
1234
+ }
1235
+
1236
+ $lockDocument = [pscustomobject]@{
1237
+ lockVersion = "0.1"
1238
+ package = "codex-harness"
1239
+ version = $packageVersion
1240
+ sourceCommit = $sourceCommit
1241
+ installMode = $InstallMode
1242
+ vendor = $VendorInstalled
1243
+ installedAt = (Get-Date).ToString("o")
1244
+ source = [pscustomobject]@{
1245
+ packageRoot = $PackageRoot
1246
+ commit = $sourceCommit
1247
+ }
1248
+ manifests = [pscustomobject]@{
1249
+ aiKit = if (Test-Path -LiteralPath $aiKitManifestPath -PathType Leaf) { "ai-sync/ai-kit-manifest.json" } else { "" }
1250
+ install = "install-manifest.json"
1251
+ }
1252
+ managedFiles = @(Get-InstallLockManagedFiles `
1253
+ -ManifestInfo $ManifestInfo `
1254
+ -InstallMode $InstallMode `
1255
+ -VendorInstalled:$VendorInstalled)
1256
+ }
1257
+
1258
+ $lockPath = Join-Path $lockDirectory "package.lock.json"
1259
+ $lockDocument | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $lockPath -Encoding UTF8
1260
+ return $lockPath
1261
+ }
1262
+
1263
+ function Write-ProjectHarnessConfig {
1264
+ param(
1265
+ [object]$ManifestInfo,
1266
+ [string]$ProjectRoot,
1267
+ [string]$InstallScope,
1268
+ [bool]$VendorInstalled,
1269
+ [string]$PackageRoot
1270
+ )
1271
+
1272
+ $configDirectory = Join-Path $ProjectRoot ".codex-harness\state"
1273
+ if (-not (Test-Path -LiteralPath $configDirectory -PathType Container)) {
1274
+ New-Item -ItemType Directory -Force -Path $configDirectory | Out-Null
1275
+ }
1276
+
1277
+ $configDocument = [pscustomobject]@{
1278
+ package = "codex-harness"
1279
+ version = Get-InstallManifestVersion -ManifestInfo $ManifestInfo
1280
+ packageRoot = [System.IO.Path]::GetFullPath($PackageRoot)
1281
+ installScope = $InstallScope
1282
+ vendor = $VendorInstalled
1283
+ }
1284
+
1285
+ $configPath = Join-Path $configDirectory "config.json"
1286
+ $configDocument | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $configPath -Encoding UTF8
1287
+ return $configPath
1288
+ }
1289
+
1290
+ function Write-UserPackageLock {
1291
+ param(
1292
+ [object]$ManifestInfo,
1293
+ [string]$PackageRoot,
1294
+ [string]$InstallRoot
1295
+ )
1296
+
1297
+ $lockDirectory = Split-Path -Parent $InstallRoot
1298
+ if (-not (Test-Path -LiteralPath $lockDirectory -PathType Container)) {
1299
+ New-Item -ItemType Directory -Force -Path $lockDirectory | Out-Null
1300
+ }
1301
+
1302
+ $packageVersion = Get-InstallManifestVersion -ManifestInfo $ManifestInfo
1303
+ $sourceCommit = Get-PackageSourceCommit -PackageRoot $PackageRoot
1304
+ $lockDocument = [pscustomobject]@{
1305
+ lockVersion = "0.1"
1306
+ package = "codex-harness"
1307
+ version = $packageVersion
1308
+ latestVersion = $packageVersion
1309
+ sourceCommit = $sourceCommit
1310
+ installedAt = (Get-Date).ToString("o")
1311
+ packageRoot = [System.IO.Path]::GetFullPath($InstallRoot)
1312
+ source = [pscustomobject]@{
1313
+ packageRoot = [System.IO.Path]::GetFullPath($PackageRoot)
1314
+ commit = $sourceCommit
1315
+ }
1316
+ managedFiles = @(Get-InstalledPackageManagedFiles -PackageRoot $PackageRoot -InstallRoot $InstallRoot)
1317
+ }
1318
+
1319
+ $lockPath = Join-Path $lockDirectory "package.lock.json"
1320
+ $lockDocument | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $lockPath -Encoding UTF8
1321
+ return $lockPath
1322
+ }
1323
+
1324
+ function Get-UserPackageInstallRoot {
1325
+ param([object]$ManifestInfo)
1326
+
1327
+ $packageVersion = Get-InstallManifestVersion -ManifestInfo $ManifestInfo
1328
+ return [System.IO.Path]::GetFullPath((Join-Path $env:USERPROFILE ".codex\packages\codex-harness\$packageVersion"))
1329
+ }
1330
+
1331
+ function Install-UserPackageLayer {
1332
+ param(
1333
+ [object]$ManifestInfo,
1334
+ [string]$PackageRoot
1335
+ )
1336
+
1337
+ $installRoot = Get-UserPackageInstallRoot -ManifestInfo $ManifestInfo
1338
+ if (-not (Test-Path -LiteralPath $installRoot -PathType Container)) {
1339
+ New-Item -ItemType Directory -Force -Path $installRoot | Out-Null
1340
+ }
1341
+
1342
+ Copy-DirectoryContentExcludingNames -SourceDirectory $PackageRoot -DestinationDirectory $installRoot -ExcludeNames @(".git")
1343
+ $lockPath = Write-UserPackageLock -ManifestInfo $ManifestInfo -PackageRoot $PackageRoot -InstallRoot $installRoot
1344
+
1345
+ return [pscustomobject]@{
1346
+ PackageRoot = $installRoot
1347
+ LockPath = $lockPath
1348
+ }
1349
+ }
1350
+
1351
+ function Invoke-UpgradeExecution {
1352
+ param(
1353
+ [object]$ManifestInfo,
1354
+ [string]$ProjectRoot,
1355
+ [string]$AgentsRoot,
1356
+ [string]$RequestedMode,
1357
+ [string]$PackageRoot
1358
+ )
1359
+
1360
+ Write-Output "Upgrade execution."
1361
+ Write-Output "PlanOnly: False"
1362
+ Write-Output ("ProjectRoot: {0}" -f $ProjectRoot)
1363
+ Write-Output ("AgentsRoot: {0}" -f $AgentsRoot)
1364
+ Write-Output ("RequestedMode: {0}" -f $RequestedMode)
1365
+ Write-Output ("Manifest: {0}" -f $ManifestInfo.Path)
1366
+
1367
+ $lockInfo = Read-PackageLockOrNull -ProjectRoot $ProjectRoot
1368
+ if ($null -eq $lockInfo) {
1369
+ throw "missing-lock: .codex-harness/locks/package.lock.json 不存在,无法安全执行升级。"
1370
+ }
1371
+
1372
+ $lockDocument = $lockInfo.Document
1373
+ $installedMode = Get-InstalledModeFromLock -LockDocument $lockDocument -RequestedMode $RequestedMode
1374
+ $vendorInstalled = [bool]$lockDocument.vendor
1375
+
1376
+ Write-Output ("Lock: {0}" -f $lockInfo.Path)
1377
+ Write-Output ("InstalledMode: {0}" -f $installedMode)
1378
+ Write-Output ("InstalledVendor: {0}" -f $vendorInstalled)
1379
+
1380
+ $actions = New-Object System.Collections.Generic.List[object]
1381
+ $plannedEntries = Get-ManifestEntriesForMode -ManifestInfo $ManifestInfo -InstallMode $installedMode
1382
+ foreach ($entry in @($plannedEntries)) {
1383
+ if ([bool]$entry.Mutable) {
1384
+ $actions.Add([pscustomobject]@{
1385
+ Entry = $entry
1386
+ Action = "manual-review"
1387
+ Source = [string]$entry.Source
1388
+ SourcePath = [string]$entry.SourcePath
1389
+ Destination = [string]$entry.Destination
1390
+ TargetPath = [string]$entry.TargetPath
1391
+ Reason = "mutable=true,升级执行不会直接覆盖用户可编辑文件。"
1392
+ })
1393
+ continue
1394
+ }
1395
+
1396
+ if ($entry.SourceKind -eq "directory") {
1397
+ $sourceDirectory = [System.IO.Path]::GetFullPath($entry.SourcePath).TrimEnd('\', '/')
1398
+ $sourceRoot = ([string]$entry.Source).TrimEnd('/')
1399
+ $destinationRoot = ([string]$entry.Destination).TrimEnd('/')
1400
+ foreach ($sourceFile in @(Get-InstallChildFiles -Directory $sourceDirectory | Sort-Object FullName)) {
1401
+ $relativeFilePath = $sourceFile.FullName.Substring($sourceDirectory.Length).TrimStart('\', '/').Replace('\', '/')
1402
+ $fileSource = $sourceRoot + "/" + $relativeFilePath
1403
+ $fileDestination = $destinationRoot + "/" + $relativeFilePath
1404
+ $fileTargetPath = Join-Path $entry.TargetPath ($relativeFilePath.Replace('/', '\'))
1405
+ $decision = Get-UpgradePlanFileDecision `
1406
+ -LockDocument $lockDocument `
1407
+ -Destination $fileDestination `
1408
+ -SourcePath $sourceFile.FullName `
1409
+ -TargetPath $fileTargetPath
1410
+
1411
+ $actions.Add([pscustomobject]@{
1412
+ Entry = $entry
1413
+ Action = $decision.Action
1414
+ Source = $fileSource
1415
+ SourcePath = $sourceFile.FullName
1416
+ Destination = $fileDestination
1417
+ TargetPath = $fileTargetPath
1418
+ Reason = $decision.Reason
1419
+ })
1420
+ }
1421
+
1422
+ continue
1423
+ }
1424
+
1425
+ $decision = Get-UpgradePlanFileDecision `
1426
+ -LockDocument $lockDocument `
1427
+ -Destination ([string]$entry.Destination) `
1428
+ -SourcePath ([string]$entry.SourcePath) `
1429
+ -TargetPath ([string]$entry.TargetPath)
1430
+
1431
+ $actions.Add([pscustomobject]@{
1432
+ Entry = $entry
1433
+ Action = $decision.Action
1434
+ Source = [string]$entry.Source
1435
+ SourcePath = [string]$entry.SourcePath
1436
+ Destination = [string]$entry.Destination
1437
+ TargetPath = [string]$entry.TargetPath
1438
+ Reason = $decision.Reason
1439
+ })
1440
+ }
1441
+
1442
+ $plannedActions = @($actions.ToArray())
1443
+ foreach ($action in $plannedActions) {
1444
+ Write-UpgradePlanItem `
1445
+ -Entry $action.Entry `
1446
+ -Action ([string]$action.Action) `
1447
+ -Source ([string]$action.Source) `
1448
+ -Destination ([string]$action.Destination) `
1449
+ -Target ([string]$action.TargetPath) `
1450
+ -Reason ([string]$action.Reason)
1451
+ }
1452
+
1453
+ $blockedActions = @($plannedActions | Where-Object { [string]$_.Action -eq "blocked-user-drift" })
1454
+ if ($blockedActions.Count -gt 0) {
1455
+ Write-Output ("blocked-user-drift: {0} 个文件已偏离 lock,升级已停止。" -f $blockedActions.Count)
1456
+ exit 1
1457
+ }
1458
+
1459
+ $changedCount = 0
1460
+ foreach ($action in $plannedActions) {
1461
+ if (@("update-immutable", "install-missing") -notcontains [string]$action.Action) {
1462
+ continue
1463
+ }
1464
+
1465
+ Copy-InstallManagedFile -SourcePath ([string]$action.SourcePath) -TargetPath ([string]$action.TargetPath)
1466
+ $changedCount += 1
1467
+ }
1468
+
1469
+ $effectiveInstallMode = if ($installedMode -eq "vendor") { "vendor" } elseif ($vendorInstalled) { "full" } else { "project" }
1470
+ $lockPath = Write-InstalledPackageLock `
1471
+ -ManifestInfo $ManifestInfo `
1472
+ -ProjectRoot $ProjectRoot `
1473
+ -InstallMode $effectiveInstallMode `
1474
+ -VendorInstalled:$vendorInstalled `
1475
+ -PackageRoot $PackageRoot
1476
+
1477
+ Write-Output ("ChangedFiles: {0}" -f $changedCount)
1478
+ Write-Output ("LockWritten: {0}" -f $lockPath)
1479
+ }
1480
+
1481
+ function Test-PathUnderRoot {
1482
+ param(
1483
+ [string]$Root,
1484
+ [string]$Path
1485
+ )
1486
+
1487
+ $rootFullPath = [System.IO.Path]::GetFullPath($Root).TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
1488
+ $pathFullPath = [System.IO.Path]::GetFullPath($Path)
1489
+ return $pathFullPath.StartsWith($rootFullPath, [System.StringComparison]::OrdinalIgnoreCase)
1490
+ }
1491
+
1492
+ function Remove-EmptyDirectoriesUpToRoot {
1493
+ param(
1494
+ [string]$StartDirectory,
1495
+ [string]$StopRoot
1496
+ )
1497
+
1498
+ $stopFullPath = [System.IO.Path]::GetFullPath($StopRoot).TrimEnd('\', '/')
1499
+ $current = $StartDirectory
1500
+ while (-not [string]::IsNullOrWhiteSpace($current)) {
1501
+ $currentFullPath = [System.IO.Path]::GetFullPath($current).TrimEnd('\', '/')
1502
+ if (-not $currentFullPath.StartsWith($stopFullPath, [System.StringComparison]::OrdinalIgnoreCase)) {
1503
+ break
1504
+ }
1505
+
1506
+ if ($currentFullPath.Equals($stopFullPath, [System.StringComparison]::OrdinalIgnoreCase)) {
1507
+ break
1508
+ }
1509
+
1510
+ if (-not (Test-Path -LiteralPath $currentFullPath -PathType Container)) {
1511
+ $current = Split-Path -Parent $currentFullPath
1512
+ continue
1513
+ }
1514
+
1515
+ if (@(Get-ChildItem -LiteralPath $currentFullPath -Force).Count -gt 0) {
1516
+ break
1517
+ }
1518
+
1519
+ Remove-Item -LiteralPath $currentFullPath -Force
1520
+ $current = Split-Path -Parent $currentFullPath
1521
+ }
1522
+ }
1523
+
1524
+ function Invoke-UninstallExecution {
1525
+ param(
1526
+ [object]$ManifestInfo,
1527
+ [string]$ProjectRoot,
1528
+ [string]$AgentsRoot,
1529
+ [string]$RequestedMode,
1530
+ [string]$PackageRoot
1531
+ )
1532
+
1533
+ Write-Output "Uninstall execution."
1534
+ Write-Output "PlanOnly: False"
1535
+ Write-Output ("ProjectRoot: {0}" -f $ProjectRoot)
1536
+ Write-Output ("AgentsRoot: {0}" -f $AgentsRoot)
1537
+ Write-Output ("RequestedMode: {0}" -f $RequestedMode)
1538
+ Write-Output ("Manifest: {0}" -f $ManifestInfo.Path)
1539
+
1540
+ $lockInfo = Read-PackageLockOrNull -ProjectRoot $ProjectRoot
1541
+ if ($null -eq $lockInfo) {
1542
+ throw "missing-lock: .codex-harness/locks/package.lock.json 不存在,无法安全执行卸载。"
1543
+ }
1544
+
1545
+ $lockDocument = $lockInfo.Document
1546
+ $installedMode = Get-InstalledModeFromLock -LockDocument $lockDocument -RequestedMode $RequestedMode
1547
+ $vendorInstalled = [bool]$lockDocument.vendor
1548
+ Write-Output ("Lock: {0}" -f $lockInfo.Path)
1549
+ Write-Output ("InstalledMode: {0}" -f $installedMode)
1550
+ Write-Output ("InstalledVendor: {0}" -f $vendorInstalled)
1551
+
1552
+ if (-not $vendorInstalled) {
1553
+ $lockPath = Write-InstalledPackageLock `
1554
+ -ManifestInfo $ManifestInfo `
1555
+ -ProjectRoot $ProjectRoot `
1556
+ -InstallMode "project" `
1557
+ -VendorInstalled:$false `
1558
+ -PackageRoot $PackageRoot
1559
+
1560
+ Write-Output "RemovedFiles: 0"
1561
+ Write-Output ("LockWritten: {0}" -f $lockPath)
1562
+ return
1563
+ }
1564
+
1565
+ $vendorManagedFiles = @(
1566
+ @($lockDocument.managedFiles) |
1567
+ Where-Object { [string]$_.scope -eq "vendor" } |
1568
+ Sort-Object path -Descending
1569
+ )
1570
+
1571
+ if ($vendorManagedFiles.Count -eq 0) {
1572
+ throw "missing-vendor-lock-entries: lock 中缺少 vendor managedFiles,无法安全执行卸载。"
1573
+ }
1574
+
1575
+ $blockedFiles = New-Object System.Collections.Generic.List[object]
1576
+ foreach ($managedFile in $vendorManagedFiles) {
1577
+ $managedPath = Normalize-ManifestPath -Path ([string]$managedFile.path) -Label "vendor managed file path"
1578
+ $targetPath = [System.IO.Path]::GetFullPath((Join-Path $ProjectRoot ($managedPath.Replace('/', '\'))))
1579
+ if (-not (Test-PathUnderRoot -Root $AgentsRoot -Path $targetPath)) {
1580
+ throw "vendor managed file 不在 AgentsRoot 内,拒绝删除: $targetPath"
1581
+ }
1582
+
1583
+ if (-not (Test-Path -LiteralPath $targetPath -PathType Leaf)) {
1584
+ continue
1585
+ }
1586
+
1587
+ $actualSha256 = Get-InstallFileSha256 -Path $targetPath
1588
+ $lockedSha256 = ([string]$managedFile.sha256).ToLowerInvariant()
1589
+ if ($actualSha256 -ne $lockedSha256) {
1590
+ $blockedFiles.Add([pscustomobject]@{
1591
+ Path = $managedPath
1592
+ TargetPath = $targetPath
1593
+ })
1594
+ }
1595
+ }
1596
+
1597
+ $blockedFileArray = @($blockedFiles.ToArray())
1598
+ if ($blockedFileArray.Count -gt 0) {
1599
+ foreach ($blockedFile in $blockedFileArray) {
1600
+ Write-Output ("- action=blocked-user-drift scope=vendor path={0}" -f $blockedFile.Path)
1601
+ Write-Output (" target: {0}" -f $blockedFile.TargetPath)
1602
+ Write-Output " reason: vendor 文件已偏离 lock,卸载前需要人工确认。"
1603
+ }
1604
+
1605
+ Write-Output ("blocked-user-drift: {0} 个 vendor 文件已偏离 lock,卸载已停止。" -f $blockedFileArray.Count)
1606
+ exit 1
1607
+ }
1608
+
1609
+ $removedCount = 0
1610
+ foreach ($managedFile in $vendorManagedFiles) {
1611
+ $managedPath = Normalize-ManifestPath -Path ([string]$managedFile.path) -Label "vendor managed file path"
1612
+ $targetPath = [System.IO.Path]::GetFullPath((Join-Path $ProjectRoot ($managedPath.Replace('/', '\'))))
1613
+ if (Test-Path -LiteralPath $targetPath -PathType Leaf) {
1614
+ Remove-Item -LiteralPath $targetPath -Force
1615
+ $removedCount += 1
1616
+ Remove-EmptyDirectoriesUpToRoot -StartDirectory (Split-Path -Parent $targetPath) -StopRoot $AgentsRoot
1617
+ }
1618
+ }
1619
+
1620
+ $lockPath = Write-InstalledPackageLock `
1621
+ -ManifestInfo $ManifestInfo `
1622
+ -ProjectRoot $ProjectRoot `
1623
+ -InstallMode "project" `
1624
+ -VendorInstalled:$false `
1625
+ -PackageRoot $PackageRoot
1626
+
1627
+ Write-Output ("RemovedFiles: {0}" -f $removedCount)
1628
+ Write-Output ("LockWritten: {0}" -f $lockPath)
1629
+ }
1630
+
1631
+ function Test-GitRepository {
1632
+ param([string]$Root)
1633
+
1634
+ $gitPath = (Get-Command git -ErrorAction Stop).Source
1635
+ $stdoutPath = [System.IO.Path]::GetTempFileName()
1636
+ $stderrPath = [System.IO.Path]::GetTempFileName()
1637
+
1638
+ try {
1639
+ $process = Start-Process `
1640
+ -FilePath $gitPath `
1641
+ -ArgumentList @('-C', $Root, 'rev-parse', '--show-toplevel') `
1642
+ -NoNewWindow `
1643
+ -Wait `
1644
+ -PassThru `
1645
+ -RedirectStandardOutput $stdoutPath `
1646
+ -RedirectStandardError $stderrPath
1647
+
1648
+ return ($process.ExitCode -eq 0)
1649
+ }
1650
+ finally {
1651
+ Remove-Item -LiteralPath $stdoutPath -Force -ErrorAction SilentlyContinue
1652
+ Remove-Item -LiteralPath $stderrPath -Force -ErrorAction SilentlyContinue
1653
+ }
1654
+ }
1655
+
1656
+ function Assert-GitRepoOrInit {
1657
+ param(
1658
+ [string]$Root,
1659
+ [bool]$AllowInit
1660
+ )
1661
+
1662
+ $repoExists = Test-GitRepository -Root $Root
1663
+
1664
+ if ($repoExists) {
1665
+ return $true
1666
+ }
1667
+
1668
+ if (-not $AllowInit) {
1669
+ throw "目标目录不是 Git 仓库: $Root。请先初始化 Git,或传入 -InitGitIfNeeded。"
1670
+ }
1671
+
1672
+ Write-Step "目标目录不是 Git 仓库,执行 git init。"
1673
+ & git -C $Root init | Out-Null
1674
+ if ($LASTEXITCODE -ne 0) {
1675
+ throw "git init 失败: $Root"
1676
+ }
1677
+
1678
+ return $false
1679
+ }
1680
+
1681
+ function Get-GitStatusLines {
1682
+ param([string]$Root)
1683
+
1684
+ $output = & git -C $Root status --short
1685
+ if ($LASTEXITCODE -ne 0) {
1686
+ throw "无法读取 Git 状态: $Root"
1687
+ }
1688
+
1689
+ if ($null -eq $output) {
1690
+ return @()
1691
+ }
1692
+
1693
+ return @($output)
1694
+ }
1695
+
1696
+ function Test-GitHeadExists {
1697
+ param([string]$Root)
1698
+
1699
+ $gitPath = (Get-Command git -ErrorAction Stop).Source
1700
+ $stdoutPath = [System.IO.Path]::GetTempFileName()
1701
+ $stderrPath = [System.IO.Path]::GetTempFileName()
1702
+ try {
1703
+ $process = Start-Process `
1704
+ -FilePath $gitPath `
1705
+ -ArgumentList @('-C', $Root, 'rev-parse', '--verify', 'HEAD') `
1706
+ -NoNewWindow `
1707
+ -Wait `
1708
+ -PassThru `
1709
+ -RedirectStandardOutput $stdoutPath `
1710
+ -RedirectStandardError $stderrPath
1711
+
1712
+ return ($process.ExitCode -eq 0)
1713
+ }
1714
+ finally {
1715
+ Remove-Item -LiteralPath $stdoutPath -Force -ErrorAction SilentlyContinue
1716
+ Remove-Item -LiteralPath $stderrPath -Force -ErrorAction SilentlyContinue
1717
+ }
1718
+ }
1719
+
1720
+ function Build-BaselineCommitMessage {
1721
+ param(
1722
+ [string]$InstallMode,
1723
+ [bool]$HadHeadBeforeInstall,
1724
+ [bool]$HadAgentsBeforeInstall
1725
+ )
1726
+
1727
+ if ($HadHeadBeforeInstall) {
1728
+ if (-not $HadAgentsBeforeInstall) {
1729
+ return "chore: add codex agent package"
1730
+ }
1731
+
1732
+ return "chore: refresh codex agent package"
1733
+ }
1734
+
1735
+ return "chore: initialize codex agent package"
1736
+ }
1737
+
1738
+ function Get-GitConfigValue {
1739
+ param([string[]]$Arguments)
1740
+
1741
+ $gitPath = (Get-Command git -ErrorAction Stop).Source
1742
+ $stdoutPath = [System.IO.Path]::GetTempFileName()
1743
+ $stderrPath = [System.IO.Path]::GetTempFileName()
1744
+
1745
+ try {
1746
+ $process = Start-Process `
1747
+ -FilePath $gitPath `
1748
+ -ArgumentList $Arguments `
1749
+ -NoNewWindow `
1750
+ -Wait `
1751
+ -PassThru `
1752
+ -RedirectStandardOutput $stdoutPath `
1753
+ -RedirectStandardError $stderrPath
1754
+
1755
+ if ($process.ExitCode -ne 0) {
1756
+ return ""
1757
+ }
1758
+
1759
+ return (Get-Content -LiteralPath $stdoutPath -Raw).Trim()
1760
+ }
1761
+ finally {
1762
+ Remove-Item -LiteralPath $stdoutPath -Force -ErrorAction SilentlyContinue
1763
+ Remove-Item -LiteralPath $stderrPath -Force -ErrorAction SilentlyContinue
1764
+ }
1765
+ }
1766
+
1767
+ function Test-GitIdentityConfigured {
1768
+ param([string]$Root)
1769
+
1770
+ $userName = Get-GitConfigValue -Arguments @('-C', $Root, 'config', '--get', 'user.name')
1771
+ if ([string]::IsNullOrWhiteSpace([string]$userName)) {
1772
+ $userName = Get-GitConfigValue -Arguments @('config', '--global', '--get', 'user.name')
1773
+ }
1774
+
1775
+ $userEmail = Get-GitConfigValue -Arguments @('-C', $Root, 'config', '--get', 'user.email')
1776
+ if ([string]::IsNullOrWhiteSpace([string]$userEmail)) {
1777
+ $userEmail = Get-GitConfigValue -Arguments @('config', '--global', '--get', 'user.email')
1778
+ }
1779
+
1780
+ return (-not [string]::IsNullOrWhiteSpace([string]$userName)) -and (-not [string]::IsNullOrWhiteSpace([string]$userEmail))
1781
+ }
1782
+
1783
+ function Copy-DirectoryContent {
1784
+ param(
1785
+ [string]$SourceDirectory,
1786
+ [string]$DestinationDirectory
1787
+ )
1788
+
1789
+ if (-not (Test-Path -LiteralPath $DestinationDirectory)) {
1790
+ New-Item -ItemType Directory -Path $DestinationDirectory | Out-Null
1791
+ }
1792
+
1793
+ Get-ChildItem -LiteralPath $SourceDirectory -Force | ForEach-Object {
1794
+ $destinationPath = Join-Path $DestinationDirectory $_.Name
1795
+ Copy-Item -LiteralPath $_.FullName -Destination $destinationPath -Recurse -Force
1796
+ }
1797
+ }
1798
+
1799
+ function Copy-DirectoryContentExcludingNames {
1800
+ param(
1801
+ [string]$SourceDirectory,
1802
+ [string]$DestinationDirectory,
1803
+ [string[]]$ExcludeNames = @()
1804
+ )
1805
+
1806
+ if (-not (Test-Path -LiteralPath $DestinationDirectory)) {
1807
+ New-Item -ItemType Directory -Path $DestinationDirectory | Out-Null
1808
+ }
1809
+
1810
+ foreach ($child in @(Get-ChildItem -LiteralPath $SourceDirectory -Force | Where-Object { $ExcludeNames -notcontains $_.Name })) {
1811
+ $destinationPath = Join-Path $DestinationDirectory $child.Name
1812
+ if ($child.PSIsContainer) {
1813
+ if (-not (Test-Path -LiteralPath $destinationPath -PathType Container)) {
1814
+ New-Item -ItemType Directory -Force -Path $destinationPath | Out-Null
1815
+ }
1816
+
1817
+ $robocopyArgs = @(
1818
+ $child.FullName,
1819
+ $destinationPath,
1820
+ "/E",
1821
+ "/COPY:DAT",
1822
+ "/DCOPY:DAT",
1823
+ "/R:2",
1824
+ "/W:1",
1825
+ "/NFL",
1826
+ "/NDL",
1827
+ "/NJH",
1828
+ "/NJS",
1829
+ "/NP"
1830
+ )
1831
+
1832
+ & robocopy @robocopyArgs | Out-Null
1833
+ $robocopyExitCode = $LASTEXITCODE
1834
+ if ($robocopyExitCode -ge 8) {
1835
+ throw "复制目录失败: $($child.FullName) -> $destinationPath (robocopy exit $robocopyExitCode)"
1836
+ }
1837
+
1838
+ $global:LASTEXITCODE = 0
1839
+ continue
1840
+ }
1841
+
1842
+ Copy-Item -LiteralPath $child.FullName -Destination $destinationPath -Force
1843
+ }
1844
+ }
1845
+
1846
+ function Copy-ManagedFile {
1847
+ param(
1848
+ [string]$SourceRoot,
1849
+ [string]$SourceRelativePath,
1850
+ [string]$DestinationRoot,
1851
+ [string]$DestinationRelativePath
1852
+ )
1853
+
1854
+ $sourcePath = Join-Path $SourceRoot $SourceRelativePath
1855
+ if (-not (Test-Path -LiteralPath $sourcePath)) {
1856
+ throw "模板文件不存在: $sourcePath"
1857
+ }
1858
+
1859
+ $destinationPath = Join-Path $DestinationRoot $DestinationRelativePath
1860
+ $destinationDirectory = Split-Path -Parent $destinationPath
1861
+ if (-not (Test-Path -LiteralPath $destinationDirectory)) {
1862
+ New-Item -ItemType Directory -Force -Path $destinationDirectory | Out-Null
1863
+ }
1864
+
1865
+ Copy-Item -LiteralPath $sourcePath -Destination $destinationPath -Force
1866
+ }
1867
+
1868
+ function Copy-ManagedDirectory {
1869
+ param(
1870
+ [string]$SourceDirectory,
1871
+ [string]$DestinationDirectory,
1872
+ [bool]$Overwrite
1873
+ )
1874
+
1875
+ if (-not (Test-Path -LiteralPath $SourceDirectory)) {
1876
+ throw "模板目录不存在: $SourceDirectory"
1877
+ }
1878
+
1879
+ if (Test-Path -LiteralPath $DestinationDirectory) {
1880
+ if (-not $Overwrite) {
1881
+ return
1882
+ }
1883
+
1884
+ Remove-Item -LiteralPath $DestinationDirectory -Recurse -Force
1885
+ }
1886
+
1887
+ New-Item -ItemType Directory -Force -Path $DestinationDirectory | Out-Null
1888
+ Copy-DirectoryContent -SourceDirectory $SourceDirectory -DestinationDirectory $DestinationDirectory
1889
+ }
1890
+
1891
+ function Copy-TemplatePackageCodex {
1892
+ param(
1893
+ [string]$TemplateRoot,
1894
+ [string]$DestinationRoot
1895
+ )
1896
+
1897
+ $codexRoot = Join-Path $DestinationRoot ".codex"
1898
+ if (-not (Test-Path -LiteralPath $codexRoot)) {
1899
+ New-Item -ItemType Directory -Force -Path $codexRoot | Out-Null
1900
+ }
1901
+
1902
+ $fileMappings = @(
1903
+ @{ Source = "config\codex-config.toml"; Destination = ".codex\config.toml" },
1904
+ @{ Source = "config\codex-readme.md"; Destination = ".codex\README.md" },
1905
+ @{ Source = "hooks\hooks.json"; Destination = ".codex\hooks.json" },
1906
+ @{ Source = "runtime\task-run-profile.json"; Destination = ".codex\task-run-profile.json" }
1907
+ )
1908
+
1909
+ foreach ($mapping in $fileMappings) {
1910
+ Copy-ManagedFile `
1911
+ -SourceRoot $TemplateRoot `
1912
+ -SourceRelativePath $mapping.Source `
1913
+ -DestinationRoot $DestinationRoot `
1914
+ -DestinationRelativePath $mapping.Destination
1915
+ }
1916
+
1917
+ Copy-DirectoryContent -SourceDirectory (Join-Path $TemplateRoot "config\agents") -DestinationDirectory (Join-Path $codexRoot "agents")
1918
+ Copy-DirectoryContent -SourceDirectory (Join-Path $TemplateRoot "config\rules") -DestinationDirectory (Join-Path $codexRoot "rules")
1919
+ Copy-DirectoryContent -SourceDirectory (Join-Path $TemplateRoot "prompts") -DestinationDirectory (Join-Path $codexRoot "prompts")
1920
+ }
1921
+
1922
+ function Copy-AssetDirectory {
1923
+ param(
1924
+ [string]$AssetsRoot,
1925
+ [string]$SourceRelativePath,
1926
+ [string]$DestinationRoot,
1927
+ [string]$DestinationRelativePath
1928
+ )
1929
+
1930
+ $sourcePath = Join-Path $AssetsRoot $SourceRelativePath
1931
+ if (-not (Test-Path -LiteralPath $sourcePath)) {
1932
+ throw "模板目录不存在: $sourcePath"
1933
+ }
1934
+
1935
+ $destinationPath = Join-Path $DestinationRoot $DestinationRelativePath
1936
+ $destinationParent = Split-Path -Parent $destinationPath
1937
+ if (-not (Test-Path -LiteralPath $destinationParent)) {
1938
+ New-Item -ItemType Directory -Force -Path $destinationParent | Out-Null
1939
+ }
1940
+
1941
+ if (-not (Test-Path -LiteralPath $destinationPath)) {
1942
+ New-Item -ItemType Directory -Force -Path $destinationPath | Out-Null
1943
+ }
1944
+
1945
+ $robocopyArgs = @(
1946
+ $sourcePath,
1947
+ $destinationPath,
1948
+ "/E",
1949
+ "/COPY:DAT",
1950
+ "/DCOPY:DAT",
1951
+ "/R:2",
1952
+ "/W:1",
1953
+ "/NFL",
1954
+ "/NDL",
1955
+ "/NJH",
1956
+ "/NJS",
1957
+ "/NP"
1958
+ )
1959
+
1960
+ & robocopy @robocopyArgs | Out-Null
1961
+ $robocopyExitCode = $LASTEXITCODE
1962
+
1963
+ if ($robocopyExitCode -ge 8) {
1964
+ throw "复制模板目录失败: $sourcePath -> $destinationPath (robocopy exit $robocopyExitCode)"
1965
+ }
1966
+
1967
+ $global:LASTEXITCODE = 0
1968
+ }
1969
+
1970
+ function Copy-ManifestEntries {
1971
+ param(
1972
+ [object]$ManifestInfo,
1973
+ [string[]]$Scopes
1974
+ )
1975
+
1976
+ $selectedEntries = @(
1977
+ $ManifestInfo.Entries |
1978
+ Where-Object { $Scopes -contains [string]$_.Scope }
1979
+ )
1980
+
1981
+ foreach ($entry in $selectedEntries) {
1982
+ if ($entry.SourceKind -eq "file") {
1983
+ $targetParent = Split-Path -Parent $entry.TargetPath
1984
+ if (-not (Test-Path -LiteralPath $targetParent -PathType Container)) {
1985
+ New-Item -ItemType Directory -Force -Path $targetParent | Out-Null
1986
+ }
1987
+
1988
+ Copy-Item -LiteralPath $entry.SourcePath -Destination $entry.TargetPath -Force
1989
+ continue
1990
+ }
1991
+
1992
+ if ($entry.SourceKind -ne "directory") {
1993
+ throw "不支持的 manifest sourceKind: $($entry.SourceKind)"
1994
+ }
1995
+
1996
+ if (-not (Test-Path -LiteralPath $entry.TargetPath -PathType Container)) {
1997
+ New-Item -ItemType Directory -Force -Path $entry.TargetPath | Out-Null
1998
+ }
1999
+
2000
+ $robocopyArgs = @(
2001
+ $entry.SourcePath,
2002
+ $entry.TargetPath,
2003
+ "/E",
2004
+ "/COPY:DAT",
2005
+ "/DCOPY:DAT",
2006
+ "/R:2",
2007
+ "/W:1",
2008
+ "/NFL",
2009
+ "/NDL",
2010
+ "/NJH",
2011
+ "/NJS",
2012
+ "/NP"
2013
+ )
2014
+
2015
+ & robocopy @robocopyArgs | Out-Null
2016
+ $robocopyExitCode = $LASTEXITCODE
2017
+ if ($robocopyExitCode -ge 8) {
2018
+ throw "复制 manifest 目录失败: $($entry.Source) -> $($entry.Destination) (robocopy exit $robocopyExitCode)"
2019
+ }
2020
+
2021
+ $global:LASTEXITCODE = 0
2022
+ }
2023
+ }
2024
+
2025
+ function Overlay-DirectoryIfPresent {
2026
+ param(
2027
+ [string]$SourceDirectory,
2028
+ [string]$DestinationDirectory
2029
+ )
2030
+
2031
+ if (-not (Test-Path -LiteralPath $SourceDirectory -PathType Container)) {
2032
+ return
2033
+ }
2034
+
2035
+ if (-not (Test-Path -LiteralPath $DestinationDirectory)) {
2036
+ New-Item -ItemType Directory -Force -Path $DestinationDirectory | Out-Null
2037
+ }
2038
+
2039
+ foreach ($directory in Get-ChildItem -LiteralPath $SourceDirectory -Recurse -Force -Directory) {
2040
+ $relativePath = $directory.FullName.Substring($SourceDirectory.Length + 1)
2041
+ $targetDirectory = Join-Path $DestinationDirectory $relativePath
2042
+ if (-not (Test-Path -LiteralPath $targetDirectory)) {
2043
+ New-Item -ItemType Directory -Force -Path $targetDirectory | Out-Null
2044
+ }
2045
+ }
2046
+
2047
+ foreach ($file in Get-ChildItem -LiteralPath $SourceDirectory -Recurse -Force -File) {
2048
+ $relativePath = $file.FullName.Substring($SourceDirectory.Length + 1)
2049
+ $targetPath = Join-Path $DestinationDirectory $relativePath
2050
+ $targetParent = Split-Path -Parent $targetPath
2051
+ if (-not (Test-Path -LiteralPath $targetParent)) {
2052
+ New-Item -ItemType Directory -Force -Path $targetParent | Out-Null
2053
+ }
2054
+
2055
+ Copy-Item -LiteralPath $file.FullName -Destination $targetPath -Force
2056
+ }
2057
+ }
2058
+
2059
+ function Ensure-ReadmeForSmoke {
2060
+ param([string]$Root)
2061
+
2062
+ $readmePath = Join-Path $Root "README.md"
2063
+ if (Test-Path -LiteralPath $readmePath) {
2064
+ return $null
2065
+ }
2066
+
2067
+ @(
2068
+ "# Project README",
2069
+ "",
2070
+ "This README was generated by install-agent.ps1 to support the initial smoke task.",
2071
+ "Replace it with project-specific content after harness setup is verified."
2072
+ ) | Set-Content -LiteralPath $readmePath -Encoding UTF8
2073
+
2074
+ return $readmePath
2075
+ }
2076
+
2077
+ function Copy-Package {
2078
+ param(
2079
+ [string]$SourceRoot,
2080
+ [string]$DestinationRoot,
2081
+ [string]$InstallMode
2082
+ )
2083
+
2084
+ $templateRoot = Join-Path $SourceRoot "docs\codex-harness-engineering\templates"
2085
+ if (-not (Test-Path -LiteralPath $templateRoot)) {
2086
+ throw "找不到模板目录: $templateRoot"
2087
+ }
2088
+
2089
+ $packageAssetsRoot = Join-Path $templateRoot "package-assets"
2090
+ if (-not (Test-Path -LiteralPath $packageAssetsRoot)) {
2091
+ throw "找不到 package-assets 模板目录: $packageAssetsRoot"
2092
+ }
2093
+
2094
+ $rootFileMappings = @(
2095
+ @{ SourceRoot = $templateRoot; Source = "runtime\AGENTS.md"; Destination = "AGENTS.md" },
2096
+ @{ SourceRoot = $templateRoot; Source = "bootstrap-codex-harness.ps1"; Destination = "bootstrap-codex-harness.ps1" },
2097
+ @{ SourceRoot = $templateRoot; Source = "runtime\codex-loop.ps1"; Destination = "codex-loop.ps1" },
2098
+ @{ SourceRoot = $templateRoot; Source = "config\env-check.ps1"; Destination = "env-check.ps1" },
2099
+ @{ SourceRoot = $templateRoot; Source = "runtime\verify.ps1"; Destination = "verify.ps1" },
2100
+ @{ SourceRoot = $templateRoot; Source = "trace\trace.schema.json"; Destination = "trace.schema.json" },
2101
+ @{ SourceRoot = $SourceRoot; Source = "install-manifest.json"; Destination = "install-manifest.json" },
2102
+ @{ SourceRoot = $SourceRoot; Source = "install-manifest.schema.json"; Destination = "install-manifest.schema.json" },
2103
+ @{ SourceRoot = $packageAssetsRoot; Source = "root\install-agent.ps1"; Destination = "install-agent.ps1" },
2104
+ @{ SourceRoot = $packageAssetsRoot; Source = "root\install-agent-here.ps1"; Destination = "install-agent-here.ps1" },
2105
+ @{ SourceRoot = $packageAssetsRoot; Source = "root\README.md"; Destination = "README.md" },
2106
+ @{ SourceRoot = $packageAssetsRoot; Source = "root\PACKAGE.md"; Destination = "PACKAGE.md" }
2107
+ )
2108
+
2109
+ foreach ($mapping in $rootFileMappings) {
2110
+ Copy-ManagedFile `
2111
+ -SourceRoot $mapping.SourceRoot `
2112
+ -SourceRelativePath $mapping.Source `
2113
+ -DestinationRoot $DestinationRoot `
2114
+ -DestinationRelativePath $mapping.Destination
2115
+ }
2116
+
2117
+ $projectRoot = Split-Path -Parent $DestinationRoot
2118
+
2119
+ Copy-AssetDirectory `
2120
+ -AssetsRoot $packageAssetsRoot `
2121
+ -SourceRelativePath "rules" `
2122
+ -DestinationRoot $projectRoot `
2123
+ -DestinationRelativePath ".codex\rules"
2124
+
2125
+ $dirsToCopy = @("workflows", "scripts", ".specify", "skills")
2126
+
2127
+ foreach ($dir in $dirsToCopy) {
2128
+ Copy-AssetDirectory `
2129
+ -AssetsRoot $packageAssetsRoot `
2130
+ -SourceRelativePath $dir `
2131
+ -DestinationRoot $DestinationRoot `
2132
+ -DestinationRelativePath $dir
2133
+ }
2134
+
2135
+ Copy-AssetDirectory `
2136
+ -AssetsRoot (Join-Path $SourceRoot "docs\codex-harness-engineering") `
2137
+ -SourceRelativePath "templates" `
2138
+ -DestinationRoot $DestinationRoot `
2139
+ -DestinationRelativePath "docs\codex-harness-engineering\templates"
2140
+ }
2141
+
2142
+ $sourceRoot = Get-PackageRoot
2143
+ if ([string]::IsNullOrWhiteSpace($ProjectRoot)) {
2144
+ $ProjectRoot = $sourceRoot
2145
+ }
2146
+
2147
+ $resolvedProjectRoot = [System.IO.Path]::GetFullPath($ProjectRoot)
2148
+ $targetAgentsRoot = Join-Path $resolvedProjectRoot ".agents"
2149
+ $stagedSourceRoot = $null
2150
+ $effectiveSourceRoot = $sourceRoot
2151
+ $scopeUserPackage = $null
2152
+ $baselineCommitted = $false
2153
+ $baselinePolicy = "skipped"
2154
+
2155
+ try {
2156
+ $modeWasProvided = $PSBoundParameters.ContainsKey("Mode")
2157
+ $scopeWasProvided = $PSBoundParameters.ContainsKey("Scope")
2158
+ $defaultThinInstall = (-not $modeWasProvided) -and (-not $scopeWasProvided)
2159
+ if ((-not [string]::IsNullOrWhiteSpace($Scope)) -and $modeWasProvided) {
2160
+ throw "-Scope 和 -Mode 只能选择一个。"
2161
+ }
2162
+
2163
+ $installScope = ""
2164
+ if ($defaultThinInstall) {
2165
+ $Mode = "project"
2166
+ $installScope = "project"
2167
+ }
2168
+ elseif (-not [string]::IsNullOrWhiteSpace($Scope)) {
2169
+ $Mode = $Scope
2170
+ $installScope = $Scope
2171
+ }
2172
+ elseif ($Mode -ne "full") {
2173
+ $installScope = $Mode
2174
+ }
2175
+ else {
2176
+ $installScope = "full"
2177
+ }
2178
+
2179
+ $installManifestInfo = Read-InstallManifest -SourceRoot $effectiveSourceRoot -ProjectRoot $resolvedProjectRoot
2180
+ $planSwitchCount = 0
2181
+ foreach ($selectedPlanSwitch in @($Plan.IsPresent, $UpgradePlan.IsPresent, $UninstallPlan.IsPresent, $MigratePlan.IsPresent, $MigrateApply.IsPresent, $Upgrade.IsPresent, $Uninstall.IsPresent)) {
2182
+ if ($selectedPlanSwitch) {
2183
+ $planSwitchCount += 1
2184
+ }
2185
+ }
2186
+
2187
+ if ($planSwitchCount -gt 1) {
2188
+ throw "-Plan、-UpgradePlan、-UninstallPlan、-MigratePlan、-MigrateApply、-Upgrade 和 -Uninstall 只能选择一个。"
2189
+ }
2190
+
2191
+ if ($Confirm.IsPresent -and -not $MigrateApply.IsPresent) {
2192
+ throw "-Confirm 只能与 -MigrateApply 一起使用。"
2193
+ }
2194
+
2195
+ if ($Plan.IsPresent) {
2196
+ $thinProjectPlan = $defaultThinInstall -or ($Scope -eq "project")
2197
+ Write-InstallPlan `
2198
+ -ManifestInfo $installManifestInfo `
2199
+ -ProjectRoot $resolvedProjectRoot `
2200
+ -AgentsRoot $targetAgentsRoot `
2201
+ -InstallMode $Mode `
2202
+ -ThinProjectProfile:$thinProjectPlan
2203
+ return
2204
+ }
2205
+
2206
+ if ($UpgradePlan.IsPresent) {
2207
+ Write-UpgradePlan `
2208
+ -ManifestInfo $installManifestInfo `
2209
+ -ProjectRoot $resolvedProjectRoot `
2210
+ -AgentsRoot $targetAgentsRoot `
2211
+ -RequestedMode $Mode
2212
+ return
2213
+ }
2214
+
2215
+ if ($UninstallPlan.IsPresent) {
2216
+ Write-UninstallPlan `
2217
+ -ManifestInfo $installManifestInfo `
2218
+ -ProjectRoot $resolvedProjectRoot `
2219
+ -AgentsRoot $targetAgentsRoot `
2220
+ -RequestedMode $Mode
2221
+ return
2222
+ }
2223
+
2224
+ if ($MigratePlan.IsPresent) {
2225
+ Write-MigrationPlan `
2226
+ -ManifestInfo $installManifestInfo `
2227
+ -ProjectRoot $resolvedProjectRoot `
2228
+ -AgentsRoot $targetAgentsRoot `
2229
+ -RequestedMode $Mode
2230
+ return
2231
+ }
2232
+
2233
+ if ($MigrateApply.IsPresent) {
2234
+ Invoke-MigrationApply `
2235
+ -ManifestInfo $installManifestInfo `
2236
+ -ProjectRoot $resolvedProjectRoot `
2237
+ -AgentsRoot $targetAgentsRoot `
2238
+ -RequestedMode $Mode `
2239
+ -PackageRoot $effectiveSourceRoot `
2240
+ -Confirmed:$Confirm.IsPresent
2241
+ return
2242
+ }
2243
+
2244
+ if ($Upgrade.IsPresent) {
2245
+ Invoke-UpgradeExecution `
2246
+ -ManifestInfo $installManifestInfo `
2247
+ -ProjectRoot $resolvedProjectRoot `
2248
+ -AgentsRoot $targetAgentsRoot `
2249
+ -RequestedMode $Mode `
2250
+ -PackageRoot $effectiveSourceRoot
2251
+ return
2252
+ }
2253
+
2254
+ if ($Uninstall.IsPresent) {
2255
+ Invoke-UninstallExecution `
2256
+ -ManifestInfo $installManifestInfo `
2257
+ -ProjectRoot $resolvedProjectRoot `
2258
+ -AgentsRoot $targetAgentsRoot `
2259
+ -RequestedMode $Mode `
2260
+ -PackageRoot $effectiveSourceRoot
2261
+ return
2262
+ }
2263
+
2264
+ if (($Mode -eq "user" -or $Mode -eq "vendor") -and $InitSmoke.IsPresent) {
2265
+ throw "-InitSmoke 仅支持 full/project 模式。"
2266
+ }
2267
+
2268
+ if ($Mode -eq "user") {
2269
+ Write-Step "安装用户级 codex-harness package"
2270
+ $userPackage = Install-UserPackageLayer -ManifestInfo $installManifestInfo -PackageRoot $effectiveSourceRoot
2271
+ Write-Step "安装共享 agent package 资源到用户目录"
2272
+ Copy-ManifestEntries -ManifestInfo $installManifestInfo -Scopes @("user")
2273
+
2274
+ Write-Output ""
2275
+ Write-Output "Install completed."
2276
+ Write-Output ("Mode: {0}" -f $Mode)
2277
+ if (-not [string]::IsNullOrWhiteSpace($Scope)) {
2278
+ Write-Output ("Scope: {0}" -f $Scope)
2279
+ }
2280
+ Write-Output ("Manifest: {0}" -f $installManifestInfo.Path)
2281
+ Write-Output ("PackageRoot: {0}" -f $userPackage.PackageRoot)
2282
+ Write-Output ("UserPackageLock: {0}" -f $userPackage.LockPath)
2283
+ Write-Output ("Entries: {0}" -f @(Get-ManifestEntriesForMode -ManifestInfo $installManifestInfo -InstallMode $Mode).Count)
2284
+ return
2285
+ }
2286
+
2287
+ if (-not (Test-Path -LiteralPath $resolvedProjectRoot)) {
2288
+ Write-Step "目标目录不存在,创建目录: $resolvedProjectRoot"
2289
+ New-Item -ItemType Directory -Path $resolvedProjectRoot | Out-Null
2290
+ }
2291
+
2292
+ $targetAgentsExistedBeforeInstall = Test-Path -LiteralPath $targetAgentsRoot
2293
+ if (($Mode -ne "project") -and (Test-Path -LiteralPath $targetAgentsRoot) -and (-not $Force.IsPresent)) {
2294
+ throw "目标项目已存在 .agents 目录: $targetAgentsRoot。若要覆盖,请显式传入 -Force。"
2295
+ }
2296
+
2297
+ $repoExistedBeforeInstall = Assert-GitRepoOrInit -Root $resolvedProjectRoot -AllowInit:$InitGitIfNeeded.IsPresent
2298
+ $hadGitHeadBeforeInstall = Test-GitHeadExists -Root $resolvedProjectRoot
2299
+ $statusBeforeInstall = if ($repoExistedBeforeInstall) { @(Get-GitStatusLines -Root $resolvedProjectRoot) } else { @() }
2300
+
2301
+ if ((Test-Path -LiteralPath $targetAgentsRoot) -and
2302
+ ([System.StringComparer]::OrdinalIgnoreCase.Equals(
2303
+ [System.IO.Path]::GetFullPath($targetAgentsRoot),
2304
+ $sourceRoot
2305
+ ))) {
2306
+ $stagedSourceRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("codex-agent-stage-" + [System.Guid]::NewGuid().ToString("N"))
2307
+ New-Item -ItemType Directory -Path $stagedSourceRoot | Out-Null
2308
+ Copy-DirectoryContent -SourceDirectory $sourceRoot -DestinationDirectory $stagedSourceRoot
2309
+ $effectiveSourceRoot = $stagedSourceRoot
2310
+ $installManifestInfo = Read-InstallManifest -SourceRoot $effectiveSourceRoot -ProjectRoot $resolvedProjectRoot
2311
+ Write-Step "检测到从已安装的 .agents 自更新,已创建临时复制源: $effectiveSourceRoot"
2312
+ }
2313
+
2314
+ $templateRoot = Join-Path $effectiveSourceRoot "docs\codex-harness-engineering\templates"
2315
+
2316
+ if ($Mode -eq "project") {
2317
+ if ($Scope -eq "project" -or $defaultThinInstall) {
2318
+ Write-Step "安装用户级 codex-harness package"
2319
+ $scopeUserPackage = Install-UserPackageLayer -ManifestInfo $installManifestInfo -PackageRoot $effectiveSourceRoot
2320
+ }
2321
+
2322
+ $bootstrapScript = Join-Path $effectiveSourceRoot "tools\install\bootstrap-codex-harness.ps1"
2323
+ Write-Step "同步项目根 runtime 文件 (mode=$Mode)"
2324
+ $bootstrapArgs = @(
2325
+ '-NoProfile',
2326
+ '-ExecutionPolicy', 'Bypass',
2327
+ '-File', $bootstrapScript,
2328
+ '-ProjectRoot', $resolvedProjectRoot,
2329
+ '-TemplateRoot', $templateRoot,
2330
+ '-InstallMode', 'project'
2331
+ )
2332
+ if ($Force.IsPresent) {
2333
+ $bootstrapArgs += '-Force'
2334
+ }
2335
+ if ($Scope -eq "project" -or $defaultThinInstall) {
2336
+ $bootstrapArgs += @('-Profile', 'thin')
2337
+ }
2338
+
2339
+ & powershell @bootstrapArgs | Out-Host
2340
+ if ($LASTEXITCODE -ne 0) {
2341
+ throw "bootstrap-codex-harness.ps1 执行失败: $resolvedProjectRoot"
2342
+ }
2343
+ }
2344
+ elseif ($Mode -eq "vendor") {
2345
+ if (Test-Path -LiteralPath $targetAgentsRoot) {
2346
+ Write-Step "删除已存在的 .agents 目录: $targetAgentsRoot"
2347
+ Remove-Item -LiteralPath $targetAgentsRoot -Recurse -Force
2348
+ }
2349
+
2350
+ Write-Step "复制 vendor agent package 到目标项目 .agents/ (mode=$Mode)"
2351
+ Copy-ManifestEntries -ManifestInfo $installManifestInfo -Scopes @("vendor")
2352
+ $null = Write-InstalledPackageLock `
2353
+ -ManifestInfo $installManifestInfo `
2354
+ -ProjectRoot $resolvedProjectRoot `
2355
+ -InstallMode "vendor" `
2356
+ -VendorInstalled:$true `
2357
+ -PackageRoot $effectiveSourceRoot
2358
+ }
2359
+ else {
2360
+ if (Test-Path -LiteralPath $targetAgentsRoot) {
2361
+ Write-Step "删除已存在的 .agents 目录: $targetAgentsRoot"
2362
+ Remove-Item -LiteralPath $targetAgentsRoot -Recurse -Force
2363
+ }
2364
+
2365
+ Write-Step "复制 agent package 到目标项目 .agents/ (mode=$Mode)"
2366
+ New-Item -ItemType Directory -Path $targetAgentsRoot | Out-Null
2367
+ Copy-Package -SourceRoot $effectiveSourceRoot -DestinationRoot $targetAgentsRoot -InstallMode $Mode
2368
+
2369
+ $bootstrapScript = Join-Path $targetAgentsRoot "bootstrap-codex-harness.ps1"
2370
+
2371
+ Write-Step "调用 bootstrap-codex-harness.ps1 同步项目根 runtime 文件"
2372
+ $bootstrapArgs = @(
2373
+ '-NoProfile',
2374
+ '-ExecutionPolicy', 'Bypass',
2375
+ '-File', $bootstrapScript,
2376
+ '-ProjectRoot', $resolvedProjectRoot,
2377
+ '-TemplateRoot', $templateRoot,
2378
+ '-InstallMode', 'full',
2379
+ '-VendorInstalled'
2380
+ )
2381
+ if ($Force.IsPresent) {
2382
+ $bootstrapArgs += '-Force'
2383
+ }
2384
+
2385
+ & powershell @bootstrapArgs | Out-Host
2386
+ if ($LASTEXITCODE -ne 0) {
2387
+ throw "bootstrap-codex-harness.ps1 执行失败: $resolvedProjectRoot"
2388
+ }
2389
+ }
2390
+
2391
+ if ($Mode -eq "project") {
2392
+ $projectPackageRoot = if ($null -ne $scopeUserPackage) { [string]$scopeUserPackage.PackageRoot } else { $effectiveSourceRoot }
2393
+ $lockPath = Write-InstalledPackageLock `
2394
+ -ManifestInfo $installManifestInfo `
2395
+ -ProjectRoot $resolvedProjectRoot `
2396
+ -InstallMode "project" `
2397
+ -VendorInstalled:$false `
2398
+ -PackageRoot $projectPackageRoot
2399
+ Write-Step "已写入 package lock: $lockPath"
2400
+ }
2401
+
2402
+ if ($Mode -eq "project" -or $Mode -eq "vendor") {
2403
+ $configPackageRoot = if ($Mode -eq "vendor") { $targetAgentsRoot } elseif ($null -ne $scopeUserPackage) { [string]$scopeUserPackage.PackageRoot } else { $effectiveSourceRoot }
2404
+ $configPath = Write-ProjectHarnessConfig `
2405
+ -ManifestInfo $installManifestInfo `
2406
+ -ProjectRoot $resolvedProjectRoot `
2407
+ -InstallScope $Mode `
2408
+ -VendorInstalled:($Mode -eq "vendor") `
2409
+ -PackageRoot $configPackageRoot
2410
+ Write-Step "已写入 harness config: $configPath"
2411
+ }
2412
+
2413
+ $generatedReadme = $null
2414
+ if ($InitSmoke) {
2415
+ $generatedReadme = Ensure-ReadmeForSmoke -Root $resolvedProjectRoot
2416
+ if ($null -ne $generatedReadme) {
2417
+ Write-Step "为 smoke 初始化补充 README.md: $generatedReadme"
2418
+ }
2419
+
2420
+ $smokeTaskPath = Join-Path $resolvedProjectRoot "tools\harness\templates\smoke-task.json"
2421
+ $taskPath = Join-Path $resolvedProjectRoot "task.json"
2422
+ if (-not (Test-Path -LiteralPath $smokeTaskPath)) {
2423
+ throw "找不到 smoke-task.json: $smokeTaskPath"
2424
+ }
2425
+
2426
+ Copy-Item -LiteralPath $smokeTaskPath -Destination $taskPath -Force
2427
+ Write-Step "已将 smoke-task.json 覆盖到 task.json"
2428
+ }
2429
+
2430
+ $shouldCommitBaseline = $false
2431
+ if ($SkipBaselineCommit.IsPresent) {
2432
+ $baselinePolicy = "disabled-by-flag"
2433
+ }
2434
+ elseif ($CommitBaseline.IsPresent) {
2435
+ $shouldCommitBaseline = $true
2436
+ $baselinePolicy = "explicit"
2437
+ }
2438
+ elseif (@($statusBeforeInstall).Count -eq 0) {
2439
+ $shouldCommitBaseline = $true
2440
+ $baselinePolicy = if ($hadGitHeadBeforeInstall -or $targetAgentsExistedBeforeInstall) { "auto-clean-repo" } else { "auto-fresh-repo" }
2441
+ }
2442
+ else {
2443
+ $baselinePolicy = "skipped-dirty-before-install"
2444
+ }
2445
+
2446
+ if ($shouldCommitBaseline) {
2447
+ if ($repoExistedBeforeInstall -and (@($statusBeforeInstall).Count -gt 0)) {
2448
+ throw "目标项目在安装前已存在未提交改动。为避免把无关改动并入 baseline,本次拒绝自动提交。"
2449
+ }
2450
+
2451
+ if (-not (Test-GitIdentityConfigured -Root $resolvedProjectRoot)) {
2452
+ if ($CommitBaseline.IsPresent) {
2453
+ throw "当前 Git 未配置 user.name / user.email,无法执行 baseline commit。"
2454
+ }
2455
+
2456
+ Write-Step "当前 Git 未配置 user.name / user.email,跳过自动 baseline commit。"
2457
+ $baselinePolicy = "skipped-missing-git-identity"
2458
+ }
2459
+ else {
2460
+ $statusAfterInstall = @(Get-GitStatusLines -Root $resolvedProjectRoot)
2461
+ if ($statusAfterInstall.Count -eq 0) {
2462
+ Write-Step "安装后没有新增 Git 变更,跳过 baseline commit。"
2463
+ $baselinePolicy = "no-op"
2464
+ }
2465
+ else {
2466
+ Write-Step "创建 baseline commit"
2467
+ & git -C $resolvedProjectRoot -c core.longpaths=true add --all
2468
+ if ($LASTEXITCODE -ne 0) {
2469
+ throw "git add 失败: $resolvedProjectRoot"
2470
+ }
2471
+
2472
+ $baselineMessage = Build-BaselineCommitMessage `
2473
+ -InstallMode $Mode `
2474
+ -HadHeadBeforeInstall:$hadGitHeadBeforeInstall `
2475
+ -HadAgentsBeforeInstall:$targetAgentsExistedBeforeInstall
2476
+ & git -C $resolvedProjectRoot -c core.longpaths=true commit -m $baselineMessage | Out-Host
2477
+ if ($LASTEXITCODE -ne 0) {
2478
+ throw "git commit 失败: $resolvedProjectRoot"
2479
+ }
2480
+
2481
+ $baselineCommitted = $true
2482
+ }
2483
+ }
2484
+ }
2485
+
2486
+ Write-Output ""
2487
+ Write-Output "Install completed."
2488
+ Write-Output ("ProjectRoot: {0}" -f $resolvedProjectRoot)
2489
+ Write-Output ("AgentsRoot: {0}" -f $targetAgentsRoot)
2490
+ Write-Output ("Mode: {0}" -f $Mode)
2491
+ if (-not [string]::IsNullOrWhiteSpace($Scope)) {
2492
+ Write-Output ("Scope: {0}" -f $Scope)
2493
+ }
2494
+ Write-Output ("SmokeInitialized: {0}" -f $InitSmoke.IsPresent)
2495
+ Write-Output ("BaselineCommitted: {0}" -f $baselineCommitted)
2496
+ Write-Output ("BaselinePolicy: {0}" -f $baselinePolicy)
2497
+ if ($Mode -eq "full" -or $Mode -eq "project") {
2498
+ Write-Output ""
2499
+ Write-Output "Next steps:"
2500
+ Write-Output ("- 先裁剪 `"{0}`"、`"{1}`" 和 `"{2}`" 为目标项目事实" -f (Join-Path $resolvedProjectRoot 'docs\ai\repo-map.md'), (Join-Path $resolvedProjectRoot 'docs\ai\architecture-brief.md'), (Join-Path $resolvedProjectRoot 'docs\ai\CURRENT_TASK.md'))
2501
+ Write-Output ("- 复杂项目继续补齐 `"{0}`"、`"{1}`"、`"{2}`"、`"{3}`"、`"{4}`"、`"{5}`"" -f (Join-Path $resolvedProjectRoot 'docs\ai\PROJECT_CONTEXT.md'), (Join-Path $resolvedProjectRoot 'docs\ai\DECISIONS.md'), (Join-Path $resolvedProjectRoot 'docs\ai\API_MAP.md'), (Join-Path $resolvedProjectRoot 'docs\ai\DB_SCHEMA.md'), (Join-Path $resolvedProjectRoot 'docs\ai\KNOWN_ISSUES.md'), (Join-Path $resolvedProjectRoot 'docs\ai\CHANGELOG_AI.md'))
2502
+ Write-Output ("- powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f (Join-Path $resolvedProjectRoot 'tools\install\env-check.ps1'))
2503
+ Write-Output ("- powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f (Join-Path $resolvedProjectRoot 'tools\harness\verify.ps1'))
2504
+ Write-Output ("- 如需接入外部知识或代码语义工具,先读 `"{0}`" 和 `"{1}`"" -f (Join-Path $resolvedProjectRoot 'docs\harness\mcp-knowledge-governance.md'), (Join-Path $resolvedProjectRoot 'docs\harness\code-semantics-and-navigation.md'))
2505
+ Write-Output ("- 如需 7x24 长时间推进,可在 Codex app 中使用 `/goal`;推荐先读 `"{0}`" 和 `"{1}`"" -f (Join-Path $resolvedProjectRoot 'docs\codex-harness-engineering\goal-harness-integration-guide.md'), (Join-Path $resolvedProjectRoot 'docs\codex-harness-engineering\examples\goal-templates.md'))
2506
+ Write-Output ("- powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f (Join-Path $resolvedProjectRoot 'tools\harness\codex-loop.ps1'))
2507
+ }
2508
+ }
2509
+ finally {
2510
+ if (($null -ne $stagedSourceRoot) -and (Test-Path -LiteralPath $stagedSourceRoot)) {
2511
+ Remove-Item -LiteralPath $stagedSourceRoot -Recurse -Force -ErrorAction SilentlyContinue
2512
+ }
2513
+ }