@ryuenn3123/agentic-senior-core 3.0.12 → 3.0.13

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.
@@ -20,9 +20,16 @@ The `.agent-context/rules/` directory is the default guidance source for impleme
20
20
  - Backend and frontend mindset checks are both required when a task spans API and UI boundaries.
21
21
  - Security and testing are non-negotiable baseline requirements.
22
22
  - Hard block before coding:
23
+ - `docs/project-brief.md` must exist.
23
24
  - `docs/architecture-decision-record.md` (alias: `docs/Architecture-Decision-Record.md`) must exist.
25
+ - `docs/flow-overview.md` must exist.
26
+ - If the project uses persistent data, `docs/database-schema.md` must exist.
27
+ - If the project exposes API or web application flows, `docs/api-contract.md` must exist.
24
28
  - For UI scope, `docs/DESIGN.md` and `docs/design-intent.json` must exist.
25
29
  - If required project context docs are missing, stop implementation and bootstrap docs before writing application code.
30
+ - Bootstrap flow: analyze the real repo plus the latest user prompt before authoring those docs.
31
+ - Bootstrap docs must be adaptive and project-specific. Do not create generic placeholder templates.
32
+ - When context is incomplete, separate confirmed facts from assumptions, add an `Assumptions to Validate` section, and end with the next validation action.
26
33
 
27
34
  ## Rules as Guardian (Cross-Session Consistency)
28
35
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-04-21T07:20:28.027Z",
2
+ "generatedAt": "2026-04-21T11:40:14.071Z",
3
3
  "reportName": "memory-continuity-benchmark",
4
4
  "schemaVersion": "1.0.0",
5
5
  "passed": true,
package/.cursorrules CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET
2
2
 
3
- Generated by Agentic-Senior-Core CLI v3.0.12
3
+ Generated by Agentic-Senior-Core CLI v3.0.13
4
4
  Timestamp: 2026-04-18T00:00:00.000Z
5
5
  Selected profile: beginner
6
6
  Selected policy file: .agent-context/policies/llm-judge-threshold.json
package/.windsurfrules CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET
2
2
 
3
- Generated by Agentic-Senior-Core CLI v3.0.12
3
+ Generated by Agentic-Senior-Core CLI v3.0.13
4
4
  Timestamp: 2026-04-18T00:00:00.000Z
5
5
  Selected profile: beginner
6
6
  Selected policy file: .agent-context/policies/llm-judge-threshold.json
@@ -8,13 +8,13 @@ import fs from 'node:fs/promises';
8
8
  import path from 'node:path';
9
9
 
10
10
  import {
11
+ PROJECT_SCOPE_CHOICES,
11
12
  CLI_VERSION,
12
13
  AGENT_CONTEXT_DIR,
13
14
  INIT_PRESETS,
14
15
  PROFILE_PRESETS,
15
16
  GOLDEN_STANDARD_PROFILE_NAME,
16
17
  BLUEPRINT_RECOMMENDATIONS,
17
- PROJECT_SCOPE_CHOICES,
18
18
  FALLBACK_STACK_FILE_NAMES,
19
19
  FALLBACK_BLUEPRINT_FILE_NAMES,
20
20
  RUNTIME_ENVIRONMENT_CHOICES,
@@ -42,10 +42,13 @@ import {
42
42
  } from '../detector.mjs';
43
43
  import { compileDynamicContext, writeSelectedPolicy, writeOnboardingReport } from '../compiler.mjs';
44
44
  import {
45
+ filterStackFileNamesByCandidates,
45
46
  filterBlueprintFileNamesByCandidates,
46
47
  normalizeAdditionalStackSelection,
47
48
  normalizeAdditionalBlueprintSelection,
48
49
  deriveAdditionalBlueprintFileNamesFromStacks,
50
+ resolveScopeStackCandidates,
51
+ resolveScopeBlueprintCandidates,
49
52
  } from '../init-selection.mjs';
50
53
  import {
51
54
  buildExistingProjectMajorConstraints,
@@ -75,11 +78,7 @@ import {
75
78
  createMemoryContinuityState,
76
79
  writeMemoryContinuityState,
77
80
  } from '../memory-continuity.mjs';
78
- import {
79
- readArchitectPreferenceState,
80
- writeArchitectPreferenceState,
81
- } from '../architect.mjs';
82
- import { resolveArchitectureSelection } from '../init-architecture-flow.mjs';
81
+ import { recommendArchitecture } from '../architect.mjs';
83
82
 
84
83
  export { REPO_ROOT } from '../constants.mjs';
85
84
  // Keep these architect option flags visible in the init command surface for validator coverage:
@@ -156,6 +155,82 @@ export function detectRuntimeEnvironment() {
156
155
  };
157
156
  }
158
157
 
158
+ function resolveProjectScopeLabelFromKey(projectScopeKey) {
159
+ return PROJECT_SCOPE_CHOICES.find((scopeChoice) => scopeChoice.key === projectScopeKey)?.label
160
+ || PROJECT_SCOPE_CHOICES.find((scopeChoice) => scopeChoice.key === 'both')?.label
161
+ || 'Both (frontend + backend)';
162
+ }
163
+
164
+ function inferProjectScopeFromDiscoveryAnswers(discoveryAnswers) {
165
+ const normalizedDomain = String(discoveryAnswers?.primaryDomain || '').trim().toLowerCase();
166
+ const normalizedDescription = [
167
+ discoveryAnswers?.projectDescription,
168
+ ...(Array.isArray(discoveryAnswers?.features) ? discoveryAnswers.features : []),
169
+ ].join(' ').toLowerCase();
170
+
171
+ if (
172
+ normalizedDomain.includes('api service')
173
+ || normalizedDomain.includes('cli tool')
174
+ || normalizedDomain.includes('library')
175
+ ) {
176
+ return 'backend-only';
177
+ }
178
+
179
+ if (normalizedDomain.includes('mobile app')) {
180
+ return 'frontend-only';
181
+ }
182
+
183
+ if (normalizedDomain.includes('web application')) {
184
+ if (/(landing page|marketing site|showcase|portfolio|brochure|company profile)/.test(normalizedDescription)) {
185
+ return 'frontend-only';
186
+ }
187
+
188
+ return 'both';
189
+ }
190
+
191
+ return 'both';
192
+ }
193
+
194
+ function resolveSilentCiGuardrailsDefault({
195
+ initOptions,
196
+ selectedPreset,
197
+ selectedProfilePack,
198
+ selectedProfile,
199
+ }) {
200
+ if (typeof initOptions.ci === 'boolean') {
201
+ return {
202
+ value: initOptions.ci,
203
+ shouldAsk: false,
204
+ };
205
+ }
206
+
207
+ if (typeof selectedPreset?.ci === 'boolean') {
208
+ return {
209
+ value: selectedPreset.ci,
210
+ shouldAsk: false,
211
+ };
212
+ }
213
+
214
+ if (typeof selectedProfilePack?.defaultCi === 'boolean') {
215
+ return {
216
+ value: selectedProfilePack.defaultCi,
217
+ shouldAsk: Boolean(!selectedProfilePack.lockCi),
218
+ };
219
+ }
220
+
221
+ if (selectedProfile.lockCi) {
222
+ return {
223
+ value: selectedProfile.defaultCi,
224
+ shouldAsk: false,
225
+ };
226
+ }
227
+
228
+ return {
229
+ value: selectedProfile.defaultCi,
230
+ shouldAsk: true,
231
+ };
232
+ }
233
+
159
234
  async function askStackSelection(promptMessage, selectableStackFileNames, userInterface) {
160
235
  const stackDisplayChoices = selectableStackFileNames.map((stackFileName) => toTitleCase(stackFileName));
161
236
  const selectedDisplayChoice = await askChoice(promptMessage, stackDisplayChoices, userInterface);
@@ -242,8 +317,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
242
317
  const wasDirectoryEffectivelyEmpty = await isDirectoryEffectivelyEmpty(resolvedTargetDirectoryPath);
243
318
  const hadExistingProjectDocsBeforeInit = await hasExistingProjectDocs(resolvedTargetDirectoryPath);
244
319
 
245
- await createBackup(resolvedTargetDirectoryPath);
246
-
247
320
  const userInterface = createInterface({ input: stdin, output: stdout });
248
321
 
249
322
  try {
@@ -442,20 +515,21 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
442
515
  let selectedAdditionalBlueprintFileNames = [];
443
516
  let detectedSetupWasApplied = false;
444
517
  let selectedProjectScopeKey = 'both';
445
- let selectedProjectScopeLabel = PROJECT_SCOPE_CHOICES.find(
446
- (scopeChoice) => scopeChoice.key === 'both'
447
- )?.label || 'Both (frontend + backend)';
448
-
518
+ let selectedProjectScopeLabel = resolveProjectScopeLabelFromKey('both');
449
519
  let architectureRecommendation = null;
450
- let architectureProjectDescription = '';
451
- let architectPreferenceState = await readArchitectPreferenceState();
452
- let architectPreferenceUpdated = false;
453
-
454
- const shouldRunArchitectureRecommendation = !selectedStackFileNameFromOption
455
- && !selectedPreset?.stack
456
- && !shouldAutoApplyDetectedStack
457
- && !selectedProfilePack?.defaultStackFileName
458
- && !selectedProfile.defaultStackFileName;
520
+ let architectureProjectDescription = String(initOptions.projectDescription || '').trim();
521
+ let discoveryAnswers = null;
522
+ const ciGuardrailsSelection = resolveSilentCiGuardrailsDefault({
523
+ initOptions,
524
+ selectedPreset,
525
+ selectedProfilePack,
526
+ selectedProfile,
527
+ });
528
+ const isFreshProjectTarget = !projectDetection.hasExistingProjectFiles
529
+ && wasDirectoryEffectivelyEmpty
530
+ && !hadExistingProjectDocsBeforeInit;
531
+ const shouldRunInteractiveScaffolding = isInteractiveSession
532
+ && (initOptions.scaffoldDocs === true || (initOptions.scaffoldDocs !== false && isFreshProjectTarget));
459
533
 
460
534
  const detectedSetupDecision = await resolveDetectedSetupDecision({
461
535
  shouldAutoApplyDetectedStack,
@@ -479,37 +553,76 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
479
553
  selectedAdditionalStackFileNames = detectedSetupDecision.selectedAdditionalStackFileNames;
480
554
  detectedBlueprintFileName = detectedSetupDecision.detectedBlueprintFileName;
481
555
 
482
- const architectureSelection = await resolveArchitectureSelection({
483
- shouldRunArchitectureRecommendation,
484
- initOptions: {
485
- ...initOptions,
486
- targetDirectoryPath: resolvedTargetDirectoryPath,
556
+ if (initOptions.projectConfig) {
557
+ discoveryAnswers = await loadProjectConfig(initOptions.projectConfig);
558
+ console.log(`\nLoaded project configuration from: ${initOptions.projectConfig}`);
559
+ } else if (shouldRunInteractiveScaffolding) {
560
+ discoveryAnswers = await runProjectDiscovery(userInterface, {
561
+ defaultProjectName: path.basename(resolvedTargetDirectoryPath),
562
+ defaultProjectDescription: architectureProjectDescription,
563
+ defaultIncludeCiGuardrails: ciGuardrailsSelection.value,
564
+ askForCiGuardrails: ciGuardrailsSelection.shouldAsk,
565
+ });
566
+ } else if (initOptions.scaffoldDocs === true && !isInteractiveSession) {
567
+ throw new Error('Non-interactive scaffolding requires --project-config when --scaffold-docs is enabled.');
568
+ }
569
+
570
+ if (discoveryAnswers?.projectDescription) {
571
+ architectureProjectDescription = discoveryAnswers.projectDescription;
572
+ }
573
+
574
+ if (discoveryAnswers) {
575
+ selectedProjectScopeKey = inferProjectScopeFromDiscoveryAnswers(discoveryAnswers);
576
+ selectedProjectScopeLabel = resolveProjectScopeLabelFromKey(selectedProjectScopeKey);
577
+ }
578
+
579
+ const shouldUseSilentArchitectureSelection = !selectedStackFileNameFromOption
580
+ && !selectedPreset?.stack
581
+ && !shouldAutoApplyDetectedStack
582
+ && !selectedProfilePack?.defaultStackFileName
583
+ && !selectedProfile.defaultStackFileName;
584
+
585
+ if (shouldUseSilentArchitectureSelection) {
586
+ const architectureScopeStackCandidates = filterStackFileNamesByCandidates(
587
+ stackFileNames,
588
+ resolveScopeStackCandidates(selectedProjectScopeKey)
589
+ );
590
+ const architectureScopeBlueprintCandidates = filterBlueprintFileNamesByCandidates(
591
+ blueprintFileNames,
592
+ resolveScopeBlueprintCandidates(selectedProjectScopeKey)
593
+ );
594
+
595
+ architectureRecommendation = recommendArchitecture({
596
+ projectDescription: architectureProjectDescription || `A software project named ${path.basename(resolvedTargetDirectoryPath)}.`,
597
+ projectDetection,
598
+ stackFileNames: architectureScopeStackCandidates,
599
+ blueprintFileNames: architectureScopeBlueprintCandidates,
600
+ tokenBudget: initOptions.architectTokenBudget,
601
+ timeoutMs: initOptions.architectTimeoutMs,
487
602
  researchMode: initOptions.architectResearchMode,
488
603
  enableRealtimeResearch: initOptions.enableRealtimeResearch,
489
- },
490
- projectDetection,
491
- stackFileNames,
492
- blueprintFileNames,
493
- userInterface,
494
- isInteractiveSession,
495
- initialSelectedProjectScopeKey: selectedProjectScopeKey,
496
- initialSelectedProjectScopeLabel: selectedProjectScopeLabel,
497
- initialSelectedManualStackFileName: selectedManualStackFileName,
498
- initialSelectedManualBlueprintFileName: selectedManualBlueprintFileName,
499
- architectPreferenceState,
500
- askStackSelection,
501
- askBlueprintSelection,
502
- detectionTransparency,
503
- });
604
+ realtimeSignalFilePath: initOptions.architectRealtimeSignalFile,
605
+ });
504
606
 
505
- selectedProjectScopeKey = architectureSelection.selectedProjectScopeKey;
506
- selectedProjectScopeLabel = architectureSelection.selectedProjectScopeLabel;
507
- selectedManualStackFileName = architectureSelection.selectedManualStackFileName;
508
- selectedManualBlueprintFileName = architectureSelection.selectedManualBlueprintFileName;
509
- architectureProjectDescription = architectureSelection.architectureProjectDescription;
510
- architectureRecommendation = architectureSelection.architectureRecommendation;
511
- architectPreferenceState = architectureSelection.architectPreferenceState;
512
- architectPreferenceUpdated = architectureSelection.architectPreferenceUpdated;
607
+ architectureRecommendation.projectDomain = {
608
+ key: selectedProjectScopeKey,
609
+ label: selectedProjectScopeLabel,
610
+ };
611
+ architectureRecommendation.userVeto = {
612
+ applied: false,
613
+ selectedStackFileName: architectureRecommendation.recommendedStackFileName,
614
+ selectedBlueprintFileName: architectureRecommendation.recommendedBlueprintFileName,
615
+ source: projectDetection.hasExistingProjectFiles ? 'silent-existing-bootstrap' : 'silent-fresh-bootstrap',
616
+ };
617
+
618
+ selectedManualStackFileName = architectureRecommendation.recommendedStackFileName;
619
+ selectedManualBlueprintFileName = architectureRecommendation.recommendedBlueprintFileName;
620
+
621
+ if (!projectDetection.hasExistingProjectFiles) {
622
+ detectionTransparency.quickConfirmation.response = 'fresh-project-streamlined';
623
+ detectionTransparency.decision.mode = 'fresh-project-streamlined';
624
+ }
625
+ }
513
626
 
514
627
  const blueprintDisplayChoices = blueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName));
515
628
 
@@ -550,15 +663,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
550
663
  if (architectureRecommendation) {
551
664
  architectureRecommendation.appliedStackFileName = selectedResolvedStackFileName;
552
665
  architectureRecommendation.appliedBlueprintFileName = selectedResolvedBlueprintFileName;
553
-
554
- if (!architectureRecommendation.userVeto) {
555
- architectureRecommendation.userVeto = {
556
- applied: false,
557
- selectedStackFileName: selectedResolvedStackFileName,
558
- selectedBlueprintFileName: selectedResolvedBlueprintFileName,
559
- source: 'recommendation',
560
- };
561
- }
562
666
  }
563
667
 
564
668
  const derivedAdditionalBlueprintFileNames = deriveAdditionalBlueprintFileNamesFromStacks(
@@ -580,23 +684,25 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
580
684
  detectionTransparency.decision.selectedAdditionalBlueprintFileNames = selectedAdditionalBlueprintFileNames;
581
685
  detectionTransparency.decision.usedDetectedSetup = detectedSetupWasApplied;
582
686
 
583
- const includeCiGuardrails = typeof initOptions.ci === 'boolean'
584
- ? initOptions.ci
585
- : typeof selectedPreset?.ci === 'boolean'
586
- ? selectedPreset.ci
587
- : selectedProfilePack?.lockCi
588
- ? selectedProfilePack.defaultCi
589
- : typeof selectedProfilePack?.defaultCi === 'boolean'
590
- ? selectedProfilePack.defaultCi
591
- : selectedProfile.lockCi
592
- ? selectedProfile.defaultCi
593
- : await askYesNo('Enable CI/CD quality checks (guardrails) and the LLM Judge policy?', userInterface, selectedProfile.defaultCi);
687
+ const includeCiGuardrails = typeof discoveryAnswers?.includeCiGuardrails === 'boolean'
688
+ ? discoveryAnswers.includeCiGuardrails
689
+ : ciGuardrailsSelection.shouldAsk
690
+ ? (!isInteractiveSession
691
+ ? ciGuardrailsSelection.value
692
+ : await askYesNo(
693
+ 'Enable CI/CD quality checks (guardrails) and the LLM Judge policy?',
694
+ userInterface,
695
+ ciGuardrailsSelection.value
696
+ ))
697
+ : ciGuardrailsSelection.value;
594
698
 
595
699
  detectionTransparency.activeRulesSummary.ciGuardrailsEnabled = includeCiGuardrails;
596
700
 
597
701
  detectionTransparency.decision.selectedProjectScopeKey = selectedProjectScopeKey;
598
702
  detectionTransparency.decision.selectedProjectScopeLabel = selectedProjectScopeLabel;
599
703
 
704
+ await createBackup(resolvedTargetDirectoryPath);
705
+
600
706
  await copyGovernanceAssetsToTarget(resolvedTargetDirectoryPath, {
601
707
  includeMcpTemplate: shouldIncludeMcpTemplate,
602
708
  });
@@ -629,83 +735,50 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
629
735
  // --- Project Documentation Scaffolding ---
630
736
  let scaffoldingResult = null;
631
737
  const supplementalMaterializedDocFileNames = [];
632
- const isFreshProjectTarget = wasDirectoryEffectivelyEmpty && !hadExistingProjectDocsBeforeInit;
633
- const shouldOfferScaffolding = initOptions.scaffoldDocs === true
634
- || Boolean(initOptions.projectConfig)
635
- || (initOptions.scaffoldDocs !== false && isFreshProjectTarget);
636
-
637
- if (shouldOfferScaffolding) {
638
- if (initOptions.scaffoldDocs === true && !initOptions.projectConfig && !isInteractiveSession) {
639
- throw new Error('Non-interactive scaffolding requires --project-config when --scaffold-docs is enabled.');
738
+ if (discoveryAnswers) {
739
+ const normalizedConfigDocsLanguage = normalizeDocsLanguage(discoveryAnswers.docsLang || '');
740
+ if (discoveryAnswers.docsLang && !normalizedConfigDocsLanguage) {
741
+ throw new Error(`Unsupported docs language in project config: ${discoveryAnswers.docsLang}. Supported values: en, id`);
640
742
  }
641
743
 
642
- const userWantsScaffolding = initOptions.scaffoldDocs === true
643
- || initOptions.projectConfig
644
- || (!isInteractiveSession
645
- ? false
646
- : await askYesNo(
647
- 'This is a fresh project. Want me to scaffold project documentation (architecture, database, API contract, flow)?',
648
- userInterface,
649
- true
650
- ));
744
+ // Keep generated docs in English by default to align with the writing scope.
745
+ // A different output language is only used when explicitly requested via --docs-lang.
746
+ const selectedDocsLanguage = initOptions.docsLang;
651
747
 
652
- if (userWantsScaffolding) {
653
- let discoveryAnswers;
748
+ if (!initOptions.docsLangProvided && normalizedConfigDocsLanguage && normalizedConfigDocsLanguage !== 'en') {
749
+ console.log('[INFO] Project config docsLang is set, but output defaults to English. Use --docs-lang to override.');
750
+ }
654
751
 
655
- if (initOptions.projectConfig) {
656
- discoveryAnswers = await loadProjectConfig(initOptions.projectConfig);
657
- console.log(`\nLoaded project configuration from: ${initOptions.projectConfig}`);
658
- } else {
659
- discoveryAnswers = await runProjectDiscovery(userInterface, {
660
- defaultProjectName: path.basename(resolvedTargetDirectoryPath),
661
- defaultProjectDescription: architectureProjectDescription,
662
- });
752
+ scaffoldingResult = await generateProjectDocumentation(
753
+ resolvedTargetDirectoryPath,
754
+ discoveryAnswers,
755
+ {
756
+ stackFileName: selectedResolvedStackFileName,
757
+ additionalStackFileNames: selectedAdditionalStackFileNames,
758
+ blueprintFileName: selectedResolvedBlueprintFileName,
759
+ additionalBlueprintFileNames: selectedAdditionalBlueprintFileNames,
760
+ runtimeEnvironmentKey: selectedRuntimeEnvironmentKey,
761
+ runtimeEnvironmentLabel: resolveRuntimeEnvironmentLabelFromKey(selectedRuntimeEnvironmentKey),
762
+ architectureRecommendation,
763
+ },
764
+ {
765
+ docsLanguage: selectedDocsLanguage,
663
766
  }
767
+ );
664
768
 
665
- const normalizedConfigDocsLanguage = normalizeDocsLanguage(discoveryAnswers.docsLang || '');
666
- if (discoveryAnswers.docsLang && !normalizedConfigDocsLanguage) {
667
- throw new Error(`Unsupported docs language in project config: ${discoveryAnswers.docsLang}. Supported values: en, id`);
769
+ if (scaffoldingResult.bootstrapMode === 'ai-synthesis') {
770
+ console.log(`\nAI synthesis bootstrap prompts generated in .agent-context/prompts/:`);
771
+ for (const generatedPromptFileName of scaffoldingResult.generatedPromptFileNames || []) {
772
+ console.log(` - .agent-context/prompts/${generatedPromptFileName}`);
668
773
  }
669
-
670
- // Keep generated docs in English by default to align with the writing scope.
671
- // A different output language is only used when explicitly requested via --docs-lang.
672
- const selectedDocsLanguage = initOptions.docsLang;
673
-
674
- if (!initOptions.docsLangProvided && normalizedConfigDocsLanguage && normalizedConfigDocsLanguage !== 'en') {
675
- console.log('[INFO] Project config docsLang is set, but output defaults to English. Use --docs-lang to override.');
774
+ for (const materializedFileName of scaffoldingResult.materializedFileNames || []) {
775
+ console.log(` - docs/${materializedFileName}`);
676
776
  }
677
-
678
- scaffoldingResult = await generateProjectDocumentation(
679
- resolvedTargetDirectoryPath,
680
- discoveryAnswers,
681
- {
682
- stackFileName: selectedResolvedStackFileName,
683
- additionalStackFileNames: selectedAdditionalStackFileNames,
684
- blueprintFileName: selectedResolvedBlueprintFileName,
685
- additionalBlueprintFileNames: selectedAdditionalBlueprintFileNames,
686
- runtimeEnvironmentKey: selectedRuntimeEnvironmentKey,
687
- runtimeEnvironmentLabel: resolveRuntimeEnvironmentLabelFromKey(selectedRuntimeEnvironmentKey),
688
- architectureRecommendation,
689
- },
690
- {
691
- docsLanguage: selectedDocsLanguage,
692
- }
693
- );
694
-
695
- if (scaffoldingResult.bootstrapMode === 'ai-synthesis') {
696
- console.log(`\nAI synthesis bootstrap prompts generated in .agent-context/prompts/:`);
697
- for (const generatedPromptFileName of scaffoldingResult.generatedPromptFileNames || []) {
698
- console.log(` - .agent-context/prompts/${generatedPromptFileName}`);
699
- }
700
- for (const materializedFileName of scaffoldingResult.materializedFileNames || []) {
701
- console.log(` - docs/${materializedFileName}`);
702
- }
703
- console.log('Project docs will be authored dynamically by your IDE assistant from these prompts.');
704
- } else {
705
- console.log(`\nProject documentation generated in docs/:`);
706
- for (const generatedFileName of scaffoldingResult.generatedFileNames) {
707
- console.log(` - docs/${generatedFileName}`);
708
- }
777
+ console.log('Project docs will be authored dynamically by your IDE assistant from these prompts.');
778
+ } else {
779
+ console.log(`\nProject documentation generated in docs/:`);
780
+ for (const generatedFileName of scaffoldingResult.generatedFileNames) {
781
+ console.log(` - docs/${generatedFileName}`);
709
782
  }
710
783
  }
711
784
  }
@@ -795,10 +868,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
795
868
  uiScopeSignals: existingProjectUiScopeSignals,
796
869
  });
797
870
 
798
- if (architectPreferenceUpdated && architectPreferenceState) {
799
- await writeArchitectPreferenceState(architectPreferenceState);
800
- }
801
-
802
871
  console.log('\nInitialization complete.');
803
872
  console.log(`- Target directory: ${resolvedTargetDirectoryPath}`);
804
873
  console.log(`- Profile: ${selectedProfile.displayName}`);
@@ -808,18 +877,8 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
808
877
  if (selectedProfilePack) {
809
878
  console.log(`- Team profile pack: ${selectedProfilePack.displayName}`);
810
879
  }
811
- if (architectureRecommendation) {
812
- console.log(
813
- `- Architect recommendation: ${toTitleCase(architectureRecommendation.recommendedStackFileName)} + ${toTitleCase(architectureRecommendation.recommendedBlueprintFileName)} (${architectureRecommendation.confidenceLabel})`
814
- );
815
- if (!projectDetection.hasExistingProjectFiles) {
816
- console.log(`- Project domain: ${selectedProjectScopeLabel}`);
817
- }
818
- if (architectureRecommendation.userVeto?.applied) {
819
- console.log(
820
- `- User veto path: applied (${toTitleCase(architectureRecommendation.userVeto.selectedStackFileName)} + ${toTitleCase(architectureRecommendation.userVeto.selectedBlueprintFileName)})`
821
- );
822
- }
880
+ if (!projectDetection.hasExistingProjectFiles) {
881
+ console.log(`- Project domain: ${selectedProjectScopeLabel}`);
823
882
  }
824
883
  console.log(`- Stack: ${toTitleCase(selectedResolvedStackFileName)}`);
825
884
  if (selectedAdditionalStackFileNames.length > 0) {
@@ -396,9 +396,15 @@ export async function buildCompiledRulesContent({
396
396
  ...projectDocsEntries.map((docFileName, docIndex) => `${docIndex + 1}. docs/${docFileName}`),
397
397
  '',
398
398
  'Universal SOP hard block policy:',
399
+ '- Stop implementation if docs/project-brief.md is missing.',
399
400
  '- Stop implementation if docs/architecture-decision-record.md (alias: docs/Architecture-Decision-Record.md) is missing.',
401
+ '- Stop implementation if docs/flow-overview.md is missing.',
402
+ '- If the product uses persistent data, docs/database-schema.md must exist before coding continues.',
403
+ '- If the product exposes API or web application flows, docs/api-contract.md must exist before coding continues.',
400
404
  '- For UI scope, stop implementation if docs/DESIGN.md or docs/design-intent.json is missing.',
401
405
  '- Materialize missing docs first, then continue coding.',
406
+ '- Bootstrap missing docs from real repo evidence and the latest user request. Do not write generic placeholder templates.',
407
+ '- Separate confirmed facts from assumptions and end each major explanation with the next validation action.',
402
408
  '',
403
409
  'These docs were generated during project initialization and reflect the architecture,',
404
410
  'database design, API contracts, and application flows chosen for this project.',
@@ -428,10 +434,15 @@ export async function buildCompiledRulesContent({
428
434
  '',
429
435
  'Bootstrap policy:',
430
436
  '- Hard block: do not write application code until docs/project-brief.md and docs/architecture-decision-record.md exist.',
437
+ '- docs/flow-overview.md must also exist before coding continues.',
438
+ '- Add docs/database-schema.md when persistent data is involved.',
439
+ '- Add docs/api-contract.md when API or web application flows are involved.',
431
440
  '- If docs/project-brief.md is missing, execute bootstrap-project-context prompt immediately.',
432
441
  hasBootstrapDesignPrompt
433
442
  ? '- For UI scope: if docs/DESIGN.md or docs/design-intent.json is missing, execute bootstrap-design prompt before implementing UI surfaces.'
434
443
  : '- For UI scope: add a design bootstrap prompt before implementing UI surfaces.',
444
+ '- Bootstrap docs from repo evidence and the latest user request. Do not use generic placeholder templates.',
445
+ '- Separate confirmed facts from assumptions, include an Assumptions to Validate section when context is incomplete, and end with the next validation action.',
435
446
  '- Save generated docs under docs/ and keep them updated when feature scope changes.',
436
447
  'Latest user prompt defines current feature scope and product direction.',
437
448
  'Treat synthesized docs as living references, then continue implementation with those docs as source of truth.',
@@ -100,6 +100,24 @@ const PROJECT_MARKER_FILE_NAMES = new Set([
100
100
  'tsconfig.json',
101
101
  ...DIRECT_UI_MARKER_NAMES,
102
102
  ]);
103
+ const INTERNAL_GOVERNANCE_SURFACE_NAMES = new Set([
104
+ '.agent-context',
105
+ '.agent-instructions.md',
106
+ '.agent-override.md',
107
+ '.agentic-backup',
108
+ '.agents',
109
+ '.clauderc',
110
+ '.cursorrules',
111
+ '.cursor',
112
+ '.gemini',
113
+ '.github',
114
+ '.instructions.md',
115
+ '.vscode',
116
+ '.windsurfrules',
117
+ '.zed',
118
+ 'AGENTS.md',
119
+ 'mcp.json',
120
+ ]);
103
121
 
104
122
  function looksLikeWorkspaceSearchCandidate(directoryName) {
105
123
  const normalizedDirectoryName = String(directoryName || '').trim().toLowerCase();
@@ -148,6 +166,10 @@ export async function collectProjectMarkers(targetDirectoryPath) {
148
166
  continue;
149
167
  }
150
168
 
169
+ if (INTERNAL_GOVERNANCE_SURFACE_NAMES.has(directoryEntry.name)) {
170
+ continue;
171
+ }
172
+
151
173
  markerNames.add(directoryEntry.name);
152
174
  }
153
175
 
@@ -6,7 +6,7 @@
6
6
  import fs from 'node:fs/promises';
7
7
  import path from 'node:path';
8
8
 
9
- import { ensureDirectory, askChoice, toTitleCase, pathExists } from './utils.mjs';
9
+ import { ensureDirectory, askChoice, askYesNo, toTitleCase, pathExists } from './utils.mjs';
10
10
 
11
11
  const SUPPORTED_DOC_LANGUAGES = new Set(['en', 'id']);
12
12
  const PROJECT_DOC_FILE_NAMES = [
@@ -137,14 +137,18 @@ export function normalizeDocsLanguage(rawDocsLanguage = 'en') {
137
137
  * Returns a structured object with all user responses.
138
138
  */
139
139
  export async function runProjectDiscovery(userInterface, options = {}) {
140
- console.log('\n--- Project Discovery ---');
141
- console.log('I will ask a few questions to generate project-specific documentation.');
140
+ console.log('\n--- Project Setup ---');
141
+ console.log('I will ask one focused set of questions to bootstrap project context and documentation.');
142
142
  console.log('This helps AI agents understand your project before writing code.\n');
143
143
  console.log('You can answer in your own language.');
144
144
  console.log('CLI prompts stay in English, but non-English answers are fully supported.\n');
145
145
 
146
146
  const defaultProjectName = (options.defaultProjectName || '').trim();
147
147
  const defaultProjectDescription = String(options.defaultProjectDescription || '').trim();
148
+ const defaultIncludeCiGuardrails = typeof options.defaultIncludeCiGuardrails === 'boolean'
149
+ ? options.defaultIncludeCiGuardrails
150
+ : true;
151
+ const shouldAskForCiGuardrails = options.askForCiGuardrails !== false;
148
152
  let projectName = '';
149
153
 
150
154
  const projectNamePrompt = defaultProjectName
@@ -171,6 +175,14 @@ export async function runProjectDiscovery(userInterface, options = {}) {
171
175
  projectDescription = defaultProjectDescription || `A ${projectName} project.`;
172
176
  }
173
177
 
178
+ const includeCiGuardrails = shouldAskForCiGuardrails
179
+ ? await askYesNo(
180
+ 'Enable CI/CD quality checks (guardrails) and the LLM Judge policy?',
181
+ userInterface,
182
+ defaultIncludeCiGuardrails
183
+ )
184
+ : defaultIncludeCiGuardrails;
185
+
174
186
  const domainSelection = await askChoice(
175
187
  'Primary domain:',
176
188
  DOMAIN_CHOICES,
@@ -210,24 +222,18 @@ export async function runProjectDiscovery(userInterface, options = {}) {
210
222
  userInterface
211
223
  );
212
224
 
213
- let features = await askFeatureList(userInterface);
214
-
215
- if (features.length === 0) {
216
- features.push('Core functionality (define during development)');
217
- }
218
-
219
- const additionalContext = (await userInterface.question('\nAdditional context (optional, press Enter to skip): ')).trim()
220
- || 'No additional context provided.';
225
+ const features = await askFeatureList(userInterface);
221
226
 
222
227
  return {
223
228
  projectName,
224
229
  projectDescription,
230
+ includeCiGuardrails,
225
231
  primaryDomain,
226
232
  databaseChoice,
227
233
  authStrategy,
228
234
  dockerStrategy,
229
235
  features,
230
- additionalContext,
236
+ additionalContext: 'No additional context provided.',
231
237
  };
232
238
  }
233
239
 
@@ -508,7 +514,14 @@ function buildDesignIntentContractObject({
508
514
  primaryDomain,
509
515
  features,
510
516
  });
511
- const designSignals = architectureRecommendation?.designGuidance?.normalizedSignals || null;
517
+ const normalizedPrimaryDomain = String(primaryDomain || '').trim().toLowerCase();
518
+ const resolvedSpacingPattern = inferredKeywords.densityMode === 'dense'
519
+ ? 'compact-grid'
520
+ : normalizedPrimaryDomain.includes('mobile')
521
+ ? 'mobile-first-single-axis'
522
+ : inferredKeywords.densityMode === 'focused'
523
+ ? 'high-contrast-rhythm'
524
+ : 'balanced-grid';
512
525
 
513
526
  return {
514
527
  mode: 'dynamic',
@@ -531,14 +544,14 @@ function buildDesignIntentContractObject({
531
544
  mathSystems: {
532
545
  typographyScaleRatio: inferredKeywords.typographyScaleRatio,
533
546
  baseGridUnit: inferredKeywords.baseGridUnit,
534
- spacingPattern: designSignals?.spacingPattern || 'balanced-grid',
547
+ spacingPattern: resolvedSpacingPattern,
535
548
  densityMode: inferredKeywords.densityMode,
536
549
  },
537
550
  colorTruth: {
538
551
  format: 'OKLCH',
539
552
  allowHexDerivatives: true,
540
553
  requirePerceptualLightnessCurve: true,
541
- paletteRoles: designSignals?.paletteRoles || ['base', 'surface', 'accent'],
554
+ paletteRoles: ['base', 'surface', 'accent'],
542
555
  intent: inferredKeywords.colorIntent,
543
556
  },
544
557
  crossViewportAdaptation: {
@@ -603,7 +616,6 @@ function buildDesignIntentContractObject({
603
616
  '.agent-context/rules/microservices.md',
604
617
  ],
605
618
  },
606
- architectSignals: designSignals,
607
619
  ...supplementalFields,
608
620
  };
609
621
  }
@@ -766,7 +778,7 @@ function buildProjectContextBootstrapPrompt({
766
778
  }) {
767
779
  const featuresList = Array.isArray(discoveryAnswers.features) && discoveryAnswers.features.length > 0
768
780
  ? discoveryAnswers.features.map((feature, featureIndex) => `${featureIndex + 1}. ${feature}`).join('\n')
769
- : '1. Core functionality (define during implementation)';
781
+ : 'Derive the first concrete feature set from the project name, description, and domain. Do not invent arbitrary modules just to fill space.';
770
782
 
771
783
  const expectedDocsList = expectedDocFileNames
772
784
  .map((fileName, fileIndex) => `${fileIndex + 1}. docs/${fileName}`)
@@ -802,6 +814,11 @@ function buildProjectContextBootstrapPrompt({
802
814
  '3. Keep stack, database, and auth aligned with the project constraints below unless user explicitly requests migration.',
803
815
  '4. Output must be implementation-ready for engineers, not generic textbook explanation.',
804
816
  '5. For any research-backed claim, include citation metadata (source + fetchedAt timestamp) from the Architect Engine Snapshot.',
817
+ '6. Write for native English speakers at an 8th-grade reading level. Use clear, direct, plain language.',
818
+ '7. Avoid emoji, AI cliches, buzzwords, academic phrasing, padding, and generic filler.',
819
+ '8. Separate confirmed facts from assumptions explicitly. When context is incomplete, add an `Assumptions to Validate` section and a `Next Validation Action` line.',
820
+ '9. If user inputs conflict with repo evidence, call out the conflict and choose the safer interpretation instead of silently forcing a generic answer.',
821
+ '10. Do not invent modules or architecture layers only to make the docs look complete.',
805
822
  '',
806
823
  '## Project Inputs',
807
824
  `- Project name: ${discoveryAnswers.projectName}`,
@@ -829,8 +846,10 @@ function buildProjectContextBootstrapPrompt({
829
846
  '',
830
847
  '## Required Execution',
831
848
  '1. Create all required docs files listed above with complete Markdown content.',
832
- '2. Keep content original, specific to this project, and actionable for implementation.',
833
- '3. After writing docs, continue coding tasks using these docs as living project context.',
849
+ '2. Make the docs adaptive to the real repo and prompt context. These are living references, not frozen templates.',
850
+ '3. In docs/project-brief.md and docs/architecture-decision-record.md, include explicit sections for confirmed facts, assumptions to validate, and next validation actions whenever context is incomplete.',
851
+ '4. Keep content original, specific to this project, and actionable for implementation.',
852
+ '5. After writing docs, continue coding tasks using these docs as living project context.',
834
853
  '',
835
854
  ].join('\n');
836
855
  }
@@ -841,8 +860,6 @@ function buildDesignBootstrapPrompt({
841
860
  docsLanguage,
842
861
  architectureRecommendation,
843
862
  }) {
844
- const designSignals = architectureRecommendation?.designGuidance?.normalizedSignals || null;
845
- const designSignalsJson = JSON.stringify(designSignals, null, 2);
846
863
  const designIntentSeed = buildDesignIntentSeed({
847
864
  discoveryAnswers,
848
865
  initContext,
@@ -918,12 +935,6 @@ function buildDesignBootstrapPrompt({
918
935
  `- Stack: ${toTitleCase(initContext.stackFileName)}`,
919
936
  `- Blueprint: ${toTitleCase(initContext.blueprintFileName)}`,
920
937
  '',
921
- '## Architect Design Signals (raw control vector)',
922
- 'Use this only as baseline fuel, then expand into full design direction with original reasoning:',
923
- '```json',
924
- designSignalsJson || 'null',
925
- '```',
926
- '',
927
938
  '## Seed Machine Contract',
928
939
  'Refine this seed instead of discarding it. Keep the final JSON aligned with the markdown design system.',
929
940
  '```json',
@@ -1133,6 +1144,7 @@ export async function loadProjectConfig(configFilePath) {
1133
1144
  return {
1134
1145
  projectName: configEntries.projectName || configEntries.name || '',
1135
1146
  projectDescription: configEntries.projectDescription || configEntries.description || '',
1147
+ includeCiGuardrails: parseBooleanLikeValue(configEntries.includeCiGuardrails) ?? parseBooleanLikeValue(configEntries.ci) ?? true,
1136
1148
  primaryDomain: configEntries.primaryDomain || configEntries.domain || 'API service',
1137
1149
  databaseChoice: configEntries.databaseChoice || configEntries.database || 'None (stateless service)',
1138
1150
  authStrategy: configEntries.authStrategy || configEntries.auth || 'None (public service)',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "3.0.12",
3
+ "version": "3.0.13",
4
4
  "type": "module",
5
5
  "description": "Force your AI Agent to code like a Staff Engineer, not a Junior.",
6
6
  "bin": {