dev-rules 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +197 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inject.d.ts +6 -0
- package/dist/commands/inject.d.ts.map +1 -0
- package/dist/commands/inject.js +95 -0
- package/dist/commands/inject.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +111 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/agents-generator.d.ts +3 -0
- package/dist/utils/agents-generator.d.ts.map +1 -0
- package/dist/utils/agents-generator.js +59 -0
- package/dist/utils/agents-generator.js.map +1 -0
- package/dist/utils/file-ops.d.ts +7 -0
- package/dist/utils/file-ops.d.ts.map +1 -0
- package/dist/utils/file-ops.js +49 -0
- package/dist/utils/file-ops.js.map +1 -0
- package/dist/utils/paths.d.ts +18 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +44 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/stack-detector.d.ts +9 -0
- package/dist/utils/stack-detector.d.ts.map +1 -0
- package/dist/utils/stack-detector.js +60 -0
- package/dist/utils/stack-detector.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# dev-rules CLI
|
|
2
|
+
|
|
3
|
+
CLI tool to automate "Senior Architect" setup for new and existing projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Use directly with npx (no installation required)
|
|
9
|
+
npx dev-rules init my-app
|
|
10
|
+
|
|
11
|
+
# Or install globally
|
|
12
|
+
npm install -g dev-rules
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### `dev-rules init <name>`
|
|
18
|
+
|
|
19
|
+
Scaffold a new project with the latest standards.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
dev-rules init my-app
|
|
23
|
+
dev-rules init my-app --template ts # TypeScript (default)
|
|
24
|
+
dev-rules init my-app --template python # Python
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**What it does:**
|
|
28
|
+
- Creates project directory with standard structure
|
|
29
|
+
- Generates `AGENTS.md` with strict development rules
|
|
30
|
+
- Installs relevant rule files to `.cursor/rules/`
|
|
31
|
+
- Sets up basic project files (package.json/pyproject.toml, tsconfig, etc.)
|
|
32
|
+
|
|
33
|
+
### `dev-rules inject`
|
|
34
|
+
|
|
35
|
+
Add standards to an existing project (current directory).
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd my-existing-project
|
|
39
|
+
dev-rules inject
|
|
40
|
+
dev-rules inject --force # Overwrite existing files
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**What it does:**
|
|
44
|
+
- Detects project type (TypeScript, Python, Rust)
|
|
45
|
+
- Generates customized `AGENTS.md`
|
|
46
|
+
- Installs relevant rule files to `.cursor/rules/`
|
|
47
|
+
|
|
48
|
+
### `dev-rules update`
|
|
49
|
+
|
|
50
|
+
Check and update outdated rules from the source.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
dev-rules update
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**What it does:**
|
|
57
|
+
- Compares local `.cursor/rules/` files with source
|
|
58
|
+
- Shows which files are outdated
|
|
59
|
+
- Prompts user to select files to update
|
|
60
|
+
- Fetches and overwrites selected files
|
|
61
|
+
|
|
62
|
+
## Source of Truth
|
|
63
|
+
|
|
64
|
+
The CLI automatically determines where to get rules from:
|
|
65
|
+
|
|
66
|
+
1. **Local**: If running from within the `dev-handbook` repo, uses local files
|
|
67
|
+
2. **Remote**: Otherwise, fetches from GitHub
|
|
68
|
+
|
|
69
|
+
## Development
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd cli
|
|
73
|
+
npm install
|
|
74
|
+
npm run build
|
|
75
|
+
npm run dev -- init test-app
|
|
76
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAUA,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCnF"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import prompts from "prompts";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { join, resolve } from "path";
|
|
5
|
+
import { getRulesSource } from "../utils/paths.js";
|
|
6
|
+
import { ensureDir, writeFile, copyFile, fetchRemoteFile } from "../utils/file-ops.js";
|
|
7
|
+
import { generateAgentsMd } from "../utils/agents-generator.js";
|
|
8
|
+
import { getRelevantRules } from "../utils/stack-detector.js";
|
|
9
|
+
export async function initCommand(name, options) {
|
|
10
|
+
const targetDir = resolve(process.cwd(), name);
|
|
11
|
+
if (existsSync(targetDir)) {
|
|
12
|
+
const response = await prompts({
|
|
13
|
+
type: "confirm",
|
|
14
|
+
name: "proceed",
|
|
15
|
+
message: `Directory "${name}" already exists. Continue anyway?`,
|
|
16
|
+
initial: false,
|
|
17
|
+
});
|
|
18
|
+
if (!response.proceed) {
|
|
19
|
+
console.log(chalk.red("Aborted."));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
console.log(chalk.blue(`\nInitializing project: ${name}`));
|
|
24
|
+
console.log(chalk.blue(`Template: ${options.template}`));
|
|
25
|
+
ensureDir(targetDir);
|
|
26
|
+
const stack = buildStackFromTemplate(options.template);
|
|
27
|
+
await scaffoldProject(targetDir, name, stack, options.template);
|
|
28
|
+
console.log(chalk.green("\nProject initialized successfully!"));
|
|
29
|
+
console.log(chalk.blue("\nNext steps:"));
|
|
30
|
+
console.log(` cd ${name}`);
|
|
31
|
+
if (options.template === "ts") {
|
|
32
|
+
console.log(" npm install");
|
|
33
|
+
}
|
|
34
|
+
else if (options.template === "python") {
|
|
35
|
+
console.log(" pip install -r requirements.txt");
|
|
36
|
+
}
|
|
37
|
+
console.log(" # Start coding with AI assistance!");
|
|
38
|
+
}
|
|
39
|
+
function buildStackFromTemplate(template) {
|
|
40
|
+
switch (template) {
|
|
41
|
+
case "ts":
|
|
42
|
+
case "typescript":
|
|
43
|
+
return { primary: "typescript", hasReact: false, hasDatabase: false };
|
|
44
|
+
case "ts-react":
|
|
45
|
+
case "react":
|
|
46
|
+
return { primary: "typescript", hasReact: true, hasDatabase: false };
|
|
47
|
+
case "python":
|
|
48
|
+
case "py":
|
|
49
|
+
return { primary: "python", hasReact: false, hasDatabase: false };
|
|
50
|
+
case "rust":
|
|
51
|
+
case "rs":
|
|
52
|
+
return { primary: "rust", hasReact: false, hasDatabase: false };
|
|
53
|
+
default:
|
|
54
|
+
return { primary: "typescript", hasReact: false, hasDatabase: false };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function scaffoldProject(targetDir, projectName, stack, template) {
|
|
58
|
+
const rulesDir = join(targetDir, ".cursor", "rules");
|
|
59
|
+
ensureDir(rulesDir);
|
|
60
|
+
const agentsMd = generateAgentsMd(stack, ".cursor/rules");
|
|
61
|
+
writeFile(join(targetDir, "AGENTS.md"), agentsMd);
|
|
62
|
+
console.log(chalk.green("Created AGENTS.md"));
|
|
63
|
+
await installRulesForInit(rulesDir, stack);
|
|
64
|
+
if (template === "ts" || template === "typescript") {
|
|
65
|
+
await scaffoldTypeScriptProject(targetDir, projectName);
|
|
66
|
+
}
|
|
67
|
+
else if (template === "python" || template === "py") {
|
|
68
|
+
await scaffoldPythonProject(targetDir, projectName);
|
|
69
|
+
}
|
|
70
|
+
const readmeContent = `# ${projectName}
|
|
71
|
+
|
|
72
|
+
> This project follows the Senior Architect development standards.
|
|
73
|
+
|
|
74
|
+
## Getting Started
|
|
75
|
+
|
|
76
|
+
See \`AGENTS.md\` for development guidelines and rules.
|
|
77
|
+
|
|
78
|
+
## Structure
|
|
79
|
+
|
|
80
|
+
- \`.cursor/rules/\` - Coding standards and rules for AI assistance
|
|
81
|
+
- \`AGENTS.md\` - Main configuration for AI development
|
|
82
|
+
`;
|
|
83
|
+
writeFile(join(targetDir, "README.md"), readmeContent);
|
|
84
|
+
console.log(chalk.green("Created README.md"));
|
|
85
|
+
const gitignoreContent = `node_modules/
|
|
86
|
+
dist/
|
|
87
|
+
.env
|
|
88
|
+
.env.local
|
|
89
|
+
*.log
|
|
90
|
+
.DS_Store
|
|
91
|
+
__pycache__/
|
|
92
|
+
*.pyc
|
|
93
|
+
.venv/
|
|
94
|
+
`;
|
|
95
|
+
writeFile(join(targetDir, ".gitignore"), gitignoreContent);
|
|
96
|
+
console.log(chalk.green("Created .gitignore"));
|
|
97
|
+
}
|
|
98
|
+
async function installRulesForInit(rulesDir, stack) {
|
|
99
|
+
const source = getRulesSource();
|
|
100
|
+
const relevantRules = getRelevantRules(stack);
|
|
101
|
+
console.log(chalk.blue(`Installing ${relevantRules.length} rule files...`));
|
|
102
|
+
for (const rule of relevantRules) {
|
|
103
|
+
const destPath = join(rulesDir, rule);
|
|
104
|
+
try {
|
|
105
|
+
if (source.type === "local") {
|
|
106
|
+
const srcPath = join(source.path, "rules", rule);
|
|
107
|
+
if (existsSync(srcPath)) {
|
|
108
|
+
copyFile(srcPath, destPath);
|
|
109
|
+
console.log(chalk.green(` Installed ${rule}`));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const content = await fetchRemoteFile(`${source.path}/rules/${rule}`);
|
|
114
|
+
writeFile(destPath, content);
|
|
115
|
+
console.log(chalk.green(` Fetched ${rule}`));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
console.log(chalk.yellow(` Could not install ${rule}`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function scaffoldTypeScriptProject(targetDir, projectName) {
|
|
124
|
+
const packageJson = {
|
|
125
|
+
name: projectName,
|
|
126
|
+
version: "1.0.0",
|
|
127
|
+
description: "",
|
|
128
|
+
main: "dist/index.js",
|
|
129
|
+
scripts: {
|
|
130
|
+
build: "tsc",
|
|
131
|
+
dev: "ts-node src/index.ts",
|
|
132
|
+
start: "node dist/index.js",
|
|
133
|
+
test: "vitest",
|
|
134
|
+
lint: "eslint src/",
|
|
135
|
+
typecheck: "tsc --noEmit",
|
|
136
|
+
},
|
|
137
|
+
devDependencies: {
|
|
138
|
+
"@types/node": "^20.14.0",
|
|
139
|
+
"ts-node": "^10.9.2",
|
|
140
|
+
typescript: "^5.4.5",
|
|
141
|
+
vitest: "^1.6.0",
|
|
142
|
+
eslint: "^9.0.0",
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
writeFile(join(targetDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
146
|
+
console.log(chalk.green("Created package.json"));
|
|
147
|
+
const tsconfig = {
|
|
148
|
+
compilerOptions: {
|
|
149
|
+
target: "ES2022",
|
|
150
|
+
module: "NodeNext",
|
|
151
|
+
moduleResolution: "NodeNext",
|
|
152
|
+
lib: ["ES2022"],
|
|
153
|
+
outDir: "./dist",
|
|
154
|
+
rootDir: "./src",
|
|
155
|
+
strict: true,
|
|
156
|
+
esModuleInterop: true,
|
|
157
|
+
skipLibCheck: true,
|
|
158
|
+
forceConsistentCasingInFileNames: true,
|
|
159
|
+
},
|
|
160
|
+
include: ["src/**/*"],
|
|
161
|
+
exclude: ["node_modules", "dist"],
|
|
162
|
+
};
|
|
163
|
+
writeFile(join(targetDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
|
|
164
|
+
console.log(chalk.green("Created tsconfig.json"));
|
|
165
|
+
ensureDir(join(targetDir, "src"));
|
|
166
|
+
writeFile(join(targetDir, "src", "index.ts"), `console.log("Hello, ${projectName}!");\n`);
|
|
167
|
+
console.log(chalk.green("Created src/index.ts"));
|
|
168
|
+
}
|
|
169
|
+
async function scaffoldPythonProject(targetDir, projectName) {
|
|
170
|
+
const pyprojectToml = `[build-system]
|
|
171
|
+
requires = ["setuptools>=61.0"]
|
|
172
|
+
build-backend = "setuptools.build_meta"
|
|
173
|
+
|
|
174
|
+
[project]
|
|
175
|
+
name = "${projectName}"
|
|
176
|
+
version = "1.0.0"
|
|
177
|
+
description = ""
|
|
178
|
+
readme = "README.md"
|
|
179
|
+
requires-python = ">=3.11"
|
|
180
|
+
dependencies = []
|
|
181
|
+
|
|
182
|
+
[project.optional-dependencies]
|
|
183
|
+
dev = [
|
|
184
|
+
"pytest>=8.0.0",
|
|
185
|
+
"ruff>=0.4.0",
|
|
186
|
+
"mypy>=1.10.0",
|
|
187
|
+
]
|
|
188
|
+
`;
|
|
189
|
+
writeFile(join(targetDir, "pyproject.toml"), pyprojectToml);
|
|
190
|
+
console.log(chalk.green("Created pyproject.toml"));
|
|
191
|
+
const srcDir = join(targetDir, "src", projectName.replace(/-/g, "_"));
|
|
192
|
+
ensureDir(srcDir);
|
|
193
|
+
writeFile(join(srcDir, "__init__.py"), "");
|
|
194
|
+
writeFile(join(srcDir, "main.py"), `def main() -> None:\n print("Hello, ${projectName}!")\n\n\nif __name__ == "__main__":\n main()\n`);
|
|
195
|
+
console.log(chalk.green("Created src module"));
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject.d.ts","sourceRoot":"","sources":["../../src/commands/inject.ts"],"names":[],"mappings":"AASA,UAAU,aAAa;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDzE"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import prompts from "prompts";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { detectStack, getRelevantRules } from "../utils/stack-detector.js";
|
|
6
|
+
import { getRulesSource } from "../utils/paths.js";
|
|
7
|
+
import { ensureDir, writeFile, copyFile, fetchRemoteFile } from "../utils/file-ops.js";
|
|
8
|
+
import { generateAgentsMd } from "../utils/agents-generator.js";
|
|
9
|
+
export async function injectCommand(options) {
|
|
10
|
+
const targetDir = process.cwd();
|
|
11
|
+
console.log(chalk.blue("Analyzing project..."));
|
|
12
|
+
const stack = detectStack(targetDir);
|
|
13
|
+
if (stack.primary === "unknown") {
|
|
14
|
+
console.log(chalk.yellow("Could not detect project type. No package.json, pyproject.toml, or Cargo.toml found."));
|
|
15
|
+
const response = await prompts({
|
|
16
|
+
type: "select",
|
|
17
|
+
name: "stack",
|
|
18
|
+
message: "What type of project is this?",
|
|
19
|
+
choices: [
|
|
20
|
+
{ title: "TypeScript/Node.js", value: "typescript" },
|
|
21
|
+
{ title: "Python", value: "python" },
|
|
22
|
+
{ title: "Rust", value: "rust" },
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
if (!response.stack) {
|
|
26
|
+
console.log(chalk.red("Aborted."));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
stack.primary = response.stack;
|
|
30
|
+
}
|
|
31
|
+
console.log(chalk.green(`Detected stack: ${stack.primary}${stack.hasReact ? " + React" : ""}${stack.hasDatabase ? " + Database" : ""}`));
|
|
32
|
+
const agentsPath = join(targetDir, "AGENTS.md");
|
|
33
|
+
const rulesDir = join(targetDir, ".cursor", "rules");
|
|
34
|
+
if (existsSync(agentsPath) && !options.force) {
|
|
35
|
+
const response = await prompts({
|
|
36
|
+
type: "confirm",
|
|
37
|
+
name: "overwrite",
|
|
38
|
+
message: "AGENTS.md already exists. Overwrite?",
|
|
39
|
+
initial: false,
|
|
40
|
+
});
|
|
41
|
+
if (!response.overwrite) {
|
|
42
|
+
console.log(chalk.yellow("Skipping AGENTS.md"));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
await installAgentsMd(targetDir, stack, rulesDir);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
await installAgentsMd(targetDir, stack, rulesDir);
|
|
50
|
+
}
|
|
51
|
+
await installRules(targetDir, stack, rulesDir, options.force);
|
|
52
|
+
console.log(chalk.green("\nInjection complete!"));
|
|
53
|
+
console.log(chalk.blue("Files created:"));
|
|
54
|
+
console.log(` - AGENTS.md`);
|
|
55
|
+
console.log(` - .cursor/rules/*.md`);
|
|
56
|
+
}
|
|
57
|
+
async function installAgentsMd(targetDir, stack, rulesDir) {
|
|
58
|
+
const agentsMd = generateAgentsMd(stack, ".cursor/rules");
|
|
59
|
+
writeFile(join(targetDir, "AGENTS.md"), agentsMd);
|
|
60
|
+
console.log(chalk.green("Created AGENTS.md"));
|
|
61
|
+
}
|
|
62
|
+
async function installRules(targetDir, stack, rulesDir, force) {
|
|
63
|
+
ensureDir(rulesDir);
|
|
64
|
+
const source = getRulesSource();
|
|
65
|
+
const relevantRules = getRelevantRules(stack);
|
|
66
|
+
console.log(chalk.blue(`\nInstalling ${relevantRules.length} rule files from ${source.type} source...`));
|
|
67
|
+
for (const rule of relevantRules) {
|
|
68
|
+
const destPath = join(rulesDir, rule);
|
|
69
|
+
if (existsSync(destPath) && !force) {
|
|
70
|
+
console.log(chalk.yellow(` Skipping ${rule} (exists)`));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
if (source.type === "local") {
|
|
75
|
+
const srcPath = join(source.path, "rules", rule);
|
|
76
|
+
if (existsSync(srcPath)) {
|
|
77
|
+
copyFile(srcPath, destPath);
|
|
78
|
+
console.log(chalk.green(` Copied ${rule}`));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(chalk.yellow(` Rule not found: ${rule}`));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const content = await fetchRemoteFile(`${source.path}/rules/${rule}`);
|
|
86
|
+
writeFile(destPath, content);
|
|
87
|
+
console.log(chalk.green(` Fetched ${rule}`));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.log(chalk.red(` Failed to install ${rule}: ${error}`));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=inject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject.js","sourceRoot":"","sources":["../../src/commands/inject.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAkBA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAkHnD"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import prompts from "prompts";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { listFiles, readFile, writeFile, fetchRemoteFile } from "../utils/file-ops.js";
|
|
6
|
+
import { getRulesSource } from "../utils/paths.js";
|
|
7
|
+
import crypto from "crypto";
|
|
8
|
+
const GITHUB_RAW_BASE = "https://raw.githubusercontent.com/your-org/dev-handbook/main";
|
|
9
|
+
export async function updateCommand() {
|
|
10
|
+
const targetDir = process.cwd();
|
|
11
|
+
const rulesDir = join(targetDir, ".cursor", "rules");
|
|
12
|
+
if (!existsSync(rulesDir)) {
|
|
13
|
+
console.log(chalk.red("No .cursor/rules/ directory found."));
|
|
14
|
+
console.log(chalk.yellow("Run 'dev-rules inject' first to install rules."));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
console.log(chalk.blue("Checking for updates...\n"));
|
|
18
|
+
const localRules = listFiles(rulesDir).filter((f) => f.endsWith(".md"));
|
|
19
|
+
if (localRules.length === 0) {
|
|
20
|
+
console.log(chalk.yellow("No rule files found in .cursor/rules/"));
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
const source = getRulesSource();
|
|
24
|
+
const statuses = [];
|
|
25
|
+
for (const rule of localRules) {
|
|
26
|
+
const localPath = join(rulesDir, rule);
|
|
27
|
+
const localContent = readFile(localPath);
|
|
28
|
+
const localHash = hashContent(localContent);
|
|
29
|
+
let remoteHash = null;
|
|
30
|
+
let error;
|
|
31
|
+
try {
|
|
32
|
+
let remoteContent;
|
|
33
|
+
if (source.type === "local") {
|
|
34
|
+
const remotePath = join(source.path, "rules", rule);
|
|
35
|
+
if (existsSync(remotePath)) {
|
|
36
|
+
remoteContent = readFile(remotePath);
|
|
37
|
+
remoteHash = hashContent(remoteContent);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
remoteContent = await fetchRemoteFile(`${GITHUB_RAW_BASE}/rules/${rule}`);
|
|
42
|
+
remoteHash = hashContent(remoteContent);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
error = e instanceof Error ? e.message : "Unknown error";
|
|
47
|
+
}
|
|
48
|
+
statuses.push({
|
|
49
|
+
name: rule,
|
|
50
|
+
localHash,
|
|
51
|
+
remoteHash,
|
|
52
|
+
isOutdated: remoteHash !== null && localHash !== remoteHash,
|
|
53
|
+
error,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const outdated = statuses.filter((s) => s.isOutdated);
|
|
57
|
+
const upToDate = statuses.filter((s) => !s.isOutdated && !s.error);
|
|
58
|
+
const errors = statuses.filter((s) => s.error);
|
|
59
|
+
console.log(chalk.blue("Status:"));
|
|
60
|
+
for (const status of upToDate) {
|
|
61
|
+
console.log(chalk.green(` ✓ ${status.name} (up to date)`));
|
|
62
|
+
}
|
|
63
|
+
for (const status of outdated) {
|
|
64
|
+
console.log(chalk.yellow(` ↻ ${status.name} (outdated)`));
|
|
65
|
+
}
|
|
66
|
+
for (const status of errors) {
|
|
67
|
+
console.log(chalk.red(` ✗ ${status.name} (${status.error})`));
|
|
68
|
+
}
|
|
69
|
+
if (outdated.length === 0) {
|
|
70
|
+
console.log(chalk.green("\nAll rules are up to date!"));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
console.log(chalk.yellow(`\n${outdated.length} rule(s) have updates available.`));
|
|
74
|
+
const response = await prompts({
|
|
75
|
+
type: "multiselect",
|
|
76
|
+
name: "toUpdate",
|
|
77
|
+
message: "Select rules to update:",
|
|
78
|
+
choices: outdated.map((s) => ({
|
|
79
|
+
title: s.name,
|
|
80
|
+
value: s.name,
|
|
81
|
+
selected: true,
|
|
82
|
+
})),
|
|
83
|
+
});
|
|
84
|
+
if (!response.toUpdate || response.toUpdate.length === 0) {
|
|
85
|
+
console.log(chalk.yellow("No rules selected for update."));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
console.log(chalk.blue("\nUpdating selected rules..."));
|
|
89
|
+
for (const ruleName of response.toUpdate) {
|
|
90
|
+
const destPath = join(rulesDir, ruleName);
|
|
91
|
+
try {
|
|
92
|
+
let content;
|
|
93
|
+
if (source.type === "local") {
|
|
94
|
+
content = readFile(join(source.path, "rules", ruleName));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
content = await fetchRemoteFile(`${GITHUB_RAW_BASE}/rules/${ruleName}`);
|
|
98
|
+
}
|
|
99
|
+
writeFile(destPath, content);
|
|
100
|
+
console.log(chalk.green(` Updated ${ruleName}`));
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.log(chalk.red(` Failed to update ${ruleName}: ${e}`));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
console.log(chalk.green("\nUpdate complete!"));
|
|
107
|
+
}
|
|
108
|
+
function hashContent(content) {
|
|
109
|
+
return crypto.createHash("md5").update(content).digest("hex");
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { initCommand } from "./commands/init.js";
|
|
4
|
+
import { injectCommand } from "./commands/inject.js";
|
|
5
|
+
import { updateCommand } from "./commands/update.js";
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program
|
|
8
|
+
.name("dev-rules")
|
|
9
|
+
.description("CLI tool to automate Senior Architect setup for projects")
|
|
10
|
+
.version("1.0.0");
|
|
11
|
+
program
|
|
12
|
+
.command("init <name>")
|
|
13
|
+
.description("Scaffold a new project with the latest standards")
|
|
14
|
+
.option("-t, --template <type>", "Project template (ts, python)", "ts")
|
|
15
|
+
.action(initCommand);
|
|
16
|
+
program
|
|
17
|
+
.command("inject")
|
|
18
|
+
.description("Add standards to the current directory")
|
|
19
|
+
.option("-f, --force", "Overwrite existing files", false)
|
|
20
|
+
.action(injectCommand);
|
|
21
|
+
program
|
|
22
|
+
.command("update")
|
|
23
|
+
.description("Check and update outdated rules from GitHub")
|
|
24
|
+
.action(updateCommand);
|
|
25
|
+
program.parse(process.argv);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,0DAA0D,CAAC;KACvE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,uBAAuB,EAAE,+BAA+B,EAAE,IAAI,CAAC;KACtE,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,aAAa,EAAE,0BAA0B,EAAE,KAAK,CAAC;KACxD,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-generator.d.ts","sourceRoot":"","sources":["../../src/utils/agents-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAiCpF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function generateAgentsMd(stack, rulesLocation) {
|
|
2
|
+
const ruleActivation = buildRuleActivation(stack, rulesLocation);
|
|
3
|
+
return `# AGENTS.md
|
|
4
|
+
|
|
5
|
+
## DEV STANDARDS (STRICT)
|
|
6
|
+
|
|
7
|
+
**Role:** Senior Engineer. **Manager:** User (Architect).
|
|
8
|
+
**Goal:** Production-Ready, Type-Safe, Modular.
|
|
9
|
+
|
|
10
|
+
### HARD CONSTRAINTS
|
|
11
|
+
1. **NO SPEC = NO CODE:** Demand \`SPEC.md\` before implementation.
|
|
12
|
+
2. **ZERO TOLERANCE:** No lint errors. No type errors (no \`any\`). No failing tests.
|
|
13
|
+
3. **ATOMICITY:** One feature at a time. No "while I'm here" refactoring.
|
|
14
|
+
4. **SAFETY:** All I/O wrapped in \`try/catch\`. All Secrets via ENV.
|
|
15
|
+
|
|
16
|
+
### RULE ACTIVATION
|
|
17
|
+
*You must strictly apply the following rules based on the task:*
|
|
18
|
+
${ruleActivation}
|
|
19
|
+
|
|
20
|
+
### ARCHITECTURE (3-LAYER)
|
|
21
|
+
1. **Presentation:** CLI/UI only. No logic.
|
|
22
|
+
2. **Service:** Pure business logic. No I/O context.
|
|
23
|
+
3. **Data:** DB/API access only.
|
|
24
|
+
*Use DTOs (Zod/Pydantic) for all layer communication.*
|
|
25
|
+
|
|
26
|
+
### WORKFLOW LOOP
|
|
27
|
+
1. **READ:** Development Guidance + Spec.
|
|
28
|
+
2. **PLAN:** Critically review spec for gaps.
|
|
29
|
+
3. **TDD:** Write failing test -> Validate failure.
|
|
30
|
+
4. **CODE:** Pass test -> Refactor -> Type Check.
|
|
31
|
+
5. **HALT:** If lint/test fails, fix immediately.
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
function buildRuleActivation(stack, rulesLocation) {
|
|
35
|
+
const lines = [];
|
|
36
|
+
lines.push(`- **All Projects:** \`${rulesLocation}/architecture.md\`, \`${rulesLocation}/workflow.md\``);
|
|
37
|
+
switch (stack.primary) {
|
|
38
|
+
case "typescript":
|
|
39
|
+
if (stack.hasReact) {
|
|
40
|
+
lines.push(`- **TypeScript/React:** \`${rulesLocation}/rules_ts.md\`, \`${rulesLocation}/rules_react.md\`, \`${rulesLocation}/logging.md\``);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
lines.push(`- **TypeScript:** \`${rulesLocation}/rules_ts.md\`, \`${rulesLocation}/logging.md\``);
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
case "python":
|
|
47
|
+
lines.push(`- **Python:** \`${rulesLocation}/rules_python.md\`, \`${rulesLocation}/logging.md\``);
|
|
48
|
+
break;
|
|
49
|
+
case "rust":
|
|
50
|
+
lines.push(`- **Rust:** \`${rulesLocation}/rules_rust.md\``);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
if (stack.hasDatabase) {
|
|
54
|
+
lines.push(`- **Database/SQL:** \`${rulesLocation}/rules_sql.md\``);
|
|
55
|
+
}
|
|
56
|
+
lines.push(`- **API/Security:** \`${rulesLocation}/api_design.md\`, \`${rulesLocation}/security.md\``);
|
|
57
|
+
return lines.join("\n");
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=agents-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-generator.js","sourceRoot":"","sources":["../../src/utils/agents-generator.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,KAAoB,EAAE,aAAqB;IAC1E,MAAM,cAAc,GAAG,mBAAmB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAEjE,OAAO;;;;;;;;;;;;;;;EAeP,cAAc;;;;;;;;;;;;;;CAcf,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAoB,EAAE,aAAqB;IACtE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,yBAAyB,aAAa,yBAAyB,aAAa,gBAAgB,CAAC,CAAC;IAEzG,QAAQ,KAAK,CAAC,OAAO,EAAE,CAAC;QACtB,KAAK,YAAY;YACf,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,KAAK,CAAC,IAAI,CAAC,6BAA6B,aAAa,qBAAqB,aAAa,wBAAwB,aAAa,eAAe,CAAC,CAAC;YAC/I,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,uBAAuB,aAAa,qBAAqB,aAAa,eAAe,CAAC,CAAC;YACpG,CAAC;YACD,MAAM;QACR,KAAK,QAAQ;YACX,KAAK,CAAC,IAAI,CAAC,mBAAmB,aAAa,yBAAyB,aAAa,eAAe,CAAC,CAAC;YAClG,MAAM;QACR,KAAK,MAAM;YACT,KAAK,CAAC,IAAI,CAAC,iBAAiB,aAAa,kBAAkB,CAAC,CAAC;YAC7D,MAAM;IACV,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,yBAAyB,aAAa,iBAAiB,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,yBAAyB,aAAa,uBAAuB,aAAa,gBAAgB,CAAC,CAAC;IAEvG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function ensureDir(dirPath: string): void;
|
|
2
|
+
export declare function readFile(filePath: string): string;
|
|
3
|
+
export declare function writeFile(filePath: string, content: string): void;
|
|
4
|
+
export declare function copyFile(src: string, dest: string): void;
|
|
5
|
+
export declare function listFiles(dirPath: string): string[];
|
|
6
|
+
export declare function fetchRemoteFile(url: string): Promise<string>;
|
|
7
|
+
//# sourceMappingURL=file-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-ops.d.ts","sourceRoot":"","sources":["../../src/utils/file-ops.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI/C;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAGjE;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAGxD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAKnD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB5D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, readdirSync } from "fs";
|
|
2
|
+
import { dirname } from "path";
|
|
3
|
+
import https from "https";
|
|
4
|
+
import http from "http";
|
|
5
|
+
export function ensureDir(dirPath) {
|
|
6
|
+
if (!existsSync(dirPath)) {
|
|
7
|
+
mkdirSync(dirPath, { recursive: true });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function readFile(filePath) {
|
|
11
|
+
return readFileSync(filePath, "utf-8");
|
|
12
|
+
}
|
|
13
|
+
export function writeFile(filePath, content) {
|
|
14
|
+
ensureDir(dirname(filePath));
|
|
15
|
+
writeFileSync(filePath, content, "utf-8");
|
|
16
|
+
}
|
|
17
|
+
export function copyFile(src, dest) {
|
|
18
|
+
ensureDir(dirname(dest));
|
|
19
|
+
copyFileSync(src, dest);
|
|
20
|
+
}
|
|
21
|
+
export function listFiles(dirPath) {
|
|
22
|
+
if (!existsSync(dirPath)) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
return readdirSync(dirPath);
|
|
26
|
+
}
|
|
27
|
+
export function fetchRemoteFile(url) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const protocol = url.startsWith("https") ? https : http;
|
|
30
|
+
protocol.get(url, (res) => {
|
|
31
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
32
|
+
const redirectUrl = res.headers.location;
|
|
33
|
+
if (redirectUrl) {
|
|
34
|
+
fetchRemoteFile(redirectUrl).then(resolve).catch(reject);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (res.statusCode !== 200) {
|
|
39
|
+
reject(new Error(`Failed to fetch ${url}: ${res.statusCode}`));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
let data = "";
|
|
43
|
+
res.on("data", (chunk) => (data += chunk));
|
|
44
|
+
res.on("end", () => resolve(data));
|
|
45
|
+
res.on("error", reject);
|
|
46
|
+
}).on("error", reject);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=file-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-ops.js","sourceRoot":"","sources":["../../src/utils/file-ops.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AACnG,OAAO,EAAQ,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,OAAe;IACzD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7B,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,IAAY;IAChD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACzB,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAExD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBACrD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACzC,IAAI,WAAW,EAAE,CAAC;oBAChB,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBACzD,OAAO;gBACT,CAAC;YACH,CAAC;YAED,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YAED,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines the source of truth for rules:
|
|
3
|
+
* - If running from within the dev-handbook repo, uses local files
|
|
4
|
+
* - Otherwise, indicates rules should be fetched from GitHub
|
|
5
|
+
*/
|
|
6
|
+
export declare function getRulesSource(): {
|
|
7
|
+
type: "local" | "remote";
|
|
8
|
+
path: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Get the path to rules directory
|
|
12
|
+
*/
|
|
13
|
+
export declare function getRulesPath(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get the path to templates directory
|
|
16
|
+
*/
|
|
17
|
+
export declare function getTemplatesPath(): string;
|
|
18
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,cAAc,IAAI;IAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAgB3E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
import { dirname, join, resolve } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
/**
|
|
7
|
+
* Determines the source of truth for rules:
|
|
8
|
+
* - If running from within the dev-handbook repo, uses local files
|
|
9
|
+
* - Otherwise, indicates rules should be fetched from GitHub
|
|
10
|
+
*/
|
|
11
|
+
export function getRulesSource() {
|
|
12
|
+
// Navigate from cli/dist/utils to repo root
|
|
13
|
+
const repoRoot = resolve(__dirname, "..", "..", "..");
|
|
14
|
+
const localRulesPath = join(repoRoot, "rules");
|
|
15
|
+
const localTemplatesPath = join(repoRoot, "templates");
|
|
16
|
+
// Check if we're running from within the dev-handbook repo
|
|
17
|
+
if (existsSync(localRulesPath) && existsSync(localTemplatesPath)) {
|
|
18
|
+
return { type: "local", path: repoRoot };
|
|
19
|
+
}
|
|
20
|
+
// Fall back to remote GitHub
|
|
21
|
+
return {
|
|
22
|
+
type: "remote",
|
|
23
|
+
path: "https://raw.githubusercontent.com/your-org/dev-handbook/main",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the path to rules directory
|
|
28
|
+
*/
|
|
29
|
+
export function getRulesPath() {
|
|
30
|
+
const source = getRulesSource();
|
|
31
|
+
return source.type === "local"
|
|
32
|
+
? join(source.path, "rules")
|
|
33
|
+
: `${source.path}/rules`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the path to templates directory
|
|
37
|
+
*/
|
|
38
|
+
export function getTemplatesPath() {
|
|
39
|
+
const source = getRulesSource();
|
|
40
|
+
return source.type === "local"
|
|
41
|
+
? join(source.path, "templates")
|
|
42
|
+
: `${source.path}/templates`;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAEvD,2DAA2D;IAC3D,IAAI,UAAU,CAAC,cAAc,CAAC,IAAI,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC3C,CAAC;IAED,6BAA6B;IAC7B,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,8DAA8D;KACrE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,IAAI,KAAK,OAAO;QAC5B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;QAC5B,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,QAAQ,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,IAAI,KAAK,OAAO;QAC5B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC;QAChC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,YAAY,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type StackType = "typescript" | "python" | "rust" | "unknown";
|
|
2
|
+
export interface DetectedStack {
|
|
3
|
+
primary: StackType;
|
|
4
|
+
hasReact: boolean;
|
|
5
|
+
hasDatabase: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function detectStack(targetDir: string): DetectedStack;
|
|
8
|
+
export declare function getRelevantRules(stack: DetectedStack): string[];
|
|
9
|
+
//# sourceMappingURL=stack-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-detector.d.ts","sourceRoot":"","sources":["../../src/utils/stack-detector.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAqC5D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAyB/D"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
export function detectStack(targetDir) {
|
|
4
|
+
const result = {
|
|
5
|
+
primary: "unknown",
|
|
6
|
+
hasReact: false,
|
|
7
|
+
hasDatabase: false,
|
|
8
|
+
};
|
|
9
|
+
const tsIndicators = ["package.json", "tsconfig.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"];
|
|
10
|
+
const pythonIndicators = ["pyproject.toml", "requirements.txt", "setup.py", "Pipfile"];
|
|
11
|
+
const rustIndicators = ["Cargo.toml", "Cargo.lock"];
|
|
12
|
+
const hasTs = tsIndicators.some((f) => existsSync(join(targetDir, f)));
|
|
13
|
+
const hasPython = pythonIndicators.some((f) => existsSync(join(targetDir, f)));
|
|
14
|
+
const hasRust = rustIndicators.some((f) => existsSync(join(targetDir, f)));
|
|
15
|
+
if (hasTs) {
|
|
16
|
+
result.primary = "typescript";
|
|
17
|
+
const packageJsonPath = join(targetDir, "package.json");
|
|
18
|
+
if (existsSync(packageJsonPath)) {
|
|
19
|
+
try {
|
|
20
|
+
const pkg = require(packageJsonPath);
|
|
21
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
22
|
+
result.hasReact = "react" in allDeps;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else if (hasPython) {
|
|
29
|
+
result.primary = "python";
|
|
30
|
+
}
|
|
31
|
+
else if (hasRust) {
|
|
32
|
+
result.primary = "rust";
|
|
33
|
+
}
|
|
34
|
+
const sqlIndicators = [".sql", "migrations", "prisma", "drizzle.config.ts", "knexfile.js"];
|
|
35
|
+
result.hasDatabase = sqlIndicators.some((f) => existsSync(join(targetDir, f)));
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
export function getRelevantRules(stack) {
|
|
39
|
+
const rules = ["architecture.md", "workflow.md", "security.md"];
|
|
40
|
+
switch (stack.primary) {
|
|
41
|
+
case "typescript":
|
|
42
|
+
rules.push("rules_ts.md", "logging.md", "testing.md");
|
|
43
|
+
if (stack.hasReact) {
|
|
44
|
+
rules.push("rules_react.md");
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
case "python":
|
|
48
|
+
rules.push("rules_python.md", "logging.md", "testing.md");
|
|
49
|
+
break;
|
|
50
|
+
case "rust":
|
|
51
|
+
rules.push("rules_rust.md", "testing.md");
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
if (stack.hasDatabase) {
|
|
55
|
+
rules.push("rules_sql.md");
|
|
56
|
+
}
|
|
57
|
+
rules.push("api_design.md", "documentation.md");
|
|
58
|
+
return rules;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=stack-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-detector.js","sourceRoot":"","sources":["../../src/utils/stack-detector.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dev-rules",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to automate Senior Architect setup for new and existing projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"dev-rules": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "ts-node src/index.ts",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"cli",
|
|
18
|
+
"developer-tools",
|
|
19
|
+
"standards",
|
|
20
|
+
"architect",
|
|
21
|
+
"coding-standards"
|
|
22
|
+
],
|
|
23
|
+
"author": "",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
|
+
"commander": "^12.1.0",
|
|
28
|
+
"prompts": "^2.4.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^20.14.0",
|
|
32
|
+
"@types/prompts": "^2.4.9",
|
|
33
|
+
"ts-node": "^10.9.2",
|
|
34
|
+
"typescript": "^5.4.5"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/your-org/dev-handbook"
|
|
46
|
+
}
|
|
47
|
+
}
|