@ryuenn3123/agentic-senior-core 3.0.47 → 3.0.49
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 +8 -10
- package/.agent-context/prompts/init-project.md +2 -2
- package/.agent-context/rules/architecture.md +2 -2
- package/.agent-context/rules/frontend-architecture.md +9 -13
- package/.agent-context/state/architecture-map.md +3 -3
- package/.agent-context/state/dependency-map.md +2 -2
- package/AGENTS.md +170 -35
- package/CLAUDE.md +1 -44
- package/CONTRIBUTING.md +2 -3
- package/GEMINI.md +1 -44
- package/README.md +24 -22
- package/lib/cli/commands/init.mjs +10 -28
- package/lib/cli/commands/optimize.mjs +2 -48
- package/lib/cli/commands/upgrade.mjs +9 -51
- package/lib/cli/compiler.mjs +8 -93
- package/lib/cli/constants.mjs +1 -9
- package/lib/cli/detector.mjs +0 -1
- package/lib/cli/init-options.mjs +1 -1
- package/lib/cli/project-scaffolder/design-contract/validation.mjs +4 -0
- package/lib/cli/project-scaffolder/design-contract.mjs +4 -0
- package/lib/cli/project-scaffolder/prompt-builders.mjs +5 -1
- package/lib/cli/utils/filesystem.mjs +2 -0
- package/lib/cli/utils/managed-surface.mjs +45 -2
- package/lib/cli/utils.mjs +19 -4
- package/package.json +1 -10
- package/scripts/bump-version.mjs +1 -16
- package/scripts/docs-quality-drift-report.mjs +0 -6
- package/scripts/frontend-usability-audit.mjs +6 -2
- package/scripts/governance-weekly-report.mjs +2 -2
- package/scripts/single-source-lazy-loading-audit.mjs +13 -126
- package/scripts/sync-thin-adapters.mjs +13 -121
- package/scripts/validate/config.mjs +14 -25
- package/scripts/validate/coverage-checks.mjs +9 -76
- package/scripts/validate.mjs +12 -97
- package/.agent-override.md +0 -36
- package/.agents/workflows/init-project.md +0 -12
- package/.agents/workflows/refactor.md +0 -12
- package/.agents/workflows/review-code.md +0 -11
- package/.cursor/mcp.json +0 -10
- package/.cursor/rules/agentic-senior-core.mdc +0 -49
- package/.cursorrules +0 -26
- package/.gemini/instructions.md +0 -44
- package/.github/copilot-instructions.md +0 -44
- package/.github/instructions/agentic-senior-core.instructions.md +0 -48
- package/.github/workflows/benchmark-detection.yml +0 -45
- package/.github/workflows/benchmark-intelligence.yml +0 -50
- package/.github/workflows/docs-quality-drift-report.yml +0 -37
- package/.github/workflows/frontend-usability-gate.yml +0 -36
- package/.github/workflows/governance-weekly-report.yml +0 -43
- package/.github/workflows/publish.yml +0 -32
- package/.github/workflows/release-gate.yml +0 -32
- package/.github/workflows/sbom-compliance.yml +0 -32
- package/.instructions.md +0 -187
- package/.windsurf/rules/agentic-senior-core.md +0 -44
- package/.windsurfrules +0 -26
package/lib/cli/utils.mjs
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
collectRelativeTreeEntries,
|
|
24
24
|
analyzeManagedGovernanceSurface,
|
|
25
|
+
legacyManagedInstructionDirectories,
|
|
25
26
|
} from './utils/managed-surface.mjs';
|
|
26
27
|
export {
|
|
27
28
|
pathExists,
|
|
@@ -32,6 +33,7 @@ export {
|
|
|
32
33
|
} from './utils/filesystem.mjs';
|
|
33
34
|
export {
|
|
34
35
|
analyzeManagedGovernanceSurface,
|
|
36
|
+
legacyManagedInstructionDirectories,
|
|
35
37
|
} from './utils/managed-surface.mjs';
|
|
36
38
|
export {
|
|
37
39
|
askChoice,
|
|
@@ -71,8 +73,8 @@ export function printUsage() {
|
|
|
71
73
|
console.log(' --no-token-optimize Disable token optimization policy during init');
|
|
72
74
|
console.log(' --memory-continuity Explicitly enable cross-session memory continuity policy during init (default behavior)');
|
|
73
75
|
console.log(' --no-memory-continuity Disable memory continuity policy during init');
|
|
74
|
-
console.log(' --mcp-template Explicitly enable cross-IDE MCP auto-configuration (
|
|
75
|
-
console.log(' --no-mcp-template
|
|
76
|
+
console.log(' --mcp-template Explicitly enable cross-IDE MCP auto-configuration (opt-in)');
|
|
77
|
+
console.log(' --no-mcp-template Keep MCP configuration disabled (default behavior)');
|
|
76
78
|
console.log(' --scaffold-docs Force project documentation scaffolding (architecture, database, API, flow)');
|
|
77
79
|
console.log(' --no-scaffold-docs Skip project documentation scaffolding');
|
|
78
80
|
console.log(' --docs-lang Optional override for bootstrap docs synthesis language (default: en)');
|
|
@@ -83,8 +85,8 @@ export function printUsage() {
|
|
|
83
85
|
console.log(' --prune Keep managed governance files synchronized 1:1 (default in upgrade)');
|
|
84
86
|
console.log(' --no-prune Do not remove stale managed governance files during upgrade');
|
|
85
87
|
console.log(' --agent Target agent integration for token optimization mode');
|
|
86
|
-
console.log(' --enable Enable token optimization policy
|
|
87
|
-
console.log(' --disable Disable token optimization policy
|
|
88
|
+
console.log(' --enable Enable token optimization policy state');
|
|
89
|
+
console.log(' --disable Disable token optimization policy state');
|
|
88
90
|
console.log(' --show Print current token optimization state as JSON');
|
|
89
91
|
}
|
|
90
92
|
|
|
@@ -125,6 +127,17 @@ async function syncMcpConfig(mcpJsonPath, templateConfig) {
|
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
|
|
130
|
+
async function pruneEmptyLegacyInstructionDirectories(resolvedTargetDirectoryPath) {
|
|
131
|
+
for (const relativeDirectoryPath of legacyManagedInstructionDirectories) {
|
|
132
|
+
const directoryPath = path.join(resolvedTargetDirectoryPath, ...relativeDirectoryPath.split('/'));
|
|
133
|
+
try {
|
|
134
|
+
await fs.rmdir(directoryPath);
|
|
135
|
+
} catch {
|
|
136
|
+
// Keep non-empty or missing directories. They may contain user-owned files.
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
128
141
|
export async function copyGovernanceAssetsToTarget(
|
|
129
142
|
resolvedTargetDirectoryPath,
|
|
130
143
|
options = {}
|
|
@@ -205,6 +218,8 @@ export async function copyGovernanceAssetsToTarget(
|
|
|
205
218
|
await fs.rm(staleDirectoryPath, { recursive: true, force: true });
|
|
206
219
|
deletedManagedDirectories.push(staleDirectoryRelativePath);
|
|
207
220
|
}
|
|
221
|
+
|
|
222
|
+
await pruneEmptyLegacyInstructionDirectories(resolvedTargetDirectoryPath);
|
|
208
223
|
}
|
|
209
224
|
|
|
210
225
|
if (shouldIncludeMcpTemplate) {
|
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.49",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Force your AI Agent to code like a Staff Engineer, not a Junior.",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"lib/",
|
|
12
12
|
"scripts/",
|
|
13
|
-
".instructions.md",
|
|
14
13
|
".agent-context/policies/",
|
|
15
14
|
".agent-context/prompts/",
|
|
16
15
|
".agent-context/review-checklists/",
|
|
@@ -24,17 +23,9 @@
|
|
|
24
23
|
".agent-context/state/benchmark-writer-judge-config.json",
|
|
25
24
|
".agent-context/state/memory-adapter-contract.json",
|
|
26
25
|
".agent-context/state/memory-schema-v1.json",
|
|
27
|
-
".agents/",
|
|
28
|
-
".cursor/",
|
|
29
|
-
".github/",
|
|
30
|
-
".gemini/",
|
|
31
|
-
".windsurf/",
|
|
32
|
-
".cursorrules",
|
|
33
|
-
".windsurfrules",
|
|
34
26
|
"AGENTS.md",
|
|
35
27
|
"CLAUDE.md",
|
|
36
28
|
"GEMINI.md",
|
|
37
|
-
".agent-override.md",
|
|
38
29
|
"mcp.json",
|
|
39
30
|
"README.md",
|
|
40
31
|
"LICENSE",
|
package/scripts/bump-version.mjs
CHANGED
|
@@ -71,22 +71,7 @@ async function bumpVersion() {
|
|
|
71
71
|
console.log('Updated docs/deep-analysis-and-roadmap-backlog.md');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// 4. Update
|
|
75
|
-
const legacyAdapterFiles = ['.cursorrules', '.windsurfrules'];
|
|
76
|
-
for (const legacyAdapterFile of legacyAdapterFiles) {
|
|
77
|
-
const legacyAdapterPath = path.join(ROOT_DIR, legacyAdapterFile);
|
|
78
|
-
if (await fileExists(legacyAdapterPath)) {
|
|
79
|
-
const legacyAdapterContent = await readTextFile(legacyAdapterPath);
|
|
80
|
-
const updatedLegacyAdapterContent = legacyAdapterContent.replace(
|
|
81
|
-
/Generated by Agentic-Senior-Core CLI v\d+\.\d+\.\d+/,
|
|
82
|
-
`Generated by Agentic-Senior-Core CLI v${newVersion}`
|
|
83
|
-
);
|
|
84
|
-
await writeTextFile(legacyAdapterPath, updatedLegacyAdapterContent);
|
|
85
|
-
console.log(`Updated ${legacyAdapterFile}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// 5. Update CHANGELOG.md
|
|
74
|
+
// 4. Update CHANGELOG.md
|
|
90
75
|
const changelogPath = path.join(ROOT_DIR, 'CHANGELOG.md');
|
|
91
76
|
if (await fileExists(changelogPath)) {
|
|
92
77
|
let changelogContent = await readTextFile(changelogPath);
|
|
@@ -24,15 +24,9 @@ const LONG_SENTENCE_WORD_THRESHOLD = 28;
|
|
|
24
24
|
const MONITORED_STATIC_FILE_PATHS = [
|
|
25
25
|
'README.md',
|
|
26
26
|
'CHANGELOG.md',
|
|
27
|
-
'.instructions.md',
|
|
28
27
|
'AGENTS.md',
|
|
29
28
|
'CLAUDE.md',
|
|
30
29
|
'GEMINI.md',
|
|
31
|
-
'.github/copilot-instructions.md',
|
|
32
|
-
'.github/instructions/agentic-senior-core.instructions.md',
|
|
33
|
-
'.gemini/instructions.md',
|
|
34
|
-
'.cursor/rules/agentic-senior-core.mdc',
|
|
35
|
-
'.windsurf/rules/agentic-senior-core.md',
|
|
36
30
|
'docs/deep-analysis-and-roadmap-backlog.md',
|
|
37
31
|
];
|
|
38
32
|
|
|
@@ -20,7 +20,7 @@ const REQUIRED_FILES = [
|
|
|
20
20
|
'docs/roadmap.md',
|
|
21
21
|
'docs/archive/v1.7-issue-breakdown.md',
|
|
22
22
|
'docs/archive/v1.7-execution-playbook.md',
|
|
23
|
-
'.
|
|
23
|
+
'AGENTS.md',
|
|
24
24
|
'.agent-context/prompts/bootstrap-design.md',
|
|
25
25
|
'scripts/ui-design-judge.mjs',
|
|
26
26
|
'scripts/ui-rubric-calibration.mjs',
|
|
@@ -74,9 +74,12 @@ const REQUIRED_FRONTEND_RULE_SNIPPETS = [
|
|
|
74
74
|
'Prefer visually exploratory, product-derived palettes while preserving WCAG contrast and status clarity.',
|
|
75
75
|
'## Responsive Mutation',
|
|
76
76
|
'Responsive quality is not scale-only.',
|
|
77
|
+
'container queries',
|
|
77
78
|
'## Accessibility',
|
|
78
79
|
'WCAG 2.2 AA is the hard floor.',
|
|
79
80
|
'APCA is advisory perceptual tuning only.',
|
|
81
|
+
'## CSS Production Hardening',
|
|
82
|
+
'overflow, wrapping, truncation',
|
|
80
83
|
'## Implementation Boundaries',
|
|
81
84
|
'Do not hardcode Zustand, React Query, smart/dumb component doctrine',
|
|
82
85
|
];
|
|
@@ -89,6 +92,7 @@ const REQUIRED_BOOTSTRAP_DESIGN_SNIPPETS = [
|
|
|
89
92
|
'repoEvidence.designEvidenceSummary',
|
|
90
93
|
'research current official docs',
|
|
91
94
|
'Responsive design means recomposition, not resizing.',
|
|
95
|
+
'Implementation Craft Layer',
|
|
92
96
|
'agent-chosen visual direction',
|
|
93
97
|
'viewport mutation rules',
|
|
94
98
|
'WCAG 2.2 AA is the hard floor',
|
|
@@ -173,7 +177,7 @@ function runAudit() {
|
|
|
173
177
|
const roadmapPath = 'docs/roadmap.md';
|
|
174
178
|
const frontendRulePath = '.agent-context/rules/frontend-architecture.md';
|
|
175
179
|
const bootstrapDesignPromptPath = '.agent-context/prompts/bootstrap-design.md';
|
|
176
|
-
const instructionsPath = '.
|
|
180
|
+
const instructionsPath = 'AGENTS.md';
|
|
177
181
|
const prChecklistPath = '.agent-context/review-checklists/pr-checklist.md';
|
|
178
182
|
const architectureChecklistPath = '.agent-context/review-checklists/architecture-review.md';
|
|
179
183
|
const designEvidenceExtractorPath = 'lib/cli/detector/design-evidence.mjs';
|
|
@@ -44,7 +44,7 @@ const REQUIRED_VERIFIED_DOMAINS = new Set([
|
|
|
44
44
|
'state-continuity',
|
|
45
45
|
]);
|
|
46
46
|
const GOVERNANCE_SURFACE_PATHS = {
|
|
47
|
-
'canonical-instructions': '.
|
|
47
|
+
'canonical-instructions': 'AGENTS.md',
|
|
48
48
|
'frontend-design-contract': '.agent-context/prompts/bootstrap-design.md',
|
|
49
49
|
'frontend-architecture': '.agent-context/rules/frontend-architecture.md',
|
|
50
50
|
'backend-architecture': '.agent-context/rules/architecture.md',
|
|
@@ -75,7 +75,7 @@ const BACKEND_GOVERNANCE_COVERAGE = [
|
|
|
75
75
|
constraint: 'Global backend/API rule routing',
|
|
76
76
|
status: 'strengthened',
|
|
77
77
|
sourcePaths: [
|
|
78
|
-
'.
|
|
78
|
+
'AGENTS.md',
|
|
79
79
|
'.agent-context/rules/architecture.md',
|
|
80
80
|
'.agent-context/prompts/refactor.md',
|
|
81
81
|
],
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
import { existsSync, readFileSync } from 'node:fs';
|
|
13
13
|
import { execFileSync } from 'node:child_process';
|
|
14
|
-
import { createHash } from 'node:crypto';
|
|
15
14
|
import { dirname, resolve } from 'node:path';
|
|
16
15
|
import { fileURLToPath } from 'node:url';
|
|
17
16
|
|
|
@@ -19,28 +18,16 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
19
18
|
const __dirname = dirname(__filename);
|
|
20
19
|
const REPOSITORY_ROOT = resolve(__dirname, '..');
|
|
21
20
|
|
|
22
|
-
const CANONICAL_SOURCE_PATH = '.
|
|
21
|
+
const CANONICAL_SOURCE_PATH = 'AGENTS.md';
|
|
23
22
|
const ADAPTER_PATHS = [
|
|
24
|
-
'AGENTS.md',
|
|
25
23
|
'CLAUDE.md',
|
|
26
24
|
'GEMINI.md',
|
|
27
|
-
'.github/copilot-instructions.md',
|
|
28
|
-
'.github/instructions/agentic-senior-core.instructions.md',
|
|
29
|
-
'.gemini/instructions.md',
|
|
30
|
-
'.cursor/rules/agentic-senior-core.mdc',
|
|
31
|
-
'.windsurf/rules/agentic-senior-core.md',
|
|
32
25
|
];
|
|
33
26
|
const COMPILER_PATH = 'lib/cli/compiler.mjs';
|
|
34
27
|
const ONBOARDING_REPORT_PATH = '.agent-context/state/onboarding-report.json';
|
|
35
28
|
const ARCHITECTURE_RULE_PATH = '.agent-context/rules/architecture.md';
|
|
36
29
|
const PR_CHECKLIST_PATH = '.agent-context/review-checklists/pr-checklist.md';
|
|
37
30
|
const REVIEW_PROMPT_PATH = '.agent-context/prompts/review-code.md';
|
|
38
|
-
const COMPILED_RULE_PATHS = ['.cursorrules', '.windsurfrules'];
|
|
39
|
-
const REQUIRED_LEGACY_ROOT_ADAPTER_SNIPPETS = [
|
|
40
|
-
'Adapter Mode: legacy-thin',
|
|
41
|
-
'Adapter Source: .agent-instructions.md',
|
|
42
|
-
'Canonical baseline: .instructions.md',
|
|
43
|
-
];
|
|
44
31
|
|
|
45
32
|
const DEFAULT_WORKFLOW = 'standard';
|
|
46
33
|
const SUPPORTED_WORKFLOWS = new Set([
|
|
@@ -69,7 +56,7 @@ const MAX_EAGER_STACK_MENTIONS = 4;
|
|
|
69
56
|
|
|
70
57
|
const REQUIRED_ARCHITECTURE_RULE_SNIPPETS = [
|
|
71
58
|
'## Single Source of Truth and Lazy Rule Loading',
|
|
72
|
-
'Canonical rule source is .
|
|
59
|
+
'Canonical rule source is AGENTS.md.',
|
|
73
60
|
'Load global domain rules lazily based on touched scope.',
|
|
74
61
|
'Do not create or load stack-specific governance adapters as the baseline.',
|
|
75
62
|
];
|
|
@@ -273,11 +260,8 @@ function runAudit() {
|
|
|
273
260
|
pushResult(results, true, 'canonical-source-exists', `${CANONICAL_SOURCE_PATH} is present`);
|
|
274
261
|
}
|
|
275
262
|
|
|
276
|
-
const canonicalHash = canonicalSourceExists
|
|
277
|
-
|
|
278
|
-
: '';
|
|
279
|
-
|
|
280
|
-
let adapterHashPassCount = 0;
|
|
263
|
+
const canonicalHash = canonicalSourceExists ? 'native-import-bridges' : '';
|
|
264
|
+
let adapterImportPassCount = 0;
|
|
281
265
|
const adapterChecks = [];
|
|
282
266
|
|
|
283
267
|
for (const adapterPath of ADAPTER_PATHS) {
|
|
@@ -289,51 +273,27 @@ function runAudit() {
|
|
|
289
273
|
adapterChecks.push({
|
|
290
274
|
path: adapterPath,
|
|
291
275
|
exists: false,
|
|
292
|
-
|
|
293
|
-
sourcePointerValid: false,
|
|
294
|
-
hashMatchesCanonical: false,
|
|
276
|
+
importsCanonical: false,
|
|
295
277
|
});
|
|
296
278
|
continue;
|
|
297
279
|
}
|
|
298
280
|
|
|
299
281
|
pushResult(results, true, 'adapter-file-exists', `${adapterPath} is present`);
|
|
300
282
|
|
|
301
|
-
const
|
|
302
|
-
const sourcePointerValid = adapterContent.includes('Adapter Source: .instructions.md');
|
|
303
|
-
const hashMatch = adapterContent.match(/Canonical Snapshot SHA256:\s*([a-f0-9]{64})/);
|
|
304
|
-
const hashMatchesCanonical = Boolean(hashMatch && canonicalHash && hashMatch[1] === canonicalHash);
|
|
305
|
-
|
|
306
|
-
if (!thinAdapterMode) {
|
|
307
|
-
failures.push(`${adapterPath} must stay in thin adapter mode`);
|
|
308
|
-
pushResult(results, false, 'adapter-thin-mode', `${adapterPath} is missing Adapter Mode: thin metadata`);
|
|
309
|
-
} else {
|
|
310
|
-
pushResult(results, true, 'adapter-thin-mode', `${adapterPath} declares thin adapter mode`);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (!sourcePointerValid) {
|
|
314
|
-
failures.push(`${adapterPath} must point to canonical source .instructions.md`);
|
|
315
|
-
pushResult(results, false, 'adapter-canonical-source-pointer', `${adapterPath} is missing canonical source pointer`);
|
|
316
|
-
} else {
|
|
317
|
-
pushResult(results, true, 'adapter-canonical-source-pointer', `${adapterPath} points to canonical source`);
|
|
318
|
-
}
|
|
283
|
+
const importsCanonical = normalizeLineEndings(adapterContent).trim() === '@AGENTS.md';
|
|
319
284
|
|
|
320
|
-
if (!
|
|
321
|
-
failures.push(`${adapterPath} must
|
|
322
|
-
pushResult(results, false, 'adapter-canonical-
|
|
323
|
-
} else if (!hashMatchesCanonical) {
|
|
324
|
-
failures.push(`${adapterPath} canonical hash drift detected`);
|
|
325
|
-
pushResult(results, false, 'adapter-canonical-hash', `${adapterPath} hash does not match ${CANONICAL_SOURCE_PATH}`);
|
|
285
|
+
if (!importsCanonical) {
|
|
286
|
+
failures.push(`${adapterPath} must import canonical AGENTS.md`);
|
|
287
|
+
pushResult(results, false, 'adapter-canonical-import', `${adapterPath} is not @AGENTS.md`);
|
|
326
288
|
} else {
|
|
327
|
-
|
|
328
|
-
pushResult(results, true, 'adapter-canonical-
|
|
289
|
+
adapterImportPassCount += 1;
|
|
290
|
+
pushResult(results, true, 'adapter-canonical-import', `${adapterPath} imports AGENTS.md`);
|
|
329
291
|
}
|
|
330
292
|
|
|
331
293
|
adapterChecks.push({
|
|
332
294
|
path: adapterPath,
|
|
333
295
|
exists: true,
|
|
334
|
-
|
|
335
|
-
sourcePointerValid,
|
|
336
|
-
hashMatchesCanonical,
|
|
296
|
+
importsCanonical,
|
|
337
297
|
});
|
|
338
298
|
}
|
|
339
299
|
|
|
@@ -409,84 +369,11 @@ function runAudit() {
|
|
|
409
369
|
}
|
|
410
370
|
}
|
|
411
371
|
|
|
412
|
-
let compiledRulesCanonicalPassCount = 0;
|
|
413
372
|
let eagerLoadingDetected = false;
|
|
414
373
|
const compiledRuleChecks = [];
|
|
415
374
|
|
|
416
|
-
for (const compiledRulePath of COMPILED_RULE_PATHS) {
|
|
417
|
-
const compiledRuleContent = readText(compiledRulePath);
|
|
418
|
-
|
|
419
|
-
if (!compiledRuleContent) {
|
|
420
|
-
failures.push(`Missing compiled rules file: ${compiledRulePath}`);
|
|
421
|
-
pushResult(results, false, 'compiled-rules-file-exists', `Missing ${compiledRulePath}`);
|
|
422
|
-
compiledRuleChecks.push({
|
|
423
|
-
path: compiledRulePath,
|
|
424
|
-
exists: false,
|
|
425
|
-
canonicalBaselineDeclared: false,
|
|
426
|
-
stackMentionCount: 0,
|
|
427
|
-
eagerLoadingDetected: false,
|
|
428
|
-
});
|
|
429
|
-
continue;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
pushResult(results, true, 'compiled-rules-file-exists', `${compiledRulePath} is present`);
|
|
433
|
-
|
|
434
|
-
const canonicalBaselineDeclared = compiledRuleContent.includes('Canonical baseline: .instructions.md');
|
|
435
|
-
if (canonicalBaselineDeclared) {
|
|
436
|
-
compiledRulesCanonicalPassCount += 1;
|
|
437
|
-
pushResult(results, true, 'compiled-rules-canonical-baseline', `${compiledRulePath} declares canonical baseline`);
|
|
438
|
-
} else {
|
|
439
|
-
failures.push(`${compiledRulePath} must declare canonical baseline ${CANONICAL_SOURCE_PATH}`);
|
|
440
|
-
pushResult(results, false, 'compiled-rules-canonical-baseline', `${compiledRulePath} is missing canonical baseline declaration`);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const stackMentionCount = countStackMentions(compiledRuleContent);
|
|
444
|
-
const isEagerLoading = stackMentionCount > MAX_EAGER_STACK_MENTIONS;
|
|
445
|
-
const missingLegacyAdapterSnippets = REQUIRED_LEGACY_ROOT_ADAPTER_SNIPPETS
|
|
446
|
-
.filter((requiredSnippet) => !compiledRuleContent.includes(requiredSnippet));
|
|
447
|
-
|
|
448
|
-
if (missingLegacyAdapterSnippets.length > 0) {
|
|
449
|
-
failures.push(`${compiledRulePath} must stay a legacy thin adapter`);
|
|
450
|
-
pushResult(
|
|
451
|
-
results,
|
|
452
|
-
false,
|
|
453
|
-
'legacy-root-adapter-thin-mode',
|
|
454
|
-
`${compiledRulePath} is missing: ${missingLegacyAdapterSnippets.join(', ')}`
|
|
455
|
-
);
|
|
456
|
-
} else {
|
|
457
|
-
pushResult(results, true, 'legacy-root-adapter-thin-mode', `${compiledRulePath} stays legacy-thin`);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
if (isEagerLoading) {
|
|
461
|
-
eagerLoadingDetected = true;
|
|
462
|
-
failures.push(`${compiledRulePath} appears to preload too many stack profiles (${stackMentionCount})`);
|
|
463
|
-
pushResult(
|
|
464
|
-
results,
|
|
465
|
-
false,
|
|
466
|
-
'compiled-rules-lazy-loading-density',
|
|
467
|
-
`${compiledRulePath} has ${stackMentionCount} stack profile mentions; expected <= ${MAX_EAGER_STACK_MENTIONS}`
|
|
468
|
-
);
|
|
469
|
-
} else {
|
|
470
|
-
pushResult(
|
|
471
|
-
results,
|
|
472
|
-
true,
|
|
473
|
-
'compiled-rules-lazy-loading-density',
|
|
474
|
-
`${compiledRulePath} has ${stackMentionCount} stack profile mentions (lazy-loading threshold satisfied)`
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
compiledRuleChecks.push({
|
|
479
|
-
path: compiledRulePath,
|
|
480
|
-
exists: true,
|
|
481
|
-
canonicalBaselineDeclared,
|
|
482
|
-
stackMentionCount,
|
|
483
|
-
eagerLoadingDetected: isEagerLoading,
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
|
|
487
375
|
const canonicalSourceEnforced = canonicalSourceExists
|
|
488
|
-
&&
|
|
489
|
-
&& compiledRulesCanonicalPassCount === COMPILED_RULE_PATHS.length
|
|
376
|
+
&& adapterImportPassCount === ADAPTER_PATHS.length
|
|
490
377
|
&& architectureCoverageComplete
|
|
491
378
|
&& checklistCoverageComplete
|
|
492
379
|
&& reviewPromptCoverageComplete;
|
|
@@ -3,154 +3,47 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* sync-thin-adapters.mjs
|
|
5
5
|
*
|
|
6
|
-
* Regenerates
|
|
7
|
-
* and keeps canonical hash metadata synchronized.
|
|
6
|
+
* Regenerates minimal native-tool import bridges from canonical AGENTS.md.
|
|
8
7
|
*
|
|
9
8
|
* Usage:
|
|
10
9
|
* - node scripts/sync-thin-adapters.mjs
|
|
11
10
|
* - node scripts/sync-thin-adapters.mjs --check
|
|
12
11
|
*/
|
|
13
12
|
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { dirname, join, posix, resolve } from 'node:path';
|
|
13
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
14
|
+
import { join, resolve, dirname } from 'node:path';
|
|
17
15
|
import { fileURLToPath } from 'node:url';
|
|
18
16
|
|
|
19
17
|
const SCRIPT_FILE_PATH = fileURLToPath(import.meta.url);
|
|
20
18
|
const ROOT_DIR = resolve(dirname(SCRIPT_FILE_PATH), '..');
|
|
21
|
-
const CANONICAL_SOURCE_PATH = '.instructions.md';
|
|
22
|
-
const CANONICAL_SOURCE_ABSOLUTE_PATH = join(ROOT_DIR, CANONICAL_SOURCE_PATH);
|
|
23
19
|
const IS_CHECK_MODE = process.argv.includes('--check');
|
|
24
20
|
|
|
25
|
-
function normalizeLineEndings(content) {
|
|
26
|
-
return content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function buildAdapterLink(adapterRelativePath, targetRelativePath) {
|
|
30
|
-
const adapterDirectoryPath = posix.dirname(adapterRelativePath);
|
|
31
|
-
const relativePath = posix.relative(adapterDirectoryPath === '.' ? '' : adapterDirectoryPath, targetRelativePath);
|
|
32
|
-
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function buildThinAdapter({
|
|
36
|
-
relativePath,
|
|
37
|
-
title,
|
|
38
|
-
canonicalHash,
|
|
39
|
-
frontmatter = '',
|
|
40
|
-
}) {
|
|
41
|
-
const canonicalLink = buildAdapterLink(relativePath, '.instructions.md');
|
|
42
|
-
const rulesLink = buildAdapterLink(relativePath, '.agent-context/rules');
|
|
43
|
-
const promptsLink = buildAdapterLink(relativePath, '.agent-context/prompts');
|
|
44
|
-
const designPromptLink = buildAdapterLink(relativePath, '.agent-context/prompts/bootstrap-design.md');
|
|
45
|
-
const frontendRuleLink = buildAdapterLink(relativePath, '.agent-context/rules/frontend-architecture.md');
|
|
46
|
-
const checklistLink = buildAdapterLink(relativePath, '.agent-context/review-checklists/pr-checklist.md');
|
|
47
|
-
const stateLink = buildAdapterLink(relativePath, '.agent-context/state');
|
|
48
|
-
const policiesLink = buildAdapterLink(relativePath, '.agent-context/policies');
|
|
49
|
-
const adapterHeader = frontmatter.trim() ? [frontmatter.trim(), ''] : [];
|
|
50
|
-
|
|
51
|
-
return [
|
|
52
|
-
...adapterHeader,
|
|
53
|
-
`# ${title}`,
|
|
54
|
-
'',
|
|
55
|
-
'Adapter Mode: thin',
|
|
56
|
-
'Adapter Source: .instructions.md',
|
|
57
|
-
`Canonical Snapshot SHA256: ${canonicalHash}`,
|
|
58
|
-
'',
|
|
59
|
-
'This repository is governed by a strict instruction contract.',
|
|
60
|
-
`Use [${CANONICAL_SOURCE_PATH}](${canonicalLink}) as the canonical policy source.`,
|
|
61
|
-
'Use .agent-context/ for technical rules, prompts, checklists, policies, and state.',
|
|
62
|
-
'Treat README.md as public and developer overview, setup, usage, and user-facing context only when governance files conflict.',
|
|
63
|
-
'',
|
|
64
|
-
'## Critical Bootstrap Floor',
|
|
65
|
-
'',
|
|
66
|
-
'- If your host stops at this file, continue the chain manually before coding.',
|
|
67
|
-
'- Read `.agent-instructions.md` next when it exists.',
|
|
68
|
-
'- Memory continuity does not replace bootstrap loading.',
|
|
69
|
-
`- For UI, UX, layout, screen, tailwind, frontend, or redesign requests, load [bootstrap-design.md](${designPromptLink}) and [frontend-architecture.md](${frontendRuleLink}) before code edits.`,
|
|
70
|
-
'- For UI scope, include a one-line Motion/Palette Decision in the Bootstrap Receipt; product categories are heuristics, not style presets.',
|
|
71
|
-
'- For UI scope, create or refine `docs/DESIGN.md` and `docs/design-intent.json` before UI implementation.',
|
|
72
|
-
'- For documentation-first requests, create or refine required project docs in English by default and do not write application, firmware, or UI code until the user asks or approves.',
|
|
73
|
-
'- Create or refine root README.md as the public and developer entrypoint before implementation.',
|
|
74
|
-
`- For backend, API, data, auth, error, event, queue, worker, or distributed-system requests, load only relevant global rules from .agent-context/rules/ ([link](${rulesLink})).`,
|
|
75
|
-
'- For ecosystem, framework, dependency, or Docker claims, perform live web research.',
|
|
76
|
-
'- Resolve runtime choices from project evidence and live official documentation; resolve structural planning from constraints and architecture boundaries.',
|
|
77
|
-
'',
|
|
78
|
-
'## Mandatory Bootstrap Chain',
|
|
79
|
-
'',
|
|
80
|
-
`1. Load [${CANONICAL_SOURCE_PATH}](${canonicalLink}).`,
|
|
81
|
-
'2. Load `.agent-instructions.md` when present.',
|
|
82
|
-
`3. Load only relevant files from .agent-context/rules/ ([link](${rulesLink})).`,
|
|
83
|
-
`4. Apply matching prompts from .agent-context/prompts/ ([link](${promptsLink})).`,
|
|
84
|
-
`5. Enforce .agent-context/review-checklists/ ([link](${checklistLink})).`,
|
|
85
|
-
`6. Use .agent-context/state/ ([link](${stateLink})) and .agent-context/policies/ ([link](${policiesLink})) only when relevant.`,
|
|
86
|
-
'7. Use project docs and live evidence for runtime, dependency, and architecture claims.',
|
|
87
|
-
'',
|
|
88
|
-
'## Bootstrap Receipt',
|
|
89
|
-
'',
|
|
90
|
-
'For non-trivial coding, review, planning, or governance work, produce a short Bootstrap Receipt before implementation output: `loaded_files`, `selected_rules`, `skipped_rules`, `unreachable_files`, and `validation_plan`.',
|
|
91
|
-
'',
|
|
92
|
-
'## Completion Gate',
|
|
93
|
-
'',
|
|
94
|
-
`Run [pr-checklist.md](${checklistLink}) before declaring work complete.`,
|
|
95
|
-
'',
|
|
96
|
-
`If this adapter drifts from canonical behavior, refresh from [${CANONICAL_SOURCE_PATH}](${canonicalLink}) and update the hash metadata.`,
|
|
97
|
-
].join('\n');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
21
|
const ADAPTERS = [
|
|
101
|
-
{
|
|
102
|
-
relativePath: 'AGENTS.md',
|
|
103
|
-
title: 'AGENTS.md - Thin Adapter',
|
|
104
|
-
},
|
|
105
22
|
{
|
|
106
23
|
relativePath: 'CLAUDE.md',
|
|
107
|
-
|
|
24
|
+
content: '@AGENTS.md\n',
|
|
108
25
|
},
|
|
109
26
|
{
|
|
110
27
|
relativePath: 'GEMINI.md',
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
relativePath: '.github/copilot-instructions.md',
|
|
115
|
-
title: 'GitHub Copilot Instructions - Thin Adapter',
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
relativePath: '.github/instructions/agentic-senior-core.instructions.md',
|
|
119
|
-
title: 'GitHub Copilot Path Instructions - Thin Adapter',
|
|
120
|
-
frontmatter: '---\napplyTo: "**"\n---',
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
relativePath: '.gemini/instructions.md',
|
|
124
|
-
title: 'Gemini Instructions - Thin Adapter',
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
relativePath: '.cursor/rules/agentic-senior-core.mdc',
|
|
128
|
-
title: 'Cursor Rule - Thin Adapter',
|
|
129
|
-
frontmatter: '---\ndescription: Agentic Senior Core bootstrap adapter\nalwaysApply: true\n---',
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
relativePath: '.windsurf/rules/agentic-senior-core.md',
|
|
133
|
-
title: 'Windsurf Rule - Thin Adapter',
|
|
28
|
+
content: '@AGENTS.md\n',
|
|
134
29
|
},
|
|
135
30
|
];
|
|
136
31
|
|
|
32
|
+
function normalizeLineEndings(content) {
|
|
33
|
+
return content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
34
|
+
}
|
|
35
|
+
|
|
137
36
|
async function main() {
|
|
138
|
-
|
|
139
|
-
const canonicalHash = createHash('sha256').update(canonicalContent).digest('hex');
|
|
37
|
+
await readFile(join(ROOT_DIR, 'AGENTS.md'), 'utf8');
|
|
140
38
|
|
|
141
39
|
let hasDrift = false;
|
|
142
40
|
|
|
143
41
|
for (const adapter of ADAPTERS) {
|
|
144
42
|
const adapterAbsolutePath = join(ROOT_DIR, adapter.relativePath);
|
|
145
|
-
const expectedContent = buildThinAdapter({
|
|
146
|
-
...adapter,
|
|
147
|
-
canonicalHash,
|
|
148
|
-
});
|
|
149
43
|
|
|
150
44
|
if (IS_CHECK_MODE) {
|
|
151
45
|
const existingContent = normalizeLineEndings(await readFile(adapterAbsolutePath, 'utf8'));
|
|
152
|
-
|
|
153
|
-
if (existingContent !== expectedNormalized) {
|
|
46
|
+
if (existingContent !== adapter.content) {
|
|
154
47
|
hasDrift = true;
|
|
155
48
|
console.error(`[DRIFT] ${adapter.relativePath} does not match canonical adapter output.`);
|
|
156
49
|
} else {
|
|
@@ -159,8 +52,7 @@ async function main() {
|
|
|
159
52
|
continue;
|
|
160
53
|
}
|
|
161
54
|
|
|
162
|
-
await
|
|
163
|
-
await writeFile(adapterAbsolutePath, `${expectedContent.trimEnd()}\n`, 'utf8');
|
|
55
|
+
await writeFile(adapterAbsolutePath, adapter.content, 'utf8');
|
|
164
56
|
console.log(`[SYNC] ${adapter.relativePath}`);
|
|
165
57
|
}
|
|
166
58
|
|
|
@@ -170,7 +62,7 @@ async function main() {
|
|
|
170
62
|
return;
|
|
171
63
|
}
|
|
172
64
|
|
|
173
|
-
console.log('[OK] All
|
|
65
|
+
console.log('[OK] All native import bridges match canonical source output.');
|
|
174
66
|
}
|
|
175
67
|
}
|
|
176
68
|
|