@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.
Files changed (198) hide show
  1. package/.agents/plugins/marketplace.json +21 -0
  2. package/.agents/rules/agentic-senior-core.md +126 -0
  3. package/.claude-plugin/marketplace.json +17 -0
  4. package/.claude-plugin/plugin.json +17 -0
  5. package/.clinerules/agentic-senior-core.md +94 -0
  6. package/.codex-plugin/plugin.json +24 -0
  7. package/.cursor/rules/agentic-senior-core.mdc +99 -0
  8. package/.devin-plugin/plugin.json +13 -0
  9. package/.github/copilot-instructions.md +94 -0
  10. package/.github/plugin/marketplace.json +20 -0
  11. package/.github/plugin/plugin.json +16 -0
  12. package/.kiro/steering/agentic-senior-core.md +94 -0
  13. package/.openclaw/skills/asc/SKILL.md +23 -0
  14. package/.openclaw/skills/asc-audit/SKILL.md +28 -0
  15. package/.openclaw/skills/asc-review/SKILL.md +54 -0
  16. package/.opencode/plugins/agentic-senior-core.mjs +31 -0
  17. package/.windsurf/rules/agentic-senior-core.md +94 -0
  18. package/AGENTS.md +126 -179
  19. package/CONTRIBUTING.md +93 -63
  20. package/README.md +160 -111
  21. package/__init__.py +61 -0
  22. package/bin/agentic-senior-core.js +41 -43
  23. package/commands/asc-audit.md +1 -0
  24. package/commands/asc-audit.toml +2 -0
  25. package/commands/asc-help.md +9 -0
  26. package/commands/asc-help.toml +2 -0
  27. package/commands/asc-refactor.md +1 -0
  28. package/commands/asc-refactor.toml +2 -0
  29. package/commands/asc-review.md +1 -0
  30. package/commands/asc-review.toml +2 -0
  31. package/gemini-extension.json +10 -0
  32. package/hooks/copilot-hooks.json +21 -0
  33. package/hooks/hooks.json +31 -0
  34. package/hooks/session-start.js +36 -0
  35. package/hooks/subagent-start.js +38 -0
  36. package/lib/cli/commands/adapter.mjs +109 -0
  37. package/lib/cli/commands/clean.mjs +63 -0
  38. package/lib/cli/commands/status.mjs +94 -0
  39. package/package.json +43 -67
  40. package/plugin.yaml +16 -0
  41. package/scripts/uninstall.js +38 -0
  42. package/skills/asc/SKILL.md +16 -0
  43. package/skills/asc-audit/SKILL.md +28 -0
  44. package/skills/asc-refactor/SKILL.md +35 -0
  45. package/skills/asc-review/SKILL.md +54 -0
  46. package/.agent-context/policies/llm-judge-threshold.json +0 -29
  47. package/.agent-context/prompts/bootstrap-design.md +0 -63
  48. package/.agent-context/prompts/compact-natural-mode.md +0 -100
  49. package/.agent-context/prompts/init-project.md +0 -60
  50. package/.agent-context/prompts/refactor.md +0 -38
  51. package/.agent-context/prompts/review-code.md +0 -31
  52. package/.agent-context/review-checklists/architecture-review.md +0 -57
  53. package/.agent-context/review-checklists/pr-checklist.md +0 -136
  54. package/.agent-context/rules/api-docs.md +0 -24
  55. package/.agent-context/rules/api-versioning.md +0 -16
  56. package/.agent-context/rules/architecture.md +0 -33
  57. package/.agent-context/rules/background-jobs.md +0 -17
  58. package/.agent-context/rules/config-and-flags.md +0 -16
  59. package/.agent-context/rules/database-design.md +0 -18
  60. package/.agent-context/rules/docker-runtime.md +0 -17
  61. package/.agent-context/rules/error-handling.md +0 -16
  62. package/.agent-context/rules/event-driven.md +0 -16
  63. package/.agent-context/rules/frontend-architecture.md +0 -54
  64. package/.agent-context/rules/microservices.md +0 -16
  65. package/.agent-context/rules/migrations.md +0 -16
  66. package/.agent-context/rules/observability.md +0 -16
  67. package/.agent-context/rules/performance.md +0 -16
  68. package/.agent-context/rules/realtime.md +0 -16
  69. package/.agent-context/rules/resilience.md +0 -18
  70. package/.agent-context/rules/security.md +0 -18
  71. package/.agent-context/rules/testing.md +0 -16
  72. package/.agent-context/state/README.md +0 -25
  73. package/.agent-context/state/architecture-map.md +0 -40
  74. package/.agent-context/state/benchmark-comparison-schema.json +0 -181
  75. package/.agent-context/state/benchmark-reproducibility.json +0 -87
  76. package/.agent-context/state/benchmark-thresholds.json +0 -10
  77. package/.agent-context/state/benchmark-writer-judge-config.json +0 -58
  78. package/.agent-context/state/dependency-map.md +0 -41
  79. package/.agent-context/state/memory-adapter-contract.json +0 -52
  80. package/.agent-context/state/memory-schema-v1.json +0 -88
  81. package/GEMINI.md +0 -1
  82. package/benchmarks/README.md +0 -60
  83. package/benchmarks/compact-natural-mode/fixtures.mjs +0 -359
  84. package/benchmarks/compact-natural-mode/scorer.mjs +0 -331
  85. package/benchmarks/runtime-token-saver/fixtures.mjs +0 -836
  86. package/lib/cli/adaptive-context/catalog.mjs +0 -390
  87. package/lib/cli/adaptive-context/file-signals.mjs +0 -100
  88. package/lib/cli/adaptive-context/implications.mjs +0 -44
  89. package/lib/cli/adaptive-context.mjs +0 -365
  90. package/lib/cli/audits/typography-palette-anti-repeat/color-utils.mjs +0 -156
  91. package/lib/cli/audits/typography-palette-anti-repeat/file-scanner.mjs +0 -103
  92. package/lib/cli/audits/typography-palette-anti-repeat/typography-utils.mjs +0 -70
  93. package/lib/cli/audits/typography-palette-anti-repeat-audit.mjs +0 -239
  94. package/lib/cli/backup.mjs +0 -210
  95. package/lib/cli/commands/audit-design-anti-repeat.mjs +0 -39
  96. package/lib/cli/commands/context.mjs +0 -140
  97. package/lib/cli/commands/init/project-context.mjs +0 -60
  98. package/lib/cli/commands/init/runtime-environment.mjs +0 -59
  99. package/lib/cli/commands/init/setup-decisions.mjs +0 -83
  100. package/lib/cli/commands/init.mjs +0 -654
  101. package/lib/cli/commands/launch.mjs +0 -76
  102. package/lib/cli/commands/optimize.mjs +0 -284
  103. package/lib/cli/commands/rollback.mjs +0 -64
  104. package/lib/cli/commands/upgrade/token-optimization-state.mjs +0 -51
  105. package/lib/cli/commands/upgrade.mjs +0 -451
  106. package/lib/cli/compiler.mjs +0 -570
  107. package/lib/cli/constants.mjs +0 -136
  108. package/lib/cli/detector/constants.mjs +0 -135
  109. package/lib/cli/detector/design-evidence/collector.mjs +0 -256
  110. package/lib/cli/detector/design-evidence/constants.mjs +0 -39
  111. package/lib/cli/detector/design-evidence/file-traversal.mjs +0 -83
  112. package/lib/cli/detector/design-evidence/structured-attribute-evidence.mjs +0 -117
  113. package/lib/cli/detector/design-evidence/summary.mjs +0 -109
  114. package/lib/cli/detector/design-evidence/utility-helpers.mjs +0 -122
  115. package/lib/cli/detector/design-evidence.mjs +0 -25
  116. package/lib/cli/detector/stack-detection.mjs +0 -243
  117. package/lib/cli/detector/ui-signals.mjs +0 -150
  118. package/lib/cli/detector/workspace-scan.mjs +0 -177
  119. package/lib/cli/detector.mjs +0 -23
  120. package/lib/cli/init-detection-flow.mjs +0 -48
  121. package/lib/cli/init-options.mjs +0 -237
  122. package/lib/cli/init-selection.mjs +0 -29
  123. package/lib/cli/memory-continuity.mjs +0 -537
  124. package/lib/cli/preflight.mjs +0 -76
  125. package/lib/cli/project-scaffolder/constants.mjs +0 -69
  126. package/lib/cli/project-scaffolder/discovery.mjs +0 -272
  127. package/lib/cli/project-scaffolder/prompt-builders.mjs +0 -171
  128. package/lib/cli/project-scaffolder/storage.mjs +0 -144
  129. package/lib/cli/project-scaffolder/ui-scope-detection.mjs +0 -36
  130. package/lib/cli/project-scaffolder.mjs +0 -29
  131. package/lib/cli/rollback.mjs +0 -66
  132. package/lib/cli/token-optimization.mjs +0 -486
  133. package/lib/cli/utils/filesystem.mjs +0 -81
  134. package/lib/cli/utils/managed-surface.mjs +0 -280
  135. package/lib/cli/utils/prompting.mjs +0 -44
  136. package/lib/cli/utils.mjs +0 -479
  137. package/mcp.json +0 -134
  138. package/scripts/adaptive-context/fixtures.mjs +0 -183
  139. package/scripts/adaptive-context-benchmark.mjs +0 -9
  140. package/scripts/ascx-runtime-token-saver-benchmark.mjs +0 -9
  141. package/scripts/audit-cache-layer-contract.mjs +0 -263
  142. package/scripts/audit-caching-scope-hygiene.mjs +0 -268
  143. package/scripts/audit-file-size.mjs +0 -219
  144. package/scripts/audit-reflection-citations.mjs +0 -163
  145. package/scripts/audit-release-bundle.mjs +0 -170
  146. package/scripts/audit-rule-id-uniqueness.mjs +0 -313
  147. package/scripts/audit-typography-palette-anti-repeat.mjs +0 -120
  148. package/scripts/benchmark-evidence-bundle.mjs +0 -645
  149. package/scripts/benchmark-gate.mjs +0 -121
  150. package/scripts/benchmark-intelligence.mjs +0 -33
  151. package/scripts/benchmark-writer-judge-matrix.mjs +0 -379
  152. package/scripts/build-release-benchmark-bundle.mjs +0 -202
  153. package/scripts/bump-version.mjs +0 -103
  154. package/scripts/clean-local-artifacts.mjs +0 -78
  155. package/scripts/compact-natural-mode-benchmark.mjs +0 -9
  156. package/scripts/context-triggered-audit.mjs +0 -391
  157. package/scripts/detection-benchmark.mjs +0 -127
  158. package/scripts/docs-quality-drift-report.mjs +0 -358
  159. package/scripts/documentation-boundary-audit.mjs +0 -305
  160. package/scripts/explain-on-demand-audit.mjs +0 -427
  161. package/scripts/forbidden-content-check.mjs +0 -123
  162. package/scripts/frontend-usability-audit.mjs +0 -243
  163. package/scripts/generate-sbom.mjs +0 -61
  164. package/scripts/governance-weekly-report.mjs +0 -466
  165. package/scripts/llm-judge/checklist-loader.mjs +0 -45
  166. package/scripts/llm-judge/constants.mjs +0 -66
  167. package/scripts/llm-judge/diff-collection.mjs +0 -74
  168. package/scripts/llm-judge/prompting.mjs +0 -78
  169. package/scripts/llm-judge/providers.mjs +0 -111
  170. package/scripts/llm-judge/verdict.mjs +0 -134
  171. package/scripts/llm-judge.mjs +0 -200
  172. package/scripts/memory-continuity-benchmark.mjs +0 -322
  173. package/scripts/quality-trend-report.mjs +0 -289
  174. package/scripts/release-gate/audit-checks.mjs +0 -441
  175. package/scripts/release-gate/constants.mjs +0 -53
  176. package/scripts/release-gate/runtime.mjs +0 -63
  177. package/scripts/release-gate/static-checks.mjs +0 -182
  178. package/scripts/release-gate.mjs +0 -42
  179. package/scripts/rules-guardian-audit.mjs +0 -580
  180. package/scripts/single-source-lazy-loading-audit.mjs +0 -449
  181. package/scripts/sync-thin-adapters.mjs +0 -72
  182. package/scripts/token-optimization-benchmark.mjs +0 -252
  183. package/scripts/ui-design-judge/constants.mjs +0 -13
  184. package/scripts/ui-design-judge/design-execution-summary.mjs +0 -81
  185. package/scripts/ui-design-judge/git-input.mjs +0 -134
  186. package/scripts/ui-design-judge/prompting.mjs +0 -52
  187. package/scripts/ui-design-judge/providers.mjs +0 -102
  188. package/scripts/ui-design-judge/reporting.mjs +0 -183
  189. package/scripts/ui-design-judge/rubric-calibration.mjs +0 -214
  190. package/scripts/ui-design-judge/rubric-goldset.json +0 -188
  191. package/scripts/ui-design-judge.mjs +0 -319
  192. package/scripts/ui-rubric-calibration.mjs +0 -35
  193. package/scripts/validate/config.mjs +0 -519
  194. package/scripts/validate/coverage-checks.mjs +0 -446
  195. package/scripts/validate/file-structure.mjs +0 -162
  196. package/scripts/validate/markdown-content.mjs +0 -109
  197. package/scripts/validate/project-metadata.mjs +0 -166
  198. 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';