universal-dev-standards 3.4.2 → 3.5.0-beta.2
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/package.json +1 -1
- package/src/commands/check.js +21 -15
- package/src/utils/hasher.js +72 -1
- package/standards-registry.json +3 -3
package/package.json
CHANGED
package/src/commands/check.js
CHANGED
|
@@ -183,7 +183,8 @@ export async function checkCommand(options = {}) {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
// Interactive mode (default when issues detected)
|
|
186
|
-
const hasIssues = fileStatus.modified.length > 0 ||
|
|
186
|
+
const hasIssues = fileStatus.modified.length > 0 ||
|
|
187
|
+
fileStatus.missing.length > 0;
|
|
187
188
|
if (hasIssues && !options.noInteractive) {
|
|
188
189
|
await interactiveMode(projectPath, manifest, fileStatus);
|
|
189
190
|
} else if (hasIssues) {
|
|
@@ -210,7 +211,8 @@ export async function checkCommand(options = {}) {
|
|
|
210
211
|
displayCoverageReport(manifest);
|
|
211
212
|
|
|
212
213
|
// Final status
|
|
213
|
-
const allGood = fileStatus.missing.length === 0 &&
|
|
214
|
+
const allGood = fileStatus.missing.length === 0 &&
|
|
215
|
+
fileStatus.modified.length === 0;
|
|
214
216
|
if (allGood) {
|
|
215
217
|
console.log(chalk.green('✓ Project is compliant with standards'));
|
|
216
218
|
} else {
|
|
@@ -238,22 +240,26 @@ async function interactiveMode(projectPath, manifest, fileStatus) {
|
|
|
238
240
|
console.log(chalk.gray('─'.repeat(50)));
|
|
239
241
|
if (issue.status === 'modified') {
|
|
240
242
|
console.log(chalk.yellow(`⚠ Modified: ${issue.file}`));
|
|
241
|
-
} else {
|
|
243
|
+
} else if (issue.status === 'missing') {
|
|
242
244
|
console.log(chalk.red(`✗ Missing: ${issue.file}`));
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
247
|
+
let choices;
|
|
248
|
+
if (issue.status === 'modified') {
|
|
249
|
+
choices = [
|
|
250
|
+
{ name: 'view - View diff between current and original', value: 'view' },
|
|
251
|
+
{ name: 'restore - Restore to original version', value: 'restore' },
|
|
252
|
+
{ name: 'keep - Keep current version (update hash in manifest)', value: 'keep' },
|
|
253
|
+
{ name: 'skip - Skip this file for now', value: 'skip' }
|
|
254
|
+
];
|
|
255
|
+
} else {
|
|
256
|
+
// missing
|
|
257
|
+
choices = [
|
|
258
|
+
{ name: 'restore - Download and restore file', value: 'restore' },
|
|
259
|
+
{ name: 'remove - Remove from manifest (no longer track)', value: 'remove' },
|
|
260
|
+
{ name: 'skip - Skip this file for now', value: 'skip' }
|
|
261
|
+
];
|
|
262
|
+
}
|
|
257
263
|
|
|
258
264
|
const { action } = await inquirer.prompt([
|
|
259
265
|
{
|
package/src/utils/hasher.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
|
-
import { readFileSync, statSync, existsSync } from 'fs';
|
|
2
|
+
import { readFileSync, statSync, existsSync, readdirSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -146,3 +146,74 @@ export function getFileStatusSummary(projectPath, manifest) {
|
|
|
146
146
|
|
|
147
147
|
return summary;
|
|
148
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Recursively scan directory for all files
|
|
152
|
+
* @param {string} dirPath - Directory to scan
|
|
153
|
+
* @param {string} basePath - Base path for relative path calculation
|
|
154
|
+
* @returns {string[]} Array of relative paths
|
|
155
|
+
*/
|
|
156
|
+
function scanDirectory(dirPath, basePath) {
|
|
157
|
+
const files = [];
|
|
158
|
+
const items = readdirSync(dirPath, { withFileTypes: true });
|
|
159
|
+
|
|
160
|
+
for (const item of items) {
|
|
161
|
+
const fullPath = join(dirPath, item.name);
|
|
162
|
+
// Calculate relative path by removing basePath prefix
|
|
163
|
+
const relativePath = fullPath.slice(basePath.length + 1);
|
|
164
|
+
|
|
165
|
+
if (item.isDirectory()) {
|
|
166
|
+
files.push(...scanDirectory(fullPath, basePath));
|
|
167
|
+
} else if (item.isFile()) {
|
|
168
|
+
files.push(relativePath);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return files;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Scan for untracked files in .standards/ and integration locations
|
|
177
|
+
* @param {string} projectPath - Project root path
|
|
178
|
+
* @param {Object} manifest - Manifest object
|
|
179
|
+
* @returns {string[]} Array of relative paths to untracked files
|
|
180
|
+
*/
|
|
181
|
+
export function scanForUntrackedFiles(projectPath, manifest) {
|
|
182
|
+
const untracked = [];
|
|
183
|
+
const trackedPaths = new Set(Object.keys(manifest.fileHashes || {}));
|
|
184
|
+
|
|
185
|
+
// 1. Scan .standards/ directory (excluding manifest.json)
|
|
186
|
+
const standardsDir = join(projectPath, '.standards');
|
|
187
|
+
if (existsSync(standardsDir)) {
|
|
188
|
+
const standardsFiles = scanDirectory(standardsDir, projectPath);
|
|
189
|
+
for (const relPath of standardsFiles) {
|
|
190
|
+
// Skip manifest.json itself
|
|
191
|
+
if (relPath === '.standards/manifest.json' ||
|
|
192
|
+
relPath === '.standards\\manifest.json') {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!trackedPaths.has(relPath)) {
|
|
196
|
+
untracked.push(relPath);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 2. Scan for known integration files in project root
|
|
202
|
+
const knownIntegrations = [
|
|
203
|
+
'.cursorrules',
|
|
204
|
+
'.windsurfrules',
|
|
205
|
+
'.clinerules',
|
|
206
|
+
'.github/copilot-instructions.md',
|
|
207
|
+
'CLAUDE.md',
|
|
208
|
+
'INSTRUCTIONS.md'
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
for (const intFile of knownIntegrations) {
|
|
212
|
+
const fullPath = join(projectPath, intFile);
|
|
213
|
+
if (existsSync(fullPath) && !trackedPaths.has(intFile)) {
|
|
214
|
+
untracked.push(intFile);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return untracked;
|
|
219
|
+
}
|
package/standards-registry.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"lastUpdated": "2026-01-
|
|
3
|
+
"version": "3.5.0-beta.1",
|
|
4
|
+
"lastUpdated": "2026-01-09",
|
|
5
5
|
"description": "Standards registry for universal-dev-standards with integrated skills and AI-optimized formats",
|
|
6
6
|
"formats": {
|
|
7
7
|
"ai": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"url": "https://github.com/AsiaOstrich/universal-dev-standards",
|
|
56
56
|
"localPath": "skills/claude-code",
|
|
57
57
|
"rawUrl": "https://raw.githubusercontent.com/AsiaOstrich/universal-dev-standards/main/skills/claude-code",
|
|
58
|
-
"version": "3.
|
|
58
|
+
"version": "3.5.0-beta.1",
|
|
59
59
|
"note": "Skills are now included in the main repository under skills/"
|
|
60
60
|
}
|
|
61
61
|
},
|