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.
- package/.agent/skills/gsd/SKILL.md +152 -123
- package/.agent/skills/gsd/VERSION +1 -0
- package/.agent/skills/gsd/assets/templates/user-profile.md +8 -8
- package/.agent/skills/gsd/bin/gsd-tools.cjs +81 -3
- package/.agent/skills/gsd/bin/help-manifest.json +24 -1
- package/.agent/skills/gsd/bin/hooks/gsd-check-update.js +15 -5
- package/.agent/skills/gsd/bin/hooks/gsd-context-monitor.js +1 -1
- package/.agent/skills/gsd/bin/hooks/gsd-phase-boundary.sh +27 -0
- package/.agent/skills/gsd/bin/hooks/gsd-prompt-guard.js +2 -1
- package/.agent/skills/gsd/bin/hooks/gsd-read-guard.js +1 -1
- package/.agent/skills/gsd/bin/hooks/gsd-session-state.sh +33 -0
- package/.agent/skills/gsd/bin/hooks/gsd-statusline.js +5 -5
- package/.agent/skills/gsd/bin/hooks/gsd-validate-commit.sh +47 -0
- package/.agent/skills/gsd/bin/hooks/gsd-workflow-guard.js +1 -1
- package/.agent/skills/gsd/bin/lib/config.cjs +31 -10
- package/.agent/skills/gsd/bin/lib/core.cjs +48 -13
- package/.agent/skills/gsd/bin/lib/frontmatter.cjs +34 -2
- package/.agent/skills/gsd/bin/lib/intel.cjs +660 -0
- package/.agent/skills/gsd/bin/lib/learnings.cjs +378 -0
- package/.agent/skills/gsd/bin/lib/milestone.cjs +13 -4
- package/.agent/skills/gsd/bin/lib/model-profiles.cjs +17 -17
- package/.agent/skills/gsd/bin/lib/profile-output.cjs +31 -31
- package/.agent/skills/gsd/bin/lib/security.cjs +119 -0
- package/.agent/skills/gsd/bin/lib/verify.cjs +15 -15
- package/.agent/skills/gsd/migration_report.md +7 -0
- package/.agent/skills/gsd/references/agents/gsd-code-fixer.md +516 -0
- package/.agent/skills/gsd/references/agents/gsd-code-reviewer.md +355 -0
- package/.agent/skills/gsd/references/agents/gsd-debugger.md +10 -1
- package/.agent/skills/gsd/references/agents/gsd-executor.md +3 -0
- package/.agent/skills/gsd/references/agents/gsd-intel-updater.md +314 -0
- package/.agent/skills/gsd/references/agents/gsd-phase-researcher.md +3 -0
- package/.agent/skills/gsd/references/agents/gsd-plan-checker.md +16 -4
- package/.agent/skills/gsd/references/agents/gsd-planner.md +7 -0
- package/.agent/skills/gsd/references/agents/gsd-user-profiler.md +5 -5
- package/.agent/skills/gsd/references/agents/gsd-verifier.md +55 -1
- package/.agent/skills/gsd/references/agents/profiles/dev.md +21 -0
- package/.agent/skills/gsd/references/agents/profiles/research.md +22 -0
- package/.agent/skills/gsd/references/agents/profiles/review.md +22 -0
- package/.agent/skills/gsd/references/commands/{gsd-add-todo.md → atomic/add-todo.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-check-todos.md → atomic/check-todos.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-cleanup.md → atomic/cleanup.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-do.md → atomic/do.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-help.md → atomic/help.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-join-discord.md → atomic/join-discord.md} +21 -19
- package/.agent/skills/gsd/references/commands/{gsd-note.md → atomic/note.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-session-report.md → atomic/session-report.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-ship.md → atomic/ship.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-stats.md → atomic/stats.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-thread.md → atomic/thread.md} +7 -6
- package/.agent/skills/gsd/references/commands/atomic/undo.md +36 -0
- package/.agent/skills/gsd/references/commands/{gsd-add-backlog.md → milestone/add-backlog.md} +8 -7
- package/.agent/skills/gsd/references/commands/{gsd-audit-milestone.md → milestone/audit-milestone.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-complete-milestone.md → milestone/complete-milestone.md} +6 -4
- package/.agent/skills/gsd/references/commands/{gsd-milestone-summary.md → milestone/milestone-summary.md} +5 -3
- package/.agent/skills/gsd/references/commands/{gsd-new-milestone.md → milestone/new-milestone.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-plan-milestone-gaps.md → milestone/plan-milestone-gaps.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-plant-seed.md → milestone/plant-seed.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-review-backlog.md → milestone/review-backlog.md} +6 -5
- package/.agent/skills/gsd/references/commands/misc/audit-fix.md +35 -0
- package/.agent/skills/gsd/references/commands/{gsd-audit-uat.md → misc/audit-uat.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-next.md → misc/next.md} +6 -3
- package/.agent/skills/gsd/references/commands/{gsd-progress.md → misc/progress.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-verify-work.md → misc/verify-work.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-add-phase.md → phase/add-phase.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-add-tests.md → phase/add-tests.md} +8 -3
- package/.agent/skills/gsd/references/commands/{gsd-discuss-phase.md → phase/discuss-phase.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-execute-phase.md → phase/execute-phase.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-insert-phase.md → phase/insert-phase.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-list-phase-assumptions.md → phase/list-phase-assumptions.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-plan-phase.md → phase/plan-phase.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-remove-phase.md → phase/remove-phase.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-research-phase.md → phase/research-phase.md} +7 -6
- package/.agent/skills/gsd/references/commands/{gsd-secure-phase.md → phase/secure-phase.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-ui-phase.md → phase/ui-phase.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-ui-review.md → phase/ui-review.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-validate-phase.md → phase/validate-phase.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-workstreams.md → phase/workstreams.md} +71 -70
- package/.agent/skills/gsd/references/commands/{gsd-analyze-dependencies.md → project/analyze-dependencies.md} +5 -4
- package/.agent/skills/gsd/references/commands/project/explore.md +29 -0
- package/.agent/skills/gsd/references/commands/project/import.md +38 -0
- package/.agent/skills/gsd/references/commands/project/intel.md +181 -0
- package/.agent/skills/gsd/references/commands/{gsd-list-workspaces.md → project/list-workspaces.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-map-codebase.md → project/map-codebase.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-new-project.md → project/new-project.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-new-workspace.md → project/new-workspace.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-remove-workspace.md → project/remove-workspace.md} +4 -3
- package/.agent/skills/gsd/references/commands/project/scan.md +28 -0
- package/.agent/skills/gsd/references/commands/{gsd-autonomous.md → system/autonomous.md} +4 -3
- package/.agent/skills/gsd/references/commands/system/code-review-fix.md +54 -0
- package/.agent/skills/gsd/references/commands/system/code-review.md +57 -0
- package/.agent/skills/gsd/references/commands/{gsd-debug.md → system/debug.md} +7 -6
- package/.agent/skills/gsd/references/commands/{gsd-docs-update.md → system/docs-update.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-fast.md → system/fast.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-forensics.md → system/forensics.md} +5 -3
- package/.agent/skills/gsd/references/commands/{gsd-health.md → system/health.md} +5 -4
- package/.agent/skills/gsd/references/commands/{gsd-manager.md → system/manager.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-pause-work.md → system/pause-work.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-pr-branch.md → system/pr-branch.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-profile-user.md → system/profile-user.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-quick.md → system/quick.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-reapply-patches.md → system/reapply-patches.md} +25 -7
- package/.agent/skills/gsd/references/commands/{gsd-resume-work.md → system/resume-work.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-review.md → system/review.md} +4 -3
- package/.agent/skills/gsd/references/commands/system/set-profile.md +14 -0
- package/.agent/skills/gsd/references/commands/{gsd-settings.md → system/settings.md} +4 -3
- package/.agent/skills/gsd/references/commands/{gsd-update.md → system/update.md} +4 -3
- package/.agent/skills/gsd/references/docs/agent-contracts.md +79 -0
- package/.agent/skills/gsd/references/docs/common-bug-patterns.md +114 -0
- package/.agent/skills/gsd/references/docs/context-budget.md +49 -0
- package/.agent/skills/gsd/references/docs/domain-probes.md +125 -0
- package/.agent/skills/gsd/references/docs/few-shot-examples/plan-checker.md +73 -0
- package/.agent/skills/gsd/references/docs/few-shot-examples/verifier.md +109 -0
- package/.agent/skills/gsd/references/docs/gate-prompts.md +100 -0
- package/.agent/skills/gsd/references/docs/gates.md +70 -0
- package/.agent/skills/gsd/references/docs/model-profile-resolution.md +2 -0
- package/.agent/skills/gsd/references/docs/model-profiles.md +20 -14
- package/.agent/skills/gsd/references/docs/planning-config.md +216 -1
- package/.agent/skills/gsd/references/docs/revision-loop.md +97 -0
- package/.agent/skills/gsd/references/docs/thinking-models-debug.md +44 -0
- package/.agent/skills/gsd/references/docs/thinking-models-execution.md +50 -0
- package/.agent/skills/gsd/references/docs/thinking-models-planning.md +62 -0
- package/.agent/skills/gsd/references/docs/thinking-models-research.md +50 -0
- package/.agent/skills/gsd/references/docs/thinking-models-verification.md +55 -0
- package/.agent/skills/gsd/references/docs/thinking-partner.md +96 -0
- package/.agent/skills/gsd/references/docs/universal-anti-patterns.md +58 -0
- package/.agent/skills/gsd/references/docs/user-profiling.md +10 -10
- package/.agent/skills/gsd/references/docs/verification-overrides.md +227 -0
- package/.agent/skills/gsd/references/docs/workstream-flag.md +2 -2
- package/.agent/skills/gsd/references/mapping.md +11 -21
- package/.agent/skills/gsd/references/workflows/analyze-dependencies.md +3 -3
- package/.agent/skills/gsd/references/workflows/audit-fix.md +157 -0
- package/.agent/skills/gsd/references/workflows/autonomous.md +22 -1
- package/.agent/skills/gsd/references/workflows/code-review-fix.md +497 -0
- package/.agent/skills/gsd/references/workflows/code-review.md +515 -0
- package/.agent/skills/gsd/references/workflows/discuss-phase-power.md +3 -3
- package/.agent/skills/gsd/references/workflows/discuss-phase.md +20 -0
- package/.agent/skills/gsd/references/workflows/execute-phase.md +103 -0
- package/.agent/skills/gsd/references/workflows/explore.md +139 -0
- package/.agent/skills/gsd/references/workflows/import.md +274 -0
- package/.agent/skills/gsd/references/workflows/inbox.md +384 -0
- package/.agent/skills/gsd/references/workflows/manager.md +5 -5
- package/.agent/skills/gsd/references/workflows/new-milestone.md +1 -1
- package/.agent/skills/gsd/references/workflows/next.md +56 -0
- package/.agent/skills/gsd/references/workflows/plan-phase.md +48 -1
- package/.agent/skills/gsd/references/workflows/quick.md +96 -2
- package/.agent/skills/gsd/references/workflows/review.md +23 -3
- package/.agent/skills/gsd/references/workflows/scan.md +102 -0
- package/.agent/skills/gsd/references/workflows/settings.md +1 -1
- package/.agent/skills/gsd/references/workflows/ui-review.md +2 -2
- package/.agent/skills/gsd/references/workflows/undo.md +312 -0
- package/.agent/skills/gsd/references/workflows/update.md +5 -5
- package/.agent/skills/gsd-converter/SKILL.md +67 -59
- package/.agent/skills/gsd-converter/assets/migration-manifest.json +74 -0
- package/.agent/skills/gsd-converter/references/mapping.md +6 -16
- package/.agent/skills/gsd-converter/scripts/convert.py +419 -80
- package/.agent/skills/gsd-converter/scripts/regression_test.py +33 -0
- package/.agent/skills/selectpaste-update/SKILL.md +46 -0
- package/.agent/skills/selectpaste-update/scripts/sync-commands.py +317 -0
- package/README.md +4 -2
- package/bin/install.js +116 -116
- package/package.json +1 -1
- package/.agent/skills/gsd/references/commands/gsd-set-profile.md +0 -12
- /package/.agent/skills/gsd/references/commands/{gsd-tools.md → system/gsd-tools.md} +0 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learnings — Global knowledge store with CRUD operations
|
|
3
|
+
*
|
|
4
|
+
* Provides a cross-project learnings store at ~/.gsd/knowledge/.
|
|
5
|
+
* Each learning is stored as an individual JSON file with content-hash
|
|
6
|
+
* deduplication. Supports write, read, list, query, delete, copy-from-project,
|
|
7
|
+
* and prune operations.
|
|
8
|
+
*
|
|
9
|
+
* Storage format: { id, source_project, date, context, learning, tags, content_hash }
|
|
10
|
+
* File naming: {id}.json
|
|
11
|
+
* Deduplication: SHA-256 of learning text + source_project
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const crypto = require('crypto');
|
|
19
|
+
const os = require('os');
|
|
20
|
+
const { output, error: coreError } = require('./core.cjs');
|
|
21
|
+
|
|
22
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
const DEFAULT_STORE_DIR = path.join(os.homedir(), '.gsd', 'knowledge');
|
|
25
|
+
|
|
26
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the store directory, allowing override for testing.
|
|
30
|
+
* @param {object} [opts]
|
|
31
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
function getStoreDir(opts) {
|
|
35
|
+
return (opts && opts.storeDir) || DEFAULT_STORE_DIR;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Ensure the store directory exists. Created on first write, not on install.
|
|
40
|
+
* @param {string} dir
|
|
41
|
+
*/
|
|
42
|
+
function ensureStoreDir(dir) {
|
|
43
|
+
if (!fs.existsSync(dir)) {
|
|
44
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Generate a content hash for deduplication.
|
|
50
|
+
* Uses SHA-256 of learning text combined with source_project.
|
|
51
|
+
* @param {string} learning
|
|
52
|
+
* @param {string} sourceProject
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
function contentHash(learning, sourceProject) {
|
|
56
|
+
return crypto.createHash('sha256')
|
|
57
|
+
.update(learning + '\n' + sourceProject)
|
|
58
|
+
.digest('hex');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Generate a unique ID based on timestamp + random suffix.
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
65
|
+
function generateId() {
|
|
66
|
+
const ts = Date.now().toString(36);
|
|
67
|
+
const rand = crypto.randomBytes(4).toString('hex');
|
|
68
|
+
return `${ts}-${rand}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Read and parse a single learning JSON file.
|
|
73
|
+
* Returns null (with stderr warning) for malformed files.
|
|
74
|
+
* @param {string} filePath
|
|
75
|
+
* @returns {object|null}
|
|
76
|
+
*/
|
|
77
|
+
function readLearningFile(filePath) {
|
|
78
|
+
try {
|
|
79
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
80
|
+
return JSON.parse(content);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
process.stderr.write(`Warning: skipping malformed file ${filePath}: ${err.message}\n`);
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ─── CRUD Operations ─────────────────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Write a learning to the global store.
|
|
91
|
+
* Deduplicates by content hash — same content from same project is not stored twice.
|
|
92
|
+
*
|
|
93
|
+
* @param {object} entry
|
|
94
|
+
* @param {string} entry.source_project - Project name or path
|
|
95
|
+
* @param {string} entry.learning - The learning text
|
|
96
|
+
* @param {string} [entry.context] - Additional context
|
|
97
|
+
* @param {string[]} [entry.tags] - Tags for querying
|
|
98
|
+
* @param {object} [opts]
|
|
99
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
100
|
+
* @returns {{ id: string, created: boolean, content_hash: string }}
|
|
101
|
+
*/
|
|
102
|
+
function learningsWrite(entry, opts) {
|
|
103
|
+
const dir = getStoreDir(opts);
|
|
104
|
+
ensureStoreDir(dir);
|
|
105
|
+
|
|
106
|
+
const hash = contentHash(entry.learning, entry.source_project);
|
|
107
|
+
|
|
108
|
+
// Check for duplicate by scanning existing files
|
|
109
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
const existing = readLearningFile(path.join(dir, file));
|
|
112
|
+
if (existing && existing.content_hash === hash) {
|
|
113
|
+
return { id: existing.id, created: false, content_hash: hash };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const id = generateId();
|
|
118
|
+
const record = {
|
|
119
|
+
id,
|
|
120
|
+
source_project: entry.source_project,
|
|
121
|
+
date: new Date().toISOString(),
|
|
122
|
+
context: entry.context || '',
|
|
123
|
+
learning: entry.learning,
|
|
124
|
+
tags: entry.tags || [],
|
|
125
|
+
content_hash: hash,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
fs.writeFileSync(path.join(dir, `${id}.json`), JSON.stringify(record, null, 2), 'utf-8');
|
|
129
|
+
return { id, created: true, content_hash: hash };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Read a single learning by ID.
|
|
134
|
+
*
|
|
135
|
+
* @param {string} id
|
|
136
|
+
* @param {object} [opts]
|
|
137
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
138
|
+
* @returns {object|null}
|
|
139
|
+
*/
|
|
140
|
+
function learningsRead(id, opts) {
|
|
141
|
+
if (!/^[a-z0-9]+-[a-f0-9]+$/.test(id)) return null;
|
|
142
|
+
const dir = getStoreDir(opts);
|
|
143
|
+
const filePath = path.join(dir, `${id}.json`);
|
|
144
|
+
if (!fs.existsSync(filePath)) return null;
|
|
145
|
+
return readLearningFile(filePath);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* List all learnings, sorted by date (newest first).
|
|
150
|
+
*
|
|
151
|
+
* @param {object} [opts]
|
|
152
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
153
|
+
* @returns {object[]}
|
|
154
|
+
*/
|
|
155
|
+
function learningsList(opts) {
|
|
156
|
+
const dir = getStoreDir(opts);
|
|
157
|
+
if (!fs.existsSync(dir)) return [];
|
|
158
|
+
|
|
159
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
160
|
+
const results = [];
|
|
161
|
+
for (const file of files) {
|
|
162
|
+
const record = readLearningFile(path.join(dir, file));
|
|
163
|
+
if (record) results.push(record);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Sort by date descending (newest first)
|
|
167
|
+
results.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
168
|
+
return results;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Query learnings by tag.
|
|
173
|
+
*
|
|
174
|
+
* @param {object} query
|
|
175
|
+
* @param {string} [query.tag] - Tag to filter by
|
|
176
|
+
* @param {object} [opts]
|
|
177
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
178
|
+
* @returns {object[]}
|
|
179
|
+
*/
|
|
180
|
+
function learningsQuery(query, opts) {
|
|
181
|
+
const all = learningsList(opts);
|
|
182
|
+
if (query && query.tag) {
|
|
183
|
+
return all.filter(r => r.tags && r.tags.includes(query.tag));
|
|
184
|
+
}
|
|
185
|
+
return all;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Delete a learning by ID.
|
|
190
|
+
*
|
|
191
|
+
* @param {string} id
|
|
192
|
+
* @param {object} [opts]
|
|
193
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
194
|
+
* @returns {boolean} true if deleted, false if not found
|
|
195
|
+
*/
|
|
196
|
+
function learningsDelete(id, opts) {
|
|
197
|
+
if (!/^[a-z0-9]+-[a-f0-9]+$/.test(id)) return false;
|
|
198
|
+
const dir = getStoreDir(opts);
|
|
199
|
+
const filePath = path.join(dir, `${id}.json`);
|
|
200
|
+
if (!fs.existsSync(filePath)) return false;
|
|
201
|
+
fs.unlinkSync(filePath);
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Copy learnings from a project's LEARNINGS.md into the global store.
|
|
207
|
+
* Parses markdown sections as individual learnings. Deduplicates by content hash.
|
|
208
|
+
*
|
|
209
|
+
* Expected LEARNINGS.md format:
|
|
210
|
+
* ## Section Title
|
|
211
|
+
* Learning content paragraph(s)...
|
|
212
|
+
*
|
|
213
|
+
* ## Another Section
|
|
214
|
+
* More content...
|
|
215
|
+
*
|
|
216
|
+
* @param {string} planningDir - Path to .planning/ directory (or directory containing LEARNINGS.md)
|
|
217
|
+
* @param {object} [opts]
|
|
218
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
219
|
+
* @param {string} [opts.sourceProject] - Project name (defaults to directory basename)
|
|
220
|
+
* @returns {{ total: number, created: number, skipped: number }}
|
|
221
|
+
*/
|
|
222
|
+
function learningsCopyFromProject(planningDir, opts) {
|
|
223
|
+
const learningsPath = path.join(planningDir, 'LEARNINGS.md');
|
|
224
|
+
if (!fs.existsSync(learningsPath)) {
|
|
225
|
+
return { total: 0, created: 0, skipped: 0 };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const content = fs.readFileSync(learningsPath, 'utf-8');
|
|
229
|
+
const sourceProject = (opts && opts.sourceProject) || path.basename(path.resolve(planningDir, '..'));
|
|
230
|
+
|
|
231
|
+
// Parse markdown: split on ## headings
|
|
232
|
+
const sections = content.split(/^## /m).slice(1); // skip preamble before first ##
|
|
233
|
+
let created = 0;
|
|
234
|
+
let skipped = 0;
|
|
235
|
+
|
|
236
|
+
for (const section of sections) {
|
|
237
|
+
const lines = section.trim().split('\n');
|
|
238
|
+
const title = lines[0].trim();
|
|
239
|
+
const body = lines.slice(1).join('\n').trim();
|
|
240
|
+
if (!body) continue;
|
|
241
|
+
|
|
242
|
+
// Extract tags from title (simple: use words as tags)
|
|
243
|
+
const tags = title.toLowerCase().split(/\s+/).filter(w => w.length > 2);
|
|
244
|
+
|
|
245
|
+
const result = learningsWrite({
|
|
246
|
+
source_project: sourceProject,
|
|
247
|
+
learning: body,
|
|
248
|
+
context: title,
|
|
249
|
+
tags,
|
|
250
|
+
}, opts);
|
|
251
|
+
|
|
252
|
+
if (result.created) {
|
|
253
|
+
created++;
|
|
254
|
+
} else {
|
|
255
|
+
skipped++;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return { total: created + skipped, created, skipped };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Prune learnings older than a given threshold.
|
|
264
|
+
*
|
|
265
|
+
* @param {string} olderThan - Duration string like "90d", "30d", "7d"
|
|
266
|
+
* @param {object} [opts]
|
|
267
|
+
* @param {string} [opts.storeDir] - Override store directory
|
|
268
|
+
* @returns {{ removed: number, kept: number }}
|
|
269
|
+
*/
|
|
270
|
+
function learningsPrune(olderThan, opts) {
|
|
271
|
+
const match = /^(\d+)d$/.exec(olderThan);
|
|
272
|
+
if (!match) {
|
|
273
|
+
throw new Error(`Invalid duration format: "${olderThan}" — expected format like "90d"`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const days = parseInt(match[1], 10);
|
|
277
|
+
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
278
|
+
const dir = getStoreDir(opts);
|
|
279
|
+
|
|
280
|
+
if (!fs.existsSync(dir)) return { removed: 0, kept: 0 };
|
|
281
|
+
|
|
282
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
283
|
+
let removed = 0;
|
|
284
|
+
let kept = 0;
|
|
285
|
+
|
|
286
|
+
for (const file of files) {
|
|
287
|
+
const filePath = path.join(dir, file);
|
|
288
|
+
const record = readLearningFile(filePath);
|
|
289
|
+
if (!record) continue;
|
|
290
|
+
|
|
291
|
+
const recordDate = new Date(record.date);
|
|
292
|
+
if (recordDate < cutoff) {
|
|
293
|
+
fs.unlinkSync(filePath);
|
|
294
|
+
removed++;
|
|
295
|
+
} else {
|
|
296
|
+
kept++;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return { removed, kept };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ─── CLI Command Handlers ────────────────────────────────────────────────────
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Handle `gsd-tools learnings list`
|
|
307
|
+
* @param {boolean} raw - Raw output flag
|
|
308
|
+
*/
|
|
309
|
+
function cmdLearningsList(raw) {
|
|
310
|
+
const results = learningsList();
|
|
311
|
+
output({ learnings: results, count: results.length }, raw);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Handle `gsd-tools learnings query --tag <tag>`
|
|
316
|
+
* @param {string} tag
|
|
317
|
+
* @param {boolean} raw - Raw output flag
|
|
318
|
+
*/
|
|
319
|
+
function cmdLearningsQuery(tag, raw) {
|
|
320
|
+
const results = learningsQuery({ tag });
|
|
321
|
+
output({ learnings: results, count: results.length, tag }, raw);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Handle `gsd-tools learnings copy`
|
|
326
|
+
* @param {string} cwd - Current working directory
|
|
327
|
+
* @param {boolean} raw - Raw output flag
|
|
328
|
+
*/
|
|
329
|
+
function cmdLearningsCopy(cwd, raw) {
|
|
330
|
+
const planningDir = path.join(cwd, '.planning');
|
|
331
|
+
const result = learningsCopyFromProject(planningDir);
|
|
332
|
+
output(result, raw);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Handle `gsd-tools learnings prune --older-than <duration>`
|
|
337
|
+
* @param {string} olderThan - Duration string like "90d"
|
|
338
|
+
* @param {boolean} raw - Raw output flag
|
|
339
|
+
*/
|
|
340
|
+
function cmdLearningsPrune(olderThan, raw) {
|
|
341
|
+
try {
|
|
342
|
+
const result = learningsPrune(olderThan);
|
|
343
|
+
output(result, raw);
|
|
344
|
+
} catch (err) {
|
|
345
|
+
coreError(err.message);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Handle `gsd-tools learnings delete <id>`
|
|
351
|
+
* @param {string} id
|
|
352
|
+
* @param {boolean} raw - Raw output flag
|
|
353
|
+
*/
|
|
354
|
+
function cmdLearningsDelete(id, raw) {
|
|
355
|
+
if (!/^[a-z0-9]+-[a-f0-9]+$/.test(id)) {
|
|
356
|
+
coreError(`Invalid learning ID: "${id}"`);
|
|
357
|
+
}
|
|
358
|
+
const deleted = learningsDelete(id);
|
|
359
|
+
output({ id, deleted }, raw);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ─── Exports ─────────────────────────────────────────────────────────────────
|
|
363
|
+
|
|
364
|
+
module.exports = {
|
|
365
|
+
learningsWrite,
|
|
366
|
+
learningsRead,
|
|
367
|
+
learningsList,
|
|
368
|
+
learningsQuery,
|
|
369
|
+
learningsDelete,
|
|
370
|
+
learningsCopyFromProject,
|
|
371
|
+
learningsPrune,
|
|
372
|
+
cmdLearningsList,
|
|
373
|
+
cmdLearningsQuery,
|
|
374
|
+
cmdLearningsCopy,
|
|
375
|
+
cmdLearningsPrune,
|
|
376
|
+
cmdLearningsDelete,
|
|
377
|
+
DEFAULT_STORE_DIR,
|
|
378
|
+
};
|
|
@@ -246,15 +246,24 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
|
|
|
246
246
|
output(result, raw);
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
function cmdPhasesClear(cwd, raw) {
|
|
249
|
+
function cmdPhasesClear(cwd, raw, args) {
|
|
250
250
|
const phasesDir = planningPaths(cwd).phases;
|
|
251
|
+
const confirm = Array.isArray(args) && args.includes('--confirm');
|
|
251
252
|
let cleared = 0;
|
|
252
253
|
|
|
253
254
|
if (fs.existsSync(phasesDir)) {
|
|
255
|
+
const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
256
|
+
const dirs = entries.filter(e => e.isDirectory() && !/^999(?:\.|$)/.test(e.name));
|
|
257
|
+
|
|
258
|
+
if (dirs.length > 0 && !confirm) {
|
|
259
|
+
error(
|
|
260
|
+
`phases clear would delete ${dirs.length} phase director${dirs.length === 1 ? 'y' : 'ies'}. ` +
|
|
261
|
+
`Pass --confirm to proceed.`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
254
265
|
try {
|
|
255
|
-
const
|
|
256
|
-
for (const entry of entries) {
|
|
257
|
-
if (!entry.isDirectory()) continue;
|
|
266
|
+
for (const entry of dirs) {
|
|
258
267
|
fs.rmSync(path.join(phasesDir, entry.name), { recursive: true, force: true });
|
|
259
268
|
cleared++;
|
|
260
269
|
}
|
|
@@ -7,23 +7,23 @@
|
|
|
7
7
|
* would be faster, use fewer tokens, and be less error-prone).
|
|
8
8
|
*/
|
|
9
9
|
const MODEL_PROFILES = {
|
|
10
|
-
'gsd-planner': { quality: 'opus', balanced: 'opus', budget: 'sonnet' },
|
|
11
|
-
'gsd-roadmapper': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
|
|
12
|
-
'gsd-executor': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
|
|
13
|
-
'gsd-phase-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
|
|
14
|
-
'gsd-project-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
|
|
15
|
-
'gsd-research-synthesizer': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
16
|
-
'gsd-debugger': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
|
|
17
|
-
'gsd-codebase-mapper': { quality: 'sonnet', balanced: 'haiku', budget: 'haiku' },
|
|
18
|
-
'gsd-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
19
|
-
'gsd-plan-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
20
|
-
'gsd-integration-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
21
|
-
'gsd-nyquist-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
22
|
-
'gsd-ui-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
|
|
23
|
-
'gsd-ui-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
24
|
-
'gsd-ui-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
25
|
-
'gsd-doc-writer': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
|
|
26
|
-
'gsd-doc-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
|
|
10
|
+
'gsd-planner': { quality: 'opus', balanced: 'opus', budget: 'sonnet', adaptive: 'opus' },
|
|
11
|
+
'gsd-roadmapper': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet', adaptive: 'sonnet' },
|
|
12
|
+
'gsd-executor': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet', adaptive: 'sonnet' },
|
|
13
|
+
'gsd-phase-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku', adaptive: 'sonnet' },
|
|
14
|
+
'gsd-project-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku', adaptive: 'sonnet' },
|
|
15
|
+
'gsd-research-synthesizer': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
16
|
+
'gsd-debugger': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet', adaptive: 'opus' },
|
|
17
|
+
'gsd-codebase-mapper': { quality: 'sonnet', balanced: 'haiku', budget: 'haiku', adaptive: 'haiku' },
|
|
18
|
+
'gsd-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'sonnet' },
|
|
19
|
+
'gsd-plan-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
20
|
+
'gsd-integration-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
21
|
+
'gsd-nyquist-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
22
|
+
'gsd-ui-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku', adaptive: 'sonnet' },
|
|
23
|
+
'gsd-ui-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
24
|
+
'gsd-ui-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
25
|
+
'gsd-doc-writer': { quality: 'opus', balanced: 'sonnet', budget: 'haiku', adaptive: 'sonnet' },
|
|
26
|
+
'gsd-doc-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku', adaptive: 'haiku' },
|
|
27
27
|
};
|
|
28
28
|
const VALID_PROFILES = Object.keys(MODEL_PROFILES['gsd-planner']);
|
|
29
29
|
|
|
@@ -121,7 +121,7 @@ const PROFILING_QUESTIONS = [
|
|
|
121
121
|
},
|
|
122
122
|
];
|
|
123
123
|
|
|
124
|
-
const
|
|
124
|
+
const ANTIGRAVITY_INSTRUCTIONS = {
|
|
125
125
|
communication_style: {
|
|
126
126
|
'terse-direct': 'Keep responses concise and action-oriented. Skip lengthy preambles. Match this developer\'s direct style.',
|
|
127
127
|
'conversational': 'Use a natural conversational tone. Explain reasoning briefly alongside code. Engage with the developer\'s questions.',
|
|
@@ -172,7 +172,7 @@ const CLAUDE_INSTRUCTIONS = {
|
|
|
172
172
|
},
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
const
|
|
175
|
+
const ANTIGRAVITY_MD_FALLBACKS = {
|
|
176
176
|
project: 'Project not yet initialized. Run /gsd-new-project to set up.',
|
|
177
177
|
stack: 'Technology stack not yet documented. Will populate after codebase mapping or first phase.',
|
|
178
178
|
conventions: 'Conventions not yet established. Will populate as patterns emerge during development.',
|
|
@@ -183,7 +183,7 @@ const CLAUDE_MD_FALLBACKS = {
|
|
|
183
183
|
// Directories where project skills may live (checked in order)
|
|
184
184
|
const SKILL_SEARCH_DIRS = ['.antigravity/skills', '.agents/skills', '.cursor/skills', '.github/skills'];
|
|
185
185
|
|
|
186
|
-
const
|
|
186
|
+
const ANTIGRAVITY_MD_WORKFLOW_ENFORCEMENT = [
|
|
187
187
|
'Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.',
|
|
188
188
|
'',
|
|
189
189
|
'Use these entry points:',
|
|
@@ -194,7 +194,7 @@ const CLAUDE_MD_WORKFLOW_ENFORCEMENT = [
|
|
|
194
194
|
'Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.',
|
|
195
195
|
].join('\n');
|
|
196
196
|
|
|
197
|
-
const
|
|
197
|
+
const ANTIGRAVITY_MD_PROFILE_PLACEHOLDER = [
|
|
198
198
|
'<!-- GSD:profile-start -->',
|
|
199
199
|
'## Developer Profile',
|
|
200
200
|
'',
|
|
@@ -214,8 +214,8 @@ function isAmbiguousAnswer(dimension, value) {
|
|
|
214
214
|
return option.rating === 'mixed';
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
function
|
|
218
|
-
const dimInstructions =
|
|
217
|
+
function generateAntigravityInstruction(dimension, rating) {
|
|
218
|
+
const dimInstructions = ANTIGRAVITY_INSTRUCTIONS[dimension];
|
|
219
219
|
if (dimInstructions && dimInstructions[rating]) {
|
|
220
220
|
return dimInstructions[rating];
|
|
221
221
|
}
|
|
@@ -285,7 +285,7 @@ function generateProjectSection(cwd) {
|
|
|
285
285
|
const projectPath = path.join(cwd, '.planning', 'PROJECT.md');
|
|
286
286
|
const content = safeReadFile(projectPath);
|
|
287
287
|
if (!content) {
|
|
288
|
-
return { content:
|
|
288
|
+
return { content: ANTIGRAVITY_MD_FALLBACKS.project, source: 'PROJECT.md', hasFallback: true };
|
|
289
289
|
}
|
|
290
290
|
const parts = [];
|
|
291
291
|
const h1Match = content.match(/^# (.+)$/m);
|
|
@@ -306,7 +306,7 @@ function generateProjectSection(cwd) {
|
|
|
306
306
|
if (body) parts.push(`### Constraints\n\n${body}`);
|
|
307
307
|
}
|
|
308
308
|
if (parts.length === 0) {
|
|
309
|
-
return { content:
|
|
309
|
+
return { content: ANTIGRAVITY_MD_FALLBACKS.project, source: 'PROJECT.md', hasFallback: true };
|
|
310
310
|
}
|
|
311
311
|
return { content: parts.join('\n\n'), source: 'PROJECT.md', hasFallback: false };
|
|
312
312
|
}
|
|
@@ -321,7 +321,7 @@ function generateStackSection(cwd) {
|
|
|
321
321
|
source = 'research/STACK.md';
|
|
322
322
|
}
|
|
323
323
|
if (!content) {
|
|
324
|
-
return { content:
|
|
324
|
+
return { content: ANTIGRAVITY_MD_FALLBACKS.stack, source: 'STACK.md', hasFallback: true };
|
|
325
325
|
}
|
|
326
326
|
const lines = content.split('\n');
|
|
327
327
|
const summaryLines = [];
|
|
@@ -343,7 +343,7 @@ function generateConventionsSection(cwd) {
|
|
|
343
343
|
const conventionsPath = path.join(cwd, '.planning', 'codebase', 'CONVENTIONS.md');
|
|
344
344
|
const content = safeReadFile(conventionsPath);
|
|
345
345
|
if (!content) {
|
|
346
|
-
return { content:
|
|
346
|
+
return { content: ANTIGRAVITY_MD_FALLBACKS.conventions, source: 'CONVENTIONS.md', hasFallback: true };
|
|
347
347
|
}
|
|
348
348
|
const lines = content.split('\n');
|
|
349
349
|
const summaryLines = [];
|
|
@@ -359,7 +359,7 @@ function generateArchitectureSection(cwd) {
|
|
|
359
359
|
const architecturePath = path.join(cwd, '.planning', 'codebase', 'ARCHITECTURE.md');
|
|
360
360
|
const content = safeReadFile(architecturePath);
|
|
361
361
|
if (!content) {
|
|
362
|
-
return { content:
|
|
362
|
+
return { content: ANTIGRAVITY_MD_FALLBACKS.architecture, source: 'ARCHITECTURE.md', hasFallback: true };
|
|
363
363
|
}
|
|
364
364
|
const lines = content.split('\n');
|
|
365
365
|
const summaryLines = [];
|
|
@@ -373,7 +373,7 @@ function generateArchitectureSection(cwd) {
|
|
|
373
373
|
|
|
374
374
|
function generateWorkflowSection() {
|
|
375
375
|
return {
|
|
376
|
-
content:
|
|
376
|
+
content: ANTIGRAVITY_MD_WORKFLOW_ENFORCEMENT,
|
|
377
377
|
source: 'GSD defaults',
|
|
378
378
|
hasFallback: false,
|
|
379
379
|
};
|
|
@@ -421,7 +421,7 @@ function generateSkillsSection(cwd) {
|
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
if (discovered.length === 0) {
|
|
424
|
-
return { content:
|
|
424
|
+
return { content: ANTIGRAVITY_MD_FALLBACKS.skills, source: 'skills/', hasFallback: true };
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
const lines = ['| Skill | Description | Path |', '|-------|-------------|------|'];
|
|
@@ -565,10 +565,10 @@ function cmdWriteProfile(cwd, options, raw) {
|
|
|
565
565
|
if (conf === 'HIGH' || conf === 'MEDIUM' || conf === 'LOW') dimensionsScored++;
|
|
566
566
|
if (conf === 'HIGH') {
|
|
567
567
|
highCount++;
|
|
568
|
-
if (dim.
|
|
568
|
+
if (dim.antigravity_instruction) summaryLines.push(`- **${dimensionLabels[dimKey] || dimKey}:** ${dim.antigravity_instruction} (HIGH)`);
|
|
569
569
|
} else if (conf === 'MEDIUM') {
|
|
570
570
|
mediumCount++;
|
|
571
|
-
if (dim.
|
|
571
|
+
if (dim.antigravity_instruction) summaryLines.push(`- **${dimensionLabels[dimKey] || dimKey}:** ${dim.antigravity_instruction} (MEDIUM)`);
|
|
572
572
|
} else if (conf === 'LOW') {
|
|
573
573
|
lowCount++;
|
|
574
574
|
}
|
|
@@ -596,7 +596,7 @@ function cmdWriteProfile(cwd, options, raw) {
|
|
|
596
596
|
const dim = analysis.dimensions[dimKey] || {};
|
|
597
597
|
const rating = dim.rating || 'UNSCORED';
|
|
598
598
|
const confidence = dim.confidence || 'UNSCORED';
|
|
599
|
-
const instruction = dim.
|
|
599
|
+
const instruction = dim.antigravity_instruction || 'No strong preference detected. Ask the developer when this dimension is relevant.';
|
|
600
600
|
const summary = dim.summary || '';
|
|
601
601
|
|
|
602
602
|
let evidenceBlock = '';
|
|
@@ -615,7 +615,7 @@ function cmdWriteProfile(cwd, options, raw) {
|
|
|
615
615
|
|
|
616
616
|
template = template.replace(new RegExp(`\\{\\{${dimKey}\\.rating\\}\\}`, 'g'), rating);
|
|
617
617
|
template = template.replace(new RegExp(`\\{\\{${dimKey}\\.confidence\\}\\}`, 'g'), confidence);
|
|
618
|
-
template = template.replace(new RegExp(`\\{\\{${dimKey}\\.
|
|
618
|
+
template = template.replace(new RegExp(`\\{\\{${dimKey}\\.antigravity_instruction\\}\\}`, 'g'), instruction);
|
|
619
619
|
template = template.replace(new RegExp(`\\{\\{${dimKey}\\.summary\\}\\}`, 'g'), summary);
|
|
620
620
|
template = template.replace(new RegExp(`\\{\\{${dimKey}\\.evidence\\}\\}`, 'g'), evidenceBlock);
|
|
621
621
|
}
|
|
@@ -697,7 +697,7 @@ function cmdProfileQuestionnaire(options, raw) {
|
|
|
697
697
|
project: 'N/A (questionnaire)',
|
|
698
698
|
}],
|
|
699
699
|
summary: `Developer self-reported as ${selectedOption.rating} for ${question.header.toLowerCase()}.`,
|
|
700
|
-
|
|
700
|
+
antigravity_instruction: generateAntigravityInstruction(question.dimension, selectedOption.rating),
|
|
701
701
|
};
|
|
702
702
|
}
|
|
703
703
|
|
|
@@ -745,9 +745,9 @@ function cmdGenerateDevPreferences(cwd, options, raw) {
|
|
|
745
745
|
if (!dim) continue;
|
|
746
746
|
const label = devPrefLabels[dimKey] || dimKey;
|
|
747
747
|
const confidence = dim.confidence || 'UNSCORED';
|
|
748
|
-
let instruction = dim.
|
|
748
|
+
let instruction = dim.antigravity_instruction;
|
|
749
749
|
if (!instruction) {
|
|
750
|
-
const lookup =
|
|
750
|
+
const lookup = ANTIGRAVITY_INSTRUCTIONS[dimKey];
|
|
751
751
|
if (lookup && dim.rating && lookup[dim.rating]) {
|
|
752
752
|
instruction = lookup[dim.rating];
|
|
753
753
|
} else {
|
|
@@ -793,7 +793,7 @@ function cmdGenerateDevPreferences(cwd, options, raw) {
|
|
|
793
793
|
output(result, raw);
|
|
794
794
|
}
|
|
795
795
|
|
|
796
|
-
function
|
|
796
|
+
function cmdGenerateAntigravityProfile(cwd, options, raw) {
|
|
797
797
|
if (!options.analysis) error('--analysis <path> is required');
|
|
798
798
|
|
|
799
799
|
let analysisPath = options.analysis;
|
|
@@ -834,9 +834,9 @@ function cmdGenerateClaudeProfile(cwd, options, raw) {
|
|
|
834
834
|
const rating = dim.rating || 'UNSCORED';
|
|
835
835
|
const confidence = dim.confidence || 'UNSCORED';
|
|
836
836
|
tableRows.push(`| ${label} | ${rating} | ${confidence} |`);
|
|
837
|
-
let instruction = dim.
|
|
837
|
+
let instruction = dim.antigravity_instruction;
|
|
838
838
|
if (!instruction) {
|
|
839
|
-
const lookup =
|
|
839
|
+
const lookup = ANTIGRAVITY_INSTRUCTIONS[dimKey];
|
|
840
840
|
if (lookup && dim.rating && lookup[dim.rating]) {
|
|
841
841
|
instruction = lookup[dim.rating];
|
|
842
842
|
} else {
|
|
@@ -899,7 +899,7 @@ function cmdGenerateClaudeProfile(cwd, options, raw) {
|
|
|
899
899
|
}
|
|
900
900
|
|
|
901
901
|
const result = {
|
|
902
|
-
|
|
902
|
+
antigravity_md_path: targetPath,
|
|
903
903
|
action,
|
|
904
904
|
dimensions_included: dimensionsIncluded,
|
|
905
905
|
is_global: !!options.global,
|
|
@@ -908,7 +908,7 @@ function cmdGenerateClaudeProfile(cwd, options, raw) {
|
|
|
908
908
|
output(result, raw);
|
|
909
909
|
}
|
|
910
910
|
|
|
911
|
-
function
|
|
911
|
+
function cmdGenerateAntigravityMd(cwd, options, raw) {
|
|
912
912
|
const MANAGED_SECTIONS = ['project', 'stack', 'conventions', 'architecture', 'skills', 'workflow'];
|
|
913
913
|
const generators = {
|
|
914
914
|
project: generateProjectSection,
|
|
@@ -961,7 +961,7 @@ function cmdGenerateClaudeMd(cwd, options, raw) {
|
|
|
961
961
|
sections.push(buildSection(name, gen.source, body));
|
|
962
962
|
}
|
|
963
963
|
sections.push('');
|
|
964
|
-
sections.push(
|
|
964
|
+
sections.push(ANTIGRAVITY_MD_PROFILE_PLACEHOLDER);
|
|
965
965
|
existingContent = sections.join('\n\n') + '\n';
|
|
966
966
|
action = 'created';
|
|
967
967
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
@@ -998,7 +998,7 @@ function cmdGenerateClaudeMd(cwd, options, raw) {
|
|
|
998
998
|
}
|
|
999
999
|
|
|
1000
1000
|
if (!options.auto && fileContent.indexOf('<!-- GSD:profile-start') === -1) {
|
|
1001
|
-
fileContent = fileContent.trimEnd() + '\n\n' +
|
|
1001
|
+
fileContent = fileContent.trimEnd() + '\n\n' + ANTIGRAVITY_MD_PROFILE_PLACEHOLDER + '\n';
|
|
1002
1002
|
}
|
|
1003
1003
|
|
|
1004
1004
|
fs.writeFileSync(outputPath, fileContent, 'utf-8');
|
|
@@ -1024,7 +1024,7 @@ function cmdGenerateClaudeMd(cwd, options, raw) {
|
|
|
1024
1024
|
if (profileStatus === 'placeholder_added') message += ' Run /gsd-profile-user to unlock Developer Profile.';
|
|
1025
1025
|
|
|
1026
1026
|
const result = {
|
|
1027
|
-
|
|
1027
|
+
antigravity_md_path: outputPath,
|
|
1028
1028
|
action,
|
|
1029
1029
|
sections_generated: sectionsGenerated,
|
|
1030
1030
|
sections_fallback: sectionsFallback,
|
|
@@ -1041,8 +1041,8 @@ module.exports = {
|
|
|
1041
1041
|
cmdWriteProfile,
|
|
1042
1042
|
cmdProfileQuestionnaire,
|
|
1043
1043
|
cmdGenerateDevPreferences,
|
|
1044
|
-
|
|
1045
|
-
|
|
1044
|
+
cmdGenerateAntigravityProfile,
|
|
1045
|
+
cmdGenerateAntigravityMd,
|
|
1046
1046
|
PROFILING_QUESTIONS,
|
|
1047
|
-
|
|
1047
|
+
ANTIGRAVITY_INSTRUCTIONS,
|
|
1048
1048
|
};
|