@ryuenn3123/agentic-senior-core 3.0.37 → 3.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent-context/prompts/bootstrap-design.md +108 -146
- package/.agent-context/rules/frontend-architecture.md +92 -108
- package/.agent-context/state/README.md +26 -0
- package/.cursor/mcp.json +10 -0
- package/.cursor/rules/agentic-senior-core.mdc +48 -0
- package/.cursorrules +22 -88
- package/.gemini/instructions.md +25 -16
- package/.github/copilot-instructions.md +25 -16
- package/.github/instructions/agentic-senior-core.instructions.md +47 -0
- package/.instructions.md +98 -207
- package/.windsurf/rules/agentic-senior-core.md +43 -0
- package/.windsurfrules +22 -88
- package/AGENTS.md +23 -26
- package/CLAUDE.md +43 -0
- package/CONTRIBUTING.md +5 -2
- package/GEMINI.md +43 -0
- package/README.md +24 -7
- package/lib/cli/backup.mjs +4 -4
- package/lib/cli/commands/init/project-context.mjs +101 -0
- package/lib/cli/commands/init/runtime-environment.mjs +59 -0
- package/lib/cli/commands/init/setup-decisions.mjs +83 -0
- package/lib/cli/commands/init.mjs +33 -250
- package/lib/cli/commands/optimize.mjs +1 -1
- package/lib/cli/commands/upgrade.mjs +32 -7
- package/lib/cli/compiler.mjs +59 -17
- package/lib/cli/constants.mjs +5 -0
- package/lib/cli/detector.mjs +4 -0
- package/lib/cli/preflight.mjs +3 -3
- package/lib/cli/project-scaffolder/design-contract/validation.mjs +789 -0
- package/lib/cli/project-scaffolder/design-contract.mjs +119 -924
- package/lib/cli/project-scaffolder/prompt-builders.mjs +69 -84
- package/lib/cli/utils/filesystem.mjs +79 -0
- package/lib/cli/utils/managed-surface.mjs +237 -0
- package/lib/cli/utils/prompting.mjs +44 -0
- package/lib/cli/utils.mjs +33 -335
- package/package.json +21 -2
- package/scripts/clean-local-artifacts.mjs +76 -0
- package/scripts/docs-quality-drift-report.mjs +5 -0
- package/scripts/frontend-usability-audit.mjs +23 -19
- package/scripts/governance-weekly-report.mjs +37 -15
- package/scripts/single-source-lazy-loading-audit.mjs +24 -0
- package/scripts/sync-thin-adapters.mjs +99 -129
- package/scripts/v3-purge-audit.mjs +5 -0
- package/scripts/validate/config.mjs +10 -0
- package/scripts/validate/coverage-checks.mjs +55 -0
- package/.agent-context/marketplace/trust-tiers.json +0 -114
- package/.agent-context/state/benchmark-analysis.json +0 -431
- package/.agent-context/state/benchmark-evidence-bundle.json +0 -1040
- package/.agent-context/state/benchmark-history.json +0 -75
- package/.agent-context/state/benchmark-trend-report.csv +0 -5
- package/.agent-context/state/benchmark-trend-report.json +0 -140
- package/.agent-context/state/benchmark-writer-judge-matrix.json +0 -462
- package/.agent-context/state/memory-continuity-benchmark.json +0 -132
- package/.agent-context/state/onboarding-report.json +0 -102
- package/.agent-context/state/quality-trend-report.json +0 -89
- package/.agent-context/state/token-optimization-benchmark.json +0 -130
- package/.agent-context/state/weekly-governance-report.json +0 -329
- package/lib/cli/compatibility.mjs +0 -124
|
@@ -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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
'.
|
|
427
|
-
'.
|
|
428
|
-
'.
|
|
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 .
|
|
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,
|
|
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
|
|
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: .
|
|
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) {
|
|
@@ -251,7 +251,18 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
251
251
|
detectionSummary: buildDetectionSummary(projectDetection),
|
|
252
252
|
activeRulesSummary: {
|
|
253
253
|
canonicalSource: '.instructions.md',
|
|
254
|
-
|
|
254
|
+
compiledRulebook: '.agent-instructions.md',
|
|
255
|
+
legacyThinAdapters: ['.cursorrules', '.windsurfrules', '.clauderc'],
|
|
256
|
+
generatedBridgeAdapters: [
|
|
257
|
+
'AGENTS.md',
|
|
258
|
+
'CLAUDE.md',
|
|
259
|
+
'GEMINI.md',
|
|
260
|
+
'.cursor/rules/agentic-senior-core.mdc',
|
|
261
|
+
'.windsurf/rules/agentic-senior-core.md',
|
|
262
|
+
'.github/copilot-instructions.md',
|
|
263
|
+
'.github/instructions/agentic-senior-core.instructions.md',
|
|
264
|
+
'.gemini/instructions.md',
|
|
265
|
+
],
|
|
255
266
|
stackLoadingMode: 'lazy',
|
|
256
267
|
domainRuleLoadingMode: 'lazy',
|
|
257
268
|
selectedProfile: selectedProfileName,
|
|
@@ -281,7 +292,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
281
292
|
} else {
|
|
282
293
|
console.log('- Detected stack: unresolved (insufficient markers).');
|
|
283
294
|
}
|
|
284
|
-
console.log('- Active rules baseline: canonical .instructions.md -> compiled .
|
|
295
|
+
console.log('- Active rules baseline: canonical .instructions.md -> compiled .agent-instructions.md + legacy thin root adapters');
|
|
285
296
|
console.log(
|
|
286
297
|
`- Active review thresholds: ${(
|
|
287
298
|
PROFILE_PRESETS[selectedProfileName]?.blockingSeverities || []
|
|
@@ -296,7 +307,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
296
307
|
|
|
297
308
|
const projectDocStalenessReport = await detectProjectDocTemplateStaleness(resolvedTargetDirectoryPath);
|
|
298
309
|
|
|
299
|
-
const currentRulesPath = path.join(resolvedTargetDirectoryPath, '.
|
|
310
|
+
const currentRulesPath = path.join(resolvedTargetDirectoryPath, '.agent-instructions.md');
|
|
300
311
|
const currentRulesContent = await pathExists(currentRulesPath)
|
|
301
312
|
? await fs.readFile(currentRulesPath, 'utf8')
|
|
302
313
|
: '';
|
|
@@ -423,13 +434,14 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
423
434
|
}
|
|
424
435
|
}
|
|
425
436
|
|
|
426
|
-
await compileDynamicContext({
|
|
437
|
+
const compileResult = await compileDynamicContext({
|
|
427
438
|
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
428
439
|
selectedStackFileName,
|
|
429
440
|
selectedAdditionalStackFileNames,
|
|
430
441
|
selectedBlueprintFileName,
|
|
431
442
|
selectedAdditionalBlueprintFileNames,
|
|
432
443
|
includeCiGuardrails,
|
|
444
|
+
preserveUserOwnedEntrypoints: true,
|
|
433
445
|
});
|
|
434
446
|
await writeSelectedPolicy(resolvedTargetDirectoryPath, selectedProfileName);
|
|
435
447
|
|
|
@@ -454,25 +466,38 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
454
466
|
console.log('\nUpgrade complete.');
|
|
455
467
|
console.log(`- Governance surface sync: 1:1 (${governanceSyncResult.updatedFiles.length} updated, ${governanceSyncResult.createdFiles.length} new, ${governanceSyncResult.deletedManagedFiles.length} deleted, ${governanceSyncResult.unchangedFiles.length} unchanged)`);
|
|
456
468
|
console.log(`- Rules rewritten: ${isRulesContentChanged ? 'yes' : 'no (metadata refreshed)'}`);
|
|
469
|
+
const preservedInstructionEntrypoints = Array.from(new Set([
|
|
470
|
+
...(governanceSyncResult.preservedFiles || []),
|
|
471
|
+
...(compileResult.preservedEntrypoints || []),
|
|
472
|
+
])).sort();
|
|
473
|
+
if (preservedInstructionEntrypoints.length > 0) {
|
|
474
|
+
console.log(`- User-owned instruction entrypoints preserved: ${preservedInstructionEntrypoints.length}`);
|
|
475
|
+
}
|
|
457
476
|
if (governanceSyncResult.deletedManagedDirectories.length > 0) {
|
|
458
477
|
console.log(`- Managed stale directories removed: ${governanceSyncResult.deletedManagedDirectories.length}`);
|
|
459
478
|
}
|
|
460
479
|
console.log(`- Setup time: ${formatDuration(setupDurationMs)}`);
|
|
461
480
|
|
|
462
|
-
|
|
481
|
+
const hasDetailedGovernanceChanges = governanceSyncResult.updatedFiles.length > 0
|
|
482
|
+
|| governanceSyncResult.createdFiles.length > 0
|
|
483
|
+
|| governanceSyncResult.deletedManagedFiles.length > 0
|
|
484
|
+
|| preservedInstructionEntrypoints.length > 0;
|
|
485
|
+
|
|
486
|
+
if (hasDetailedGovernanceChanges) {
|
|
463
487
|
console.log('\nDetailed changes:');
|
|
464
488
|
governanceSyncResult.createdFiles.forEach((fileName) => console.log(` [NEW] ${fileName}`));
|
|
465
489
|
governanceSyncResult.updatedFiles.forEach((fileName) => console.log(` [UPDATED] ${fileName}`));
|
|
466
490
|
governanceSyncResult.deletedManagedFiles.forEach((fileName) => console.log(` [DELETED] ${fileName}`));
|
|
491
|
+
preservedInstructionEntrypoints.forEach((fileName) => console.log(` [PRESERVE] ${fileName}`));
|
|
467
492
|
}
|
|
468
493
|
if (supplementalCreatedFileNames.length > 0) {
|
|
469
|
-
if (!
|
|
494
|
+
if (!hasDetailedGovernanceChanges) {
|
|
470
495
|
console.log('\nDetailed changes:');
|
|
471
496
|
}
|
|
472
497
|
supplementalCreatedFileNames.forEach((fileName) => console.log(` [NEW] ${fileName} (seed)`));
|
|
473
498
|
}
|
|
474
499
|
|
|
475
|
-
console.log('\nRefreshed files: .instructions.md, .agent-instructions.md,
|
|
500
|
+
console.log('\nRefreshed files: .instructions.md, .agent-instructions.md, legacy thin adapters, generated bridge adapters, and .agent-context/state/onboarding-report.json');
|
|
476
501
|
} catch (error) {
|
|
477
502
|
console.error('\n[FATAL] An error occurred during upgrade. Attempting automatic rollback...');
|
|
478
503
|
try {
|
package/lib/cli/compiler.mjs
CHANGED
|
@@ -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
|
|
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
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
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
|
-
|
|
618
|
-
|
|
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
|
-
|
|
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
|
}
|
package/lib/cli/constants.mjs
CHANGED
|
@@ -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
|
|
package/lib/cli/detector.mjs
CHANGED
|
@@ -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
|
|
package/lib/cli/preflight.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { constants } from 'node:fs';
|
|
4
4
|
import { pathExists } from './utils.mjs';
|
|
5
|
+
import { entryPointFiles } from './constants.mjs';
|
|
5
6
|
|
|
6
7
|
const MINIMUM_NODE_VERSION = 18;
|
|
7
8
|
const MINIMUM_FREE_DISK_SPACE_MB = 5;
|
|
@@ -73,15 +74,14 @@ export async function runPreflightChecks(targetDirectoryPath, operationMode) {
|
|
|
73
74
|
// Check 4: Conflicting Files
|
|
74
75
|
if (operationMode === 'init') {
|
|
75
76
|
const potentiallyConflictingPaths = [
|
|
76
|
-
path.join(targetDirectoryPath,
|
|
77
|
-
path.join(targetDirectoryPath, '.windsurfrules'),
|
|
77
|
+
...entryPointFiles.map((entryPointFileName) => path.join(targetDirectoryPath, entryPointFileName)),
|
|
78
78
|
path.join(targetDirectoryPath, '.agent-context'),
|
|
79
79
|
];
|
|
80
80
|
|
|
81
81
|
const conflictingFound = [];
|
|
82
82
|
for (const conflictPath of potentiallyConflictingPaths) {
|
|
83
83
|
if (await pathExists(conflictPath)) {
|
|
84
|
-
conflictingFound.push(path.
|
|
84
|
+
conflictingFound.push(path.relative(targetDirectoryPath, conflictPath).replace(/\\/g, '/'));
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|