logicstamp-context 0.1.1 → 0.2.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/LLM_CONTEXT.md +4 -3
- package/README.md +116 -19
- package/dist/cli/commands/compare.d.ts.map +1 -1
- package/dist/cli/commands/compare.js +17 -8
- package/dist/cli/commands/compare.js.map +1 -1
- package/dist/cli/commands/context/bundleFormatter.d.ts +20 -0
- package/dist/cli/commands/context/bundleFormatter.d.ts.map +1 -0
- package/dist/cli/commands/context/bundleFormatter.js +55 -0
- package/dist/cli/commands/context/bundleFormatter.js.map +1 -0
- package/dist/cli/commands/context/configManager.d.ts +23 -0
- package/dist/cli/commands/context/configManager.d.ts.map +1 -0
- package/dist/cli/commands/context/configManager.js +69 -0
- package/dist/cli/commands/context/configManager.js.map +1 -0
- package/dist/cli/commands/context/contractBuilder.d.ts +18 -0
- package/dist/cli/commands/context/contractBuilder.d.ts.map +1 -0
- package/dist/cli/commands/context/contractBuilder.js +72 -0
- package/dist/cli/commands/context/contractBuilder.js.map +1 -0
- package/dist/cli/commands/context/fileWriter.d.ts +38 -0
- package/dist/cli/commands/context/fileWriter.d.ts.map +1 -0
- package/dist/cli/commands/context/fileWriter.js +165 -0
- package/dist/cli/commands/context/fileWriter.js.map +1 -0
- package/dist/cli/commands/context/statsCalculator.d.ts +44 -0
- package/dist/cli/commands/context/statsCalculator.d.ts.map +1 -0
- package/dist/cli/commands/context/statsCalculator.js +150 -0
- package/dist/cli/commands/context/statsCalculator.js.map +1 -0
- package/dist/cli/commands/context/tokenEstimator.d.ts +76 -0
- package/dist/cli/commands/context/tokenEstimator.d.ts.map +1 -0
- package/dist/cli/commands/context/tokenEstimator.js +258 -0
- package/dist/cli/commands/context/tokenEstimator.js.map +1 -0
- package/dist/cli/commands/context.d.ts +1 -0
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +72 -399
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/style.d.ts +11 -0
- package/dist/cli/commands/style.d.ts.map +1 -0
- package/dist/cli/commands/style.js +15 -0
- package/dist/cli/commands/style.js.map +1 -0
- package/dist/cli/handlers/cleanHandler.d.ts +5 -0
- package/dist/cli/handlers/cleanHandler.d.ts.map +1 -0
- package/dist/cli/handlers/cleanHandler.js +28 -0
- package/dist/cli/handlers/cleanHandler.js.map +1 -0
- package/dist/cli/handlers/compareHandler.d.ts +5 -0
- package/dist/cli/handlers/compareHandler.d.ts.map +1 -0
- package/dist/cli/handlers/compareHandler.js +332 -0
- package/dist/cli/handlers/compareHandler.js.map +1 -0
- package/dist/cli/handlers/contextHandler.d.ts +5 -0
- package/dist/cli/handlers/contextHandler.d.ts.map +1 -0
- package/dist/cli/handlers/contextHandler.js +24 -0
- package/dist/cli/handlers/contextHandler.js.map +1 -0
- package/dist/cli/handlers/initHandler.d.ts +6 -0
- package/dist/cli/handlers/initHandler.d.ts.map +1 -0
- package/dist/cli/handlers/initHandler.js +30 -0
- package/dist/cli/handlers/initHandler.js.map +1 -0
- package/dist/cli/handlers/styleHandler.d.ts +5 -0
- package/dist/cli/handlers/styleHandler.d.ts.map +1 -0
- package/dist/cli/handlers/styleHandler.js +30 -0
- package/dist/cli/handlers/styleHandler.js.map +1 -0
- package/dist/cli/handlers/validateHandler.d.ts +5 -0
- package/dist/cli/handlers/validateHandler.d.ts.map +1 -0
- package/dist/cli/handlers/validateHandler.js +23 -0
- package/dist/cli/handlers/validateHandler.js.map +1 -0
- package/dist/cli/parser/argumentParser.d.ts +44 -0
- package/dist/cli/parser/argumentParser.d.ts.map +1 -0
- package/dist/cli/parser/argumentParser.js +194 -0
- package/dist/cli/parser/argumentParser.js.map +1 -0
- package/dist/cli/parser/helpText.d.ts +11 -0
- package/dist/cli/parser/helpText.d.ts.map +1 -0
- package/dist/cli/parser/helpText.js +373 -0
- package/dist/cli/parser/helpText.js.map +1 -0
- package/dist/cli/stamp.js +14 -821
- package/dist/cli/stamp.js.map +1 -1
- package/dist/core/astParser/detectors.d.ts +24 -0
- package/dist/core/astParser/detectors.d.ts.map +1 -0
- package/dist/core/astParser/detectors.js +102 -0
- package/dist/core/astParser/detectors.js.map +1 -0
- package/dist/core/astParser/extractors/componentExtractor.d.ts +13 -0
- package/dist/core/astParser/extractors/componentExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/componentExtractor.js +41 -0
- package/dist/core/astParser/extractors/componentExtractor.js.map +1 -0
- package/dist/core/astParser/extractors/eventExtractor.d.ts +14 -0
- package/dist/core/astParser/extractors/eventExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/eventExtractor.js +49 -0
- package/dist/core/astParser/extractors/eventExtractor.js.map +1 -0
- package/dist/core/astParser/extractors/propExtractor.d.ts +14 -0
- package/dist/core/astParser/extractors/propExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/propExtractor.js +73 -0
- package/dist/core/astParser/extractors/propExtractor.js.map +1 -0
- package/dist/core/astParser/extractors/stateExtractor.d.ts +13 -0
- package/dist/core/astParser/extractors/stateExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/stateExtractor.js +66 -0
- package/dist/core/astParser/extractors/stateExtractor.js.map +1 -0
- package/dist/core/astParser.d.ts.map +1 -1
- package/dist/core/astParser.js +5 -307
- package/dist/core/astParser.js.map +1 -1
- package/dist/core/contractBuilder.d.ts +1 -0
- package/dist/core/contractBuilder.d.ts.map +1 -1
- package/dist/core/contractBuilder.js +1 -0
- package/dist/core/contractBuilder.js.map +1 -1
- package/dist/core/pack/builder.d.ts +35 -0
- package/dist/core/pack/builder.d.ts.map +1 -0
- package/dist/core/pack/builder.js +76 -0
- package/dist/core/pack/builder.js.map +1 -0
- package/dist/core/pack/collector.d.ts +20 -0
- package/dist/core/pack/collector.d.ts.map +1 -0
- package/dist/core/pack/collector.js +71 -0
- package/dist/core/pack/collector.js.map +1 -0
- package/dist/core/pack/loader.d.ts +23 -0
- package/dist/core/pack/loader.d.ts.map +1 -0
- package/dist/core/pack/loader.js +66 -0
- package/dist/core/pack/loader.js.map +1 -0
- package/dist/core/pack/resolver.d.ts +21 -0
- package/dist/core/pack/resolver.d.ts.map +1 -0
- package/dist/core/pack/resolver.js +79 -0
- package/dist/core/pack/resolver.js.map +1 -0
- package/dist/core/pack.d.ts +17 -27
- package/dist/core/pack.d.ts.map +1 -1
- package/dist/core/pack.js +18 -225
- package/dist/core/pack.js.map +1 -1
- package/dist/core/styleExtractor/index.d.ts +11 -0
- package/dist/core/styleExtractor/index.d.ts.map +1 -0
- package/dist/core/styleExtractor/index.js +11 -0
- package/dist/core/styleExtractor/index.js.map +1 -0
- package/dist/core/styleExtractor/layout.d.ts +14 -0
- package/dist/core/styleExtractor/layout.d.ts.map +1 -0
- package/dist/core/styleExtractor/layout.js +86 -0
- package/dist/core/styleExtractor/layout.js.map +1 -0
- package/dist/core/styleExtractor/motion.d.ts +20 -0
- package/dist/core/styleExtractor/motion.d.ts.map +1 -0
- package/dist/core/styleExtractor/motion.js +74 -0
- package/dist/core/styleExtractor/motion.js.map +1 -0
- package/dist/core/styleExtractor/scss.d.ts +30 -0
- package/dist/core/styleExtractor/scss.d.ts.map +1 -0
- package/dist/core/styleExtractor/scss.js +80 -0
- package/dist/core/styleExtractor/scss.js.map +1 -0
- package/dist/core/styleExtractor/styleExtractor.d.ts +11 -0
- package/dist/core/styleExtractor/styleExtractor.d.ts.map +1 -0
- package/dist/core/styleExtractor/styleExtractor.js +115 -0
- package/dist/core/styleExtractor/styleExtractor.js.map +1 -0
- package/dist/core/styleExtractor/styled.d.ts +13 -0
- package/dist/core/styleExtractor/styled.d.ts.map +1 -0
- package/dist/core/styleExtractor/styled.js +31 -0
- package/dist/core/styleExtractor/styled.js.map +1 -0
- package/dist/core/styleExtractor/tailwind.d.ts +16 -0
- package/dist/core/styleExtractor/tailwind.d.ts.map +1 -0
- package/dist/core/styleExtractor/tailwind.js +85 -0
- package/dist/core/styleExtractor/tailwind.js.map +1 -0
- package/dist/core/styleExtractor.d.ts +8 -0
- package/dist/core/styleExtractor.d.ts.map +1 -0
- package/dist/core/styleExtractor.js +8 -0
- package/dist/core/styleExtractor.js.map +1 -0
- package/dist/types/UIFContract.d.ts +71 -0
- package/dist/types/UIFContract.d.ts.map +1 -1
- package/dist/types/UIFContract.js.map +1 -1
- package/dist/utils/tokens.d.ts +18 -10
- package/dist/utils/tokens.d.ts.map +1 -1
- package/dist/utils/tokens.js +112 -10
- package/dist/utils/tokens.js.map +1 -1
- package/package.json +3 -1
- package/schema/logicstamp.context.schema.json +288 -0
package/dist/cli/stamp.js
CHANGED
|
@@ -3,22 +3,17 @@
|
|
|
3
3
|
* Stamp CLI - Main entry point for LogicStamp Context tools
|
|
4
4
|
* Routes to context operations: generate, validate, compare
|
|
5
5
|
*/
|
|
6
|
-
import { contextCommand } from './commands/context.js';
|
|
7
|
-
import { compareCommand, multiFileCompare, displayMultiFileCompareResult, cleanOrphanedFiles, } from './commands/compare.js';
|
|
8
|
-
import { validateCommand } from './commands/validate.js';
|
|
9
|
-
import { init } from './commands/init.js';
|
|
10
|
-
import { cleanCommand } from './commands/clean.js';
|
|
11
6
|
import { readFile } from 'node:fs/promises';
|
|
12
7
|
import { join, dirname } from 'node:path';
|
|
13
8
|
import { fileURLToPath } from 'node:url';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
9
|
+
import { handleInit } from './handlers/initHandler.js';
|
|
10
|
+
import { handleValidate } from './handlers/validateHandler.js';
|
|
11
|
+
import { handleCompare } from './handlers/compareHandler.js';
|
|
12
|
+
import { handleClean } from './handlers/cleanHandler.js';
|
|
13
|
+
import { handleStyle } from './handlers/styleHandler.js';
|
|
14
|
+
import { handleGenerate } from './handlers/contextHandler.js';
|
|
15
|
+
import { getMainHelp } from './parser/helpText.js';
|
|
16
|
+
import { printFoxIcon } from './handlers/initHandler.js';
|
|
22
17
|
async function main() {
|
|
23
18
|
const args = process.argv.slice(2);
|
|
24
19
|
// Check for version
|
|
@@ -41,7 +36,7 @@ async function main() {
|
|
|
41
36
|
// Check for help - only if no args or first arg is help
|
|
42
37
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
43
38
|
printFoxIcon();
|
|
44
|
-
|
|
39
|
+
console.log(getMainHelp());
|
|
45
40
|
process.exit(0);
|
|
46
41
|
}
|
|
47
42
|
// First argument should be the subcommand
|
|
@@ -71,815 +66,13 @@ async function main() {
|
|
|
71
66
|
await handleClean(contextArgs.slice(1));
|
|
72
67
|
return;
|
|
73
68
|
}
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
async function handleInit(args) {
|
|
78
|
-
printFoxIcon();
|
|
79
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
80
|
-
printInitHelp();
|
|
81
|
-
process.exit(0);
|
|
82
|
-
}
|
|
83
|
-
const options = {};
|
|
84
|
-
// Parse command line arguments
|
|
85
|
-
for (let i = 0; i < args.length; i++) {
|
|
86
|
-
const arg = args[i];
|
|
87
|
-
if (arg.startsWith('--')) {
|
|
88
|
-
const key = arg.replace(/^--/, '');
|
|
89
|
-
switch (key) {
|
|
90
|
-
case 'skip-gitignore':
|
|
91
|
-
options.skipGitignore = true;
|
|
92
|
-
break;
|
|
93
|
-
case 'quiet':
|
|
94
|
-
// Ignore --quiet for init (quiet mode not supported)
|
|
95
|
-
break;
|
|
96
|
-
default:
|
|
97
|
-
console.error(`❌ Unknown option: ${arg}`);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else if (arg !== '-q') {
|
|
102
|
-
// First non-option argument is the target directory (ignore -q)
|
|
103
|
-
if (!options.targetDir) {
|
|
104
|
-
options.targetDir = arg;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
try {
|
|
109
|
-
await init(options);
|
|
110
|
-
}
|
|
111
|
-
catch (error) {
|
|
112
|
-
console.error('❌ Initialization failed:', error.message);
|
|
113
|
-
process.exit(1);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
async function handleValidate(args) {
|
|
117
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
118
|
-
printFoxIcon();
|
|
119
|
-
printValidateHelp();
|
|
120
|
-
process.exit(0);
|
|
121
|
-
}
|
|
122
|
-
const quiet = args.includes('--quiet') || args.includes('-q');
|
|
123
|
-
const filePath = args.filter(arg => arg !== '--quiet' && arg !== '-q')[0];
|
|
124
|
-
try {
|
|
125
|
-
await validateCommand(filePath, quiet);
|
|
126
|
-
}
|
|
127
|
-
catch (error) {
|
|
128
|
-
console.error('❌ Validation failed:', error.message);
|
|
129
|
-
process.exit(1);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
async function handleClean(args) {
|
|
133
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
134
|
-
printFoxIcon();
|
|
135
|
-
printCleanHelp();
|
|
136
|
-
process.exit(0);
|
|
137
|
-
}
|
|
138
|
-
const options = {
|
|
139
|
-
all: args.includes('--all'),
|
|
140
|
-
yes: args.includes('--yes'),
|
|
141
|
-
quiet: args.includes('--quiet') || args.includes('-q'),
|
|
142
|
-
};
|
|
143
|
-
// First non-option argument is the target directory
|
|
144
|
-
for (const arg of args) {
|
|
145
|
-
if (!arg.startsWith('--') && !options.projectRoot) {
|
|
146
|
-
options.projectRoot = arg;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
try {
|
|
151
|
-
await cleanCommand(options);
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
console.error('❌ Clean failed:', error.message);
|
|
155
|
-
process.exit(1);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Prompt user for Y/N input (only in TTY mode)
|
|
160
|
-
*/
|
|
161
|
-
async function promptYesNo(question) {
|
|
162
|
-
const { createInterface } = await import('node:readline');
|
|
163
|
-
const readline = createInterface({
|
|
164
|
-
input: process.stdin,
|
|
165
|
-
output: process.stdout,
|
|
166
|
-
});
|
|
167
|
-
return new Promise((resolve) => {
|
|
168
|
-
readline.question(question, (answer) => {
|
|
169
|
-
readline.close();
|
|
170
|
-
resolve(answer.toLowerCase() === 'y');
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Check if running in interactive TTY
|
|
176
|
-
*/
|
|
177
|
-
function isTTY() {
|
|
178
|
-
return process.stdout.isTTY === true && process.stdin.isTTY === true;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Wrap a function call to suppress or filter console output
|
|
182
|
-
*/
|
|
183
|
-
async function handleCompare(args) {
|
|
184
|
-
if (args[0] === '--help' || args[0] === '-h') {
|
|
185
|
-
printFoxIcon();
|
|
186
|
-
printCompareHelp();
|
|
187
|
-
process.exit(0);
|
|
188
|
-
}
|
|
189
|
-
const stats = args.includes('--stats');
|
|
190
|
-
const approve = args.includes('--approve');
|
|
191
|
-
const cleanOrphaned = args.includes('--clean-orphaned');
|
|
192
|
-
const quiet = args.includes('--quiet') || args.includes('-q');
|
|
193
|
-
const skipGitignore = args.includes('--skip-gitignore');
|
|
194
|
-
// Filter out flag arguments to get positional args (including -q)
|
|
195
|
-
const positionalArgs = args.filter(arg => !arg.startsWith('--') && arg !== '-q');
|
|
196
|
-
// Auto-mode: no files specified - use multi-file comparison with context_main.json
|
|
197
|
-
if (positionalArgs.length === 0) {
|
|
198
|
-
const { tmpdir } = await import('node:os');
|
|
199
|
-
const { join, dirname } = await import('node:path');
|
|
200
|
-
const { unlink, copyFile, rm, mkdir } = await import('node:fs/promises');
|
|
201
|
-
const { existsSync } = await import('node:fs');
|
|
202
|
-
// Check if context_main.json exists
|
|
203
|
-
if (!existsSync('context_main.json')) {
|
|
204
|
-
console.error('❌ context_main.json not found. Run "stamp context" first to generate context files.');
|
|
205
|
-
process.exit(1);
|
|
206
|
-
}
|
|
207
|
-
if (!quiet) {
|
|
208
|
-
console.log('Auto-compare mode');
|
|
209
|
-
}
|
|
210
|
-
// Create temp directory for new context generation
|
|
211
|
-
const tempDir = join(tmpdir(), `context-compare-${Date.now()}`);
|
|
212
|
-
await mkdir(tempDir, { recursive: true });
|
|
213
|
-
if (!quiet) {
|
|
214
|
-
console.log('🔄 Generating fresh context...');
|
|
215
|
-
}
|
|
216
|
-
// Generate fresh context to temp directory
|
|
217
|
-
const contextOptions = {
|
|
218
|
-
depth: 1,
|
|
219
|
-
includeCode: 'header',
|
|
220
|
-
format: 'json',
|
|
221
|
-
out: tempDir,
|
|
222
|
-
hashLock: false,
|
|
223
|
-
strict: false,
|
|
224
|
-
allowMissing: true,
|
|
225
|
-
maxNodes: 100,
|
|
226
|
-
profile: 'llm-chat',
|
|
227
|
-
predictBehavior: false,
|
|
228
|
-
dryRun: false,
|
|
229
|
-
stats: false,
|
|
230
|
-
strictMissing: false,
|
|
231
|
-
compareModes: false,
|
|
232
|
-
skipGitignore,
|
|
233
|
-
quiet,
|
|
234
|
-
suppressSuccessIndicator: true, // Suppress ✓ when called internally from compare
|
|
235
|
-
};
|
|
236
|
-
try {
|
|
237
|
-
await contextCommand(contextOptions);
|
|
238
|
-
// Multi-file compare using context_main.json indices
|
|
239
|
-
if (!quiet) {
|
|
240
|
-
console.log('🔍 Comparing all context files...\n');
|
|
241
|
-
}
|
|
242
|
-
const multiCompareOptions = {
|
|
243
|
-
oldIndexFile: 'context_main.json',
|
|
244
|
-
newIndexFile: join(tempDir, 'context_main.json'),
|
|
245
|
-
stats,
|
|
246
|
-
approve,
|
|
247
|
-
autoCleanOrphaned: cleanOrphaned,
|
|
248
|
-
quiet,
|
|
249
|
-
};
|
|
250
|
-
const result = await multiFileCompare(multiCompareOptions);
|
|
251
|
-
displayMultiFileCompareResult(result, stats, quiet);
|
|
252
|
-
// Handle drift approval
|
|
253
|
-
if (result.status === 'DRIFT') {
|
|
254
|
-
let shouldUpdate = false;
|
|
255
|
-
if (approve) {
|
|
256
|
-
// --approve flag: non-interactive, deterministic
|
|
257
|
-
shouldUpdate = true;
|
|
258
|
-
console.log('🔄 --approve flag set, updating all context files...');
|
|
259
|
-
}
|
|
260
|
-
else if (isTTY()) {
|
|
261
|
-
// Interactive prompt (local dev convenience)
|
|
262
|
-
shouldUpdate = await promptYesNo('Update all context files? (y/N) ');
|
|
263
|
-
}
|
|
264
|
-
if (shouldUpdate) {
|
|
265
|
-
// Copy all new context files to current directory
|
|
266
|
-
const { readFile } = await import('node:fs/promises');
|
|
267
|
-
const newIndexContent = await readFile(join(tempDir, 'context_main.json'), 'utf8');
|
|
268
|
-
const newIndex = JSON.parse(newIndexContent);
|
|
269
|
-
let copiedFiles = 0;
|
|
270
|
-
for (const folder of newIndex.folders) {
|
|
271
|
-
const srcPath = join(tempDir, folder.contextFile);
|
|
272
|
-
const destPath = folder.contextFile;
|
|
273
|
-
// Create parent directory if needed
|
|
274
|
-
await mkdir(dirname(destPath), { recursive: true });
|
|
275
|
-
await copyFile(srcPath, destPath);
|
|
276
|
-
copiedFiles++;
|
|
277
|
-
if (!quiet) {
|
|
278
|
-
console.log(` ✓ Updated ${destPath}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// Copy context_main.json
|
|
282
|
-
await copyFile(join(tempDir, 'context_main.json'), 'context_main.json');
|
|
283
|
-
if (!quiet) {
|
|
284
|
-
console.log(` ✓ Updated context_main.json`);
|
|
285
|
-
}
|
|
286
|
-
// Clean up orphaned files if requested
|
|
287
|
-
if (cleanOrphaned && result.orphanedFiles && result.orphanedFiles.length > 0) {
|
|
288
|
-
if (!quiet) {
|
|
289
|
-
console.log('\n🗑️ Cleaning up orphaned files...');
|
|
290
|
-
}
|
|
291
|
-
const deletedCount = await cleanOrphanedFiles(result.orphanedFiles, '.', quiet);
|
|
292
|
-
if (!quiet) {
|
|
293
|
-
console.log(` ✓ Deleted ${deletedCount} orphaned file(s)`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
if (!quiet) {
|
|
297
|
-
console.log(`\n✅ ${copiedFiles + 1} context files updated successfully`);
|
|
298
|
-
}
|
|
299
|
-
// Clean up temp directory
|
|
300
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
301
|
-
process.exit(0); // Success: drift approved and updated
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
// Clean up temp directory
|
|
305
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
306
|
-
if (isTTY() && !approve) {
|
|
307
|
-
console.log('❌ Update declined\n');
|
|
308
|
-
}
|
|
309
|
-
process.exit(1); // Drift detected but not approved
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
// No drift - clean up and exit success
|
|
314
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
315
|
-
process.exit(0);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
catch (error) {
|
|
319
|
-
// Try to clean up temp directory even on error
|
|
320
|
-
try {
|
|
321
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
322
|
-
}
|
|
323
|
-
catch { }
|
|
324
|
-
console.error('❌ Compare failed:', error.message);
|
|
325
|
-
process.exit(1);
|
|
326
|
-
}
|
|
69
|
+
// Check for 'style' subcommand (stamp context style)
|
|
70
|
+
if (contextArgs[0] === 'style') {
|
|
71
|
+
await handleStyle(contextArgs.slice(1));
|
|
327
72
|
return;
|
|
328
73
|
}
|
|
329
|
-
//
|
|
330
|
-
|
|
331
|
-
printFoxIcon();
|
|
332
|
-
printCompareHelp();
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
335
|
-
const oldFile = positionalArgs[0];
|
|
336
|
-
const newFile = positionalArgs[1];
|
|
337
|
-
// Detect if we're comparing context_main.json files (multi-file mode)
|
|
338
|
-
const isMultiFileMode = oldFile.endsWith('context_main.json') || oldFile.endsWith('context_main.json');
|
|
339
|
-
if (isMultiFileMode) {
|
|
340
|
-
// Multi-file comparison mode
|
|
341
|
-
const multiCompareOptions = {
|
|
342
|
-
oldIndexFile: oldFile,
|
|
343
|
-
newIndexFile: newFile,
|
|
344
|
-
stats,
|
|
345
|
-
approve,
|
|
346
|
-
autoCleanOrphaned: cleanOrphaned,
|
|
347
|
-
quiet,
|
|
348
|
-
};
|
|
349
|
-
try {
|
|
350
|
-
const result = await multiFileCompare(multiCompareOptions);
|
|
351
|
-
displayMultiFileCompareResult(result, stats, quiet);
|
|
352
|
-
// Handle drift approval in manual mode
|
|
353
|
-
if (result.status === 'DRIFT') {
|
|
354
|
-
let shouldUpdate = false;
|
|
355
|
-
if (approve) {
|
|
356
|
-
// --approve flag: non-interactive, deterministic
|
|
357
|
-
shouldUpdate = true;
|
|
358
|
-
if (!quiet) {
|
|
359
|
-
console.log('🔄 --approve flag set, updating all context files...');
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
else if (isTTY()) {
|
|
363
|
-
// Interactive prompt (local dev convenience)
|
|
364
|
-
shouldUpdate = await promptYesNo('Update all context files? (y/N) ');
|
|
365
|
-
}
|
|
366
|
-
if (shouldUpdate) {
|
|
367
|
-
// Copy all new context files
|
|
368
|
-
const { readFile, copyFile, mkdir } = await import('node:fs/promises');
|
|
369
|
-
const { dirname } = await import('node:path');
|
|
370
|
-
const newIndexContent = await readFile(newFile, 'utf8');
|
|
371
|
-
const newIndex = JSON.parse(newIndexContent);
|
|
372
|
-
const baseDir = dirname(oldFile);
|
|
373
|
-
let copiedFiles = 0;
|
|
374
|
-
for (const folder of newIndex.folders) {
|
|
375
|
-
const { join } = await import('node:path');
|
|
376
|
-
const srcPath = join(dirname(newFile), folder.contextFile);
|
|
377
|
-
const destPath = join(baseDir, folder.contextFile);
|
|
378
|
-
// Create parent directory if needed
|
|
379
|
-
await mkdir(dirname(destPath), { recursive: true });
|
|
380
|
-
await copyFile(srcPath, destPath);
|
|
381
|
-
copiedFiles++;
|
|
382
|
-
if (!quiet) {
|
|
383
|
-
console.log(` ✓ Updated ${folder.contextFile}`);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
// Copy context_main.json
|
|
387
|
-
await copyFile(newFile, oldFile);
|
|
388
|
-
if (!quiet) {
|
|
389
|
-
console.log(` ✓ Updated ${oldFile}`);
|
|
390
|
-
}
|
|
391
|
-
// Clean up orphaned files if requested
|
|
392
|
-
if (cleanOrphaned && result.orphanedFiles && result.orphanedFiles.length > 0) {
|
|
393
|
-
if (!quiet) {
|
|
394
|
-
console.log('\n🗑️ Cleaning up orphaned files...');
|
|
395
|
-
}
|
|
396
|
-
const deletedCount = await cleanOrphanedFiles(result.orphanedFiles, baseDir, quiet);
|
|
397
|
-
if (!quiet) {
|
|
398
|
-
console.log(` ✓ Deleted ${deletedCount} orphaned file(s)`);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (!quiet) {
|
|
402
|
-
console.log(`\n✅ ${copiedFiles + 1} context files updated successfully`);
|
|
403
|
-
}
|
|
404
|
-
process.exit(0); // Success: drift approved and updated
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
if (isTTY() && !approve) {
|
|
408
|
-
console.log('❌ Update declined\n');
|
|
409
|
-
}
|
|
410
|
-
process.exit(1); // Drift detected but not approved
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
// No drift
|
|
415
|
-
process.exit(0);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
catch (error) {
|
|
419
|
-
console.error('❌ Compare failed:', error.message);
|
|
420
|
-
process.exit(1);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
else {
|
|
424
|
-
// Single-file comparison mode (backward compatible)
|
|
425
|
-
const compareOptions = {
|
|
426
|
-
oldFile,
|
|
427
|
-
newFile,
|
|
428
|
-
stats,
|
|
429
|
-
approve,
|
|
430
|
-
quiet,
|
|
431
|
-
};
|
|
432
|
-
try {
|
|
433
|
-
const result = await compareCommand(compareOptions);
|
|
434
|
-
// Handle drift approval in manual mode
|
|
435
|
-
if (result.status === 'DRIFT') {
|
|
436
|
-
let shouldUpdate = false;
|
|
437
|
-
if (approve) {
|
|
438
|
-
// --approve flag: non-interactive, deterministic
|
|
439
|
-
shouldUpdate = true;
|
|
440
|
-
if (!quiet) {
|
|
441
|
-
console.log(`🔄 --approve flag set, updating ${oldFile}...`);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
else if (isTTY()) {
|
|
445
|
-
// Interactive prompt (local dev convenience)
|
|
446
|
-
shouldUpdate = await promptYesNo(`Update ${oldFile} with ${newFile}? (y/N) `);
|
|
447
|
-
}
|
|
448
|
-
if (shouldUpdate) {
|
|
449
|
-
const { copyFile } = await import('node:fs/promises');
|
|
450
|
-
await copyFile(newFile, oldFile);
|
|
451
|
-
if (!quiet) {
|
|
452
|
-
console.log(`✅ ${oldFile} updated successfully\n`);
|
|
453
|
-
}
|
|
454
|
-
process.exit(0); // Success: drift approved and updated
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
if (isTTY() && !approve) {
|
|
458
|
-
console.log('❌ Update declined\n');
|
|
459
|
-
}
|
|
460
|
-
process.exit(1); // Drift detected but not approved
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
// No drift
|
|
465
|
-
process.exit(0);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
catch (error) {
|
|
469
|
-
console.error('❌ Compare failed:', error.message);
|
|
470
|
-
process.exit(1);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
async function handleGenerate(args) {
|
|
475
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
476
|
-
printFoxIcon();
|
|
477
|
-
printGenerateHelp();
|
|
478
|
-
process.exit(0);
|
|
479
|
-
}
|
|
480
|
-
const options = {
|
|
481
|
-
depth: 1,
|
|
482
|
-
includeCode: 'header',
|
|
483
|
-
format: 'json',
|
|
484
|
-
out: 'context.json',
|
|
485
|
-
hashLock: false,
|
|
486
|
-
strict: false,
|
|
487
|
-
allowMissing: true,
|
|
488
|
-
maxNodes: 100,
|
|
489
|
-
profile: 'llm-chat',
|
|
490
|
-
predictBehavior: false,
|
|
491
|
-
dryRun: false,
|
|
492
|
-
stats: false,
|
|
493
|
-
strictMissing: false,
|
|
494
|
-
compareModes: false,
|
|
495
|
-
skipGitignore: false,
|
|
496
|
-
quiet: false,
|
|
497
|
-
};
|
|
498
|
-
// Parse command line arguments
|
|
499
|
-
for (let i = 0; i < args.length; i++) {
|
|
500
|
-
const arg = args[i];
|
|
501
|
-
if (arg.startsWith('--') || arg.startsWith('-')) {
|
|
502
|
-
const key = arg.replace(/^--?/, '');
|
|
503
|
-
const value = args[i + 1];
|
|
504
|
-
switch (key) {
|
|
505
|
-
case 'depth':
|
|
506
|
-
case 'd':
|
|
507
|
-
options.depth = parseInt(value, 10);
|
|
508
|
-
i++;
|
|
509
|
-
break;
|
|
510
|
-
case 'include-code':
|
|
511
|
-
case 'c':
|
|
512
|
-
options.includeCode = value;
|
|
513
|
-
i++;
|
|
514
|
-
break;
|
|
515
|
-
case 'format':
|
|
516
|
-
case 'f':
|
|
517
|
-
options.format = value;
|
|
518
|
-
i++;
|
|
519
|
-
break;
|
|
520
|
-
case 'out':
|
|
521
|
-
case 'o':
|
|
522
|
-
options.out = value;
|
|
523
|
-
i++;
|
|
524
|
-
break;
|
|
525
|
-
case 'max-nodes':
|
|
526
|
-
case 'm':
|
|
527
|
-
options.maxNodes = parseInt(value, 10);
|
|
528
|
-
i++;
|
|
529
|
-
break;
|
|
530
|
-
case 'profile':
|
|
531
|
-
options.profile = value;
|
|
532
|
-
i++;
|
|
533
|
-
break;
|
|
534
|
-
case 'strict':
|
|
535
|
-
case 's':
|
|
536
|
-
options.strict = true;
|
|
537
|
-
break;
|
|
538
|
-
case 'predict-behavior':
|
|
539
|
-
options.predictBehavior = true;
|
|
540
|
-
break;
|
|
541
|
-
case 'dry-run':
|
|
542
|
-
options.dryRun = true;
|
|
543
|
-
break;
|
|
544
|
-
case 'stats':
|
|
545
|
-
options.stats = true;
|
|
546
|
-
break;
|
|
547
|
-
case 'strict-missing':
|
|
548
|
-
options.strictMissing = true;
|
|
549
|
-
break;
|
|
550
|
-
case 'compare-modes':
|
|
551
|
-
options.compareModes = true;
|
|
552
|
-
break;
|
|
553
|
-
case 'skip-gitignore':
|
|
554
|
-
options.skipGitignore = true;
|
|
555
|
-
break;
|
|
556
|
-
case 'quiet':
|
|
557
|
-
case 'q':
|
|
558
|
-
options.quiet = true;
|
|
559
|
-
break;
|
|
560
|
-
default:
|
|
561
|
-
console.error(`❌ Unknown option: ${arg}`);
|
|
562
|
-
process.exit(1);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
// First non-option argument is the entry path
|
|
567
|
-
if (!options.entry) {
|
|
568
|
-
options.entry = arg;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
try {
|
|
573
|
-
await contextCommand(options);
|
|
574
|
-
}
|
|
575
|
-
catch (error) {
|
|
576
|
-
console.error('❌ Context generation failed:', error.message);
|
|
577
|
-
console.error(error.stack);
|
|
578
|
-
process.exit(1);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
function printMainHelp() {
|
|
582
|
-
console.log(`
|
|
583
|
-
╭─────────────────────────────────────────────────╮
|
|
584
|
-
│ Stamp - LogicStamp Context CLI │
|
|
585
|
-
│ AI-ready context generation for React/TS │
|
|
586
|
-
╰─────────────────────────────────────────────────╯
|
|
587
|
-
|
|
588
|
-
USAGE:
|
|
589
|
-
stamp init [path] Initialize LogicStamp in a project
|
|
590
|
-
stamp context [path] [options] Generate context
|
|
591
|
-
stamp context validate [file] Validate context file
|
|
592
|
-
stamp context compare [options] Detect drift (auto-generates fresh context)
|
|
593
|
-
stamp context clean [path] [options] Remove all generated context artifacts
|
|
594
|
-
|
|
595
|
-
OPTIONS:
|
|
596
|
-
-v, --version Show version number
|
|
597
|
-
-h, --help Show this help
|
|
598
|
-
|
|
599
|
-
EXAMPLES:
|
|
600
|
-
stamp init
|
|
601
|
-
Set up LogicStamp in current directory (creates/updates .gitignore)
|
|
602
|
-
|
|
603
|
-
stamp context
|
|
604
|
-
Generate context.json for current directory
|
|
605
|
-
|
|
606
|
-
stamp context validate
|
|
607
|
-
Validate context.json in current directory
|
|
608
|
-
|
|
609
|
-
stamp context compare
|
|
610
|
-
Auto-detect drift by comparing with fresh context
|
|
611
|
-
|
|
612
|
-
stamp context clean
|
|
613
|
-
Show what would be removed (dry run)
|
|
614
|
-
|
|
615
|
-
stamp context clean --all --yes
|
|
616
|
-
Actually delete all context artifacts
|
|
617
|
-
|
|
618
|
-
For detailed help on a specific command, run:
|
|
619
|
-
stamp init --help
|
|
620
|
-
stamp context --help
|
|
621
|
-
stamp context validate --help
|
|
622
|
-
stamp context compare --help
|
|
623
|
-
stamp context clean --help
|
|
624
|
-
`);
|
|
625
|
-
}
|
|
626
|
-
function printGenerateHelp() {
|
|
627
|
-
console.log(`
|
|
628
|
-
╭─────────────────────────────────────────────────╮
|
|
629
|
-
│ Stamp Context - Generate AI Context │
|
|
630
|
-
│ Scan and analyze React/TS codebase │
|
|
631
|
-
╰─────────────────────────────────────────────────╯
|
|
632
|
-
|
|
633
|
-
USAGE:
|
|
634
|
-
stamp context [path] [options]
|
|
635
|
-
|
|
636
|
-
ARGUMENTS:
|
|
637
|
-
[path] Directory to scan (default: current)
|
|
638
|
-
|
|
639
|
-
OPTIONS:
|
|
640
|
-
--depth, -d <n> Dependency depth (default: 1)
|
|
641
|
-
--include-code, -c <mode> Code inclusion: none|header|full (default: header)
|
|
642
|
-
--format, -f <format> Output format: json|pretty|ndjson (default: json)
|
|
643
|
-
--out, -o <file> Output file (default: context.json)
|
|
644
|
-
--max-nodes, -m <n> Max nodes per bundle (default: 100)
|
|
645
|
-
--profile <profile> Preset profile: llm-safe|llm-chat|ci-strict
|
|
646
|
-
--strict, -s Fail on missing dependencies
|
|
647
|
-
--strict-missing Exit with error if any missing dependencies
|
|
648
|
-
--predict-behavior Include behavior predictions
|
|
649
|
-
--dry-run Skip writing output
|
|
650
|
-
--stats Emit JSON stats
|
|
651
|
-
--compare-modes Show detailed mode comparison table
|
|
652
|
-
--skip-gitignore Skip .gitignore setup (never prompt or modify)
|
|
653
|
-
--quiet, -q Suppress verbose output (show only errors)
|
|
654
|
-
-h, --help Show this help
|
|
655
|
-
|
|
656
|
-
EXAMPLES:
|
|
657
|
-
stamp context
|
|
658
|
-
Generate context for current directory
|
|
659
|
-
|
|
660
|
-
stamp context ./src --depth 2
|
|
661
|
-
Deep scan of src directory
|
|
662
|
-
|
|
663
|
-
stamp context --include-code none --out api.json
|
|
664
|
-
Generate API documentation only
|
|
665
|
-
|
|
666
|
-
stamp context --compare-modes
|
|
667
|
-
Show token cost comparison across modes
|
|
668
|
-
|
|
669
|
-
stamp context --quiet
|
|
670
|
-
Suppress verbose output (show only errors)
|
|
671
|
-
`);
|
|
672
|
-
}
|
|
673
|
-
function printValidateHelp() {
|
|
674
|
-
console.log(`
|
|
675
|
-
╭─────────────────────────────────────────────────╮
|
|
676
|
-
│ Stamp Context Validate - Bundle Validator │
|
|
677
|
-
│ Validate context.json structure and schema │
|
|
678
|
-
╰─────────────────────────────────────────────────╯
|
|
679
|
-
|
|
680
|
-
USAGE:
|
|
681
|
-
stamp context validate [file]
|
|
682
|
-
|
|
683
|
-
ARGUMENTS:
|
|
684
|
-
[file] Path to context.json (default: context.json)
|
|
685
|
-
|
|
686
|
-
OPTIONS:
|
|
687
|
-
--quiet Show only errors (suppress summaries and valid folders)
|
|
688
|
-
-h, --help Show this help
|
|
689
|
-
|
|
690
|
-
EXAMPLES:
|
|
691
|
-
stamp context validate
|
|
692
|
-
Validate context.json in current directory
|
|
693
|
-
|
|
694
|
-
stamp context validate docs/api-context.json
|
|
695
|
-
Validate a specific context file
|
|
696
|
-
|
|
697
|
-
stamp context validate --quiet
|
|
698
|
-
Show only validation errors
|
|
699
|
-
|
|
700
|
-
NOTES:
|
|
701
|
-
• Validates bundle structure and schema compliance
|
|
702
|
-
• Checks for required fields and hash formats
|
|
703
|
-
• Exits with code 0 on success, 1 on failure
|
|
704
|
-
`);
|
|
705
|
-
}
|
|
706
|
-
function printCompareHelp() {
|
|
707
|
-
console.log(`
|
|
708
|
-
╭─────────────────────────────────────────────────╮
|
|
709
|
-
│ Stamp Context Compare - Drift Detection │
|
|
710
|
-
│ Compare context files for changes │
|
|
711
|
-
╰─────────────────────────────────────────────────╯
|
|
712
|
-
|
|
713
|
-
USAGE:
|
|
714
|
-
stamp context compare [options] Auto-compare all context files
|
|
715
|
-
stamp context compare <old.json> <new.json> Compare two specific files
|
|
716
|
-
stamp context compare <old_main.json> <new_main.json> Compare multi-file indices
|
|
717
|
-
|
|
718
|
-
ARGUMENTS:
|
|
719
|
-
<old.json> Path to old context file or context_main.json
|
|
720
|
-
<new.json> Path to new context file or context_main.json
|
|
721
|
-
|
|
722
|
-
OPTIONS:
|
|
723
|
-
--approve Auto-approve updates (non-interactive, CI-safe)
|
|
724
|
-
--clean-orphaned Auto-delete orphaned files with --approve
|
|
725
|
-
--quiet Show only diffs (suppress summaries, PASS folders, and token analysis)
|
|
726
|
-
-h, --help Show this help
|
|
727
|
-
|
|
728
|
-
COMPARISON MODES:
|
|
729
|
-
Auto-Mode (Multi-File):
|
|
730
|
-
Compares ALL context files using context_main.json as index
|
|
731
|
-
→ Detects ADDED, ORPHANED, DRIFT, and PASS status per folder
|
|
732
|
-
→ Shows three-tier output: folder summary, component summary, details
|
|
733
|
-
|
|
734
|
-
Single-File Mode:
|
|
735
|
-
Compares two individual context.json files
|
|
736
|
-
→ Detects added/removed/changed components
|
|
737
|
-
|
|
738
|
-
Multi-File Manual Mode:
|
|
739
|
-
Auto-detects when comparing context_main.json files
|
|
740
|
-
→ Compares all referenced context files
|
|
741
|
-
|
|
742
|
-
EXAMPLES:
|
|
743
|
-
stamp context compare
|
|
744
|
-
Auto-mode: generate fresh context, compare ALL files
|
|
745
|
-
→ Shows folder-level and component-level changes
|
|
746
|
-
→ Interactive: prompts Y/N to update if drift detected
|
|
747
|
-
→ CI: exits with code 1 if drift detected (no prompt)
|
|
748
|
-
|
|
749
|
-
stamp context compare --approve
|
|
750
|
-
Auto-approve and update ALL context files if drift (like jest -u)
|
|
751
|
-
|
|
752
|
-
stamp context compare --approve --clean-orphaned
|
|
753
|
-
Auto-approve updates and delete orphaned context files
|
|
754
|
-
|
|
755
|
-
stamp context compare --stats
|
|
756
|
-
Show per-folder token count deltas
|
|
757
|
-
|
|
758
|
-
stamp context compare --quiet
|
|
759
|
-
Show only diffs (suppress summaries, PASS folders, and status headers)
|
|
760
|
-
|
|
761
|
-
stamp context compare old.json new.json
|
|
762
|
-
Compare two specific context files
|
|
763
|
-
|
|
764
|
-
stamp context compare old/context_main.json new/context_main.json
|
|
765
|
-
Compare all context files between two directories
|
|
766
|
-
|
|
767
|
-
stamp context compare || exit 1
|
|
768
|
-
CI validation: fail build if drift detected
|
|
769
|
-
|
|
770
|
-
EXIT CODES:
|
|
771
|
-
0 PASS - No drift OR drift approved and updated
|
|
772
|
-
1 DRIFT - Changes detected but not approved
|
|
773
|
-
|
|
774
|
-
BEHAVIOR:
|
|
775
|
-
• --approve: Non-interactive, deterministic, updates immediately if drift
|
|
776
|
-
• Interactive (TTY): Prompts "Update all context files? (y/N)" if drift
|
|
777
|
-
• CI (non-TTY): Never prompts, exits 1 if drift detected
|
|
778
|
-
• --clean-orphaned: Requires --approve, deletes orphaned files automatically
|
|
779
|
-
• --quiet: Shows only diffs - suppresses status headers (PASS), summaries, PASS folders, and token analysis
|
|
780
|
-
|
|
781
|
-
DRIFT INDICATORS:
|
|
782
|
-
➕ ADDED FILE New folder with context file
|
|
783
|
-
🗑️ ORPHANED FILE Folder removed (context file still exists)
|
|
784
|
-
⚠️ DRIFT Folder has component changes
|
|
785
|
-
✅ PASS Folder unchanged
|
|
786
|
-
|
|
787
|
-
NOTES:
|
|
788
|
-
This matches Jest snapshot workflow:
|
|
789
|
-
jest → prompts to update snapshots locally
|
|
790
|
-
jest -u → updates snapshots without prompt
|
|
791
|
-
CI → fails if snapshots don't match
|
|
792
|
-
`);
|
|
793
|
-
}
|
|
794
|
-
function printCleanHelp() {
|
|
795
|
-
console.log(`
|
|
796
|
-
╭─────────────────────────────────────────────────╮
|
|
797
|
-
│ Stamp Context Clean - Remove Artifacts │
|
|
798
|
-
│ Delete all generated context files │
|
|
799
|
-
╰─────────────────────────────────────────────────╯
|
|
800
|
-
|
|
801
|
-
USAGE:
|
|
802
|
-
stamp context clean [path] [options]
|
|
803
|
-
|
|
804
|
-
ARGUMENTS:
|
|
805
|
-
[path] Directory to clean (default: current)
|
|
806
|
-
|
|
807
|
-
OPTIONS:
|
|
808
|
-
--all Include all context files
|
|
809
|
-
--yes Confirm deletion (required with --all)
|
|
810
|
-
--quiet, -q Suppress verbose output (show only errors)
|
|
811
|
-
-h, --help Show this help
|
|
812
|
-
|
|
813
|
-
BEHAVIOR:
|
|
814
|
-
• Default (dry run): Shows what would be removed
|
|
815
|
-
• --all --yes: Actually deletes the files
|
|
816
|
-
• Automatically includes .logicstamp/ directory if it exists
|
|
817
|
-
• --quiet: Shows only ✓ on success, errors otherwise
|
|
818
|
-
|
|
819
|
-
FILES REMOVED:
|
|
820
|
-
• context_main.json Main index file
|
|
821
|
-
• **/context.json All folder context files
|
|
822
|
-
• .logicstamp/ Cache directory (if present)
|
|
823
|
-
|
|
824
|
-
EXAMPLES:
|
|
825
|
-
stamp context clean
|
|
826
|
-
Show what would be removed (dry run)
|
|
827
|
-
|
|
828
|
-
stamp context clean --all --yes
|
|
829
|
-
Actually delete all context artifacts (includes .logicstamp/ if present)
|
|
830
|
-
|
|
831
|
-
stamp context clean --all --yes --quiet
|
|
832
|
-
Delete files silently (show only ✓)
|
|
833
|
-
|
|
834
|
-
stamp context clean ./src --all --yes
|
|
835
|
-
Clean context files in specific directory
|
|
836
|
-
|
|
837
|
-
NOTES:
|
|
838
|
-
• Safe by default - requires --all --yes to actually delete
|
|
839
|
-
• Ignores node_modules, dist, build, .next directories
|
|
840
|
-
• Exits with code 0 on success
|
|
841
|
-
`);
|
|
842
|
-
}
|
|
843
|
-
function printInitHelp() {
|
|
844
|
-
console.log(`
|
|
845
|
-
╭─────────────────────────────────────────────────╮
|
|
846
|
-
│ Stamp Init - Initialize LogicStamp │
|
|
847
|
-
│ Set up LogicStamp in your project │
|
|
848
|
-
╰─────────────────────────────────────────────────╯
|
|
849
|
-
|
|
850
|
-
USAGE:
|
|
851
|
-
stamp init [path] [options]
|
|
852
|
-
|
|
853
|
-
ARGUMENTS:
|
|
854
|
-
[path] Target directory (default: current)
|
|
855
|
-
|
|
856
|
-
OPTIONS:
|
|
857
|
-
--skip-gitignore Skip .gitignore setup
|
|
858
|
-
-h, --help Show this help
|
|
859
|
-
|
|
860
|
-
EXAMPLES:
|
|
861
|
-
stamp init
|
|
862
|
-
Set up LogicStamp in current directory
|
|
863
|
-
|
|
864
|
-
stamp init ./my-project
|
|
865
|
-
Set up LogicStamp in a specific directory
|
|
866
|
-
|
|
867
|
-
stamp init --skip-gitignore
|
|
868
|
-
Initialize without modifying .gitignore
|
|
869
|
-
|
|
870
|
-
WHAT IT DOES:
|
|
871
|
-
• Creates or updates .gitignore with LogicStamp patterns:
|
|
872
|
-
- context.json
|
|
873
|
-
- context_*.json
|
|
874
|
-
- *.uif.json
|
|
875
|
-
- logicstamp.manifest.json
|
|
876
|
-
- .logicstamp/
|
|
877
|
-
|
|
878
|
-
NOTES:
|
|
879
|
-
• Safe to run multiple times (idempotent)
|
|
880
|
-
• Won't duplicate patterns if they already exist
|
|
881
|
-
• Creates .gitignore if it doesn't exist
|
|
882
|
-
`);
|
|
74
|
+
// Default: generate context
|
|
75
|
+
await handleGenerate(contextArgs);
|
|
883
76
|
}
|
|
884
77
|
main();
|
|
885
78
|
//# sourceMappingURL=stamp.js.map
|