@ryuenn3123/agentic-senior-core 4.3.15 → 5.1.0
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/.agents/plugins/marketplace.json +21 -0
- package/.agents/rules/agentic-senior-core.md +126 -0
- package/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.clinerules/agentic-senior-core.md +94 -0
- package/.codex-plugin/plugin.json +24 -0
- package/.cursor/rules/agentic-senior-core.mdc +99 -0
- package/.devin-plugin/plugin.json +13 -0
- package/.github/copilot-instructions.md +94 -0
- package/.github/plugin/marketplace.json +20 -0
- package/.github/plugin/plugin.json +16 -0
- package/.kiro/steering/agentic-senior-core.md +94 -0
- package/.openclaw/skills/asc/SKILL.md +23 -0
- package/.openclaw/skills/asc-audit/SKILL.md +28 -0
- package/.openclaw/skills/asc-review/SKILL.md +54 -0
- package/.opencode/plugins/agentic-senior-core.mjs +31 -0
- package/.windsurf/rules/agentic-senior-core.md +94 -0
- package/AGENTS.md +126 -179
- package/CONTRIBUTING.md +93 -63
- package/README.md +160 -111
- package/__init__.py +61 -0
- package/bin/agentic-senior-core.js +41 -43
- package/commands/asc-audit.md +1 -0
- package/commands/asc-audit.toml +2 -0
- package/commands/asc-help.md +9 -0
- package/commands/asc-help.toml +2 -0
- package/commands/asc-refactor.md +1 -0
- package/commands/asc-refactor.toml +2 -0
- package/commands/asc-review.md +1 -0
- package/commands/asc-review.toml +2 -0
- package/gemini-extension.json +10 -0
- package/hooks/copilot-hooks.json +21 -0
- package/hooks/hooks.json +31 -0
- package/hooks/session-start.js +36 -0
- package/hooks/subagent-start.js +38 -0
- package/lib/cli/commands/adapter.mjs +109 -0
- package/lib/cli/commands/clean.mjs +63 -0
- package/lib/cli/commands/status.mjs +94 -0
- package/package.json +43 -67
- package/plugin.yaml +16 -0
- package/scripts/uninstall.js +38 -0
- package/skills/asc/SKILL.md +16 -0
- package/skills/asc-audit/SKILL.md +28 -0
- package/skills/asc-refactor/SKILL.md +35 -0
- package/skills/asc-review/SKILL.md +54 -0
- package/.agent-context/policies/llm-judge-threshold.json +0 -29
- package/.agent-context/prompts/bootstrap-design.md +0 -63
- package/.agent-context/prompts/compact-natural-mode.md +0 -100
- package/.agent-context/prompts/init-project.md +0 -60
- package/.agent-context/prompts/refactor.md +0 -38
- package/.agent-context/prompts/review-code.md +0 -31
- package/.agent-context/review-checklists/architecture-review.md +0 -57
- package/.agent-context/review-checklists/pr-checklist.md +0 -136
- package/.agent-context/rules/api-docs.md +0 -24
- package/.agent-context/rules/api-versioning.md +0 -16
- package/.agent-context/rules/architecture.md +0 -33
- package/.agent-context/rules/background-jobs.md +0 -17
- package/.agent-context/rules/config-and-flags.md +0 -16
- package/.agent-context/rules/database-design.md +0 -18
- package/.agent-context/rules/docker-runtime.md +0 -17
- package/.agent-context/rules/error-handling.md +0 -16
- package/.agent-context/rules/event-driven.md +0 -16
- package/.agent-context/rules/frontend-architecture.md +0 -54
- package/.agent-context/rules/microservices.md +0 -16
- package/.agent-context/rules/migrations.md +0 -16
- package/.agent-context/rules/observability.md +0 -16
- package/.agent-context/rules/performance.md +0 -16
- package/.agent-context/rules/realtime.md +0 -16
- package/.agent-context/rules/resilience.md +0 -18
- package/.agent-context/rules/security.md +0 -18
- package/.agent-context/rules/testing.md +0 -16
- package/.agent-context/state/README.md +0 -25
- package/.agent-context/state/architecture-map.md +0 -40
- package/.agent-context/state/benchmark-comparison-schema.json +0 -181
- package/.agent-context/state/benchmark-reproducibility.json +0 -87
- package/.agent-context/state/benchmark-thresholds.json +0 -10
- package/.agent-context/state/benchmark-writer-judge-config.json +0 -58
- package/.agent-context/state/dependency-map.md +0 -41
- package/.agent-context/state/memory-adapter-contract.json +0 -52
- package/.agent-context/state/memory-schema-v1.json +0 -88
- package/GEMINI.md +0 -1
- package/benchmarks/README.md +0 -60
- package/benchmarks/compact-natural-mode/fixtures.mjs +0 -359
- package/benchmarks/compact-natural-mode/scorer.mjs +0 -331
- package/benchmarks/runtime-token-saver/fixtures.mjs +0 -836
- package/lib/cli/adaptive-context/catalog.mjs +0 -390
- package/lib/cli/adaptive-context/file-signals.mjs +0 -100
- package/lib/cli/adaptive-context/implications.mjs +0 -44
- package/lib/cli/adaptive-context.mjs +0 -365
- package/lib/cli/audits/typography-palette-anti-repeat/color-utils.mjs +0 -156
- package/lib/cli/audits/typography-palette-anti-repeat/file-scanner.mjs +0 -103
- package/lib/cli/audits/typography-palette-anti-repeat/typography-utils.mjs +0 -70
- package/lib/cli/audits/typography-palette-anti-repeat-audit.mjs +0 -239
- package/lib/cli/backup.mjs +0 -210
- package/lib/cli/commands/audit-design-anti-repeat.mjs +0 -39
- package/lib/cli/commands/context.mjs +0 -140
- package/lib/cli/commands/init/project-context.mjs +0 -60
- package/lib/cli/commands/init/runtime-environment.mjs +0 -59
- package/lib/cli/commands/init/setup-decisions.mjs +0 -83
- package/lib/cli/commands/init.mjs +0 -654
- package/lib/cli/commands/launch.mjs +0 -76
- package/lib/cli/commands/optimize.mjs +0 -284
- package/lib/cli/commands/rollback.mjs +0 -64
- package/lib/cli/commands/upgrade/token-optimization-state.mjs +0 -51
- package/lib/cli/commands/upgrade.mjs +0 -451
- package/lib/cli/compiler.mjs +0 -570
- package/lib/cli/constants.mjs +0 -136
- package/lib/cli/detector/constants.mjs +0 -135
- package/lib/cli/detector/design-evidence/collector.mjs +0 -256
- package/lib/cli/detector/design-evidence/constants.mjs +0 -39
- package/lib/cli/detector/design-evidence/file-traversal.mjs +0 -83
- package/lib/cli/detector/design-evidence/structured-attribute-evidence.mjs +0 -117
- package/lib/cli/detector/design-evidence/summary.mjs +0 -109
- package/lib/cli/detector/design-evidence/utility-helpers.mjs +0 -122
- package/lib/cli/detector/design-evidence.mjs +0 -25
- package/lib/cli/detector/stack-detection.mjs +0 -243
- package/lib/cli/detector/ui-signals.mjs +0 -150
- package/lib/cli/detector/workspace-scan.mjs +0 -177
- package/lib/cli/detector.mjs +0 -23
- package/lib/cli/init-detection-flow.mjs +0 -48
- package/lib/cli/init-options.mjs +0 -237
- package/lib/cli/init-selection.mjs +0 -29
- package/lib/cli/memory-continuity.mjs +0 -537
- package/lib/cli/preflight.mjs +0 -76
- package/lib/cli/project-scaffolder/constants.mjs +0 -69
- package/lib/cli/project-scaffolder/discovery.mjs +0 -272
- package/lib/cli/project-scaffolder/prompt-builders.mjs +0 -171
- package/lib/cli/project-scaffolder/storage.mjs +0 -144
- package/lib/cli/project-scaffolder/ui-scope-detection.mjs +0 -36
- package/lib/cli/project-scaffolder.mjs +0 -29
- package/lib/cli/rollback.mjs +0 -66
- package/lib/cli/token-optimization.mjs +0 -486
- package/lib/cli/utils/filesystem.mjs +0 -81
- package/lib/cli/utils/managed-surface.mjs +0 -280
- package/lib/cli/utils/prompting.mjs +0 -44
- package/lib/cli/utils.mjs +0 -479
- package/mcp.json +0 -134
- package/scripts/adaptive-context/fixtures.mjs +0 -183
- package/scripts/adaptive-context-benchmark.mjs +0 -9
- package/scripts/ascx-runtime-token-saver-benchmark.mjs +0 -9
- package/scripts/audit-cache-layer-contract.mjs +0 -263
- package/scripts/audit-caching-scope-hygiene.mjs +0 -268
- package/scripts/audit-file-size.mjs +0 -219
- package/scripts/audit-reflection-citations.mjs +0 -163
- package/scripts/audit-release-bundle.mjs +0 -170
- package/scripts/audit-rule-id-uniqueness.mjs +0 -313
- package/scripts/audit-typography-palette-anti-repeat.mjs +0 -120
- package/scripts/benchmark-evidence-bundle.mjs +0 -645
- package/scripts/benchmark-gate.mjs +0 -121
- package/scripts/benchmark-intelligence.mjs +0 -33
- package/scripts/benchmark-writer-judge-matrix.mjs +0 -379
- package/scripts/build-release-benchmark-bundle.mjs +0 -202
- package/scripts/bump-version.mjs +0 -103
- package/scripts/clean-local-artifacts.mjs +0 -78
- package/scripts/compact-natural-mode-benchmark.mjs +0 -9
- package/scripts/context-triggered-audit.mjs +0 -391
- package/scripts/detection-benchmark.mjs +0 -127
- package/scripts/docs-quality-drift-report.mjs +0 -358
- package/scripts/documentation-boundary-audit.mjs +0 -305
- package/scripts/explain-on-demand-audit.mjs +0 -427
- package/scripts/forbidden-content-check.mjs +0 -123
- package/scripts/frontend-usability-audit.mjs +0 -243
- package/scripts/generate-sbom.mjs +0 -61
- package/scripts/governance-weekly-report.mjs +0 -466
- package/scripts/llm-judge/checklist-loader.mjs +0 -45
- package/scripts/llm-judge/constants.mjs +0 -66
- package/scripts/llm-judge/diff-collection.mjs +0 -74
- package/scripts/llm-judge/prompting.mjs +0 -78
- package/scripts/llm-judge/providers.mjs +0 -111
- package/scripts/llm-judge/verdict.mjs +0 -134
- package/scripts/llm-judge.mjs +0 -200
- package/scripts/memory-continuity-benchmark.mjs +0 -322
- package/scripts/quality-trend-report.mjs +0 -289
- package/scripts/release-gate/audit-checks.mjs +0 -441
- package/scripts/release-gate/constants.mjs +0 -53
- package/scripts/release-gate/runtime.mjs +0 -63
- package/scripts/release-gate/static-checks.mjs +0 -182
- package/scripts/release-gate.mjs +0 -42
- package/scripts/rules-guardian-audit.mjs +0 -580
- package/scripts/single-source-lazy-loading-audit.mjs +0 -449
- package/scripts/sync-thin-adapters.mjs +0 -72
- package/scripts/token-optimization-benchmark.mjs +0 -252
- package/scripts/ui-design-judge/constants.mjs +0 -13
- package/scripts/ui-design-judge/design-execution-summary.mjs +0 -81
- package/scripts/ui-design-judge/git-input.mjs +0 -134
- package/scripts/ui-design-judge/prompting.mjs +0 -52
- package/scripts/ui-design-judge/providers.mjs +0 -102
- package/scripts/ui-design-judge/reporting.mjs +0 -183
- package/scripts/ui-design-judge/rubric-calibration.mjs +0 -214
- package/scripts/ui-design-judge/rubric-goldset.json +0 -188
- package/scripts/ui-design-judge.mjs +0 -319
- package/scripts/ui-rubric-calibration.mjs +0 -35
- package/scripts/validate/config.mjs +0 -519
- package/scripts/validate/coverage-checks.mjs +0 -446
- package/scripts/validate/file-structure.mjs +0 -162
- package/scripts/validate/markdown-content.mjs +0 -109
- package/scripts/validate/project-metadata.mjs +0 -166
- package/scripts/validate.mjs +0 -338
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
|
|
3
|
-
import { askChoice, askYesNo } from '../utils.mjs';
|
|
4
|
-
import {
|
|
5
|
-
ARCHITECTURE_STYLE_CHOICES,
|
|
6
|
-
DOC_INDEX_FILE_NAME,
|
|
7
|
-
DOCKER_STRATEGY_CHOICES,
|
|
8
|
-
SUPPORTED_DOC_LANGUAGES,
|
|
9
|
-
} from './constants.mjs';
|
|
10
|
-
|
|
11
|
-
const PROJECT_SCOPE_CHOICES = [
|
|
12
|
-
'Frontend only',
|
|
13
|
-
'Backend only',
|
|
14
|
-
'Both (frontend + backend)',
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const AGENT_RECOMMENDATION_REQUIRED = 'Agent recommendation required from current brief, repo evidence, and live official docs';
|
|
18
|
-
|
|
19
|
-
function parseBooleanLikeValue(rawValue) {
|
|
20
|
-
const normalizedValue = String(rawValue || '').trim().toLowerCase();
|
|
21
|
-
if (['true', 'yes', 'y', '1'].includes(normalizedValue)) {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (['false', 'no', 'n', '0'].includes(normalizedValue)) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function resolveDockerStrategy({ dockerStrategy, useDocker, useDockerDevelopment, useDockerProduction }) {
|
|
33
|
-
if (typeof dockerStrategy === 'string' && dockerStrategy.trim().length > 0) {
|
|
34
|
-
const normalizedDockerStrategy = dockerStrategy.trim().toLowerCase();
|
|
35
|
-
const directMatch = DOCKER_STRATEGY_CHOICES.find(
|
|
36
|
-
(dockerStrategyChoice) => dockerStrategyChoice.toLowerCase() === normalizedDockerStrategy
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
if (directMatch) {
|
|
40
|
-
return directMatch;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const normalizedUseDocker = typeof useDocker === 'boolean' ? useDocker : parseBooleanLikeValue(useDocker);
|
|
45
|
-
const normalizedUseDockerDevelopment = typeof useDockerDevelopment === 'boolean'
|
|
46
|
-
? useDockerDevelopment
|
|
47
|
-
: parseBooleanLikeValue(useDockerDevelopment);
|
|
48
|
-
const normalizedUseDockerProduction = typeof useDockerProduction === 'boolean'
|
|
49
|
-
? useDockerProduction
|
|
50
|
-
: parseBooleanLikeValue(useDockerProduction);
|
|
51
|
-
|
|
52
|
-
if (normalizedUseDocker === false) {
|
|
53
|
-
return DOCKER_STRATEGY_CHOICES[0];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (normalizedUseDockerDevelopment === true && normalizedUseDockerProduction === true) {
|
|
57
|
-
return DOCKER_STRATEGY_CHOICES[3];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (normalizedUseDockerDevelopment === true && normalizedUseDockerProduction !== true) {
|
|
61
|
-
return DOCKER_STRATEGY_CHOICES[1];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (normalizedUseDockerProduction === true && normalizedUseDockerDevelopment !== true) {
|
|
65
|
-
return DOCKER_STRATEGY_CHOICES[2];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (normalizedUseDocker === true) {
|
|
69
|
-
return DOCKER_STRATEGY_CHOICES[3];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return DOCKER_STRATEGY_CHOICES[0];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function resolveArchitectureStyle(rawArchitectureStyle) {
|
|
76
|
-
const normalizedArchitectureStyle = String(rawArchitectureStyle || '').trim().toLowerCase();
|
|
77
|
-
|
|
78
|
-
if (!normalizedArchitectureStyle) {
|
|
79
|
-
return AGENT_RECOMMENDATION_REQUIRED;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (normalizedArchitectureStyle === 'monolith' || normalizedArchitectureStyle === 'modular monolith') {
|
|
83
|
-
return ARCHITECTURE_STYLE_CHOICES[0];
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
normalizedArchitectureStyle === 'microservice'
|
|
88
|
-
|| normalizedArchitectureStyle === 'microservices'
|
|
89
|
-
|| normalizedArchitectureStyle === 'distributed'
|
|
90
|
-
|| normalizedArchitectureStyle === 'distributed system'
|
|
91
|
-
|| normalizedArchitectureStyle === 'microservice / distributed system'
|
|
92
|
-
) {
|
|
93
|
-
return ARCHITECTURE_STYLE_CHOICES[1];
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const directMatch = ARCHITECTURE_STYLE_CHOICES.find(
|
|
97
|
-
(architectureStyleChoice) => architectureStyleChoice.toLowerCase() === normalizedArchitectureStyle
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
return directMatch || ARCHITECTURE_STYLE_CHOICES[0];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function normalizeDocsLanguage(rawDocsLanguage = 'en') {
|
|
104
|
-
const normalizedDocsLanguage = String(rawDocsLanguage || 'en').trim().toLowerCase();
|
|
105
|
-
return SUPPORTED_DOC_LANGUAGES.has(normalizedDocsLanguage) ? normalizedDocsLanguage : null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export async function runProjectDiscovery(userInterface, options = {}) {
|
|
109
|
-
console.log('\n--- Project Setup ---');
|
|
110
|
-
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');
|
|
111
|
-
console.log('You can answer in your own language.');
|
|
112
|
-
console.log('CLI prompts stay in English, but non-English answers are fully supported.\n');
|
|
113
|
-
|
|
114
|
-
const defaultProjectName = (options.defaultProjectName || '').trim();
|
|
115
|
-
const defaultProjectDescription = String(options.defaultProjectDescription || '').trim();
|
|
116
|
-
const defaultIncludeCiGuardrails = typeof options.defaultIncludeCiGuardrails === 'boolean'
|
|
117
|
-
? options.defaultIncludeCiGuardrails
|
|
118
|
-
: true;
|
|
119
|
-
const shouldAskForCiGuardrails = options.askForCiGuardrails !== false;
|
|
120
|
-
|
|
121
|
-
const projectName = defaultProjectName || 'Untitled project';
|
|
122
|
-
const briefPrompt = defaultProjectDescription
|
|
123
|
-
? `One-line project brief (press Enter to use current brief): `
|
|
124
|
-
: 'One-line project brief (optional but recommended): ';
|
|
125
|
-
const projectBriefAnswer = (await userInterface.question(briefPrompt)).trim();
|
|
126
|
-
const projectDescription = projectBriefAnswer
|
|
127
|
-
|| defaultProjectDescription
|
|
128
|
-
|| 'Project brief unresolved. The AI agent must ask for or infer product context before implementation.';
|
|
129
|
-
|
|
130
|
-
const projectScope = await askChoice('Project scope:', PROJECT_SCOPE_CHOICES, userInterface);
|
|
131
|
-
const primaryDomain = projectScope === 'Frontend only'
|
|
132
|
-
? 'Frontend/UI application'
|
|
133
|
-
: projectScope === 'Backend only'
|
|
134
|
-
? 'Backend/API service'
|
|
135
|
-
: 'Fullstack product';
|
|
136
|
-
|
|
137
|
-
const dockerStrategy = await askChoice(
|
|
138
|
-
'Containerization strategy:',
|
|
139
|
-
DOCKER_STRATEGY_CHOICES,
|
|
140
|
-
userInterface
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const includeCiGuardrails = shouldAskForCiGuardrails
|
|
144
|
-
? await askYesNo(
|
|
145
|
-
'Enable CI/CD quality checks (guardrails) and the LLM Judge policy?',
|
|
146
|
-
userInterface,
|
|
147
|
-
defaultIncludeCiGuardrails
|
|
148
|
-
)
|
|
149
|
-
: defaultIncludeCiGuardrails;
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
projectName,
|
|
153
|
-
projectDescription,
|
|
154
|
-
architectureStyle: AGENT_RECOMMENDATION_REQUIRED,
|
|
155
|
-
includeCiGuardrails,
|
|
156
|
-
primaryDomain,
|
|
157
|
-
databaseChoice: AGENT_RECOMMENDATION_REQUIRED,
|
|
158
|
-
authStrategy: AGENT_RECOMMENDATION_REQUIRED,
|
|
159
|
-
dockerStrategy,
|
|
160
|
-
features: [],
|
|
161
|
-
additionalContext: 'Fresh-project technical decisions are intentionally unresolved. The AI agent must recommend them from current context and official docs before coding.',
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function resolveProjectDocTargets(discoveryAnswers) {
|
|
166
|
-
const hasDatabase = !discoveryAnswers.databaseChoice.toLowerCase().startsWith('none');
|
|
167
|
-
const isApiOrWebDomain = ['API service', 'Web application'].includes(discoveryAnswers.primaryDomain)
|
|
168
|
-
|| discoveryAnswers.primaryDomain.toLowerCase().includes('api')
|
|
169
|
-
|| discoveryAnswers.primaryDomain.toLowerCase().includes('web')
|
|
170
|
-
|| discoveryAnswers.primaryDomain.toLowerCase().includes('fullstack');
|
|
171
|
-
|
|
172
|
-
const requiredDocFileNames = [
|
|
173
|
-
DOC_INDEX_FILE_NAME,
|
|
174
|
-
'project-brief.md',
|
|
175
|
-
'architecture-decision-record.md',
|
|
176
|
-
'flow-overview.md',
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
if (hasDatabase) {
|
|
180
|
-
requiredDocFileNames.push('database-schema.md');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (isApiOrWebDomain) {
|
|
184
|
-
requiredDocFileNames.push('api-contract.md');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return { requiredDocFileNames };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function buildSynthesisContext(_discoveryAnswers, initContext) {
|
|
191
|
-
const additionalStackFileNames = Array.isArray(initContext.additionalStackFileNames)
|
|
192
|
-
? initContext.additionalStackFileNames
|
|
193
|
-
: [];
|
|
194
|
-
const additionalBlueprintFileNames = Array.isArray(initContext.additionalBlueprintFileNames)
|
|
195
|
-
? initContext.additionalBlueprintFileNames
|
|
196
|
-
: [];
|
|
197
|
-
|
|
198
|
-
return {
|
|
199
|
-
stackFileName: initContext.stackFileName,
|
|
200
|
-
additionalStackFileNames,
|
|
201
|
-
blueprintFileName: initContext.blueprintFileName,
|
|
202
|
-
additionalBlueprintFileNames,
|
|
203
|
-
runtimeEnvironmentKey: initContext.runtimeEnvironmentKey || 'linux',
|
|
204
|
-
runtimeEnvironmentLabel: initContext.runtimeEnvironmentLabel || 'Linux',
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export async function loadProjectConfig(configFilePath) {
|
|
209
|
-
const configContent = await fs.readFile(configFilePath, 'utf8');
|
|
210
|
-
const configLines = configContent.split(/\r?\n/);
|
|
211
|
-
const configEntries = {};
|
|
212
|
-
let currentKey = null;
|
|
213
|
-
let currentArrayValues = null;
|
|
214
|
-
|
|
215
|
-
for (const configLine of configLines) {
|
|
216
|
-
const trimmedLine = configLine.trim();
|
|
217
|
-
|
|
218
|
-
if (!trimmedLine || trimmedLine.startsWith('#')) {
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (trimmedLine.startsWith('- ') && currentKey && currentArrayValues !== null) {
|
|
223
|
-
currentArrayValues.push(trimmedLine.slice(2).trim());
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (currentKey && currentArrayValues !== null) {
|
|
228
|
-
configEntries[currentKey] = currentArrayValues;
|
|
229
|
-
currentKey = null;
|
|
230
|
-
currentArrayValues = null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const colonIndex = trimmedLine.indexOf(':');
|
|
234
|
-
if (colonIndex === -1) {
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const entryKey = trimmedLine.slice(0, colonIndex).trim();
|
|
239
|
-
const entryValue = trimmedLine.slice(colonIndex + 1).trim();
|
|
240
|
-
|
|
241
|
-
if (!entryValue) {
|
|
242
|
-
currentKey = entryKey;
|
|
243
|
-
currentArrayValues = [];
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
configEntries[entryKey] = entryValue;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (currentKey && currentArrayValues !== null) {
|
|
251
|
-
configEntries[currentKey] = currentArrayValues;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return {
|
|
255
|
-
projectName: configEntries.projectName || configEntries.name || '',
|
|
256
|
-
projectDescription: configEntries.projectDescription || configEntries.description || '',
|
|
257
|
-
architectureStyle: resolveArchitectureStyle(configEntries.architectureStyle || configEntries.topology || configEntries.serviceTopology),
|
|
258
|
-
includeCiGuardrails: parseBooleanLikeValue(configEntries.includeCiGuardrails) ?? parseBooleanLikeValue(configEntries.ci) ?? true,
|
|
259
|
-
primaryDomain: configEntries.primaryDomain || configEntries.domain || AGENT_RECOMMENDATION_REQUIRED,
|
|
260
|
-
databaseChoice: configEntries.databaseChoice || configEntries.database || AGENT_RECOMMENDATION_REQUIRED,
|
|
261
|
-
authStrategy: configEntries.authStrategy || configEntries.auth || AGENT_RECOMMENDATION_REQUIRED,
|
|
262
|
-
dockerStrategy: resolveDockerStrategy({
|
|
263
|
-
dockerStrategy: configEntries.dockerStrategy || configEntries.containerStrategy,
|
|
264
|
-
useDocker: configEntries.useDocker,
|
|
265
|
-
useDockerDevelopment: configEntries.useDockerDevelopment || configEntries.dockerDevelopment,
|
|
266
|
-
useDockerProduction: configEntries.useDockerProduction || configEntries.dockerProduction,
|
|
267
|
-
}),
|
|
268
|
-
features: Array.isArray(configEntries.features) ? configEntries.features : [],
|
|
269
|
-
additionalContext: configEntries.additionalContext || configEntries.context || 'No additional context provided.',
|
|
270
|
-
docsLang: configEntries.docsLang || configEntries.docsLanguage || 'en',
|
|
271
|
-
};
|
|
272
|
-
}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { toTitleCase } from '../utils.mjs';
|
|
2
|
-
import {
|
|
3
|
-
PROJECT_DOC_SYNTHESIS_PROMPT_VERSION,
|
|
4
|
-
} from './constants.mjs';
|
|
5
|
-
|
|
6
|
-
function buildDockerStrategyExecutionBlock(dockerStrategy) {
|
|
7
|
-
const selectedDockerStrategy = String(dockerStrategy || '').trim();
|
|
8
|
-
const normalizedDockerStrategy = selectedDockerStrategy.toLowerCase();
|
|
9
|
-
|
|
10
|
-
if (!selectedDockerStrategy || normalizedDockerStrategy.startsWith('no docker')) {
|
|
11
|
-
return [
|
|
12
|
-
'## Docker Execution Gate',
|
|
13
|
-
'Docker was not selected. Do not create container assets unless the user changes scope.',
|
|
14
|
-
];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const requiredAssetFloor = [
|
|
18
|
-
'.dockerignore',
|
|
19
|
-
normalizedDockerStrategy.includes('development') || normalizedDockerStrategy.includes('both') ? 'compose.yaml for development' : null,
|
|
20
|
-
normalizedDockerStrategy.includes('production') || normalizedDockerStrategy.includes('both') ? 'compose.prod.yaml or a documented production Compose override' : null,
|
|
21
|
-
'Dockerfile stage(s) derived from the actual stack',
|
|
22
|
-
'docs/docker-runtime.md or a deployment runbook with ports, entrypoints, health checks, and source URLs',
|
|
23
|
-
].filter(Boolean).join(', ');
|
|
24
|
-
|
|
25
|
-
return [
|
|
26
|
-
'## Docker Execution Gate',
|
|
27
|
-
`Selected Docker strategy: ${selectedDockerStrategy}`,
|
|
28
|
-
'- Load .agent-context/rules/docker-runtime.md and verify current official Docker docs before authoring assets.',
|
|
29
|
-
'- Materialize Docker assets from the actual stack; do not stop at docs-only acknowledgement or runtime notes.',
|
|
30
|
-
'- Required asset floor: ' + requiredAssetFloor + '.',
|
|
31
|
-
'- Keep development and production lanes separate when both are selected.',
|
|
32
|
-
'- If the user asks to create files without commands, write the files and documented commands, but do not execute Docker build, Compose, or registry commands.',
|
|
33
|
-
'- If Docker is enabled for development, local development setup and first-build instructions in the README must use Docker (e.g., `docker compose up`) rather than fallback local commands like `npm run dev`.',
|
|
34
|
-
];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function buildProjectContextBootstrapPrompt({
|
|
38
|
-
discoveryAnswers,
|
|
39
|
-
initContext,
|
|
40
|
-
expectedDocFileNames,
|
|
41
|
-
docsLanguage,
|
|
42
|
-
}) {
|
|
43
|
-
const featuresList = Array.isArray(discoveryAnswers.features) && discoveryAnswers.features.length > 0
|
|
44
|
-
? discoveryAnswers.features.map((feature, featureIndex) => `${featureIndex + 1}. ${feature}`).join('\n')
|
|
45
|
-
: 'Derive the first concrete feature set from the project name, description, and domain. Do not invent arbitrary modules just to fill space.';
|
|
46
|
-
|
|
47
|
-
const expectedDocsList = [
|
|
48
|
-
'README.md',
|
|
49
|
-
...expectedDocFileNames.map((fileName) => `docs/${fileName}`),
|
|
50
|
-
]
|
|
51
|
-
.map((filePath, fileIndex) => `${fileIndex + 1}. ${filePath}`)
|
|
52
|
-
.join('\n');
|
|
53
|
-
|
|
54
|
-
return [
|
|
55
|
-
'# Bootstrap Prompt: Dynamic Project Context Synthesis',
|
|
56
|
-
'',
|
|
57
|
-
`Protocol version: ${PROJECT_DOC_SYNTHESIS_PROMPT_VERSION}`,
|
|
58
|
-
'',
|
|
59
|
-
'You are a Lead Solution Architect and Principal Engineer.',
|
|
60
|
-
'Write project context docs from scratch (no template rendering, no placeholder boilerplate).',
|
|
61
|
-
'',
|
|
62
|
-
'## Mission',
|
|
63
|
-
`Create or update these files in ${docsLanguage.toUpperCase()} language:`,
|
|
64
|
-
expectedDocsList,
|
|
65
|
-
'',
|
|
66
|
-
'## Hard Rules',
|
|
67
|
-
'1. No copy-paste from external prose.',
|
|
68
|
-
'2. Every major section must explain rationale, constraints, and required action.',
|
|
69
|
-
'3. Keep database, auth, runtime, and architecture aligned with explicit project constraints below unless user requests migration.',
|
|
70
|
-
'4. Output must be implementation-ready for engineers, not generic textbook explanation.',
|
|
71
|
-
'5. For any ecosystem or technology claim, perform live web research and include citation metadata (source + fetchedAt timestamp) rather than relying on offline heuristics.',
|
|
72
|
-
'6. Write for native English speakers at an 8th-grade reading level. Use clear, direct, plain language.',
|
|
73
|
-
'7. Avoid emoji, AI cliches, buzzwords, academic phrasing, padding, and generic filler.',
|
|
74
|
-
'8. Separate confirmed facts from assumptions explicitly. When context is incomplete, add an `Assumptions to Validate` section and a `Next Validation Action` line.',
|
|
75
|
-
'9. If user inputs conflict with repo evidence, call out the conflict and choose the safer interpretation instead of silently forcing a generic answer.',
|
|
76
|
-
'10. Do not invent modules or architecture layers only to make the docs look complete.',
|
|
77
|
-
'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.',
|
|
78
|
-
'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.',
|
|
79
|
-
'13. Required docs coverage must include a public and developer README entrypoint, 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.',
|
|
80
|
-
'14. Use Mermaid.js as the default diagram format for flow, sequence, ER, architecture, C4, and state diagrams embedded in Markdown docs. Do not use PlantUML, ASCII art diagrams, Graphviz DOT, or Structurizr DSL. When updating existing docs that contain prose-only descriptions, convert relevant sections to Mermaid diagrams in the same change.',
|
|
81
|
-
'15. README.md must be public and developer friendly, including for private projects: what it is, who it is for, setup, core workflow, configuration, and links to deeper docs. Do not include secrets, internal agent notes, private reasoning, or governance policy dumps.',
|
|
82
|
-
'16. docs/doc-index.md is the low-token routing map for docs/*. Keep it short, list each active doc, and explain when an agent should read it. Do not make it the source of truth for requirements or architecture.',
|
|
83
|
-
'17. Keep docs complete but compact. Add extra docs files only for stable, distinct, or long workflows such as hardware setup, deployment, operations, testing validation, or troubleshooting.',
|
|
84
|
-
'18. Add SRS, PRD, technical-design, or ERD docs only when project evidence triggers them. Use PRD for product-roadmap/user-story ownership, SRS for contractual or multi-stakeholder acceptance criteria, technical-design for non-trivial architecture decisions, and ERD only as a separate file when the schema is too complex for docs/database-schema.md.',
|
|
85
|
-
'',
|
|
86
|
-
'## Project Inputs',
|
|
87
|
-
`- Project name: ${discoveryAnswers.projectName}`,
|
|
88
|
-
`- Project description: ${discoveryAnswers.projectDescription}`,
|
|
89
|
-
`- Project topology decision: ${discoveryAnswers.architectureStyle}`,
|
|
90
|
-
`- Primary domain: ${discoveryAnswers.primaryDomain}`,
|
|
91
|
-
`- Database strategy: ${discoveryAnswers.databaseChoice}`,
|
|
92
|
-
`- Auth strategy: ${discoveryAnswers.authStrategy}`,
|
|
93
|
-
`- Docker strategy: ${discoveryAnswers.dockerStrategy}`,
|
|
94
|
-
`- Runtime environment: ${initContext.runtimeEnvironmentLabel || initContext.runtimeEnvironmentKey || 'Linux'}`,
|
|
95
|
-
`- Runtime constraint: ${initContext.stackFileName === 'agent-decision-runtime.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.stackFileName)}`,
|
|
96
|
-
`- Architecture constraint: ${initContext.blueprintFileName === 'agent-decision-architecture.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.blueprintFileName)}`,
|
|
97
|
-
`- Additional runtime constraints: ${Array.isArray(initContext.additionalStackFileNames) && initContext.additionalStackFileNames.length > 0 ? initContext.additionalStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ') : 'none'}`,
|
|
98
|
-
`- Additional architecture constraints: ${Array.isArray(initContext.additionalBlueprintFileNames) && initContext.additionalBlueprintFileNames.length > 0 ? initContext.additionalBlueprintFileNames.map((blueprintFileName) => toTitleCase(blueprintFileName)).join(', ') : 'none'}`,
|
|
99
|
-
'',
|
|
100
|
-
...buildDockerStrategyExecutionBlock(discoveryAnswers.dockerStrategy),
|
|
101
|
-
'',
|
|
102
|
-
'## Key Features',
|
|
103
|
-
featuresList,
|
|
104
|
-
'',
|
|
105
|
-
'## Additional Context',
|
|
106
|
-
discoveryAnswers.additionalContext || 'No additional context provided.',
|
|
107
|
-
'',
|
|
108
|
-
'## Required Execution',
|
|
109
|
-
'1. Create all required docs files listed above with complete Markdown content.',
|
|
110
|
-
'2. Make the docs adaptive to the real repo and prompt context. These are living references, not frozen templates.',
|
|
111
|
-
'3. In docs/doc-index.md, include a compact table with document path, purpose, reads-when triggers, status, and last-updated date.',
|
|
112
|
-
'4. 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.',
|
|
113
|
-
'5. Before implementation, use README.md plus docs/doc-index.md to select only the relevant docs for the current task instead of broad-reading docs/*.md.',
|
|
114
|
-
'6. Before implementation, use the docs to confirm stack, runtime, architecture, public contracts, data, validation, and delivery assumptions.',
|
|
115
|
-
'7. Keep content original, specific to this project, and actionable for implementation.',
|
|
116
|
-
'8. After writing docs, continue coding tasks using these docs as living project context.',
|
|
117
|
-
'',
|
|
118
|
-
].join('\n');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function buildDesignBootstrapPrompt({
|
|
122
|
-
discoveryAnswers,
|
|
123
|
-
initContext,
|
|
124
|
-
docsLanguage,
|
|
125
|
-
}) {
|
|
126
|
-
|
|
127
|
-
return [
|
|
128
|
-
'# Bootstrap Prompt: Dynamic Design Contract Synthesis',
|
|
129
|
-
'',
|
|
130
|
-
`Protocol version: ${PROJECT_DOC_SYNTHESIS_PROMPT_VERSION}`,
|
|
131
|
-
'',
|
|
132
|
-
'You are the Lead UI/UX Art Director for this project.',
|
|
133
|
-
'Create a compact design token file, not a fixed stylistic template or prose document.',
|
|
134
|
-
'',
|
|
135
|
-
'## Mission',
|
|
136
|
-
`Author docs/DESIGN.md in ${docsLanguage.toUpperCase()} language as a compact token file under 400 tokens.`,
|
|
137
|
-
'',
|
|
138
|
-
'## Deliverables',
|
|
139
|
-
'1. docs/DESIGN.md (compact token file)',
|
|
140
|
-
'',
|
|
141
|
-
'## Design Direction Process',
|
|
142
|
-
'Follow `.agent-context/prompts/bootstrap-design.md` for the three-step design direction:',
|
|
143
|
-
'1. Name your defaults (three temptations and why each flattens this product)',
|
|
144
|
-
'2. Choose a concrete anchor (googleable, specific, not a generic quality word)',
|
|
145
|
-
'3. Record creative commitments (typography, palette, motion, composition)',
|
|
146
|
-
'',
|
|
147
|
-
'## Hard Rules',
|
|
148
|
-
'1. Do not copy external style guides or anchor to famous product surfaces.',
|
|
149
|
-
'2. Use repo evidence, active brief, current docs, and current official docs for technology choices.',
|
|
150
|
-
'3. WCAG 2.2 AA is the hard floor. APCA is advisory perceptual tuning only.',
|
|
151
|
-
'4. Research current official docs before importing any new UI-related library.',
|
|
152
|
-
'5. Do not default to any component kit by habit, and do not avoid them when they fit.',
|
|
153
|
-
'6. Keep research vocabulary internal; evidence, anchor, and category-code labels must not appear in public-facing docs.',
|
|
154
|
-
'7. Treat production content as blocking: remove demo, placeholder, lorem, TODO, and scaffold copy.',
|
|
155
|
-
'',
|
|
156
|
-
'## Project Inputs',
|
|
157
|
-
`- Project name: ${discoveryAnswers.projectName}`,
|
|
158
|
-
`- Product context: ${discoveryAnswers.projectDescription}`,
|
|
159
|
-
`- Project topology decision: ${discoveryAnswers.architectureStyle}`,
|
|
160
|
-
`- Domain: ${discoveryAnswers.primaryDomain}`,
|
|
161
|
-
`- Runtime constraint: ${initContext.stackFileName === 'agent-decision-runtime.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.stackFileName)}`,
|
|
162
|
-
`- Architecture constraint: ${initContext.blueprintFileName === 'agent-decision-architecture.md' ? 'agent recommendation required before coding' : toTitleCase(initContext.blueprintFileName)}`,
|
|
163
|
-
'',
|
|
164
|
-
'## Required Execution',
|
|
165
|
-
'1. Follow the output format defined in `.agent-context/prompts/bootstrap-design.md`: Anchor, Tokens, Constraints, Previous Directions.',
|
|
166
|
-
'2. Keep docs/DESIGN.md under 400 tokens. Rationale and derivation stay in working memory.',
|
|
167
|
-
'3. Make the token file executable without screenshot dependency.',
|
|
168
|
-
'4. After the token file exists, use it as a first-class source for future UI tasks.',
|
|
169
|
-
'',
|
|
170
|
-
].join('\n');
|
|
171
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
import { ensureDirectory, pathExists } from '../utils.mjs';
|
|
5
|
-
import {
|
|
6
|
-
PROJECT_DOC_FILE_NAMES,
|
|
7
|
-
PROJECT_DOC_SYNTHESIS_PROMPT_VERSION,
|
|
8
|
-
PROJECT_DOC_TEMPLATE_VERSION,
|
|
9
|
-
UI_DESIGN_CONTRACT_FILE_NAMES,
|
|
10
|
-
} from './constants.mjs';
|
|
11
|
-
import {
|
|
12
|
-
buildSynthesisContext,
|
|
13
|
-
normalizeDocsLanguage,
|
|
14
|
-
resolveProjectDocTargets,
|
|
15
|
-
} from './discovery.mjs';
|
|
16
|
-
import {
|
|
17
|
-
shouldBootstrapDesignDocument,
|
|
18
|
-
} from './ui-scope-detection.mjs';
|
|
19
|
-
import {
|
|
20
|
-
buildDesignBootstrapPrompt,
|
|
21
|
-
buildProjectContextBootstrapPrompt,
|
|
22
|
-
} from './prompt-builders.mjs';
|
|
23
|
-
|
|
24
|
-
export async function generateProjectDocumentation(
|
|
25
|
-
targetDirectoryPath,
|
|
26
|
-
discoveryAnswers,
|
|
27
|
-
initContext,
|
|
28
|
-
options = {}
|
|
29
|
-
) {
|
|
30
|
-
const normalizedDocsLanguage = normalizeDocsLanguage(options.docsLanguage || 'en');
|
|
31
|
-
if (!normalizedDocsLanguage) {
|
|
32
|
-
throw new Error(`Unsupported docs language: ${options.docsLanguage}. Supported values: en, id`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const docsDirectoryPath = path.join(targetDirectoryPath, 'docs');
|
|
36
|
-
const promptsDirectoryPath = path.join(targetDirectoryPath, '.agent-context', 'prompts');
|
|
37
|
-
await ensureDirectory(docsDirectoryPath);
|
|
38
|
-
await ensureDirectory(promptsDirectoryPath);
|
|
39
|
-
|
|
40
|
-
const synthesisContext = buildSynthesisContext(discoveryAnswers, initContext);
|
|
41
|
-
const { requiredDocFileNames } = resolveProjectDocTargets(discoveryAnswers);
|
|
42
|
-
const expectedDocFileNames = [...requiredDocFileNames];
|
|
43
|
-
const generatedPromptFileNames = [];
|
|
44
|
-
const materializedFileNames = [];
|
|
45
|
-
const shouldCreateDesignContract = shouldBootstrapDesignDocument(discoveryAnswers, initContext);
|
|
46
|
-
|
|
47
|
-
if (shouldCreateDesignContract) {
|
|
48
|
-
for (const designContractFileName of UI_DESIGN_CONTRACT_FILE_NAMES) {
|
|
49
|
-
if (!expectedDocFileNames.includes(designContractFileName)) {
|
|
50
|
-
expectedDocFileNames.push(designContractFileName);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const projectContextPromptFileName = 'bootstrap-project-context.md';
|
|
56
|
-
const projectContextPromptContent = buildProjectContextBootstrapPrompt({
|
|
57
|
-
discoveryAnswers,
|
|
58
|
-
initContext: synthesisContext,
|
|
59
|
-
expectedDocFileNames,
|
|
60
|
-
docsLanguage: normalizedDocsLanguage,
|
|
61
|
-
});
|
|
62
|
-
await fs.writeFile(
|
|
63
|
-
path.join(promptsDirectoryPath, projectContextPromptFileName),
|
|
64
|
-
projectContextPromptContent,
|
|
65
|
-
'utf8'
|
|
66
|
-
);
|
|
67
|
-
generatedPromptFileNames.push(projectContextPromptFileName);
|
|
68
|
-
|
|
69
|
-
if (shouldCreateDesignContract) {
|
|
70
|
-
const designPromptFileName = 'bootstrap-design.md';
|
|
71
|
-
const designPromptContent = buildDesignBootstrapPrompt({
|
|
72
|
-
discoveryAnswers,
|
|
73
|
-
initContext: synthesisContext,
|
|
74
|
-
docsLanguage: normalizedDocsLanguage,
|
|
75
|
-
});
|
|
76
|
-
await fs.writeFile(path.join(promptsDirectoryPath, designPromptFileName), designPromptContent, 'utf8');
|
|
77
|
-
generatedPromptFileNames.push(designPromptFileName);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
docsDirectoryPath,
|
|
82
|
-
generatedFileNames: expectedDocFileNames,
|
|
83
|
-
generatedPromptFileNames,
|
|
84
|
-
materializedFileNames,
|
|
85
|
-
bootstrapMode: 'ai-synthesis',
|
|
86
|
-
synthesisPromptVersion: PROJECT_DOC_SYNTHESIS_PROMPT_VERSION,
|
|
87
|
-
templateVersion: PROJECT_DOC_TEMPLATE_VERSION,
|
|
88
|
-
docsLanguage: normalizedDocsLanguage,
|
|
89
|
-
discoveryAnswers,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function isDirectoryEffectivelyEmpty(targetDirectoryPath) {
|
|
94
|
-
try {
|
|
95
|
-
const directoryEntries = await fs.readdir(targetDirectoryPath);
|
|
96
|
-
const meaningfulEntries = directoryEntries.filter(
|
|
97
|
-
(entryName) => entryName !== '.git' && entryName !== '.gitignore'
|
|
98
|
-
);
|
|
99
|
-
return meaningfulEntries.length === 0;
|
|
100
|
-
} catch {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export async function hasExistingProjectDocs(targetDirectoryPath) {
|
|
106
|
-
const projectBriefPath = path.join(targetDirectoryPath, 'docs', 'project-brief.md');
|
|
107
|
-
return pathExists(projectBriefPath);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function extractTemplateVersion(documentContent) {
|
|
111
|
-
const templateVersionMatch = documentContent.match(/^(?:Template version|Versi template):\s*(.+)$/im);
|
|
112
|
-
return templateVersionMatch ? templateVersionMatch[1].trim() : null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function detectProjectDocTemplateStaleness(targetDirectoryPath) {
|
|
116
|
-
const docsDirectoryPath = path.join(targetDirectoryPath, 'docs');
|
|
117
|
-
const checkedFileNames = [];
|
|
118
|
-
const staleFiles = [];
|
|
119
|
-
|
|
120
|
-
for (const projectDocFileName of PROJECT_DOC_FILE_NAMES) {
|
|
121
|
-
const projectDocFilePath = path.join(docsDirectoryPath, projectDocFileName);
|
|
122
|
-
if (!(await pathExists(projectDocFilePath))) {
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
checkedFileNames.push(projectDocFileName);
|
|
127
|
-
const projectDocContent = await fs.readFile(projectDocFilePath, 'utf8');
|
|
128
|
-
const detectedTemplateVersion = extractTemplateVersion(projectDocContent);
|
|
129
|
-
|
|
130
|
-
if (!detectedTemplateVersion || detectedTemplateVersion !== PROJECT_DOC_TEMPLATE_VERSION) {
|
|
131
|
-
staleFiles.push({
|
|
132
|
-
fileName: projectDocFileName,
|
|
133
|
-
detectedTemplateVersion,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
hasProjectDocs: checkedFileNames.length > 0,
|
|
140
|
-
expectedTemplateVersion: PROJECT_DOC_TEMPLATE_VERSION,
|
|
141
|
-
checkedFileNames,
|
|
142
|
-
staleFiles,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI scope detection utility. Determines whether a project needs
|
|
3
|
-
* design bootstrap based on domain and blueprint signals.
|
|
4
|
-
*
|
|
5
|
-
* Extracted from design-contract/seed-signals.mjs so the design
|
|
6
|
-
* contract module can be removed without breaking this dependency.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export function shouldBootstrapDesignDocument(discoveryAnswers, initContext) {
|
|
10
|
-
const normalizedDomain = String(discoveryAnswers.primaryDomain || '').trim().toLowerCase();
|
|
11
|
-
const normalizedBlueprint = String(initContext.blueprintFileName || '').trim().toLowerCase();
|
|
12
|
-
|
|
13
|
-
const isUiDomain = normalizedDomain.includes('web')
|
|
14
|
-
|| normalizedDomain.includes('mobile')
|
|
15
|
-
|| normalizedDomain.includes('frontend')
|
|
16
|
-
|| normalizedDomain.includes('fullstack')
|
|
17
|
-
|| normalizedDomain.includes('ui');
|
|
18
|
-
|
|
19
|
-
const isBackendOnlyDomain = normalizedDomain.includes('api service')
|
|
20
|
-
|| normalizedDomain.includes('cli tool')
|
|
21
|
-
|| normalizedDomain.includes('library');
|
|
22
|
-
|
|
23
|
-
const blueprintLooksUi = normalizedBlueprint.includes('frontend')
|
|
24
|
-
|| normalizedBlueprint.includes('landing')
|
|
25
|
-
|| normalizedBlueprint.includes('ui');
|
|
26
|
-
|
|
27
|
-
if (isUiDomain) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!isBackendOnlyDomain && blueprintLooksUi) {
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project scaffolder public surface.
|
|
3
|
-
*
|
|
4
|
-
* The implementation is grouped by function under `lib/cli/project-scaffolder/`
|
|
5
|
-
* so discovery, design-contract logic, prompt building, and persistence do not
|
|
6
|
-
* collapse into one oversized module.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
PROJECT_DOC_TEMPLATE_VERSION,
|
|
11
|
-
PROJECT_DOC_SYNTHESIS_PROMPT_VERSION,
|
|
12
|
-
} from './project-scaffolder/constants.mjs';
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
normalizeDocsLanguage,
|
|
16
|
-
runProjectDiscovery,
|
|
17
|
-
loadProjectConfig,
|
|
18
|
-
} from './project-scaffolder/discovery.mjs';
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
shouldBootstrapDesignDocument,
|
|
22
|
-
} from './project-scaffolder/ui-scope-detection.mjs';
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
generateProjectDocumentation,
|
|
26
|
-
isDirectoryEffectivelyEmpty,
|
|
27
|
-
hasExistingProjectDocs,
|
|
28
|
-
detectProjectDocTemplateStaleness,
|
|
29
|
-
} from './project-scaffolder/storage.mjs';
|