@ryuenn3123/agentic-senior-core 3.0.19 → 3.0.21

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 (77) hide show
  1. package/.agent-context/prompts/bootstrap-design.md +96 -103
  2. package/.agent-context/prompts/init-project.md +32 -100
  3. package/.agent-context/prompts/refactor.md +22 -44
  4. package/.agent-context/prompts/review-code.md +28 -52
  5. package/.agent-context/review-checklists/architecture-review.md +31 -62
  6. package/.agent-context/review-checklists/pr-checklist.md +74 -108
  7. package/.agent-context/rules/api-docs.md +18 -206
  8. package/.agent-context/rules/architecture.md +40 -207
  9. package/.agent-context/rules/database-design.md +10 -199
  10. package/.agent-context/rules/docker-runtime.md +5 -5
  11. package/.agent-context/rules/efficiency-vs-hype.md +11 -149
  12. package/.agent-context/rules/error-handling.md +9 -231
  13. package/.agent-context/rules/event-driven.md +17 -221
  14. package/.agent-context/rules/frontend-architecture.md +74 -119
  15. package/.agent-context/rules/git-workflow.md +1 -1
  16. package/.agent-context/rules/microservices.md +28 -161
  17. package/.agent-context/rules/naming-conv.md +8 -138
  18. package/.agent-context/rules/performance.md +9 -175
  19. package/.agent-context/rules/realtime.md +11 -44
  20. package/.agent-context/rules/security.md +11 -295
  21. package/.agent-context/rules/testing.md +9 -174
  22. package/.agent-context/state/benchmark-analysis.json +3 -3
  23. package/.agent-context/state/memory-continuity-benchmark.json +1 -1
  24. package/.agent-context/state/onboarding-report.json +71 -11
  25. package/.agents/workflows/init-project.md +7 -24
  26. package/.agents/workflows/refactor.md +7 -24
  27. package/.agents/workflows/review-code.md +7 -24
  28. package/.cursorrules +22 -21
  29. package/.gemini/instructions.md +2 -2
  30. package/.github/copilot-instructions.md +2 -2
  31. package/.instructions.md +112 -213
  32. package/.windsurfrules +22 -21
  33. package/AGENTS.md +4 -4
  34. package/CONTRIBUTING.md +13 -22
  35. package/README.md +6 -20
  36. package/lib/cli/commands/init.mjs +102 -148
  37. package/lib/cli/commands/launch.mjs +3 -3
  38. package/lib/cli/commands/optimize.mjs +14 -4
  39. package/lib/cli/commands/upgrade.mjs +25 -23
  40. package/lib/cli/compiler.mjs +96 -62
  41. package/lib/cli/constants.mjs +28 -136
  42. package/lib/cli/detector/design-evidence.mjs +189 -6
  43. package/lib/cli/detector.mjs +6 -7
  44. package/lib/cli/init-detection-flow.mjs +10 -93
  45. package/lib/cli/init-selection.mjs +2 -68
  46. package/lib/cli/project-scaffolder/constants.mjs +1 -1
  47. package/lib/cli/project-scaffolder/design-contract.mjs +183 -108
  48. package/lib/cli/project-scaffolder/discovery.mjs +36 -82
  49. package/lib/cli/project-scaffolder/prompt-builders.mjs +45 -55
  50. package/lib/cli/project-scaffolder/storage.mjs +0 -2
  51. package/lib/cli/token-optimization.mjs +1 -1
  52. package/lib/cli/utils.mjs +75 -9
  53. package/package.json +2 -2
  54. package/scripts/detection-benchmark.mjs +4 -15
  55. package/scripts/documentation-boundary-audit.mjs +9 -9
  56. package/scripts/explain-on-demand-audit.mjs +11 -11
  57. package/scripts/forbidden-content-check.mjs +9 -9
  58. package/scripts/frontend-usability-audit.mjs +45 -35
  59. package/scripts/llm-judge.mjs +1 -1
  60. package/scripts/mcp-server/constants.mjs +2 -2
  61. package/scripts/mcp-server/tool-registry.mjs +1 -1
  62. package/scripts/release-gate/audit-checks.mjs +22 -7
  63. package/scripts/release-gate/static-checks.mjs +5 -5
  64. package/scripts/release-gate.mjs +1 -1
  65. package/scripts/rules-guardian-audit.mjs +14 -13
  66. package/scripts/single-source-lazy-loading-audit.mjs +3 -3
  67. package/scripts/sync-thin-adapters.mjs +5 -5
  68. package/scripts/ui-design-judge/design-execution-summary.mjs +27 -1
  69. package/scripts/ui-design-judge/prompting.mjs +5 -5
  70. package/scripts/ui-design-judge/reporting.mjs +3 -1
  71. package/scripts/ui-design-judge/rubric-calibration.mjs +8 -5
  72. package/scripts/ui-design-judge/rubric-goldset.json +2 -2
  73. package/scripts/ui-design-judge.mjs +75 -7
  74. package/scripts/validate/config.mjs +138 -48
  75. package/scripts/validate/coverage-checks.mjs +32 -7
  76. package/scripts/validate.mjs +8 -4
  77. package/lib/cli/architect.mjs +0 -431
package/CONTRIBUTING.md CHANGED
@@ -10,13 +10,13 @@ Thanks for wanting to make AI agents write better code. Here's how to contribute
10
10
  |------|-------|-------------|
11
11
  | New rule | `.agent-context/rules/` | Universal engineering standard |
12
12
  | Stack strategy update | `.agent-context/rules/`, `.agent-context/state/stack-research-snapshot.json` | Dynamic language/runtime guidance and evidence |
13
- | Architecture playbook update | `.agent-context/prompts/`, `lib/cli/compiler.mjs` | Dynamic scaffolding and project-context guidance |
13
+ | Structural planning guidance update | `.agent-context/prompts/`, `lib/cli/compiler.mjs` | Scope planning, docs bootstrap, and project-context guidance |
14
14
  | New checklist | `.agent-context/review-checklists/` | Self-audit guide |
15
15
  | State intelligence update | `.agent-context/state/` | Architecture boundaries and dependency map |
16
- | Override policy update | `.agent-override.md` | Scoped enterprise rule exceptions |
16
+ | Override policy update | `.agent-override.md` | Scoped rule exceptions |
17
17
  | MCP workflow update | `mcp.json` | Self-healing automation flow |
18
- | Bug fix | Any file | Typos, broken links, incorrect examples |
19
- | Improvement | Any file | Sharper wording, better examples |
18
+ | Bug fix | Any file | Typos, broken links, incorrect rules |
19
+ | Improvement | Any file | Sharper wording, stricter boundaries |
20
20
 
21
21
  ---
22
22
 
@@ -24,19 +24,10 @@ Thanks for wanting to make AI agents write better code. Here's how to contribute
24
24
 
25
25
  This is the single most important rule: **every file must be "galak" (strict/fierce).**
26
26
 
27
- Your contribution MUST be opinionated, specific, and enforceable. We reject generic advice.
28
-
29
- ```
30
- BAD (generic, useless):
31
- "Use descriptive variable names."
32
-
33
- GOOD (specific, enforceable):
34
- "NEVER use single-letter variables except `i` in `for(let i=0; i<n; i++)`.
35
- Function names MUST start with a verb. Booleans MUST use is/has/can prefix."
36
- ```
27
+ Your contribution MUST be opinionated, specific, and enforceable. We reject generic advice, externally anchored rules, and borrowed-pattern guidance that can become accidental style anchors.
37
28
 
38
29
  ### The Litmus Test
39
- - Does your rule include concrete BANNED / REQUIRED examples?
30
+ - Does your rule include concrete BANNED / REQUIRED boundaries?
40
31
  - Would an AI agent be able to enforce it without ambiguity?
41
32
  - Does it teach the reader WHY, not just WHAT?
42
33
 
@@ -54,11 +45,11 @@ If all three are "yes", it belongs here.
54
45
 
55
46
  ---
56
47
 
57
- ## How to Add or Adjust Architecture Playbooks
48
+ ## How to Add or Adjust Structural Planning Guidance
58
49
 
59
- 1. Update the architecture options in `.agent-context/prompts/init-project.md` and related discovery guidance.
50
+ 1. Update the planning guidance in `.agent-context/prompts/init-project.md` and related discovery guidance.
60
51
  2. Update compiler/init behavior if generated project-context guidance or bootstrap flow changes.
61
- 3. Keep transport/service/repository separation and validation boundaries explicit in examples.
52
+ 3. Keep system boundaries, required docs, and validation boundaries explicit without silently recommending a framework from offline heuristics.
62
53
  4. Run `npm run validate` and `npm test`.
63
54
  5. Open a PR.
64
55
 
@@ -70,10 +61,10 @@ If all three are "yes", it belongs here.
70
61
  2. Structure:
71
62
  - Opening quote (sets the tone)
72
63
  - Core principle (1-2 sentences)
73
- - BANNED / REQUIRED sections with code examples
74
- - Decision tree or quick reference (if applicable)
64
+ - BANNED / REQUIRED sections with enforceable boundaries
65
+ - Decision tree or quick ruleset when it reduces ambiguity
75
66
  3. Update `AGENTS.md` rules manifest table
76
- 4. Update `review-checklists/pr-checklist.md` if the rule should be checked in reviews
67
+ 4. Update `review-checklists/pr-checklist.md` when the rule is part of review scope
77
68
  5. Validate and PR
78
69
 
79
70
  ---
@@ -95,7 +86,7 @@ If all three are "yes", it belongs here.
95
86
  ## What We Don't Accept
96
87
 
97
88
  - Generic content that reads like it was auto-generated without thought
98
- - Rules without concrete code examples
89
+ - Rules without concrete enforcement boundaries
99
90
  - Stack profiles for languages the author doesn't actually use in production
100
91
  - Blueprints that are just folder structures without code patterns
101
92
  - PRs that don't update the relevant manifest files (AGENTS.md, checklists)
package/README.md CHANGED
@@ -14,7 +14,7 @@ Latest release: 3.0.9 (2026-04-20).
14
14
 
15
15
  Highlights in 3.0.9:
16
16
  - Design bootstrap prompts now rely on shipped project evidence instead of assuming extra docs exist in every initialized repository.
17
- - Dynamic UI design guidance now emphasizes structure, rationale, and anti-generic constraints without anchoring to example brand systems.
17
+ - Dynamic UI design guidance now emphasizes structure, rationale, and anti-generic constraints without anchoring to brand systems.
18
18
  - Init prompts now point agents at the active onboarding and compiled-rule context that actually exists in target projects.
19
19
 
20
20
  </div>
@@ -31,26 +31,12 @@ npx @ryuenn3123/agentic-senior-core init
31
31
 
32
32
  One command to initialize rules, checklists, and strict AI coding guidelines context for your project.
33
33
 
34
- > **See [docs/deep-dive.md](docs/deep-dive.md) and [docs/roadmap.md](docs/roadmap.md) for advanced configuration, architect mode, snapshot, and realtime options.**
34
+ > **See [docs/deep-dive.md](docs/deep-dive.md) and [docs/roadmap.md](docs/roadmap.md) for advanced configuration, planning mode, snapshot, and realtime options.**
35
35
 
36
36
  - This command writes `.agent-context/state/v3-purge-audit.json` and reports whether static directory deletion is safe.
37
37
 
38
38
  ---
39
39
 
40
- ## Before / After
41
-
42
- ```text
43
- Before:
44
- "Build me a user registration API"
45
- => one file, weak validation, no typed errors, weak structure
46
-
47
- After:
48
- "Build me a user registration API"
49
- => layered modules, validated inputs, typed errors, tests, docs updates
50
- ```
51
-
52
- ---
53
-
54
40
  ## MCP Quick Setup (VS Code)
55
41
 
56
42
  1. Generate workspace MCP config:
@@ -73,7 +59,7 @@ If you see `Property $schema is not allowed`, keep `.vscode/mcp.json` without `$
73
59
 
74
60
  | Command | Purpose |
75
61
  |---------|---------|
76
- | `agentic-senior-core init` | Initialize strict AI coding guidelines (Federated Governance baseline) |
62
+ | `agentic-senior-core init` | Initialize the project guidance pack and compiled AI rulebook |
77
63
  | `agentic-senior-core upgrade --dry-run` | Preview safe upgrades |
78
64
  | `agentic-senior-core optimize --show` | Show token optimization state |
79
65
  | `npm run audit:v3-purge` | Run deep purge readiness audit (no deletion) |
@@ -97,9 +83,9 @@ Use `--no-prune` if you want to keep legacy managed files.
97
83
 
98
84
  ## Terminology Mapping (Final)
99
85
 
100
- | Canonical Enterprise Term | Developer-Facing Alias | Usage Rule |
101
- |---------------------------|------------------------|------------|
102
- | Federated Governance | Federated Rules Operations | Use canonical term in compliance/audit artifacts. |
86
+ | Canonical Term | Developer-Facing Alias | Usage Rule |
87
+ |----------------|------------------------|------------|
88
+ | Federated Governance | Federated Rules Operations | Use canonical term in formal policy artifacts. |
103
89
  | Governance Engine | Rules Engine | Use alias in onboarding and day-to-day developer docs. |
104
90
  | Guardrails | Quality Checks | Use alias in implementation guidance and quickstart docs. |
105
91
 
@@ -14,18 +14,17 @@ import {
14
14
  INIT_PRESETS,
15
15
  PROFILE_PRESETS,
16
16
  GOLDEN_STANDARD_PROFILE_NAME,
17
- BLUEPRINT_RECOMMENDATIONS,
18
- FALLBACK_STACK_FILE_NAMES,
19
- FALLBACK_BLUEPRINT_FILE_NAMES,
17
+ AGENT_DECISION_STACK_FILE_NAME,
18
+ AGENT_DECISION_BLUEPRINT_FILE_NAME,
20
19
  RUNTIME_ENVIRONMENT_CHOICES,
21
20
  } from '../constants.mjs';
22
21
 
23
22
  import {
24
23
  ensureDirectory,
25
- askChoice,
26
24
  askYesNo,
27
25
  toTitleCase,
28
26
  matchFileNameFromInput,
27
+ normalizeChoiceInput,
29
28
  collectFileNames,
30
29
  formatBlockingSeverities,
31
30
  formatDuration,
@@ -41,20 +40,13 @@ import {
41
40
  } from '../detector.mjs';
42
41
  import { compileDynamicContext, writeSelectedPolicy, writeOnboardingReport } from '../compiler.mjs';
43
42
  import {
44
- filterStackFileNamesByCandidates,
45
- filterBlueprintFileNamesByCandidates,
46
43
  normalizeAdditionalStackSelection,
47
44
  normalizeAdditionalBlueprintSelection,
48
- deriveAdditionalBlueprintFileNamesFromStacks,
49
- resolveScopeStackCandidates,
50
- resolveScopeBlueprintCandidates,
51
45
  } from '../init-selection.mjs';
52
46
  import {
53
47
  buildExistingProjectMajorConstraints,
54
48
  resolveDetectedSetupDecision,
55
49
  } from '../init-detection-flow.mjs';
56
- // Existing project quick confirmation prompt string is preserved for validator coverage:
57
- // Use detected setup for this existing project?
58
50
  import { runPreflightChecks } from '../preflight.mjs';
59
51
  import { createBackup } from '../backup.mjs';
60
52
  import {
@@ -77,7 +69,6 @@ import {
77
69
  createMemoryContinuityState,
78
70
  writeMemoryContinuityState,
79
71
  } from '../memory-continuity.mjs';
80
- import { recommendArchitecture } from '../architect.mjs';
81
72
 
82
73
  export { REPO_ROOT } from '../constants.mjs';
83
74
  export {
@@ -85,13 +76,67 @@ export {
85
76
  normalizeRuntimeEnvironmentKey,
86
77
  } from '../init-options.mjs';
87
78
  export {
88
- filterStackFileNamesByCandidates,
89
- filterBlueprintFileNamesByCandidates,
90
79
  resolveProjectScopeKeyFromLabel,
91
80
  normalizeAdditionalStackSelection,
92
81
  normalizeAdditionalBlueprintSelection,
93
82
  } from '../init-selection.mjs';
94
83
 
84
+ function normalizeContextLine(rawText) {
85
+ return String(rawText || '')
86
+ .replace(/\s+/g, ' ')
87
+ .trim();
88
+ }
89
+
90
+ async function readTextIfExists(filePath) {
91
+ try {
92
+ return await fs.readFile(filePath, 'utf8');
93
+ } catch {
94
+ return '';
95
+ }
96
+ }
97
+
98
+ function extractMarkdownContext(rawMarkdown) {
99
+ return String(rawMarkdown || '')
100
+ .split(/\r?\n/)
101
+ .map((line) => normalizeContextLine(line.replace(/^#+\s*/, '')))
102
+ .filter((line) => line && !line.startsWith('---') && !line.startsWith('```'))
103
+ .slice(0, 3)
104
+ .join(' ');
105
+ }
106
+
107
+ async function inferExistingProjectDescriptionHint(targetDirectoryPath) {
108
+ const evidence = [];
109
+ const packageJsonContent = await readTextIfExists(path.join(targetDirectoryPath, 'package.json'));
110
+
111
+ if (packageJsonContent) {
112
+ try {
113
+ const packageManifest = JSON.parse(packageJsonContent);
114
+ const packageSummary = [
115
+ normalizeContextLine(packageManifest.name),
116
+ normalizeContextLine(packageManifest.description),
117
+ ].filter(Boolean).join(': ');
118
+
119
+ if (packageSummary) {
120
+ evidence.push(`package.json: ${packageSummary}`);
121
+ }
122
+ } catch {
123
+ // Invalid package metadata should not block init; other files can still provide context.
124
+ }
125
+ }
126
+
127
+ for (const relativeDocPath of ['docs/project-brief.md', 'docs/README.md', 'README.md']) {
128
+ const docContext = extractMarkdownContext(
129
+ await readTextIfExists(path.join(targetDirectoryPath, relativeDocPath))
130
+ );
131
+
132
+ if (docContext) {
133
+ evidence.push(`${relativeDocPath}: ${docContext}`);
134
+ }
135
+ }
136
+
137
+ return evidence.slice(0, 3).join(' | ');
138
+ }
139
+
95
140
  export function resolveRuntimeEnvironmentKeyFromLabel(selectedRuntimeEnvironmentLabel) {
96
141
  const runtimeEnvironmentEntry = RUNTIME_ENVIRONMENT_CHOICES.find(
97
142
  (runtimeEnvironmentChoice) => runtimeEnvironmentChoice.label === selectedRuntimeEnvironmentLabel
@@ -218,18 +263,17 @@ function resolveSilentCiGuardrailsDefault({
218
263
  };
219
264
  }
220
265
 
221
- async function askStackSelection(promptMessage, selectableStackFileNames, userInterface) {
222
- const stackDisplayChoices = selectableStackFileNames.map((stackFileName) => toTitleCase(stackFileName));
223
- const selectedDisplayChoice = await askChoice(promptMessage, stackDisplayChoices, userInterface);
224
- const selectedIndex = stackDisplayChoices.indexOf(selectedDisplayChoice);
225
- return selectableStackFileNames[selectedIndex] || selectableStackFileNames[0] || null;
226
- }
266
+ function normalizeExplicitProfileFileName(rawInput, discoveredFileNames) {
267
+ const matchedFileName = Array.isArray(discoveredFileNames) && discoveredFileNames.length > 0
268
+ ? matchFileNameFromInput(rawInput, discoveredFileNames)
269
+ : null;
270
+
271
+ if (matchedFileName) {
272
+ return matchedFileName;
273
+ }
227
274
 
228
- async function askBlueprintSelection(promptMessage, selectableBlueprintFileNames, userInterface) {
229
- const blueprintDisplayChoices = selectableBlueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName));
230
- const selectedDisplayChoice = await askChoice(promptMessage, blueprintDisplayChoices, userInterface);
231
- const selectedIndex = blueprintDisplayChoices.indexOf(selectedDisplayChoice);
232
- return selectableBlueprintFileNames[selectedIndex] || selectableBlueprintFileNames[0] || null;
275
+ const normalizedBaseName = normalizeChoiceInput(String(rawInput || '').replace(/\.md$/i, ''));
276
+ return normalizedBaseName ? `${normalizedBaseName}.md` : null;
233
277
  }
234
278
 
235
279
  function buildInitExistingProjectDesignIntentSeed({
@@ -238,14 +282,14 @@ function buildInitExistingProjectDesignIntentSeed({
238
282
  selectedStackFileName,
239
283
  selectedBlueprintFileName,
240
284
  uiScopeSignals,
241
- architectureProjectDescription,
285
+ projectDescriptionHint,
242
286
  }) {
243
287
  const projectName = String(packageManifest?.name || path.basename(targetDirectoryPath)).trim() || 'existing-ui-project';
244
288
  const isMobileUiProject = String(selectedStackFileName || '').toLowerCase().includes('react-native')
245
289
  || String(selectedStackFileName || '').toLowerCase().includes('flutter')
246
290
  || uiScopeSignals.signalReasons.some((signalReason) => signalReason.includes('android') || signalReason.includes('ios'));
247
291
  const resolvedDomain = isMobileUiProject ? 'Mobile app' : 'Web application';
248
- const projectDescription = String(packageManifest?.description || architectureProjectDescription || '').trim()
292
+ const projectDescription = String(packageManifest?.description || projectDescriptionHint || '').trim()
249
293
  || `Existing ${resolvedDomain.toLowerCase()} detected during init. Create a project-specific dynamic design contract before shipping new UI work.`;
250
294
 
251
295
  return buildDesignIntentSeedFromSignals({
@@ -310,12 +354,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
310
354
  try {
311
355
  const discoveredStackFileNames = await collectFileNames(path.join(AGENT_CONTEXT_DIR, 'stacks'));
312
356
  const discoveredBlueprintFileNames = await collectFileNames(path.join(AGENT_CONTEXT_DIR, 'blueprints'));
313
- const stackFileNames = discoveredStackFileNames.length > 0
314
- ? discoveredStackFileNames
315
- : FALLBACK_STACK_FILE_NAMES;
316
- const blueprintFileNames = discoveredBlueprintFileNames.length > 0
317
- ? discoveredBlueprintFileNames
318
- : FALLBACK_BLUEPRINT_FILE_NAMES;
319
357
 
320
358
  if (discoveredStackFileNames.length === 0 || discoveredBlueprintFileNames.length === 0) {
321
359
  console.log('[INFO] Static stack/blueprint profiles are not fully present. Using compatibility labels for dynamic reasoning mode.');
@@ -324,25 +362,18 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
324
362
  const selectedPreset = initOptions.preset ? INIT_PRESETS[initOptions.preset] || null : null;
325
363
 
326
364
  const selectedStackFileNameFromOption = initOptions.stack
327
- ? matchFileNameFromInput(initOptions.stack, stackFileNames)
365
+ ? normalizeExplicitProfileFileName(initOptions.stack, discoveredStackFileNames)
328
366
  : null;
329
367
  const selectedBlueprintFileNameFromOption = initOptions.blueprint
330
- ? matchFileNameFromInput(initOptions.blueprint, blueprintFileNames)
368
+ ? normalizeExplicitProfileFileName(initOptions.blueprint, discoveredBlueprintFileNames)
331
369
  : null;
332
- if (initOptions.stack && !selectedStackFileNameFromOption) {
333
- throw new Error(`Unknown stack: ${initOptions.stack}`);
334
- }
335
-
336
- if (initOptions.blueprint && !selectedBlueprintFileNameFromOption) {
337
- throw new Error(`Unknown blueprint: ${initOptions.blueprint}`);
338
- }
339
370
 
340
371
  if (initOptions.preset && !selectedPreset) {
341
372
  throw new Error(`Unknown preset: ${initOptions.preset}`);
342
373
  }
343
374
 
344
375
  console.log(`\nAgentic-Senior-Core CLI v${CLI_VERSION}`);
345
- console.log('I will copy rules operations assets (Federated Governance baseline) into your target folder and compile a single rulebook for your AI tools.');
376
+ console.log('I will copy the project guidance pack into your target folder and compile a single rulebook for your AI tools.');
346
377
 
347
378
  if (selectedPreset) {
348
379
  console.log(`Using preset: ${initOptions.preset} (${selectedPreset.description}).`);
@@ -418,10 +449,10 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
418
449
  if (projectDetection.hasExistingProjectFiles) {
419
450
  console.log('\nExisting project detection transparency:');
420
451
 
421
- if (projectDetection.recommendedStackFileName) {
452
+ if (projectDetection.detectedStackFileName) {
422
453
  const confidenceScoreLabel = Number(projectDetection.confidenceScore || 0).toFixed(2);
423
454
  console.log(
424
- `- Detected stack: ${toTitleCase(projectDetection.recommendedStackFileName)} (${projectDetection.confidenceLabel}, score ${confidenceScoreLabel})`
455
+ `- Detected stack: ${toTitleCase(projectDetection.detectedStackFileName)} (${projectDetection.confidenceLabel}, score ${confidenceScoreLabel})`
425
456
  );
426
457
 
427
458
  if (projectDetection.secondaryStackFileNames?.length) {
@@ -444,17 +475,10 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
444
475
  }
445
476
 
446
477
  const hasReliableDetectedStack = projectDetection.hasExistingProjectFiles
447
- && projectDetection.recommendedStackFileName
478
+ && projectDetection.detectedStackFileName
448
479
  && (projectDetection.confidenceLabel === 'high' || projectDetection.confidenceLabel === 'medium');
449
480
 
450
- const shouldAutoApplyDetectedStack = hasReliableDetectedStack
451
- && !selectedStackFileNameFromOption
452
- && !selectedPreset?.stack
453
- && !selectedPolicyProfile.defaultStackFileName;
454
- let detectedBlueprintFileName = projectDetection.recommendedBlueprintFileName
455
- || BLUEPRINT_RECOMMENDATIONS[projectDetection.recommendedStackFileName]
456
- || null;
457
-
481
+ const shouldAutoApplyDetectedStack = false;
458
482
  let selectedManualStackFileName = null;
459
483
  let selectedManualBlueprintFileName = null;
460
484
  let selectedAdditionalStackFileNames = [];
@@ -462,8 +486,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
462
486
  let detectedSetupWasApplied = false;
463
487
  let selectedProjectScopeKey = 'both';
464
488
  let selectedProjectScopeLabel = resolveProjectScopeLabelFromKey('both');
465
- let architectureRecommendation = null;
466
- let architectureProjectDescription = String(initOptions.projectDescription || '').trim();
489
+ let projectDescriptionHint = String(initOptions.projectDescription || '').trim();
467
490
  let discoveryAnswers = null;
468
491
  const ciGuardrailsSelection = resolveSilentCiGuardrailsDefault({
469
492
  initOptions,
@@ -476,17 +499,20 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
476
499
  const shouldRunInteractiveScaffolding = isInteractiveSession
477
500
  && (initOptions.scaffoldDocs === true || (initOptions.scaffoldDocs !== false && isFreshProjectTarget));
478
501
 
502
+ if (projectDetection.hasExistingProjectFiles && !projectDescriptionHint) {
503
+ projectDescriptionHint = await inferExistingProjectDescriptionHint(resolvedTargetDirectoryPath);
504
+ if (projectDescriptionHint) {
505
+ console.log(`- Project context evidence: ${projectDescriptionHint}`);
506
+ } else {
507
+ console.log('- Project context evidence: unresolved from lightweight file scan; agent must inspect project files before coding.');
508
+ }
509
+ }
510
+ detectionTransparency.projectContextEvidence = projectDescriptionHint || null;
511
+
479
512
  const detectedSetupDecision = await resolveDetectedSetupDecision({
480
513
  shouldAutoApplyDetectedStack,
481
514
  projectDetection,
482
- stackFileNames,
483
- blueprintFileNames,
484
- userInterface,
485
- isInteractiveSession,
486
515
  detectionTransparency,
487
- askYesNo,
488
- askStackSelection,
489
- askBlueprintSelection,
490
516
  initialSelectedManualStackFileName: selectedManualStackFileName,
491
517
  initialSelectedManualBlueprintFileName: selectedManualBlueprintFileName,
492
518
  initialSelectedAdditionalStackFileNames: selectedAdditionalStackFileNames,
@@ -496,15 +522,13 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
496
522
  selectedManualStackFileName = detectedSetupDecision.selectedManualStackFileName;
497
523
  selectedManualBlueprintFileName = detectedSetupDecision.selectedManualBlueprintFileName;
498
524
  selectedAdditionalStackFileNames = detectedSetupDecision.selectedAdditionalStackFileNames;
499
- detectedBlueprintFileName = detectedSetupDecision.detectedBlueprintFileName;
500
-
501
525
  if (initOptions.projectConfig) {
502
526
  discoveryAnswers = await loadProjectConfig(initOptions.projectConfig);
503
527
  console.log(`\nLoaded project configuration from: ${initOptions.projectConfig}`);
504
528
  } else if (shouldRunInteractiveScaffolding) {
505
529
  discoveryAnswers = await runProjectDiscovery(userInterface, {
506
530
  defaultProjectName: path.basename(resolvedTargetDirectoryPath),
507
- defaultProjectDescription: architectureProjectDescription,
531
+ defaultProjectDescription: projectDescriptionHint,
508
532
  defaultIncludeCiGuardrails: ciGuardrailsSelection.value,
509
533
  askForCiGuardrails: ciGuardrailsSelection.shouldAsk,
510
534
  });
@@ -513,7 +537,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
513
537
  }
514
538
 
515
539
  if (discoveryAnswers?.projectDescription) {
516
- architectureProjectDescription = discoveryAnswers.projectDescription;
540
+ projectDescriptionHint = discoveryAnswers.projectDescription;
517
541
  }
518
542
 
519
543
  if (discoveryAnswers) {
@@ -521,98 +545,26 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
521
545
  selectedProjectScopeLabel = resolveProjectScopeLabelFromKey(selectedProjectScopeKey);
522
546
  }
523
547
 
524
- const shouldUseSilentArchitectureSelection = !selectedStackFileNameFromOption
525
- && !selectedPreset?.stack
526
- && !shouldAutoApplyDetectedStack
527
- && !selectedPolicyProfile.defaultStackFileName;
528
-
529
- if (shouldUseSilentArchitectureSelection) {
530
- const architectureScopeStackCandidates = filterStackFileNamesByCandidates(
531
- stackFileNames,
532
- resolveScopeStackCandidates(selectedProjectScopeKey)
533
- );
534
- const architectureScopeBlueprintCandidates = filterBlueprintFileNamesByCandidates(
535
- blueprintFileNames,
536
- resolveScopeBlueprintCandidates(selectedProjectScopeKey)
537
- );
538
-
539
- architectureRecommendation = recommendArchitecture({
540
- projectDescription: architectureProjectDescription || `A software project named ${path.basename(resolvedTargetDirectoryPath)}.`,
541
- projectDetection,
542
- stackFileNames: architectureScopeStackCandidates,
543
- blueprintFileNames: architectureScopeBlueprintCandidates,
544
- });
545
-
546
- architectureRecommendation.projectDomain = {
547
- key: selectedProjectScopeKey,
548
- label: selectedProjectScopeLabel,
549
- };
550
- architectureRecommendation.userVeto = {
551
- applied: false,
552
- selectedStackFileName: architectureRecommendation.recommendedStackFileName,
553
- selectedBlueprintFileName: architectureRecommendation.recommendedBlueprintFileName,
554
- source: projectDetection.hasExistingProjectFiles ? 'silent-existing-bootstrap' : 'silent-fresh-bootstrap',
555
- };
556
-
557
- selectedManualStackFileName = architectureRecommendation.recommendedStackFileName;
558
- selectedManualBlueprintFileName = architectureRecommendation.recommendedBlueprintFileName;
559
-
560
- if (!projectDetection.hasExistingProjectFiles) {
561
- detectionTransparency.quickConfirmation.response = 'fresh-project-streamlined';
562
- detectionTransparency.decision.mode = 'fresh-project-streamlined';
563
- }
564
- }
565
-
566
- const blueprintDisplayChoices = blueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName));
567
-
568
548
  const selectedResolvedStackFileName = selectedStackFileNameFromOption
569
- || selectedPreset?.stack
570
549
  || selectedManualStackFileName
571
- || (detectedSetupWasApplied ? projectDetection.recommendedStackFileName : null)
572
550
  || selectedPolicyProfile.defaultStackFileName
573
- || stackFileNames[0];
551
+ || AGENT_DECISION_STACK_FILE_NAME;
574
552
 
575
553
  selectedAdditionalStackFileNames = normalizeAdditionalStackSelection(
576
554
  selectedResolvedStackFileName,
577
555
  selectedAdditionalStackFileNames
578
556
  );
579
557
 
580
- const recommendedBlueprintFileName = detectedSetupWasApplied
581
- && detectedBlueprintFileName
582
- ? detectedBlueprintFileName
583
- : BLUEPRINT_RECOMMENDATIONS[selectedResolvedStackFileName] || null;
584
-
585
- if (!recommendedBlueprintFileName && !selectedBlueprintFileNameFromOption && !selectedPolicyProfile.defaultBlueprintFileName) {
586
- console.log('\nI could not map that stack to a first-party blueprint automatically, so I will ask you to choose one.');
587
- }
588
-
589
558
  const selectedResolvedBlueprintFileName = selectedBlueprintFileNameFromOption
590
- || selectedPreset?.blueprint
591
559
  || selectedManualBlueprintFileName
592
- || recommendedBlueprintFileName
593
560
  || selectedPolicyProfile.defaultBlueprintFileName
594
- || blueprintFileNames[
595
- blueprintDisplayChoices.indexOf(
596
- await askChoice('Which blueprint should I scaffold into the compiled rulebook?', blueprintDisplayChoices, userInterface)
597
- )
598
- ];
599
-
600
- if (architectureRecommendation) {
601
- architectureRecommendation.appliedStackFileName = selectedResolvedStackFileName;
602
- architectureRecommendation.appliedBlueprintFileName = selectedResolvedBlueprintFileName;
603
- }
604
-
605
- const derivedAdditionalBlueprintFileNames = deriveAdditionalBlueprintFileNamesFromStacks(
606
- selectedAdditionalStackFileNames,
607
- blueprintFileNames,
608
- selectedResolvedBlueprintFileName
609
- );
561
+ || AGENT_DECISION_BLUEPRINT_FILE_NAME;
610
562
 
611
563
  selectedAdditionalBlueprintFileNames = normalizeAdditionalBlueprintSelection(
612
564
  selectedResolvedBlueprintFileName,
613
565
  selectedAdditionalBlueprintFileNames.length > 0
614
566
  ? selectedAdditionalBlueprintFileNames
615
- : derivedAdditionalBlueprintFileNames
567
+ : []
616
568
  );
617
569
 
618
570
  detectionTransparency.decision.selectedStackFileName = selectedResolvedStackFileName;
@@ -696,7 +648,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
696
648
  additionalBlueprintFileNames: selectedAdditionalBlueprintFileNames,
697
649
  runtimeEnvironmentKey: selectedRuntimeEnvironmentKey,
698
650
  runtimeEnvironmentLabel: resolveRuntimeEnvironmentLabelFromKey(selectedRuntimeEnvironmentKey),
699
- architectureRecommendation,
700
651
  },
701
652
  {
702
653
  docsLanguage: selectedDocsLanguage,
@@ -740,7 +691,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
740
691
  selectedStackFileName: selectedResolvedStackFileName,
741
692
  selectedBlueprintFileName: selectedResolvedBlueprintFileName,
742
693
  uiScopeSignals: existingProjectUiScopeSignals,
743
- architectureProjectDescription,
694
+ projectDescriptionHint,
744
695
  });
745
696
 
746
697
  await ensureDirectory(docsDirectoryPath);
@@ -798,7 +749,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
798
749
  adapters: memoryContinuityState?.adapters || [],
799
750
  stateFile: isMemoryContinuityEnabled ? '.agent-context/state/memory-continuity.json' : null,
800
751
  },
801
- architectRecommendation: architectureRecommendation,
802
752
  detectionTransparency,
803
753
  uiScopeSignals: existingProjectUiScopeSignals,
804
754
  });
@@ -814,11 +764,11 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
814
764
  console.log(`- Project topology: ${discoveryAnswers.architectureStyle}`);
815
765
  }
816
766
  }
817
- console.log(`- Stack: ${toTitleCase(selectedResolvedStackFileName)}`);
767
+ console.log(`- Runtime decision: ${selectedResolvedStackFileName === AGENT_DECISION_STACK_FILE_NAME ? 'agent recommendation required from current repo/brief evidence' : toTitleCase(selectedResolvedStackFileName)}`);
818
768
  if (selectedAdditionalStackFileNames.length > 0) {
819
769
  console.log(`- Additional stacks: ${selectedAdditionalStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}`);
820
770
  }
821
- console.log(`- Blueprint: ${toTitleCase(selectedResolvedBlueprintFileName)}`);
771
+ console.log(`- Architecture decision: ${selectedResolvedBlueprintFileName === AGENT_DECISION_BLUEPRINT_FILE_NAME ? 'agent recommendation required from current repo/brief evidence' : toTitleCase(selectedResolvedBlueprintFileName)}`);
822
772
  if (selectedAdditionalBlueprintFileNames.length > 0) {
823
773
  console.log(`- Additional blueprints: ${selectedAdditionalBlueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName)).join(', ')}`);
824
774
  }
@@ -854,7 +804,11 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
854
804
  console.log('- Token optimization policy: disabled (--no-token-optimize)');
855
805
  }
856
806
  console.log('\nPlain-language summary:');
857
- console.log(`I prepared a repo-grounded rules operations pack (Federated Governance baseline) for a ${toTitleCase(selectedResolvedStackFileName)} project using the ${toTitleCase(selectedResolvedBlueprintFileName)} blueprint.`);
807
+ if (selectedResolvedStackFileName === AGENT_DECISION_STACK_FILE_NAME || selectedResolvedBlueprintFileName === AGENT_DECISION_BLUEPRINT_FILE_NAME) {
808
+ console.log('I prepared a repo-grounded guidance pack that asks your AI agent to recommend runtime and architecture choices from the current brief, repo evidence, and live research before coding.');
809
+ } else {
810
+ console.log(`I prepared a repo-grounded guidance pack using your explicit runtime constraint (${toTitleCase(selectedResolvedStackFileName)}) and architecture constraint (${toTitleCase(selectedResolvedBlueprintFileName)}).`);
811
+ }
858
812
  if (selectedAdditionalStackFileNames.length > 0) {
859
813
  console.log(`I also included additional stack context for ${selectedAdditionalStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
860
814
  }
@@ -21,7 +21,7 @@ export async function runLaunchCommand() {
21
21
  'How do you want to start?',
22
22
  [
23
23
  'npm / npx path',
24
- 'Preset starter',
24
+ 'Scope hint preset',
25
25
  'Interactive init wizard',
26
26
  'Enable token optimization',
27
27
  'Exit',
@@ -37,10 +37,10 @@ export async function runLaunchCommand() {
37
37
  return;
38
38
  }
39
39
 
40
- if (launchChoice === 'Preset starter') {
40
+ if (launchChoice === 'Scope hint preset') {
41
41
  const presetNames = Object.keys(INIT_PRESETS);
42
42
  const selectedPresetName = await askChoice(
43
- 'Choose a starter preset:',
43
+ 'Choose a scope hint preset:',
44
44
  presetNames.map((presetName) => `${presetName} - ${INIT_PRESETS[presetName].description}`),
45
45
  userInterface
46
46
  );
@@ -3,6 +3,10 @@ import path from 'node:path';
3
3
 
4
4
  import { ensureDirectory, formatDuration } from '../utils.mjs';
5
5
  import { compileDynamicContext, loadOnboardingReportIfExists } from '../compiler.mjs';
6
+ import {
7
+ AGENT_DECISION_STACK_FILE_NAME,
8
+ AGENT_DECISION_BLUEPRINT_FILE_NAME,
9
+ } from '../constants.mjs';
6
10
  import {
7
11
  TOKEN_OPTIMIZATION_REPORT_FILE_NAME,
8
12
  normalizeAgentName,
@@ -115,14 +119,20 @@ export async function runOptimizeCommand(targetDirectoryArgument, optimizeOption
115
119
 
116
120
  await writeTokenOptimizationState(resolvedTargetDirectoryPath, tokenOptimizationState);
117
121
 
118
- const selectedStackFileName = normalizeMarkdownFileName(onboardingReport.selectedStack, 'typescript.md');
119
- const selectedAdditionalStackFileNames = Array.isArray(onboardingReport.selectedAdditionalStacks)
122
+ const hasExplicitRuntimeConstraint = onboardingReport?.runtimeDecision?.mode === 'explicit-constraint';
123
+ const hasExplicitArchitectureConstraint = onboardingReport?.architectureDecision?.mode === 'explicit-constraint';
124
+ const selectedStackFileName = hasExplicitRuntimeConstraint
125
+ ? normalizeMarkdownFileName(onboardingReport.selectedStack, AGENT_DECISION_STACK_FILE_NAME)
126
+ : AGENT_DECISION_STACK_FILE_NAME;
127
+ const selectedAdditionalStackFileNames = hasExplicitRuntimeConstraint && Array.isArray(onboardingReport.selectedAdditionalStacks)
120
128
  ? onboardingReport.selectedAdditionalStacks
121
129
  .map((stackFileName) => normalizeMarkdownFileName(stackFileName, ''))
122
130
  .filter((stackFileName) => stackFileName && stackFileName !== selectedStackFileName)
123
131
  : [];
124
- const selectedBlueprintFileName = normalizeMarkdownFileName(onboardingReport.selectedBlueprint, 'api-nextjs.md');
125
- const selectedAdditionalBlueprintFileNames = Array.isArray(onboardingReport.selectedAdditionalBlueprints)
132
+ const selectedBlueprintFileName = hasExplicitArchitectureConstraint
133
+ ? normalizeMarkdownFileName(onboardingReport.selectedBlueprint, AGENT_DECISION_BLUEPRINT_FILE_NAME)
134
+ : AGENT_DECISION_BLUEPRINT_FILE_NAME;
135
+ const selectedAdditionalBlueprintFileNames = hasExplicitArchitectureConstraint && Array.isArray(onboardingReport.selectedAdditionalBlueprints)
126
136
  ? onboardingReport.selectedAdditionalBlueprints
127
137
  .map((blueprintFileName) => normalizeMarkdownFileName(blueprintFileName, ''))
128
138
  .filter((blueprintFileName) => blueprintFileName && blueprintFileName !== selectedBlueprintFileName)