@ryuenn3123/agentic-senior-core 3.0.37 → 3.0.38
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-context/prompts/bootstrap-design.md +108 -146
- package/.agent-context/rules/frontend-architecture.md +92 -108
- package/.agent-context/state/README.md +26 -0
- package/.cursor/mcp.json +10 -0
- package/.cursor/rules/agentic-senior-core.mdc +48 -0
- package/.cursorrules +22 -88
- package/.gemini/instructions.md +25 -16
- package/.github/copilot-instructions.md +25 -16
- package/.github/instructions/agentic-senior-core.instructions.md +47 -0
- package/.instructions.md +98 -207
- package/.windsurf/rules/agentic-senior-core.md +43 -0
- package/.windsurfrules +22 -88
- package/AGENTS.md +23 -26
- package/CLAUDE.md +43 -0
- package/CONTRIBUTING.md +5 -2
- package/GEMINI.md +43 -0
- package/README.md +24 -7
- package/lib/cli/backup.mjs +4 -4
- package/lib/cli/commands/init/project-context.mjs +101 -0
- package/lib/cli/commands/init/runtime-environment.mjs +59 -0
- package/lib/cli/commands/init/setup-decisions.mjs +83 -0
- package/lib/cli/commands/init.mjs +33 -250
- package/lib/cli/commands/optimize.mjs +1 -1
- package/lib/cli/commands/upgrade.mjs +32 -7
- package/lib/cli/compiler.mjs +59 -17
- package/lib/cli/constants.mjs +5 -0
- package/lib/cli/detector.mjs +4 -0
- package/lib/cli/preflight.mjs +3 -3
- package/lib/cli/project-scaffolder/design-contract/validation.mjs +789 -0
- package/lib/cli/project-scaffolder/design-contract.mjs +119 -924
- package/lib/cli/project-scaffolder/prompt-builders.mjs +69 -84
- package/lib/cli/utils/filesystem.mjs +79 -0
- package/lib/cli/utils/managed-surface.mjs +237 -0
- package/lib/cli/utils/prompting.mjs +44 -0
- package/lib/cli/utils.mjs +33 -335
- package/package.json +21 -2
- package/scripts/clean-local-artifacts.mjs +76 -0
- package/scripts/docs-quality-drift-report.mjs +5 -0
- package/scripts/frontend-usability-audit.mjs +23 -19
- package/scripts/governance-weekly-report.mjs +37 -15
- package/scripts/single-source-lazy-loading-audit.mjs +24 -0
- package/scripts/sync-thin-adapters.mjs +99 -129
- package/scripts/v3-purge-audit.mjs +5 -0
- package/scripts/validate/config.mjs +10 -0
- package/scripts/validate/coverage-checks.mjs +55 -0
- package/.agent-context/marketplace/trust-tiers.json +0 -114
- package/.agent-context/state/benchmark-analysis.json +0 -431
- package/.agent-context/state/benchmark-evidence-bundle.json +0 -1040
- package/.agent-context/state/benchmark-history.json +0 -75
- package/.agent-context/state/benchmark-trend-report.csv +0 -5
- package/.agent-context/state/benchmark-trend-report.json +0 -140
- package/.agent-context/state/benchmark-writer-judge-matrix.json +0 -462
- package/.agent-context/state/memory-continuity-benchmark.json +0 -132
- package/.agent-context/state/onboarding-report.json +0 -102
- package/.agent-context/state/quality-trend-report.json +0 -89
- package/.agent-context/state/token-optimization-benchmark.json +0 -130
- package/.agent-context/state/weekly-governance-report.json +0 -329
- package/lib/cli/compatibility.mjs +0 -124
package/lib/cli/utils.mjs
CHANGED
|
@@ -14,6 +14,29 @@ import {
|
|
|
14
14
|
entryPointFiles,
|
|
15
15
|
directoryCopies,
|
|
16
16
|
} from './constants.mjs';
|
|
17
|
+
import {
|
|
18
|
+
pathExists,
|
|
19
|
+
ensureDirectory,
|
|
20
|
+
syncFile,
|
|
21
|
+
} from './utils/filesystem.mjs';
|
|
22
|
+
import {
|
|
23
|
+
collectRelativeTreeEntries,
|
|
24
|
+
analyzeManagedGovernanceSurface,
|
|
25
|
+
} from './utils/managed-surface.mjs';
|
|
26
|
+
export {
|
|
27
|
+
pathExists,
|
|
28
|
+
ensureDirectory,
|
|
29
|
+
copyDirectory,
|
|
30
|
+
isAgenticManagedContent,
|
|
31
|
+
syncFile,
|
|
32
|
+
} from './utils/filesystem.mjs';
|
|
33
|
+
export {
|
|
34
|
+
analyzeManagedGovernanceSurface,
|
|
35
|
+
} from './utils/managed-surface.mjs';
|
|
36
|
+
export {
|
|
37
|
+
askChoice,
|
|
38
|
+
askYesNo,
|
|
39
|
+
} from './utils/prompting.mjs';
|
|
17
40
|
|
|
18
41
|
export function printUsage() {
|
|
19
42
|
const presetNames = Object.keys(INIT_PRESETS).join(', ');
|
|
@@ -65,67 +88,6 @@ export function printUsage() {
|
|
|
65
88
|
console.log(' --show Print current token optimization state as JSON');
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
export async function pathExists(targetPath) {
|
|
69
|
-
try {
|
|
70
|
-
await fs.stat(targetPath);
|
|
71
|
-
return true;
|
|
72
|
-
} catch {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export async function ensureDirectory(directoryPath) {
|
|
78
|
-
await fs.mkdir(directoryPath, { recursive: true });
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function copyDirectory(sourceDirectoryPath, targetDirectoryPath) {
|
|
82
|
-
if (path.resolve(sourceDirectoryPath) === path.resolve(targetDirectoryPath)) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
await ensureDirectory(targetDirectoryPath);
|
|
87
|
-
const directoryEntries = await fs.readdir(sourceDirectoryPath, { withFileTypes: true });
|
|
88
|
-
|
|
89
|
-
for (const directoryEntry of directoryEntries) {
|
|
90
|
-
const sourceEntryPath = path.join(sourceDirectoryPath, directoryEntry.name);
|
|
91
|
-
const targetEntryPath = path.join(targetDirectoryPath, directoryEntry.name);
|
|
92
|
-
|
|
93
|
-
if (directoryEntry.isDirectory()) {
|
|
94
|
-
await copyDirectory(sourceEntryPath, targetEntryPath);
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (path.resolve(sourceEntryPath) === path.resolve(targetEntryPath)) {
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
await fs.copyFile(sourceEntryPath, targetEntryPath);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Synchronizes a single file between source and target, returning the operation status.
|
|
108
|
-
*/
|
|
109
|
-
export async function syncFile(sourcePath, targetPath) {
|
|
110
|
-
if (!(await pathExists(sourcePath))) return { status: 'skipped' };
|
|
111
|
-
|
|
112
|
-
if (!(await pathExists(targetPath))) {
|
|
113
|
-
await ensureDirectory(path.dirname(targetPath));
|
|
114
|
-
await fs.copyFile(sourcePath, targetPath);
|
|
115
|
-
return { status: 'created' };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const sourceContent = await fs.readFile(sourcePath);
|
|
119
|
-
const targetContent = await fs.readFile(targetPath);
|
|
120
|
-
|
|
121
|
-
if (sourceContent.equals(targetContent)) {
|
|
122
|
-
return { status: 'unchanged' };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
await fs.copyFile(sourcePath, targetPath);
|
|
126
|
-
return { status: 'updated' };
|
|
127
|
-
}
|
|
128
|
-
|
|
129
91
|
/**
|
|
130
92
|
* Intelligent MCP configuration synchronization.
|
|
131
93
|
* Merges the agentic-senior-core server into existing config or creates new.
|
|
@@ -163,233 +125,6 @@ async function syncMcpConfig(mcpJsonPath, templateConfig) {
|
|
|
163
125
|
}
|
|
164
126
|
}
|
|
165
127
|
|
|
166
|
-
function toPosixRelativePath(relativePath) {
|
|
167
|
-
return relativePath.split(path.sep).join('/');
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function isPathWithinPrefix(relativePath, prefixPath) {
|
|
171
|
-
const normalizedRelativePath = toPosixRelativePath(relativePath).replace(/\/+$/g, '');
|
|
172
|
-
const normalizedPrefixPath = toPosixRelativePath(prefixPath).replace(/\/+$/g, '');
|
|
173
|
-
|
|
174
|
-
if (!normalizedPrefixPath) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return normalizedRelativePath === normalizedPrefixPath
|
|
179
|
-
|| normalizedRelativePath.startsWith(`${normalizedPrefixPath}/`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const localOnlyGovernanceFiles = new Set([
|
|
183
|
-
'.agent-context/state/active-memory.json',
|
|
184
|
-
]);
|
|
185
|
-
|
|
186
|
-
function isLocalOnlyGovernanceFile(relativePath) {
|
|
187
|
-
return localOnlyGovernanceFiles.has(toPosixRelativePath(relativePath));
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async function collectRelativeTreeEntries(baseDirectoryPath, relativeRootPath) {
|
|
191
|
-
const files = [];
|
|
192
|
-
const directories = [];
|
|
193
|
-
|
|
194
|
-
if (!(await pathExists(baseDirectoryPath))) {
|
|
195
|
-
return { files, directories };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const normalizedRootPath = toPosixRelativePath(relativeRootPath);
|
|
199
|
-
directories.push(normalizedRootPath);
|
|
200
|
-
|
|
201
|
-
async function walkDirectory(currentDirectoryPath, currentRelativePath) {
|
|
202
|
-
const directoryEntries = await fs.readdir(currentDirectoryPath, { withFileTypes: true });
|
|
203
|
-
|
|
204
|
-
for (const directoryEntry of directoryEntries) {
|
|
205
|
-
const sourceEntryPath = path.join(currentDirectoryPath, directoryEntry.name);
|
|
206
|
-
const relativeEntryPath = toPosixRelativePath(path.join(currentRelativePath, directoryEntry.name));
|
|
207
|
-
|
|
208
|
-
if (directoryEntry.isDirectory()) {
|
|
209
|
-
directories.push(relativeEntryPath);
|
|
210
|
-
await walkDirectory(sourceEntryPath, relativeEntryPath);
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (isLocalOnlyGovernanceFile(relativeEntryPath)) {
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
files.push(relativeEntryPath);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
await walkDirectory(baseDirectoryPath, normalizedRootPath);
|
|
223
|
-
return { files, directories };
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
async function collectOptionalManagedEntries(baseDirectoryPath, options = {}) {
|
|
227
|
-
const files = new Set();
|
|
228
|
-
const directories = new Set();
|
|
229
|
-
|
|
230
|
-
if (options.includeMcpTemplate === true) {
|
|
231
|
-
const mcpServerEntrypointPath = path.join(baseDirectoryPath, 'scripts', 'mcp-server.mjs');
|
|
232
|
-
if (await pathExists(mcpServerEntrypointPath)) {
|
|
233
|
-
files.add('scripts/mcp-server.mjs');
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const mcpServerHelpersDirectoryPath = path.join(baseDirectoryPath, 'scripts', 'mcp-server');
|
|
237
|
-
const mcpServerTreeEntries = await collectRelativeTreeEntries(
|
|
238
|
-
mcpServerHelpersDirectoryPath,
|
|
239
|
-
'scripts/mcp-server'
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
for (const relativeFilePath of mcpServerTreeEntries.files) {
|
|
243
|
-
files.add(relativeFilePath);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
for (const relativeDirectoryPath of mcpServerTreeEntries.directories) {
|
|
247
|
-
directories.add(relativeDirectoryPath);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return { files, directories };
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
async function buildManagedSourceManifest(options = {}) {
|
|
255
|
-
const sourceFiles = new Set();
|
|
256
|
-
const sourceDirectories = new Set();
|
|
257
|
-
|
|
258
|
-
for (const sourceDirectoryName of directoryCopies) {
|
|
259
|
-
const sourceDirectoryPath = path.join(REPO_ROOT, sourceDirectoryName);
|
|
260
|
-
const sourceTreeEntries = await collectRelativeTreeEntries(sourceDirectoryPath, sourceDirectoryName);
|
|
261
|
-
|
|
262
|
-
for (const sourceFilePath of sourceTreeEntries.files) {
|
|
263
|
-
sourceFiles.add(sourceFilePath);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
for (const sourceDirectoryPathRelative of sourceTreeEntries.directories) {
|
|
267
|
-
sourceDirectories.add(sourceDirectoryPathRelative);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
for (const entryPointFileName of entryPointFiles) {
|
|
272
|
-
const sourceFilePath = path.join(REPO_ROOT, entryPointFileName);
|
|
273
|
-
if (!(await pathExists(sourceFilePath))) {
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
sourceFiles.add(toPosixRelativePath(entryPointFileName));
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const optionalManagedEntries = await collectOptionalManagedEntries(REPO_ROOT, options);
|
|
281
|
-
for (const sourceFilePath of optionalManagedEntries.files) {
|
|
282
|
-
sourceFiles.add(sourceFilePath);
|
|
283
|
-
}
|
|
284
|
-
for (const sourceDirectoryPath of optionalManagedEntries.directories) {
|
|
285
|
-
sourceDirectories.add(sourceDirectoryPath);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
return {
|
|
289
|
-
files: sourceFiles,
|
|
290
|
-
directories: sourceDirectories,
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
async function collectManagedTargetManifest(resolvedTargetDirectoryPath, options = {}) {
|
|
295
|
-
const targetFiles = new Set();
|
|
296
|
-
const targetDirectories = new Set();
|
|
297
|
-
|
|
298
|
-
for (const sourceDirectoryName of directoryCopies) {
|
|
299
|
-
const targetDirectoryPath = path.join(resolvedTargetDirectoryPath, sourceDirectoryName);
|
|
300
|
-
const targetTreeEntries = await collectRelativeTreeEntries(targetDirectoryPath, sourceDirectoryName);
|
|
301
|
-
|
|
302
|
-
for (const targetFilePath of targetTreeEntries.files) {
|
|
303
|
-
targetFiles.add(targetFilePath);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
for (const targetDirectoryPathRelative of targetTreeEntries.directories) {
|
|
307
|
-
targetDirectories.add(targetDirectoryPathRelative);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
for (const entryPointFileName of entryPointFiles) {
|
|
312
|
-
const targetFilePath = path.join(resolvedTargetDirectoryPath, entryPointFileName);
|
|
313
|
-
if (!(await pathExists(targetFilePath))) {
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
targetFiles.add(toPosixRelativePath(entryPointFileName));
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
const optionalManagedEntries = await collectOptionalManagedEntries(resolvedTargetDirectoryPath, options);
|
|
321
|
-
for (const targetFilePath of optionalManagedEntries.files) {
|
|
322
|
-
targetFiles.add(targetFilePath);
|
|
323
|
-
}
|
|
324
|
-
for (const targetDirectoryPath of optionalManagedEntries.directories) {
|
|
325
|
-
targetDirectories.add(targetDirectoryPath);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return {
|
|
329
|
-
files: targetFiles,
|
|
330
|
-
directories: targetDirectories,
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export async function analyzeManagedGovernanceSurface(
|
|
335
|
-
resolvedTargetDirectoryPath,
|
|
336
|
-
options = {}
|
|
337
|
-
) {
|
|
338
|
-
const preservePathPrefixes = Array.isArray(options.preservePathPrefixes)
|
|
339
|
-
? options.preservePathPrefixes
|
|
340
|
-
: ['.agent-context/state'];
|
|
341
|
-
|
|
342
|
-
const sourceManifest = await buildManagedSourceManifest(options);
|
|
343
|
-
const targetManifest = await collectManagedTargetManifest(resolvedTargetDirectoryPath, options);
|
|
344
|
-
|
|
345
|
-
const staleFiles = [];
|
|
346
|
-
const staleDirectories = [];
|
|
347
|
-
const preservedFiles = [];
|
|
348
|
-
const preservedDirectories = [];
|
|
349
|
-
|
|
350
|
-
const sortedTargetFiles = [...targetManifest.files].sort((leftPath, rightPath) => leftPath.localeCompare(rightPath));
|
|
351
|
-
const sortedTargetDirectories = [...targetManifest.directories].sort(
|
|
352
|
-
(leftPath, rightPath) => rightPath.length - leftPath.length || leftPath.localeCompare(rightPath)
|
|
353
|
-
);
|
|
354
|
-
|
|
355
|
-
for (const targetFilePath of sortedTargetFiles) {
|
|
356
|
-
if (sourceManifest.files.has(targetFilePath)) {
|
|
357
|
-
continue;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
if (preservePathPrefixes.some((prefixPath) => isPathWithinPrefix(targetFilePath, prefixPath))) {
|
|
361
|
-
preservedFiles.push(targetFilePath);
|
|
362
|
-
continue;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
staleFiles.push(targetFilePath);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
for (const targetDirectoryPathRelative of sortedTargetDirectories) {
|
|
369
|
-
if (sourceManifest.directories.has(targetDirectoryPathRelative)) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (preservePathPrefixes.some((prefixPath) => isPathWithinPrefix(targetDirectoryPathRelative, prefixPath))) {
|
|
374
|
-
preservedDirectories.push(targetDirectoryPathRelative);
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
staleDirectories.push(targetDirectoryPathRelative);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return {
|
|
382
|
-
staleFiles,
|
|
383
|
-
staleDirectories,
|
|
384
|
-
preservedFiles,
|
|
385
|
-
preservedDirectories,
|
|
386
|
-
managedSourceFileCount: sourceManifest.files.size,
|
|
387
|
-
managedSourceDirectoryCount: sourceManifest.directories.size,
|
|
388
|
-
managedTargetFileCount: targetManifest.files.size,
|
|
389
|
-
managedTargetDirectoryCount: targetManifest.directories.size,
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
|
|
393
128
|
export async function copyGovernanceAssetsToTarget(
|
|
394
129
|
resolvedTargetDirectoryPath,
|
|
395
130
|
options = {}
|
|
@@ -406,6 +141,7 @@ export async function copyGovernanceAssetsToTarget(
|
|
|
406
141
|
const createdFiles = [];
|
|
407
142
|
const updatedFiles = [];
|
|
408
143
|
const unchangedFiles = [];
|
|
144
|
+
const preservedFiles = [];
|
|
409
145
|
|
|
410
146
|
for (const sourceDirectoryName of directoryCopies) {
|
|
411
147
|
const sourceDirectoryPath = path.join(REPO_ROOT, sourceDirectoryName);
|
|
@@ -417,11 +153,14 @@ export async function copyGovernanceAssetsToTarget(
|
|
|
417
153
|
for (const relativeFilePath of sourceTree.files) {
|
|
418
154
|
const sourcePath = path.join(REPO_ROOT, ...relativeFilePath.split('/'));
|
|
419
155
|
const targetPath = path.join(resolvedTargetDirectoryPath, ...relativeFilePath.split('/'));
|
|
420
|
-
const syncResult = await syncFile(sourcePath, targetPath
|
|
156
|
+
const syncResult = await syncFile(sourcePath, targetPath, {
|
|
157
|
+
preserveUserOwned: sourceDirectoryName === '.gemini',
|
|
158
|
+
});
|
|
421
159
|
|
|
422
160
|
if (syncResult.status === 'created') createdFiles.push(relativeFilePath);
|
|
423
161
|
else if (syncResult.status === 'updated') updatedFiles.push(relativeFilePath);
|
|
424
162
|
else if (syncResult.status === 'unchanged') unchangedFiles.push(relativeFilePath);
|
|
163
|
+
else if (syncResult.status === 'preserved') preservedFiles.push(relativeFilePath);
|
|
425
164
|
}
|
|
426
165
|
}
|
|
427
166
|
|
|
@@ -437,10 +176,13 @@ export async function copyGovernanceAssetsToTarget(
|
|
|
437
176
|
continue;
|
|
438
177
|
}
|
|
439
178
|
|
|
440
|
-
const syncResult = await syncFile(sourceFilePath, targetFilePath
|
|
179
|
+
const syncResult = await syncFile(sourceFilePath, targetFilePath, {
|
|
180
|
+
preserveUserOwned: true,
|
|
181
|
+
});
|
|
441
182
|
if (syncResult.status === 'created') createdFiles.push(entryPointFileName);
|
|
442
183
|
else if (syncResult.status === 'updated') updatedFiles.push(entryPointFileName);
|
|
443
184
|
else if (syncResult.status === 'unchanged') unchangedFiles.push(entryPointFileName);
|
|
185
|
+
else if (syncResult.status === 'preserved') preservedFiles.push(entryPointFileName);
|
|
444
186
|
}
|
|
445
187
|
|
|
446
188
|
if (shouldPruneManagedSurface && managedSurfacePlan) {
|
|
@@ -595,55 +337,11 @@ export async function copyGovernanceAssetsToTarget(
|
|
|
595
337
|
createdFiles,
|
|
596
338
|
updatedFiles,
|
|
597
339
|
unchangedFiles,
|
|
340
|
+
preservedFiles,
|
|
598
341
|
managedSurfacePlan,
|
|
599
342
|
};
|
|
600
343
|
}
|
|
601
344
|
|
|
602
|
-
export async function askChoice(promptMessage, options, userInterface) {
|
|
603
|
-
console.log(`\n${promptMessage}`);
|
|
604
|
-
options.forEach((choiceLabel, choiceIndex) => {
|
|
605
|
-
console.log(` ${choiceIndex + 1}. ${choiceLabel}`);
|
|
606
|
-
});
|
|
607
|
-
|
|
608
|
-
while (true) {
|
|
609
|
-
const selectedRawInput = await userInterface.question('Choose a number (press Enter for 1): ');
|
|
610
|
-
const normalizedInput = selectedRawInput.trim();
|
|
611
|
-
|
|
612
|
-
if (!normalizedInput) {
|
|
613
|
-
return options[0];
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
const selectedIndex = Number.parseInt(normalizedInput, 10) - 1;
|
|
617
|
-
|
|
618
|
-
if (Number.isNaN(selectedIndex) || selectedIndex < 0 || selectedIndex >= options.length) {
|
|
619
|
-
console.log('Invalid choice. Please select a valid number.');
|
|
620
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
return options[selectedIndex];
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
export async function askYesNo(promptMessage, userInterface, defaultValue) {
|
|
628
|
-
const suffix = typeof defaultValue === 'boolean'
|
|
629
|
-
? defaultValue ? ' (Y/n): ' : ' (y/N): '
|
|
630
|
-
: ' (y/n): ';
|
|
631
|
-
|
|
632
|
-
while (true) {
|
|
633
|
-
const answer = await userInterface.question(`\n${promptMessage}${suffix}`);
|
|
634
|
-
const normalizedAnswer = answer.trim().toLowerCase();
|
|
635
|
-
|
|
636
|
-
if (!normalizedAnswer && typeof defaultValue === 'boolean') {
|
|
637
|
-
return defaultValue;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
if (normalizedAnswer === 'y' || normalizedAnswer === 'yes') return true;
|
|
641
|
-
if (normalizedAnswer === 'n' || normalizedAnswer === 'no') return false;
|
|
642
|
-
|
|
643
|
-
console.log("Please answer with 'y' or 'n'.");
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
345
|
export function toTitleCase(fileName) {
|
|
648
346
|
return fileName
|
|
649
347
|
.replace(/\.md$/i, '')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryuenn3123/agentic-senior-core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.38",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Force your AI Agent to code like a Staff Engineer, not a Junior.",
|
|
6
6
|
"bin": {
|
|
@@ -11,13 +11,31 @@
|
|
|
11
11
|
"lib/",
|
|
12
12
|
"scripts/",
|
|
13
13
|
".instructions.md",
|
|
14
|
-
".agent-context/",
|
|
14
|
+
".agent-context/policies/",
|
|
15
|
+
".agent-context/prompts/",
|
|
16
|
+
".agent-context/review-checklists/",
|
|
17
|
+
".agent-context/rules/",
|
|
18
|
+
".agent-context/state/README.md",
|
|
19
|
+
".agent-context/state/architecture-map.md",
|
|
20
|
+
".agent-context/state/dependency-map.md",
|
|
21
|
+
".agent-context/state/benchmark-comparison-schema.json",
|
|
22
|
+
".agent-context/state/benchmark-reproducibility.json",
|
|
23
|
+
".agent-context/state/benchmark-thresholds.json",
|
|
24
|
+
".agent-context/state/benchmark-watchlist.json",
|
|
25
|
+
".agent-context/state/benchmark-writer-judge-config.json",
|
|
26
|
+
".agent-context/state/memory-adapter-contract.json",
|
|
27
|
+
".agent-context/state/memory-schema-v1.json",
|
|
28
|
+
".agent-context/state/stack-research-snapshot.json",
|
|
15
29
|
".agents/",
|
|
30
|
+
".cursor/",
|
|
16
31
|
".github/",
|
|
17
32
|
".gemini/",
|
|
33
|
+
".windsurf/",
|
|
18
34
|
".cursorrules",
|
|
19
35
|
".windsurfrules",
|
|
20
36
|
"AGENTS.md",
|
|
37
|
+
"CLAUDE.md",
|
|
38
|
+
"GEMINI.md",
|
|
21
39
|
".agent-override.md",
|
|
22
40
|
"mcp.json",
|
|
23
41
|
"README.md",
|
|
@@ -65,6 +83,7 @@
|
|
|
65
83
|
"report:quality-trend": "node ./scripts/quality-trend-report.mjs",
|
|
66
84
|
"report:docs-quality-drift": "node ./scripts/docs-quality-drift-report.mjs",
|
|
67
85
|
"report:governance-weekly": "node ./scripts/governance-weekly-report.mjs",
|
|
86
|
+
"clean:local": "node ./scripts/clean-local-artifacts.mjs",
|
|
68
87
|
"validate": "node ./scripts/validate.mjs",
|
|
69
88
|
"test": "node --test ./tests/cli-smoke.test.mjs ./tests/mcp-server.test.mjs ./tests/llm-judge.test.mjs ./tests/ui-rubric-calibration.test.mjs ./tests/operations.test.mjs"
|
|
70
89
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { rm, stat } from 'node:fs/promises';
|
|
4
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const SCRIPT_FILE_PATH = fileURLToPath(import.meta.url);
|
|
8
|
+
const REPOSITORY_ROOT = resolve(dirname(SCRIPT_FILE_PATH), '..');
|
|
9
|
+
|
|
10
|
+
const LOCAL_ARTIFACT_PATHS = [
|
|
11
|
+
'test_output.txt',
|
|
12
|
+
'validate_output.txt',
|
|
13
|
+
'release-gate-report.json',
|
|
14
|
+
'.benchmarks',
|
|
15
|
+
'.agentic-backup',
|
|
16
|
+
'.agent-context/state/active-memory.json',
|
|
17
|
+
'.agent-context/state/v3-purge-audit.json',
|
|
18
|
+
'.agent-context/state/llm-judge-report.json',
|
|
19
|
+
'.agent-context/state/benchmark-analysis.json',
|
|
20
|
+
'.agent-context/state/benchmark-evidence-bundle.json',
|
|
21
|
+
'.agent-context/state/benchmark-history.json',
|
|
22
|
+
'.agent-context/state/benchmark-trend-report.csv',
|
|
23
|
+
'.agent-context/state/benchmark-trend-report.json',
|
|
24
|
+
'.agent-context/state/benchmark-writer-judge-matrix.json',
|
|
25
|
+
'.agent-context/state/docs-quality-drift-report.json',
|
|
26
|
+
'.agent-context/state/memory-continuity-benchmark.json',
|
|
27
|
+
'.agent-context/state/quality-trend-report.json',
|
|
28
|
+
'.agent-context/state/token-optimization-benchmark.json',
|
|
29
|
+
'.agent-context/state/weekly-governance-report.json',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
function resolveLocalArtifactPath(relativePath) {
|
|
33
|
+
const resolvedPath = resolve(REPOSITORY_ROOT, relativePath);
|
|
34
|
+
const repositoryRelativePath = relative(REPOSITORY_ROOT, resolvedPath);
|
|
35
|
+
|
|
36
|
+
if (
|
|
37
|
+
repositoryRelativePath.startsWith('..')
|
|
38
|
+
|| repositoryRelativePath === ''
|
|
39
|
+
|| resolve(repositoryRelativePath) === repositoryRelativePath
|
|
40
|
+
) {
|
|
41
|
+
throw new Error(`Refusing to clean path outside repository root: ${relativePath}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return resolvedPath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function pathExists(targetPath) {
|
|
48
|
+
try {
|
|
49
|
+
await stat(targetPath);
|
|
50
|
+
return true;
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let removedCount = 0;
|
|
57
|
+
let skippedCount = 0;
|
|
58
|
+
|
|
59
|
+
for (const relativePath of LOCAL_ARTIFACT_PATHS) {
|
|
60
|
+
const targetPath = resolveLocalArtifactPath(relativePath);
|
|
61
|
+
|
|
62
|
+
if (!(await pathExists(targetPath))) {
|
|
63
|
+
skippedCount += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
await rm(targetPath, {
|
|
68
|
+
force: true,
|
|
69
|
+
recursive: true,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
removedCount += 1;
|
|
73
|
+
console.log(`removed ${relativePath}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(`local artifact cleanup complete: removed=${removedCount}, skipped=${skippedCount}`);
|
|
@@ -26,8 +26,13 @@ const MONITORED_STATIC_FILE_PATHS = [
|
|
|
26
26
|
'CHANGELOG.md',
|
|
27
27
|
'.instructions.md',
|
|
28
28
|
'AGENTS.md',
|
|
29
|
+
'CLAUDE.md',
|
|
30
|
+
'GEMINI.md',
|
|
29
31
|
'.github/copilot-instructions.md',
|
|
32
|
+
'.github/instructions/agentic-senior-core.instructions.md',
|
|
30
33
|
'.gemini/instructions.md',
|
|
34
|
+
'.cursor/rules/agentic-senior-core.mdc',
|
|
35
|
+
'.windsurf/rules/agentic-senior-core.md',
|
|
31
36
|
'docs/deep_analysis_and_roadmap_backlog.md',
|
|
32
37
|
];
|
|
33
38
|
|
|
@@ -54,25 +54,29 @@ const REQUIRED_ARCHITECTURE_CHECKLIST_SNIPPETS = [
|
|
|
54
54
|
|
|
55
55
|
const REQUIRED_FRONTEND_RULE_SNIPPETS = [
|
|
56
56
|
'Frontend Design and Interaction Boundaries',
|
|
57
|
-
'
|
|
58
|
-
'##
|
|
59
|
-
'
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'Repo evidence outranks memory residue
|
|
65
|
-
'##
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
72
|
-
'##
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
57
|
+
'Load this rule for UI-facing work. Keep the loaded surface small.',
|
|
58
|
+
'## Activation',
|
|
59
|
+
'## Authority',
|
|
60
|
+
'Treat `.agent-context/` as design governance authority.',
|
|
61
|
+
'Treat `README.md` as overview/install/user context only',
|
|
62
|
+
'Do not choose final style, framework, palette, typography, layout paradigm, or animation library offline.',
|
|
63
|
+
'Keep design continuity opt-in.',
|
|
64
|
+
'Repo evidence outranks memory residue.',
|
|
65
|
+
'## Required Design Contract',
|
|
66
|
+
'## Anti-Generic UI Gate',
|
|
67
|
+
'Do not ship interchangeable dashboard chrome',
|
|
68
|
+
'Do not let repeated surfaces share one visual treatment by habit',
|
|
69
|
+
'Use the rename test:',
|
|
70
|
+
'decorative geometry are invalid as wallpaper',
|
|
71
|
+
'## Dynamic Anchor Gate',
|
|
72
|
+
'## Motion, Palette, and 3D',
|
|
73
|
+
'Treat motion, 3D, WebGL, canvas, scroll choreography, and animation libraries as first-class options.',
|
|
74
|
+
'Prefer visually exploratory, product-derived palettes while preserving WCAG contrast and status clarity.',
|
|
75
|
+
'## Responsive Mutation',
|
|
76
|
+
'Responsive quality is not scale-only.',
|
|
77
|
+
'## Accessibility',
|
|
78
|
+
'WCAG 2.2 AA is the hard floor.',
|
|
79
|
+
'APCA is advisory perceptual tuning only.',
|
|
76
80
|
'## Implementation Boundaries',
|
|
77
81
|
'Do not hardcode Zustand, React Query, smart/dumb component doctrine',
|
|
78
82
|
];
|