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.
- package/LICENSE +15 -0
- package/README.md +161 -0
- package/package.json +88 -0
- package/src/assets/dev-guides/agent-deep-flow.md +139 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/01-project-scope-and-mvp.md +45 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/02-stack-and-data-model.md +56 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/03-external-integrations.md +44 -0
- package/src/assets/dev-guides/prompt-tracks/00-lite-mode/04-launch-checklist.md +26 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/01-project-vision.md +77 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/02-problem-definition.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/03-success-metrics.md +48 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/05-engineering-culture-and-silos.md +41 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/00-foundation/06-foundation-approval.md +57 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/01-tech-stack.md +62 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/02-local-environment.md +50 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/03-version-control-and-tracking.md +65 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/04-hello-world-validation.md +37 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/01-setup/05-setup-approval.md +61 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/01-folder-structure.md +49 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/02-design-patterns.md +59 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/03-apis-and-communication.md +55 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/04-security-and-access.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/05-security-audit.md +64 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/06-design-system-ux.md +72 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/07-ai-strategy.md +72 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/08-observability.md +65 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/09-technical-documentation.md +64 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/10-infrastructure-and-costs.md +40 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/11-data-privacy-compliance.md +41 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/12-performance-and-scale.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/13-disaster-recovery.md +39 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/02-architecture/14-architecture-approval.md +81 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/01-ci-cd-pipeline.md +49 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/02-quality-standards.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/03-delivery/03-delivery-approval.md +58 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/00-feature-template.md +30 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/01-context-and-scope.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/02-business-rules.md +39 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/03-architecture-and-design.md +50 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/04-testing-strategy.md +48 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/05-implementation-plan.md +45 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/04-features/06-feature-approval.md +46 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/01-rfcs-and-changes.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/02-incident-postmortems.md +64 -0
- package/src/assets/dev-guides/prompt-tracks/01-new-evolution/05-evolution/03-adr-template.md +66 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/00-foundation/01-legacy-vision.md +73 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/00-foundation/02-foundation-approval.md +53 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/01-tech-debt-inventory.md +55 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/02-security-audit.md +63 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/03-regression-baseline.md +49 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/01-analysis/04-analysis-approval.md +65 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/01-modernization-approach.md +60 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/02-versioning-and-coexistence.md +57 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/03-new-demands-triage.md +41 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/02-strategy/04-strategy-approval.md +56 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/03-refactor/01-cleanup-backlog.md +45 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/03-refactor/02-refactor-approval.md +53 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/01-migration-roadmap.md +47 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/02-data-sync-strategy.md +56 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/04-migration/03-migration-approval.md +55 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/05-sunset/01-decommission-plan.md +47 -0
- package/src/assets/dev-guides/prompt-tracks/02-legacy-modernization/05-sunset/02-sunset-approval.md +60 -0
- package/src/assets/dev-guides/prompt-tracks/README.md +144 -0
- package/src/assets/dev-guides/software-development-lifecycle-sdlc.md +147 -0
- package/src/assets/dev-guides/spec-driven-dev-guide.md +81 -0
- package/src/assets/dev-guides/ui-prompt-guide.md +181 -0
- package/src/assets/img/sdg-agents-icon-dark.svg +55 -0
- package/src/assets/img/sdg-agents-icon-light.svg +55 -0
- package/src/assets/img/sdg-agents-menu-v1.png +0 -0
- package/src/assets/img/sdg-icon.svg +110 -0
- package/src/assets/instructions/commands/sdg-docs.md +69 -0
- package/src/assets/instructions/commands/sdg-feat.md +45 -0
- package/src/assets/instructions/commands/sdg-fix.md +41 -0
- package/src/assets/instructions/commands/sdg-land.md +128 -0
- package/src/assets/instructions/competencies/backend.md +353 -0
- package/src/assets/instructions/competencies/frontend.md +439 -0
- package/src/assets/instructions/core/agent-roles.md +104 -0
- package/src/assets/instructions/core/api-design.md +65 -0
- package/src/assets/instructions/core/ci-cd.md +144 -0
- package/src/assets/instructions/core/cloud.md +63 -0
- package/src/assets/instructions/core/code-style.md +144 -0
- package/src/assets/instructions/core/containers.md +115 -0
- package/src/assets/instructions/core/data-access.md +119 -0
- package/src/assets/instructions/core/engineering-standards.md +502 -0
- package/src/assets/instructions/core/naming.md +136 -0
- package/src/assets/instructions/core/observability.md +73 -0
- package/src/assets/instructions/core/security-pipeline.md +209 -0
- package/src/assets/instructions/core/security.md +45 -0
- package/src/assets/instructions/core/sql-style.md +138 -0
- package/src/assets/instructions/core/staff-dna.md +72 -0
- package/src/assets/instructions/core/testing-principles.md +212 -0
- package/src/assets/instructions/core/ui/architecture.md +171 -0
- package/src/assets/instructions/core/ui/design-thinking.md +319 -0
- package/src/assets/instructions/core/ui/presets.md +200 -0
- package/src/assets/instructions/core/ui/standards.md +144 -0
- package/src/assets/instructions/core/writing-soul.md +82 -0
- package/src/assets/instructions/flavors/legacy/principles.md +64 -0
- package/src/assets/instructions/flavors/lite/principles.md +39 -0
- package/src/assets/instructions/flavors/mvc/principles.md +124 -0
- package/src/assets/instructions/flavors/vertical-slice/principles.md +178 -0
- package/src/assets/instructions/idioms/csharp/patterns.md +367 -0
- package/src/assets/instructions/idioms/flutter/patterns.md +97 -0
- package/src/assets/instructions/idioms/go/patterns.md +193 -0
- package/src/assets/instructions/idioms/java/patterns.md +233 -0
- package/src/assets/instructions/idioms/javascript/patterns.md +223 -0
- package/src/assets/instructions/idioms/kotlin/patterns.md +94 -0
- package/src/assets/instructions/idioms/python/patterns.md +185 -0
- package/src/assets/instructions/idioms/rust/patterns.md +189 -0
- package/src/assets/instructions/idioms/scripts/patterns.md +81 -0
- package/src/assets/instructions/idioms/sql/patterns.md +109 -0
- package/src/assets/instructions/idioms/swift/patterns.md +97 -0
- package/src/assets/instructions/idioms/typescript/patterns.md +304 -0
- package/src/assets/instructions/idioms/vbnet/patterns.md +96 -0
- package/src/assets/instructions/idioms/vbnet-legacy/patterns.md +104 -0
- package/src/assets/instructions/templates/workflow.md +244 -0
- package/src/assets/instructions/workflows/governance.md +162 -0
- package/src/engine/bin/add-idiom.mjs +186 -0
- package/src/engine/bin/index.mjs +226 -0
- package/src/engine/config/stack-display.mjs +75 -0
- package/src/engine/config/stack-versions.mjs +76 -0
- package/src/engine/lib/cli-parser.mjs +80 -0
- package/src/engine/lib/display-utils.mjs +20 -0
- package/src/engine/lib/fs-utils.mjs +99 -0
- package/src/engine/lib/instruction-assembler.mjs +487 -0
- package/src/engine/lib/manifest-utils.mjs +128 -0
- package/src/engine/lib/prompt-utils.mjs +137 -0
- package/src/engine/lib/result-utils.mjs +14 -0
- package/src/engine/lib/ruleset-injector.mjs +183 -0
- package/src/engine/lib/ui-utils.mjs +216 -0
- 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 };
|