gsd-antigravity-kit 1.32.0 → 2.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 (163) hide show
  1. package/.agent/skills/gsd/SKILL.md +152 -123
  2. package/.agent/skills/gsd/VERSION +1 -0
  3. package/.agent/skills/gsd/assets/templates/user-profile.md +8 -8
  4. package/.agent/skills/gsd/bin/gsd-tools.cjs +81 -3
  5. package/.agent/skills/gsd/bin/help-manifest.json +24 -1
  6. package/.agent/skills/gsd/bin/hooks/gsd-check-update.js +15 -5
  7. package/.agent/skills/gsd/bin/hooks/gsd-context-monitor.js +1 -1
  8. package/.agent/skills/gsd/bin/hooks/gsd-phase-boundary.sh +27 -0
  9. package/.agent/skills/gsd/bin/hooks/gsd-prompt-guard.js +2 -1
  10. package/.agent/skills/gsd/bin/hooks/gsd-read-guard.js +1 -1
  11. package/.agent/skills/gsd/bin/hooks/gsd-session-state.sh +33 -0
  12. package/.agent/skills/gsd/bin/hooks/gsd-statusline.js +5 -5
  13. package/.agent/skills/gsd/bin/hooks/gsd-validate-commit.sh +47 -0
  14. package/.agent/skills/gsd/bin/hooks/gsd-workflow-guard.js +1 -1
  15. package/.agent/skills/gsd/bin/lib/config.cjs +31 -10
  16. package/.agent/skills/gsd/bin/lib/core.cjs +48 -13
  17. package/.agent/skills/gsd/bin/lib/frontmatter.cjs +34 -2
  18. package/.agent/skills/gsd/bin/lib/intel.cjs +660 -0
  19. package/.agent/skills/gsd/bin/lib/learnings.cjs +378 -0
  20. package/.agent/skills/gsd/bin/lib/milestone.cjs +13 -4
  21. package/.agent/skills/gsd/bin/lib/model-profiles.cjs +17 -17
  22. package/.agent/skills/gsd/bin/lib/profile-output.cjs +31 -31
  23. package/.agent/skills/gsd/bin/lib/security.cjs +119 -0
  24. package/.agent/skills/gsd/bin/lib/verify.cjs +15 -15
  25. package/.agent/skills/gsd/migration_report.md +7 -0
  26. package/.agent/skills/gsd/references/agents/gsd-code-fixer.md +516 -0
  27. package/.agent/skills/gsd/references/agents/gsd-code-reviewer.md +355 -0
  28. package/.agent/skills/gsd/references/agents/gsd-debugger.md +10 -1
  29. package/.agent/skills/gsd/references/agents/gsd-executor.md +3 -0
  30. package/.agent/skills/gsd/references/agents/gsd-intel-updater.md +314 -0
  31. package/.agent/skills/gsd/references/agents/gsd-phase-researcher.md +3 -0
  32. package/.agent/skills/gsd/references/agents/gsd-plan-checker.md +16 -4
  33. package/.agent/skills/gsd/references/agents/gsd-planner.md +7 -0
  34. package/.agent/skills/gsd/references/agents/gsd-user-profiler.md +5 -5
  35. package/.agent/skills/gsd/references/agents/gsd-verifier.md +55 -1
  36. package/.agent/skills/gsd/references/agents/profiles/dev.md +21 -0
  37. package/.agent/skills/gsd/references/agents/profiles/research.md +22 -0
  38. package/.agent/skills/gsd/references/agents/profiles/review.md +22 -0
  39. package/.agent/skills/gsd/references/commands/{gsd-add-todo.md → atomic/add-todo.md} +5 -4
  40. package/.agent/skills/gsd/references/commands/{gsd-check-todos.md → atomic/check-todos.md} +5 -4
  41. package/.agent/skills/gsd/references/commands/{gsd-cleanup.md → atomic/cleanup.md} +4 -3
  42. package/.agent/skills/gsd/references/commands/{gsd-do.md → atomic/do.md} +4 -3
  43. package/.agent/skills/gsd/references/commands/{gsd-help.md → atomic/help.md} +4 -3
  44. package/.agent/skills/gsd/references/commands/{gsd-join-discord.md → atomic/join-discord.md} +21 -19
  45. package/.agent/skills/gsd/references/commands/{gsd-note.md → atomic/note.md} +4 -3
  46. package/.agent/skills/gsd/references/commands/{gsd-session-report.md → atomic/session-report.md} +4 -3
  47. package/.agent/skills/gsd/references/commands/{gsd-ship.md → atomic/ship.md} +4 -3
  48. package/.agent/skills/gsd/references/commands/{gsd-stats.md → atomic/stats.md} +4 -3
  49. package/.agent/skills/gsd/references/commands/{gsd-thread.md → atomic/thread.md} +7 -6
  50. package/.agent/skills/gsd/references/commands/atomic/undo.md +36 -0
  51. package/.agent/skills/gsd/references/commands/{gsd-add-backlog.md → milestone/add-backlog.md} +8 -7
  52. package/.agent/skills/gsd/references/commands/{gsd-audit-milestone.md → milestone/audit-milestone.md} +4 -3
  53. package/.agent/skills/gsd/references/commands/{gsd-complete-milestone.md → milestone/complete-milestone.md} +6 -4
  54. package/.agent/skills/gsd/references/commands/{gsd-milestone-summary.md → milestone/milestone-summary.md} +5 -3
  55. package/.agent/skills/gsd/references/commands/{gsd-new-milestone.md → milestone/new-milestone.md} +4 -3
  56. package/.agent/skills/gsd/references/commands/{gsd-plan-milestone-gaps.md → milestone/plan-milestone-gaps.md} +4 -3
  57. package/.agent/skills/gsd/references/commands/{gsd-plant-seed.md → milestone/plant-seed.md} +4 -3
  58. package/.agent/skills/gsd/references/commands/{gsd-review-backlog.md → milestone/review-backlog.md} +6 -5
  59. package/.agent/skills/gsd/references/commands/misc/audit-fix.md +35 -0
  60. package/.agent/skills/gsd/references/commands/{gsd-audit-uat.md → misc/audit-uat.md} +4 -3
  61. package/.agent/skills/gsd/references/commands/{gsd-next.md → misc/next.md} +6 -3
  62. package/.agent/skills/gsd/references/commands/{gsd-progress.md → misc/progress.md} +4 -3
  63. package/.agent/skills/gsd/references/commands/{gsd-verify-work.md → misc/verify-work.md} +4 -3
  64. package/.agent/skills/gsd/references/commands/{gsd-add-phase.md → phase/add-phase.md} +5 -4
  65. package/.agent/skills/gsd/references/commands/{gsd-add-tests.md → phase/add-tests.md} +8 -3
  66. package/.agent/skills/gsd/references/commands/{gsd-discuss-phase.md → phase/discuss-phase.md} +5 -4
  67. package/.agent/skills/gsd/references/commands/{gsd-execute-phase.md → phase/execute-phase.md} +4 -3
  68. package/.agent/skills/gsd/references/commands/{gsd-insert-phase.md → phase/insert-phase.md} +5 -4
  69. package/.agent/skills/gsd/references/commands/{gsd-list-phase-assumptions.md → phase/list-phase-assumptions.md} +4 -3
  70. package/.agent/skills/gsd/references/commands/{gsd-plan-phase.md → phase/plan-phase.md} +4 -3
  71. package/.agent/skills/gsd/references/commands/{gsd-remove-phase.md → phase/remove-phase.md} +5 -4
  72. package/.agent/skills/gsd/references/commands/{gsd-research-phase.md → phase/research-phase.md} +7 -6
  73. package/.agent/skills/gsd/references/commands/{gsd-secure-phase.md → phase/secure-phase.md} +4 -3
  74. package/.agent/skills/gsd/references/commands/{gsd-ui-phase.md → phase/ui-phase.md} +4 -3
  75. package/.agent/skills/gsd/references/commands/{gsd-ui-review.md → phase/ui-review.md} +4 -3
  76. package/.agent/skills/gsd/references/commands/{gsd-validate-phase.md → phase/validate-phase.md} +4 -3
  77. package/.agent/skills/gsd/references/commands/{gsd-workstreams.md → phase/workstreams.md} +71 -70
  78. package/.agent/skills/gsd/references/commands/{gsd-analyze-dependencies.md → project/analyze-dependencies.md} +5 -4
  79. package/.agent/skills/gsd/references/commands/project/explore.md +29 -0
  80. package/.agent/skills/gsd/references/commands/project/import.md +38 -0
  81. package/.agent/skills/gsd/references/commands/project/intel.md +181 -0
  82. package/.agent/skills/gsd/references/commands/{gsd-list-workspaces.md → project/list-workspaces.md} +4 -3
  83. package/.agent/skills/gsd/references/commands/{gsd-map-codebase.md → project/map-codebase.md} +4 -3
  84. package/.agent/skills/gsd/references/commands/{gsd-new-project.md → project/new-project.md} +4 -3
  85. package/.agent/skills/gsd/references/commands/{gsd-new-workspace.md → project/new-workspace.md} +4 -3
  86. package/.agent/skills/gsd/references/commands/{gsd-remove-workspace.md → project/remove-workspace.md} +4 -3
  87. package/.agent/skills/gsd/references/commands/project/scan.md +28 -0
  88. package/.agent/skills/gsd/references/commands/{gsd-autonomous.md → system/autonomous.md} +4 -3
  89. package/.agent/skills/gsd/references/commands/system/code-review-fix.md +54 -0
  90. package/.agent/skills/gsd/references/commands/system/code-review.md +57 -0
  91. package/.agent/skills/gsd/references/commands/{gsd-debug.md → system/debug.md} +7 -6
  92. package/.agent/skills/gsd/references/commands/{gsd-docs-update.md → system/docs-update.md} +4 -3
  93. package/.agent/skills/gsd/references/commands/{gsd-fast.md → system/fast.md} +4 -3
  94. package/.agent/skills/gsd/references/commands/{gsd-forensics.md → system/forensics.md} +5 -3
  95. package/.agent/skills/gsd/references/commands/{gsd-health.md → system/health.md} +5 -4
  96. package/.agent/skills/gsd/references/commands/{gsd-manager.md → system/manager.md} +4 -3
  97. package/.agent/skills/gsd/references/commands/{gsd-pause-work.md → system/pause-work.md} +4 -3
  98. package/.agent/skills/gsd/references/commands/{gsd-pr-branch.md → system/pr-branch.md} +4 -3
  99. package/.agent/skills/gsd/references/commands/{gsd-profile-user.md → system/profile-user.md} +4 -3
  100. package/.agent/skills/gsd/references/commands/{gsd-quick.md → system/quick.md} +4 -3
  101. package/.agent/skills/gsd/references/commands/{gsd-reapply-patches.md → system/reapply-patches.md} +25 -7
  102. package/.agent/skills/gsd/references/commands/{gsd-resume-work.md → system/resume-work.md} +4 -3
  103. package/.agent/skills/gsd/references/commands/{gsd-review.md → system/review.md} +4 -3
  104. package/.agent/skills/gsd/references/commands/system/set-profile.md +14 -0
  105. package/.agent/skills/gsd/references/commands/{gsd-settings.md → system/settings.md} +4 -3
  106. package/.agent/skills/gsd/references/commands/{gsd-update.md → system/update.md} +4 -3
  107. package/.agent/skills/gsd/references/docs/agent-contracts.md +79 -0
  108. package/.agent/skills/gsd/references/docs/common-bug-patterns.md +114 -0
  109. package/.agent/skills/gsd/references/docs/context-budget.md +49 -0
  110. package/.agent/skills/gsd/references/docs/domain-probes.md +125 -0
  111. package/.agent/skills/gsd/references/docs/few-shot-examples/plan-checker.md +73 -0
  112. package/.agent/skills/gsd/references/docs/few-shot-examples/verifier.md +109 -0
  113. package/.agent/skills/gsd/references/docs/gate-prompts.md +100 -0
  114. package/.agent/skills/gsd/references/docs/gates.md +70 -0
  115. package/.agent/skills/gsd/references/docs/model-profile-resolution.md +2 -0
  116. package/.agent/skills/gsd/references/docs/model-profiles.md +20 -14
  117. package/.agent/skills/gsd/references/docs/planning-config.md +216 -1
  118. package/.agent/skills/gsd/references/docs/revision-loop.md +97 -0
  119. package/.agent/skills/gsd/references/docs/thinking-models-debug.md +44 -0
  120. package/.agent/skills/gsd/references/docs/thinking-models-execution.md +50 -0
  121. package/.agent/skills/gsd/references/docs/thinking-models-planning.md +62 -0
  122. package/.agent/skills/gsd/references/docs/thinking-models-research.md +50 -0
  123. package/.agent/skills/gsd/references/docs/thinking-models-verification.md +55 -0
  124. package/.agent/skills/gsd/references/docs/thinking-partner.md +96 -0
  125. package/.agent/skills/gsd/references/docs/universal-anti-patterns.md +58 -0
  126. package/.agent/skills/gsd/references/docs/user-profiling.md +10 -10
  127. package/.agent/skills/gsd/references/docs/verification-overrides.md +227 -0
  128. package/.agent/skills/gsd/references/docs/workstream-flag.md +2 -2
  129. package/.agent/skills/gsd/references/mapping.md +11 -21
  130. package/.agent/skills/gsd/references/workflows/analyze-dependencies.md +3 -3
  131. package/.agent/skills/gsd/references/workflows/audit-fix.md +157 -0
  132. package/.agent/skills/gsd/references/workflows/autonomous.md +22 -1
  133. package/.agent/skills/gsd/references/workflows/code-review-fix.md +497 -0
  134. package/.agent/skills/gsd/references/workflows/code-review.md +515 -0
  135. package/.agent/skills/gsd/references/workflows/discuss-phase-power.md +3 -3
  136. package/.agent/skills/gsd/references/workflows/discuss-phase.md +20 -0
  137. package/.agent/skills/gsd/references/workflows/execute-phase.md +103 -0
  138. package/.agent/skills/gsd/references/workflows/explore.md +139 -0
  139. package/.agent/skills/gsd/references/workflows/import.md +274 -0
  140. package/.agent/skills/gsd/references/workflows/inbox.md +384 -0
  141. package/.agent/skills/gsd/references/workflows/manager.md +5 -5
  142. package/.agent/skills/gsd/references/workflows/new-milestone.md +1 -1
  143. package/.agent/skills/gsd/references/workflows/next.md +56 -0
  144. package/.agent/skills/gsd/references/workflows/plan-phase.md +48 -1
  145. package/.agent/skills/gsd/references/workflows/quick.md +96 -2
  146. package/.agent/skills/gsd/references/workflows/review.md +23 -3
  147. package/.agent/skills/gsd/references/workflows/scan.md +102 -0
  148. package/.agent/skills/gsd/references/workflows/settings.md +1 -1
  149. package/.agent/skills/gsd/references/workflows/ui-review.md +2 -2
  150. package/.agent/skills/gsd/references/workflows/undo.md +312 -0
  151. package/.agent/skills/gsd/references/workflows/update.md +5 -5
  152. package/.agent/skills/gsd-converter/SKILL.md +67 -59
  153. package/.agent/skills/gsd-converter/assets/migration-manifest.json +74 -0
  154. package/.agent/skills/gsd-converter/references/mapping.md +6 -16
  155. package/.agent/skills/gsd-converter/scripts/convert.py +419 -80
  156. package/.agent/skills/gsd-converter/scripts/regression_test.py +33 -0
  157. package/.agent/skills/selectpaste-update/SKILL.md +46 -0
  158. package/.agent/skills/selectpaste-update/scripts/sync-commands.py +317 -0
  159. package/README.md +4 -2
  160. package/bin/install.js +116 -116
  161. package/package.json +1 -1
  162. package/.agent/skills/gsd/references/commands/gsd-set-profile.md +0 -12
  163. /package/.agent/skills/gsd/references/commands/{gsd-tools.md → system/gsd-tools.md} +0 -0
@@ -7,6 +7,15 @@ import subprocess
7
7
  import json
8
8
  from datetime import datetime
9
9
 
10
+ def load_manifest():
11
+ script_dir = os.path.dirname(os.path.abspath(__file__))
12
+ manifest_path = os.path.join(script_dir, '..', 'assets', 'migration-manifest.json')
13
+ if not os.path.exists(manifest_path):
14
+ print(f" ❌ Manifest not found at {manifest_path}")
15
+ sys.exit(1)
16
+ with open(manifest_path, 'r', encoding='utf-8') as f:
17
+ return json.load(f)
18
+
10
19
  def setup_args():
11
20
  # Force UTF-8 for Windows terminals
12
21
  if sys.platform == 'win32':
@@ -112,18 +121,48 @@ def discover_commands(source_gsd_tools_path):
112
121
 
113
122
  return commands
114
123
 
115
- def migrate_files(source_base, target_base):
124
+ def get_command_category(cmd_name):
125
+ """Categorize GSD commands based on their primary function."""
126
+ atomic = ['add-todo', 'check-todos', 'note', 'ship', 'cleanup', 'undo', 'help', 'do', 'stats', 'thread', 'session-report', 'join-discord']
127
+ phase = ['plan-phase', 'execute-phase', 'research-phase', 'validate-phase', 'discuss-phase', 'remove-phase', 'insert-phase', 'add-phase', 'list-phase-assumptions', 'secure-phase', 'ui-phase', 'ui-review', 'add-tests', 'workstreams']
128
+ milestone = ['new-milestone', 'complete-milestone', 'audit-milestone', 'milestone-summary', 'plan-milestone-gaps', 'review-backlog', 'add-backlog', 'plant-seed']
129
+ project = ['new-project', 'new-workspace', 'list-workspaces', 'remove-workspace', 'map-codebase', 'scan', 'intel', 'analyze-dependencies', 'explore', 'import']
130
+ system = ['gsd-tools', 'health', 'settings', 'profile-user', 'set-profile', 'update', 'pause-work', 'resume-work', 'reapply-patches', 'debug', 'forensics', 'manager', 'autonomous', 'fast', 'quick', 'code-review', 'code-review-fix', 'review', 'docs-update', 'pr-branch']
131
+
132
+ if cmd_name in atomic: return 'atomic'
133
+ if cmd_name in phase: return 'phase'
134
+ if cmd_name in milestone: return 'milestone'
135
+ if cmd_name in project: return 'project'
136
+ if cmd_name in system: return 'system'
137
+ return 'misc'
138
+
139
+ def inject_metadata(file_path, version):
140
+ """Inject GSD version and migration date into markdown frontmatter."""
141
+ if not file_path.endswith('.md'): return
142
+ try:
143
+ with open(file_path, 'r', encoding='utf-8') as f:
144
+ content = f.read()
145
+
146
+ # Parse frontmatter
147
+ match = re.match(r'^(---\s*\n)(.*?\n)(---)', content, re.DOTALL)
148
+ if match:
149
+ start, mid, end = match.groups()
150
+ # Check if already injected
151
+ if 'gsd-source-version' in mid: return
152
+
153
+ new_meta = f"gsd-source-version: {version}\nmigration-date: {datetime.now().strftime('%Y-%m-%d')}\n"
154
+ new_content = start + mid + new_meta + end + content[match.end():]
155
+
156
+ with open(file_path, 'w', encoding='utf-8') as f:
157
+ f.write(new_content)
158
+ except Exception as e:
159
+ print(f" ⚠️ Failed to inject metadata to {file_path}: {e}")
160
+
161
+ def migrate_files(source_base, target_base, manifest):
116
162
  print(f"🚀 Starting migration from {source_base} to {target_base}...")
117
163
 
118
- # Define mappings (source_rel, target_rel)
119
- mappings = [
120
- ('get-shit-done/references', 'references/docs'),
121
- ('get-shit-done/workflows', 'references/workflows'),
122
- ('agents', 'references/agents'),
123
- ('get-shit-done/templates', 'assets/templates'),
124
- ('get-shit-done/bin', 'bin'),
125
- ('hooks', 'bin/hooks')
126
- ]
164
+ # Define mappings (source_rel, target_rel) from manifest
165
+ mappings = [(m['source'], m['target']) for m in manifest['mappings']]
127
166
 
128
167
  for src_rel, tgt_rel in mappings:
129
168
  src_path = os.path.join(source_base, src_rel)
@@ -136,7 +175,17 @@ def migrate_files(source_base, target_base):
136
175
 
137
176
  for item in os.listdir(src_path):
138
177
  s = os.path.join(src_path, item)
139
- d = os.path.join(tgt_path, item)
178
+
179
+ # Special handling for command categorization
180
+ if src_rel == 'commands/gsd/':
181
+ cmd_name = item[:-3] if item.endswith('.md') else item
182
+ category = get_command_category(cmd_name)
183
+ cat_path = os.path.join(tgt_path, category)
184
+ os.makedirs(cat_path, exist_ok=True)
185
+ d = os.path.join(cat_path, item)
186
+ else:
187
+ d = os.path.join(tgt_path, item)
188
+
140
189
  if os.path.isdir(s):
141
190
  shutil.copytree(s, d, dirs_exist_ok=True)
142
191
  else:
@@ -148,17 +197,16 @@ def migrate_files(source_base, target_base):
148
197
  skills_src = os.path.join(source_base, 'skills')
149
198
  commands_tgt = os.path.join(target_base, 'references/commands')
150
199
  if os.path.exists(skills_src):
151
- print(f" 📁 Migrating modular skills -> references/commands")
152
- os.makedirs(commands_tgt, exist_ok=True)
200
+ print(f" 📁 Migrating modular skills -> references/commands/modular")
201
+ modular_tgt = os.path.join(commands_tgt, 'modular')
202
+ os.makedirs(modular_tgt, exist_ok=True)
153
203
  for skill_dir in os.listdir(skills_src):
154
204
  s_full = os.path.join(skills_src, skill_dir)
155
205
  if os.path.isdir(s_full):
156
206
  skill_md = os.path.join(s_full, 'SKILL.md')
157
207
  if os.path.exists(skill_md):
158
- # Flatten into references/commands/gsd-name.md
159
- # Clean up the name (remove gsd- prefix if present for redundancy, or keep it)
160
208
  target_name = skill_dir + '.md'
161
- shutil.copy2(skill_md, os.path.join(commands_tgt, target_name))
209
+ shutil.copy2(skill_md, os.path.join(modular_tgt, target_name))
162
210
 
163
211
  # Migrate internal documentation (mapping.md)
164
212
  script_dir = os.path.dirname(os.path.abspath(__file__))
@@ -169,34 +217,38 @@ def migrate_files(source_base, target_base):
169
217
  os.makedirs(os.path.dirname(mapping_tgt), exist_ok=True)
170
218
  shutil.copy2(mapping_src, mapping_tgt)
171
219
 
172
- def refactor_content(target_base):
220
+ def refactor_content(target_base, version, manifest):
173
221
  print("🔧 Refactoring file contents and paths...")
174
222
 
175
- replacements = [
223
+ # Load rebranding rules from manifest
224
+ rebranding_rules = manifest.get('rebranding', {}).get('replacements', [])
225
+ replacements = []
226
+ for rule in rebranding_rules:
227
+ replacements.append((re.compile(rule['pattern']), rule['replacement']))
228
+
229
+ # Standard GSD replacements (preserved)
230
+ standard_replacements = [
176
231
  # Skill-relative internal references
177
- (r'@.*?\.claude/commands/gsd/', '@references/commands/'),
178
- (r'@.*?\.claude/get-shit-done/references/', '@references/docs/'),
179
- (r'@.*?\.claude/get-shit-done/workflows/', '@references/workflows/'),
180
- (r'@.*?\.claude/get-shit-done/templates/', '@assets/templates/'),
181
- (r'@.*?\.claude/agents/', '@references/agents/'),
182
- (r'@.*?\.claude/hooks/', '@bin/hooks/'),
232
+ (re.compile(r'@.*?\.claude/commands/gsd/'), '@references/commands/'),
233
+ (re.compile(r'@.*?\.claude/get-shit-done/references/'), '@references/docs/'),
234
+ (re.compile(r'@.*?\.claude/get-shit-done/workflows/'), '@references/workflows/'),
235
+ (re.compile(r'@.*?\.claude/get-shit-done/contexts/'), '@references/agents/profiles/'),
236
+ (re.compile(r'@.*?\.claude/get-shit-done/templates/'), '@assets/templates/'),
237
+ (re.compile(r'@.*?\.claude/agents/'), '@references/agents/'),
238
+ (re.compile(r'@.*?\.claude/hooks/'), '@bin/hooks/'),
183
239
 
184
240
  # Local filesystem paths
185
- (r'\.?/?.*?\.claude/agents/', 'references/agents/'),
186
- (r'\.?/?.*?\.claude/get-shit-done/templates/', 'assets/templates/'),
187
- (r'\.?/?.*?\.claude/get-shit-done/workflows/', 'references/workflows/'),
188
- (r'\.?/?.*?\.claude/get-shit-done/bin/', '.agent/skills/gsd/bin/'),
189
- (r'\.?/?.*?\.claude/hooks/', '.agent/skills/gsd/bin/hooks/'),
190
-
191
- # Rebranding
192
- (r'\bClaude Code\b', 'Antigravity'),
193
- (r'\bClaude\b', 'Antigravity'),
194
- (r'\bclaude\b', 'antigravity'),
195
- (r'\bCLAUDE\b', 'ANTIGRAVITY'),
196
- (r'generate-antigravity-profile', 'generate-antigravity-profile'), # Ensure double rebrands don't break
197
- (r'generate-antigravity-md', 'generate-antigravity-md'),
241
+ (re.compile(r'\.?/?.*?\.claude/agents/'), 'references/agents/'),
242
+ (re.compile(r'\.?/?.*?\.claude/get-shit-done/templates/'), 'assets/templates/'),
243
+ (re.compile(r'\.?/?.*?\.claude/get-shit-done/workflows/'), 'references/workflows/'),
244
+ (re.compile(r'\.?/?.*?\.claude/get-shit-done/contexts/'), 'references/agents/profiles/'),
245
+ (re.compile(r'\.?/?.*?\.claude/get-shit-done/bin/'), '.agent/skills/gsd/bin/'),
246
+ (re.compile(r'\.?/?.*?\.claude/hooks/'), '.agent/skills/gsd/bin/hooks/'),
198
247
  ]
199
248
 
249
+ # Rebranding aliases to prevent double rebrands breaking things
250
+ # These are handled by the manifest now, but we keep some specific ones if needed
251
+
200
252
  exact_replacements = [
201
253
  ("@~/.claude/commands/gsd/", "@references/commands/"),
202
254
  ("@$HOME/.claude/commands/gsd/", "@references/commands/"),
@@ -204,6 +256,8 @@ def refactor_content(target_base):
204
256
  ("@$HOME/.claude/get-shit-done/references/", "@references/docs/"),
205
257
  ("@~/.claude/get-shit-done/workflows/", "@references/workflows/"),
206
258
  ("@$HOME/.claude/get-shit-done/workflows/", "@references/workflows/"),
259
+ ("@~/.claude/get-shit-done/contexts/", "@references/agents/profiles/"),
260
+ ("@$HOME/.claude/get-shit-done/contexts/", "@references/agents/profiles/"),
207
261
  ("@~/.claude/get-shit-done/templates/", "@assets/templates/"),
208
262
  ("@$HOME/.claude/get-shit-done/templates/", "@assets/templates/"),
209
263
  ("@~/.claude/agents/", "@references/agents/"),
@@ -218,6 +272,7 @@ def refactor_content(target_base):
218
272
  ("path.join(homeDir, '.claude', 'get-shit-done'", "path.join(homeDir, '.gemini', 'antigravity', 'skills', 'gsd'")
219
273
  ]
220
274
 
275
+ # Pass 1: Content processing
221
276
  for root, dirs, files in os.walk(target_base):
222
277
  for file in files:
223
278
  file_path = os.path.join(root, file)
@@ -231,8 +286,25 @@ def refactor_content(target_base):
231
286
  for exact, repl in exact_replacements:
232
287
  new_content = new_content.replace(exact, repl)
233
288
 
289
+ for pattern, replacement in standard_replacements:
290
+ new_content = pattern.sub(replacement, new_content)
291
+
234
292
  for pattern, replacement in replacements:
235
- new_content = re.sub(pattern, replacement, new_content)
293
+ new_content = pattern.sub(replacement, new_content)
294
+
295
+ # Pass 2: Categorized path resolution for commands
296
+ # We need to find @references/commands/cmd.md and fix it
297
+ def fix_cmd_path(match):
298
+ p = match.group(1)
299
+ cmd_filename = os.path.basename(p)
300
+ cmd_name = cmd_filename[:-3] if cmd_filename.endswith('.md') else cmd_filename
301
+ category = get_command_category(cmd_name)
302
+ # Special case for modular or injected
303
+ if 'modular' in p: category = 'modular'
304
+ if cmd_name == 'gsd-tools': category = 'system'
305
+ return f"@references/commands/{category}/{cmd_filename}"
306
+
307
+ new_content = re.sub(r'@references/commands/([^/\s]+?\.md)', fix_cmd_path, new_content)
236
308
 
237
309
  if new_content != content:
238
310
  with open(file_path, 'w', encoding='utf-8') as f:
@@ -240,6 +312,13 @@ def refactor_content(target_base):
240
312
  except Exception as e:
241
313
  print(f" ⚠️ Error processing {file_path}: {e}")
242
314
 
315
+ # Metadata Injection
316
+ for root, dirs, files in os.walk(target_base):
317
+ for file in files:
318
+ file_path = os.path.join(root, file)
319
+ if file.endswith('.md') and 'commands' in root:
320
+ inject_metadata(file_path, version)
321
+
243
322
  # Cleanup .bak files
244
323
  for root, dirs, files in os.walk(target_base):
245
324
  for file in files:
@@ -320,23 +399,34 @@ def scan_commands(target_base):
320
399
  commands_dir = os.path.join(target_base, 'references', 'commands')
321
400
  commands = []
322
401
  if os.path.exists(commands_dir):
323
- for f in sorted(os.listdir(commands_dir)):
324
- if f.endswith('.md'):
325
- cmd_name = f[:-3] # remove .md
326
- file_path = os.path.join(commands_dir, f)
327
- description = ""
328
- try:
329
- with open(file_path, 'r', encoding='utf-8') as cf:
330
- text = cf.read()
331
- # Parse frontmatter description
332
- match = re.search(r'---[\s\S]*?description:\s*["\']?(.*?)["\']?\n[\s\S]*?---', text)
333
- if match:
334
- description = match.group(1).strip()
335
- except Exception as e:
336
- print(f" ⚠️ Error parsing {f}: {e}")
337
-
338
- commands.append({'name': cmd_name, 'description': description})
339
- return commands
402
+ for root, dirs, files in os.walk(commands_dir):
403
+ for f in sorted(files):
404
+ if f.endswith('.md'):
405
+ cmd_name = f[:-3] # remove .md
406
+ file_path = os.path.join(root, f)
407
+ description = ""
408
+ try:
409
+ with open(file_path, 'r', encoding='utf-8') as cf:
410
+ text = cf.read()
411
+ # Parse frontmatter description
412
+ match = re.search(r'---[\s\S]*?description:\s*["\']?(.*?)["\']?\n[\s\S]*?---', text)
413
+ if match:
414
+ description = match.group(1).strip()
415
+ except Exception as e:
416
+ print(f" ⚠️ Error parsing {f}: {e}")
417
+
418
+ commands.append({'name': cmd_name, 'description': description})
419
+
420
+ # Sort into categories for SKILL.md
421
+ categorized = {}
422
+ for cmd in commands:
423
+ cat = get_command_category(cmd['name'])
424
+ # If it's in a different folder than its category, we should still respect it
425
+ # but for GSD commands we use the categorizer
426
+ if cat not in categorized: categorized[cat] = []
427
+ categorized[cat].append(cmd)
428
+
429
+ return categorized
340
430
 
341
431
  def create_skill_md(target_base, skill_name, version):
342
432
  skill_md_path = os.path.join(target_base, 'SKILL.md')
@@ -345,16 +435,22 @@ def create_skill_md(target_base, skill_name, version):
345
435
  script_dir = os.path.dirname(os.path.abspath(__file__))
346
436
  template_path = os.path.join(script_dir, '..', 'assets', 'gsd_skill_template.md')
347
437
 
348
- commands = scan_commands(target_base)
438
+ categorized_commands = scan_commands(target_base)
439
+
440
+ # Flatten for triggers
441
+ all_commands = []
442
+ for cat in categorized_commands:
443
+ all_commands.extend(categorized_commands[cat])
349
444
 
350
445
  # Format for triggers: - `gsd:command`
351
- command_triggers_str = "\n".join([f"- `gsd:{cmd['name']}`" for cmd in commands])
446
+ command_triggers_str = "\n".join([f"- `gsd:{cmd['name']}`" for cmd in sorted(all_commands, key=lambda x: x['name'])])
352
447
 
353
- # Format for detailed list: bold command name with link, then description
354
- commands_list_str = "\n".join([
355
- f"- **[`gsd:{cmd['name']}`](references/commands/{cmd['name']}.md)**: {cmd['description']}"
356
- for cmd in commands
357
- ])
448
+ # Format for detailed list: categorized bold command name with link
449
+ commands_list_str = ""
450
+ for cat in sorted(categorized_commands.keys()):
451
+ commands_list_str += f"\n### {cat.capitalize()} Commands\n"
452
+ for cmd in categorized_commands[cat]:
453
+ commands_list_str += f"- **[`gsd:{cmd['name']}`](references/commands/{cat}/{cmd['name']}.md)**: {cmd['description']}\n"
358
454
 
359
455
  if not os.path.exists(template_path):
360
456
  print(f" ⚠️ Template not found at {template_path}. Using fallback.")
@@ -373,32 +469,251 @@ Template missing.
373
469
  title_name = skill_name.upper()
374
470
  date_str = datetime.now().strftime('%Y-%m-%d')
375
471
 
376
- try:
377
- content = template_content.format(
378
- skill_name=skill_name,
379
- version=version,
380
- title_name=title_name,
381
- date=date_str,
382
- command_triggers=command_triggers_str,
383
- commands_list=commands_list_str
384
- )
385
- except KeyError as e:
386
- print(f" ⚠️ Error formatting template: {e}")
387
- content = template_content
472
+ # Use .replace() instead of .format() to avoid issues with literal braces in the template
473
+ content = template_content.replace('{skill_name}', skill_name) \
474
+ .replace('{version}', version) \
475
+ .replace('{title_name}', title_name) \
476
+ .replace('{date}', date_str) \
477
+ .replace('{command_triggers}', command_triggers_str) \
478
+ .replace('{commands_list}', commands_list_str)
388
479
 
389
480
  with open(skill_md_path, 'w', encoding='utf-8') as f:
390
481
  f.write(content)
391
482
  print(" ✅ Created SKILL.md from template with updated commands")
392
483
 
484
+ def run_regression_tests(target_base):
485
+ """Run Phase 2 regression tests on the generated skill."""
486
+ print("🧪 Running regression tests...")
487
+ script_dir = os.path.dirname(os.path.abspath(__file__))
488
+ test_script = os.path.join(script_dir, 'regression_test.py')
489
+
490
+ if not os.path.exists(test_script):
491
+ # Create it if it doesn't exist (self-bootstrapping for this turn)
492
+ with open(test_script, 'w', encoding='utf-8') as f:
493
+ f.write("""import os, re, sys
494
+ def test_skill(base):
495
+ print(f" Checking {base}...")
496
+ errors = []
497
+ # 1. Check categorized paths
498
+ cmd_dir = os.path.join(base, 'references', 'commands')
499
+ if not os.path.exists(cmd_dir): return ["Commands dir missing"]
500
+
501
+ for root, dirs, files in os.walk(cmd_dir):
502
+ for f in files:
503
+ if f.endswith('.md'):
504
+ path = os.path.join(root, f)
505
+ with open(path, 'r', encoding='utf-8') as file:
506
+ content = file.read()
507
+ # Check metadata
508
+ if 'gsd-source-version' not in content:
509
+ errors.append(f"Missing metadata in {f}")
510
+ # Check internal inclusions
511
+ inclusions = re.findall(r"@references/commands/([^/]+?\\\\.md)", content)
512
+ if inclusions:
513
+ # Find where they should be
514
+ cmd_name = inclusions[0][:-3]
515
+ category = get_command_category(cmd_name)
516
+ errors.append(f"Broken inclusive path in {f}: {inclusions[0]}. Should be {category}/{inclusions[0]}")
517
+ return errors
518
+
519
+ if __name__ == '__main__':
520
+ target = sys.argv[1] if len(sys.argv) > 1 else '.'
521
+ errs = test_skill(target)
522
+ if errs:
523
+ for e in errs: print(f" ❌ {e}")
524
+ sys.exit(1)
525
+ print(" ✅ Regression tests passed.")
526
+ """)
527
+
528
+ try:
529
+ result = subprocess.run(
530
+ [sys.executable, test_script, target_base],
531
+ check=True,
532
+ capture_output=True,
533
+ text=True,
534
+ encoding='utf-8'
535
+ )
536
+ print(result.stdout)
537
+ except subprocess.CalledProcessError as e:
538
+ print(f" ❌ Regression tests failed!")
539
+ print(e.stdout)
540
+ print(e.stderr)
541
+ return False
542
+ return True
543
+
544
+ def discover_source_structure(source_base):
545
+ """Scan .claude for directories and identify unmapped ones."""
546
+ print("🔍 Discovering source structure...")
547
+ mappings = [
548
+ 'commands/gsd/',
549
+ 'get-shit-done/references/',
550
+ 'get-shit-done/workflows/',
551
+ 'get-shit-done/contexts/',
552
+ 'agents/',
553
+ 'get-shit-done/templates/',
554
+ 'get-shit-done/bin/',
555
+ 'hooks/',
556
+ 'skills/'
557
+ ]
558
+
559
+ # Directories we expect to see as parents but aren't mapped directly
560
+ allowed_parents = ['', 'commands', 'get-shit-done']
561
+
562
+ unmapped = []
563
+ for root, dirs, files in os.walk(source_base):
564
+ rel_root = os.path.relpath(root, source_base).replace('\\', '/')
565
+ if rel_root == '.': rel_root = ''
566
+
567
+ if rel_root not in allowed_parents and not any(rel_root.startswith(m.strip('/')) for m in mappings):
568
+ # This dir itself might be unmapped
569
+ if rel_root + '/' not in mappings:
570
+ unmapped.append(rel_root)
571
+
572
+ # Check subdirs of current root
573
+ for d in dirs:
574
+ full_rel = os.path.join(rel_root, d).replace('\\', '/') + '/'
575
+ if full_rel not in mappings and os.path.dirname(full_rel.strip('/')) in allowed_parents:
576
+ unmapped.append(full_rel)
577
+
578
+ # Deduplicate and filter out parents
579
+ unmapped = sorted(list(set([u for u in unmapped if u.strip('/') not in allowed_parents])))
580
+
581
+ if unmapped:
582
+ print(f" ⚠️ Found unmapped directories in source: {', '.join(unmapped)}")
583
+ else:
584
+ print(" ✅ All recognized source directories are mapped.")
585
+ return unmapped
586
+
587
+ def audit_spec(manifest):
588
+ """Verify code mappings against internal mapping.md documentation."""
589
+ print("📋 Auditing code against spec (mapping.md)...")
590
+ script_dir = os.path.dirname(os.path.abspath(__file__))
591
+ mapping_md_path = os.path.abspath(os.path.join(script_dir, '..', 'references', 'mapping.md'))
592
+
593
+ if not os.path.exists(mapping_md_path):
594
+ print(" ⚠️ mapping.md not found, skipping spec audit.")
595
+ return True
596
+
597
+ try:
598
+ with open(mapping_md_path, 'r', encoding='utf-8') as f:
599
+ content = f.read()
600
+
601
+ # Simple extraction of | .claude/path | ... |
602
+ spec_paths = re.findall(r'\|\s*`\.claude/(.*?)`\s*\|', content)
603
+ code_paths = [m['source'] for m in manifest['mappings']]
604
+
605
+ mismatches = []
606
+ for sp in spec_paths:
607
+ if sp not in code_paths:
608
+ mismatches.append(f"Spec path '{sp}' missing in code")
609
+ for cp in code_paths:
610
+ if cp not in spec_paths:
611
+ mismatches.append(f"Code path '{cp}' missing in spec")
612
+
613
+ if mismatches:
614
+ print(" ❌ Spec Audit Failed:")
615
+ for m in mismatches:
616
+ print(f" - {m}")
617
+ return False
618
+
619
+ print(" ✅ Code mappings are in sync with mapping.md.")
620
+ return True
621
+ except Exception as e:
622
+ print(f" ⚠️ Error during spec audit: {e}")
623
+ return False
624
+
625
+ def verify_migration(target_base):
626
+ """Pre-flight check for the migrated skill."""
627
+ print("🛡️ Verifying migrated skill integrity...")
628
+ checks = [
629
+ (os.path.join(target_base, 'bin', 'gsd-tools.cjs'), "GSD Tools CLI"),
630
+ (os.path.join(target_base, 'bin', 'help-manifest.json'), "Help Manifest"),
631
+ (os.path.join(target_base, 'references', 'commands'), "Commands Directory"),
632
+ (os.path.join(target_base, 'references', 'agents', 'profiles'), "Context Profiles"),
633
+ (os.path.join(target_base, 'references', 'agents'), "Agents Directory"),
634
+ (os.path.join(target_base, 'SKILL.md'), "Skill Specification")
635
+ ]
636
+
637
+ failures = []
638
+ for path, label in checks:
639
+ if not os.path.exists(path):
640
+ failures.append(f"Missing {label}: {path}")
641
+
642
+ # Check if commands dir is empty
643
+ cmd_dir = os.path.join(target_base, 'references', 'commands')
644
+ if os.path.exists(cmd_dir) and not os.listdir(cmd_dir):
645
+ failures.append("Commands directory is empty - migration likely failed to copy core prompts.")
646
+
647
+ if failures:
648
+ print(" ❌ Verification Failed:")
649
+ for f in failures:
650
+ print(f" - {f}")
651
+ return False
652
+
653
+ print(" ✅ Skill integrity verified.")
654
+ return True
655
+
656
+ def sync_mapping_docs(target_base, manifest):
657
+ """Regenerate mapping.md from manifest to ensure documentation is always in sync."""
658
+ print("📝 Syncing mapping.md documentation from manifest...")
659
+
660
+ docs_to_sync = [
661
+ os.path.join(target_base, 'references', 'mapping.md')
662
+ ]
663
+
664
+ # Also sync the converter's own reference if it exists
665
+ script_dir = os.path.dirname(os.path.abspath(__file__))
666
+ internal_mapping = os.path.abspath(os.path.join(script_dir, '..', 'references', 'mapping.md'))
667
+ if os.path.exists(internal_mapping):
668
+ docs_to_sync.append(internal_mapping)
669
+
670
+ content = [
671
+ "# Path Mapping Reference",
672
+ "",
673
+ "When converting from a standard GSD installation to an Antigravity Skill, paths are refactored to ensure the skill is self-contained and portable.",
674
+ "",
675
+ "## Directory Mapping",
676
+ "",
677
+ "| Source GSD Path | Target Skill Path | Purpose |",
678
+ "|-----------------|-------------------|---------|"
679
+ ]
680
+
681
+ for m in manifest['mappings']:
682
+ content.append(f"| `.claude/{m['source']}` | `{m['target']}` | {m['purpose']} |")
683
+
684
+ content.extend([
685
+ "",
686
+ "## Project Context",
687
+ "References to `@.planning/` are **preserved**, as these refer to the active project's local planning directory, not the skill's own resources.",
688
+ "",
689
+ "---",
690
+ f"*Generated by gsd-converter on {datetime.now().strftime('%Y-%m-%d')}*"
691
+ ])
692
+
693
+ markdown = "\n".join(content)
694
+
695
+ for path in docs_to_sync:
696
+ os.makedirs(os.path.dirname(path), exist_ok=True)
697
+ with open(path, 'w', encoding='utf-8') as f:
698
+ f.write(markdown)
699
+ print(f" ✅ {os.path.basename(os.path.dirname(os.path.dirname(path)))} mapping.md updated.")
700
+
393
701
  def main():
394
702
  args = setup_args()
703
+ manifest = load_manifest()
395
704
 
396
705
  # Enforce 'gsd' as the skill name
397
706
  skill_name = 'gsd'
398
707
  target_base = os.path.abspath(os.path.join(args.path, skill_name))
399
708
  source_base = args.source
400
709
 
401
- print(f"🧹 Cleaning up existing skill folder: {target_base}")
710
+ # 1. Audit Spec
711
+ audit_spec(manifest)
712
+
713
+ # 2. Discover Structure
714
+ unmapped_dirs = discover_source_structure(source_base)
715
+
716
+ print(f"\n🧹 Cleaning up existing skill folder: {target_base}")
402
717
  if os.path.exists(target_base):
403
718
  # Retry logic for Windows directory locking issues
404
719
  import time
@@ -424,9 +739,10 @@ def main():
424
739
  os.makedirs(target_base, exist_ok=True)
425
740
 
426
741
  # 3. Perform migration and refactoring
427
- migrate_files(source_base, target_base)
742
+ migrate_files(source_base, target_base, manifest)
428
743
 
429
- refactor_content(target_base)
744
+ refactor_content(target_base, new_version, manifest)
745
+ sync_mapping_docs(target_base, manifest)
430
746
  optimize_gsd_tools(target_base)
431
747
 
432
748
  # 4. Inject Dynamic Help Manifest
@@ -449,9 +765,12 @@ def main():
449
765
 
450
766
  # 5. Inject custom assets
451
767
  script_dir = os.path.dirname(os.path.abspath(__file__))
452
- custom_assets = [
453
- ('gsd-tools.md', 'references/commands/gsd-tools.md'),
454
- ]
768
+
769
+ # Write VERSION file to skill root
770
+ with open(os.path.join(target_base, 'VERSION'), 'w', encoding='utf-8') as f:
771
+ f.write(new_version)
772
+
773
+ custom_assets = [(a['name'], a['target_rel']) for a in manifest.get('injected_assets', [])]
455
774
  for asset_name, target_rel in custom_assets:
456
775
  asset_path = os.path.join(script_dir, '..', 'assets', asset_name)
457
776
  target_path = os.path.join(target_base, target_rel)
@@ -468,6 +787,26 @@ def main():
468
787
 
469
788
  create_skill_md(target_base, skill_name, new_version)
470
789
 
790
+ # 6. Final Verification
791
+ verify_migration(target_base)
792
+
793
+ # 7. Regression Testing
794
+ run_regression_tests(target_base)
795
+
796
+ # 8. Generate Report
797
+ report_path = os.path.join(target_base, 'migration_report.md')
798
+ with open(report_path, 'w', encoding='utf-8') as f:
799
+ f.write(f"# GSD Migration Report\n\n")
800
+ f.write(f"- **Timestamp**: {datetime.now().isoformat()}\n")
801
+ f.write(f"- **Version**: {old_version} -> {new_version}\n")
802
+ f.write(f"- **Skill Name**: {skill_name}\n")
803
+ if unmapped_dirs:
804
+ f.write(f"\n### ⚠️ Unmapped Source Directories\n")
805
+ for d in unmapped_dirs:
806
+ f.write(f"- {d}\n")
807
+ else:
808
+ f.write(f"\n✅ All recognized source directories were successfully mapped and migrated.\n")
809
+
471
810
  print(f"\n{'='*40}")
472
811
  print(f"✨ Dynamic Skill '{skill_name}' is ready at {target_base}")
473
812
  print(f"📊 GSD Version: {old_version} -> {new_version}\n")
@@ -0,0 +1,33 @@
1
+ import os, re, sys
2
+ def test_skill(base):
3
+ print(f" Checking {base}...")
4
+ errors = []
5
+ # 1. Check categorized paths
6
+ cmd_dir = os.path.join(base, 'references', 'commands')
7
+ if not os.path.exists(cmd_dir): return ["Commands dir missing"]
8
+
9
+ for root, dirs, files in os.walk(cmd_dir):
10
+ for f in files:
11
+ if f.endswith('.md'):
12
+ path = os.path.join(root, f)
13
+ with open(path, 'r', encoding='utf-8') as file:
14
+ content = file.read()
15
+ # Check metadata
16
+ if 'gsd-source-version' not in content:
17
+ errors.append(f"Missing metadata in {f}")
18
+ # Check internal inclusions
19
+ inclusions = re.findall(r"@references/commands/([^/]+?\\.md)", content)
20
+ if inclusions:
21
+ # Find where they should be
22
+ cmd_name = inclusions[0][:-3]
23
+ category = get_command_category(cmd_name)
24
+ errors.append(f"Broken inclusive path in {f}: {inclusions[0]}. Should be {category}/{inclusions[0]}")
25
+ return errors
26
+
27
+ if __name__ == '__main__':
28
+ target = sys.argv[1] if len(sys.argv) > 1 else '.'
29
+ errs = test_skill(target)
30
+ if errs:
31
+ for e in errs: print(f" ❌ {e}")
32
+ sys.exit(1)
33
+ print(" ✅ Regression tests passed.")