@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.
Files changed (55) hide show
  1. package/.agent-context/prompts/bootstrap-design.md +8 -10
  2. package/.agent-context/prompts/init-project.md +2 -2
  3. package/.agent-context/rules/architecture.md +2 -2
  4. package/.agent-context/rules/frontend-architecture.md +9 -13
  5. package/.agent-context/state/architecture-map.md +3 -3
  6. package/.agent-context/state/dependency-map.md +2 -2
  7. package/AGENTS.md +170 -35
  8. package/CLAUDE.md +1 -44
  9. package/CONTRIBUTING.md +2 -3
  10. package/GEMINI.md +1 -44
  11. package/README.md +24 -22
  12. package/lib/cli/commands/init.mjs +10 -28
  13. package/lib/cli/commands/optimize.mjs +2 -48
  14. package/lib/cli/commands/upgrade.mjs +9 -51
  15. package/lib/cli/compiler.mjs +8 -93
  16. package/lib/cli/constants.mjs +1 -9
  17. package/lib/cli/detector.mjs +0 -1
  18. package/lib/cli/init-options.mjs +1 -1
  19. package/lib/cli/project-scaffolder/design-contract/validation.mjs +4 -0
  20. package/lib/cli/project-scaffolder/design-contract.mjs +4 -0
  21. package/lib/cli/project-scaffolder/prompt-builders.mjs +5 -1
  22. package/lib/cli/utils/filesystem.mjs +2 -0
  23. package/lib/cli/utils/managed-surface.mjs +45 -2
  24. package/lib/cli/utils.mjs +19 -4
  25. package/package.json +1 -10
  26. package/scripts/bump-version.mjs +1 -16
  27. package/scripts/docs-quality-drift-report.mjs +0 -6
  28. package/scripts/frontend-usability-audit.mjs +6 -2
  29. package/scripts/governance-weekly-report.mjs +2 -2
  30. package/scripts/single-source-lazy-loading-audit.mjs +13 -126
  31. package/scripts/sync-thin-adapters.mjs +13 -121
  32. package/scripts/validate/config.mjs +14 -25
  33. package/scripts/validate/coverage-checks.mjs +9 -76
  34. package/scripts/validate.mjs +12 -97
  35. package/.agent-override.md +0 -36
  36. package/.agents/workflows/init-project.md +0 -12
  37. package/.agents/workflows/refactor.md +0 -12
  38. package/.agents/workflows/review-code.md +0 -11
  39. package/.cursor/mcp.json +0 -10
  40. package/.cursor/rules/agentic-senior-core.mdc +0 -49
  41. package/.cursorrules +0 -26
  42. package/.gemini/instructions.md +0 -44
  43. package/.github/copilot-instructions.md +0 -44
  44. package/.github/instructions/agentic-senior-core.instructions.md +0 -48
  45. package/.github/workflows/benchmark-detection.yml +0 -45
  46. package/.github/workflows/benchmark-intelligence.yml +0 -50
  47. package/.github/workflows/docs-quality-drift-report.yml +0 -37
  48. package/.github/workflows/frontend-usability-gate.yml +0 -36
  49. package/.github/workflows/governance-weekly-report.yml +0 -43
  50. package/.github/workflows/publish.yml +0 -32
  51. package/.github/workflows/release-gate.yml +0 -32
  52. package/.github/workflows/sbom-compliance.yml +0 -32
  53. package/.instructions.md +0 -187
  54. package/.windsurf/rules/agentic-senior-core.md +0 -44
  55. 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 (default behavior)');
75
- console.log(' --no-mcp-template Disable automatic MCP configuration across your IDEs');
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 and rebuild compiled rules');
87
- console.log(' --disable Disable token optimization policy and rebuild compiled rules');
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.47",
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",
@@ -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 legacy root adapters that carry release metadata.
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
- '.instructions.md',
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 = '.instructions.md';
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': '.instructions.md',
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
- '.instructions.md',
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 = '.instructions.md';
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 .instructions.md.',
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
- ? createHash('sha256').update(normalizeLineEndings(canonicalSourceContent)).digest('hex')
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
- thinAdapterMode: false,
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 thinAdapterMode = adapterContent.includes('Adapter Mode: thin');
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 (!hashMatch) {
321
- failures.push(`${adapterPath} must declare Canonical Snapshot SHA256`);
322
- pushResult(results, false, 'adapter-canonical-hash', `${adapterPath} is missing Canonical Snapshot SHA256 metadata`);
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
- adapterHashPassCount += 1;
328
- pushResult(results, true, 'adapter-canonical-hash', `${adapterPath} hash matches canonical source`);
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
- thinAdapterMode,
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
- && adapterHashPassCount === ADAPTER_PATHS.length
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 thin instruction adapters from the canonical policy source
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 { mkdir, readFile, writeFile } from 'node:fs/promises';
15
- import { createHash } from 'node:crypto';
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
- title: 'CLAUDE.md - Thin Adapter',
24
+ content: '@AGENTS.md\n',
108
25
  },
109
26
  {
110
27
  relativePath: 'GEMINI.md',
111
- title: 'GEMINI.md - Thin Adapter',
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
- const canonicalContent = normalizeLineEndings(await readFile(CANONICAL_SOURCE_ABSOLUTE_PATH, 'utf8'));
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
- const expectedNormalized = normalizeLineEndings(`${expectedContent.trimEnd()}\n`);
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 mkdir(dirname(adapterAbsolutePath), { recursive: true });
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 thin adapters match canonical source output.');
65
+ console.log('[OK] All native import bridges match canonical source output.');
174
66
  }
175
67
  }
176
68