@ryuenn3123/agentic-senior-core 3.0.17 → 3.0.20
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 +84 -94
- package/.agent-context/prompts/init-project.md +32 -100
- package/.agent-context/prompts/refactor.md +22 -44
- package/.agent-context/prompts/review-code.md +28 -52
- package/.agent-context/review-checklists/architecture-review.md +31 -62
- package/.agent-context/review-checklists/pr-checklist.md +74 -108
- package/.agent-context/rules/api-docs.md +18 -206
- package/.agent-context/rules/architecture.md +40 -207
- package/.agent-context/rules/database-design.md +10 -199
- package/.agent-context/rules/docker-runtime.md +5 -5
- package/.agent-context/rules/efficiency-vs-hype.md +11 -149
- package/.agent-context/rules/error-handling.md +9 -231
- package/.agent-context/rules/event-driven.md +17 -221
- package/.agent-context/rules/frontend-architecture.md +66 -119
- package/.agent-context/rules/git-workflow.md +1 -1
- package/.agent-context/rules/microservices.md +28 -161
- package/.agent-context/rules/naming-conv.md +8 -138
- package/.agent-context/rules/performance.md +9 -175
- package/.agent-context/rules/realtime.md +11 -44
- package/.agent-context/rules/security.md +11 -295
- package/.agent-context/rules/testing.md +9 -174
- package/.agent-context/state/benchmark-analysis.json +3 -3
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.agent-context/state/onboarding-report.json +71 -11
- package/.agents/workflows/init-project.md +7 -24
- package/.agents/workflows/refactor.md +7 -24
- package/.agents/workflows/review-code.md +7 -24
- package/.cursorrules +22 -21
- package/.gemini/instructions.md +2 -2
- package/.github/copilot-instructions.md +2 -2
- package/.instructions.md +112 -213
- package/.windsurfrules +22 -21
- package/AGENTS.md +4 -4
- package/CONTRIBUTING.md +13 -22
- package/README.md +6 -20
- package/lib/cli/commands/init.mjs +102 -148
- package/lib/cli/commands/launch.mjs +3 -3
- package/lib/cli/commands/optimize.mjs +14 -4
- package/lib/cli/commands/upgrade.mjs +25 -23
- package/lib/cli/compiler.mjs +96 -62
- package/lib/cli/constants.mjs +28 -136
- package/lib/cli/detector/design-evidence.mjs +189 -6
- package/lib/cli/detector.mjs +6 -7
- package/lib/cli/init-detection-flow.mjs +10 -93
- package/lib/cli/init-selection.mjs +2 -68
- package/lib/cli/project-scaffolder/constants.mjs +1 -1
- package/lib/cli/project-scaffolder/design-contract.mjs +438 -335
- package/lib/cli/project-scaffolder/discovery.mjs +36 -82
- package/lib/cli/project-scaffolder/prompt-builders.mjs +55 -63
- package/lib/cli/project-scaffolder/storage.mjs +0 -4
- package/lib/cli/token-optimization.mjs +1 -1
- package/lib/cli/utils.mjs +75 -9
- package/package.json +2 -2
- package/scripts/detection-benchmark.mjs +4 -15
- package/scripts/documentation-boundary-audit.mjs +9 -9
- package/scripts/explain-on-demand-audit.mjs +11 -11
- package/scripts/forbidden-content-check.mjs +9 -9
- package/scripts/frontend-usability-audit.mjs +57 -36
- package/scripts/llm-judge.mjs +1 -1
- package/scripts/mcp-server/constants.mjs +60 -0
- package/scripts/mcp-server/tool-registry.mjs +149 -0
- package/scripts/mcp-server/tools.mjs +446 -0
- package/scripts/mcp-server.mjs +23 -661
- package/scripts/release-gate/audit-checks.mjs +426 -0
- package/scripts/release-gate/constants.mjs +53 -0
- package/scripts/release-gate/runtime.mjs +63 -0
- package/scripts/release-gate/static-checks.mjs +182 -0
- package/scripts/release-gate.mjs +13 -794
- package/scripts/rules-guardian-audit.mjs +14 -13
- package/scripts/single-source-lazy-loading-audit.mjs +3 -3
- package/scripts/sync-thin-adapters.mjs +5 -5
- package/scripts/ui-design-judge/constants.mjs +24 -0
- package/scripts/ui-design-judge/design-execution-summary.mjs +259 -0
- package/scripts/ui-design-judge/git-input.mjs +131 -0
- package/scripts/ui-design-judge/prompting.mjs +73 -0
- package/scripts/ui-design-judge/providers.mjs +102 -0
- package/scripts/ui-design-judge/reporting.mjs +182 -0
- package/scripts/ui-design-judge/rubric-calibration.mjs +214 -0
- package/scripts/ui-design-judge/rubric-goldset.json +188 -0
- package/scripts/ui-design-judge.mjs +166 -771
- package/scripts/ui-rubric-calibration.mjs +35 -0
- package/scripts/validate/config.mjs +198 -55
- package/scripts/validate/coverage-checks.mjs +32 -7
- package/scripts/validate.mjs +8 -4
- package/lib/cli/architect.mjs +0 -431
|
@@ -3,13 +3,18 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import { askChoice, askYesNo } from '../utils.mjs';
|
|
4
4
|
import {
|
|
5
5
|
ARCHITECTURE_STYLE_CHOICES,
|
|
6
|
-
AUTH_CHOICES,
|
|
7
|
-
DATABASE_CHOICES,
|
|
8
6
|
DOCKER_STRATEGY_CHOICES,
|
|
9
|
-
DOMAIN_CHOICES,
|
|
10
7
|
SUPPORTED_DOC_LANGUAGES,
|
|
11
8
|
} from './constants.mjs';
|
|
12
9
|
|
|
10
|
+
const PROJECT_SCOPE_CHOICES = [
|
|
11
|
+
'Frontend only',
|
|
12
|
+
'Backend only',
|
|
13
|
+
'Both (frontend + backend)',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const AGENT_RECOMMENDATION_REQUIRED = 'Agent recommendation required from current brief, repo evidence, and live official docs';
|
|
17
|
+
|
|
13
18
|
function parseBooleanLikeValue(rawValue) {
|
|
14
19
|
const normalizedValue = String(rawValue || '').trim().toLowerCase();
|
|
15
20
|
if (['true', 'yes', 'y', '1'].includes(normalizedValue)) {
|
|
@@ -70,7 +75,7 @@ function resolveArchitectureStyle(rawArchitectureStyle) {
|
|
|
70
75
|
const normalizedArchitectureStyle = String(rawArchitectureStyle || '').trim().toLowerCase();
|
|
71
76
|
|
|
72
77
|
if (!normalizedArchitectureStyle) {
|
|
73
|
-
return
|
|
78
|
+
return AGENT_RECOMMENDATION_REQUIRED;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
if (normalizedArchitectureStyle === 'monolith' || normalizedArchitectureStyle === 'modular monolith') {
|
|
@@ -94,22 +99,6 @@ function resolveArchitectureStyle(rawArchitectureStyle) {
|
|
|
94
99
|
return directMatch || ARCHITECTURE_STYLE_CHOICES[0];
|
|
95
100
|
}
|
|
96
101
|
|
|
97
|
-
async function askFeatureList(userInterface) {
|
|
98
|
-
console.log('\nList your key features (one per line, press Enter to finish):');
|
|
99
|
-
|
|
100
|
-
const features = [];
|
|
101
|
-
while (features.length < 10) {
|
|
102
|
-
const featureLine = (await userInterface.question(` Feature ${features.length + 1}: `)).trim();
|
|
103
|
-
if (!featureLine) {
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
features.push(featureLine);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return features;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
102
|
export function normalizeDocsLanguage(rawDocsLanguage = 'en') {
|
|
114
103
|
const normalizedDocsLanguage = String(rawDocsLanguage || 'en').trim().toLowerCase();
|
|
115
104
|
return SUPPORTED_DOC_LANGUAGES.has(normalizedDocsLanguage) ? normalizedDocsLanguage : null;
|
|
@@ -117,8 +106,7 @@ export function normalizeDocsLanguage(rawDocsLanguage = 'en') {
|
|
|
117
106
|
|
|
118
107
|
export async function runProjectDiscovery(userInterface, options = {}) {
|
|
119
108
|
console.log('\n--- Project Setup ---');
|
|
120
|
-
console.log('I will ask
|
|
121
|
-
console.log('This helps AI agents understand your project before writing code.\n');
|
|
109
|
+
console.log('I will ask the minimum needed questions, then let the AI agent recommend unresolved technical decisions from the brief, repo evidence, and live official docs.\n');
|
|
122
110
|
console.log('You can answer in your own language.');
|
|
123
111
|
console.log('CLI prompts stay in English, but non-English answers are fully supported.\n');
|
|
124
112
|
|
|
@@ -129,33 +117,25 @@ export async function runProjectDiscovery(userInterface, options = {}) {
|
|
|
129
117
|
: true;
|
|
130
118
|
const shouldAskForCiGuardrails = options.askForCiGuardrails !== false;
|
|
131
119
|
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
120
|
+
const projectName = defaultProjectName || 'Untitled project';
|
|
121
|
+
const briefPrompt = defaultProjectDescription
|
|
122
|
+
? `One-line project brief (press Enter to use current brief): `
|
|
123
|
+
: 'One-line project brief (optional but recommended): ';
|
|
124
|
+
const projectBriefAnswer = (await userInterface.question(briefPrompt)).trim();
|
|
125
|
+
const projectDescription = projectBriefAnswer
|
|
126
|
+
|| defaultProjectDescription
|
|
127
|
+
|| 'Project brief unresolved. The AI agent must ask for or infer product context before implementation.';
|
|
128
|
+
|
|
129
|
+
const projectScope = await askChoice('Project scope:', PROJECT_SCOPE_CHOICES, userInterface);
|
|
130
|
+
const primaryDomain = projectScope === 'Frontend only'
|
|
131
|
+
? 'Frontend/UI application'
|
|
132
|
+
: projectScope === 'Backend only'
|
|
133
|
+
? 'Backend/API service'
|
|
134
|
+
: 'Fullstack product';
|
|
137
135
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (!projectName) {
|
|
143
|
-
throw new Error('Project name is required for documentation scaffolding.');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const projectDescriptionPrompt = defaultProjectDescription
|
|
147
|
-
? `One-line description (press Enter to use: ${defaultProjectDescription}): `
|
|
148
|
-
: 'One-line description: ';
|
|
149
|
-
|
|
150
|
-
let projectDescription = (await userInterface.question(projectDescriptionPrompt)).trim();
|
|
151
|
-
|
|
152
|
-
if (!projectDescription) {
|
|
153
|
-
projectDescription = defaultProjectDescription || `A ${projectName} project.`;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const architectureStyle = await askChoice(
|
|
157
|
-
'Project topology:',
|
|
158
|
-
ARCHITECTURE_STYLE_CHOICES,
|
|
136
|
+
const dockerStrategy = await askChoice(
|
|
137
|
+
'Containerization strategy:',
|
|
138
|
+
DOCKER_STRATEGY_CHOICES,
|
|
159
139
|
userInterface
|
|
160
140
|
);
|
|
161
141
|
|
|
@@ -167,43 +147,17 @@ export async function runProjectDiscovery(userInterface, options = {}) {
|
|
|
167
147
|
)
|
|
168
148
|
: defaultIncludeCiGuardrails;
|
|
169
149
|
|
|
170
|
-
const domainSelection = await askChoice('Primary domain:', DOMAIN_CHOICES, userInterface);
|
|
171
|
-
let primaryDomain = domainSelection;
|
|
172
|
-
if (domainSelection === 'Other') {
|
|
173
|
-
primaryDomain = (await userInterface.question('Describe your domain: ')).trim() || 'Custom domain';
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const databaseSelection = await askChoice('Database needs:', DATABASE_CHOICES, userInterface);
|
|
177
|
-
let databaseChoice = databaseSelection;
|
|
178
|
-
if (databaseSelection === 'Other') {
|
|
179
|
-
databaseChoice = (await userInterface.question('Describe your database setup: ')).trim() || 'Custom database';
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const authSelection = await askChoice('Auth strategy:', AUTH_CHOICES, userInterface);
|
|
183
|
-
let authStrategy = authSelection;
|
|
184
|
-
if (authSelection === 'Other') {
|
|
185
|
-
authStrategy = (await userInterface.question('Describe your auth setup: ')).trim() || 'Custom auth';
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const dockerStrategy = await askChoice(
|
|
189
|
-
'Containerization strategy:',
|
|
190
|
-
DOCKER_STRATEGY_CHOICES,
|
|
191
|
-
userInterface
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
const features = await askFeatureList(userInterface);
|
|
195
|
-
|
|
196
150
|
return {
|
|
197
151
|
projectName,
|
|
198
152
|
projectDescription,
|
|
199
|
-
architectureStyle,
|
|
153
|
+
architectureStyle: AGENT_RECOMMENDATION_REQUIRED,
|
|
200
154
|
includeCiGuardrails,
|
|
201
155
|
primaryDomain,
|
|
202
|
-
databaseChoice,
|
|
203
|
-
authStrategy,
|
|
156
|
+
databaseChoice: AGENT_RECOMMENDATION_REQUIRED,
|
|
157
|
+
authStrategy: AGENT_RECOMMENDATION_REQUIRED,
|
|
204
158
|
dockerStrategy,
|
|
205
|
-
features,
|
|
206
|
-
additionalContext: '
|
|
159
|
+
features: [],
|
|
160
|
+
additionalContext: 'Fresh-project technical decisions are intentionally unresolved. The AI agent must recommend them from current context and official docs before coding.',
|
|
207
161
|
};
|
|
208
162
|
}
|
|
209
163
|
|
|
@@ -299,9 +253,9 @@ export async function loadProjectConfig(configFilePath) {
|
|
|
299
253
|
projectDescription: configEntries.projectDescription || configEntries.description || '',
|
|
300
254
|
architectureStyle: resolveArchitectureStyle(configEntries.architectureStyle || configEntries.topology || configEntries.serviceTopology),
|
|
301
255
|
includeCiGuardrails: parseBooleanLikeValue(configEntries.includeCiGuardrails) ?? parseBooleanLikeValue(configEntries.ci) ?? true,
|
|
302
|
-
primaryDomain: configEntries.primaryDomain || configEntries.domain ||
|
|
303
|
-
databaseChoice: configEntries.databaseChoice || configEntries.database ||
|
|
304
|
-
authStrategy: configEntries.authStrategy || configEntries.auth ||
|
|
256
|
+
primaryDomain: configEntries.primaryDomain || configEntries.domain || AGENT_RECOMMENDATION_REQUIRED,
|
|
257
|
+
databaseChoice: configEntries.databaseChoice || configEntries.database || AGENT_RECOMMENDATION_REQUIRED,
|
|
258
|
+
authStrategy: configEntries.authStrategy || configEntries.auth || AGENT_RECOMMENDATION_REQUIRED,
|
|
305
259
|
dockerStrategy: resolveDockerStrategy({
|
|
306
260
|
dockerStrategy: configEntries.dockerStrategy || configEntries.containerStrategy,
|
|
307
261
|
useDocker: configEntries.useDocker,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { toTitleCase } from '../utils.mjs';
|
|
2
2
|
import {
|
|
3
|
-
ARCHITECTURE_STYLE_CHOICES,
|
|
4
3
|
PROJECT_DOC_SYNTHESIS_PROMPT_VERSION,
|
|
5
4
|
} from './constants.mjs';
|
|
6
5
|
import { buildDesignIntentSeed } from './design-contract.mjs';
|
|
@@ -10,7 +9,6 @@ export function buildProjectContextBootstrapPrompt({
|
|
|
10
9
|
initContext,
|
|
11
10
|
expectedDocFileNames,
|
|
12
11
|
docsLanguage,
|
|
13
|
-
architectureRecommendation,
|
|
14
12
|
}) {
|
|
15
13
|
const featuresList = Array.isArray(discoveryAnswers.features) && discoveryAnswers.features.length > 0
|
|
16
14
|
? discoveryAnswers.features.map((feature, featureIndex) => `${featureIndex + 1}. ${feature}`).join('\n')
|
|
@@ -20,19 +18,6 @@ export function buildProjectContextBootstrapPrompt({
|
|
|
20
18
|
.map((fileName, fileIndex) => `${fileIndex + 1}. docs/${fileName}`)
|
|
21
19
|
.join('\n');
|
|
22
20
|
|
|
23
|
-
const architectureSnapshot = architectureRecommendation
|
|
24
|
-
? JSON.stringify({
|
|
25
|
-
briefType: architectureRecommendation.briefType,
|
|
26
|
-
stack: architectureRecommendation.recommendedStackFileName,
|
|
27
|
-
blueprint: architectureRecommendation.recommendedBlueprintFileName,
|
|
28
|
-
confidenceLabel: architectureRecommendation.confidenceLabel,
|
|
29
|
-
confidenceScore: architectureRecommendation.confidenceScore,
|
|
30
|
-
signalSummary: architectureRecommendation.signalSummary,
|
|
31
|
-
uncertaintyNotes: architectureRecommendation.uncertaintyNotes,
|
|
32
|
-
failureModes: architectureRecommendation.failureModes,
|
|
33
|
-
}, null, 2)
|
|
34
|
-
: 'null';
|
|
35
|
-
|
|
36
21
|
return [
|
|
37
22
|
'# Bootstrap Prompt: Dynamic Project Context Synthesis',
|
|
38
23
|
'',
|
|
@@ -47,8 +32,8 @@ export function buildProjectContextBootstrapPrompt({
|
|
|
47
32
|
'',
|
|
48
33
|
'## Hard Rules',
|
|
49
34
|
'1. No copy-paste from external prose.',
|
|
50
|
-
'2. Every major section must explain rationale and
|
|
51
|
-
'3. Keep
|
|
35
|
+
'2. Every major section must explain rationale, constraints, and required action.',
|
|
36
|
+
'3. Keep database, auth, runtime, and architecture aligned with explicit project constraints below unless user requests migration.',
|
|
52
37
|
'4. Output must be implementation-ready for engineers, not generic textbook explanation.',
|
|
53
38
|
'5. For any ecosystem or technology claim, perform live web research and include citation metadata (source + fetchedAt timestamp) rather than relying on offline heuristics.',
|
|
54
39
|
'6. Write for native English speakers at an 8th-grade reading level. Use clear, direct, plain language.',
|
|
@@ -56,22 +41,23 @@ export function buildProjectContextBootstrapPrompt({
|
|
|
56
41
|
'8. Separate confirmed facts from assumptions explicitly. When context is incomplete, add an `Assumptions to Validate` section and a `Next Validation Action` line.',
|
|
57
42
|
'9. If user inputs conflict with repo evidence, call out the conflict and choose the safer interpretation instead of silently forcing a generic answer.',
|
|
58
43
|
'10. Do not invent modules or architecture layers only to make the docs look complete.',
|
|
59
|
-
'11.
|
|
60
|
-
'12. Treat
|
|
44
|
+
'11. If runtime or framework setup is unresolved, recommend the latest stable compatible option from the brief, constraints, and live official documentation before coding. If an official setup flow yields newer, better-supported defaults than manual package assembly, use that path after approval.',
|
|
45
|
+
'12. Treat topology as an agent decision unless the user explicitly constrained it. If monolith fits, explain why. If a service split fits, document the evidence and service boundary logic.',
|
|
46
|
+
'13. Required docs coverage must include feature plan, architecture rationale, flow, public API or integration contracts when relevant, data model when relevant, UI/design when relevant, security assumptions, testing strategy, runtime/deployment notes, and next validation actions.',
|
|
61
47
|
'',
|
|
62
48
|
'## Project Inputs',
|
|
63
49
|
`- Project name: ${discoveryAnswers.projectName}`,
|
|
64
50
|
`- Project description: ${discoveryAnswers.projectDescription}`,
|
|
65
|
-
`- Project topology: ${discoveryAnswers.architectureStyle
|
|
51
|
+
`- Project topology decision: ${discoveryAnswers.architectureStyle}`,
|
|
66
52
|
`- Primary domain: ${discoveryAnswers.primaryDomain}`,
|
|
67
53
|
`- Database strategy: ${discoveryAnswers.databaseChoice}`,
|
|
68
54
|
`- Auth strategy: ${discoveryAnswers.authStrategy}`,
|
|
69
55
|
`- Docker strategy: ${discoveryAnswers.dockerStrategy}`,
|
|
70
56
|
`- Runtime environment: ${initContext.runtimeEnvironmentLabel || initContext.runtimeEnvironmentKey || 'Linux'}`,
|
|
71
|
-
`-
|
|
72
|
-
`-
|
|
73
|
-
`- Additional
|
|
74
|
-
`- Additional
|
|
57
|
+
`- Runtime constraint: ${initContext.stackFileName === 'agent-decision-runtime.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.stackFileName)}`,
|
|
58
|
+
`- Architecture constraint: ${initContext.blueprintFileName === 'agent-decision-architecture.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.blueprintFileName)}`,
|
|
59
|
+
`- Additional runtime constraints: ${Array.isArray(initContext.additionalStackFileNames) && initContext.additionalStackFileNames.length > 0 ? initContext.additionalStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ') : 'none'}`,
|
|
60
|
+
`- Additional architecture constraints: ${Array.isArray(initContext.additionalBlueprintFileNames) && initContext.additionalBlueprintFileNames.length > 0 ? initContext.additionalBlueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName)).join(', ') : 'none'}`,
|
|
75
61
|
'',
|
|
76
62
|
'## Key Features',
|
|
77
63
|
featuresList,
|
|
@@ -79,11 +65,6 @@ export function buildProjectContextBootstrapPrompt({
|
|
|
79
65
|
'## Additional Context',
|
|
80
66
|
discoveryAnswers.additionalContext || 'No additional context provided.',
|
|
81
67
|
'',
|
|
82
|
-
'## Architecture Brief Snapshot (for grounding)',
|
|
83
|
-
'```json',
|
|
84
|
-
architectureSnapshot,
|
|
85
|
-
'```',
|
|
86
|
-
'',
|
|
87
68
|
'## Required Execution',
|
|
88
69
|
'1. Create all required docs files listed above with complete Markdown content.',
|
|
89
70
|
'2. Make the docs adaptive to the real repo and prompt context. These are living references, not frozen templates.',
|
|
@@ -98,12 +79,10 @@ export function buildDesignBootstrapPrompt({
|
|
|
98
79
|
discoveryAnswers,
|
|
99
80
|
initContext,
|
|
100
81
|
docsLanguage,
|
|
101
|
-
architectureRecommendation,
|
|
102
82
|
}) {
|
|
103
83
|
const designIntentSeed = buildDesignIntentSeed({
|
|
104
84
|
discoveryAnswers,
|
|
105
85
|
initContext,
|
|
106
|
-
architectureRecommendation,
|
|
107
86
|
});
|
|
108
87
|
|
|
109
88
|
return [
|
|
@@ -133,7 +112,7 @@ export function buildDesignBootstrapPrompt({
|
|
|
133
112
|
'8. Responsive Strategy and Cross-Viewport Adaptation Matrix',
|
|
134
113
|
'9. Motion and Interaction Principles',
|
|
135
114
|
'10. Component Language and Morphology (cards, forms, nav, states)',
|
|
136
|
-
'11. Context Hygiene and
|
|
115
|
+
'11. Context Hygiene and Source Boundaries',
|
|
137
116
|
'12. Accessibility Non-Negotiables',
|
|
138
117
|
'13. Anti-Patterns to Avoid',
|
|
139
118
|
'14. Implementation Notes for Future UI Tasks',
|
|
@@ -153,47 +132,57 @@ export function buildDesignBootstrapPrompt({
|
|
|
153
132
|
'12. motionSystem',
|
|
154
133
|
'13. componentMorphology',
|
|
155
134
|
'14. accessibilityPolicy',
|
|
156
|
-
'15.
|
|
157
|
-
'16.
|
|
158
|
-
'17.
|
|
159
|
-
'18.
|
|
160
|
-
'19.
|
|
161
|
-
'20.
|
|
162
|
-
'21.
|
|
163
|
-
'22.
|
|
135
|
+
'15. designExecutionPolicy',
|
|
136
|
+
'16. designExecutionHandoff',
|
|
137
|
+
'17. reviewRubric',
|
|
138
|
+
'18. contextHygiene',
|
|
139
|
+
'19. experiencePrinciples',
|
|
140
|
+
'20. forbiddenPatterns',
|
|
141
|
+
'21. validationHints',
|
|
142
|
+
'22. requiredDesignSections',
|
|
143
|
+
'23. implementation',
|
|
144
|
+
'24. repoEvidence when onboarding or detector evidence exists',
|
|
164
145
|
'',
|
|
165
146
|
'## Hard Rules',
|
|
166
147
|
'1. No copy-paste from external style guides.',
|
|
167
148
|
'2. Every major decision must include psychological/product rationale.',
|
|
168
|
-
'3.
|
|
149
|
+
'3. Do not choose the final style, framework, component library, animation library, palette, typography, or layout paradigm from this offline scaffold. If unresolved, require an agent recommendation from repo evidence and live official docs before coding.',
|
|
169
150
|
'4. Keep tone decisive like an art director, not generic AI boilerplate.',
|
|
170
|
-
'5. Do not anchor the final design language to
|
|
151
|
+
'5. Do not anchor the final design language to famous products, benchmark visuals, or external reference surfaces.',
|
|
171
152
|
'6. Reject interchangeable hero layouts, generic SaaS gradients, and trend-chasing decoration unless the project context explicitly justifies them.',
|
|
172
153
|
'7. Encode color intent in perceptual terms first. Hex values may exist only as implementation derivatives.',
|
|
173
|
-
'8. Token guidance must define primitive, semantic, and component layers plus aliasing rules. Component tokens
|
|
154
|
+
'8. Token guidance must define primitive, semantic, and component layers plus aliasing rules. Component tokens must consume semantic aliases instead of raw values.',
|
|
174
155
|
'9. Responsive guidance must include layout mutation rules for mobile, tablet, and desktop. Shrinking the desktop layout is not enough.',
|
|
175
|
-
'10.
|
|
176
|
-
'11.
|
|
177
|
-
'12.
|
|
178
|
-
'13.
|
|
179
|
-
'14.
|
|
180
|
-
'15.
|
|
181
|
-
'16.
|
|
182
|
-
'17.
|
|
183
|
-
'18.
|
|
184
|
-
'19.
|
|
185
|
-
'20.
|
|
156
|
+
'10. Do not let repeated surfaces, component-kit defaults, or safe typography become the final direction without explicit product rationale.',
|
|
157
|
+
'11. The LLM must choose color, type, spacing, density, morphology, and motion dynamically from the active project context instead of copying this seed.',
|
|
158
|
+
'12. Viewport mutation must be operation-based. For each viewport, define the primary mutation operation, required surface actions, and forbidden responsive fallback patterns.',
|
|
159
|
+
'13. Motion can be bold, cinematic, or highly expressive when it improves memorability, hierarchy, feedback, or product confidence. If a motion library is needed, research current official docs and select the latest stable compatible option instead of using an offline default. Only reject motion when it harms clarity, accessibility, or runtime performance.',
|
|
160
|
+
'14. Define component morphology across interaction states and viewports so cards, forms, nav, and feedback surfaces adapt coherently instead of only resizing.',
|
|
161
|
+
'15. Keep UI-only requests context-isolated. Load frontend design rules first and do not eagerly load backend-only or workflow-only rules unless the task explicitly crosses those boundaries.',
|
|
162
|
+
'16. Treat WCAG 2.2 AA as the hard accessibility floor. Use APCA only as advisory perceptual tuning, never as a reason to waive a WCAG failure.',
|
|
163
|
+
'17. Accessibility planning must explicitly cover focus visibility, focus appearance, target size, accessible authentication, keyboard access, and dynamic status/state access.',
|
|
164
|
+
'18. Structured design execution must stay representation-first. Define a surface plan, component graph, content-priority map, viewport mutation plan, and interaction-state matrix before relying on semantic review.',
|
|
165
|
+
'19. design-intent.json must carry an explicit structured handoff, not just policy flags. The handoff must make surface plans, component relationships, task flow, and signature moves executable before coding starts.',
|
|
166
|
+
'20. Do not depend on screenshot capture, browser automation, or image diff artifacts as the default path. The contract must be strong enough to guide precise UI from repo evidence, component logic, and user intent alone.',
|
|
167
|
+
'21. Semantic review must judge contract fidelity, distinctiveness, hierarchy, state behavior, and viewport mutation directly from the contract and changed UI code.',
|
|
168
|
+
'22. Treat prior website memory, unrelated project aesthetics, and remembered screenshots as tainted context unless the user explicitly approves continuity.',
|
|
169
|
+
'23. Design continuity is opt-in. If no approved continuity exists, synthesize from the current repo evidence, current brief, and current project docs only.',
|
|
170
|
+
'24. Make at least one memorable visual bet so the resulting system is recognizable and not template-neutral.',
|
|
171
|
+
'25. Define a stable review rubric for distinctiveness, contract fidelity, visual consistency, heuristic UX quality, and motion discipline.',
|
|
172
|
+
'26. Genericity findings must name the actual drift signal. Do not label something generic without explaining the anti-pattern or rubric dimension.',
|
|
173
|
+
'27. Review rubric must support automatic genericity failure when named drift signals dominate a redesign or new UI surface.',
|
|
174
|
+
'28. Separate taste from failure. Bold direction is allowed when it still follows the contract, serves the product, and stays accessible.',
|
|
186
175
|
'',
|
|
187
176
|
'## Project Inputs',
|
|
188
177
|
`- Project name: ${discoveryAnswers.projectName}`,
|
|
189
178
|
`- Product context: ${discoveryAnswers.projectDescription}`,
|
|
190
|
-
`- Project topology: ${discoveryAnswers.architectureStyle
|
|
179
|
+
`- Project topology decision: ${discoveryAnswers.architectureStyle}`,
|
|
191
180
|
`- Domain: ${discoveryAnswers.primaryDomain}`,
|
|
192
|
-
`-
|
|
193
|
-
`-
|
|
181
|
+
`- Runtime constraint: ${initContext.stackFileName === 'agent-decision-runtime.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.stackFileName)}`,
|
|
182
|
+
`- Architecture constraint: ${initContext.blueprintFileName === 'agent-decision-architecture.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.blueprintFileName)}`,
|
|
194
183
|
'',
|
|
195
184
|
'## Seed Machine Contract',
|
|
196
|
-
'Refine this seed instead of discarding it. Keep the
|
|
185
|
+
'Refine this scaffold seed instead of discarding it. Keep the structural fields that are already valid, but replace all placeholder expressive direction with agent-chosen decisions grounded in repo evidence, the active brief, and live official docs when technology choices matter.',
|
|
197
186
|
'```json',
|
|
198
187
|
designIntentSeed.trim(),
|
|
199
188
|
'```',
|
|
@@ -203,11 +192,14 @@ export function buildDesignBootstrapPrompt({
|
|
|
203
192
|
'2. Create or update docs/design-intent.json with machine-readable design intent.',
|
|
204
193
|
'3. Keep both files synchronized: the markdown explains the rationale and the JSON captures the machine-readable contract.',
|
|
205
194
|
'4. Encode accessibility as a split policy: WCAG 2.2 AA hard floor, APCA advisory readability tuning, and explicit hard-vs-advisory checks.',
|
|
206
|
-
'5. Encode
|
|
207
|
-
'6.
|
|
208
|
-
'7.
|
|
209
|
-
'8.
|
|
210
|
-
'9.
|
|
195
|
+
'5. Encode structured design execution as policy: representation strategy, surface plan, component graph, content-priority map, viewport mutation plan, interaction-state matrix, semantic review focus, and structured handoff requirements.',
|
|
196
|
+
'6. Encode an explicit structured handoff inside docs/design-intent.json: surface plan, component graph, content-priority map, viewport mutation plan, interaction-state matrix, task-flow narrative, and signature move rationale.',
|
|
197
|
+
'7. Encode a stable review rubric: required dimensions, genericity signals, valid bold signals, and reporting rules that separate taste from real failure.',
|
|
198
|
+
'8. Make the handoff executable without screenshot dependency. The contract must still guide high-precision UI generation from repo evidence and changed code alone.',
|
|
199
|
+
'9. Preserve repoEvidence.designEvidenceSummary when onboarding or detector evidence exists instead of discarding it.',
|
|
200
|
+
'10. If repoEvidence.designEvidenceSummary.structuredInspection exists, use it as stronger evidence for class surfaces, inline style bypasses, and expression-backed UI structure before defaulting to generic assumptions.',
|
|
201
|
+
'11. Ensure both files stay project-specific, dynamic, and practical for implementation and review. The seed may guide structure, but it must not decide style offline.',
|
|
202
|
+
'12. After the contract exists, use it as a first-class source for future UI tasks.',
|
|
211
203
|
'',
|
|
212
204
|
].join('\n');
|
|
213
205
|
}
|
|
@@ -45,13 +45,11 @@ export async function generateProjectDocumentation(
|
|
|
45
45
|
const materializedFileNames = [];
|
|
46
46
|
|
|
47
47
|
const projectContextPromptFileName = 'bootstrap-project-context.md';
|
|
48
|
-
const architectureRecommendation = initContext.architectureRecommendation || null;
|
|
49
48
|
const projectContextPromptContent = buildProjectContextBootstrapPrompt({
|
|
50
49
|
discoveryAnswers,
|
|
51
50
|
initContext: synthesisContext,
|
|
52
51
|
expectedDocFileNames,
|
|
53
52
|
docsLanguage: normalizedDocsLanguage,
|
|
54
|
-
architectureRecommendation,
|
|
55
53
|
});
|
|
56
54
|
await fs.writeFile(
|
|
57
55
|
path.join(promptsDirectoryPath, projectContextPromptFileName),
|
|
@@ -66,7 +64,6 @@ export async function generateProjectDocumentation(
|
|
|
66
64
|
discoveryAnswers,
|
|
67
65
|
initContext: synthesisContext,
|
|
68
66
|
docsLanguage: normalizedDocsLanguage,
|
|
69
|
-
architectureRecommendation,
|
|
70
67
|
});
|
|
71
68
|
await fs.writeFile(path.join(promptsDirectoryPath, designPromptFileName), designPromptContent, 'utf8');
|
|
72
69
|
generatedPromptFileNames.push(designPromptFileName);
|
|
@@ -75,7 +72,6 @@ export async function generateProjectDocumentation(
|
|
|
75
72
|
const designIntentSeedContent = buildDesignIntentSeed({
|
|
76
73
|
discoveryAnswers,
|
|
77
74
|
initContext: synthesisContext,
|
|
78
|
-
architectureRecommendation,
|
|
79
75
|
});
|
|
80
76
|
await fs.writeFile(path.join(docsDirectoryPath, designIntentSeedFileName), designIntentSeedContent, 'utf8');
|
|
81
77
|
materializedFileNames.push(designIntentSeedFileName);
|
|
@@ -253,7 +253,7 @@ export function buildTokenOptimizationGuidanceBlock(tokenOptimizationState) {
|
|
|
253
253
|
);
|
|
254
254
|
|
|
255
255
|
const fallbackGuidance = [
|
|
256
|
-
'-
|
|
256
|
+
'- Use command variants with bounded output such as git diff --stat, rg --max-count, and npm test -- --reporter=dot.',
|
|
257
257
|
'- Request only the lines or sections required for the current decision.',
|
|
258
258
|
'- If shell output is still large, summarize and continue iteratively instead of dumping full logs.',
|
|
259
259
|
];
|
package/lib/cli/utils.mjs
CHANGED
|
@@ -38,9 +38,9 @@ export function printUsage() {
|
|
|
38
38
|
console.log('Options:');
|
|
39
39
|
console.log(' --help Show help');
|
|
40
40
|
console.log(' --version Show CLI version');
|
|
41
|
-
console.log(` --preset Use a
|
|
42
|
-
console.log(' --stack
|
|
43
|
-
console.log(' --blueprint
|
|
41
|
+
console.log(` --preset Use a scope hint preset; it does not choose stack/framework (${presetNames})`);
|
|
42
|
+
console.log(' --stack Explicit runtime constraint from the user');
|
|
43
|
+
console.log(' --blueprint Explicit architecture constraint from the user');
|
|
44
44
|
console.log(' --project-description Project intent text used to build an offline architecture brief before agent-led live research');
|
|
45
45
|
console.log(' --ci Override CI/CD quality checks (guardrails) (true|false)');
|
|
46
46
|
console.log(' --token-optimize Explicitly enable token optimization policy during init (default behavior)');
|
|
@@ -211,7 +211,35 @@ async function collectRelativeTreeEntries(baseDirectoryPath, relativeRootPath) {
|
|
|
211
211
|
return { files, directories };
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
async function
|
|
214
|
+
async function collectOptionalManagedEntries(baseDirectoryPath, options = {}) {
|
|
215
|
+
const files = new Set();
|
|
216
|
+
const directories = new Set();
|
|
217
|
+
|
|
218
|
+
if (options.includeMcpTemplate === true) {
|
|
219
|
+
const mcpServerEntrypointPath = path.join(baseDirectoryPath, 'scripts', 'mcp-server.mjs');
|
|
220
|
+
if (await pathExists(mcpServerEntrypointPath)) {
|
|
221
|
+
files.add('scripts/mcp-server.mjs');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const mcpServerHelpersDirectoryPath = path.join(baseDirectoryPath, 'scripts', 'mcp-server');
|
|
225
|
+
const mcpServerTreeEntries = await collectRelativeTreeEntries(
|
|
226
|
+
mcpServerHelpersDirectoryPath,
|
|
227
|
+
'scripts/mcp-server'
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
for (const relativeFilePath of mcpServerTreeEntries.files) {
|
|
231
|
+
files.add(relativeFilePath);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
for (const relativeDirectoryPath of mcpServerTreeEntries.directories) {
|
|
235
|
+
directories.add(relativeDirectoryPath);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return { files, directories };
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function buildManagedSourceManifest(options = {}) {
|
|
215
243
|
const sourceFiles = new Set();
|
|
216
244
|
const sourceDirectories = new Set();
|
|
217
245
|
|
|
@@ -237,13 +265,21 @@ async function buildManagedSourceManifest() {
|
|
|
237
265
|
sourceFiles.add(toPosixRelativePath(entryPointFileName));
|
|
238
266
|
}
|
|
239
267
|
|
|
268
|
+
const optionalManagedEntries = await collectOptionalManagedEntries(REPO_ROOT, options);
|
|
269
|
+
for (const sourceFilePath of optionalManagedEntries.files) {
|
|
270
|
+
sourceFiles.add(sourceFilePath);
|
|
271
|
+
}
|
|
272
|
+
for (const sourceDirectoryPath of optionalManagedEntries.directories) {
|
|
273
|
+
sourceDirectories.add(sourceDirectoryPath);
|
|
274
|
+
}
|
|
275
|
+
|
|
240
276
|
return {
|
|
241
277
|
files: sourceFiles,
|
|
242
278
|
directories: sourceDirectories,
|
|
243
279
|
};
|
|
244
280
|
}
|
|
245
281
|
|
|
246
|
-
async function collectManagedTargetManifest(resolvedTargetDirectoryPath) {
|
|
282
|
+
async function collectManagedTargetManifest(resolvedTargetDirectoryPath, options = {}) {
|
|
247
283
|
const targetFiles = new Set();
|
|
248
284
|
const targetDirectories = new Set();
|
|
249
285
|
|
|
@@ -269,6 +305,14 @@ async function collectManagedTargetManifest(resolvedTargetDirectoryPath) {
|
|
|
269
305
|
targetFiles.add(toPosixRelativePath(entryPointFileName));
|
|
270
306
|
}
|
|
271
307
|
|
|
308
|
+
const optionalManagedEntries = await collectOptionalManagedEntries(resolvedTargetDirectoryPath, options);
|
|
309
|
+
for (const targetFilePath of optionalManagedEntries.files) {
|
|
310
|
+
targetFiles.add(targetFilePath);
|
|
311
|
+
}
|
|
312
|
+
for (const targetDirectoryPath of optionalManagedEntries.directories) {
|
|
313
|
+
targetDirectories.add(targetDirectoryPath);
|
|
314
|
+
}
|
|
315
|
+
|
|
272
316
|
return {
|
|
273
317
|
files: targetFiles,
|
|
274
318
|
directories: targetDirectories,
|
|
@@ -283,8 +327,8 @@ export async function analyzeManagedGovernanceSurface(
|
|
|
283
327
|
? options.preservePathPrefixes
|
|
284
328
|
: ['.agent-context/state'];
|
|
285
329
|
|
|
286
|
-
const sourceManifest = await buildManagedSourceManifest();
|
|
287
|
-
const targetManifest = await collectManagedTargetManifest(resolvedTargetDirectoryPath);
|
|
330
|
+
const sourceManifest = await buildManagedSourceManifest(options);
|
|
331
|
+
const targetManifest = await collectManagedTargetManifest(resolvedTargetDirectoryPath, options);
|
|
288
332
|
|
|
289
333
|
const staleFiles = [];
|
|
290
334
|
const staleDirectories = [];
|
|
@@ -332,14 +376,18 @@ export async function analyzeManagedGovernanceSurface(
|
|
|
332
376
|
managedTargetFileCount: targetManifest.files.size,
|
|
333
377
|
managedTargetDirectoryCount: targetManifest.directories.size,
|
|
334
378
|
};
|
|
335
|
-
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export async function copyGovernanceAssetsToTarget(
|
|
336
382
|
resolvedTargetDirectoryPath,
|
|
337
383
|
options = {}
|
|
338
384
|
) {
|
|
339
385
|
const shouldIncludeMcpTemplate = options.includeMcpTemplate === true;
|
|
340
386
|
const shouldPruneManagedSurface = options.pruneManagedSurface === true;
|
|
341
387
|
const managedSurfacePlan = shouldPruneManagedSurface
|
|
342
|
-
? options.managedSurfacePlan || await analyzeManagedGovernanceSurface(resolvedTargetDirectoryPath
|
|
388
|
+
? options.managedSurfacePlan || await analyzeManagedGovernanceSurface(resolvedTargetDirectoryPath, {
|
|
389
|
+
includeMcpTemplate: shouldIncludeMcpTemplate,
|
|
390
|
+
})
|
|
343
391
|
: null;
|
|
344
392
|
const deletedManagedFiles = [];
|
|
345
393
|
const deletedManagedDirectories = [];
|
|
@@ -415,6 +463,24 @@ export async function analyzeManagedGovernanceSurface(
|
|
|
415
463
|
if (mcpServerSync.status === 'created') createdFiles.push('scripts/mcp-server.mjs');
|
|
416
464
|
else if (mcpServerSync.status === 'updated') updatedFiles.push('scripts/mcp-server.mjs');
|
|
417
465
|
|
|
466
|
+
const sourceMcpHelpersDirectoryPath = path.join(REPO_ROOT, 'scripts', 'mcp-server');
|
|
467
|
+
if (await pathExists(sourceMcpHelpersDirectoryPath)) {
|
|
468
|
+
const mcpHelperTreeEntries = await collectRelativeTreeEntries(
|
|
469
|
+
sourceMcpHelpersDirectoryPath,
|
|
470
|
+
'scripts/mcp-server'
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
for (const relativeHelperFilePath of mcpHelperTreeEntries.files) {
|
|
474
|
+
const sourceHelperFilePath = path.join(REPO_ROOT, ...relativeHelperFilePath.split('/'));
|
|
475
|
+
const targetHelperFilePath = path.join(resolvedTargetDirectoryPath, ...relativeHelperFilePath.split('/'));
|
|
476
|
+
const helperSyncResult = await syncFile(sourceHelperFilePath, targetHelperFilePath);
|
|
477
|
+
|
|
478
|
+
if (helperSyncResult.status === 'created') createdFiles.push(relativeHelperFilePath);
|
|
479
|
+
else if (helperSyncResult.status === 'updated') updatedFiles.push(relativeHelperFilePath);
|
|
480
|
+
else if (helperSyncResult.status === 'unchanged') unchangedFiles.push(relativeHelperFilePath);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
418
484
|
// 1. VS Code (Workspace Local Settings)
|
|
419
485
|
const vscodeMcpJsonPath = path.join(resolvedTargetDirectoryPath, '.vscode', 'mcp.json');
|
|
420
486
|
const vscodeWorkspaceMcpConfig = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryuenn3123/agentic-senior-core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Force your AI Agent to code like a Staff Engineer, not a Junior.",
|
|
6
6
|
"bin": {
|
|
@@ -66,6 +66,6 @@
|
|
|
66
66
|
"report:docs-quality-drift": "node ./scripts/docs-quality-drift-report.mjs",
|
|
67
67
|
"report:governance-weekly": "node ./scripts/governance-weekly-report.mjs",
|
|
68
68
|
"validate": "node ./scripts/validate.mjs",
|
|
69
|
-
"test": "node --test ./tests/cli-smoke.test.mjs ./tests/mcp-server.test.mjs ./tests/llm-judge.test.mjs ./tests/
|
|
69
|
+
"test": "node --test ./tests/cli-smoke.test.mjs ./tests/mcp-server.test.mjs ./tests/llm-judge.test.mjs ./tests/ui-rubric-calibration.test.mjs ./tests/operations.test.mjs"
|
|
70
70
|
}
|
|
71
71
|
}
|