@ryuenn3123/agentic-senior-core 3.0.11 → 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.
- package/.agent-context/prompts/bootstrap-design.md +7 -1
- package/.agent-context/rules/architecture.md +7 -0
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.cursorrules +1 -1
- package/.windsurfrules +1 -1
- package/lib/cli/commands/init.mjs +215 -154
- package/lib/cli/commands/upgrade.mjs +5 -0
- package/lib/cli/compiler.mjs +20 -0
- package/lib/cli/constants.mjs +1 -0
- package/lib/cli/detector.mjs +444 -90
- package/lib/cli/project-scaffolder.mjs +161 -35
- package/package.json +1 -1
- package/scripts/frontend-usability-audit.mjs +2 -0
- package/scripts/mcp-server.mjs +200 -118
- package/scripts/ui-design-judge.mjs +3 -2
- package/scripts/validate.mjs +4 -0
|
@@ -23,6 +23,8 @@ The agent must:
|
|
|
23
23
|
8. Treat any example structure or stylistic inspiration as non-normative. Use it only to judge depth and clarity, never to copy a visual language directly.
|
|
24
24
|
9. All references to docs or rules must be clickable markdown links.
|
|
25
25
|
10. Responsive work must adapt layout, navigation, density, and task order across viewports. Shrinking desktop layouts is not enough.
|
|
26
|
+
11. Motion is allowed when it improves feedback, continuity, or spatial understanding. Do not flatten everything into static screens, but do reject decorative motion with no product value.
|
|
27
|
+
12. Define how core components morph across interaction states and viewports. Component quality is not only visual styling; it includes behavior under hover, focus, active, loading, error, and constrained layouts.
|
|
26
28
|
|
|
27
29
|
Required `docs/DESIGN.md` sections:
|
|
28
30
|
1. Design Intent and Product Personality
|
|
@@ -33,7 +35,7 @@ Required `docs/DESIGN.md` sections:
|
|
|
33
35
|
6. Spacing, Layout Rhythm, and Density Strategy
|
|
34
36
|
7. Responsive Strategy and Cross-Viewport Adaptation Matrix
|
|
35
37
|
8. Interaction, Motion, and Feedback Rules
|
|
36
|
-
9. Component Language and Shared Patterns
|
|
38
|
+
9. Component Language, Morphology, and Shared Patterns
|
|
37
39
|
10. Accessibility Non-Negotiables
|
|
38
40
|
11. Anti-Patterns to Avoid
|
|
39
41
|
12. Implementation Notes for Future UI Tasks
|
|
@@ -49,6 +51,8 @@ Required `docs/design-intent.json` fields:
|
|
|
49
51
|
- `mathSystems`
|
|
50
52
|
- `colorTruth`
|
|
51
53
|
- `crossViewportAdaptation`
|
|
54
|
+
- `motionSystem`
|
|
55
|
+
- `componentMorphology`
|
|
52
56
|
- `experiencePrinciples`
|
|
53
57
|
- `forbiddenPatterns`
|
|
54
58
|
- `validationHints`
|
|
@@ -59,7 +63,9 @@ Output:
|
|
|
59
63
|
- Create or update both `docs/DESIGN.md` and `docs/design-intent.json`.
|
|
60
64
|
- Keep both files synchronized: the markdown explains the why, the JSON captures the contract in machine-readable form.
|
|
61
65
|
- `docs/design-intent.json` must include deterministic fields for `colorTruth.format`, `colorTruth.allowHexDerivatives`, and `crossViewportAdaptation.mutationRules.mobile/tablet/desktop`.
|
|
66
|
+
- `docs/design-intent.json` must also include `motionSystem` and `componentMorphology` so future UI work preserves state behavior and purposeful motion without collapsing into generic static output.
|
|
62
67
|
- Color intent must be defined in a perceptual or relational color model first. Hex values may appear only as implementation derivatives.
|
|
63
68
|
- The contract must encode viewport mutation rules, not just breakpoint names.
|
|
69
|
+
- Motion guidance must preserve creativity: allow meaningful animation, define reduced-motion behavior, and keep choreography fast, intentional, and performant.
|
|
64
70
|
- Use practical, modern, accessible language grounded in the project, not generic SaaS defaults or copycat brand systems.
|
|
65
71
|
- Wait for user approval before generating Figma or code assets.
|
|
@@ -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
|
|
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.
|
|
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.
|
|
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);
|
|
@@ -204,6 +279,7 @@ function buildInitExistingProjectDesignIntentSeed({
|
|
|
204
279
|
repoEvidence: {
|
|
205
280
|
uiSignalReasons: uiScopeSignals.signalReasons,
|
|
206
281
|
frontendMetrics: uiScopeSignals.frontendEvidenceMetrics || null,
|
|
282
|
+
workspaceUiEntries: uiScopeSignals.workspaceUiEntries || [],
|
|
207
283
|
},
|
|
208
284
|
},
|
|
209
285
|
});
|
|
@@ -241,8 +317,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
241
317
|
const wasDirectoryEffectivelyEmpty = await isDirectoryEffectivelyEmpty(resolvedTargetDirectoryPath);
|
|
242
318
|
const hadExistingProjectDocsBeforeInit = await hasExistingProjectDocs(resolvedTargetDirectoryPath);
|
|
243
319
|
|
|
244
|
-
await createBackup(resolvedTargetDirectoryPath);
|
|
245
|
-
|
|
246
320
|
const userInterface = createInterface({ input: stdin, output: stdout });
|
|
247
321
|
|
|
248
322
|
try {
|
|
@@ -441,20 +515,21 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
441
515
|
let selectedAdditionalBlueprintFileNames = [];
|
|
442
516
|
let detectedSetupWasApplied = false;
|
|
443
517
|
let selectedProjectScopeKey = 'both';
|
|
444
|
-
let selectedProjectScopeLabel =
|
|
445
|
-
(scopeChoice) => scopeChoice.key === 'both'
|
|
446
|
-
)?.label || 'Both (frontend + backend)';
|
|
447
|
-
|
|
518
|
+
let selectedProjectScopeLabel = resolveProjectScopeLabelFromKey('both');
|
|
448
519
|
let architectureRecommendation = null;
|
|
449
|
-
let architectureProjectDescription = '';
|
|
450
|
-
let
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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));
|
|
458
533
|
|
|
459
534
|
const detectedSetupDecision = await resolveDetectedSetupDecision({
|
|
460
535
|
shouldAutoApplyDetectedStack,
|
|
@@ -478,37 +553,76 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
478
553
|
selectedAdditionalStackFileNames = detectedSetupDecision.selectedAdditionalStackFileNames;
|
|
479
554
|
detectedBlueprintFileName = detectedSetupDecision.detectedBlueprintFileName;
|
|
480
555
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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,
|
|
486
602
|
researchMode: initOptions.architectResearchMode,
|
|
487
603
|
enableRealtimeResearch: initOptions.enableRealtimeResearch,
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
stackFileNames,
|
|
491
|
-
blueprintFileNames,
|
|
492
|
-
userInterface,
|
|
493
|
-
isInteractiveSession,
|
|
494
|
-
initialSelectedProjectScopeKey: selectedProjectScopeKey,
|
|
495
|
-
initialSelectedProjectScopeLabel: selectedProjectScopeLabel,
|
|
496
|
-
initialSelectedManualStackFileName: selectedManualStackFileName,
|
|
497
|
-
initialSelectedManualBlueprintFileName: selectedManualBlueprintFileName,
|
|
498
|
-
architectPreferenceState,
|
|
499
|
-
askStackSelection,
|
|
500
|
-
askBlueprintSelection,
|
|
501
|
-
detectionTransparency,
|
|
502
|
-
});
|
|
604
|
+
realtimeSignalFilePath: initOptions.architectRealtimeSignalFile,
|
|
605
|
+
});
|
|
503
606
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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
|
+
}
|
|
512
626
|
|
|
513
627
|
const blueprintDisplayChoices = blueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName));
|
|
514
628
|
|
|
@@ -549,15 +663,6 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
549
663
|
if (architectureRecommendation) {
|
|
550
664
|
architectureRecommendation.appliedStackFileName = selectedResolvedStackFileName;
|
|
551
665
|
architectureRecommendation.appliedBlueprintFileName = selectedResolvedBlueprintFileName;
|
|
552
|
-
|
|
553
|
-
if (!architectureRecommendation.userVeto) {
|
|
554
|
-
architectureRecommendation.userVeto = {
|
|
555
|
-
applied: false,
|
|
556
|
-
selectedStackFileName: selectedResolvedStackFileName,
|
|
557
|
-
selectedBlueprintFileName: selectedResolvedBlueprintFileName,
|
|
558
|
-
source: 'recommendation',
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
666
|
}
|
|
562
667
|
|
|
563
668
|
const derivedAdditionalBlueprintFileNames = deriveAdditionalBlueprintFileNamesFromStacks(
|
|
@@ -579,23 +684,25 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
579
684
|
detectionTransparency.decision.selectedAdditionalBlueprintFileNames = selectedAdditionalBlueprintFileNames;
|
|
580
685
|
detectionTransparency.decision.usedDetectedSetup = detectedSetupWasApplied;
|
|
581
686
|
|
|
582
|
-
const includeCiGuardrails = typeof
|
|
583
|
-
?
|
|
584
|
-
:
|
|
585
|
-
?
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
:
|
|
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;
|
|
593
698
|
|
|
594
699
|
detectionTransparency.activeRulesSummary.ciGuardrailsEnabled = includeCiGuardrails;
|
|
595
700
|
|
|
596
701
|
detectionTransparency.decision.selectedProjectScopeKey = selectedProjectScopeKey;
|
|
597
702
|
detectionTransparency.decision.selectedProjectScopeLabel = selectedProjectScopeLabel;
|
|
598
703
|
|
|
704
|
+
await createBackup(resolvedTargetDirectoryPath);
|
|
705
|
+
|
|
599
706
|
await copyGovernanceAssetsToTarget(resolvedTargetDirectoryPath, {
|
|
600
707
|
includeMcpTemplate: shouldIncludeMcpTemplate,
|
|
601
708
|
});
|
|
@@ -628,83 +735,50 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
628
735
|
// --- Project Documentation Scaffolding ---
|
|
629
736
|
let scaffoldingResult = null;
|
|
630
737
|
const supplementalMaterializedDocFileNames = [];
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
if (shouldOfferScaffolding) {
|
|
637
|
-
if (initOptions.scaffoldDocs === true && !initOptions.projectConfig && !isInteractiveSession) {
|
|
638
|
-
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`);
|
|
639
742
|
}
|
|
640
743
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
? false
|
|
645
|
-
: await askYesNo(
|
|
646
|
-
'This is a fresh project. Want me to scaffold project documentation (architecture, database, API contract, flow)?',
|
|
647
|
-
userInterface,
|
|
648
|
-
true
|
|
649
|
-
));
|
|
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;
|
|
650
747
|
|
|
651
|
-
if (
|
|
652
|
-
|
|
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
|
+
}
|
|
653
751
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
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,
|
|
662
766
|
}
|
|
767
|
+
);
|
|
663
768
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
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}`);
|
|
667
773
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
// A different output language is only used when explicitly requested via --docs-lang.
|
|
671
|
-
const selectedDocsLanguage = initOptions.docsLang;
|
|
672
|
-
|
|
673
|
-
if (!initOptions.docsLangProvided && normalizedConfigDocsLanguage && normalizedConfigDocsLanguage !== 'en') {
|
|
674
|
-
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}`);
|
|
675
776
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
{
|
|
681
|
-
stackFileName: selectedResolvedStackFileName,
|
|
682
|
-
additionalStackFileNames: selectedAdditionalStackFileNames,
|
|
683
|
-
blueprintFileName: selectedResolvedBlueprintFileName,
|
|
684
|
-
additionalBlueprintFileNames: selectedAdditionalBlueprintFileNames,
|
|
685
|
-
runtimeEnvironmentKey: selectedRuntimeEnvironmentKey,
|
|
686
|
-
runtimeEnvironmentLabel: resolveRuntimeEnvironmentLabelFromKey(selectedRuntimeEnvironmentKey),
|
|
687
|
-
architectureRecommendation,
|
|
688
|
-
},
|
|
689
|
-
{
|
|
690
|
-
docsLanguage: selectedDocsLanguage,
|
|
691
|
-
}
|
|
692
|
-
);
|
|
693
|
-
|
|
694
|
-
if (scaffoldingResult.bootstrapMode === 'ai-synthesis') {
|
|
695
|
-
console.log(`\nAI synthesis bootstrap prompts generated in .agent-context/prompts/:`);
|
|
696
|
-
for (const generatedPromptFileName of scaffoldingResult.generatedPromptFileNames || []) {
|
|
697
|
-
console.log(` - .agent-context/prompts/${generatedPromptFileName}`);
|
|
698
|
-
}
|
|
699
|
-
for (const materializedFileName of scaffoldingResult.materializedFileNames || []) {
|
|
700
|
-
console.log(` - docs/${materializedFileName}`);
|
|
701
|
-
}
|
|
702
|
-
console.log('Project docs will be authored dynamically by your IDE assistant from these prompts.');
|
|
703
|
-
} else {
|
|
704
|
-
console.log(`\nProject documentation generated in docs/:`);
|
|
705
|
-
for (const generatedFileName of scaffoldingResult.generatedFileNames) {
|
|
706
|
-
console.log(` - docs/${generatedFileName}`);
|
|
707
|
-
}
|
|
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}`);
|
|
708
782
|
}
|
|
709
783
|
}
|
|
710
784
|
}
|
|
@@ -791,12 +865,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
791
865
|
},
|
|
792
866
|
architectRecommendation: architectureRecommendation,
|
|
793
867
|
detectionTransparency,
|
|
868
|
+
uiScopeSignals: existingProjectUiScopeSignals,
|
|
794
869
|
});
|
|
795
870
|
|
|
796
|
-
if (architectPreferenceUpdated && architectPreferenceState) {
|
|
797
|
-
await writeArchitectPreferenceState(architectPreferenceState);
|
|
798
|
-
}
|
|
799
|
-
|
|
800
871
|
console.log('\nInitialization complete.');
|
|
801
872
|
console.log(`- Target directory: ${resolvedTargetDirectoryPath}`);
|
|
802
873
|
console.log(`- Profile: ${selectedProfile.displayName}`);
|
|
@@ -806,18 +877,8 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
806
877
|
if (selectedProfilePack) {
|
|
807
878
|
console.log(`- Team profile pack: ${selectedProfilePack.displayName}`);
|
|
808
879
|
}
|
|
809
|
-
if (
|
|
810
|
-
console.log(
|
|
811
|
-
`- Architect recommendation: ${toTitleCase(architectureRecommendation.recommendedStackFileName)} + ${toTitleCase(architectureRecommendation.recommendedBlueprintFileName)} (${architectureRecommendation.confidenceLabel})`
|
|
812
|
-
);
|
|
813
|
-
if (!projectDetection.hasExistingProjectFiles) {
|
|
814
|
-
console.log(`- Project domain: ${selectedProjectScopeLabel}`);
|
|
815
|
-
}
|
|
816
|
-
if (architectureRecommendation.userVeto?.applied) {
|
|
817
|
-
console.log(
|
|
818
|
-
`- User veto path: applied (${toTitleCase(architectureRecommendation.userVeto.selectedStackFileName)} + ${toTitleCase(architectureRecommendation.userVeto.selectedBlueprintFileName)})`
|
|
819
|
-
);
|
|
820
|
-
}
|
|
880
|
+
if (!projectDetection.hasExistingProjectFiles) {
|
|
881
|
+
console.log(`- Project domain: ${selectedProjectScopeLabel}`);
|
|
821
882
|
}
|
|
822
883
|
console.log(`- Stack: ${toTitleCase(selectedResolvedStackFileName)}`);
|
|
823
884
|
if (selectedAdditionalStackFileNames.length > 0) {
|
|
@@ -140,6 +140,7 @@ function buildUpgradeDesignIntentSeed({
|
|
|
140
140
|
repoEvidence: {
|
|
141
141
|
uiSignalReasons: uiScopeSignals.signalReasons,
|
|
142
142
|
frontendMetrics: uiScopeSignals.frontendEvidenceMetrics || null,
|
|
143
|
+
workspaceUiEntries: uiScopeSignals.workspaceUiEntries || [],
|
|
143
144
|
},
|
|
144
145
|
},
|
|
145
146
|
});
|
|
@@ -365,6 +366,9 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
365
366
|
if (uiScopeSignals.signalReasons.length > 0) {
|
|
366
367
|
console.log(`- Detection signals: ${uiScopeSignals.signalReasons.join('; ')}`);
|
|
367
368
|
}
|
|
369
|
+
if (Array.isArray(uiScopeSignals.workspaceUiEntries) && uiScopeSignals.workspaceUiEntries.length > 0) {
|
|
370
|
+
console.log(`- Nested UI workspaces: ${uiScopeSignals.workspaceUiEntries.map((workspaceUiEntry) => workspaceUiEntry.relativePath).join(', ')}`);
|
|
371
|
+
}
|
|
368
372
|
if (shouldSeedDesignIntentOnApply) {
|
|
369
373
|
console.log('- Planned seed on apply: docs/design-intent.json');
|
|
370
374
|
}
|
|
@@ -424,6 +428,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
424
428
|
runtimeEnvironment: existingOnboardingReport?.runtimeEnvironment || null,
|
|
425
429
|
operationMode: 'upgrade',
|
|
426
430
|
detectionTransparency,
|
|
431
|
+
uiScopeSignals,
|
|
427
432
|
});
|
|
428
433
|
|
|
429
434
|
console.log('\nUpgrade complete.');
|
package/lib/cli/compiler.mjs
CHANGED
|
@@ -51,6 +51,7 @@ export async function writeOnboardingReport({
|
|
|
51
51
|
memoryContinuity = undefined,
|
|
52
52
|
architectRecommendation = null,
|
|
53
53
|
detectionTransparency = null,
|
|
54
|
+
uiScopeSignals = null,
|
|
54
55
|
}) {
|
|
55
56
|
const onboardingReportPath = path.join(targetDirectoryPath, '.agent-context', 'state', 'onboarding-report.json');
|
|
56
57
|
const resolvedTokenOptimization = typeof tokenOptimization === 'undefined'
|
|
@@ -105,6 +106,14 @@ export async function writeOnboardingReport({
|
|
|
105
106
|
rankedCandidates: projectDetection.rankedCandidates,
|
|
106
107
|
evidence: projectDetection.evidence,
|
|
107
108
|
detectionTransparency: detectionTransparency || null,
|
|
109
|
+
uiScope: uiScopeSignals
|
|
110
|
+
? {
|
|
111
|
+
isUiScopeLikely: uiScopeSignals.isUiScopeLikely === true,
|
|
112
|
+
signalReasons: uiScopeSignals.signalReasons || [],
|
|
113
|
+
workspaceUiEntries: uiScopeSignals.workspaceUiEntries || [],
|
|
114
|
+
frontendEvidenceMetrics: uiScopeSignals.frontendEvidenceMetrics || null,
|
|
115
|
+
}
|
|
116
|
+
: null,
|
|
108
117
|
},
|
|
109
118
|
};
|
|
110
119
|
|
|
@@ -387,9 +396,15 @@ export async function buildCompiledRulesContent({
|
|
|
387
396
|
...projectDocsEntries.map((docFileName, docIndex) => `${docIndex + 1}. docs/${docFileName}`),
|
|
388
397
|
'',
|
|
389
398
|
'Universal SOP hard block policy:',
|
|
399
|
+
'- Stop implementation if docs/project-brief.md is missing.',
|
|
390
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.',
|
|
391
404
|
'- For UI scope, stop implementation if docs/DESIGN.md or docs/design-intent.json is missing.',
|
|
392
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.',
|
|
393
408
|
'',
|
|
394
409
|
'These docs were generated during project initialization and reflect the architecture,',
|
|
395
410
|
'database design, API contracts, and application flows chosen for this project.',
|
|
@@ -419,10 +434,15 @@ export async function buildCompiledRulesContent({
|
|
|
419
434
|
'',
|
|
420
435
|
'Bootstrap policy:',
|
|
421
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.',
|
|
422
440
|
'- If docs/project-brief.md is missing, execute bootstrap-project-context prompt immediately.',
|
|
423
441
|
hasBootstrapDesignPrompt
|
|
424
442
|
? '- For UI scope: if docs/DESIGN.md or docs/design-intent.json is missing, execute bootstrap-design prompt before implementing UI surfaces.'
|
|
425
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.',
|
|
426
446
|
'- Save generated docs under docs/ and keep them updated when feature scope changes.',
|
|
427
447
|
'Latest user prompt defines current feature scope and product direction.',
|
|
428
448
|
'Treat synthesized docs as living references, then continue implementation with those docs as source of truth.',
|