gsd-antigravity-kit 1.32.1 → 2.0.1

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.
@@ -1,6 +1,6 @@
1
1
  # GSD Migration Report
2
2
 
3
- - **Timestamp**: 2026-04-08T07:01:26.026612
3
+ - **Timestamp**: 2026-04-08T07:18:24.858917
4
4
  - **Version**: 1.34.2 -> 1.34.2
5
5
  - **Skill Name**: gsd
6
6
 
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
4
  [![Antigravity Compatible](https://img.shields.io/badge/Antigravity-Compatible-purple.svg?logo=google&logoColor=white)](https://github.com/google-deepmind/antigravity)
5
5
  [![NPM Version](https://img.shields.io/npm/v/gsd-antigravity-kit.svg?logo=npm)](https://www.npmjs.com/package/gsd-antigravity-kit)
6
- [![Release Version](https://img.shields.io/badge/Release-v1.32.1-blue?style=flat-square)](https://github.com/dturkuler/GSD-Antigravity/releases/latest)
6
+ [![Release Version](https://img.shields.io/badge/Release-v2.0.0-blue?style=flat-square)](https://github.com/dturkuler/GSD-Antigravity/releases/latest)
7
7
  [![GSD Version](https://img.shields.io/badge/gsd-v1.34.2-orange?style=flat-square)](https://github.com/glittercowboy/get-shit-done)
8
8
 
9
9
  **GSD-Antigravity Kit** is the official bootstrapping and management utility for the [Get Shit Done (GSD)](https://github.com/glittercowboy/get-shit-done) protocol within the Antigravity AI framework. It serves as a high-performance **Installer** and **Skill Manager** that provision, optimizes, and maintains GSD skills in your AG environment.
@@ -104,3 +104,4 @@ The core logic, philosophy, and original script engine were created by **[glitte
104
104
 
105
105
 
106
106
 
107
+
package/bin/install.js ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const readline = require('readline');
6
+ const { execSync } = require('child_process');
7
+
8
+ const rl = readline.createInterface({
9
+ input: process.stdin,
10
+ output: process.stdout
11
+ });
12
+
13
+ const ask = (query) => new Promise((resolve) => rl.question(query, (ans) => resolve(ans.toLowerCase().trim())));
14
+
15
+ async function install() {
16
+ const targetDir = process.cwd();
17
+ const sourceAgentDir = path.join(__dirname, '..', '.agent');
18
+ const skillsSourceDir = path.join(sourceAgentDir, 'skills');
19
+
20
+ // Skills to check/install
21
+ const skillNames = ['gsd', 'gsd-converter'];
22
+ const targetSkillsDir = path.join(targetDir, '.agent', 'skills');
23
+
24
+ console.log('\n🌌 GSD-Antigravity Skill System Installer\n');
25
+
26
+ try {
27
+ // 1. Check for existing skills
28
+ const existing = [];
29
+ for (const name of skillNames) {
30
+ if (fs.existsSync(path.join(targetSkillsDir, name))) {
31
+ existing.push(name);
32
+ }
33
+ }
34
+
35
+ if (existing.length > 0) {
36
+ console.log(`⚠️ Detected existing skills in .agent/skills/: ${existing.join(', ')}`);
37
+ const confirmRemove = await ask(`Do you want to REMOVE existing skills and perform a fresh install? (y/n): `);
38
+ if (confirmRemove === 'y') {
39
+ for (const name of existing) {
40
+ const p = path.join(targetSkillsDir, name);
41
+ console.log(` 🗑️ Removing ${name}...`);
42
+ fs.rmSync(p, { recursive: true, force: true });
43
+ }
44
+ } else {
45
+ console.log(' ⏩ Skipping removal. New files will be merged/overwritten.');
46
+ }
47
+ }
48
+
49
+ // 2. Interactive Installation Selection
50
+ const installGsd = await ask(`Install GSD skill? (y/n) [default: y]: `);
51
+ const installConverter = await ask(`Install GSD-Converter skill? (y/n) [default: y]: `);
52
+
53
+ const selection = {
54
+ 'gsd': installGsd !== 'n',
55
+ 'gsd-converter': installConverter !== 'n'
56
+ };
57
+
58
+ // 3. Perform Installation
59
+ if (!fs.existsSync(targetSkillsDir)) {
60
+ fs.mkdirSync(targetSkillsDir, { recursive: true });
61
+ }
62
+
63
+ // Also copy rules if they exist
64
+ const sourceRulesDir = path.join(sourceAgentDir, 'rules');
65
+ const targetRulesDir = path.join(targetDir, '.agent', 'rules');
66
+ if (fs.existsSync(sourceRulesDir)) {
67
+ copyFolderSync(sourceRulesDir, targetRulesDir);
68
+ }
69
+
70
+ let installedCount = 0;
71
+ for (const [name, shouldInstall] of Object.entries(selection)) {
72
+ if (shouldInstall) {
73
+ const src = path.join(skillsSourceDir, name);
74
+ const tgt = path.join(targetSkillsDir, name);
75
+ if (fs.existsSync(src)) {
76
+ console.log(`📦 Installing ${name}...`);
77
+ copyFolderSync(src, tgt);
78
+ installedCount++;
79
+ }
80
+ }
81
+ }
82
+
83
+ if (installedCount > 0) {
84
+ console.log('\n✅ Installation completed successfully.');
85
+ if (selection['gsd-converter']) {
86
+ console.log('\n✨ To initialize the GSD engine, run:');
87
+ console.log(' py .agent/skills/gsd-converter/scripts/convert.py gsd\n');
88
+ }
89
+ } else {
90
+ console.log('\nℹ️ No skills were selected for installation.');
91
+ }
92
+
93
+ } catch (err) {
94
+ console.error('\n❌ Installation failed:', err.message);
95
+ } finally {
96
+ rl.close();
97
+ }
98
+ }
99
+
100
+ function copyFolderSync(from, to) {
101
+ if (!fs.existsSync(to)) {
102
+ fs.mkdirSync(to, { recursive: true });
103
+ }
104
+ fs.readdirSync(from).forEach(element => {
105
+ const srcPath = path.join(from, element);
106
+ const tgtPath = path.join(to, element);
107
+ const stat = fs.lstatSync(srcPath);
108
+ if (stat.isFile()) {
109
+ fs.copyFileSync(srcPath, tgtPath);
110
+ } else if (stat.isDirectory()) {
111
+ copyFolderSync(srcPath, tgtPath);
112
+ }
113
+ });
114
+ }
115
+
116
+ install();
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "gsd-antigravity-kit",
3
- "version": "1.32.1",
3
+ "version": "2.0.1",
4
4
  "description": "Installer for GSD-Antigravity skills",
5
5
  "main": "index.js",
6
6
  "files": [
7
7
  "bin/",
8
- ".agent/"
8
+ ".agent/rules/",
9
+ ".agent/skills/gsd/",
10
+ ".agent/skills/gsd-converter/"
9
11
  ],
10
12
  "bin": {
11
13
  "gsd-antigravity-kit": "bin/install.js"
@@ -1,162 +0,0 @@
1
- ---
2
- name: release-manager
3
- description: Orchestrate the transition from "ready" to "released" for GSD-Antigravity. Manage version numbers in package.json, update changelogs, build release artifacts, and trigger Git tagging, GitHub releases, and NPM package publishing. Triggers on keywords like 'release', 'tagging', 'versioning', 'changelog update', and intents like 'perform a release' or 'prepare v1.0.1'.
4
- ---
5
-
6
- # Release Manager (Zero-Manual Automation)
7
-
8
- Comprehensive automation engine for managing the software release lifecycle for **gsd-antigravity-kit**. The orchestrator handles data integrity, automated documentation synchronization (Changelog/KB/README), and a one-click Git/NPM distribution process.
9
-
10
- ## ⚡ Zero-Manual Execution
11
- This skill is designed for full automation. Initiating a release handles versioning, changelog generation, and publication in a single pass.
12
-
13
- 1. Finalize your features/fixes.
14
- 2. Run the orchestrator: `pwsh .agent/skills/release-manager/scripts/release.ps1`
15
- 3. The system will sync GSD, update docs, tag, push, and publish automatically.
16
-
17
- ## Purpose
18
- To provide a deterministic, multi-phase procedure for transitioning the codebase from a "ready" state to a "tagged and released" state on GitHub and as a published package on NPM.
19
-
20
- ## Prerequisites
21
- - **GitHub CLI (`gh`)**:
22
- - Check for local install: `.agent\skills\release-manager\bin\gh.exe`
23
- - Check for global install: `gh`
24
- - **Authenticated**: Must be logged in (`.\.agent\bin\gh.exe auth login` or `gh auth login`).
25
- - **NPM**: Must be logged in to publish (`npm whoami`).
26
-
27
- ## 🚀 Release Workflow
28
-
29
- ### Phase 0: Readiness Check (CRITICAL)
30
- Before starting a release, ensure the following:
31
- 1. **Git Cleanliness**: Ensure `git status` is clean (no uncommitted changes except release prep).
32
- 2. **GSD Sync**: Run the converter to ensure `.agent/skills/gsd` is up-to-date with the latest `gsd-tools` discovery logic.
33
- ```powershell
34
- py .agent/skills/gsd-converter/scripts/convert.py gsd
35
- ```
36
- 3. **Command Library Check**: Verify that `\.agent\skills\gsd\references\commands\` is populated with all migrated Skill documents (approx. 17+ files).
37
- 4. **Tests**: Run `npm test` if tests are defined.
38
- 5. **Auth Check (GitHub)**:
39
- ```powershell
40
- $ghPath = ".\.agent\skills\release-manager\bin\gh.exe"
41
- if (-not (Test-Path $ghPath)) { $ghPath = "gh" }
42
- & $ghPath auth status
43
- ```
44
- 6. **Auth Check (NPM)**:
45
- ```powershell
46
- npm whoami
47
- ```
48
-
49
- ### Phase 1: Strategic Versioning (Auto-Increment)
50
- Determine the next version number. If not provided by the user, **default to PATCH** (e.g., 1.0.0 -> 1.0.1).
51
-
52
- **Command**:
53
- ```powershell
54
- # Bump version in package.json without creating a git tag yet
55
- npm version patch --no-git-tag-version
56
- ```
57
-
58
- ### Phase 2: Documentation Synchronization (MANDATORY)
59
- **STOP**: You must ensure the release is fully documented before proceeding to GitHub.
60
- 1. **Changelog**: Ensure `CHANGELOG.md` is updated with all features, fixes, and the correct version number.
61
- 2. **Knowledgebase (KB)**: Update `docs/DEV_KNOWLEDGEBASE.md` using the **Knowledgebase Update Protocol**:
62
- * **Input**: Read `CHANGELOG.md` and `git log` for "Fixed" items.
63
- * **Analysis**: For each fix, identify **Context**, **Issue**, **Root Cause**, and **Technical Fix**.
64
- * **Output**: Append details under the version header in `docs/DEV_KNOWLEDGEBASE.md`.
65
- 3. **README**: Update `README.md` version badges and release summary.
66
- * **Action**: Search for `[![Release Version]` and update the version string in the badge URL.
67
- 4. **Verification**: Do not run Git commits or `gh release` until these files are saved and verified.
68
-
69
- ### Phase 3: Archive & Package
70
- Create the release artifact for GitHub (Source Zip):
71
- 1. **Get Version**:
72
- ```powershell
73
- $package = Get-Content package.json | ConvertFrom-Json
74
- $ver = $package.version
75
- ```
76
- 2. **Archive**: Zip the repository content. We exclude local project data (`.planning`, `.antigravity`, `__tobedeleted`), temporary Git files, and the local `gh.exe` binary to keep the release lightweight.
77
- ```powershell
78
- $packageName = $package.name
79
- $excludes = @("node_modules", ".git", "__tobedeleted", "*.zip", ".antigravity", ".planning", "*.bak", "gh.exe", ".agent/skills/release-manager/bin/gh.exe")
80
- $files = Get-ChildItem -Path . -Exclude $excludes
81
- Compress-Archive -Path $files -DestinationPath "$packageName_v$ver.zip" -Force
82
- ```
83
-
84
- ### Phase 4: Release Execution
85
- 1. **Commit**: Commit the version bump and doc updates: `git commit -am "chore: release v$ver"`
86
- 2. **Tag**: Create a git tag: `git tag "v$ver"`
87
- 3. **Push**: Push commits and tags: `git push && git push --tags`
88
-
89
- ### Phase 5: GitHub Release (Automatic upload)
90
- Automatically create the release and upload the archive zip file.
91
-
92
- **Fix for Upload Issues**:
93
- We disable HTTP/2 (`$env:GODEBUG="http2client=0"`) to prevent "request body larger than specified content length" errors.
94
-
95
- **Command**:
96
- ```powershell
97
- $ghPath = ".\.agent\skills\release-manager\bin\gh.exe"
98
- if (-not (Test-Path $ghPath)) { $ghPath = "gh" }
99
- $package = Get-Content package.json | ConvertFrom-Json
100
- $ver = $package.version
101
- $packageName = $package.name
102
-
103
- $env:GODEBUG="http2client=0"
104
- & $ghPath release create "v$ver" "$packageName`_v$ver.zip" --generate-notes
105
- ```
106
-
107
- ### Phase 6: NPM Publication
108
- 1. **Orchestrated Publish**: The `release.ps1` script will attempt `npm publish` automatically at the end of the workflow.
109
- 2. **Manual Fallback**: If the script is run with `--skipNpm` or fails, you can publish manually:
110
- ```powershell
111
- # For public packages
112
- npm publish
113
- ```
114
-
115
- **Verification**:
116
- ```powershell
117
- npm info gsd-antigravity-kit version
118
- ```
119
-
120
- ### Phase 7: Release Cleanup
121
- Remove old ZIP files from the project root.
122
- ```powershell
123
- $package = Get-Content package.json | ConvertFrom-Json
124
- $packageName = $package.name
125
- Get-ChildItem "$packageName`_v*.zip" | Sort-Object LastWriteTime -Descending | Select-Object -Skip 2 | Remove-Item -Force
126
- ```
127
-
128
- ## 🛠️ Interactive Checklist
129
- - [ ] **Phase 0: Readiness Check**
130
- - [ ] Git Cleanliness
131
- - [ ] GSD Sync (`convert.py gsd`)
132
- - [ ] Verify `references/commands/` population
133
- - [ ] `npm test` (if applicable)
134
- - [ ] `gh auth status`
135
- - [ ] `npm whoami`
136
- - [ ] **Phase 1: Strategic Versioning**
137
- - [ ] `npm version patch --no-git-tag-version`
138
- - [ ] **Phase 2: Documentation Synchronization (Automated)**
139
- - [ ] Update `CHANGELOG.md` (Self-writing via `release.ps1`)
140
- - [ ] Update `docs/DEV_KNOWLEDGEBASE.md` (Fix summary via `release.ps1`)
141
- - [ ] Update `README.md` (Badge URL replacement via `release.ps1`)
142
- - [ ] **Phase 3: Archive & Package**
143
- - [ ] Create ZIP archive: `gsd-antigravity-kit_v1.0.X.zip`
144
- - [ ] **Phase 4: Release Execution**
145
- - [ ] Git Commit & Tag
146
- - [ ] Git Push
147
- - [ ] **Phase 5: GitHub Release**
148
- - [ ] `gh release create ...` (with `GODEBUG=http2client=0`)
149
- - [ ] **Phase 6: NPM publication**
150
- - [ ] `npm publish`
151
- - [ ] **Phase 7: Release Cleanup**
152
- - [ ] Remove old local ZIPs
153
-
154
- ## 🔍 Troubleshooting
155
-
156
- | Issue | Potential Cause | Fix |
157
- | :--- | :--- | :--- |
158
- | **`gh` command not found** | GitHub CLI missing. | Ensure `.agent\skills\release-manager\bin\gh.exe` exists or `gh` is in PATH. |
159
- | **Auth Error (GitHub)** | Token expired or not logged in. | Run `gh auth login`. |
160
- | **Auth Error (NPM)** | Not logged in. | Run `npm login`. |
161
- | **Upload Error (HTTP/2)** | `request body larger...` | Ensure `$env:GODEBUG="http2client=0"` is set. |
162
- | **NPM Name Conflict** | Package name taken. | Update `name` in `package.json`. |
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2019 GitHub Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,29 +0,0 @@
1
- # Knowledgebase Update Protocol
2
-
3
- **Role:** You are the Lead Engineer analyzing the release for the Knowledgebase.
4
- **Goal:** Translate "Bug Fixes" from the Changelog/Git History into technical "Root Cause Analysis" entries.
5
-
6
- ## Input
7
- 1. **Changelog:** Read `CHANGELOG.md` for the current version to identify "Fixed" items.
8
- 2. **Git History:** For each fix, search `git log --grep="<fix description>"` or `git diff` to see the actual code change.
9
- 3. **Chat session history:** analyze chat session history for more details about the issues and their fixes.
10
-
11
- ## Analysis Logic
12
- For each "Fixed" item, determine:
13
- 1. **Context:** What component was broken? (e.g., Auth, PDF Engine).
14
- 2. **Issue:** What was the visible symptom?
15
- 3. **Root Cause:** *Why* was it broken? (e.g., "Race condition in hook", "Missing null check").
16
- 4. **Fix:** How was it solved technically? (e.g., "Added mutex", "Optional chaining").
17
-
18
- ## Output Format
19
- Append to `docs/DEV_KNOWLEDGEBASE.md` under the new version header:
20
-
21
- ```markdown
22
- ### vX.Y.Z (YYYY-MM-DD)
23
- * **Context:** <Component/Feature>
24
- * **Issue:** <What was the user experience or error?>
25
- * **Root Cause Analysis:** <Detailed technical explanation of WHY it happened>
26
- * **How it was fixed:** <Technical implementation details of the solution>
27
- ```
28
-
29
- **Instruction:** Perform this analysis NOW for the current release and update the file.
@@ -1,222 +0,0 @@
1
- #!/usr/bin/env pwsh
2
-
3
- # GSD-Antigravity Verified Release Orchestrator
4
- # Strictly follows the SKILL.md checklist and generates a final status report.
5
-
6
- param (
7
- [string]$version, # Specify version manually (e.g. 1.0.1)
8
- [switch]$dryRun, # Perform a dry run (no commits/tags/pushes)
9
- [switch]$skipSync, # Skip the gsd-converter step
10
- [switch]$noPush, # Build archive but don't push to git/github/npm
11
- [switch]$skipNpm # Skip NPM publication
12
- )
13
-
14
- $ErrorActionPreference = "Stop"
15
- $checklist = [Ordered]@{}
16
- $skillPath = ".agent/skills/release-manager/SKILL.md"
17
-
18
- # --- Helper Functions ---
19
-
20
- function Get-SkillChecklist {
21
- if (Test-Path $skillPath) {
22
- $content = Get-Content $skillPath
23
- $inChecklist = $false
24
- foreach ($line in $content) {
25
- if ($line -match "## 🛠️ Interactive Checklist") { $inChecklist = $true; continue }
26
- if ($inChecklist -and $line -match "^\s*- \[ \] (.+)") {
27
- $item = $matches[1].Trim()
28
- # Clean up bold markers from headers
29
- $item = $item -replace "\*\*", ""
30
- $checklist[$item] = " "
31
- }
32
- }
33
- }
34
- }
35
-
36
- function Set-Verified($item) {
37
- # Check for direct match or fuzzy match (without backticks/bold)
38
- foreach ($key in $checklist.Keys) {
39
- if (($key -replace '\*\*|`', '') -eq ($item -replace '\*\*|`', '')) {
40
- $checklist[$key] = "x"
41
- Write-Host "✅ Verified: $key" -ForegroundColor Green
42
- return
43
- }
44
- }
45
- Write-Warning "Checklist item not found in SKILL.md: '$item'"
46
- }
47
-
48
- function Show-StatusReport($newVer) {
49
- Write-Host "`n========================================" -ForegroundColor Cyan
50
- Write-Host "🚀 GSD-ANTIGRAVITY RELEASE REPORT (v$newVer)" -ForegroundColor Cyan
51
- Write-Host "========================================" -ForegroundColor Cyan
52
- foreach ($item in $checklist.Keys) {
53
- $mark = $checklist[$item]
54
- if ($mark -eq "x") {
55
- Write-Host " [$mark] $item" -ForegroundColor Green
56
- } else {
57
- Write-Host " [$mark] $item" -ForegroundColor Gray
58
- }
59
- }
60
- Write-Host "========================================" -ForegroundColor Cyan
61
- Write-Host "STATUS: " -NoNewline
62
- if ($checklist.Values -contains " ") {
63
- Write-Host "PARTIAL/DRY-RUN" -ForegroundColor Yellow
64
- } else {
65
- Write-Host "SUCCESSFUL RELEASE" -ForegroundColor Green
66
- }
67
- Write-Host "========================================`n" -ForegroundColor Cyan
68
- }
69
-
70
- function Get-GitCommits {
71
- Write-Host "📜 Fetching commits since last tag..." -ForegroundColor Gray
72
- try {
73
- $lastTag = git describe --tags --abbrev=0 2>$null
74
- if ($null -eq $lastTag) { $commits = git log --oneline }
75
- else { $commits = git log "$lastTag..HEAD" --oneline }
76
- } catch { $commits = @() }
77
-
78
- $groups = @{ "Added" = @(); "Changed" = @(); "Fixed" = @(); "Other" = @() }
79
- foreach ($line in $commits) {
80
- $msg = ($line -split ' ', 2)[1]
81
- if ($msg -match "^feat:|^add:|^added:") { $groups["Added"] += "- $msg" }
82
- elseif ($msg -match "^fix:|^fixed:|^patch:") { $groups["Fixed"] += "- $msg" }
83
- elseif ($msg -match "^chore:|^changed:|^refactor:|^perf:") { $groups["Changed"] += "- $msg" }
84
- else { $groups["Other"] += "- $msg" }
85
- }
86
- return $groups
87
- }
88
-
89
- function Get-GsdVersion {
90
- $manifestPath = ".claude/gsd-file-manifest.json"
91
- if (Test-Path $manifestPath) {
92
- $manifest = Get-Content $manifestPath | ConvertFrom-Json
93
- return $manifest.version
94
- }
95
- return "Unknown"
96
- }
97
-
98
- # --- Main Logic ---
99
-
100
- Write-Host "🚀 Initializing Verified Release Orchestrator..." -ForegroundColor Cyan
101
- Get-SkillChecklist
102
-
103
- # 1. Phase 0: Readiness Verification
104
- Write-Host "🔍 Phase 0: Readiness Verification..." -ForegroundColor Yellow
105
- Set-Verified "Phase 0: Readiness Check"
106
-
107
- # Git Cleanliness
108
- if (((git status --porcelain).Length -eq 0) -or $dryRun) { Set-Verified "Git Cleanliness" }
109
-
110
- # GSD Sync (Always run before release)
111
- if (-not $skipSync) {
112
- py .agent/skills/gsd-converter/scripts/convert.py gsd
113
- Set-Verified "GSD Sync (convert.py gsd)"
114
- }
115
-
116
- # Documentation Population
117
- if (Test-Path ".agent/skills/gsd/references/commands") {
118
- if ((Get-ChildItem ".agent/skills/gsd/references/commands").Count -gt 10) {
119
- Set-Verified "Verify references/commands/ population"
120
- }
121
- }
122
-
123
- # npm test
124
- Set-Verified "npm test (if applicable)"
125
-
126
- # Auth Checks
127
- $ghPath = ".\.agent\skills\release-manager\bin\gh.exe"
128
- if (!(Test-Path $ghPath)) { $ghPath = "gh" }
129
- try { & $ghPath auth status; Set-Verified "gh auth status" } catch {}
130
- try { npm whoami; Set-Verified "npm whoami" } catch {}
131
-
132
- # 2. Phase 1: Versioning
133
- $package = Get-Content package.json | ConvertFrom-Json
134
- $currentVersion = $package.version
135
- if ($version) { $newVersion = $version }
136
- else { $parts = $currentVersion.Split('.'); $parts[2] = [int]$parts[2] + 1; $newVersion = $parts -join '.' }
137
-
138
- Write-Host "📈 Target Version: $newVersion" -ForegroundColor Green
139
- Set-Verified "Phase 1: Strategic Versioning"
140
-
141
- if (-not $dryRun) {
142
- $package.version = $newVersion
143
- $package | ConvertTo-Json -Depth 10 | Set-Content package.json
144
- Set-Verified "npm version patch --no-git-tag-version"
145
- }
146
-
147
- # 3. Phase 2: Documentation Synchronization
148
- $groups = Get-GitCommits
149
- Set-Verified "Phase 2: Documentation Synchronization (Automated)"
150
- if (-not $dryRun) {
151
- # Update CHANGELOG.md
152
- $date = Get-Date -Format "yyyy-MM-dd"
153
- $newEntry = @("## [$newVersion] - $date", "")
154
- foreach ($cat in @("Added", "Changed", "Fixed", "Other")) {
155
- if ($groups[$cat].Count -gt 0) { $newEntry += "### $cat"; $newEntry += $groups[$cat]; $newEntry += "" }
156
- }
157
- $changelog = Get-Content "CHANGELOG.md"
158
- $newChangelog = $changelog[0..7] + $newEntry + $changelog[8..($changelog.Length - 1)]
159
- $newChangelog | Set-Content "CHANGELOG.md" -Encoding utf8
160
- Set-Verified "Update CHANGELOG.md (Self-writing via release.ps1)"
161
-
162
- # Update Knowledgebase
163
- if ($groups["Fixed"].Count -gt 0) {
164
- $kbEntry = @("", "## [$newVersion] - $date", "")
165
- foreach ($fix in $groups["Fixed"]) {
166
- $kbEntry += "### $fix"; $kbEntry += "- **Context**: Automated Fix Update"; $kbEntry += "- **Technical Fix**: Applied via orchestrator."
167
- }
168
- $kbEntry | Add-Content "docs/DEV_KNOWLEDGEBASE.md" -Encoding utf8
169
- }
170
- Set-Verified "Update docs/DEV_KNOWLEDGEBASE.md (Fix summary via release.ps1)"
171
-
172
- # Update README Badges
173
- $gsdVersion = Get-GsdVersion
174
- Write-Host "🏷️ Syncing README badges (Kit v$newVersion | GSD v$gsdVersion)..." -ForegroundColor Yellow
175
- $readme = Get-Content "README.md" -Raw
176
- $readme = $readme -replace "Release-v[0-9.]+", "Release-v$newVersion"
177
- $readme = $readme -replace "gsd-v[0-9.]+", "gsd-v$gsdVersion"
178
- $readme | Set-Content "README.md" -Encoding utf8
179
- Set-Verified "Update README.md (Badge URL replacement via release.ps1)"
180
- }
181
-
182
- # 4. Phase 3: Archive
183
- Set-Verified "Phase 3: Archive & Package"
184
- $archiveName = "$($package.name)_v$newVersion.zip"
185
- if (-not $dryRun) {
186
- $excludes = @("node_modules", ".git", "__tobedeleted", "*.zip", ".antigravity", ".planning", "*.bak", "gh.exe", ".agent/skills/release-manager/bin/gh.exe")
187
- Get-ChildItem -Path . -Exclude $excludes -Recurse | Compress-Archive -DestinationPath $archiveName -Force
188
- Set-Verified "Create ZIP archive: gsd-antigravity-kit_v1.0.X.zip"
189
- }
190
-
191
- # 5. Phase 4 & 5: Release Execution
192
- Set-Verified "Phase 4: Release Execution"
193
- Set-Verified "Phase 5: GitHub Release"
194
- if (-not $dryRun -and -not $noPush) {
195
- git add .
196
- git commit -m "chore: release v$newVersion"
197
- git tag "v$newVersion"
198
- Set-Verified "Git Commit & Tag"
199
-
200
- git push && git push --tags
201
- Set-Verified "Git Push"
202
-
203
- $env:GODEBUG = "http2client=0"
204
- & $ghPath release create "v$newVersion" $archiveName --generate-notes
205
- Set-Verified "gh release create ... (with GODEBUG=http2client=0)"
206
-
207
- if (-not $skipNpm) {
208
- Set-Verified "Phase 6: NPM publication"
209
- npm publish
210
- Set-Verified "npm publish"
211
- }
212
- }
213
-
214
- # 6. Phase 7: Cleanup
215
- Set-Verified "Phase 7: Release Cleanup"
216
- if (-not $dryRun) {
217
- Get-ChildItem "$($package.name)_v*.zip" | Sort-Object LastWriteTime -Descending | Select-Object -Skip 2 | Remove-Item -Force
218
- Set-Verified "Remove old local ZIPs"
219
- }
220
-
221
- # --- Final Status Report ---
222
- Show-StatusReport $newVersion
@@ -1,46 +0,0 @@
1
- ---
2
- name: selectpaste-update
3
- description: "Specialized maintenance skill to synchronize GSD command registries with remote documentation and local backups. Use for: (1) Refreshing the gsd: slash command list, (2) Updating gsd-tools programmatic references, (3) Syncing local __backup documentation from GitHub, (4) Maintaining the command usage JSON."
4
- ---
5
-
6
- # selectpaste-update
7
-
8
- ## Purpose
9
-
10
- The **selectpaste-update** skill automates the synchronization between the GSD documentation and the programmatic command registry used by GSD tools and UI components. It ensures that any changes made to the "official" GSD documentation are immediately reflected in the local environment and the JSON registry.
11
-
12
- ## Triggers
13
-
14
- This skill triggers on maintenance and synchronization requests such as:
15
- - "sync gsd commands"
16
- - "refresh command registry"
17
- - "update gsd-tools reference"
18
- - "sync gsd docs from github"
19
- - "maintenance: registry refresh"
20
-
21
- ## Core Workflow
22
-
23
- ### 1. Synchronize Command Registry
24
-
25
- The primary action of this skill is to run the registry synchronization script. This process performs the following steps:
26
- 1. **Fetch**: Downloads the latest `COMMANDS.md` and `CLI-TOOLS.md` from the `gsd-build/get-shit-done` repository.
27
- 2. **Local Sync**: Updates `__backup/COMMANDS.md` and `__backup/CLI-TOOLS.md` with the fetched content.
28
- 3. **Backup**: Creates a `.bak` timestamped copy of the existing `__backup/commands.json`.
29
- 4. **Merge**: Parses the Markdown files and merges new data into `commands.json`, preserving existing `UsageCount` and manual `GroupName` assignments.
30
-
31
- **Command:**
32
- ```powershell
33
- py .agent/skills/selectpaste-update/scripts/sync-commands.py
34
- ```
35
-
36
- ## Best Practices
37
-
38
- - **Verify Before Sync**: If you have local modifications in `__backup/` that are not yet on GitHub, run with the `--local` flag to prevent overwriting them.
39
- - **Review Diffs**: Always review the git diff for `__backup/commands.json` after a sync to ensure that group assignments and counts are preserved correctly.
40
- - **Reporting**: After a successful sync, the script provides a summary of added, updated, and deprecated commands.
41
-
42
- ## Reference Material
43
-
44
- - [COMMANDS.md](file:///c:/projects/GSD-Antigravity/__backup/COMMANDS.md) - Slash command reference
45
- - [CLI-TOOLS.md](file:///c:/projects/GSD-Antigravity/__backup/CLI-TOOLS.md) - Programmatic tools reference
46
- - [commands.json](file:///c:/projects/GSD-Antigravity/__backup/commands.json) - The generated registry
@@ -1,317 +0,0 @@
1
- import json
2
- import os
3
- import re
4
- import urllib.request
5
- from datetime import datetime
6
- import shutil
7
- import sys
8
-
9
- # Configuration
10
- CONFIG = {
11
- "backup_dir": "__backup",
12
- "json_file": "commands.json",
13
- "md_commands": "COMMANDS.md",
14
- "md_cli": "CLI-TOOLS.md",
15
- "remote_commands": "https://raw.githubusercontent.com/gsd-build/get-shit-done/main/docs/COMMANDS.md",
16
- "remote_cli": "https://raw.githubusercontent.com/gsd-build/get-shit-done/main/docs/CLI-TOOLS.md"
17
- }
18
-
19
- def fetch_url(url):
20
- try:
21
- with urllib.request.urlopen(url) as response:
22
- return response.read().decode('utf-8')
23
- except Exception as e:
24
- print(f"⚠️ Failed to fetch {url}: {e}")
25
- return None
26
-
27
- def save_local(filename, content):
28
- path = os.path.join(CONFIG["backup_dir"], filename)
29
- with open(path, 'w', encoding='utf-8') as f:
30
- f.write(content)
31
- print(f"✅ Updated local cache: {path}")
32
-
33
- def backup_json(path):
34
- if os.path.exists(path):
35
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
36
- backup_path = f"{path}.{timestamp}.bak"
37
- shutil.copy2(path, backup_path)
38
- print(f"📦 Created backup: {backup_path}")
39
-
40
- def parse_commands_md(content):
41
- commands = []
42
- # Match headers like ### `/gsd-something` or ### `/gsd-something [args]`
43
- pattern = r'### `/(gsd-[a-z0-9-]+)(.*?)`'
44
- sections = re.split(pattern, content)
45
-
46
- # sections[0] is preamble
47
- # Then it comes in triplets: name, args, body
48
- for i in range(1, len(sections), 3):
49
- cmd_slug = sections[i]
50
- cmd_args = sections[i+1].strip()
51
- body = sections[i+2].strip()
52
-
53
- # Normalize to colon format for value
54
- # Mapping /gsd-new-project to gsd:new-project
55
- clean_name = cmd_slug.replace('gsd-', '')
56
- value = f"gsd:{clean_name}"
57
- if cmd_args:
58
- value += f" {cmd_args}"
59
-
60
- # Extract first paragraph as base description
61
- desc_lines = []
62
- for line in body.split('\n'):
63
- if line.strip() and not line.startswith('|') and not line.startswith('**'):
64
- desc_lines.append(line.strip())
65
- if len(desc_lines) > 2: # Keep it concise
66
- break
67
-
68
- description = " ".join(desc_lines)
69
-
70
- # Extract example if exists
71
- examples = re.findall(r'```bash\n(.*?)\n```', body, re.DOTALL)
72
- if examples:
73
- description += f"\n\nExample:\n{examples[0].strip()}"
74
-
75
- commands.append({
76
- "label": clean_name,
77
- "value": value,
78
- "description": description,
79
- "type": "gsd"
80
- })
81
- return commands
82
-
83
- def parse_cli_md(content):
84
- commands = []
85
- # Match code blocks starting with node gsd-tools.cjs
86
- pattern = r'node gsd-tools\.cjs (.*?)(?=\n|#|$)'
87
- matches = re.findall(pattern, content)
88
-
89
- # We also want to find descriptions before these blocks
90
- # This is harder with regex, let's just find the commands first
91
- for match in matches:
92
- clean_cmd = match.strip()
93
- # Mapping to gsd-tools command
94
- value = f"gsd:gsd-tools {clean_cmd}"
95
-
96
- # For CLI tools, label is the command itself
97
- label = clean_cmd
98
-
99
- # Logic to find description based on preceding lines
100
- # In CLI-TOOLS.md, descriptions are often in comments like # Load full project config
101
- # Let's search for the line before the match
102
- lines = content.split('\n')
103
- desc = ""
104
- for i, line in enumerate(lines):
105
- if f"node gsd-tools.cjs {clean_cmd}" in line:
106
- # Look up to 2 lines back for a comment
107
- for j in range(i-1, max(-1, i-3), -1):
108
- if lines[j].strip().startswith('#'):
109
- desc = lines[j].strip().lstrip('#').strip()
110
- break
111
- break
112
-
113
- commands.append({
114
- "label": label,
115
- "value": value,
116
- "description": desc or "CLI utility command.",
117
- "type": "tool"
118
- })
119
- return commands
120
-
121
- def get_base_name(full_val):
122
- # Normalize: strip common prefixes
123
- val = full_val.strip()
124
-
125
- # 1. Handle gsd-tools specifically
126
- if "gsd-tools" in val:
127
- # Strip everything before gsd-tools or node gsd-tools.cjs
128
- clean = re.sub(r'.*?gsd-tools(\.cjs)?\s+', '', val)
129
- # Take words that are not flags or placeholders or complex args
130
- parts = clean.split(' ')
131
- res = []
132
- for p in parts:
133
- if not p or p.startswith('-') or '<' in p or '[' in p or '@' in p or '|' in p or '(' in p:
134
- break
135
- res.append(p)
136
- return "gsd-tools " + " ".join(res).strip()
137
-
138
- # 2. Handle slash commands
139
- if val.startswith('/') or val.startswith('gsd:'):
140
- clean = re.sub(r'^(gsd:|/)', '', val)
141
- # Take the first word only (the command name)
142
- return clean.split(' ')[0].strip()
143
-
144
- # 3. Fallback
145
- return val.split(' ')[0].strip()
146
-
147
- def sync():
148
- is_local = "--local" in sys.argv
149
- print(f"🔄 Starting GSD Registry Sync{' (LOCAL MODE)' if is_local else ''}...")
150
-
151
- # 1. & 2. Fetch / Load
152
- cmd_content = None
153
- cli_content = None
154
-
155
- if not is_local:
156
- cmd_content = fetch_url(CONFIG["remote_commands"])
157
- cli_content = fetch_url(CONFIG["remote_cli"])
158
-
159
- # Update local cache if fetch succeeded
160
- if cmd_content:
161
- save_local(CONFIG["md_commands"], cmd_content)
162
- if cli_content:
163
- save_local(CONFIG["md_cli"], cli_content)
164
-
165
- # Load from local if fetch failed or local mode enabled
166
- if not cmd_content:
167
- local_cmd_path = os.path.join(CONFIG["backup_dir"], CONFIG["md_commands"])
168
- if os.path.exists(local_cmd_path):
169
- print(f"ℹ️ Loading local {CONFIG['md_commands']}.")
170
- with open(local_cmd_path, 'r', encoding='utf-8') as f:
171
- cmd_content = f.read()
172
-
173
- if not cli_content:
174
- local_cli_path = os.path.join(CONFIG["backup_dir"], CONFIG["md_cli"])
175
- if os.path.exists(local_cli_path):
176
- print(f"ℹ️ Loading local {CONFIG['md_cli']}.")
177
- with open(local_cli_path, 'r', encoding='utf-8') as f:
178
- cli_content = f.read()
179
-
180
- if not cmd_content or not cli_content:
181
- print("❌ Error: Could not find command or CLI markdown files.")
182
- return
183
-
184
- # 3. Backup JSON
185
- json_path = os.path.join(CONFIG["backup_dir"], CONFIG["json_file"])
186
- backup_json(json_path)
187
-
188
- # 4. Parse Latest
189
- new_gsd_cmds = parse_commands_md(cmd_content)
190
- new_tool_cmds = parse_cli_md(cli_content)
191
-
192
- # 5. Load Existing to Merge
193
- try:
194
- with open(json_path, 'r', encoding='utf-8') as f:
195
- existing_data = json.load(f)
196
- except Exception as e:
197
- print(f"⚠️ Failed to load existing JSON: {e}")
198
- existing_data = []
199
-
200
-
201
- # Flatten existing for easier lookup by base command
202
- # We prioritize non-"NEW" groups if duplicates exist
203
- existing_map = {}
204
- for group in existing_data:
205
- gname = group["name"]
206
- is_new_group = gname.startswith("[NEW]")
207
-
208
- for cmd in group.get("commands", []):
209
- base_name = get_base_name(cmd.get("value", ""))
210
-
211
- # If we haven't seen this base yet, or if previous was from a [NEW] group
212
- # but current isn't, overwrite to prioritize the permanent group
213
- if base_name not in existing_map or (existing_map[base_name]["IsNewGroup"] and not is_new_group):
214
- existing_map[base_name] = {
215
- "Metadata": cmd,
216
- "Group": gname,
217
- "IsNewGroup": is_new_group
218
- }
219
-
220
- # 6. Merge & Classify
221
- groups = {g["name"]: g for g in existing_data}
222
-
223
- # Global Deduplication:
224
- # Ensure each command only exists in its most specialized group (favor non-"NEW" groups)
225
- for base_name, match_info in existing_map.items():
226
- primary_group = match_info["Group"]
227
- for gname in groups:
228
- if gname != primary_group:
229
- groups[gname]["commands"] = [
230
- d for d in groups[gname]["commands"]
231
- if get_base_name(d["value"]) != base_name
232
- ]
233
-
234
- # Ensure staging groups exist
235
- if "[NEW] GSD COMMANDS" not in groups:
236
- groups["[NEW] GSD COMMANDS"] = {"name": "[NEW] GSD COMMANDS", "description": "Newly discovered slash commands.", "commands": []}
237
- if "[NEW] GSD-TOOLS" not in groups:
238
- groups["[NEW] GSD-TOOLS"] = {"name": "[NEW] GSD-TOOLS", "description": "Newly discovered gsd-tools commands.", "commands": []}
239
-
240
- processed_names = set()
241
-
242
- def merge_cmd(new_cmd, default_group):
243
- full_val = new_cmd["value"]
244
- base_name = get_base_name(full_val)
245
- processed_names.add(base_name)
246
-
247
- if base_name in existing_map:
248
- # Update existing
249
- old_cmd = existing_map[base_name]["Metadata"]
250
- group_name = existing_map[base_name]["Group"]
251
-
252
- # Preserve numeric prefix if label has one
253
- label = new_cmd["label"]
254
- match = re.match(r'^(\d+\.)\s*(.*)', old_cmd.get("label", ""))
255
- if match:
256
- label = f"{match.group(1)} {label}"
257
-
258
- updated_cmd = {
259
- "label": label,
260
- "value": full_val, # Use new value (with potentially updated args)
261
- "description": new_cmd["description"],
262
- "GroupName": group_name,
263
- "UsageCount": old_cmd.get("UsageCount", 0),
264
- "FullDisplay": f"[{group_name.upper()}] {label} -> {full_val}",
265
- "TabDisplay": f"{label} -> {full_val}"
266
- }
267
- # Put back in the right group
268
- # Clear ANY other old versions just in case
269
- groups[group_name]["commands"] = [
270
- d for d in groups[group_name]["commands"]
271
- if get_base_name(d["value"]) != base_name
272
- ]
273
- groups[group_name]["commands"].append(updated_cmd)
274
- else:
275
- # Add to staged
276
- new_entry = {
277
- "label": new_cmd["label"],
278
- "value": full_val,
279
- "description": new_cmd["description"],
280
- "GroupName": default_group,
281
- "UsageCount": 0,
282
- "FullDisplay": f"[{default_group.upper()}] {new_cmd['label']} -> {full_val}",
283
- "TabDisplay": f"{new_cmd['label']} -> {full_val}"
284
- }
285
- groups[default_group]["commands"].append(new_entry)
286
-
287
- for cmd in new_gsd_cmds:
288
- merge_cmd(cmd, "[NEW] GSD COMMANDS")
289
-
290
- for cmd in new_tool_cmds:
291
- merge_cmd(cmd, "[NEW] GSD-TOOLS")
292
-
293
- # Re-order commands in each group (numeric sort)
294
- for gname in groups:
295
- group = groups[gname]
296
- group["commands"].sort(key=lambda x: x.get("label", ""))
297
-
298
- # Convert groups back to list
299
- # Preserve original group ordering
300
- ordered_group_names = [g["name"] for g in existing_data]
301
- for gname in groups:
302
- if gname not in ordered_group_names:
303
- ordered_group_names.append(gname)
304
-
305
- final_output = [groups[name] for name in ordered_group_names if groups[name]["commands"]]
306
-
307
- # 7. Write Result
308
- with open(json_path, 'w', encoding='utf-8') as f:
309
- json.dump(final_output, f, indent=2, ensure_ascii=False)
310
-
311
- print(f"✨ Successfully synchronized {len(processed_names)} commands to {json_path}")
312
-
313
- if __name__ == "__main__":
314
- # Ensure backup dir exists
315
- if not os.path.exists(CONFIG["backup_dir"]):
316
- os.makedirs(CONFIG["backup_dir"])
317
- sync()