sdg-agents 1.0.5

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 (130) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +161 -0
  3. package/package.json +88 -0
  4. package/src/assets/dev-guides/agent-deep-flow.md +139 -0
  5. package/src/assets/dev-guides/prompt-tracks/00-lite-mode/01-project-scope-and-mvp.md +45 -0
  6. package/src/assets/dev-guides/prompt-tracks/00-lite-mode/02-stack-and-data-model.md +56 -0
  7. package/src/assets/dev-guides/prompt-tracks/00-lite-mode/03-external-integrations.md +44 -0
  8. package/src/assets/dev-guides/prompt-tracks/00-lite-mode/04-launch-checklist.md +26 -0
  9. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/01-project-vision.md +77 -0
  10. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/02-problem-definition.md +63 -0
  11. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/03-success-metrics.md +48 -0
  12. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/05-engineering-culture-and-silos.md +41 -0
  13. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/06-foundation-approval.md +57 -0
  14. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/01-tech-stack.md +62 -0
  15. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/02-local-environment.md +50 -0
  16. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/03-version-control-and-tracking.md +65 -0
  17. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/04-hello-world-validation.md +37 -0
  18. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/05-setup-approval.md +61 -0
  19. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/01-folder-structure.md +49 -0
  20. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/02-design-patterns.md +59 -0
  21. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/03-apis-and-communication.md +55 -0
  22. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/04-security-and-access.md +63 -0
  23. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/05-security-audit.md +64 -0
  24. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/06-design-system-ux.md +72 -0
  25. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/07-ai-strategy.md +72 -0
  26. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/08-observability.md +65 -0
  27. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/09-technical-documentation.md +64 -0
  28. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/10-infrastructure-and-costs.md +40 -0
  29. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/11-data-privacy-compliance.md +41 -0
  30. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/12-performance-and-scale.md +46 -0
  31. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/13-disaster-recovery.md +39 -0
  32. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/14-architecture-approval.md +81 -0
  33. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/01-ci-cd-pipeline.md +49 -0
  34. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/02-quality-standards.md +46 -0
  35. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/03-delivery-approval.md +58 -0
  36. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/00-feature-template.md +30 -0
  37. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/01-context-and-scope.md +46 -0
  38. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/02-business-rules.md +39 -0
  39. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/03-architecture-and-design.md +50 -0
  40. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/04-testing-strategy.md +48 -0
  41. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/05-implementation-plan.md +45 -0
  42. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/06-feature-approval.md +46 -0
  43. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/01-rfcs-and-changes.md +63 -0
  44. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/02-incident-postmortems.md +64 -0
  45. package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/03-adr-template.md +66 -0
  46. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/00-foundation/01-legacy-vision.md +73 -0
  47. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/00-foundation/02-foundation-approval.md +53 -0
  48. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/01-tech-debt-inventory.md +55 -0
  49. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/02-security-audit.md +63 -0
  50. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/03-regression-baseline.md +49 -0
  51. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/04-analysis-approval.md +65 -0
  52. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/01-modernization-approach.md +60 -0
  53. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/02-versioning-and-coexistence.md +57 -0
  54. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/03-new-demands-triage.md +41 -0
  55. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/04-strategy-approval.md +56 -0
  56. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/03-refactor/01-cleanup-backlog.md +45 -0
  57. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/03-refactor/02-refactor-approval.md +53 -0
  58. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/01-migration-roadmap.md +47 -0
  59. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/02-data-sync-strategy.md +56 -0
  60. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/03-migration-approval.md +55 -0
  61. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/05-sunset/01-decommission-plan.md +47 -0
  62. package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/05-sunset/02-sunset-approval.md +60 -0
  63. package/src/assets/dev-guides/prompt-tracks/README.md +144 -0
  64. package/src/assets/dev-guides/software-development-lifecycle-sdlc.md +147 -0
  65. package/src/assets/dev-guides/spec-driven-dev-guide.md +81 -0
  66. package/src/assets/dev-guides/ui-prompt-guide.md +181 -0
  67. package/src/assets/img/sdg-agents-icon-dark.svg +55 -0
  68. package/src/assets/img/sdg-agents-icon-light.svg +55 -0
  69. package/src/assets/img/sdg-agents-menu-v1.png +0 -0
  70. package/src/assets/img/sdg-icon.svg +110 -0
  71. package/src/assets/instructions/commands/sdg-docs.md +69 -0
  72. package/src/assets/instructions/commands/sdg-feat.md +45 -0
  73. package/src/assets/instructions/commands/sdg-fix.md +41 -0
  74. package/src/assets/instructions/commands/sdg-land.md +128 -0
  75. package/src/assets/instructions/competencies/backend.md +353 -0
  76. package/src/assets/instructions/competencies/frontend.md +439 -0
  77. package/src/assets/instructions/core/agent-roles.md +104 -0
  78. package/src/assets/instructions/core/api-design.md +65 -0
  79. package/src/assets/instructions/core/ci-cd.md +144 -0
  80. package/src/assets/instructions/core/cloud.md +63 -0
  81. package/src/assets/instructions/core/code-style.md +144 -0
  82. package/src/assets/instructions/core/containers.md +115 -0
  83. package/src/assets/instructions/core/data-access.md +119 -0
  84. package/src/assets/instructions/core/engineering-standards.md +502 -0
  85. package/src/assets/instructions/core/naming.md +136 -0
  86. package/src/assets/instructions/core/observability.md +73 -0
  87. package/src/assets/instructions/core/security-pipeline.md +209 -0
  88. package/src/assets/instructions/core/security.md +45 -0
  89. package/src/assets/instructions/core/sql-style.md +138 -0
  90. package/src/assets/instructions/core/staff-dna.md +72 -0
  91. package/src/assets/instructions/core/testing-principles.md +212 -0
  92. package/src/assets/instructions/core/ui/architecture.md +171 -0
  93. package/src/assets/instructions/core/ui/design-thinking.md +319 -0
  94. package/src/assets/instructions/core/ui/presets.md +200 -0
  95. package/src/assets/instructions/core/ui/standards.md +144 -0
  96. package/src/assets/instructions/core/writing-soul.md +82 -0
  97. package/src/assets/instructions/flavors/legacy/principles.md +64 -0
  98. package/src/assets/instructions/flavors/lite/principles.md +39 -0
  99. package/src/assets/instructions/flavors/mvc/principles.md +124 -0
  100. package/src/assets/instructions/flavors/vertical-slice/principles.md +178 -0
  101. package/src/assets/instructions/idioms/csharp/patterns.md +367 -0
  102. package/src/assets/instructions/idioms/flutter/patterns.md +97 -0
  103. package/src/assets/instructions/idioms/go/patterns.md +193 -0
  104. package/src/assets/instructions/idioms/java/patterns.md +233 -0
  105. package/src/assets/instructions/idioms/javascript/patterns.md +223 -0
  106. package/src/assets/instructions/idioms/kotlin/patterns.md +94 -0
  107. package/src/assets/instructions/idioms/python/patterns.md +185 -0
  108. package/src/assets/instructions/idioms/rust/patterns.md +189 -0
  109. package/src/assets/instructions/idioms/scripts/patterns.md +81 -0
  110. package/src/assets/instructions/idioms/sql/patterns.md +109 -0
  111. package/src/assets/instructions/idioms/swift/patterns.md +97 -0
  112. package/src/assets/instructions/idioms/typescript/patterns.md +304 -0
  113. package/src/assets/instructions/idioms/vbnet/patterns.md +96 -0
  114. package/src/assets/instructions/idioms/vbnet-legacy/patterns.md +104 -0
  115. package/src/assets/instructions/templates/workflow.md +244 -0
  116. package/src/assets/instructions/workflows/governance.md +162 -0
  117. package/src/engine/bin/add-idiom.mjs +186 -0
  118. package/src/engine/bin/index.mjs +226 -0
  119. package/src/engine/config/stack-display.mjs +75 -0
  120. package/src/engine/config/stack-versions.mjs +76 -0
  121. package/src/engine/lib/cli-parser.mjs +80 -0
  122. package/src/engine/lib/display-utils.mjs +20 -0
  123. package/src/engine/lib/fs-utils.mjs +99 -0
  124. package/src/engine/lib/instruction-assembler.mjs +487 -0
  125. package/src/engine/lib/manifest-utils.mjs +128 -0
  126. package/src/engine/lib/prompt-utils.mjs +137 -0
  127. package/src/engine/lib/result-utils.mjs +14 -0
  128. package/src/engine/lib/ruleset-injector.mjs +183 -0
  129. package/src/engine/lib/ui-utils.mjs +216 -0
  130. package/src/engine/lib/wizard.mjs +472 -0
@@ -0,0 +1,137 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { exec } from 'node:child_process';
4
+ import { select, checkbox, confirm } from '@inquirer/prompts';
5
+
6
+ function isExitError(err) {
7
+ return err.name === 'ExitPromptError' || err.message?.includes('force closed');
8
+ }
9
+
10
+ async function safeSelect(options) {
11
+ try {
12
+ return await select(options);
13
+ } catch (error) {
14
+ if (isExitError(error)) return 'back';
15
+ throw error;
16
+ }
17
+ }
18
+
19
+ async function safeCheckbox(options) {
20
+ try {
21
+ return await checkbox(options);
22
+ } catch (error) {
23
+ if (isExitError(error)) return ['back'];
24
+ throw error;
25
+ }
26
+ }
27
+
28
+ async function safeConfirm(options) {
29
+ try {
30
+ return await confirm(options);
31
+ } catch (error) {
32
+ if (isExitError(error)) return false;
33
+ throw error;
34
+ }
35
+ }
36
+
37
+ const PROJECT_ROOT = process.cwd();
38
+ const AI_DIR = path.join(PROJECT_ROOT, '.ai');
39
+ const PROMPT_FILE = path.join(AI_DIR, 'last-prompt.md');
40
+
41
+ function isMaintainerMode() {
42
+ const pkgPath = path.join(PROJECT_ROOT, 'package.json');
43
+ if (!fs.existsSync(pkgPath)) return false;
44
+ try {
45
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
46
+ return pkg.name === 'sdg-agents';
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ function savePromptToFile(content) {
53
+ if (!fs.existsSync(AI_DIR)) {
54
+ fs.mkdirSync(AI_DIR, { recursive: true });
55
+ }
56
+ fs.writeFileSync(PROMPT_FILE, content, 'utf8');
57
+ }
58
+
59
+ async function copyToClipboard(content) {
60
+ return new Promise((resolve) => {
61
+ let command;
62
+
63
+ switch (process.platform) {
64
+ case 'darwin':
65
+ command = 'pbcopy';
66
+ break;
67
+ case 'win32':
68
+ command = 'clip';
69
+ break;
70
+ case 'linux':
71
+ command = 'xclip -selection clipboard || xsel -bi';
72
+ break;
73
+ default:
74
+ return resolve(false);
75
+ }
76
+
77
+ const child = exec(command, (error) => {
78
+ resolve(!error);
79
+ });
80
+
81
+ child.on('error', () => {
82
+ resolve(false);
83
+ });
84
+
85
+ if (child.stdin) {
86
+ child.stdin.on('error', () => {
87
+ resolve(false);
88
+ });
89
+ child.stdin.write(content);
90
+ child.stdin.end();
91
+ } else {
92
+ resolve(false);
93
+ }
94
+ });
95
+ }
96
+
97
+ async function printPromptUI(content, title = 'AI Prompt Generated') {
98
+ const maintainer = isMaintainerMode();
99
+ savePromptToFile(content);
100
+ const copied = await copyToClipboard(content);
101
+
102
+ console.log(`\n ✅ ${title}`);
103
+
104
+ if (maintainer) {
105
+ console.log(' 🛠️ MAINTAINER MODE DETECTED: Prompt targets the Core Instructions.');
106
+ }
107
+
108
+ console.log(' ' + '─'.repeat(60));
109
+
110
+ if (copied) {
111
+ console.log(' 📋 COPIED TO CLIPBOARD AUTOMATICALLY.');
112
+ } else {
113
+ console.log(' ⚠️ COULD NOT COPY TO CLIPBOARD (Install xclip/xsel on Linux).');
114
+ }
115
+
116
+ console.log(` 💾 SAVED TO: .ai/last-prompt.md`);
117
+ console.log(' ' + '─'.repeat(60));
118
+
119
+ console.log('\n 🤖 HOW TO USE WITH LOCAL AGENTS (Cursor, Claude Code, Windsurf):');
120
+ console.log(' Tell your agent: "Follow the instructions in .ai/last-prompt.md"');
121
+
122
+ console.log('\n 🌍 HOW TO USE WITH WEB CHATS (Claude.ai, ChatGPT, Gemini):');
123
+ console.log(' The prompt is already in your clipboard. Just paste it (Ctrl+V).');
124
+ console.log(' ' + '─'.repeat(60) + '\n');
125
+ }
126
+
127
+ const PromptUtils = {
128
+ isMaintainerMode,
129
+ savePromptToFile,
130
+ copyToClipboard,
131
+ printPromptUI,
132
+ safeSelect,
133
+ safeCheckbox,
134
+ safeConfirm,
135
+ };
136
+
137
+ export { PromptUtils };
@@ -0,0 +1,14 @@
1
+ function success(value) {
2
+ return { isSuccess: true, isFailure: false, value, error: null };
3
+ }
4
+
5
+ function fail(message, code) {
6
+ return { isSuccess: false, isFailure: true, value: null, error: { message, code } };
7
+ }
8
+
9
+ const ResultUtils = {
10
+ success,
11
+ fail,
12
+ };
13
+
14
+ export { ResultUtils };
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Ruleset Injector — Copies instruction files into the target project.
3
+ * Handles version-aware filtering of markdown/XML content blocks.
4
+ */
5
+
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ import { STACK_DISPLAY_NAMES } from '../config/stack-display.mjs';
10
+ import { FsUtils } from './fs-utils.mjs';
11
+
12
+ const { copyRecursiveSync, filterContentByVersion, getDirname } = FsUtils;
13
+
14
+ const __dirname = getDirname(import.meta.url);
15
+ const SOURCE_INSTRUCTIONS = path.join(__dirname, '..', '..', 'assets', 'instructions');
16
+ const SOURCE_WORKFLOWS = path.join(SOURCE_INSTRUCTIONS, 'workflows');
17
+ const SOURCE_COMMANDS = path.join(SOURCE_INSTRUCTIONS, 'commands');
18
+ const SOURCE_DEV_GUIDES = path.join(__dirname, '..', '..', 'assets', 'dev-guides');
19
+ const SOURCE_DEV_TRACKS = path.join(SOURCE_DEV_GUIDES, 'prompt-tracks');
20
+ const SOURCE_COMPETENCIES = path.join(SOURCE_INSTRUCTIONS, 'competencies');
21
+
22
+ /**
23
+ * Creates the .ai/instructions directory structure in the target project.
24
+ */
25
+ function prepareProjectStructure(targetDir) {
26
+ const instructionsDir = path.join(targetDir, '.ai', 'instructions');
27
+ const workflowsDir = path.join(targetDir, '.ai', 'workflows');
28
+ const commandsDir = path.join(targetDir, '.ai', 'commands');
29
+
30
+ if (!fs.existsSync(instructionsDir)) fs.mkdirSync(instructionsDir, { recursive: true });
31
+ if (!fs.existsSync(workflowsDir)) fs.mkdirSync(workflowsDir, { recursive: true });
32
+ if (!fs.existsSync(commandsDir)) fs.mkdirSync(commandsDir, { recursive: true });
33
+ }
34
+
35
+ /**
36
+ * Injects core, flavor, idiom, and template rulesets into the target project.
37
+ */
38
+ function injectRulesets(targetDir, selections, { noDevGuides = false } = {}) {
39
+ const { flavor, idioms } = selections;
40
+ const projectAiInstructions = path.join(targetDir, '.ai', 'instructions');
41
+
42
+ copyRecursiveSync(
43
+ path.join(SOURCE_INSTRUCTIONS, 'core'),
44
+ path.join(projectAiInstructions, 'core')
45
+ );
46
+
47
+ const flavorSrc = path.join(SOURCE_INSTRUCTIONS, 'flavors', flavor);
48
+ if (fs.existsSync(flavorSrc)) {
49
+ copyRecursiveSync(flavorSrc, path.join(projectAiInstructions, 'flavor'));
50
+ }
51
+
52
+ for (const idiom of idioms) {
53
+ injectFilteredIdiom(idiom, selections.versions[idiom], projectAiInstructions);
54
+ }
55
+
56
+ injectCompetencies(selections, projectAiInstructions);
57
+
58
+ copyRecursiveSync(
59
+ path.join(SOURCE_INSTRUCTIONS, 'templates'),
60
+ path.join(projectAiInstructions, 'templates')
61
+ );
62
+
63
+ if (fs.existsSync(SOURCE_WORKFLOWS)) {
64
+ copyRecursiveSync(SOURCE_WORKFLOWS, path.join(targetDir, '.ai', 'workflows'));
65
+ }
66
+
67
+ if (fs.existsSync(SOURCE_COMMANDS)) {
68
+ copyRecursiveSync(SOURCE_COMMANDS, path.join(targetDir, '.ai', 'commands'));
69
+ }
70
+
71
+ if (!noDevGuides) injectDevGuides(targetDir);
72
+ }
73
+
74
+ /**
75
+ * Copies dev-guides (reference files, spec templates, guides) into the target project.
76
+ * Always included alongside the instruction set.
77
+ */
78
+ function injectDevGuides(targetDir) {
79
+ if (!fs.existsSync(SOURCE_DEV_GUIDES)) return;
80
+ copyRecursiveSync(SOURCE_DEV_GUIDES, path.join(targetDir, '.ai', 'dev-guides'));
81
+ }
82
+
83
+ /**
84
+ * Injects specification templates (tracks) into the target project.
85
+ */
86
+ function injectPrompts(targetDir, track) {
87
+ const projectRootPromptsDir = path.join(targetDir, '.ai', 'prompts');
88
+ const devTracksDir = path.join(projectRootPromptsDir, 'dev-tracks');
89
+
90
+ // Total replacement: clear the WHOLE .ai/prompts directory if it exists
91
+ if (fs.existsSync(projectRootPromptsDir)) {
92
+ fs.rmSync(projectRootPromptsDir, { recursive: true, force: true });
93
+ }
94
+ fs.mkdirSync(devTracksDir, { recursive: true });
95
+
96
+ if (track === 'all') {
97
+ // Copy all tracks from source to project
98
+ copyRecursiveSync(SOURCE_DEV_TRACKS, devTracksDir);
99
+ } else {
100
+ // Copy specific track folder into dev-tracks
101
+ const trackSrc = path.join(SOURCE_DEV_TRACKS, track);
102
+ const dest = path.join(devTracksDir, track);
103
+ if (fs.existsSync(trackSrc)) {
104
+ copyRecursiveSync(trackSrc, dest);
105
+ }
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Collects the list of directories and files that would be created (for --dry-run).
111
+ */
112
+ function collectOutputSummary(selections) {
113
+ const { mode, flavor, idioms, track } = selections;
114
+ const directories = [];
115
+
116
+ if (mode === 'agents') {
117
+ directories.push('.ai/instructions/core/');
118
+ if (flavor) directories.push('.ai/instructions/flavor/');
119
+ for (const idiom of idioms) directories.push(`.ai/instructions/idioms/${idiom}/`);
120
+ directories.push('.ai/instructions/templates/');
121
+ directories.push('.ai/instructions/competencies/');
122
+ directories.push('.ai/workflows/');
123
+ directories.push('.ai/commands/');
124
+ directories.push('.ai/dev-guides/');
125
+ } else if (mode === 'prompts') {
126
+ if (track) directories.push('.ai/prompts/dev-tracks/');
127
+ }
128
+
129
+ return { directories };
130
+ }
131
+
132
+ // --- Private ---
133
+
134
+ function injectCompetencies(selections, projectAiInstructions) {
135
+ if (!fs.existsSync(SOURCE_COMPETENCIES)) return;
136
+
137
+ const hasBackend = selections.idioms.some((idiomId) => STACK_DISPLAY_NAMES[idiomId]?.isBackend);
138
+ const hasFrontend = selections.idioms.some((idiomId) => STACK_DISPLAY_NAMES[idiomId]?.isFrontend);
139
+
140
+ if (!hasBackend && !hasFrontend) return;
141
+
142
+ const competenciesDir = path.join(projectAiInstructions, 'competencies');
143
+ if (!fs.existsSync(competenciesDir)) fs.mkdirSync(competenciesDir, { recursive: true });
144
+
145
+ if (hasBackend) {
146
+ const src = path.join(SOURCE_COMPETENCIES, 'backend.md');
147
+ if (fs.existsSync(src)) fs.copyFileSync(src, path.join(competenciesDir, 'backend.md'));
148
+ }
149
+
150
+ if (hasFrontend) {
151
+ const src = path.join(SOURCE_COMPETENCIES, 'frontend.md');
152
+ if (fs.existsSync(src)) fs.copyFileSync(src, path.join(competenciesDir, 'frontend.md'));
153
+ }
154
+ }
155
+
156
+ function injectFilteredIdiom(idiom, targetVersion, projectAiInstructions) {
157
+ const idiomSrc = path.join(SOURCE_INSTRUCTIONS, 'idioms', idiom);
158
+ if (!fs.existsSync(idiomSrc)) return;
159
+
160
+ const projectIdiomDir = path.join(projectAiInstructions, 'idioms', idiom);
161
+ if (!fs.existsSync(projectIdiomDir)) fs.mkdirSync(projectIdiomDir, { recursive: true });
162
+
163
+ for (const file of fs.readdirSync(idiomSrc)) {
164
+ const srcFile = path.join(idiomSrc, file);
165
+ const destFile = path.join(projectIdiomDir, file);
166
+
167
+ if (file.endsWith('.md') || file.endsWith('.xml')) {
168
+ let content = fs.readFileSync(srcFile, 'utf8');
169
+ content = filterContentByVersion(content, targetVersion);
170
+ fs.writeFileSync(destFile, content, 'utf8');
171
+ } else {
172
+ copyRecursiveSync(srcFile, destFile);
173
+ }
174
+ }
175
+ }
176
+
177
+ export const RulesetInjector = {
178
+ prepareProjectStructure,
179
+ injectRulesets,
180
+ injectDevGuides,
181
+ injectPrompts,
182
+ collectOutputSummary,
183
+ };
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Bundle UI — All console output and user confirmation for the bundle lifecycle.
3
+ * Single responsibility: presentation and interaction only, no file I/O.
4
+ */
5
+
6
+ import { STACK_DISPLAY_NAMES } from '../config/stack-display.mjs';
7
+ import { RulesetInjector } from './ruleset-injector.mjs';
8
+ import { PromptUtils } from './prompt-utils.mjs';
9
+
10
+ const { collectOutputSummary } = RulesetInjector;
11
+ const { safeConfirm } = PromptUtils;
12
+
13
+ function printWelcome() {
14
+ console.log('\n Installing instruction set...');
15
+ console.log(' ' + '─'.repeat(55));
16
+ }
17
+
18
+ function printStep(step, total, message) {
19
+ console.log(`[${step}/${total}] ${message}`);
20
+ }
21
+
22
+ function printAborted() {
23
+ console.log('\n Aborted. No files were written.\n');
24
+ }
25
+
26
+ function printQuickSetupStart() {
27
+ console.log(`\n ⚡ Quick setup — installing with defaults...`);
28
+ }
29
+
30
+ function printProjectRoot(targetDir) {
31
+ console.log(`\n Project Root: ${targetDir}`);
32
+ }
33
+
34
+ function printActivationGuide() {
35
+ console.log('\n Your agent is ready. Start with a task.');
36
+ console.log(' If it does not auto-load the rules, paste this once:');
37
+ console.log('\n Read .ai/skill/AGENTS.md\n');
38
+ }
39
+
40
+ function printSuccessAgents(targetDir) {
41
+ console.log('\n ✅ Done.');
42
+ console.log(' ' + '─'.repeat(55));
43
+ console.log(` Project: ${targetDir}\n`);
44
+ console.log(' .ai/');
45
+ console.log(' .ai-backlog/ (gitignored)');
46
+ printActivationGuide();
47
+ }
48
+
49
+ function printSuccessPrompts(targetDir) {
50
+ console.log('\n ✅ Done.');
51
+ console.log(' ' + '─'.repeat(55));
52
+ console.log(` Project: ${targetDir}\n`);
53
+ console.log(' .ai/prompts/dev-tracks/ — specification templates\n');
54
+ }
55
+
56
+ function printQuickSuccess(targetDir) {
57
+ console.log('\n ⚡ Done.');
58
+ console.log(' ' + '─'.repeat(55));
59
+ console.log(` Project: ${targetDir}\n`);
60
+ console.log(' .ai/');
61
+ console.log(' .ai-backlog/ (gitignored)');
62
+ printActivationGuide();
63
+ }
64
+
65
+ function printQuickDryRun(targetDir) {
66
+ console.log(`\n ⚡ [DRY RUN] Quick setup — nothing will be written.`);
67
+ console.log(' ' + '─'.repeat(55));
68
+ console.log(` Project: ${targetDir}\n`);
69
+ console.log(` [1/5] Would prepare .ai/ structure`);
70
+ console.log(` [2/5] Would inject rules and dev-guides → .ai/`);
71
+ console.log(` [3/5] Would assemble AGENTS.md`);
72
+ console.log(` [4/5] Would write agent config and backlog`);
73
+ console.log(` [5/5] Would inject spec templates → .ai/prompts/dev-tracks/`);
74
+ console.log('\n Run without --dry-run to apply.\n');
75
+ }
76
+
77
+ function printDryRunPreview(selections, targetDir) {
78
+ const summary = collectOutputSummary(selections);
79
+
80
+ console.log('\n 📋 DRY RUN — Preview of files that would be created:');
81
+ console.log(' ' + '─'.repeat(55));
82
+ console.log(` Project Root: ${targetDir}\n`);
83
+
84
+ console.log(' Instruction directories:');
85
+ for (const dir of summary.directories) {
86
+ console.log(` 📁 ${dir}`);
87
+ }
88
+
89
+ console.log(` 📄 .ai/skill/AGENTS.md`);
90
+
91
+ const activeAgents = [...(selections.agents || []), selections.ide].filter(Boolean);
92
+ const ideTargets = {
93
+ cursor: '.cursor/rules/sdg-agents.mdc',
94
+ windsurf: '.windsurfrules',
95
+ vscode: '.github/copilot-instructions.md',
96
+ copilot: '.github/copilot-instructions.md',
97
+ claude: 'CLAUDE.md',
98
+ roocode: '.clinerules',
99
+ gemini: 'AI_INSTRUCTIONS.md',
100
+ };
101
+
102
+ for (const agent of activeAgents) {
103
+ if (agent === 'none' || agent === 'antigravity' || agent === 'all') continue;
104
+ if (ideTargets[agent]) {
105
+ console.log(` 📄 ${ideTargets[agent]}`);
106
+ }
107
+ }
108
+
109
+ if (selections.mode === 'agents') {
110
+ console.log(' 📄 .ai/.sdg-manifest.json');
111
+ }
112
+
113
+ console.log('\n ' + '─'.repeat(55));
114
+ console.log(' Run without --dry-run to apply.\n');
115
+ }
116
+
117
+ async function printBuildSummary(selections) {
118
+ const { flavor, idioms, versions, designPreset, mode, track } = selections;
119
+
120
+ const flavorLabel = STACK_DISPLAY_NAMES[flavor]?.name ?? flavor;
121
+ const idiomsLabel = idioms
122
+ .map((id) => {
123
+ const name = STACK_DISPLAY_NAMES[id]?.name ?? id;
124
+ const ver = versions?.[id] ? ` (${versions[id]})` : '';
125
+ return `${name}${ver}`;
126
+ })
127
+ .join(', ');
128
+
129
+ console.log('\n ┌─ Build Summary ──────────────────────────────────────┐');
130
+
131
+ if (mode === 'prompts') {
132
+ console.log(
133
+ ' │ Track: ' +
134
+ (track === 'all' ? '00, 01, 02 (Full Training)'.padEnd(43) : track.padEnd(43)) +
135
+ '│'
136
+ );
137
+ } else {
138
+ console.log(` │ Flavor: ${flavorLabel.padEnd(43)}│`);
139
+ console.log(` │ Idioms: ${idiomsLabel.padEnd(43)}│`);
140
+ if (designPreset) {
141
+ console.log(` │ Preset: ${designPreset.padEnd(43)}│`);
142
+ }
143
+ }
144
+
145
+ console.log(' └──────────────────────────────────────────────────────┘');
146
+
147
+ return safeConfirm({ message: ' Proceed?', default: true });
148
+ }
149
+
150
+ function printHeader(version) {
151
+ console.log(`\n Spec-Driven Guide — Agents v${version}`);
152
+ console.log(' ' + '─'.repeat(50));
153
+ console.log(' A working protocol and engineering rules for your AI agent.');
154
+ console.log(' Press Ctrl+C to exit.\n');
155
+ }
156
+
157
+ function printFooter() {
158
+ console.log('\n See you.\n');
159
+ }
160
+
161
+ function printHelp(version) {
162
+ console.log(`
163
+ sdg-agents v${version}
164
+ Installs a structured instruction set for AI agents into your project.
165
+
166
+ Usage:
167
+ npx sdg-agents [command] [options]
168
+
169
+ Commands:
170
+ init Install the instruction set (interactive or via flags)
171
+ review Compare local rules vs source
172
+ sync Update patterns from source
173
+ update Refresh the LTS version registry
174
+ add Add a language idiom to an existing project
175
+ clear Remove the .ai/ folder
176
+
177
+ Global Options:
178
+ -h, --help Show this help
179
+ -v, --version Show version
180
+
181
+ Init Options:
182
+ --flavor <name> Architecture flavor (vertical-slice, mvc, lite, legacy)
183
+ --idiom <name> Language idiom — repeatable or comma-separated
184
+ --no-dev-guides Skip reference files and spec templates
185
+ --dry-run Preview without writing files
186
+
187
+ Examples:
188
+ npx sdg-agents
189
+ npx sdg-agents init --flavor vertical-slice --idiom typescript
190
+ npx sdg-agents init --flavor mvc --idiom typescript,python
191
+ npx sdg-agents init --flavor lite --idiom go --no-dev-guides
192
+ npx sdg-agents init --flavor mvc --idiom python --dry-run
193
+ npx sdg-agents add
194
+ npx sdg-agents clear
195
+ `);
196
+ }
197
+
198
+ const BundleUI = {
199
+ printWelcome,
200
+ printStep,
201
+ printAborted,
202
+ printQuickSetupStart,
203
+ printProjectRoot,
204
+ printActivationGuide,
205
+ printSuccessAgents,
206
+ printSuccessPrompts,
207
+ printQuickSuccess,
208
+ printQuickDryRun,
209
+ printDryRunPreview,
210
+ printBuildSummary,
211
+ printHeader,
212
+ printFooter,
213
+ printHelp,
214
+ };
215
+
216
+ export { BundleUI };