@ryuenn3123/agentic-senior-core 3.0.37 → 3.0.39

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 (66) hide show
  1. package/.agent-context/prompts/bootstrap-design.md +109 -146
  2. package/.agent-context/rules/frontend-architecture.md +92 -108
  3. package/.agent-context/state/README.md +26 -0
  4. package/.agent-context/state/architecture-map.md +32 -17
  5. package/.agent-context/state/dependency-map.md +31 -22
  6. package/.cursor/mcp.json +10 -0
  7. package/.cursor/rules/agentic-senior-core.mdc +48 -0
  8. package/.cursorrules +22 -88
  9. package/.gemini/instructions.md +25 -16
  10. package/.github/copilot-instructions.md +25 -16
  11. package/.github/instructions/agentic-senior-core.instructions.md +47 -0
  12. package/.instructions.md +98 -207
  13. package/.windsurf/rules/agentic-senior-core.md +43 -0
  14. package/.windsurfrules +22 -88
  15. package/AGENTS.md +23 -26
  16. package/CLAUDE.md +43 -0
  17. package/CONTRIBUTING.md +7 -2
  18. package/GEMINI.md +43 -0
  19. package/README.md +25 -7
  20. package/lib/cli/backup.mjs +4 -4
  21. package/lib/cli/commands/init/project-context.mjs +101 -0
  22. package/lib/cli/commands/init/runtime-environment.mjs +59 -0
  23. package/lib/cli/commands/init/setup-decisions.mjs +83 -0
  24. package/lib/cli/commands/init.mjs +33 -250
  25. package/lib/cli/commands/optimize.mjs +1 -1
  26. package/lib/cli/commands/upgrade.mjs +34 -16
  27. package/lib/cli/compiler.mjs +59 -17
  28. package/lib/cli/constants.mjs +5 -0
  29. package/lib/cli/detector.mjs +4 -0
  30. package/lib/cli/init-detection-flow.mjs +9 -1
  31. package/lib/cli/init-selection.mjs +0 -5
  32. package/lib/cli/preflight.mjs +3 -3
  33. package/lib/cli/project-scaffolder/design-contract/validation.mjs +789 -0
  34. package/lib/cli/project-scaffolder/design-contract.mjs +119 -924
  35. package/lib/cli/project-scaffolder/prompt-builders.mjs +69 -84
  36. package/lib/cli/project-scaffolder.mjs +0 -2
  37. package/lib/cli/utils/filesystem.mjs +79 -0
  38. package/lib/cli/utils/managed-surface.mjs +237 -0
  39. package/lib/cli/utils/prompting.mjs +44 -0
  40. package/lib/cli/utils.mjs +33 -335
  41. package/package.json +21 -2
  42. package/scripts/bump-version.mjs +15 -13
  43. package/scripts/clean-local-artifacts.mjs +76 -0
  44. package/scripts/docs-quality-drift-report.mjs +5 -0
  45. package/scripts/frontend-usability-audit.mjs +23 -19
  46. package/scripts/governance-weekly-report.mjs +37 -15
  47. package/scripts/single-source-lazy-loading-audit.mjs +24 -0
  48. package/scripts/sync-thin-adapters.mjs +99 -129
  49. package/scripts/v3-purge-audit.mjs +5 -0
  50. package/scripts/validate/config.mjs +10 -0
  51. package/scripts/validate/coverage-checks.mjs +55 -0
  52. package/scripts/validate.mjs +20 -0
  53. package/.agent-context/marketplace/trust-tiers.json +0 -114
  54. package/.agent-context/state/benchmark-analysis.json +0 -431
  55. package/.agent-context/state/benchmark-evidence-bundle.json +0 -1040
  56. package/.agent-context/state/benchmark-history.json +0 -75
  57. package/.agent-context/state/benchmark-trend-report.csv +0 -5
  58. package/.agent-context/state/benchmark-trend-report.json +0 -140
  59. package/.agent-context/state/benchmark-writer-judge-matrix.json +0 -462
  60. package/.agent-context/state/memory-continuity-benchmark.json +0 -132
  61. package/.agent-context/state/onboarding-report.json +0 -102
  62. package/.agent-context/state/quality-trend-report.json +0 -89
  63. package/.agent-context/state/token-optimization-benchmark.json +0 -130
  64. package/.agent-context/state/weekly-governance-report.json +0 -329
  65. package/lib/cli/compatibility.mjs +0 -124
  66. package/scripts/validate-evidence-bundle.mjs +0 -76
@@ -8,7 +8,6 @@ import fs from 'node:fs/promises';
8
8
  import path from 'node:path';
9
9
 
10
10
  import {
11
- PROJECT_SCOPE_CHOICES,
12
11
  CLI_VERSION,
13
12
  AGENT_CONTEXT_DIR,
14
13
  INIT_PRESETS,
@@ -16,15 +15,12 @@ import {
16
15
  GOLDEN_STANDARD_PROFILE_NAME,
17
16
  AGENT_DECISION_STACK_FILE_NAME,
18
17
  AGENT_DECISION_BLUEPRINT_FILE_NAME,
19
- RUNTIME_ENVIRONMENT_CHOICES,
20
18
  } from '../constants.mjs';
21
19
 
22
20
  import {
23
21
  ensureDirectory,
24
22
  askYesNo,
25
23
  toTitleCase,
26
- matchFileNameFromInput,
27
- normalizeChoiceInput,
28
24
  collectFileNames,
29
25
  formatBlockingSeverities,
30
26
  formatDuration,
@@ -56,7 +52,6 @@ import {
56
52
  hasExistingProjectDocs,
57
53
  loadProjectConfig,
58
54
  normalizeDocsLanguage,
59
- buildDesignIntentSeedFromSignals,
60
55
  } from '../project-scaffolder.mjs';
61
56
  import { performRollback } from '../rollback.mjs';
62
57
  import {
@@ -70,6 +65,21 @@ import {
70
65
  ensureActiveMemorySnapshot,
71
66
  writeMemoryContinuityState,
72
67
  } from '../memory-continuity.mjs';
68
+ import {
69
+ buildInitExistingProjectDesignIntentSeed,
70
+ inferExistingProjectDescriptionHint,
71
+ } from './init/project-context.mjs';
72
+ import {
73
+ detectRuntimeEnvironment,
74
+ resolveRuntimeEnvironmentKeyFromLabel,
75
+ resolveRuntimeEnvironmentLabelFromKey,
76
+ } from './init/runtime-environment.mjs';
77
+ import {
78
+ inferProjectScopeFromDiscoveryAnswers,
79
+ normalizeExplicitProfileFileName,
80
+ resolveProjectScopeLabelFromKey,
81
+ resolveSilentCiGuardrailsDefault,
82
+ } from './init/setup-decisions.mjs';
73
83
 
74
84
  export { REPO_ROOT } from '../constants.mjs';
75
85
  export {
@@ -81,242 +91,11 @@ export {
81
91
  normalizeAdditionalStackSelection,
82
92
  normalizeAdditionalBlueprintSelection,
83
93
  } from '../init-selection.mjs';
84
-
85
- function normalizeContextLine(rawText) {
86
- return String(rawText || '')
87
- .replace(/\s+/g, ' ')
88
- .trim();
89
- }
90
-
91
- async function readTextIfExists(filePath) {
92
- try {
93
- return await fs.readFile(filePath, 'utf8');
94
- } catch {
95
- return '';
96
- }
97
- }
98
-
99
- function extractMarkdownContext(rawMarkdown) {
100
- return String(rawMarkdown || '')
101
- .split(/\r?\n/)
102
- .map((line) => normalizeContextLine(line.replace(/^#+\s*/, '')))
103
- .filter((line) => line && !line.startsWith('---') && !line.startsWith('```'))
104
- .slice(0, 3)
105
- .join(' ');
106
- }
107
-
108
- async function inferExistingProjectDescriptionHint(targetDirectoryPath) {
109
- const evidence = [];
110
- const packageJsonContent = await readTextIfExists(path.join(targetDirectoryPath, 'package.json'));
111
-
112
- if (packageJsonContent) {
113
- try {
114
- const packageManifest = JSON.parse(packageJsonContent);
115
- const packageSummary = [
116
- normalizeContextLine(packageManifest.name),
117
- normalizeContextLine(packageManifest.description),
118
- ].filter(Boolean).join(': ');
119
-
120
- if (packageSummary) {
121
- evidence.push(`package.json: ${packageSummary}`);
122
- }
123
- } catch {
124
- // Invalid package metadata should not block init; other files can still provide context.
125
- }
126
- }
127
-
128
- for (const relativeDocPath of ['docs/project-brief.md', 'docs/README.md', 'README.md']) {
129
- const docContext = extractMarkdownContext(
130
- await readTextIfExists(path.join(targetDirectoryPath, relativeDocPath))
131
- );
132
-
133
- if (docContext) {
134
- evidence.push(`${relativeDocPath}: ${docContext}`);
135
- }
136
- }
137
-
138
- return evidence.slice(0, 3).join(' | ');
139
- }
140
-
141
- export function resolveRuntimeEnvironmentKeyFromLabel(selectedRuntimeEnvironmentLabel) {
142
- const runtimeEnvironmentEntry = RUNTIME_ENVIRONMENT_CHOICES.find(
143
- (runtimeEnvironmentChoice) => runtimeEnvironmentChoice.label === selectedRuntimeEnvironmentLabel
144
- );
145
-
146
- return runtimeEnvironmentEntry?.key || null;
147
- }
148
-
149
- export function resolveRuntimeEnvironmentLabelFromKey(runtimeEnvironmentKey) {
150
- const runtimeEnvironmentEntry = RUNTIME_ENVIRONMENT_CHOICES.find(
151
- (runtimeEnvironmentChoice) => runtimeEnvironmentChoice.key === runtimeEnvironmentKey
152
- );
153
-
154
- return runtimeEnvironmentEntry?.label || runtimeEnvironmentKey;
155
- }
156
-
157
- export function detectRuntimeEnvironment() {
158
- const isWslEnvironment = Boolean(process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP || process.env.__IS_WSL_TEST__);
159
-
160
- if (isWslEnvironment) {
161
- return {
162
- key: 'linux-wsl',
163
- label: resolveRuntimeEnvironmentLabelFromKey('linux-wsl'),
164
- shellFamily: 'bash',
165
- isAutoDetected: true,
166
- source: 'WSL environment markers',
167
- };
168
- }
169
-
170
- if (process.platform === 'win32') {
171
- return {
172
- key: 'windows',
173
- label: resolveRuntimeEnvironmentLabelFromKey('windows'),
174
- shellFamily: 'powershell',
175
- isAutoDetected: true,
176
- source: 'process.platform',
177
- };
178
- }
179
-
180
- if (process.platform === 'darwin') {
181
- return {
182
- key: 'macos',
183
- label: resolveRuntimeEnvironmentLabelFromKey('macos'),
184
- shellFamily: 'bash',
185
- isAutoDetected: true,
186
- source: 'process.platform',
187
- };
188
- }
189
-
190
- return {
191
- key: 'linux',
192
- label: resolveRuntimeEnvironmentLabelFromKey('linux'),
193
- shellFamily: 'bash',
194
- isAutoDetected: true,
195
- source: 'process.platform',
196
- };
197
- }
198
-
199
- function resolveProjectScopeLabelFromKey(projectScopeKey) {
200
- return PROJECT_SCOPE_CHOICES.find((scopeChoice) => scopeChoice.key === projectScopeKey)?.label
201
- || PROJECT_SCOPE_CHOICES.find((scopeChoice) => scopeChoice.key === 'both')?.label
202
- || 'Both (frontend + backend)';
203
- }
204
-
205
- function inferProjectScopeFromDiscoveryAnswers(discoveryAnswers) {
206
- const normalizedDomain = String(discoveryAnswers?.primaryDomain || '').trim().toLowerCase();
207
- const normalizedDescription = [
208
- discoveryAnswers?.projectDescription,
209
- ...(Array.isArray(discoveryAnswers?.features) ? discoveryAnswers.features : []),
210
- ].join(' ').toLowerCase();
211
-
212
- if (
213
- normalizedDomain.includes('api service')
214
- || normalizedDomain.includes('cli tool')
215
- || normalizedDomain.includes('library')
216
- ) {
217
- return 'backend-only';
218
- }
219
-
220
- if (normalizedDomain.includes('mobile app')) {
221
- return 'frontend-only';
222
- }
223
-
224
- if (normalizedDomain.includes('web application')) {
225
- if (/(landing page|marketing site|showcase|portfolio|brochure|company profile)/.test(normalizedDescription)) {
226
- return 'frontend-only';
227
- }
228
-
229
- return 'both';
230
- }
231
-
232
- return 'both';
233
- }
234
-
235
- function resolveSilentCiGuardrailsDefault({
236
- initOptions,
237
- selectedPreset,
238
- selectedPolicyProfile,
239
- }) {
240
- if (typeof initOptions.ci === 'boolean') {
241
- return {
242
- value: initOptions.ci,
243
- shouldAsk: false,
244
- };
245
- }
246
-
247
- if (typeof selectedPreset?.ci === 'boolean') {
248
- return {
249
- value: selectedPreset.ci,
250
- shouldAsk: false,
251
- };
252
- }
253
-
254
- if (selectedPolicyProfile.lockCi) {
255
- return {
256
- value: selectedPolicyProfile.defaultCi,
257
- shouldAsk: false,
258
- };
259
- }
260
-
261
- return {
262
- value: selectedPolicyProfile.defaultCi,
263
- shouldAsk: true,
264
- };
265
- }
266
-
267
- function normalizeExplicitProfileFileName(rawInput, discoveredFileNames) {
268
- const matchedFileName = Array.isArray(discoveredFileNames) && discoveredFileNames.length > 0
269
- ? matchFileNameFromInput(rawInput, discoveredFileNames)
270
- : null;
271
-
272
- if (matchedFileName) {
273
- return matchedFileName;
274
- }
275
-
276
- const normalizedBaseName = normalizeChoiceInput(String(rawInput || '').replace(/\.md$/i, ''));
277
- return normalizedBaseName ? `${normalizedBaseName}.md` : null;
278
- }
279
-
280
- function buildInitExistingProjectDesignIntentSeed({
281
- targetDirectoryPath,
282
- packageManifest,
283
- selectedStackFileName,
284
- selectedBlueprintFileName,
285
- uiScopeSignals,
286
- projectDescriptionHint,
287
- }) {
288
- const projectName = String(packageManifest?.name || path.basename(targetDirectoryPath)).trim() || 'existing-ui-project';
289
- const isMobileUiProject = String(selectedStackFileName || '').toLowerCase().includes('react-native')
290
- || String(selectedStackFileName || '').toLowerCase().includes('flutter')
291
- || uiScopeSignals.signalReasons.some((signalReason) => signalReason.includes('android') || signalReason.includes('ios'));
292
- const resolvedDomain = isMobileUiProject ? 'Mobile app' : 'Web application';
293
- const projectDescription = String(packageManifest?.description || projectDescriptionHint || '').trim()
294
- || `Existing ${resolvedDomain.toLowerCase()} detected during init. Create a project-specific dynamic design contract before shipping new UI work.`;
295
-
296
- return buildDesignIntentSeedFromSignals({
297
- projectName,
298
- projectDescription,
299
- primaryDomain: resolvedDomain,
300
- features: [],
301
- initContext: {
302
- stackFileName: selectedStackFileName,
303
- blueprintFileName: selectedBlueprintFileName,
304
- },
305
- status: 'seed-generated-during-init',
306
- supplementalFields: {
307
- initSignals: {
308
- detectedFrom: uiScopeSignals.signalReasons,
309
- generatedBy: 'init-existing-project-seed',
310
- },
311
- repoEvidence: {
312
- uiSignalReasons: uiScopeSignals.signalReasons,
313
- frontendMetrics: uiScopeSignals.frontendEvidenceMetrics || null,
314
- designEvidenceSummary: uiScopeSignals.designEvidenceSummary || null,
315
- workspaceUiEntries: uiScopeSignals.workspaceUiEntries || [],
316
- },
317
- },
318
- });
319
- }
94
+ export {
95
+ detectRuntimeEnvironment,
96
+ resolveRuntimeEnvironmentKeyFromLabel,
97
+ resolveRuntimeEnvironmentLabelFromKey,
98
+ } from './init/runtime-environment.mjs';
320
99
 
321
100
  export async function runInitCommand(targetDirectoryArgument, initOptions = {}) {
322
101
  const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
@@ -420,13 +199,17 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
420
199
  : 'No existing project markers were detected.',
421
200
  activeRulesSummary: {
422
201
  canonicalSource: '.instructions.md',
423
- compiledEntrypoints: [
424
- '.agent-instructions.md',
425
- '.cursorrules',
426
- '.windsurfrules',
427
- '.clauderc',
428
- '.gemini/instructions.md',
202
+ compiledRulebook: '.agent-instructions.md',
203
+ legacyThinAdapters: ['.cursorrules', '.windsurfrules', '.clauderc'],
204
+ generatedBridgeAdapters: [
205
+ 'AGENTS.md',
206
+ 'CLAUDE.md',
207
+ 'GEMINI.md',
208
+ '.cursor/rules/agentic-senior-core.mdc',
209
+ '.windsurf/rules/agentic-senior-core.md',
429
210
  '.github/copilot-instructions.md',
211
+ '.github/instructions/agentic-senior-core.instructions.md',
212
+ '.gemini/instructions.md',
430
213
  ],
431
214
  stackLoadingMode: 'lazy',
432
215
  domainRuleLoadingMode: 'lazy',
@@ -466,7 +249,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
466
249
  console.log('- Detected stack: unresolved (insufficient markers).');
467
250
  }
468
251
 
469
- console.log('- Active rules baseline: canonical .instructions.md -> compiled .cursorrules/.windsurfrules');
252
+ console.log('- Active rules baseline: canonical .instructions.md -> compiled .agent-instructions.md + legacy thin root adapters');
470
253
  console.log(
471
254
  `- Active review thresholds: ${formatBlockingSeverities(selectedPolicyProfile.blockingSeverities)}`
472
255
  );
@@ -782,7 +565,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
782
565
  console.log(`- CI/CD quality checks (guardrails): ${includeCiGuardrails ? 'enabled' : 'disabled'}`);
783
566
  console.log(`- Review thresholds: ${formatBlockingSeverities(selectedPolicyProfile.blockingSeverities)}`);
784
567
  console.log(`- Setup time: ${formatDuration(setupDurationMs)}`);
785
- console.log('- Generated files: .instructions.md, .agent-instructions.md, compiled adapters, and .agent-context/state/onboarding-report.json');
568
+ console.log('- Generated files: .instructions.md, .agent-instructions.md, legacy thin adapters, generated bridge adapters, and .agent-context/state/onboarding-report.json');
786
569
  if (scaffoldingResult?.bootstrapMode === 'ai-synthesis') {
787
570
  console.log(`- Bootstrap prompts: ${(scaffoldingResult.generatedPromptFileNames || []).length} files generated in .agent-context/prompts/`);
788
571
  if ((scaffoldingResult.materializedFileNames || []).length > 0) {
@@ -846,7 +629,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
846
629
  console.log('- If docs/DESIGN.md is missing, execute .agent-context/prompts/bootstrap-design.md now and refine docs/design-intent.json into a complete design contract before building UI components.');
847
630
  console.log('- Keep docs/design-intent.json and docs/DESIGN.md synchronized whenever the UI direction changes.');
848
631
  }
849
- console.log('Your AI tools will now receive one compiled rulebook plus the original source rules, and your review threshold is stored in .agent-context/policies/llm-judge-threshold.json.');
632
+ console.log('Your AI tools will now receive one compiled rulebook, thin discovery adapters, and the original source rules. Your review threshold is stored in .agent-context/policies/llm-judge-threshold.json.');
850
633
  console.log('MCP server registration is manual inside your IDE settings, even when mcp.json exists.');
851
634
  } catch (error) {
852
635
  console.error('\n[FATAL] An error occurred during initialization. Attempting automatic rollback...');
@@ -174,7 +174,7 @@ export async function runOptimizeCommand(targetDirectoryArgument, optimizeOption
174
174
  console.log(`- Agent profile: ${tokenOptimizationState.selectedAgent}`);
175
175
  console.log(`- Preferred shell proxy: ${tokenOptimizationState.preferredShellProxy}`);
176
176
  console.log(`- Setup time: ${formatDuration(optimizationDurationMs)}`);
177
- console.log('- Updated files: .cursorrules, .windsurfrules, .agent-context/state/token-optimization.json');
177
+ console.log('- Updated files: .agent-instructions.md, legacy thin adapters, and .agent-context/state/token-optimization.json');
178
178
 
179
179
  if (tokenOptimizationState.enabled) {
180
180
  if (rtkDetection.isAvailable) {
@@ -48,6 +48,7 @@ import {
48
48
  buildDesignIntentSeedFromSignals,
49
49
  } from '../project-scaffolder.mjs';
50
50
  import { ensureActiveMemorySnapshot } from '../memory-continuity.mjs';
51
+ import { buildExistingProjectMajorConstraints } from '../init-detection-flow.mjs';
51
52
 
52
53
  export function parseUpgradeArguments(commandArguments) {
53
54
  const parsedUpgradeOptions = {
@@ -102,14 +103,6 @@ export function parseUpgradeArguments(commandArguments) {
102
103
  return parsedUpgradeOptions;
103
104
  }
104
105
 
105
- function buildExistingProjectMajorConstraints() {
106
- return [
107
- 'Preserve existing project markers and avoid forced stack migration.',
108
- 'Use runtime markers as evidence only unless the user already recorded an explicit runtime constraint.',
109
- 'Upgrade keeps prior explicit onboarding constraints but does not create new stack or blueprint decisions.',
110
- ];
111
- }
112
-
113
106
  function buildUpgradeDesignIntentSeed({
114
107
  targetDirectoryPath,
115
108
  packageManifest,
@@ -243,7 +236,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
243
236
  })
244
237
  : null;
245
238
 
246
- const detectionMajorConstraints = buildExistingProjectMajorConstraints();
239
+ const detectionMajorConstraints = buildExistingProjectMajorConstraints({ mode: 'upgrade' });
247
240
  const detectionTransparency = {
248
241
  declaredAt: new Date().toISOString(),
249
242
  declarationType: 'existing-project',
@@ -251,7 +244,18 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
251
244
  detectionSummary: buildDetectionSummary(projectDetection),
252
245
  activeRulesSummary: {
253
246
  canonicalSource: '.instructions.md',
254
- compiledEntrypoints: ['.cursorrules', '.windsurfrules'],
247
+ compiledRulebook: '.agent-instructions.md',
248
+ legacyThinAdapters: ['.cursorrules', '.windsurfrules', '.clauderc'],
249
+ generatedBridgeAdapters: [
250
+ 'AGENTS.md',
251
+ 'CLAUDE.md',
252
+ 'GEMINI.md',
253
+ '.cursor/rules/agentic-senior-core.mdc',
254
+ '.windsurf/rules/agentic-senior-core.md',
255
+ '.github/copilot-instructions.md',
256
+ '.github/instructions/agentic-senior-core.instructions.md',
257
+ '.gemini/instructions.md',
258
+ ],
255
259
  stackLoadingMode: 'lazy',
256
260
  domainRuleLoadingMode: 'lazy',
257
261
  selectedProfile: selectedProfileName,
@@ -281,7 +285,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
281
285
  } else {
282
286
  console.log('- Detected stack: unresolved (insufficient markers).');
283
287
  }
284
- console.log('- Active rules baseline: canonical .instructions.md -> compiled .cursorrules/.windsurfrules');
288
+ console.log('- Active rules baseline: canonical .instructions.md -> compiled .agent-instructions.md + legacy thin root adapters');
285
289
  console.log(
286
290
  `- Active review thresholds: ${(
287
291
  PROFILE_PRESETS[selectedProfileName]?.blockingSeverities || []
@@ -296,7 +300,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
296
300
 
297
301
  const projectDocStalenessReport = await detectProjectDocTemplateStaleness(resolvedTargetDirectoryPath);
298
302
 
299
- const currentRulesPath = path.join(resolvedTargetDirectoryPath, '.cursorrules');
303
+ const currentRulesPath = path.join(resolvedTargetDirectoryPath, '.agent-instructions.md');
300
304
  const currentRulesContent = await pathExists(currentRulesPath)
301
305
  ? await fs.readFile(currentRulesPath, 'utf8')
302
306
  : '';
@@ -423,13 +427,14 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
423
427
  }
424
428
  }
425
429
 
426
- await compileDynamicContext({
430
+ const compileResult = await compileDynamicContext({
427
431
  targetDirectoryPath: resolvedTargetDirectoryPath,
428
432
  selectedStackFileName,
429
433
  selectedAdditionalStackFileNames,
430
434
  selectedBlueprintFileName,
431
435
  selectedAdditionalBlueprintFileNames,
432
436
  includeCiGuardrails,
437
+ preserveUserOwnedEntrypoints: true,
433
438
  });
434
439
  await writeSelectedPolicy(resolvedTargetDirectoryPath, selectedProfileName);
435
440
 
@@ -454,25 +459,38 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
454
459
  console.log('\nUpgrade complete.');
455
460
  console.log(`- Governance surface sync: 1:1 (${governanceSyncResult.updatedFiles.length} updated, ${governanceSyncResult.createdFiles.length} new, ${governanceSyncResult.deletedManagedFiles.length} deleted, ${governanceSyncResult.unchangedFiles.length} unchanged)`);
456
461
  console.log(`- Rules rewritten: ${isRulesContentChanged ? 'yes' : 'no (metadata refreshed)'}`);
462
+ const preservedInstructionEntrypoints = Array.from(new Set([
463
+ ...(governanceSyncResult.preservedFiles || []),
464
+ ...(compileResult.preservedEntrypoints || []),
465
+ ])).sort();
466
+ if (preservedInstructionEntrypoints.length > 0) {
467
+ console.log(`- User-owned instruction entrypoints preserved: ${preservedInstructionEntrypoints.length}`);
468
+ }
457
469
  if (governanceSyncResult.deletedManagedDirectories.length > 0) {
458
470
  console.log(`- Managed stale directories removed: ${governanceSyncResult.deletedManagedDirectories.length}`);
459
471
  }
460
472
  console.log(`- Setup time: ${formatDuration(setupDurationMs)}`);
461
473
 
462
- if (governanceSyncResult.updatedFiles.length > 0 || governanceSyncResult.createdFiles.length > 0 || governanceSyncResult.deletedManagedFiles.length > 0) {
474
+ const hasDetailedGovernanceChanges = governanceSyncResult.updatedFiles.length > 0
475
+ || governanceSyncResult.createdFiles.length > 0
476
+ || governanceSyncResult.deletedManagedFiles.length > 0
477
+ || preservedInstructionEntrypoints.length > 0;
478
+
479
+ if (hasDetailedGovernanceChanges) {
463
480
  console.log('\nDetailed changes:');
464
481
  governanceSyncResult.createdFiles.forEach((fileName) => console.log(` [NEW] ${fileName}`));
465
482
  governanceSyncResult.updatedFiles.forEach((fileName) => console.log(` [UPDATED] ${fileName}`));
466
483
  governanceSyncResult.deletedManagedFiles.forEach((fileName) => console.log(` [DELETED] ${fileName}`));
484
+ preservedInstructionEntrypoints.forEach((fileName) => console.log(` [PRESERVE] ${fileName}`));
467
485
  }
468
486
  if (supplementalCreatedFileNames.length > 0) {
469
- if (!(governanceSyncResult.updatedFiles.length > 0 || governanceSyncResult.createdFiles.length > 0 || governanceSyncResult.deletedManagedFiles.length > 0)) {
487
+ if (!hasDetailedGovernanceChanges) {
470
488
  console.log('\nDetailed changes:');
471
489
  }
472
490
  supplementalCreatedFileNames.forEach((fileName) => console.log(` [NEW] ${fileName} (seed)`));
473
491
  }
474
492
 
475
- console.log('\nRefreshed files: .instructions.md, .agent-instructions.md, compiled adapters, and .agent-context/state/onboarding-report.json');
493
+ console.log('\nRefreshed files: .instructions.md, .agent-instructions.md, legacy thin adapters, generated bridge adapters, and .agent-context/state/onboarding-report.json');
476
494
  } catch (error) {
477
495
  console.error('\n[FATAL] An error occurred during upgrade. Attempting automatic rollback...');
478
496
  try {
@@ -15,6 +15,7 @@ import {
15
15
  import {
16
16
  pathExists,
17
17
  collectFileNames,
18
+ isAgenticManagedContent,
18
19
  } from './utils.mjs';
19
20
 
20
21
  import {
@@ -95,6 +96,38 @@ function buildAnchorCommitmentHeader(designIntent) {
95
96
  ].join('\n');
96
97
  }
97
98
 
99
+ function buildLegacyRootAdapterContent(adapterFileName, toolLabel) {
100
+ return [
101
+ `# ${adapterFileName} - Legacy Thin Adapter`,
102
+ '',
103
+ `Generated by Agentic-Senior-Core CLI v${CLI_VERSION}`,
104
+ 'Adapter Mode: legacy-thin',
105
+ 'Adapter Source: .agent-instructions.md when present; fallback .instructions.md',
106
+ 'Canonical baseline: .instructions.md',
107
+ '',
108
+ `This file is kept only for older ${toolLabel} discovery.`,
109
+ 'Read .agent-instructions.md for the compiled rulebook when present.',
110
+ 'Use .instructions.md as the canonical policy source.',
111
+ '',
112
+ 'Mandatory load floor:',
113
+ '1. Read .agent-instructions.md when present; otherwise read .instructions.md.',
114
+ '2. Load only relevant .agent-context/rules/ by task scope.',
115
+ '3. Apply matching .agent-context/prompts/ contracts.',
116
+ '4. Enforce .agent-context/review-checklists/ before completion.',
117
+ '5. Use .agent-context/state/ and .agent-context/policies/ only when relevant.',
118
+ '6. Resolve Runtime Decision Signals from repo evidence and live official docs.',
119
+ '7. Resolve Structural Planning Signals from constraints and architecture boundaries.',
120
+ '',
121
+ 'Current bridges:',
122
+ '- Cursor: .cursor/rules/agentic-senior-core.mdc',
123
+ '- Windsurf: .windsurf/rules/agentic-senior-core.md',
124
+ '- Claude: CLAUDE.md',
125
+ '- Gemini: GEMINI.md and .gemini/instructions.md',
126
+ '- Copilot: .github/copilot-instructions.md and .github/instructions/agentic-senior-core.instructions.md',
127
+ '',
128
+ ].join('\n');
129
+ }
130
+
98
131
  export async function writeSelectedPolicy(targetDirectoryPath, selectedProfileName) {
99
132
  const policyFilePath = path.join(targetDirectoryPath, '.agent-context', 'policies', POLICY_FILE_NAME);
100
133
  const parsedPolicy = JSON.parse(await fs.readFile(policyFilePath, 'utf8'));
@@ -265,7 +298,9 @@ export async function buildCompiledRulesContent({
265
298
  '7. docs/ project context (or bootstrap prompts when docs are not materialized)',
266
299
  '',
267
300
  'Project-specific compiled snapshot: .agent-instructions.md',
268
- 'Compiled adapter entrypoints: .cursorrules, .windsurfrules, .clauderc, .gemini/instructions.md, .github/copilot-instructions.md',
301
+ 'Compiled rulebook: .agent-instructions.md',
302
+ 'Legacy thin root adapters: .cursorrules, .windsurfrules, .clauderc',
303
+ 'Generated bridge adapters: AGENTS.md, CLAUDE.md, GEMINI.md, .cursor/rules/agentic-senior-core.mdc, .windsurf/rules/agentic-senior-core.md, .github/copilot-instructions.md, .github/instructions/agentic-senior-core.instructions.md, .gemini/instructions.md',
269
304
  'Canonical baseline: .instructions.md',
270
305
  ].join('\n')
271
306
  );
@@ -591,6 +626,7 @@ export async function compileDynamicContext({
591
626
  selectedBlueprintFileName,
592
627
  selectedAdditionalBlueprintFileNames = [],
593
628
  includeCiGuardrails,
629
+ preserveUserOwnedEntrypoints = true,
594
630
  }) {
595
631
  const resolvedTargetDirectoryPath = path.resolve(targetDirectoryPath);
596
632
  const compiledRules = await buildCompiledRulesContent({
@@ -601,23 +637,29 @@ export async function compileDynamicContext({
601
637
  selectedAdditionalBlueprintFileNames,
602
638
  includeCiGuardrails,
603
639
  });
640
+ const preservedEntrypoints = [];
604
641
 
605
- await fs.writeFile(path.join(resolvedTargetDirectoryPath, '.agent-instructions.md'), compiledRules, 'utf8');
606
- await fs.writeFile(path.join(resolvedTargetDirectoryPath, '.cursorrules'), compiledRules, 'utf8');
607
- await fs.writeFile(path.join(resolvedTargetDirectoryPath, '.windsurfrules'), compiledRules, 'utf8');
608
- await fs.writeFile(path.join(resolvedTargetDirectoryPath, '.clauderc'), compiledRules, 'utf8');
609
-
610
- // Gemini (Antigravity Editor) instructions
611
- const geminiDir = path.join(resolvedTargetDirectoryPath, '.gemini');
612
- if (!(await pathExists(geminiDir))) {
613
- await fs.mkdir(geminiDir, { recursive: true });
614
- }
615
- await fs.writeFile(path.join(geminiDir, 'instructions.md'), compiledRules, 'utf8');
642
+ async function writeGeneratedEntrypointFile(relativeFilePath, content) {
643
+ const targetFilePath = path.join(resolvedTargetDirectoryPath, relativeFilePath);
644
+
645
+ if (preserveUserOwnedEntrypoints && await pathExists(targetFilePath)) {
646
+ const existingContent = await fs.readFile(targetFilePath, 'utf8');
647
+ if (!isAgenticManagedContent(existingContent)) {
648
+ preservedEntrypoints.push(relativeFilePath);
649
+ return;
650
+ }
651
+ }
616
652
 
617
- // Copilot instructions (also used by some generic IDE extensions)
618
- const githubDir = path.join(resolvedTargetDirectoryPath, '.github');
619
- if (!(await pathExists(githubDir))) {
620
- await fs.mkdir(githubDir, { recursive: true });
653
+ await fs.mkdir(path.dirname(targetFilePath), { recursive: true });
654
+ await fs.writeFile(targetFilePath, content, 'utf8');
621
655
  }
622
- await fs.writeFile(path.join(githubDir, 'copilot-instructions.md'), compiledRules, 'utf8');
656
+
657
+ await fs.writeFile(path.join(resolvedTargetDirectoryPath, '.agent-instructions.md'), compiledRules, 'utf8');
658
+ await writeGeneratedEntrypointFile('.cursorrules', buildLegacyRootAdapterContent('.cursorrules', 'Cursor'));
659
+ await writeGeneratedEntrypointFile('.windsurfrules', buildLegacyRootAdapterContent('.windsurfrules', 'Windsurf'));
660
+ await writeGeneratedEntrypointFile('.clauderc', buildLegacyRootAdapterContent('.clauderc', 'Claude'));
661
+
662
+ return {
663
+ preservedEntrypoints,
664
+ };
623
665
  }
@@ -130,7 +130,12 @@ export const entryPointFiles = [
130
130
  '.cursorrules',
131
131
  '.windsurfrules',
132
132
  'AGENTS.md',
133
+ 'CLAUDE.md',
134
+ 'GEMINI.md',
135
+ '.cursor/rules/agentic-senior-core.mdc',
133
136
  '.github/copilot-instructions.md',
137
+ '.github/instructions/agentic-senior-core.instructions.md',
138
+ '.windsurf/rules/agentic-senior-core.md',
134
139
  '.agent-override.md',
135
140
  ];
136
141
 
@@ -22,6 +22,7 @@ const WORKSPACE_SCAN_IGNORE_DIRECTORY_NAMES = new Set([
22
22
  '.github',
23
23
  '.idea',
24
24
  '.vscode',
25
+ '.windsurf',
25
26
  '.zed',
26
27
  ]);
27
28
  const WORKSPACE_CONTAINER_DIRECTORY_NAMES = new Set([
@@ -111,9 +112,12 @@ const INTERNAL_GOVERNANCE_SURFACE_NAMES = new Set([
111
112
  '.github',
112
113
  '.instructions.md',
113
114
  '.vscode',
115
+ '.windsurf',
114
116
  '.windsurfrules',
115
117
  '.zed',
116
118
  'AGENTS.md',
119
+ 'CLAUDE.md',
120
+ 'GEMINI.md',
117
121
  'mcp.json',
118
122
  ]);
119
123
 
@@ -1,4 +1,12 @@
1
- export function buildExistingProjectMajorConstraints() {
1
+ export function buildExistingProjectMajorConstraints({ mode = 'init' } = {}) {
2
+ if (mode === 'upgrade') {
3
+ return [
4
+ 'Preserve existing project markers and avoid forced stack migration.',
5
+ 'Use runtime markers as evidence only unless the user already recorded an explicit runtime constraint.',
6
+ 'Upgrade keeps prior explicit onboarding constraints but does not create new stack or blueprint decisions.',
7
+ ];
8
+ }
9
+
2
10
  return [
3
11
  'Preserve existing project markers and avoid forced stack migration.',
4
12
  'Use detected runtime markers as evidence only; do not convert them into stack migration or design direction.',
@@ -27,8 +27,3 @@ export function normalizeAdditionalBlueprintSelection(selectedBlueprintFileName,
27
27
  (blueprintFileName) => blueprintFileName && blueprintFileName !== selectedBlueprintFileName
28
28
  )));
29
29
  }
30
-
31
- export function resolveScopeBlueprintCandidates(projectScopeKey) {
32
- void projectScopeKey;
33
- return null;
34
- }