@ryuenn3123/agentic-senior-core 3.0.19 → 3.0.21

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 (77) hide show
  1. package/.agent-context/prompts/bootstrap-design.md +96 -103
  2. package/.agent-context/prompts/init-project.md +32 -100
  3. package/.agent-context/prompts/refactor.md +22 -44
  4. package/.agent-context/prompts/review-code.md +28 -52
  5. package/.agent-context/review-checklists/architecture-review.md +31 -62
  6. package/.agent-context/review-checklists/pr-checklist.md +74 -108
  7. package/.agent-context/rules/api-docs.md +18 -206
  8. package/.agent-context/rules/architecture.md +40 -207
  9. package/.agent-context/rules/database-design.md +10 -199
  10. package/.agent-context/rules/docker-runtime.md +5 -5
  11. package/.agent-context/rules/efficiency-vs-hype.md +11 -149
  12. package/.agent-context/rules/error-handling.md +9 -231
  13. package/.agent-context/rules/event-driven.md +17 -221
  14. package/.agent-context/rules/frontend-architecture.md +74 -119
  15. package/.agent-context/rules/git-workflow.md +1 -1
  16. package/.agent-context/rules/microservices.md +28 -161
  17. package/.agent-context/rules/naming-conv.md +8 -138
  18. package/.agent-context/rules/performance.md +9 -175
  19. package/.agent-context/rules/realtime.md +11 -44
  20. package/.agent-context/rules/security.md +11 -295
  21. package/.agent-context/rules/testing.md +9 -174
  22. package/.agent-context/state/benchmark-analysis.json +3 -3
  23. package/.agent-context/state/memory-continuity-benchmark.json +1 -1
  24. package/.agent-context/state/onboarding-report.json +71 -11
  25. package/.agents/workflows/init-project.md +7 -24
  26. package/.agents/workflows/refactor.md +7 -24
  27. package/.agents/workflows/review-code.md +7 -24
  28. package/.cursorrules +22 -21
  29. package/.gemini/instructions.md +2 -2
  30. package/.github/copilot-instructions.md +2 -2
  31. package/.instructions.md +112 -213
  32. package/.windsurfrules +22 -21
  33. package/AGENTS.md +4 -4
  34. package/CONTRIBUTING.md +13 -22
  35. package/README.md +6 -20
  36. package/lib/cli/commands/init.mjs +102 -148
  37. package/lib/cli/commands/launch.mjs +3 -3
  38. package/lib/cli/commands/optimize.mjs +14 -4
  39. package/lib/cli/commands/upgrade.mjs +25 -23
  40. package/lib/cli/compiler.mjs +96 -62
  41. package/lib/cli/constants.mjs +28 -136
  42. package/lib/cli/detector/design-evidence.mjs +189 -6
  43. package/lib/cli/detector.mjs +6 -7
  44. package/lib/cli/init-detection-flow.mjs +10 -93
  45. package/lib/cli/init-selection.mjs +2 -68
  46. package/lib/cli/project-scaffolder/constants.mjs +1 -1
  47. package/lib/cli/project-scaffolder/design-contract.mjs +183 -108
  48. package/lib/cli/project-scaffolder/discovery.mjs +36 -82
  49. package/lib/cli/project-scaffolder/prompt-builders.mjs +45 -55
  50. package/lib/cli/project-scaffolder/storage.mjs +0 -2
  51. package/lib/cli/token-optimization.mjs +1 -1
  52. package/lib/cli/utils.mjs +75 -9
  53. package/package.json +2 -2
  54. package/scripts/detection-benchmark.mjs +4 -15
  55. package/scripts/documentation-boundary-audit.mjs +9 -9
  56. package/scripts/explain-on-demand-audit.mjs +11 -11
  57. package/scripts/forbidden-content-check.mjs +9 -9
  58. package/scripts/frontend-usability-audit.mjs +45 -35
  59. package/scripts/llm-judge.mjs +1 -1
  60. package/scripts/mcp-server/constants.mjs +2 -2
  61. package/scripts/mcp-server/tool-registry.mjs +1 -1
  62. package/scripts/release-gate/audit-checks.mjs +22 -7
  63. package/scripts/release-gate/static-checks.mjs +5 -5
  64. package/scripts/release-gate.mjs +1 -1
  65. package/scripts/rules-guardian-audit.mjs +14 -13
  66. package/scripts/single-source-lazy-loading-audit.mjs +3 -3
  67. package/scripts/sync-thin-adapters.mjs +5 -5
  68. package/scripts/ui-design-judge/design-execution-summary.mjs +27 -1
  69. package/scripts/ui-design-judge/prompting.mjs +5 -5
  70. package/scripts/ui-design-judge/reporting.mjs +3 -1
  71. package/scripts/ui-design-judge/rubric-calibration.mjs +8 -5
  72. package/scripts/ui-design-judge/rubric-goldset.json +2 -2
  73. package/scripts/ui-design-judge.mjs +75 -7
  74. package/scripts/validate/config.mjs +138 -48
  75. package/scripts/validate/coverage-checks.mjs +32 -7
  76. package/scripts/validate.mjs +8 -4
  77. package/lib/cli/architect.mjs +0 -431
@@ -1,431 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import { existsSync, readFileSync } from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
-
7
- import { BLUEPRINT_RECOMMENDATIONS } from './constants.mjs';
8
- import { ensureDirectory, pathExists, toTitleCase } from './utils.mjs';
9
-
10
- const ARCHITECT_MODULE_FILE_PATH = fileURLToPath(import.meta.url);
11
- const ARCHITECT_PACKAGE_ROOT = path.resolve(path.dirname(ARCHITECT_MODULE_FILE_PATH), '..', '..');
12
-
13
- const ARCHITECT_PREFERENCE_FILE_PATH = process.env.AGENTIC_ARCHITECT_PREF_FILE
14
- ? path.resolve(process.env.AGENTIC_ARCHITECT_PREF_FILE)
15
- : path.join(os.homedir(), '.agentic-senior-core', 'architect-preferences.json');
16
-
17
- // Keyword hints — low-confidence bias only, not authoritative research.
18
- const STACK_SIGNAL_WEIGHTS = {
19
- 'typescript.md': [
20
- { term: 'typescript', weight: 0.9 },
21
- { term: 'javascript', weight: 0.8 },
22
- { term: 'node', weight: 0.55 },
23
- { term: 'next.js', weight: 0.7 },
24
- { term: 'nextjs', weight: 0.7 },
25
- { term: 'react', weight: 0.45 },
26
- { term: 'web app', weight: 0.45 },
27
- { term: 'frontend', weight: 0.4 },
28
- { term: 'dashboard', weight: 0.35 },
29
- ],
30
- 'python.md': [
31
- { term: 'python', weight: 0.95 },
32
- { term: 'fastapi', weight: 0.8 },
33
- { term: 'machine learning', weight: 0.8 },
34
- { term: 'ml', weight: 0.4 },
35
- { term: 'data', weight: 0.45 },
36
- { term: 'ai', weight: 0.45 },
37
- { term: 'automation', weight: 0.35 },
38
- { term: 'analytics', weight: 0.35 },
39
- ],
40
- 'java.md': [
41
- { term: 'java', weight: 0.9 },
42
- { term: 'spring', weight: 0.75 },
43
- { term: 'enterprise', weight: 0.45 },
44
- { term: 'bank', weight: 0.35 },
45
- { term: 'regulated', weight: 0.35 },
46
- { term: 'jvm', weight: 0.35 },
47
- ],
48
- 'php.md': [
49
- { term: 'php', weight: 0.9 },
50
- { term: 'laravel', weight: 0.8 },
51
- { term: 'cms', weight: 0.4 },
52
- { term: 'wordpress', weight: 0.35 },
53
- ],
54
- 'go.md': [
55
- { term: 'go', weight: 0.5 },
56
- { term: 'golang', weight: 0.9 },
57
- { term: 'high throughput', weight: 0.55 },
58
- { term: 'microservice', weight: 0.45 },
59
- { term: 'kubernetes', weight: 0.45 },
60
- { term: 'latency', weight: 0.35 },
61
- { term: 'concurrency', weight: 0.35 },
62
- ],
63
- 'csharp.md': [
64
- { term: '.net', weight: 0.9 },
65
- { term: 'dotnet', weight: 0.9 },
66
- { term: 'c#', weight: 0.75 },
67
- { term: 'asp.net', weight: 0.8 },
68
- { term: 'microsoft', weight: 0.35 },
69
- ],
70
- 'rust.md': [
71
- { term: 'rust', weight: 0.9 },
72
- { term: 'systems', weight: 0.45 },
73
- { term: 'performance', weight: 0.35 },
74
- { term: 'memory safety', weight: 0.4 },
75
- { term: 'low latency', weight: 0.4 },
76
- ],
77
- 'ruby.md': [
78
- { term: 'ruby', weight: 0.9 },
79
- { term: 'rails', weight: 0.8 },
80
- { term: 'monolith', weight: 0.35 },
81
- { term: 'crud', weight: 0.3 },
82
- ],
83
- 'react-native.md': [
84
- { term: 'react native', weight: 0.9 },
85
- { term: 'mobile', weight: 0.4 },
86
- { term: 'android', weight: 0.35 },
87
- { term: 'ios', weight: 0.35 },
88
- { term: 'cross-platform', weight: 0.4 },
89
- ],
90
- 'flutter.md': [
91
- { term: 'flutter', weight: 0.95 },
92
- { term: 'dart', weight: 0.8 },
93
- { term: 'mobile', weight: 0.4 },
94
- { term: 'android', weight: 0.35 },
95
- { term: 'ios', weight: 0.35 },
96
- { term: 'cross-platform', weight: 0.4 },
97
- ],
98
- };
99
-
100
- const STACK_TRADEOFF_SUMMARIES = {
101
- 'typescript.md': 'great fullstack velocity, but dependency churn and runtime startup need discipline.',
102
- 'python.md': 'fast AI and API delivery, but strict latency targets may need extra optimization.',
103
- 'java.md': 'strong enterprise reliability, but setup and boilerplate are heavier.',
104
- 'php.md': 'rapid web product iteration, but architecture boundaries must be guarded early.',
105
- 'go.md': 'excellent throughput and operational simplicity, but abstractions are intentionally minimal.',
106
- 'csharp.md': 'strong for Microsoft-centered teams, but cross-platform tooling choices should be explicit.',
107
- 'rust.md': 'top performance and safety, but development ramp-up is steeper.',
108
- 'ruby.md': 'high productivity for product teams, but scaling strategy should be planned early.',
109
- 'react-native.md': 'single codebase for mobile, but native edge cases still require platform attention.',
110
- 'flutter.md': 'consistent UI across mobile platforms, but ecosystem fit should be checked per package.',
111
- };
112
-
113
- function resolveConfidenceLabel(confidenceScore) {
114
- if (confidenceScore >= 0.85) {
115
- return 'high';
116
- }
117
-
118
- if (confidenceScore >= 0.7) {
119
- return 'medium';
120
- }
121
-
122
- return 'low';
123
- }
124
-
125
- function resolveRecommendedBlueprintFileName(stackFileName, blueprintFileNames) {
126
- const recommendedBlueprintFileName = BLUEPRINT_RECOMMENDATIONS[stackFileName] || null;
127
- if (recommendedBlueprintFileName && blueprintFileNames.includes(recommendedBlueprintFileName)) {
128
- return recommendedBlueprintFileName;
129
- }
130
-
131
- return blueprintFileNames[0] || null;
132
- }
133
-
134
- /**
135
- * Generates a repo-grounded architecture brief based on project description
136
- * keywords and repository marker detection. This is an offline brief —
137
- * for ecosystem-level research, the consuming agent should perform live
138
- * web research rather than relying on stale local snapshots.
139
- */
140
- export function recommendArchitecture({
141
- projectDescription,
142
- projectDetection,
143
- stackFileNames,
144
- blueprintFileNames,
145
- }) {
146
- const normalizedDescription = String(projectDescription || '').trim().toLowerCase();
147
- const effectiveDescription = normalizedDescription || 'general software project';
148
- const uncertaintyNotes = [];
149
-
150
- // Repo marker detection scoring (grounded in actual project files).
151
- const detectionScoreByStackFileName = new Map();
152
- for (const rankedCandidate of projectDetection?.rankedCandidates || []) {
153
- const confidenceScore = Number(rankedCandidate.confidenceScore) || 0;
154
- if (confidenceScore <= 0) {
155
- continue;
156
- }
157
-
158
- detectionScoreByStackFileName.set(
159
- rankedCandidate.stackFileName,
160
- confidenceScore * 1.75
161
- );
162
- }
163
-
164
- // Keyword hint scoring (low-confidence bias, not research).
165
- const scoredStackCandidates = stackFileNames.map((stackFileName) => {
166
- const configuredSignals = STACK_SIGNAL_WEIGHTS[stackFileName] || [];
167
- const matchedKeywords = [];
168
- let keywordScore = 0;
169
-
170
- for (const configuredSignal of configuredSignals) {
171
- if (!effectiveDescription.includes(configuredSignal.term)) {
172
- continue;
173
- }
174
-
175
- keywordScore += configuredSignal.weight;
176
- matchedKeywords.push(configuredSignal.term);
177
- }
178
-
179
- const detectionScore = detectionScoreByStackFileName.get(stackFileName) || 0;
180
- const totalScore = 0.2 + keywordScore + detectionScore;
181
-
182
- return {
183
- stackFileName,
184
- totalScore,
185
- keywordScore,
186
- detectionScore,
187
- matchedKeywords,
188
- };
189
- }).sort((leftCandidate, rightCandidate) => rightCandidate.totalScore - leftCandidate.totalScore);
190
-
191
- // Fallback when no candidates can be scored.
192
- if (scoredStackCandidates.length === 0) {
193
- const fallbackStackFileName = stackFileNames.includes('typescript.md')
194
- ? 'typescript.md'
195
- : stackFileNames[0] || 'typescript.md';
196
- const fallbackBlueprintFileName = resolveRecommendedBlueprintFileName(fallbackStackFileName, blueprintFileNames);
197
-
198
- return {
199
- briefType: 'offline',
200
- projectDescription: String(projectDescription || '').trim(),
201
- recommendedStackFileName: fallbackStackFileName,
202
- recommendedBlueprintFileName: fallbackBlueprintFileName,
203
- confidenceLabel: 'low',
204
- confidenceScore: 0.35,
205
- rationaleSentences: [
206
- `Defaulting to ${toTitleCase(fallbackStackFileName)} with ${toTitleCase(fallbackBlueprintFileName)} as a safe fallback.`,
207
- 'No keyword or detection signals were strong enough for a grounded recommendation.',
208
- 'For ecosystem-level validation, perform live web research before committing to this stack.',
209
- ],
210
- alternatives: [],
211
- uncertaintyNotes: [
212
- 'This is an offline brief based on keyword hints and repo markers only.',
213
- 'Ecosystem fitness was not verified — the agent should research before finalizing.',
214
- ],
215
- signalSummary: 'fallback (no strong signals)',
216
- failureModes: {
217
- lowConfidence: true,
218
- dataConflict: false,
219
- repeatedOverride: false,
220
- },
221
- };
222
- }
223
-
224
- const strongestCandidate = scoredStackCandidates[0];
225
- const secondCandidate = scoredStackCandidates[1] || null;
226
- const scoreGap = secondCandidate
227
- ? strongestCandidate.totalScore - secondCandidate.totalScore
228
- : strongestCandidate.totalScore;
229
-
230
- let confidenceScore = 0.55
231
- + Math.min(strongestCandidate.totalScore / 8, 0.25)
232
- + Math.min(Math.max(scoreGap, 0) / 3, 0.18);
233
-
234
- if (strongestCandidate.matchedKeywords.length === 0) {
235
- confidenceScore -= 0.2;
236
- }
237
-
238
- if (secondCandidate && scoreGap < 0.18) {
239
- confidenceScore -= 0.1;
240
- }
241
-
242
- confidenceScore = Math.min(Math.max(confidenceScore, 0.35), 0.97);
243
-
244
- const confidenceLabel = resolveConfidenceLabel(confidenceScore);
245
- const lowConfidence = confidenceScore < 0.7;
246
- const dataConflict = Boolean(secondCandidate && scoreGap < 0.18);
247
-
248
- if (lowConfidence) {
249
- uncertaintyNotes.push('Low confidence: description did not map strongly to a single stack profile.');
250
- }
251
-
252
- if (dataConflict) {
253
- uncertaintyNotes.push('Data conflict: top stack candidates are close, so trade-offs need manual confirmation.');
254
- }
255
-
256
- // Offline briefs should always be transparent about their grounding source.
257
- uncertaintyNotes.push(
258
- 'This brief is grounded in repo markers and keyword hints only. '
259
- + 'For ecosystem-level validation, the agent should perform live web research.'
260
- );
261
-
262
- const recommendedStackFileName = strongestCandidate.stackFileName;
263
- const recommendedBlueprintFileName = resolveRecommendedBlueprintFileName(recommendedStackFileName, blueprintFileNames);
264
-
265
- const signalSummaryParts = [];
266
- if (strongestCandidate.matchedKeywords.length > 0) {
267
- signalSummaryParts.push(`keywords: ${strongestCandidate.matchedKeywords.slice(0, 4).join(', ')}`);
268
- }
269
- if (strongestCandidate.detectionScore > 0) {
270
- signalSummaryParts.push(`repo detection: ${strongestCandidate.detectionScore.toFixed(2)}`);
271
- }
272
- const signalSummary = signalSummaryParts.length > 0
273
- ? signalSummaryParts.join('; ')
274
- : 'weak signals only';
275
-
276
- const rationaleSentences = [
277
- `Stack brief: ${toTitleCase(recommendedStackFileName)} with ${toTitleCase(recommendedBlueprintFileName)}.`,
278
- `Grounding signals: ${signalSummary}.`,
279
- `Main trade-off: ${STACK_TRADEOFF_SUMMARIES[recommendedStackFileName] || 'validate ecosystem fit before production rollout.'}`,
280
- ];
281
-
282
- if (lowConfidence) {
283
- rationaleSentences.push('Confidence is low — review alternatives and perform live research before finalizing.');
284
- }
285
-
286
- const alternatives = scoredStackCandidates
287
- .slice(1, 3)
288
- .map((stackCandidate) => {
289
- const alternativeBlueprintFileName = resolveRecommendedBlueprintFileName(stackCandidate.stackFileName, blueprintFileNames);
290
- return {
291
- stackFileName: stackCandidate.stackFileName,
292
- blueprintFileName: alternativeBlueprintFileName,
293
- oneLineTradeoff: STACK_TRADEOFF_SUMMARIES[stackCandidate.stackFileName]
294
- || 'validate fit with your runtime and team constraints.',
295
- evidenceSummary: `keyword=${stackCandidate.keywordScore.toFixed(2)}, detection=${stackCandidate.detectionScore.toFixed(2)}`,
296
- };
297
- });
298
-
299
- return {
300
- briefType: 'offline',
301
- projectDescription: String(projectDescription || '').trim(),
302
- recommendedStackFileName,
303
- recommendedBlueprintFileName,
304
- confidenceLabel,
305
- confidenceScore: Number(confidenceScore.toFixed(2)),
306
- rationaleSentences,
307
- alternatives,
308
- uncertaintyNotes,
309
- signalSummary,
310
- failureModes: {
311
- lowConfidence,
312
- dataConflict,
313
- repeatedOverride: false,
314
- },
315
- };
316
- }
317
-
318
- export function formatArchitectureRecommendation(architectureRecommendation) {
319
- const outputLines = [
320
- '\nArchitecture brief (offline, repo-grounded):',
321
- `- Stack: ${toTitleCase(architectureRecommendation.recommendedStackFileName)}`,
322
- `- Blueprint: ${toTitleCase(architectureRecommendation.recommendedBlueprintFileName)}`,
323
- `- Confidence: ${architectureRecommendation.confidenceLabel} (${architectureRecommendation.confidenceScore})`,
324
- '- Rationale:',
325
- ...architectureRecommendation.rationaleSentences.map((sentence, sentenceIndex) => ` ${sentenceIndex + 1}. ${sentence}`),
326
- '- Alternatives:',
327
- ];
328
-
329
- if (architectureRecommendation.alternatives.length === 0) {
330
- outputLines.push(' 1. No strong alternatives detected from current input signals.');
331
- } else {
332
- outputLines.push(
333
- ...architectureRecommendation.alternatives.map(
334
- (alternative, alternativeIndex) => ` ${alternativeIndex + 1}. ${toTitleCase(alternative.stackFileName)} + ${toTitleCase(alternative.blueprintFileName)}: ${alternative.oneLineTradeoff}`
335
- )
336
- );
337
- }
338
-
339
- if (architectureRecommendation.uncertaintyNotes.length > 0) {
340
- outputLines.push('- Uncertainty notes:');
341
- outputLines.push(
342
- ...architectureRecommendation.uncertaintyNotes.map(
343
- (uncertaintyNote, uncertaintyIndex) => ` ${uncertaintyIndex + 1}. ${uncertaintyNote}`
344
- )
345
- );
346
- }
347
-
348
- const cautionLabels = [];
349
- if (architectureRecommendation.failureModes.lowConfidence) {
350
- cautionLabels.push('low-confidence');
351
- }
352
- if (architectureRecommendation.failureModes.dataConflict) {
353
- cautionLabels.push('data-conflict');
354
- }
355
- if (architectureRecommendation.failureModes.repeatedOverride) {
356
- cautionLabels.push('repeated-override');
357
- }
358
-
359
- if (cautionLabels.length > 0) {
360
- outputLines.push(`- Caution labels: ${cautionLabels.join(', ')}`);
361
- }
362
-
363
- return outputLines.join('\n');
364
- }
365
-
366
- export async function readArchitectPreferenceState() {
367
- if (!(await pathExists(ARCHITECT_PREFERENCE_FILE_PATH))) {
368
- return null;
369
- }
370
-
371
- try {
372
- const rawPreferenceContent = await fs.readFile(ARCHITECT_PREFERENCE_FILE_PATH, 'utf8');
373
- const parsedPreferencePayload = JSON.parse(rawPreferenceContent);
374
- const parsedPreferenceState = parsedPreferencePayload?.preference;
375
-
376
- if (!parsedPreferenceState?.preferredStackFileName) {
377
- return null;
378
- }
379
-
380
- return {
381
- preferredStackFileName: parsedPreferenceState.preferredStackFileName,
382
- preferredBlueprintFileName: parsedPreferenceState.preferredBlueprintFileName || null,
383
- overrideCount: Number(parsedPreferenceState.overrideCount) || 0,
384
- lastOverrideAt: parsedPreferenceState.lastOverrideAt || null,
385
- };
386
- } catch {
387
- return null;
388
- }
389
- }
390
-
391
- export function createUpdatedArchitectPreference(currentPreferenceState, {
392
- selectedStackFileName,
393
- selectedBlueprintFileName,
394
- }) {
395
- const currentOverrideCount = Number(currentPreferenceState?.overrideCount) || 0;
396
-
397
- return {
398
- preferredStackFileName: selectedStackFileName,
399
- preferredBlueprintFileName: selectedBlueprintFileName,
400
- overrideCount: currentOverrideCount + 1,
401
- lastOverrideAt: new Date().toISOString(),
402
- };
403
- }
404
-
405
- export function shouldApplyRepeatedOverridePreference(preferenceState, recommendedStackFileName) {
406
- if (!preferenceState?.preferredStackFileName) {
407
- return false;
408
- }
409
-
410
- if ((Number(preferenceState.overrideCount) || 0) < 2) {
411
- return false;
412
- }
413
-
414
- return preferenceState.preferredStackFileName !== recommendedStackFileName;
415
- }
416
-
417
- export async function writeArchitectPreferenceState(preferenceState) {
418
- const preferencePayload = {
419
- schemaVersion: '1.0.0',
420
- updatedAt: new Date().toISOString(),
421
- preference: {
422
- preferredStackFileName: preferenceState.preferredStackFileName,
423
- preferredBlueprintFileName: preferenceState.preferredBlueprintFileName,
424
- overrideCount: preferenceState.overrideCount,
425
- lastOverrideAt: preferenceState.lastOverrideAt,
426
- },
427
- };
428
-
429
- await ensureDirectory(path.dirname(ARCHITECT_PREFERENCE_FILE_PATH));
430
- await fs.writeFile(ARCHITECT_PREFERENCE_FILE_PATH, JSON.stringify(preferencePayload, null, 2) + '\n', 'utf8');
431
- }