@pzy560117/codex-harness 0.1.4 → 0.1.5

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