@mison/ag-kit-cn 3.0.0-beta.0 → 3.0.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 (254) hide show
  1. package/CHANGELOG.md +13 -11
  2. package/README.md +70 -35
  3. package/bin/adapters/codex.js +105 -372
  4. package/bin/adapters/gemini.js +133 -13
  5. package/bin/ag-kit.js +557 -155
  6. package/bin/core/builder.js +1 -1
  7. package/bin/core/generator.js +4 -4
  8. package/bin/core/resource-loader.js +2 -2
  9. package/bin/interactive.js +36 -81
  10. package/bin/utils/manifest.js +3 -3
  11. package/bin/utils.js +8 -3
  12. package/docs/PLAN.md +39 -0
  13. package/docs/TECH.md +136 -0
  14. package/package.json +11 -10
  15. package/scripts/ci-verify.js +95 -0
  16. package/scripts/clean.js +123 -0
  17. package/scripts/health-check.js +132 -0
  18. package/scripts/health-check.sh +6 -0
  19. package/tests/atomic-writer.test.js +47 -0
  20. package/tests/clean-script.test.js +77 -0
  21. package/tests/cli-smoke.test.js +479 -0
  22. package/tests/codex-adapter.test.js +132 -0
  23. package/tests/doctor.test.js +94 -0
  24. package/tests/gemini-adapter.test.js +30 -0
  25. package/tests/generator.test.js +48 -0
  26. package/tests/git-helper.test.js +53 -0
  27. package/tests/global-sync.test.js +133 -0
  28. package/tests/health-check-script.test.js +30 -0
  29. package/tests/managed-block.test.js +41 -0
  30. package/tests/manifest.test.js +97 -0
  31. package/tests/package-tarball.test.js +27 -0
  32. package/tests/phase-c.test.js +107 -0
  33. package/tests/standards-compliance.test.js +266 -0
  34. package/tests/transformer.test.js +74 -0
  35. package/docs/codex-rules-template.md +0 -36
  36. package/docs/mapping-spec.md +0 -62
  37. package/docs/multi-target-adapter.md +0 -46
  38. package/docs/official/README.md +0 -45
  39. package/docs/official/antigravity/agent-modes-settings.md +0 -64
  40. package/docs/official/antigravity/rules-workflows.md +0 -96
  41. package/docs/official/antigravity/skills.md +0 -147
  42. package/docs/official/codex/agents-md.md +0 -119
  43. package/docs/official/codex/config-advanced.md +0 -358
  44. package/docs/official/codex/config-basic.md +0 -141
  45. package/docs/official/codex/config-reference.md +0 -223
  46. package/docs/official/codex/config-sample.md +0 -216
  47. package/docs/official/codex/mcp.md +0 -107
  48. package/docs/official/codex/rules.md +0 -79
  49. package/docs/official/codex/skills.md +0 -114
  50. package/docs/official/mechanism-compat-audit-2026-03-04.md +0 -36
  51. package/docs/official/rules-baseline.md +0 -67
  52. package/docs/official/sources-index.md +0 -79
  53. package/docs/operations.md +0 -75
  54. package/docs/terminology-style-guide.md +0 -69
  55. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/charts.csv +0 -0
  56. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/colors.csv +0 -0
  57. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/icons.csv +0 -0
  58. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/landing.csv +0 -0
  59. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/products.csv +0 -0
  60. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/prompts.csv +0 -0
  61. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/react-performance.csv +0 -0
  62. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -0
  63. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -0
  64. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -0
  65. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -0
  66. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -0
  67. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -0
  68. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -0
  69. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -0
  70. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -0
  71. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -0
  72. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -0
  73. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -0
  74. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/styles.csv +0 -0
  75. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/typography.csv +0 -0
  76. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -0
  77. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -0
  78. /package/{.agent → .agents}/.shared/ui-ux-pro-max/data/web-interface.csv +0 -0
  79. /package/{.agent → .agents}/.shared/ui-ux-pro-max/scripts/core.py +0 -0
  80. /package/{.agent → .agents}/.shared/ui-ux-pro-max/scripts/design_system.py +0 -0
  81. /package/{.agent → .agents}/.shared/ui-ux-pro-max/scripts/search.py +0 -0
  82. /package/{.agent → .agents}/ARCHITECTURE.md +0 -0
  83. /package/{.agent → .agents}/agents/backend-specialist.md +0 -0
  84. /package/{.agent → .agents}/agents/code-archaeologist.md +0 -0
  85. /package/{.agent → .agents}/agents/database-architect.md +0 -0
  86. /package/{.agent → .agents}/agents/debugger.md +0 -0
  87. /package/{.agent → .agents}/agents/devops-engineer.md +0 -0
  88. /package/{.agent → .agents}/agents/documentation-writer.md +0 -0
  89. /package/{.agent → .agents}/agents/explorer-agent.md +0 -0
  90. /package/{.agent → .agents}/agents/frontend-specialist.md +0 -0
  91. /package/{.agent → .agents}/agents/game-developer.md +0 -0
  92. /package/{.agent → .agents}/agents/mobile-developer.md +0 -0
  93. /package/{.agent → .agents}/agents/orchestrator.md +0 -0
  94. /package/{.agent → .agents}/agents/penetration-tester.md +0 -0
  95. /package/{.agent → .agents}/agents/performance-optimizer.md +0 -0
  96. /package/{.agent → .agents}/agents/product-manager.md +0 -0
  97. /package/{.agent → .agents}/agents/product-owner.md +0 -0
  98. /package/{.agent → .agents}/agents/project-planner.md +0 -0
  99. /package/{.agent → .agents}/agents/qa-automation-engineer.md +0 -0
  100. /package/{.agent → .agents}/agents/security-auditor.md +0 -0
  101. /package/{.agent → .agents}/agents/seo-specialist.md +0 -0
  102. /package/{.agent → .agents}/agents/test-engineer.md +0 -0
  103. /package/{.agent → .agents}/mcp_config.json +0 -0
  104. /package/{.agent → .agents}/rules/GEMINI.md +0 -0
  105. /package/{.agent → .agents}/scripts/auto_preview.py +0 -0
  106. /package/{.agent → .agents}/scripts/checklist.py +0 -0
  107. /package/{.agent → .agents}/scripts/session_manager.py +0 -0
  108. /package/{.agent → .agents}/scripts/verify_all.py +0 -0
  109. /package/{.agent → .agents}/skills/api-patterns/SKILL.md +0 -0
  110. /package/{.agent → .agents}/skills/api-patterns/api-style.md +0 -0
  111. /package/{.agent → .agents}/skills/api-patterns/auth.md +0 -0
  112. /package/{.agent → .agents}/skills/api-patterns/documentation.md +0 -0
  113. /package/{.agent → .agents}/skills/api-patterns/graphql.md +0 -0
  114. /package/{.agent → .agents}/skills/api-patterns/rate-limiting.md +0 -0
  115. /package/{.agent → .agents}/skills/api-patterns/response.md +0 -0
  116. /package/{.agent → .agents}/skills/api-patterns/rest.md +0 -0
  117. /package/{.agent → .agents}/skills/api-patterns/scripts/api_validator.py +0 -0
  118. /package/{.agent → .agents}/skills/api-patterns/security-testing.md +0 -0
  119. /package/{.agent → .agents}/skills/api-patterns/trpc.md +0 -0
  120. /package/{.agent → .agents}/skills/api-patterns/versioning.md +0 -0
  121. /package/{.agent → .agents}/skills/app-builder/SKILL.md +0 -0
  122. /package/{.agent → .agents}/skills/app-builder/agent-coordination.md +0 -0
  123. /package/{.agent → .agents}/skills/app-builder/feature-building.md +0 -0
  124. /package/{.agent → .agents}/skills/app-builder/project-detection.md +0 -0
  125. /package/{.agent → .agents}/skills/app-builder/scaffolding.md +0 -0
  126. /package/{.agent → .agents}/skills/app-builder/tech-stack.md +0 -0
  127. /package/{.agent → .agents}/skills/app-builder/templates/SKILL.md +0 -0
  128. /package/{.agent → .agents}/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -0
  129. /package/{.agent → .agents}/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -0
  130. /package/{.agent → .agents}/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -0
  131. /package/{.agent → .agents}/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -0
  132. /package/{.agent → .agents}/skills/app-builder/templates/express-api/TEMPLATE.md +0 -0
  133. /package/{.agent → .agents}/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -0
  134. /package/{.agent → .agents}/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -0
  135. /package/{.agent → .agents}/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -0
  136. /package/{.agent → .agents}/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -0
  137. /package/{.agent → .agents}/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -0
  138. /package/{.agent → .agents}/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -0
  139. /package/{.agent → .agents}/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -0
  140. /package/{.agent → .agents}/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -0
  141. /package/{.agent → .agents}/skills/architecture/SKILL.md +0 -0
  142. /package/{.agent → .agents}/skills/architecture/context-discovery.md +0 -0
  143. /package/{.agent → .agents}/skills/architecture/examples.md +0 -0
  144. /package/{.agent → .agents}/skills/architecture/pattern-selection.md +0 -0
  145. /package/{.agent → .agents}/skills/architecture/patterns-reference.md +0 -0
  146. /package/{.agent → .agents}/skills/architecture/trade-off-analysis.md +0 -0
  147. /package/{.agent → .agents}/skills/bash-linux/SKILL.md +0 -0
  148. /package/{.agent → .agents}/skills/behavioral-modes/SKILL.md +0 -0
  149. /package/{.agent → .agents}/skills/brainstorming/SKILL.md +0 -0
  150. /package/{.agent → .agents}/skills/brainstorming/dynamic-questioning.md +0 -0
  151. /package/{.agent → .agents}/skills/clean-code/SKILL.md +0 -0
  152. /package/{.agent → .agents}/skills/code-review-checklist/SKILL.md +0 -0
  153. /package/{.agent → .agents}/skills/database-design/SKILL.md +0 -0
  154. /package/{.agent → .agents}/skills/database-design/database-selection.md +0 -0
  155. /package/{.agent → .agents}/skills/database-design/indexing.md +0 -0
  156. /package/{.agent → .agents}/skills/database-design/migrations.md +0 -0
  157. /package/{.agent → .agents}/skills/database-design/optimization.md +0 -0
  158. /package/{.agent → .agents}/skills/database-design/orm-selection.md +0 -0
  159. /package/{.agent → .agents}/skills/database-design/schema-design.md +0 -0
  160. /package/{.agent → .agents}/skills/database-design/scripts/schema_validator.py +0 -0
  161. /package/{.agent → .agents}/skills/deployment-procedures/SKILL.md +0 -0
  162. /package/{.agent → .agents}/skills/doc.md +0 -0
  163. /package/{.agent → .agents}/skills/documentation-templates/SKILL.md +0 -0
  164. /package/{.agent → .agents}/skills/frontend-design/SKILL.md +0 -0
  165. /package/{.agent → .agents}/skills/frontend-design/animation-guide.md +0 -0
  166. /package/{.agent → .agents}/skills/frontend-design/color-system.md +0 -0
  167. /package/{.agent → .agents}/skills/frontend-design/decision-trees.md +0 -0
  168. /package/{.agent → .agents}/skills/frontend-design/motion-graphics.md +0 -0
  169. /package/{.agent → .agents}/skills/frontend-design/scripts/accessibility_checker.py +0 -0
  170. /package/{.agent → .agents}/skills/frontend-design/scripts/ux_audit.py +0 -0
  171. /package/{.agent → .agents}/skills/frontend-design/typography-system.md +0 -0
  172. /package/{.agent → .agents}/skills/frontend-design/ux-psychology.md +0 -0
  173. /package/{.agent → .agents}/skills/frontend-design/visual-effects.md +0 -0
  174. /package/{.agent → .agents}/skills/game-development/2d-games/SKILL.md +0 -0
  175. /package/{.agent → .agents}/skills/game-development/3d-games/SKILL.md +0 -0
  176. /package/{.agent → .agents}/skills/game-development/SKILL.md +0 -0
  177. /package/{.agent → .agents}/skills/game-development/game-art/SKILL.md +0 -0
  178. /package/{.agent → .agents}/skills/game-development/game-audio/SKILL.md +0 -0
  179. /package/{.agent → .agents}/skills/game-development/game-design/SKILL.md +0 -0
  180. /package/{.agent → .agents}/skills/game-development/mobile-games/SKILL.md +0 -0
  181. /package/{.agent → .agents}/skills/game-development/multiplayer/SKILL.md +0 -0
  182. /package/{.agent → .agents}/skills/game-development/pc-games/SKILL.md +0 -0
  183. /package/{.agent → .agents}/skills/game-development/vr-ar/SKILL.md +0 -0
  184. /package/{.agent → .agents}/skills/game-development/web-games/SKILL.md +0 -0
  185. /package/{.agent → .agents}/skills/geo-fundamentals/SKILL.md +0 -0
  186. /package/{.agent → .agents}/skills/geo-fundamentals/scripts/geo_checker.py +0 -0
  187. /package/{.agent → .agents}/skills/i18n-localization/SKILL.md +0 -0
  188. /package/{.agent → .agents}/skills/i18n-localization/scripts/i18n_checker.py +0 -0
  189. /package/{.agent → .agents}/skills/intelligent-routing/SKILL.md +0 -0
  190. /package/{.agent → .agents}/skills/lint-and-validate/SKILL.md +0 -0
  191. /package/{.agent → .agents}/skills/lint-and-validate/scripts/lint_runner.py +0 -0
  192. /package/{.agent → .agents}/skills/lint-and-validate/scripts/type_coverage.py +0 -0
  193. /package/{.agent → .agents}/skills/mcp-builder/SKILL.md +0 -0
  194. /package/{.agent → .agents}/skills/mobile-design/SKILL.md +0 -0
  195. /package/{.agent → .agents}/skills/mobile-design/decision-trees.md +0 -0
  196. /package/{.agent → .agents}/skills/mobile-design/mobile-backend.md +0 -0
  197. /package/{.agent → .agents}/skills/mobile-design/mobile-color-system.md +0 -0
  198. /package/{.agent → .agents}/skills/mobile-design/mobile-debugging.md +0 -0
  199. /package/{.agent → .agents}/skills/mobile-design/mobile-design-thinking.md +0 -0
  200. /package/{.agent → .agents}/skills/mobile-design/mobile-navigation.md +0 -0
  201. /package/{.agent → .agents}/skills/mobile-design/mobile-performance.md +0 -0
  202. /package/{.agent → .agents}/skills/mobile-design/mobile-testing.md +0 -0
  203. /package/{.agent → .agents}/skills/mobile-design/mobile-typography.md +0 -0
  204. /package/{.agent → .agents}/skills/mobile-design/platform-android.md +0 -0
  205. /package/{.agent → .agents}/skills/mobile-design/platform-ios.md +0 -0
  206. /package/{.agent → .agents}/skills/mobile-design/scripts/mobile_audit.py +0 -0
  207. /package/{.agent → .agents}/skills/mobile-design/touch-psychology.md +0 -0
  208. /package/{.agent → .agents}/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +0 -0
  209. /package/{.agent → .agents}/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +0 -0
  210. /package/{.agent → .agents}/skills/nextjs-react-expert/3-server-server-side-performance.md +0 -0
  211. /package/{.agent → .agents}/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +0 -0
  212. /package/{.agent → .agents}/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +0 -0
  213. /package/{.agent → .agents}/skills/nextjs-react-expert/6-rendering-rendering-performance.md +0 -0
  214. /package/{.agent → .agents}/skills/nextjs-react-expert/7-js-javascript-performance.md +0 -0
  215. /package/{.agent → .agents}/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +0 -0
  216. /package/{.agent → .agents}/skills/nextjs-react-expert/SKILL.md +0 -0
  217. /package/{.agent → .agents}/skills/nextjs-react-expert/scripts/convert_rules.py +0 -0
  218. /package/{.agent → .agents}/skills/nextjs-react-expert/scripts/react_performance_checker.py +0 -0
  219. /package/{.agent → .agents}/skills/nodejs-best-practices/SKILL.md +0 -0
  220. /package/{.agent → .agents}/skills/parallel-agents/SKILL.md +0 -0
  221. /package/{.agent → .agents}/skills/performance-profiling/SKILL.md +0 -0
  222. /package/{.agent → .agents}/skills/performance-profiling/scripts/lighthouse_audit.py +0 -0
  223. /package/{.agent → .agents}/skills/plan-writing/SKILL.md +0 -0
  224. /package/{.agent → .agents}/skills/powershell-windows/SKILL.md +0 -0
  225. /package/{.agent → .agents}/skills/python-patterns/SKILL.md +0 -0
  226. /package/{.agent → .agents}/skills/red-team-tactics/SKILL.md +0 -0
  227. /package/{.agent → .agents}/skills/refactoring-patterns/SKILL.md +0 -0
  228. /package/{.agent → .agents}/skills/rust-pro/SKILL.md +0 -0
  229. /package/{.agent → .agents}/skills/seo-fundamentals/SKILL.md +0 -0
  230. /package/{.agent → .agents}/skills/seo-fundamentals/scripts/seo_checker.py +0 -0
  231. /package/{.agent → .agents}/skills/server-management/SKILL.md +0 -0
  232. /package/{.agent → .agents}/skills/systematic-debugging/SKILL.md +0 -0
  233. /package/{.agent → .agents}/skills/tailwind-patterns/SKILL.md +0 -0
  234. /package/{.agent → .agents}/skills/tdd-workflow/SKILL.md +0 -0
  235. /package/{.agent → .agents}/skills/testing-patterns/SKILL.md +0 -0
  236. /package/{.agent → .agents}/skills/testing-patterns/scripts/test_runner.py +0 -0
  237. /package/{.agent → .agents}/skills/vulnerability-scanner/SKILL.md +0 -0
  238. /package/{.agent → .agents}/skills/vulnerability-scanner/checklists.md +0 -0
  239. /package/{.agent → .agents}/skills/vulnerability-scanner/scripts/security_scan.py +0 -0
  240. /package/{.agent → .agents}/skills/web-design-guidelines/SKILL.md +0 -0
  241. /package/{.agent → .agents}/skills/webapp-testing/SKILL.md +0 -0
  242. /package/{.agent → .agents}/skills/webapp-testing/scripts/playwright_runner.py +0 -0
  243. /package/{.agent → .agents}/workflows/brainstorm.md +0 -0
  244. /package/{.agent → .agents}/workflows/create.md +0 -0
  245. /package/{.agent → .agents}/workflows/debug.md +0 -0
  246. /package/{.agent → .agents}/workflows/deploy.md +0 -0
  247. /package/{.agent → .agents}/workflows/enhance.md +0 -0
  248. /package/{.agent → .agents}/workflows/orchestrate.md +0 -0
  249. /package/{.agent → .agents}/workflows/plan.md +0 -0
  250. /package/{.agent → .agents}/workflows/preview.md +0 -0
  251. /package/{.agent → .agents}/workflows/restore-localize-compat.md +0 -0
  252. /package/{.agent → .agents}/workflows/status.md +0 -0
  253. /package/{.agent → .agents}/workflows/test.md +0 -0
  254. /package/{.agent → .agents}/workflows/ui-ux-pro-max.md +0 -0
package/bin/ag-kit.js CHANGED
@@ -5,30 +5,51 @@ const os = require("os");
5
5
  const path = require("path");
6
6
 
7
7
  const pkg = require("../package.json");
8
- const { readGlobalNpmDependencies } = require("./utils");
8
+ const { readGlobalNpmDependencies, cloneBranchAgentDir } = require("./utils");
9
+ const ManifestManager = require("./utils/manifest");
10
+ const AtomicWriter = require("./utils/atomic-writer");
11
+ const CodexBuilder = require("./core/builder");
12
+ const GeminiAdapter = require("./adapters/gemini");
9
13
  const CodexAdapter = require("./adapters/codex");
10
- const {
11
- selectTargets,
12
- selectAgentConflictPolicy,
13
- selectGeminiAgentsPolicy,
14
- } = require("./interactive");
15
-
16
- const BUNDLED_AGENT_DIR = fs.existsSync(path.resolve(__dirname, "../.agents"))
17
- ? path.resolve(__dirname, "../.agents")
18
- : path.resolve(__dirname, "../.agent");
14
+ const { selectTargets } = require("./interactive");
15
+
16
+ const BUNDLED_AGENT_DIR = path.resolve(__dirname, "../.agents");
19
17
  const WORKSPACE_INDEX_VERSION = 2;
20
18
  const UPSTREAM_GLOBAL_PACKAGE = "@vudovn/ag-kit";
21
19
  const TOOLKIT_PACKAGE_NAMES = new Set(["@mison/ag-kit-cn", "antigravity-kit-cn", "antigravity-kit"]);
22
- const SUPPORTED_TARGETS = ["full", "agents", "gemini", "codex"];
23
- const TARGET_ALIAS_MAP = {
24
- full: "full",
25
- agents: "full",
26
- gemini: "full",
27
- codex: "full",
20
+ const SUPPORTED_TARGETS = ["gemini", "codex"];
21
+ const LEGACY_INDEX_TARGET_ALIASES = {
22
+ full: "gemini",
23
+ };
24
+ const GLOBAL_TARGET_DESTINATIONS = {
25
+ codex: [
26
+ {
27
+ id: "codex",
28
+ rootParts: [".codex"],
29
+ skillsParts: [".codex", "skills"],
30
+ },
31
+ ],
32
+ gemini: [
33
+ {
34
+ id: "gemini-cli",
35
+ rootParts: [".gemini", "skills"],
36
+ skillsParts: [".gemini", "skills"],
37
+ },
38
+ {
39
+ id: "antigravity",
40
+ rootParts: [".gemini", "antigravity"],
41
+ skillsParts: [".gemini", "antigravity", "skills"],
42
+ },
43
+ ],
28
44
  };
29
45
  const INDEX_LOCK_RETRY_MS = 50;
30
46
  const INDEX_LOCK_TIMEOUT_MS = 3000;
31
47
  const INDEX_LOCK_STALE_MS = 30000;
48
+ const QUIET_STATUS_EXIT_CODES = {
49
+ installed: 0,
50
+ broken: 1,
51
+ missing: 2,
52
+ };
32
53
 
33
54
  function nowISO() {
34
55
  return new Date().toISOString();
@@ -51,20 +72,79 @@ function createEmptyWorkspaceIndex() {
51
72
  };
52
73
  }
53
74
 
75
+ function resolveGlobalRootDir() {
76
+ const customRoot = process.env.AG_KIT_GLOBAL_ROOT;
77
+ if (typeof customRoot === "string" && customRoot.trim()) {
78
+ return path.resolve(process.cwd(), customRoot);
79
+ }
80
+ return os.homedir();
81
+ }
82
+
83
+ function getGlobalDestinations(targetName, globalRoot = resolveGlobalRootDir()) {
84
+ const config = GLOBAL_TARGET_DESTINATIONS[targetName];
85
+ if (!config) {
86
+ throw new Error(`未知目标: ${targetName}`);
87
+ }
88
+ return config.map((item) => ({
89
+ ...item,
90
+ targetName,
91
+ rootDir: path.join(globalRoot, ...item.rootParts),
92
+ skillsRoot: path.join(globalRoot, ...item.skillsParts),
93
+ }));
94
+ }
95
+
96
+ function listGlobalDestinations(globalRoot = resolveGlobalRootDir()) {
97
+ return Object.keys(GLOBAL_TARGET_DESTINATIONS).flatMap((targetName) => getGlobalDestinations(targetName, globalRoot));
98
+ }
99
+
100
+ function resolveGlobalBackupRoot(timestamp) {
101
+ const globalRoot = resolveGlobalRootDir();
102
+ return path.join(globalRoot, ".ag-kit", "backups", "global", timestamp);
103
+ }
104
+
105
+ function copyDirRecursive(src, dest) {
106
+ fs.mkdirSync(dest, { recursive: true });
107
+ const entries = fs.readdirSync(src, { withFileTypes: true });
108
+ for (const entry of entries) {
109
+ const srcPath = path.join(src, entry.name);
110
+ const destPath = path.join(dest, entry.name);
111
+ if (entry.isDirectory()) {
112
+ copyDirRecursive(srcPath, destPath);
113
+ } else {
114
+ fs.copyFileSync(srcPath, destPath);
115
+ }
116
+ }
117
+ }
118
+
119
+ function areDirectoriesEqual(leftDir, rightDir) {
120
+ const left = ManifestManager.generateFromDir(leftDir);
121
+ const right = ManifestManager.generateFromDir(rightDir);
122
+ const leftKeys = Object.keys(left);
123
+ const rightKeys = Object.keys(right);
124
+ if (leftKeys.length !== rightKeys.length) {
125
+ return false;
126
+ }
127
+ for (const key of leftKeys) {
128
+ if (left[key] !== right[key]) {
129
+ return false;
130
+ }
131
+ }
132
+ return true;
133
+ }
134
+
54
135
  function printUsage() {
55
136
  console.log("用法:");
56
137
  console.log(" ag-kit init [--force] [--path <dir>] [--branch <name>] [--target <name>|--targets <a,b>] [--non-interactive] [--no-index] [--quiet] [--dry-run]");
57
138
  console.log(" ag-kit update [--path <dir>] [--branch <name>] [--target <name>|--targets <a,b>] [--no-index] [--quiet] [--dry-run]");
58
139
  console.log(" ag-kit update-all [--branch <name>] [--targets <a,b>] [--prune-missing] [--quiet] [--dry-run]");
59
140
  console.log(" ag-kit doctor [--path <dir>] [--target <name>|--targets <a,b>] [--fix] [--quiet]");
141
+ console.log(" ag-kit global sync [--target <name>|--targets <a,b>] [--branch <name>] [--quiet] [--dry-run] # 默认同步 codex + gemini(cli+antigravity)");
142
+ console.log(" ag-kit global status [--quiet]");
60
143
  console.log(" ag-kit exclude list [--quiet]");
61
144
  console.log(" ag-kit exclude add --path <dir> [--dry-run] [--quiet]");
62
145
  console.log(" ag-kit exclude remove --path <dir> [--dry-run] [--quiet]");
63
146
  console.log(" ag-kit status [--path <dir>] [--quiet]");
64
147
  console.log(" ag-kit --version");
65
- console.log("");
66
- console.log("说明:");
67
- console.log(" --target gemini/codex/full 现均归一为统一 full 安装(.agents 为主目录)");
68
148
  }
69
149
 
70
150
  function printVersion() {
@@ -89,18 +169,16 @@ function parseArgs(argv) {
89
169
  path: "",
90
170
  branch: "",
91
171
  targets: [],
92
- agentConflictPolicy: "",
93
- geminiAgentsPolicy: "",
94
172
  };
95
173
  const providedFlags = [];
96
174
 
97
175
  let startIndex = 1;
98
- if (command === "exclude") {
176
+ if (command === "exclude" || command === "global") {
99
177
  if (argv.length > 1 && !argv[1].startsWith("--")) {
100
178
  options.subcommand = argv[1];
101
179
  startIndex = 2;
102
180
  } else {
103
- options.subcommand = "list";
181
+ options.subcommand = command === "global" ? "status" : "list";
104
182
  startIndex = 1;
105
183
  }
106
184
  }
@@ -167,6 +245,8 @@ const COMMAND_ALLOWED_FLAGS = {
167
245
  "update-all": ["--branch", "--targets", "--prune-missing", "--quiet", "--dry-run"],
168
246
  doctor: ["--path", "--target", "--targets", "--fix", "--quiet"],
169
247
  status: ["--path", "--quiet"],
248
+ "global:sync": ["--target", "--targets", "--branch", "--quiet", "--dry-run"],
249
+ "global:status": ["--quiet"],
170
250
  "exclude:list": ["--quiet"],
171
251
  "exclude:add": ["--path", "--dry-run", "--quiet"],
172
252
  "exclude:remove": ["--path", "--dry-run", "--quiet"],
@@ -178,6 +258,11 @@ function resolveAllowedFlags(command, options) {
178
258
  const key = `exclude:${subcommand}`;
179
259
  return COMMAND_ALLOWED_FLAGS[key] || null;
180
260
  }
261
+ if (command === "global") {
262
+ const subcommand = String(options.subcommand || "status").toLowerCase();
263
+ const key = `global:${subcommand}`;
264
+ return COMMAND_ALLOWED_FLAGS[key] || null;
265
+ }
181
266
  return COMMAND_ALLOWED_FLAGS[command] || null;
182
267
  }
183
268
 
@@ -186,6 +271,10 @@ function resolveCommandLabel(command, options) {
186
271
  const subcommand = String(options.subcommand || "list").toLowerCase();
187
272
  return `exclude ${subcommand}`;
188
273
  }
274
+ if (command === "global") {
275
+ const subcommand = String(options.subcommand || "status").toLowerCase();
276
+ return `global ${subcommand}`;
277
+ }
189
278
  return command;
190
279
  }
191
280
 
@@ -357,25 +446,34 @@ function normalizeTargetState(value) {
357
446
  };
358
447
  }
359
448
 
360
- function normalizeTargetName(rawTarget) {
361
- const key = String(rawTarget || "").trim().toLowerCase();
362
- if (!key) {
363
- return "";
449
+ function normalizeIndexTargetName(targetName) {
450
+ if (typeof targetName !== "string") {
451
+ return null;
452
+ }
453
+ const normalized = targetName.trim().toLowerCase();
454
+ if (!normalized) {
455
+ return null;
456
+ }
457
+ if (Object.prototype.hasOwnProperty.call(LEGACY_INDEX_TARGET_ALIASES, normalized)) {
458
+ return LEGACY_INDEX_TARGET_ALIASES[normalized];
364
459
  }
365
- return TARGET_ALIAS_MAP[key] || "";
460
+ if (SUPPORTED_TARGETS.includes(normalized)) {
461
+ return normalized;
462
+ }
463
+ return null;
366
464
  }
367
465
 
368
466
  function normalizeWorkspaceRecordV2(item, normalizedPath) {
369
467
  const targets = {};
370
468
  if (item && item.targets && typeof item.targets === "object") {
371
469
  for (const [targetName, state] of Object.entries(item.targets)) {
372
- const normalizedTarget = normalizeTargetName(targetName);
373
- if (!normalizedTarget) {
470
+ const normalizedTargetName = normalizeIndexTargetName(targetName);
471
+ if (!normalizedTargetName) {
374
472
  continue;
375
473
  }
376
474
  const normalizedState = normalizeTargetState(state);
377
475
  if (normalizedState) {
378
- targets[normalizedTarget] = normalizedState;
476
+ targets[normalizedTargetName] = normalizedState;
379
477
  }
380
478
  }
381
479
  }
@@ -389,7 +487,7 @@ function migrateRecordV1ToV2(item, normalizedPath) {
389
487
  const targets = {};
390
488
  const installedAt = typeof item.installedAt === "string" ? item.installedAt : "";
391
489
  if (installedAt) {
392
- targets.full = {
490
+ targets.gemini = {
393
491
  version: typeof item.cliVersion === "string" ? item.cliVersion : "",
394
492
  installedAt,
395
493
  updatedAt: typeof item.lastUpdatedAt === "string" ? item.lastUpdatedAt : installedAt,
@@ -594,14 +692,13 @@ function upsertWorkspaceTarget(index, workspaceRoot, targetName, timestamp) {
594
692
  record.targets = {};
595
693
  }
596
694
 
597
- const normalizedTarget = normalizeTargetName(targetName) || "full";
598
- const prev = normalizeTargetState(record.targets[normalizedTarget]) || {
695
+ const prev = normalizeTargetState(record.targets[targetName]) || {
599
696
  version: "",
600
697
  installedAt: "",
601
698
  updatedAt: "",
602
699
  };
603
700
 
604
- record.targets[normalizedTarget] = {
701
+ record.targets[targetName] = {
605
702
  version: pkg.version,
606
703
  installedAt: prev.installedAt || timestamp,
607
704
  updatedAt: timestamp,
@@ -698,7 +795,12 @@ function maybeWarnUpstreamGlobalConflict(command, options) {
698
795
  if (process.env.AG_KIT_SKIP_UPSTREAM_CHECK === "1") {
699
796
  return;
700
797
  }
701
- if (command !== "init" && command !== "update" && command !== "update-all") {
798
+ const shouldWarn =
799
+ command === "init"
800
+ || command === "update"
801
+ || command === "update-all"
802
+ || (command === "global" && String(options.subcommand || "").toLowerCase() === "sync");
803
+ if (!shouldWarn) {
702
804
  return;
703
805
  }
704
806
 
@@ -714,25 +816,7 @@ function maybeWarnUpstreamGlobalConflict(command, options) {
714
816
  log(options, `⚠️ 检测到全局已安装上游英文版 ${UPSTREAM_GLOBAL_PACKAGE}。`);
715
817
  log(options, "⚠️ 上游英文版与当前中文版共用 `ag-kit` 命令名,后安装者会覆盖命令入口。");
716
818
  log(options, `👉 建议执行: npm uninstall -g ${UPSTREAM_GLOBAL_PACKAGE}`);
717
- }
718
-
719
- function maybeWarnLegacyTargetAlias(options, rawTargets) {
720
- if (options.quiet) {
721
- return;
722
- }
723
- const aliases = [];
724
- for (const raw of rawTargets || []) {
725
- const key = String(raw || "").trim().toLowerCase();
726
- if (!key || key === "full" || key === "agents") {
727
- continue;
728
- }
729
- if (key === "gemini" || key === "codex") {
730
- aliases.push(key);
731
- }
732
- }
733
- if (aliases.length > 0) {
734
- log(options, `ℹ️ 检测到兼容目标参数: ${Array.from(new Set(aliases)).join(", ")},将自动归一为 full 安装流程。`);
735
- }
819
+ log(options, "ℹ️ 若你通过 bun install -g 安装,Bun 默认会阻止本包 postinstall;因此这里会在首次执行 CLI 时再次提醒。");
736
820
  }
737
821
 
738
822
  function normalizeTargets(rawTargets) {
@@ -752,13 +836,9 @@ function normalizeTargets(rawTargets) {
752
836
  if (!SUPPORTED_TARGETS.includes(target)) {
753
837
  throw new Error(`不支持的目标: ${target}(可选: ${SUPPORTED_TARGETS.join(", ")})`);
754
838
  }
755
- const normalized = normalizeTargetName(target);
756
- if (!normalized) {
757
- continue;
758
- }
759
- if (!seen.has(normalized)) {
760
- seen.add(normalized);
761
- result.push(normalized);
839
+ if (!seen.has(target)) {
840
+ seen.add(target);
841
+ result.push(target);
762
842
  }
763
843
  }
764
844
  }
@@ -766,66 +846,155 @@ function normalizeTargets(rawTargets) {
766
846
  return result;
767
847
  }
768
848
 
769
- function isManagedLegacyCodexDir(workspaceRoot) {
770
- const legacyManifest = path.join(workspaceRoot, ".codex", "manifest.json");
771
- if (!fs.existsSync(legacyManifest)) {
772
- return false;
849
+ function detectInstalledTargets(workspaceRoot) {
850
+ const targets = [];
851
+ if (fs.existsSync(path.join(workspaceRoot, ".agent"))) {
852
+ targets.push("gemini");
773
853
  }
774
- try {
775
- const parsed = JSON.parse(fs.readFileSync(legacyManifest, "utf8"));
776
- const target = typeof parsed.target === "string" ? parsed.target.toLowerCase() : "";
777
- return (target === "codex" || target === "full") && parsed.files && typeof parsed.files === "object";
778
- } catch (_err) {
779
- return false;
854
+ if (fs.existsSync(path.join(workspaceRoot, ".agents")) || fs.existsSync(path.join(workspaceRoot, ".codex"))) {
855
+ targets.push("codex");
780
856
  }
857
+ return targets;
781
858
  }
782
859
 
783
- function hasLegacyLayoutSignal(workspaceRoot) {
784
- return fs.existsSync(path.join(workspaceRoot, ".agent"))
785
- || fs.existsSync(path.join(workspaceRoot, ".gemini"))
786
- || isManagedLegacyCodexDir(workspaceRoot);
860
+ function isTargetInstalled(workspaceRoot, targetName) {
861
+ if (targetName === "gemini") {
862
+ return fs.existsSync(path.join(workspaceRoot, ".agent"));
863
+ }
864
+ if (targetName === "codex") {
865
+ return fs.existsSync(path.join(workspaceRoot, ".agents")) || fs.existsSync(path.join(workspaceRoot, ".codex"));
866
+ }
867
+ return false;
787
868
  }
788
869
 
789
- function detectInstalledTargets(workspaceRoot) {
790
- if (fs.existsSync(path.join(workspaceRoot, ".agents")) || hasLegacyLayoutSignal(workspaceRoot)) {
791
- return ["full"];
870
+ function setQuietStatusExitCode(state) {
871
+ process.exitCode = Object.prototype.hasOwnProperty.call(QUIET_STATUS_EXIT_CODES, state)
872
+ ? QUIET_STATUS_EXIT_CODES[state]
873
+ : 1;
874
+ }
875
+
876
+ function normalizeIntegrityState(result) {
877
+ if (!result || result.status === "missing") {
878
+ return "missing";
879
+ }
880
+ if (result.status === "ok") {
881
+ return "installed";
792
882
  }
793
- return [];
883
+ return "broken";
794
884
  }
795
885
 
796
- function isTargetInstalled(workspaceRoot, targetName) {
797
- const normalized = normalizeTargetName(targetName);
798
- if (normalized === "full") {
799
- return fs.existsSync(path.join(workspaceRoot, ".agents")) || hasLegacyLayoutSignal(workspaceRoot);
886
+ function evaluateWorkspaceState(workspaceRoot, options) {
887
+ const targets = detectInstalledTargets(workspaceRoot);
888
+ if (targets.length === 0) {
889
+ return {
890
+ state: "missing",
891
+ targets: [],
892
+ };
800
893
  }
801
- return false;
894
+
895
+ const targetStates = targets.map((targetName) => {
896
+ const adapter = createAdapter(targetName, workspaceRoot, {
897
+ ...options,
898
+ quiet: true,
899
+ });
900
+ const integrity = adapter.checkIntegrity();
901
+ return {
902
+ targetName,
903
+ state: normalizeIntegrityState(integrity),
904
+ integrity,
905
+ version: typeof adapter.getInstalledVersion === "function" ? adapter.getInstalledVersion() : null,
906
+ };
907
+ });
908
+
909
+ const hasIssue = targetStates.some((item) => item.state !== "installed");
910
+ return {
911
+ state: hasIssue ? "broken" : "installed",
912
+ targets: targetStates,
913
+ };
914
+ }
915
+
916
+ function evaluateGlobalState() {
917
+ const globalRoot = resolveGlobalRootDir();
918
+ const targetStates = listGlobalDestinations(globalRoot).map((destination) => {
919
+ const rootExists = fs.existsSync(destination.rootDir);
920
+ const skillsExists = fs.existsSync(destination.skillsRoot);
921
+ const skillsCount = skillsExists ? countSkillsRecursive(destination.skillsRoot) : 0;
922
+ let state = "missing";
923
+ const issues = [];
924
+
925
+ if (rootExists || skillsExists) {
926
+ if (!skillsExists) {
927
+ state = "broken";
928
+ issues.push("Skills 根目录缺失");
929
+ } else if (skillsCount === 0) {
930
+ state = "broken";
931
+ issues.push("未检测到任何 SKILL.md");
932
+ } else {
933
+ state = "installed";
934
+ }
935
+ }
936
+
937
+ return {
938
+ targetName: destination.id,
939
+ family: destination.targetName,
940
+ state,
941
+ rootDir: destination.rootDir,
942
+ skillsRoot: destination.skillsRoot,
943
+ skillsCount,
944
+ issues,
945
+ };
946
+ }).filter((item) => item.state !== "missing");
947
+
948
+ if (targetStates.length === 0) {
949
+ return {
950
+ globalRoot,
951
+ state: "missing",
952
+ targets: [],
953
+ };
954
+ }
955
+
956
+ const hasIssue = targetStates.some((item) => item.state !== "installed");
957
+ return {
958
+ globalRoot,
959
+ state: hasIssue ? "broken" : "installed",
960
+ targets: targetStates,
961
+ };
802
962
  }
803
963
 
804
964
  function createAdapter(targetName, workspaceRoot, options) {
805
- const normalized = normalizeTargetName(targetName);
806
- if (normalized === "full") {
965
+ if (targetName === "gemini") {
966
+ return new GeminiAdapter(workspaceRoot, options);
967
+ }
968
+ if (targetName === "codex") {
807
969
  return new CodexAdapter(workspaceRoot, options);
808
970
  }
809
971
  throw new Error(`未知目标: ${targetName}`);
810
972
  }
811
973
 
812
974
  async function resolveTargetsForInit(options) {
813
- maybeWarnLegacyTargetAlias(options, options.targets);
814
975
  let targets = normalizeTargets(options.targets);
815
976
 
816
977
  if (targets.length > 0) {
817
978
  return targets;
818
979
  }
980
+
981
+ if (options.nonInteractive) {
982
+ throw new Error("非交互模式下必须通过 --target 或 --targets 指定目标");
983
+ }
984
+
985
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
986
+ throw new Error("当前环境不是交互终端,请通过 --target 或 --targets 指定目标");
987
+ }
988
+
819
989
  targets = normalizeTargets(await selectTargets(options));
820
990
  if (targets.length === 0) {
821
- return ["full"];
991
+ throw new Error("必须选择至少一个目标");
822
992
  }
823
993
 
824
994
  return targets;
825
995
  }
826
996
 
827
997
  function resolveTargetsForUpdate(workspaceRoot, options) {
828
- maybeWarnLegacyTargetAlias(options, options.targets);
829
998
  const requested = normalizeTargets(options.targets);
830
999
  if (requested.length > 0) {
831
1000
  return requested;
@@ -833,50 +1002,267 @@ function resolveTargetsForUpdate(workspaceRoot, options) {
833
1002
  return detectInstalledTargets(workspaceRoot);
834
1003
  }
835
1004
 
836
- async function resolveConflictPolicies(workspaceRoot, options) {
837
- const next = { ...options };
838
- const isInteractive = !next.nonInteractive && process.stdin.isTTY && process.stdout.isTTY;
1005
+ function resolveTargetsForGlobalSync(options) {
1006
+ const requested = normalizeTargets(options.targets);
1007
+ if (requested.length > 0) {
1008
+ return requested;
1009
+ }
1010
+ // 保持 global sync 简洁:默认同步 codex + gemini;其中 gemini 会展开为 gemini-cli 与 antigravity。
1011
+ return ["codex", "gemini"];
1012
+ }
1013
+
1014
+ function resolveAgentInstallSource(options) {
1015
+ let agentDir = BUNDLED_AGENT_DIR;
1016
+ let cleanup = null;
1017
+ let sourceLabel = "bundled";
839
1018
 
840
- if (!next.agentConflictPolicy) {
841
- if (fs.existsSync(path.join(workspaceRoot, ".agent")) && isInteractive) {
842
- next.agentConflictPolicy = await selectAgentConflictPolicy();
843
- } else {
844
- next.agentConflictPolicy = "backup_replace";
1019
+ if (options.branch) {
1020
+ const remote = cloneBranchAgentDir(options.branch, {
1021
+ quiet: options.quiet,
1022
+ logger: log.bind(null, options),
1023
+ });
1024
+ agentDir = remote.agentDir;
1025
+ cleanup = remote.cleanup;
1026
+ sourceLabel = `branch:${options.branch}`;
1027
+ }
1028
+
1029
+ if (!fs.existsSync(agentDir) && !options.branch) {
1030
+ const legacyDir = path.resolve(__dirname, "../.agent");
1031
+ if (fs.existsSync(legacyDir)) {
1032
+ agentDir = legacyDir;
1033
+ sourceLabel = "bundled:legacy";
845
1034
  }
846
1035
  }
847
1036
 
848
- if (!next.geminiAgentsPolicy) {
849
- if (fs.existsSync(path.join(workspaceRoot, ".gemini", "agents")) && isInteractive) {
850
- next.geminiAgentsPolicy = await selectGeminiAgentsPolicy();
851
- } else {
852
- next.geminiAgentsPolicy = "append";
1037
+ if (!fs.existsSync(agentDir)) {
1038
+ throw new Error(`未找到模板目录: ${agentDir}`);
1039
+ }
1040
+
1041
+ return { agentDir, cleanup, sourceLabel };
1042
+ }
1043
+
1044
+ function listSkillDirectories(skillsRoot) {
1045
+ if (!fs.existsSync(skillsRoot)) {
1046
+ return [];
1047
+ }
1048
+ return fs
1049
+ .readdirSync(skillsRoot, { withFileTypes: true })
1050
+ .filter((entry) => entry.isDirectory())
1051
+ .map((entry) => entry.name)
1052
+ .filter((name) => fs.existsSync(path.join(skillsRoot, name, "SKILL.md")));
1053
+ }
1054
+
1055
+ function backupSkillDirectory(targetName, skillName, sourceDir, timestamp, options) {
1056
+ const backupRoot = resolveGlobalBackupRoot(timestamp);
1057
+ const backupDir = path.join(backupRoot, targetName, skillName);
1058
+ fs.mkdirSync(path.dirname(backupDir), { recursive: true });
1059
+ copyDirRecursive(sourceDir, backupDir);
1060
+ log(options, `📦 已备份 ${targetName} 全局 Skill: ${skillName} -> ${backupDir}`);
1061
+ }
1062
+
1063
+ function syncSkillDirectory(destination, srcDir, destDir, timestamp, options) {
1064
+ const exists = fs.existsSync(destDir);
1065
+ if (exists) {
1066
+ if (areDirectoriesEqual(srcDir, destDir)) {
1067
+ log(options, `⏭️ 全局 Skill 已最新,无需同步: ${destination.id}/${path.basename(destDir)}`);
1068
+ return { skipped: 1, synced: 0, backedUp: 0 };
853
1069
  }
854
1070
  }
855
1071
 
856
- return next;
1072
+ if (options.dryRun) {
1073
+ log(options, `[dry-run] 将同步全局 Skill: ${destination.id}/${path.basename(destDir)}`);
1074
+ return { skipped: 0, synced: 0, backedUp: exists ? 1 : 0 };
1075
+ }
1076
+
1077
+ let backedUp = 0;
1078
+ if (exists) {
1079
+ backupSkillDirectory(destination.id, path.basename(destDir), destDir, timestamp, options);
1080
+ backedUp = 1;
1081
+ }
1082
+
1083
+ const logger = options.quiet ? (() => {}) : log.bind(null, options);
1084
+ AtomicWriter.atomicCopyDir(srcDir, destDir, { logger });
1085
+ log(options, `✅ 已同步全局 Skill: ${destination.id}/${path.basename(destDir)}`);
1086
+
1087
+ return { skipped: 0, synced: 1, backedUp };
1088
+ }
1089
+
1090
+ function syncGlobalSkillsFromRoot(targetName, skillsRoot, timestamp, options) {
1091
+ const destinations = getGlobalDestinations(targetName);
1092
+ const skillNames = listSkillDirectories(skillsRoot);
1093
+ if (skillNames.length === 0) {
1094
+ throw new Error(`未检测到可同步的 Skills: ${skillsRoot}`);
1095
+ }
1096
+
1097
+ if (options.dryRun) {
1098
+ for (const destination of destinations) {
1099
+ log(options, `[dry-run] 将同步 ${skillNames.length} 个全局 Skills -> ${destination.skillsRoot}`);
1100
+ }
1101
+ }
1102
+
1103
+ let synced = 0;
1104
+ let skipped = 0;
1105
+ let backedUp = 0;
1106
+ const destinationResults = [];
1107
+
1108
+ for (const destination of destinations) {
1109
+ let destinationSynced = 0;
1110
+ let destinationSkipped = 0;
1111
+ let destinationBackedUp = 0;
1112
+
1113
+ for (const skillName of skillNames) {
1114
+ const srcDir = path.join(skillsRoot, skillName);
1115
+ const destDir = path.join(destination.skillsRoot, skillName);
1116
+ const result = syncSkillDirectory(destination, srcDir, destDir, timestamp, options);
1117
+ synced += result.synced;
1118
+ skipped += result.skipped;
1119
+ backedUp += result.backedUp;
1120
+ destinationSynced += result.synced;
1121
+ destinationSkipped += result.skipped;
1122
+ destinationBackedUp += result.backedUp;
1123
+ }
1124
+
1125
+ destinationResults.push({
1126
+ targetName: destination.id,
1127
+ family: destination.targetName,
1128
+ destRoot: destination.skillsRoot,
1129
+ total: skillNames.length,
1130
+ synced: destinationSynced,
1131
+ skipped: destinationSkipped,
1132
+ backedUp: destinationBackedUp,
1133
+ });
1134
+ }
1135
+
1136
+ return {
1137
+ total: skillNames.length * destinations.length,
1138
+ skillsPerDestination: skillNames.length,
1139
+ synced,
1140
+ skipped,
1141
+ backedUp,
1142
+ destinations: destinationResults,
1143
+ };
1144
+ }
1145
+
1146
+ function applyGlobalSync(targetName, agentDir, timestamp, options) {
1147
+ if (targetName === "codex") {
1148
+ const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "ag-kit-global-codex-"));
1149
+ const mockRoot = path.join(tempRoot, "source");
1150
+ const mockAgent = path.join(mockRoot, ".agents");
1151
+ const outputDir = path.join(tempRoot, "out");
1152
+
1153
+ try {
1154
+ copyDirRecursive(agentDir, mockAgent);
1155
+ CodexBuilder.build(mockRoot, outputDir);
1156
+ const skillsRoot = path.join(outputDir, "skills");
1157
+ return syncGlobalSkillsFromRoot(targetName, skillsRoot, timestamp, options);
1158
+ } finally {
1159
+ fs.rmSync(tempRoot, { recursive: true, force: true });
1160
+ }
1161
+ }
1162
+
1163
+ if (targetName === "gemini") {
1164
+ const skillsRoot = path.join(agentDir, "skills");
1165
+ return syncGlobalSkillsFromRoot(targetName, skillsRoot, timestamp, options);
1166
+ }
1167
+
1168
+ throw new Error(`未知目标: ${targetName}`);
1169
+ }
1170
+
1171
+ async function commandGlobalSync(options) {
1172
+ const targets = await resolveTargetsForGlobalSync(options);
1173
+ const { agentDir, cleanup, sourceLabel } = resolveAgentInstallSource(options);
1174
+ const timestamp = nowISO().replace(/[:.]/g, "-");
1175
+
1176
+ try {
1177
+ log(options, `🌍 全局同步源: ${sourceLabel}`);
1178
+ for (const target of targets) {
1179
+ log(options, `📦 正在同步全局目标 [${target}] ...`);
1180
+ const result = applyGlobalSync(target, agentDir, timestamp, options);
1181
+ if (!options.dryRun) {
1182
+ log(options, `📊 全局同步完成 [${target}]:总计 ${result.total},新增/覆盖 ${result.synced},跳过 ${result.skipped},备份 ${result.backedUp}`);
1183
+ for (const item of result.destinations) {
1184
+ log(options, ` - ${item.targetName}: ${item.destRoot}(每目标 ${item.total} 个 Skills)`);
1185
+ }
1186
+ }
1187
+ }
1188
+ } finally {
1189
+ if (cleanup) cleanup();
1190
+ }
1191
+ }
1192
+
1193
+ function commandGlobalStatus(options) {
1194
+ const summary = evaluateGlobalState();
1195
+
1196
+ if (summary.state === "missing") {
1197
+ if (options.quiet) {
1198
+ console.log("missing");
1199
+ }
1200
+ if (!options.quiet) {
1201
+ console.log("❌ 未检测到全局安装的 Skills");
1202
+ console.log(` 全局根目录: ${summary.globalRoot}`);
1203
+ }
1204
+ setQuietStatusExitCode("missing");
1205
+ return;
1206
+ }
1207
+
1208
+ if (options.quiet) {
1209
+ console.log(summary.state);
1210
+ setQuietStatusExitCode(summary.state);
1211
+ return;
1212
+ }
1213
+
1214
+ console.log(summary.state === "installed" ? "✅ 全局 Skills 状态正常" : "⚠️ 全局 Skills 存在问题");
1215
+ console.log(` 全局根目录: ${summary.globalRoot}`);
1216
+ console.log(` 总体状态: ${summary.state}`);
1217
+ console.log(` Targets: ${summary.targets.map((item) => item.targetName).join(", ")}`);
1218
+
1219
+ for (const item of summary.targets) {
1220
+ console.log(`\n[${item.targetName}:global]`);
1221
+ console.log(` 家族: ${item.family}`);
1222
+ console.log(` 状态: ${item.state}`);
1223
+ console.log(` 路径: ${item.skillsRoot}`);
1224
+ if (item.state === "installed") {
1225
+ console.log(` Skills: ${item.skillsCount}`);
1226
+ continue;
1227
+ }
1228
+ for (const issue of item.issues) {
1229
+ console.log(` Issue: ${issue}`);
1230
+ }
1231
+ }
1232
+
1233
+ setQuietStatusExitCode(summary.state);
1234
+ }
1235
+
1236
+ function commandGlobal(options) {
1237
+ const subcommand = String(options.subcommand || "status").toLowerCase();
1238
+ if (subcommand === "sync") {
1239
+ return commandGlobalSync(options);
1240
+ }
1241
+ if (subcommand === "status") {
1242
+ return commandGlobalStatus(options);
1243
+ }
1244
+ throw new Error(`未知 global 子命令: ${subcommand}`);
857
1245
  }
858
1246
 
859
1247
  async function commandInit(options) {
860
1248
  const workspaceRoot = resolveWorkspaceRoot(options.path);
861
1249
  const targets = await resolveTargetsForInit(options);
862
- const runOptions = await resolveConflictPolicies(workspaceRoot, options);
863
1250
 
864
1251
  for (const target of targets) {
865
- const adapter = createAdapter(target, workspaceRoot, runOptions);
1252
+ const adapter = createAdapter(target, workspaceRoot, options);
866
1253
  log(options, `📦 正在初始化目标 [${target}] ...`);
867
1254
  adapter.install(BUNDLED_AGENT_DIR);
868
- registerWorkspaceTarget(workspaceRoot, target, runOptions);
1255
+ registerWorkspaceTarget(workspaceRoot, target, options);
869
1256
  }
870
1257
 
871
1258
  if (targets.length > 0) {
872
- log(options, `✅ 初始化完成 (Mode: ${targets.join(", ")})`);
1259
+ log(options, `✅ 初始化完成 (Targets: ${targets.join(", ")})`);
873
1260
  }
874
1261
  }
875
1262
 
876
1263
  async function commandUpdate(options) {
877
1264
  const workspaceRoot = resolveWorkspaceRoot(options.path);
878
1265
  const targets = resolveTargetsForUpdate(workspaceRoot, options);
879
- const runOptions = await resolveConflictPolicies(workspaceRoot, options);
880
1266
 
881
1267
  if (targets.length === 0) {
882
1268
  throw new Error("此目录未检测到 Antigravity Kit 安装,无法更新。请先执行 init。");
@@ -894,11 +1280,11 @@ async function commandUpdate(options) {
894
1280
  continue;
895
1281
  }
896
1282
 
897
- const targetOptions = { ...runOptions, force: true };
898
- const adapter = createAdapter(target, workspaceRoot, targetOptions);
1283
+ const runOptions = { ...options, force: true };
1284
+ const adapter = createAdapter(target, workspaceRoot, runOptions);
899
1285
  log(options, `📦 更新 [${target}] ...`);
900
1286
  adapter.update(BUNDLED_AGENT_DIR);
901
- registerWorkspaceTarget(workspaceRoot, target, targetOptions);
1287
+ registerWorkspaceTarget(workspaceRoot, target, runOptions);
902
1288
  updatedAny = true;
903
1289
  }
904
1290
 
@@ -912,13 +1298,12 @@ function mergeUpdatedTargets(record, workspacePath, targetNames, timestamp) {
912
1298
  const next = normalizeWorkspaceRecordV2(record || {}, normalizedPath);
913
1299
 
914
1300
  for (const target of targetNames) {
915
- const normalizedTarget = normalizeTargetName(target) || "full";
916
- const prev = normalizeTargetState(next.targets[normalizedTarget]) || {
1301
+ const prev = normalizeTargetState(next.targets[target]) || {
917
1302
  version: "",
918
1303
  installedAt: "",
919
1304
  updatedAt: "",
920
1305
  };
921
- next.targets[normalizedTarget] = {
1306
+ next.targets[target] = {
922
1307
  version: pkg.version,
923
1308
  installedAt: prev.installedAt || timestamp,
924
1309
  updatedAt: timestamp,
@@ -933,7 +1318,6 @@ async function commandUpdateAll(options) {
933
1318
  throw new Error("update-all 不支持 --path,请直接执行 ag-kit update-all");
934
1319
  }
935
1320
 
936
- maybeWarnLegacyTargetAlias(options, options.targets);
937
1321
  const requestedTargets = normalizeTargets(options.targets);
938
1322
  const { indexPath, index } = readWorkspaceIndex();
939
1323
  const records = index.workspaces || [];
@@ -1016,8 +1400,6 @@ async function commandUpdateAll(options) {
1016
1400
  force: true,
1017
1401
  path: workspacePath,
1018
1402
  silentIndexLog: true,
1019
- agentConflictPolicy: "backup_replace",
1020
- geminiAgentsPolicy: "append",
1021
1403
  };
1022
1404
  const adapter = createAdapter(target, workspacePath, runOptions);
1023
1405
  adapter.update(BUNDLED_AGENT_DIR);
@@ -1311,61 +1693,76 @@ function countSkillsRecursive(dir) {
1311
1693
 
1312
1694
  function commandStatus(options) {
1313
1695
  const workspaceRoot = resolveWorkspaceRoot(options.path);
1314
- const installedTargets = detectInstalledTargets(workspaceRoot);
1696
+ const summary = evaluateWorkspaceState(workspaceRoot, options);
1315
1697
 
1316
- if (installedTargets.length === 0) {
1698
+ if (summary.state === "missing") {
1699
+ if (options.quiet) {
1700
+ console.log("missing");
1701
+ }
1317
1702
  if (!options.quiet) {
1318
1703
  console.log("❌ 未检测到 Antigravity Kit 安装");
1319
1704
  console.log(` 目标目录: ${workspaceRoot}`);
1320
1705
  }
1321
- process.exitCode = 1;
1706
+ setQuietStatusExitCode("missing");
1322
1707
  return;
1323
1708
  }
1324
1709
 
1325
1710
  if (options.quiet) {
1326
- console.log("installed");
1711
+ console.log(summary.state);
1712
+ setQuietStatusExitCode(summary.state);
1327
1713
  return;
1328
1714
  }
1329
1715
 
1330
- console.log("✅ Antigravity Kit 已安装");
1716
+ console.log(summary.state === "installed" ? "✅ Antigravity Kit 状态正常" : "⚠️ Antigravity Kit 存在问题");
1331
1717
  console.log(` CLI 版本: ${pkg.version}`);
1332
1718
  console.log(` 工作区: ${workspaceRoot}`);
1333
- console.log(` Mode: ${installedTargets.join(", ")}`);
1334
-
1335
- const managedDir = path.join(workspaceRoot, ".agents");
1336
- const agentProjectionDir = path.join(workspaceRoot, ".agent");
1337
- const geminiProjectionDir = path.join(workspaceRoot, ".gemini");
1338
- const legacyDir = path.join(workspaceRoot, ".codex");
1339
- const hasManaged = fs.existsSync(managedDir);
1340
- const hasLegacy = fs.existsSync(legacyDir);
1341
- const isManagedLegacy = isManagedLegacyCodexDir(workspaceRoot);
1342
-
1343
- const skillsCount = countSkillsRecursive(path.join(managedDir, "skills"));
1344
- const agentsCount = countFilesIfExists(path.join(managedDir, "agents"), (name) => name.endsWith(".md"));
1345
- const workflowsCount = countFilesIfExists(path.join(managedDir, "workflows"), (name) => name.endsWith(".md"));
1346
- const hasManifest = fs.existsSync(path.join(managedDir, "manifest.json"));
1347
-
1348
- console.log("\n[full]");
1349
- console.log(` Canonical(.agents): ${hasManaged ? "yes" : "no"}`);
1350
- if (hasManaged) {
1351
- console.log(` Skills: ${skillsCount}`);
1352
- console.log(` Agents: ${agentsCount}`);
1353
- console.log(` Workflows: ${workflowsCount}`);
1354
- console.log(` Manifest: ${hasManifest ? "yes" : "no"}`);
1719
+ console.log(` 总体状态: ${summary.state}`);
1720
+ console.log(` Targets: ${summary.targets.map((item) => item.targetName).join(", ")}`);
1721
+
1722
+ const geminiState = summary.targets.find((item) => item.targetName === "gemini");
1723
+ if (geminiState) {
1724
+ const agentDir = path.join(workspaceRoot, ".agent");
1725
+ const agentsCount = countFilesIfExists(path.join(agentDir, "agents"), (name) => name.endsWith(".md"));
1726
+ const workflowsCount = countFilesIfExists(path.join(agentDir, "workflows"), (name) => name.endsWith(".md"));
1727
+ const skillsCount = countSkillsRecursive(path.join(agentDir, "skills"));
1728
+ console.log("\n[gemini]");
1729
+ console.log(` 状态: ${geminiState.state}`);
1730
+ console.log(` 路径: ${agentDir}`);
1731
+ if (geminiState.state === "installed") {
1732
+ console.log(` Agents: ${agentsCount}`);
1733
+ console.log(` Skills: ${skillsCount}`);
1734
+ console.log(` Workflows: ${workflowsCount}`);
1735
+ } else {
1736
+ for (const issue of geminiState.integrity.issues || []) {
1737
+ console.log(` Issue: ${issue}`);
1738
+ }
1739
+ }
1355
1740
  }
1356
1741
 
1357
- console.log("\n[projections]");
1358
- console.log(` .agent: ${fs.existsSync(agentProjectionDir) ? "yes" : "no"}`);
1359
- console.log(` .gemini: ${fs.existsSync(geminiProjectionDir) ? "yes" : "no"}`);
1360
-
1361
- if (hasLegacy) {
1362
- console.log("\n[legacy]");
1363
- if (isManagedLegacy) {
1364
- console.log(" .codex: 托管 legacy(建议执行 ag-kit update 迁移清理)");
1365
- } else {
1366
- console.log(" .codex: 非托管目录(已保留,不会自动删除)");
1742
+ const codexState = summary.targets.find((item) => item.targetName === "codex");
1743
+ if (codexState) {
1744
+ const managedDir = path.join(workspaceRoot, ".agents");
1745
+ const legacyDir = path.join(workspaceRoot, ".codex");
1746
+ const activeDir = fs.existsSync(managedDir) ? managedDir : legacyDir;
1747
+ const skillsCount = countSkillsRecursive(path.join(activeDir, "skills"));
1748
+ const hasManifest = fs.existsSync(path.join(activeDir, "manifest.json"));
1749
+ const legacyDetected = fs.existsSync(legacyDir);
1750
+ console.log("\n[codex]");
1751
+ console.log(` 状态: ${codexState.state}`);
1752
+ console.log(` 路径: ${activeDir}`);
1753
+ console.log(` Skills: ${skillsCount}`);
1754
+ console.log(` Manifest: ${hasManifest ? "yes" : "no"}`);
1755
+ if (legacyDetected) {
1756
+ console.log(" Legacy: 检测到 .codex(建议执行 ag-kit update 迁移清理)");
1757
+ }
1758
+ if (codexState.state !== "installed") {
1759
+ for (const issue of codexState.integrity.issues || []) {
1760
+ console.log(` Issue: ${issue}`);
1761
+ }
1367
1762
  }
1368
1763
  }
1764
+
1765
+ setQuietStatusExitCode(summary.state);
1369
1766
  }
1370
1767
 
1371
1768
  async function main() {
@@ -1407,6 +1804,11 @@ async function main() {
1407
1804
  return;
1408
1805
  }
1409
1806
 
1807
+ if (command === "global") {
1808
+ await commandGlobal(options);
1809
+ return;
1810
+ }
1811
+
1410
1812
  if (command === "exclude") {
1411
1813
  commandExclude(options);
1412
1814
  return;