@fitlab-ai/agent-infra 0.3.0

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 (285) hide show
  1. package/License.txt +21 -0
  2. package/README.md +170 -0
  3. package/README.zh-CN.md +170 -0
  4. package/bin/cli.js +65 -0
  5. package/lib/defaults.json +45 -0
  6. package/lib/init.js +203 -0
  7. package/lib/log.js +27 -0
  8. package/lib/paths.js +48 -0
  9. package/lib/prompt.js +70 -0
  10. package/lib/render.js +99 -0
  11. package/lib/update.js +161 -0
  12. package/lib/version.js +7 -0
  13. package/package.json +48 -0
  14. package/templates/.agent-workspace/README.md +26 -0
  15. package/templates/.agent-workspace/README.zh-CN.md +26 -0
  16. package/templates/.agents/QUICKSTART.md +166 -0
  17. package/templates/.agents/QUICKSTART.zh-CN.md +166 -0
  18. package/templates/.agents/README.md +134 -0
  19. package/templates/.agents/README.zh-CN.md +134 -0
  20. package/templates/.agents/skills/analyze-task/SKILL.md +169 -0
  21. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +169 -0
  22. package/templates/.agents/skills/block-task/SKILL.md +164 -0
  23. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +163 -0
  24. package/templates/.agents/skills/check-task/SKILL.md +122 -0
  25. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +122 -0
  26. package/templates/.agents/skills/close-codescan/SKILL.md +122 -0
  27. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +122 -0
  28. package/templates/.agents/skills/close-dependabot/SKILL.md +130 -0
  29. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +130 -0
  30. package/templates/.agents/skills/commit/SKILL.md +218 -0
  31. package/templates/.agents/skills/commit/SKILL.zh-CN.md +217 -0
  32. package/templates/.agents/skills/complete-task/SKILL.md +139 -0
  33. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +137 -0
  34. package/templates/.agents/skills/create-pr/SKILL.md +126 -0
  35. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +125 -0
  36. package/templates/.agents/skills/create-release-note/SKILL.md +167 -0
  37. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +166 -0
  38. package/templates/.agents/skills/create-task/SKILL.md +143 -0
  39. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +143 -0
  40. package/templates/.agents/skills/implement-task/SKILL.md +229 -0
  41. package/templates/.agents/skills/implement-task/SKILL.zh-CN.md +227 -0
  42. package/templates/.agents/skills/import-codescan/SKILL.md +103 -0
  43. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +103 -0
  44. package/templates/.agents/skills/import-dependabot/SKILL.md +107 -0
  45. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +107 -0
  46. package/templates/.agents/skills/import-issue/SKILL.md +119 -0
  47. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +119 -0
  48. package/templates/.agents/skills/init-labels/SKILL.md +74 -0
  49. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +74 -0
  50. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +111 -0
  51. package/templates/.agents/skills/init-milestones/SKILL.md +74 -0
  52. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +74 -0
  53. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +169 -0
  54. package/templates/.agents/skills/plan-task/SKILL.md +225 -0
  55. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +225 -0
  56. package/templates/.agents/skills/refine-task/SKILL.md +200 -0
  57. package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +200 -0
  58. package/templates/.agents/skills/refine-title/SKILL.md +84 -0
  59. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +83 -0
  60. package/templates/.agents/skills/release/SKILL.md +142 -0
  61. package/templates/.agents/skills/release/SKILL.zh-CN.md +141 -0
  62. package/templates/.agents/skills/release/scripts/manage-milestones.sh +80 -0
  63. package/templates/.agents/skills/review-task/SKILL.md +276 -0
  64. package/templates/.agents/skills/review-task/SKILL.zh-CN.md +276 -0
  65. package/templates/.agents/skills/sync-issue/SKILL.md +569 -0
  66. package/templates/.agents/skills/sync-issue/SKILL.zh-CN.md +569 -0
  67. package/templates/.agents/skills/sync-pr/SKILL.md +142 -0
  68. package/templates/.agents/skills/sync-pr/SKILL.zh-CN.md +142 -0
  69. package/templates/.agents/skills/test/SKILL.md +61 -0
  70. package/templates/.agents/skills/test/SKILL.zh-CN.md +61 -0
  71. package/templates/.agents/skills/test-integration/SKILL.md +70 -0
  72. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +69 -0
  73. package/templates/.agents/skills/update-agent-infra/SKILL.md +136 -0
  74. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +124 -0
  75. package/templates/.agents/skills/update-agent-infra/scripts/package.json +3 -0
  76. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +469 -0
  77. package/templates/.agents/skills/upgrade-dependency/SKILL.md +88 -0
  78. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +87 -0
  79. package/templates/.agents/templates/handoff.md +60 -0
  80. package/templates/.agents/templates/handoff.zh-CN.md +60 -0
  81. package/templates/.agents/templates/review-report.md +67 -0
  82. package/templates/.agents/templates/review-report.zh-CN.md +67 -0
  83. package/templates/.agents/templates/task.md +65 -0
  84. package/templates/.agents/templates/task.zh-CN.md +65 -0
  85. package/templates/.agents/workflows/bug-fix.yaml +149 -0
  86. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +149 -0
  87. package/templates/.agents/workflows/code-review.yaml +60 -0
  88. package/templates/.agents/workflows/code-review.zh-CN.yaml +60 -0
  89. package/templates/.agents/workflows/feature-development.yaml +150 -0
  90. package/templates/.agents/workflows/feature-development.zh-CN.yaml +150 -0
  91. package/templates/.agents/workflows/refactoring.yaml +154 -0
  92. package/templates/.agents/workflows/refactoring.zh-CN.yaml +154 -0
  93. package/templates/.claude/CLAUDE.md +163 -0
  94. package/templates/.claude/CLAUDE.zh-CN.md +163 -0
  95. package/templates/.claude/commands/analyze-task.md +8 -0
  96. package/templates/.claude/commands/analyze-task.zh-CN.md +8 -0
  97. package/templates/.claude/commands/block-task.md +8 -0
  98. package/templates/.claude/commands/block-task.zh-CN.md +8 -0
  99. package/templates/.claude/commands/check-task.md +8 -0
  100. package/templates/.claude/commands/check-task.zh-CN.md +8 -0
  101. package/templates/.claude/commands/close-codescan.md +8 -0
  102. package/templates/.claude/commands/close-codescan.zh-CN.md +8 -0
  103. package/templates/.claude/commands/close-dependabot.md +8 -0
  104. package/templates/.claude/commands/close-dependabot.zh-CN.md +8 -0
  105. package/templates/.claude/commands/commit.md +7 -0
  106. package/templates/.claude/commands/commit.zh-CN.md +7 -0
  107. package/templates/.claude/commands/complete-task.md +8 -0
  108. package/templates/.claude/commands/complete-task.zh-CN.md +8 -0
  109. package/templates/.claude/commands/create-pr.md +8 -0
  110. package/templates/.claude/commands/create-pr.zh-CN.md +8 -0
  111. package/templates/.claude/commands/create-release-note.md +8 -0
  112. package/templates/.claude/commands/create-release-note.zh-CN.md +8 -0
  113. package/templates/.claude/commands/create-task.md +8 -0
  114. package/templates/.claude/commands/create-task.zh-CN.md +8 -0
  115. package/templates/.claude/commands/implement-task.md +8 -0
  116. package/templates/.claude/commands/implement-task.zh-CN.md +8 -0
  117. package/templates/.claude/commands/import-codescan.md +8 -0
  118. package/templates/.claude/commands/import-codescan.zh-CN.md +8 -0
  119. package/templates/.claude/commands/import-dependabot.md +8 -0
  120. package/templates/.claude/commands/import-dependabot.zh-CN.md +8 -0
  121. package/templates/.claude/commands/import-issue.md +8 -0
  122. package/templates/.claude/commands/import-issue.zh-CN.md +8 -0
  123. package/templates/.claude/commands/init-labels.md +7 -0
  124. package/templates/.claude/commands/init-labels.zh-CN.md +7 -0
  125. package/templates/.claude/commands/init-milestones.md +8 -0
  126. package/templates/.claude/commands/init-milestones.zh-CN.md +8 -0
  127. package/templates/.claude/commands/plan-task.md +8 -0
  128. package/templates/.claude/commands/plan-task.zh-CN.md +8 -0
  129. package/templates/.claude/commands/refine-task.md +8 -0
  130. package/templates/.claude/commands/refine-task.zh-CN.md +8 -0
  131. package/templates/.claude/commands/refine-title.md +8 -0
  132. package/templates/.claude/commands/refine-title.zh-CN.md +8 -0
  133. package/templates/.claude/commands/release.md +8 -0
  134. package/templates/.claude/commands/release.zh-CN.md +8 -0
  135. package/templates/.claude/commands/review-task.md +8 -0
  136. package/templates/.claude/commands/review-task.zh-CN.md +8 -0
  137. package/templates/.claude/commands/sync-issue.md +8 -0
  138. package/templates/.claude/commands/sync-issue.zh-CN.md +8 -0
  139. package/templates/.claude/commands/sync-pr.md +8 -0
  140. package/templates/.claude/commands/sync-pr.zh-CN.md +8 -0
  141. package/templates/.claude/commands/test-integration.md +7 -0
  142. package/templates/.claude/commands/test-integration.zh-CN.md +7 -0
  143. package/templates/.claude/commands/test.md +7 -0
  144. package/templates/.claude/commands/test.zh-CN.md +7 -0
  145. package/templates/.claude/commands/update-agent-infra.md +7 -0
  146. package/templates/.claude/commands/update-agent-infra.zh-CN.md +7 -0
  147. package/templates/.claude/commands/upgrade-dependency.md +8 -0
  148. package/templates/.claude/commands/upgrade-dependency.zh-CN.md +8 -0
  149. package/templates/.claude/project-rules.md +65 -0
  150. package/templates/.claude/project-rules.zh-CN.md +65 -0
  151. package/templates/.claude/settings.json +20 -0
  152. package/templates/.codex/README.md +38 -0
  153. package/templates/.codex/README.zh-CN.md +37 -0
  154. package/templates/.editorconfig +15 -0
  155. package/templates/.gemini/commands/_project_/analyze-task.toml +8 -0
  156. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +8 -0
  157. package/templates/.gemini/commands/_project_/block-task.toml +8 -0
  158. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +8 -0
  159. package/templates/.gemini/commands/_project_/check-task.toml +8 -0
  160. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +8 -0
  161. package/templates/.gemini/commands/_project_/close-codescan.toml +8 -0
  162. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +8 -0
  163. package/templates/.gemini/commands/_project_/close-dependabot.toml +8 -0
  164. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +8 -0
  165. package/templates/.gemini/commands/_project_/commit.toml +6 -0
  166. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +6 -0
  167. package/templates/.gemini/commands/_project_/complete-task.toml +8 -0
  168. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +8 -0
  169. package/templates/.gemini/commands/_project_/create-pr.toml +8 -0
  170. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +8 -0
  171. package/templates/.gemini/commands/_project_/create-release-note.toml +8 -0
  172. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +8 -0
  173. package/templates/.gemini/commands/_project_/create-task.toml +8 -0
  174. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +8 -0
  175. package/templates/.gemini/commands/_project_/implement-task.toml +8 -0
  176. package/templates/.gemini/commands/_project_/implement-task.zh-CN.toml +8 -0
  177. package/templates/.gemini/commands/_project_/import-codescan.toml +8 -0
  178. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +8 -0
  179. package/templates/.gemini/commands/_project_/import-dependabot.toml +8 -0
  180. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +8 -0
  181. package/templates/.gemini/commands/_project_/import-issue.toml +8 -0
  182. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +8 -0
  183. package/templates/.gemini/commands/_project_/init-labels.toml +8 -0
  184. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +8 -0
  185. package/templates/.gemini/commands/_project_/init-milestones.toml +10 -0
  186. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +10 -0
  187. package/templates/.gemini/commands/_project_/plan-task.toml +8 -0
  188. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +8 -0
  189. package/templates/.gemini/commands/_project_/refine-task.toml +8 -0
  190. package/templates/.gemini/commands/_project_/refine-task.zh-CN.toml +8 -0
  191. package/templates/.gemini/commands/_project_/refine-title.toml +8 -0
  192. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +8 -0
  193. package/templates/.gemini/commands/_project_/release.toml +8 -0
  194. package/templates/.gemini/commands/_project_/release.zh-CN.toml +8 -0
  195. package/templates/.gemini/commands/_project_/review-task.toml +8 -0
  196. package/templates/.gemini/commands/_project_/review-task.zh-CN.toml +8 -0
  197. package/templates/.gemini/commands/_project_/sync-issue.toml +8 -0
  198. package/templates/.gemini/commands/_project_/sync-issue.zh-CN.toml +8 -0
  199. package/templates/.gemini/commands/_project_/sync-pr.toml +8 -0
  200. package/templates/.gemini/commands/_project_/sync-pr.zh-CN.toml +8 -0
  201. package/templates/.gemini/commands/_project_/test-integration.toml +6 -0
  202. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +6 -0
  203. package/templates/.gemini/commands/_project_/test.toml +6 -0
  204. package/templates/.gemini/commands/_project_/test.zh-CN.toml +6 -0
  205. package/templates/.gemini/commands/_project_/update-agent-infra.toml +6 -0
  206. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +6 -0
  207. package/templates/.gemini/commands/_project_/upgrade-dependency.toml +8 -0
  208. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +8 -0
  209. package/templates/.gemini/settings.json +3 -0
  210. package/templates/.github/ISSUE_TEMPLATE/01_bug_report.yml +149 -0
  211. package/templates/.github/ISSUE_TEMPLATE/02_question.yml +101 -0
  212. package/templates/.github/ISSUE_TEMPLATE/03_feature_request.yml +131 -0
  213. package/templates/.github/ISSUE_TEMPLATE/04_documentation.yml +165 -0
  214. package/templates/.github/ISSUE_TEMPLATE/05_other.yml +147 -0
  215. package/templates/.github/ISSUE_TEMPLATE/config.yml +11 -0
  216. package/templates/.github/PULL_REQUEST_TEMPLATE.md +123 -0
  217. package/templates/.github/dependabot.yml +17 -0
  218. package/templates/.github/hooks/check-utf8-encoding.sh +25 -0
  219. package/templates/.github/release.yml +27 -0
  220. package/templates/.github/workflows/pr-title-check.yml +42 -0
  221. package/templates/.mailmap +4 -0
  222. package/templates/.opencode/COMMAND_STYLE_GUIDE.md +232 -0
  223. package/templates/.opencode/COMMAND_STYLE_GUIDE.zh-CN.md +232 -0
  224. package/templates/.opencode/README.md +76 -0
  225. package/templates/.opencode/README.zh-CN.md +77 -0
  226. package/templates/.opencode/commands/analyze-task.md +11 -0
  227. package/templates/.opencode/commands/analyze-task.zh-CN.md +11 -0
  228. package/templates/.opencode/commands/block-task.md +11 -0
  229. package/templates/.opencode/commands/block-task.zh-CN.md +11 -0
  230. package/templates/.opencode/commands/check-task.md +11 -0
  231. package/templates/.opencode/commands/check-task.zh-CN.md +11 -0
  232. package/templates/.opencode/commands/close-codescan.md +11 -0
  233. package/templates/.opencode/commands/close-codescan.zh-CN.md +11 -0
  234. package/templates/.opencode/commands/close-dependabot.md +11 -0
  235. package/templates/.opencode/commands/close-dependabot.zh-CN.md +11 -0
  236. package/templates/.opencode/commands/commit.md +9 -0
  237. package/templates/.opencode/commands/commit.zh-CN.md +9 -0
  238. package/templates/.opencode/commands/complete-task.md +11 -0
  239. package/templates/.opencode/commands/complete-task.zh-CN.md +11 -0
  240. package/templates/.opencode/commands/create-pr.md +11 -0
  241. package/templates/.opencode/commands/create-pr.zh-CN.md +11 -0
  242. package/templates/.opencode/commands/create-release-note.md +11 -0
  243. package/templates/.opencode/commands/create-release-note.zh-CN.md +11 -0
  244. package/templates/.opencode/commands/create-task.md +11 -0
  245. package/templates/.opencode/commands/create-task.zh-CN.md +11 -0
  246. package/templates/.opencode/commands/implement-task.md +11 -0
  247. package/templates/.opencode/commands/implement-task.zh-CN.md +11 -0
  248. package/templates/.opencode/commands/import-codescan.md +11 -0
  249. package/templates/.opencode/commands/import-codescan.zh-CN.md +11 -0
  250. package/templates/.opencode/commands/import-dependabot.md +11 -0
  251. package/templates/.opencode/commands/import-dependabot.zh-CN.md +11 -0
  252. package/templates/.opencode/commands/import-issue.md +11 -0
  253. package/templates/.opencode/commands/import-issue.zh-CN.md +11 -0
  254. package/templates/.opencode/commands/init-labels.md +9 -0
  255. package/templates/.opencode/commands/init-labels.zh-CN.md +9 -0
  256. package/templates/.opencode/commands/init-milestones.md +11 -0
  257. package/templates/.opencode/commands/init-milestones.zh-CN.md +11 -0
  258. package/templates/.opencode/commands/plan-task.md +11 -0
  259. package/templates/.opencode/commands/plan-task.zh-CN.md +11 -0
  260. package/templates/.opencode/commands/refine-task.md +11 -0
  261. package/templates/.opencode/commands/refine-task.zh-CN.md +11 -0
  262. package/templates/.opencode/commands/refine-title.md +11 -0
  263. package/templates/.opencode/commands/refine-title.zh-CN.md +11 -0
  264. package/templates/.opencode/commands/release.md +11 -0
  265. package/templates/.opencode/commands/release.zh-CN.md +11 -0
  266. package/templates/.opencode/commands/review-task.md +11 -0
  267. package/templates/.opencode/commands/review-task.zh-CN.md +11 -0
  268. package/templates/.opencode/commands/sync-issue.md +11 -0
  269. package/templates/.opencode/commands/sync-issue.zh-CN.md +11 -0
  270. package/templates/.opencode/commands/sync-pr.md +11 -0
  271. package/templates/.opencode/commands/sync-pr.zh-CN.md +11 -0
  272. package/templates/.opencode/commands/test-integration.md +9 -0
  273. package/templates/.opencode/commands/test-integration.zh-CN.md +9 -0
  274. package/templates/.opencode/commands/test.md +9 -0
  275. package/templates/.opencode/commands/test.zh-CN.md +9 -0
  276. package/templates/.opencode/commands/update-agent-infra.md +9 -0
  277. package/templates/.opencode/commands/update-agent-infra.zh-CN.md +9 -0
  278. package/templates/.opencode/commands/upgrade-dependency.md +11 -0
  279. package/templates/.opencode/commands/upgrade-dependency.zh-CN.md +11 -0
  280. package/templates/AGENTS.md +91 -0
  281. package/templates/AGENTS.zh-CN.md +91 -0
  282. package/templates/CONTRIBUTING.md +126 -0
  283. package/templates/CONTRIBUTING.zh-CN.md +124 -0
  284. package/templates/SECURITY.md +131 -0
  285. package/templates/SECURITY.zh-CN.md +131 -0
@@ -0,0 +1,469 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sync-templates.js — Deterministic template sync for managed & ejected files.
4
+ *
5
+ * Handles SKILL steps: 2 (git pull), 3.0 (registry sync), 4 (managed),
6
+ * 6 (ejected), 7 (.airc.json update).
7
+ *
8
+ * Merged files (step 5) are NOT handled — they require AI semantic merge.
9
+ * The report includes `merged.pending` so the AI knows what to process.
10
+ *
11
+ * Usage:
12
+ * node .agents/skills/update-agent-infra/scripts/sync-templates.js [project-root]
13
+ *
14
+ * Output: JSON report to stdout.
15
+ */
16
+
17
+ import childProcess from 'node:child_process';
18
+ import fs from 'node:fs';
19
+ import os from 'node:os';
20
+ import path from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+
23
+ // Keep these helpers aligned with lib/paths.js for clone installs.
24
+ function resolveInstallDir() {
25
+ return path.join(os.homedir(), '.agent-infra');
26
+ }
27
+
28
+ function resolveTemplateDir() {
29
+ const clonePath = path.join(resolveInstallDir(), 'templates');
30
+ if (fs.existsSync(clonePath)) {
31
+ return clonePath;
32
+ }
33
+
34
+ return null;
35
+ }
36
+
37
+ const DEFAULTS = {
38
+ "files": {
39
+ "managed": [
40
+ ".agents/skills/",
41
+ ".agents/templates/",
42
+ ".agents/workflows/",
43
+ ".agent-workspace/README.md",
44
+ ".claude/commands/",
45
+ ".editorconfig",
46
+ ".gemini/commands/",
47
+ ".github/hooks/",
48
+ ".github/ISSUE_TEMPLATE/",
49
+ ".github/PULL_REQUEST_TEMPLATE.md",
50
+ ".github/release.yml",
51
+ ".github/workflows/pr-title-check.yml",
52
+ ".opencode/commands/"
53
+ ],
54
+ "merged": [
55
+ "**/release.*",
56
+ "**/test-integration.*",
57
+ "**/test.*",
58
+ "**/upgrade-dependency.*",
59
+ ".agents/QUICKSTART.md",
60
+ ".agents/README.md",
61
+ ".agents/skills/release/SKILL.*",
62
+ ".agents/skills/test-integration/SKILL.*",
63
+ ".agents/skills/test/SKILL.*",
64
+ ".agents/skills/upgrade-dependency/SKILL.*",
65
+ ".claude/CLAUDE.md",
66
+ ".claude/project-rules.md",
67
+ ".claude/settings.json",
68
+ ".codex/README.md",
69
+ ".gemini/settings.json",
70
+ ".github/dependabot.yml",
71
+ ".gitignore",
72
+ ".mailmap",
73
+ ".opencode/COMMAND_STYLE_GUIDE.md",
74
+ ".opencode/README.md",
75
+ "AGENTS.md",
76
+ "CONTRIBUTING.md",
77
+ "SECURITY.md"
78
+ ],
79
+ "ejected": []
80
+ }
81
+ };
82
+
83
+ const INSTALLER_VERSION = "0.3.0";
84
+
85
+ function norm(p) { return p.replace(/\\/g, '/'); }
86
+
87
+ function globMatch(pattern, filePath) {
88
+ const p = norm(pattern), f = norm(filePath);
89
+ const globstarDir = '__GLOBSTAR_DIR__';
90
+ const globstar = '__GLOBSTAR__';
91
+ const star = '__STAR__';
92
+ const qmark = '__QMARK__';
93
+ const re = p
94
+ .replace(/([.+^${}()|[\]\\])/g, '\\$1')
95
+ .replace(/\*\*\//g, globstarDir)
96
+ .replace(/\*\*/g, globstar)
97
+ .replace(/\*/g, star)
98
+ .replace(/\?/g, qmark)
99
+ .replace(new RegExp(globstarDir, 'g'), '(?:.+/)?')
100
+ .replace(new RegExp(globstar, 'g'), '[^/]*')
101
+ .replace(new RegExp(star, 'g'), '[^/]*')
102
+ .replace(new RegExp(qmark, 'g'), '[^/]');
103
+ return new RegExp('^' + re + '$').test(f);
104
+ }
105
+
106
+ function walkDir(dir) {
107
+ if (!fs.existsSync(dir)) return [];
108
+ const out = [];
109
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
110
+ const p = path.join(dir, e.name);
111
+ e.isDirectory() ? out.push(...walkDir(p)) : out.push(p);
112
+ }
113
+ return out;
114
+ }
115
+
116
+ function removeEmptyDirs(dir) {
117
+ if (!fs.existsSync(dir)) return;
118
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
119
+ if (e.isDirectory()) removeEmptyDirs(path.join(dir, e.name));
120
+ }
121
+ if (fs.readdirSync(dir).length === 0) {
122
+ fs.rmdirSync(dir);
123
+ }
124
+ }
125
+
126
+ function matchesAny(rel, patterns) {
127
+ const n = norm(rel);
128
+ return patterns.some(p => norm(p) === n || globMatch(p, n));
129
+ }
130
+
131
+ function renderContent(text, vars) {
132
+ return text
133
+ .replace(/\{\{project\}\}/g, vars.project)
134
+ .replace(/\{\{org\}\}/g, vars.org);
135
+ }
136
+
137
+ function renderPathname(p, project) {
138
+ return p.replace(/_project_/g, project);
139
+ }
140
+
141
+ function resolveProjectTemplateDir(projectRoot, templateSource) {
142
+ const fallbackRoot = resolveTemplateDir();
143
+
144
+ const candidates = [];
145
+ if (templateSource) {
146
+ if (path.isAbsolute(templateSource)) {
147
+ candidates.push(templateSource);
148
+ } else {
149
+ if (fallbackRoot) {
150
+ candidates.push(path.resolve(path.dirname(fallbackRoot), templateSource));
151
+ }
152
+ candidates.push(path.resolve(projectRoot, templateSource));
153
+ }
154
+ }
155
+ if (fallbackRoot) {
156
+ candidates.push(fallbackRoot);
157
+ }
158
+
159
+ for (const candidate of candidates) {
160
+ try {
161
+ if (fs.statSync(candidate).isDirectory()) {
162
+ return candidate;
163
+ }
164
+ } catch {
165
+ // Keep scanning until a valid directory is found.
166
+ }
167
+ }
168
+
169
+ return null;
170
+ }
171
+
172
+ function isBinary(fp) {
173
+ const fd = fs.openSync(fp, 'r');
174
+ const buf = Buffer.alloc(8192);
175
+ const n = fs.readSync(fd, buf, 0, 8192, 0);
176
+ fs.closeSync(fd);
177
+ if (n === 0) return false;
178
+ for (let i = 0; i < n; i++) if (buf[i] === 0) return true;
179
+ return false;
180
+ }
181
+
182
+ function fileModule(rel) {
183
+ const p = norm(rel);
184
+ if (p.startsWith('.github/')) return 'github';
185
+ if (p.startsWith('.agents/') || p.startsWith('.claude/') ||
186
+ p.startsWith('.gemini/') || p.startsWith('.opencode/') ||
187
+ p.startsWith('.codex/') || p === 'AGENTS.md') return 'ai';
188
+ return null;
189
+ }
190
+
191
+ function gitUrl(dir) {
192
+ try {
193
+ return childProcess.execSync('git remote get-url origin', {
194
+ cwd: dir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe']
195
+ }).trim();
196
+ } catch { return null; }
197
+ }
198
+
199
+ // Public-facing docs should keep all available language variants in sync.
200
+ const MULTI_LANG = new Set(['SECURITY.md']);
201
+
202
+ function langSelect(rels, lang, allSet, project) {
203
+ const sel = new Map();
204
+
205
+ if (lang === 'zh-CN') {
206
+ for (const r of rels) {
207
+ if (!r.includes('.zh-CN.')) continue;
208
+ const target = norm(renderPathname(r.replace(/\.zh-CN\./, '.'), project));
209
+ sel.set(target, r);
210
+ }
211
+ for (const r of rels) {
212
+ if (r.includes('.zh-CN.')) continue;
213
+ const target = norm(renderPathname(r, project));
214
+ if (sel.has(target)) continue;
215
+ const ext = path.extname(r), base = r.slice(0, -ext.length);
216
+ if (allSet.has(norm(base + '.zh-CN' + ext))) continue;
217
+ sel.set(target, r);
218
+ }
219
+ } else {
220
+ for (const r of rels) {
221
+ if (r.includes('.zh-CN.')) continue;
222
+ sel.set(norm(renderPathname(r, project)), r);
223
+ }
224
+ }
225
+
226
+ return sel;
227
+ }
228
+
229
+ function syncTemplates(projectRoot) {
230
+ const cfgPath = path.join(projectRoot, '.airc.json');
231
+ if (!fs.existsSync(cfgPath)) {
232
+ return { error: 'No .airc.json in project root.' };
233
+ }
234
+
235
+ const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
236
+ const templateRoot = resolveProjectTemplateDir(projectRoot, cfg.templateSource);
237
+ if (!templateRoot) {
238
+ return { error: 'Template source not found. Install: curl -fsSL https://raw.githubusercontent.com/fitlab-ai/agent-infra/main/install.sh | sh' };
239
+ }
240
+ const installDir = resolveInstallDir();
241
+
242
+ const hasGit = fs.existsSync(path.join(installDir, '.git'));
243
+ if (hasGit) {
244
+ try { childProcess.execSync('git fetch --tags --quiet', { cwd: installDir, stdio: 'pipe' }); } catch { /* network */ }
245
+ }
246
+
247
+ let version = 'unknown';
248
+ if (hasGit) {
249
+ let tagOutput;
250
+ try {
251
+ tagOutput = childProcess.execSync('git tag --sort=-v:refname', {
252
+ cwd: installDir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe']
253
+ }).trim();
254
+ } catch {
255
+ return { error: 'Failed to list tags in agent-infra repository. Please check git installation.' };
256
+ }
257
+ const latestTag = tagOutput.split('\n')[0];
258
+ if (!latestTag) {
259
+ return { error: 'No tags found in agent-infra repository. This is unexpected — please reinstall.' };
260
+ }
261
+ try { childProcess.execFileSync('git', ['checkout', latestTag, '--quiet'], { cwd: installDir, stdio: 'pipe' }); } catch { /* ignore */ }
262
+ version = latestTag;
263
+ } else {
264
+ version = INSTALLER_VERSION || version;
265
+ }
266
+
267
+ const { project, org, language: lang = 'en', modules = [] } = cfg;
268
+ const vars = { project, org };
269
+
270
+ const managed = [...(cfg.files.managed || [])];
271
+ const merged = [...(cfg.files.merged || [])];
272
+ const ejected = [...(cfg.files.ejected || [])];
273
+
274
+ const report = {
275
+ templateVersion: version,
276
+ templateRoot: norm(templateRoot),
277
+ registryAdded: [],
278
+ managed: { written: [], created: [], unchanged: [], skippedMerged: [], skippedModule: [], removed: [] },
279
+ ejected: { created: [], skipped: [] },
280
+ merged: { pending: [] },
281
+ configUpdated: false,
282
+ selfUpdate: false
283
+ };
284
+
285
+ const known = new Set([...managed, ...merged, ...ejected]);
286
+ for (const e of (DEFAULTS.files.managed || [])) {
287
+ if (!known.has(e)) { managed.push(e); known.add(e); report.registryAdded.push({ entry: e, list: 'managed' }); }
288
+ }
289
+ for (const e of (DEFAULTS.files.merged || [])) {
290
+ if (!known.has(e)) { merged.push(e); known.add(e); report.registryAdded.push({ entry: e, list: 'merged' }); }
291
+ }
292
+
293
+ const allRels = walkDir(templateRoot).map(f => norm(path.relative(templateRoot, f)));
294
+ const allSet = new Set(allRels);
295
+ const modSet = new Set(modules);
296
+
297
+ for (const entry of managed) {
298
+ const isDir = entry.endsWith('/');
299
+ let entryRels;
300
+ const expectedTargets = isDir ? new Set() : null;
301
+
302
+ if (isDir) {
303
+ const dir = path.join(templateRoot, entry);
304
+ if (!fs.existsSync(dir)) continue;
305
+ entryRels = walkDir(dir).map(f => norm(path.relative(templateRoot, f)));
306
+ } else {
307
+ entryRels = [];
308
+ const n = norm(entry);
309
+ if (allSet.has(n)) entryRels.push(n);
310
+ const ext = path.extname(entry), base = entry.slice(0, -ext.length);
311
+ const zh = norm(base + '.zh-CN' + ext);
312
+ if (allSet.has(zh)) entryRels.push(zh);
313
+ if (!entryRels.length) continue;
314
+ }
315
+
316
+ const selected = MULTI_LANG.has(norm(entry))
317
+ ? entryRels.map(r => [norm(renderPathname(r, project)), r])
318
+ : langSelect(entryRels, lang, allSet, project);
319
+
320
+ for (const [tgt, src] of selected) {
321
+ if (expectedTargets) expectedTargets.add(tgt);
322
+
323
+ const mod = fileModule(tgt);
324
+ if (mod !== null && !modSet.has(mod)) {
325
+ report.managed.skippedModule.push(tgt);
326
+ continue;
327
+ }
328
+
329
+ if (matchesAny(tgt, merged) || matchesAny(tgt, ejected)) {
330
+ report.managed.skippedMerged.push(tgt);
331
+ continue;
332
+ }
333
+
334
+ const srcFull = path.join(templateRoot, src);
335
+ const dstFull = path.join(projectRoot, tgt);
336
+ const bin = isBinary(srcFull);
337
+ const content = bin
338
+ ? fs.readFileSync(srcFull)
339
+ : renderContent(fs.readFileSync(srcFull, 'utf8'), vars);
340
+
341
+ const exists = fs.existsSync(dstFull);
342
+ if (exists) {
343
+ const cur = bin ? fs.readFileSync(dstFull) : fs.readFileSync(dstFull, 'utf8');
344
+ if (bin ? content.equals(cur) : content === cur) {
345
+ report.managed.unchanged.push(tgt);
346
+ continue;
347
+ }
348
+ }
349
+
350
+ const dir = path.dirname(dstFull);
351
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
352
+ fs.writeFileSync(dstFull, content);
353
+ if (tgt.endsWith('.sh')) {
354
+ try { fs.chmodSync(dstFull, 0o755); } catch { /* Windows */ }
355
+ }
356
+
357
+ (exists ? report.managed.written : report.managed.created).push(tgt);
358
+ }
359
+
360
+ if (isDir) {
361
+ const projDir = path.join(projectRoot, entry);
362
+ if (fs.existsSync(projDir)) {
363
+ const removedBefore = report.managed.removed.length;
364
+ const projFiles = walkDir(projDir).map(f => norm(path.relative(projectRoot, f)));
365
+ for (const projFile of projFiles) {
366
+ if (expectedTargets.has(projFile)) continue;
367
+ if (matchesAny(projFile, merged) || matchesAny(projFile, ejected)) continue;
368
+
369
+ const mod = fileModule(projFile);
370
+ if (mod !== null && !modSet.has(mod)) continue;
371
+
372
+ fs.unlinkSync(path.join(projectRoot, projFile));
373
+ report.managed.removed.push(projFile);
374
+ }
375
+ if (report.managed.removed.length > removedBefore) {
376
+ removeEmptyDirs(projDir);
377
+ }
378
+ }
379
+ }
380
+ }
381
+
382
+ for (const entry of ejected) {
383
+ const dstFull = path.join(projectRoot, entry);
384
+ if (fs.existsSync(dstFull)) {
385
+ report.ejected.skipped.push(entry);
386
+ continue;
387
+ }
388
+
389
+ let src = norm(entry);
390
+ if (lang === 'zh-CN') {
391
+ const ext = path.extname(entry), base = entry.slice(0, -ext.length);
392
+ const zh = norm(base + '.zh-CN' + ext);
393
+ if (allSet.has(zh)) src = zh;
394
+ }
395
+ if (!allSet.has(src)) continue;
396
+
397
+ const content = renderContent(fs.readFileSync(path.join(templateRoot, src), 'utf8'), vars);
398
+ const dir = path.dirname(dstFull);
399
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
400
+ fs.writeFileSync(dstFull, content);
401
+ report.ejected.created.push(entry);
402
+ }
403
+
404
+ const mergedMap = new Map();
405
+ for (const entry of merged) {
406
+ if (entry.includes('*')) {
407
+ const hits = allRels.filter(r => {
408
+ const t = norm(renderPathname(
409
+ r.includes('.zh-CN.') ? r.replace(/\.zh-CN\./, '.') : r, project
410
+ ));
411
+ return globMatch(entry, t);
412
+ });
413
+ for (const [t, s] of langSelect(hits, lang, allSet, project)) {
414
+ if (!mergedMap.has(t)) mergedMap.set(t, s);
415
+ }
416
+ } else {
417
+ const rels = [];
418
+ const n = norm(entry);
419
+ if (allSet.has(n)) rels.push(n);
420
+ const ext = path.extname(entry), base = entry.slice(0, -ext.length);
421
+ const zh = norm(base + '.zh-CN' + ext);
422
+ if (allSet.has(zh)) rels.push(zh);
423
+ const selected = MULTI_LANG.has(n)
424
+ ? rels.map(r => [norm(renderPathname(r, project)), r])
425
+ : langSelect(rels, lang, allSet, project);
426
+ for (const [t, s] of selected) {
427
+ if (!mergedMap.has(t)) mergedMap.set(t, s);
428
+ }
429
+ }
430
+ }
431
+ report.merged.pending = [...mergedMap].map(
432
+ ([target, template]) => ({ target, template })
433
+ );
434
+
435
+ const projUrl = gitUrl(projectRoot);
436
+ const instUrl = gitUrl(installDir);
437
+ report.selfUpdate = !!(projUrl && instUrl && projUrl === instUrl);
438
+
439
+ const hasChanges = (
440
+ report.managed.written.length +
441
+ report.managed.created.length +
442
+ report.managed.removed.length +
443
+ report.ejected.created.length +
444
+ report.registryAdded.length
445
+ ) > 0;
446
+
447
+ const prevVersion = cfg.templateVersion;
448
+
449
+ cfg.files.managed = managed;
450
+ cfg.files.merged = merged;
451
+ cfg.files.ejected = ejected;
452
+ cfg.templateVersion = version;
453
+
454
+ report.configUpdated = hasChanges || prevVersion !== version;
455
+
456
+ fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n', 'utf8');
457
+
458
+ return report;
459
+ }
460
+
461
+ const entryPath = process.argv[1] ? path.resolve(process.argv[1]) : null;
462
+ if (entryPath === fileURLToPath(import.meta.url)) {
463
+ const root = path.resolve(process.argv[2] || process.cwd());
464
+ const result = syncTemplates(root);
465
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
466
+ if (result.error) process.exitCode = 1;
467
+ }
468
+
469
+ export { syncTemplates };
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: upgrade-dependency
3
+ description: >
4
+ Upgrade a specified dependency package to a new version and verify
5
+ the change. Triggered when the user requests dependency upgrade.
6
+ Arguments: package name, old version, new version.
7
+ ---
8
+
9
+ # Upgrade Dependency
10
+
11
+ Upgrade a dependency package to the specified version with build and test verification.
12
+
13
+ <!-- TODO: Adapt the commands below to your project's package manager -->
14
+
15
+ ## Execution Flow
16
+
17
+ ### 1. Parse Arguments
18
+
19
+ Extract from arguments: package name, old version, new version.
20
+
21
+ ### 2. Find Dependency Location
22
+
23
+ Search for the package in dependency files:
24
+ - `package.json` (Node.js)
25
+ - `pom.xml` (Maven)
26
+ - `requirements.txt` / `pyproject.toml` (Python)
27
+ - `go.mod` (Go)
28
+ - Other project-specific dependency files
29
+
30
+ ### 3. Update Version
31
+
32
+ Update the version number in the dependency file.
33
+
34
+ ### 4. Install Dependencies
35
+
36
+ <!-- TODO: Replace with your project's install command -->
37
+ ```bash
38
+ # npm install (Node.js)
39
+ # mvn clean install (Maven)
40
+ # pip install -r requirements.txt (Python)
41
+ # go mod tidy (Go)
42
+ ```
43
+
44
+ ### 5. Verify Build
45
+
46
+ <!-- TODO: Replace with your project's build command -->
47
+ ```bash
48
+ # npm run build (Node.js)
49
+ # mvn compile (Maven)
50
+ # make build (generic)
51
+ ```
52
+
53
+ ### 6. Run Tests
54
+
55
+ Execute the project's test command. Reference the test skill for the project-specific test command.
56
+
57
+ ### 7. Output Results
58
+
59
+ Report:
60
+ - Files modified
61
+ - Build status (pass/fail)
62
+ - Test status (pass/fail)
63
+ - Any deprecation warnings or breaking changes noticed
64
+
65
+ Suggest next step:
66
+
67
+ > **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent.
68
+
69
+ ```
70
+ Next step - commit changes:
71
+ - Claude Code / OpenCode: /commit
72
+ - Gemini CLI: /{{project}}:commit
73
+ - Codex CLI: $commit
74
+ ```
75
+
76
+ ## Notes
77
+
78
+ 1. **No auto-commit**: Do NOT automatically commit changes
79
+ 2. **Major version upgrades**: Warn about potential breaking changes
80
+ 3. **Test failures**: Report the failure details and wait for user decision
81
+ 4. **Lock files**: If the project uses lock files (package-lock.json, yarn.lock, etc.), ensure they are updated
82
+ 5. **Transitive dependencies**: Note if the upgrade affects transitive dependencies
83
+
84
+ ## Error Handling
85
+
86
+ - Package not found: Prompt "Package {name} not found in dependency files"
87
+ - Build failure: Output errors and suggest checking for breaking changes
88
+ - Test failure: Output test errors and suggest checking migration guide
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: upgrade-dependency
3
+ description: >
4
+ 升级项目中的指定依赖包到新版本并验证变更。
5
+ 当用户要求升级依赖时触发。参数:包名、原版本和新版本。
6
+ ---
7
+
8
+ # 升级依赖
9
+
10
+ 将依赖包升级到指定版本,并进行构建和测试验证。
11
+
12
+ <!-- TODO: 根据你的项目包管理器调整以下命令 -->
13
+
14
+ ## 执行流程
15
+
16
+ ### 1. 解析参数
17
+
18
+ 从参数中提取:包名、原版本、新版本。
19
+
20
+ ### 2. 查找依赖位置
21
+
22
+ 在依赖文件中搜索目标包:
23
+ - `package.json`(Node.js)
24
+ - `pom.xml`(Maven)
25
+ - `requirements.txt` / `pyproject.toml`(Python)
26
+ - `go.mod`(Go)
27
+ - 其他项目特定的依赖文件
28
+
29
+ ### 3. 更新版本
30
+
31
+ 在依赖文件中更新版本号。
32
+
33
+ ### 4. 安装依赖
34
+
35
+ <!-- TODO: 替换为你的项目安装命令 -->
36
+ ```bash
37
+ # npm install (Node.js)
38
+ # mvn clean install (Maven)
39
+ # pip install -r requirements.txt (Python)
40
+ # go mod tidy (Go)
41
+ ```
42
+
43
+ ### 5. 验证构建
44
+
45
+ <!-- TODO: 替换为你的项目构建命令 -->
46
+ ```bash
47
+ # npm run build (Node.js)
48
+ # mvn compile (Maven)
49
+ # make build (通用)
50
+ ```
51
+
52
+ ### 6. 运行测试
53
+
54
+ 执行项目的测试命令。参考 test 技能获取项目特定的测试命令。
55
+
56
+ ### 7. 输出结果
57
+
58
+ 报告:
59
+ - 修改的文件
60
+ - 构建状态(通过/失败)
61
+ - 测试状态(通过/失败)
62
+ - 发现的任何弃用警告或破坏性变更
63
+
64
+ 建议下一步:
65
+
66
+ > **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI 代理对应的格式。
67
+
68
+ ```
69
+ 下一步 - 提交代码:
70
+ - Claude Code / OpenCode:/commit
71
+ - Gemini CLI:/{{project}}:commit
72
+ - Codex CLI:$commit
73
+ ```
74
+
75
+ ## 注意事项
76
+
77
+ 1. **禁止自动提交**:不要自动提交变更
78
+ 2. **主版本升级**:警告潜在的破坏性变更
79
+ 3. **测试失败**:报告失败详情并等待用户决定
80
+ 4. **锁文件**:如果项目使用锁文件(package-lock.json、yarn.lock 等),确保一并更新
81
+ 5. **传递依赖**:注意升级是否影响传递依赖
82
+
83
+ ## 错误处理
84
+
85
+ - 包未找到:提示 "Package {name} not found in dependency files"
86
+ - 构建失败:输出错误并建议检查破坏性变更
87
+ - 测试失败:输出测试错误并建议查看迁移指南
@@ -0,0 +1,60 @@
1
+ # Handoff Document
2
+
3
+ ## Metadata
4
+
5
+ - **Task ID**: task-XXX
6
+ - **From**: [AI tool name, e.g., claude]
7
+ - **To**: [AI tool name, e.g., codex]
8
+ - **Phase Completed**: [e.g., analysis]
9
+ - **Next Phase**: [e.g., design]
10
+ - **Date**: YYYY-MM-DD
11
+
12
+ ## Summary of Completed Work
13
+
14
+ [Brief summary of what was accomplished in the completed phase.]
15
+
16
+ ## Current State
17
+
18
+ ### Files Modified
19
+
20
+ - `path/to/file1` - What was changed and why
21
+ - `path/to/file2` - What was changed and why
22
+
23
+ ### Branch Status
24
+
25
+ - **Branch**: `feature/xxx`
26
+ - **Commits**: [Number of commits made]
27
+ - **Tests**: [Passing / Failing / Not yet written]
28
+
29
+ ### Key Decisions Made
30
+
31
+ 1. [Decision 1 and rationale]
32
+ 2. [Decision 2 and rationale]
33
+
34
+ ## Next Steps
35
+
36
+ [What the receiving AI should do next. Be specific.]
37
+
38
+ 1. [ ] Step 1
39
+ 2. [ ] Step 2
40
+ 3. [ ] Step 3
41
+
42
+ ## Important Context
43
+
44
+ [Anything the receiving AI needs to know that isn't obvious from the code.]
45
+
46
+ ### Constraints
47
+
48
+ - [Constraint 1]
49
+ - [Constraint 2]
50
+
51
+ ### Risks and Concerns
52
+
53
+ - [Risk 1]
54
+ - [Risk 2]
55
+
56
+ ## References
57
+
58
+ - Task file: `.agent-workspace/active/task-XXX.md`
59
+ - Related docs: [links or file paths]
60
+ - Related issues: #XXX