lee-spec-kit 0.1.7 → 0.1.8
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/dist/index.js +131 -28
- package/package.json +10 -8
- package/templates/en/fullstack/agents/agents.md +28 -0
- package/templates/en/fullstack/agents/custom.md +29 -0
- package/templates/en/fullstack/agents/git-workflow.md +8 -9
- package/templates/en/single/agents/agents.md +28 -0
- package/templates/en/single/agents/custom.md +29 -0
- package/templates/en/single/agents/git-workflow.md +8 -9
- package/templates/ko/fullstack/agents/agents.md +28 -0
- package/templates/ko/fullstack/agents/custom.md +29 -0
- package/templates/ko/fullstack/agents/git-workflow.md +8 -9
- package/templates/ko/single/agents/agents.md +28 -0
- package/templates/ko/single/agents/custom.md +29 -0
- package/templates/ko/single/agents/git-workflow.md +8 -9
package/dist/index.js
CHANGED
|
@@ -3,12 +3,12 @@ import { program } from 'commander';
|
|
|
3
3
|
import prompts from 'prompts';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import path3 from 'path';
|
|
6
|
-
import
|
|
6
|
+
import fs6 from 'fs-extra';
|
|
7
7
|
import { glob } from 'glob';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
|
|
10
10
|
async function copyTemplates(src, dest) {
|
|
11
|
-
await
|
|
11
|
+
await fs6.copy(src, dest, {
|
|
12
12
|
overwrite: true,
|
|
13
13
|
errorOnExist: false
|
|
14
14
|
});
|
|
@@ -16,19 +16,19 @@ async function copyTemplates(src, dest) {
|
|
|
16
16
|
async function replaceInFiles(dir, replacements) {
|
|
17
17
|
const files = await glob("**/*.md", { cwd: dir, absolute: true });
|
|
18
18
|
for (const file of files) {
|
|
19
|
-
let content = await
|
|
19
|
+
let content = await fs6.readFile(file, "utf-8");
|
|
20
20
|
for (const [search, replace] of Object.entries(replacements)) {
|
|
21
21
|
content = content.replaceAll(search, replace);
|
|
22
22
|
}
|
|
23
|
-
await
|
|
23
|
+
await fs6.writeFile(file, content, "utf-8");
|
|
24
24
|
}
|
|
25
25
|
const shFiles = await glob("**/*.sh", { cwd: dir, absolute: true });
|
|
26
26
|
for (const file of shFiles) {
|
|
27
|
-
let content = await
|
|
27
|
+
let content = await fs6.readFile(file, "utf-8");
|
|
28
28
|
for (const [search, replace] of Object.entries(replacements)) {
|
|
29
29
|
content = content.replaceAll(search, replace);
|
|
30
30
|
}
|
|
31
|
-
await
|
|
31
|
+
await fs6.writeFile(file, content, "utf-8");
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
@@ -209,8 +209,8 @@ async function runInit(options) {
|
|
|
209
209
|
assertValid(validateSafeName(projectName), "\uD504\uB85C\uC81D\uD2B8 \uC774\uB984");
|
|
210
210
|
assertValid(validateProjectType(projectType), "\uD504\uB85C\uC81D\uD2B8 \uD0C0\uC785");
|
|
211
211
|
assertValid(validateLanguage(lang), "\uC5B8\uC5B4");
|
|
212
|
-
if (await
|
|
213
|
-
const files = await
|
|
212
|
+
if (await fs6.pathExists(targetDir)) {
|
|
213
|
+
const files = await fs6.readdir(targetDir);
|
|
214
214
|
if (files.length > 0) {
|
|
215
215
|
const { overwrite } = await prompts({
|
|
216
216
|
type: "confirm",
|
|
@@ -233,7 +233,7 @@ async function runInit(options) {
|
|
|
233
233
|
console.log();
|
|
234
234
|
const templatesDir = getTemplatesDir();
|
|
235
235
|
const templatePath = path3.join(templatesDir, lang, projectType);
|
|
236
|
-
if (!await
|
|
236
|
+
if (!await fs6.pathExists(templatePath)) {
|
|
237
237
|
throw new Error(`\uD15C\uD50C\uB9BF\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${templatePath}`);
|
|
238
238
|
}
|
|
239
239
|
await copyTemplates(templatePath, targetDir);
|
|
@@ -249,7 +249,7 @@ async function runInit(options) {
|
|
|
249
249
|
createdAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
|
|
250
250
|
};
|
|
251
251
|
const configPath = path3.join(targetDir, ".lee-spec-kit.json");
|
|
252
|
-
await
|
|
252
|
+
await fs6.writeJson(configPath, config, { spaces: 2 });
|
|
253
253
|
console.log(chalk.green("\u2705 docs \uAD6C\uC870 \uC0DD\uC131 \uC644\uB8CC!"));
|
|
254
254
|
console.log();
|
|
255
255
|
await initGit(cwd, targetDir);
|
|
@@ -296,9 +296,9 @@ async function getConfig(cwd) {
|
|
|
296
296
|
];
|
|
297
297
|
for (const docsDir of possibleDirs) {
|
|
298
298
|
const configPath = path3.join(docsDir, ".lee-spec-kit.json");
|
|
299
|
-
if (await
|
|
299
|
+
if (await fs6.pathExists(configPath)) {
|
|
300
300
|
try {
|
|
301
|
-
const configFile = await
|
|
301
|
+
const configFile = await fs6.readJson(configPath);
|
|
302
302
|
return {
|
|
303
303
|
docsDir,
|
|
304
304
|
projectName: configFile.projectName,
|
|
@@ -310,14 +310,14 @@ async function getConfig(cwd) {
|
|
|
310
310
|
}
|
|
311
311
|
const agentsPath = path3.join(docsDir, "agents");
|
|
312
312
|
const featuresPath = path3.join(docsDir, "features");
|
|
313
|
-
if (await
|
|
313
|
+
if (await fs6.pathExists(agentsPath) && await fs6.pathExists(featuresPath)) {
|
|
314
314
|
const bePath = path3.join(featuresPath, "be");
|
|
315
315
|
const fePath = path3.join(featuresPath, "fe");
|
|
316
|
-
const projectType = await
|
|
316
|
+
const projectType = await fs6.pathExists(bePath) || await fs6.pathExists(fePath) ? "fullstack" : "single";
|
|
317
317
|
const agentsMdPath = path3.join(agentsPath, "agents.md");
|
|
318
318
|
let lang = "ko";
|
|
319
|
-
if (await
|
|
320
|
-
const content = await
|
|
319
|
+
if (await fs6.pathExists(agentsMdPath)) {
|
|
320
|
+
const content = await fs6.readFile(agentsMdPath, "utf-8");
|
|
321
321
|
if (!/[가-힣]/.test(content)) {
|
|
322
322
|
lang = "en";
|
|
323
323
|
}
|
|
@@ -392,16 +392,16 @@ async function runFeature(name, options) {
|
|
|
392
392
|
}
|
|
393
393
|
const featureFolderName = `${featureId}-${name}`;
|
|
394
394
|
const featureDir = path3.join(featuresDir, featureFolderName);
|
|
395
|
-
if (await
|
|
395
|
+
if (await fs6.pathExists(featureDir)) {
|
|
396
396
|
console.error(chalk.red(`\uC774\uBBF8 \uC874\uC7AC\uD558\uB294 \uD3F4\uB354\uC785\uB2C8\uB2E4: ${featureDir}`));
|
|
397
397
|
process.exit(1);
|
|
398
398
|
}
|
|
399
399
|
const featureBasePath = path3.join(docsDir, "features", "feature-base");
|
|
400
|
-
if (!await
|
|
400
|
+
if (!await fs6.pathExists(featureBasePath)) {
|
|
401
401
|
console.error(chalk.red("feature-base \uD15C\uD50C\uB9BF\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
402
402
|
process.exit(1);
|
|
403
403
|
}
|
|
404
|
-
await
|
|
404
|
+
await fs6.copy(featureBasePath, featureDir);
|
|
405
405
|
const idNumber = featureId.replace("F", "");
|
|
406
406
|
const repoName = projectType === "fullstack" && repo ? `{{projectName}}-${repo}` : "{{projectName}}";
|
|
407
407
|
const replacements = {
|
|
@@ -442,8 +442,8 @@ async function getNextFeatureId(docsDir, projectType) {
|
|
|
442
442
|
scanDirs.push(featuresDir);
|
|
443
443
|
}
|
|
444
444
|
for (const dir of scanDirs) {
|
|
445
|
-
if (!await
|
|
446
|
-
const entries = await
|
|
445
|
+
if (!await fs6.pathExists(dir)) continue;
|
|
446
|
+
const entries = await fs6.readdir(dir, { withFileTypes: true });
|
|
447
447
|
for (const entry of entries) {
|
|
448
448
|
if (!entry.isDirectory()) continue;
|
|
449
449
|
const match = entry.name.match(/^F(\d+)-/);
|
|
@@ -483,18 +483,18 @@ async function runStatus(options) {
|
|
|
483
483
|
const scopes = projectType === "fullstack" ? ["be", "fe"] : [""];
|
|
484
484
|
for (const scope of scopes) {
|
|
485
485
|
const scanDir = scope ? path3.join(featuresDir, scope) : featuresDir;
|
|
486
|
-
if (!await
|
|
487
|
-
const entries = await
|
|
486
|
+
if (!await fs6.pathExists(scanDir)) continue;
|
|
487
|
+
const entries = await fs6.readdir(scanDir, { withFileTypes: true });
|
|
488
488
|
for (const entry of entries) {
|
|
489
489
|
if (!entry.isDirectory()) continue;
|
|
490
490
|
if (entry.name === "feature-base") continue;
|
|
491
491
|
const featureDir = path3.join(scanDir, entry.name);
|
|
492
492
|
const specPath = path3.join(featureDir, "spec.md");
|
|
493
493
|
const tasksPath = path3.join(featureDir, "tasks.md");
|
|
494
|
-
if (!await
|
|
495
|
-
if (!await
|
|
496
|
-
const specContent = await
|
|
497
|
-
const tasksContent = await
|
|
494
|
+
if (!await fs6.pathExists(specPath)) continue;
|
|
495
|
+
if (!await fs6.pathExists(tasksPath)) continue;
|
|
496
|
+
const specContent = await fs6.readFile(specPath, "utf-8");
|
|
497
|
+
const tasksContent = await fs6.readFile(tasksPath, "utf-8");
|
|
498
498
|
const id = extractSpecValue(specContent, "\uAE30\uB2A5 ID") || extractSpecValue(specContent, "Feature ID") || "UNKNOWN";
|
|
499
499
|
const name = extractSpecValue(specContent, "\uAE30\uB2A5\uBA85") || extractSpecValue(specContent, "Feature Name") || entry.name;
|
|
500
500
|
const repo = extractSpecValue(specContent, "\uB300\uC0C1 \uB808\uD3EC") || extractSpecValue(specContent, "Target Repo") || (scope ? `{{projectName}}-${scope}` : "{{projectName}}");
|
|
@@ -584,7 +584,7 @@ async function runStatus(options) {
|
|
|
584
584
|
),
|
|
585
585
|
""
|
|
586
586
|
].join("\n");
|
|
587
|
-
await
|
|
587
|
+
await fs6.writeFile(outputPath, content, "utf-8");
|
|
588
588
|
console.log(chalk.green(`\u2705 ${outputPath} \uC0DD\uC131 \uC644\uB8CC`));
|
|
589
589
|
}
|
|
590
590
|
}
|
|
@@ -611,6 +611,108 @@ function countTasks(content) {
|
|
|
611
611
|
}
|
|
612
612
|
return { total, done, doing, todo };
|
|
613
613
|
}
|
|
614
|
+
function updateCommand(program2) {
|
|
615
|
+
program2.command("update").description("Update docs templates to the latest version").option("--agents", "Update agents/ folder only").option("--templates", "Update feature-base/ folder only").option("-f, --force", "Force overwrite without confirmation").action(async (options) => {
|
|
616
|
+
try {
|
|
617
|
+
await runUpdate(options);
|
|
618
|
+
} catch (error) {
|
|
619
|
+
if (error instanceof Error && error.message === "canceled") {
|
|
620
|
+
console.log(chalk.yellow("\n\uC791\uC5C5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
621
|
+
process.exit(0);
|
|
622
|
+
}
|
|
623
|
+
console.error(chalk.red("\uC624\uB958:"), error);
|
|
624
|
+
process.exit(1);
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
async function runUpdate(options) {
|
|
629
|
+
const cwd = process.cwd();
|
|
630
|
+
const config = await getConfig(cwd);
|
|
631
|
+
if (!config) {
|
|
632
|
+
console.error(
|
|
633
|
+
chalk.red("docs \uD3F4\uB354\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 init\uC744 \uC2E4\uD589\uD558\uC138\uC694.")
|
|
634
|
+
);
|
|
635
|
+
process.exit(1);
|
|
636
|
+
}
|
|
637
|
+
const { docsDir, projectType, lang } = config;
|
|
638
|
+
const templatesDir = getTemplatesDir();
|
|
639
|
+
const sourceDir = path3.join(templatesDir, lang, projectType);
|
|
640
|
+
const updateAgents = options.agents || !options.agents && !options.templates;
|
|
641
|
+
const updateTemplates = options.templates || !options.agents && !options.templates;
|
|
642
|
+
console.log(chalk.blue("\u{1F4E6} \uD15C\uD50C\uB9BF \uC5C5\uB370\uC774\uD2B8\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4..."));
|
|
643
|
+
console.log(chalk.gray(` - \uC5B8\uC5B4: ${lang}`));
|
|
644
|
+
console.log(chalk.gray(` - \uD0C0\uC785: ${projectType}`));
|
|
645
|
+
console.log();
|
|
646
|
+
let updatedCount = 0;
|
|
647
|
+
if (updateAgents) {
|
|
648
|
+
console.log(chalk.blue("\u{1F4C1} agents/ \uD3F4\uB354 \uC5C5\uB370\uC774\uD2B8 \uC911..."));
|
|
649
|
+
const sourceAgents = path3.join(sourceDir, "agents");
|
|
650
|
+
const targetAgents = path3.join(docsDir, "agents");
|
|
651
|
+
if (await fs6.pathExists(sourceAgents)) {
|
|
652
|
+
const count = await updateFolder(
|
|
653
|
+
sourceAgents,
|
|
654
|
+
targetAgents,
|
|
655
|
+
options.force
|
|
656
|
+
);
|
|
657
|
+
updatedCount += count;
|
|
658
|
+
console.log(chalk.green(` \u2705 ${count}\uAC1C \uD30C\uC77C \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC`));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (updateTemplates) {
|
|
662
|
+
console.log(chalk.blue("\u{1F4C1} features/feature-base/ \uD3F4\uB354 \uC5C5\uB370\uC774\uD2B8 \uC911..."));
|
|
663
|
+
const sourceFeatureBase = path3.join(sourceDir, "features", "feature-base");
|
|
664
|
+
const targetFeatureBase = path3.join(docsDir, "features", "feature-base");
|
|
665
|
+
if (await fs6.pathExists(sourceFeatureBase)) {
|
|
666
|
+
const count = await updateFolder(
|
|
667
|
+
sourceFeatureBase,
|
|
668
|
+
targetFeatureBase,
|
|
669
|
+
options.force
|
|
670
|
+
);
|
|
671
|
+
updatedCount += count;
|
|
672
|
+
console.log(chalk.green(` \u2705 ${count}\uAC1C \uD30C\uC77C \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC`));
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
console.log();
|
|
676
|
+
console.log(chalk.green(`\u2705 \uCD1D ${updatedCount}\uAC1C \uD30C\uC77C \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC!`));
|
|
677
|
+
}
|
|
678
|
+
async function updateFolder(sourceDir, targetDir, force) {
|
|
679
|
+
await fs6.ensureDir(targetDir);
|
|
680
|
+
const files = await fs6.readdir(sourceDir);
|
|
681
|
+
let updatedCount = 0;
|
|
682
|
+
for (const file of files) {
|
|
683
|
+
const sourcePath = path3.join(sourceDir, file);
|
|
684
|
+
const targetPath = path3.join(targetDir, file);
|
|
685
|
+
const stat = await fs6.stat(sourcePath);
|
|
686
|
+
if (stat.isFile()) {
|
|
687
|
+
if (file === "custom.md") {
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
const sourceContent = await fs6.readFile(sourcePath, "utf-8");
|
|
691
|
+
let shouldUpdate = true;
|
|
692
|
+
if (await fs6.pathExists(targetPath)) {
|
|
693
|
+
const targetContent = await fs6.readFile(targetPath, "utf-8");
|
|
694
|
+
if (sourceContent === targetContent) {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
if (!force) {
|
|
698
|
+
console.log(
|
|
699
|
+
chalk.yellow(` \u26A0\uFE0F ${file} - \uBCC0\uACBD \uAC10\uC9C0 (--force\uB85C \uB36E\uC5B4\uC4F0\uAE30)`)
|
|
700
|
+
);
|
|
701
|
+
shouldUpdate = false;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (shouldUpdate) {
|
|
705
|
+
await fs6.writeFile(targetPath, sourceContent);
|
|
706
|
+
console.log(chalk.gray(` \u{1F4C4} ${file} \uC5C5\uB370\uC774\uD2B8`));
|
|
707
|
+
updatedCount++;
|
|
708
|
+
}
|
|
709
|
+
} else if (stat.isDirectory()) {
|
|
710
|
+
const subCount = await updateFolder(sourcePath, targetPath, force);
|
|
711
|
+
updatedCount += subCount;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return updatedCount;
|
|
715
|
+
}
|
|
614
716
|
|
|
615
717
|
// src/index.ts
|
|
616
718
|
program.name("lee-spec-kit").description(
|
|
@@ -619,4 +721,5 @@ program.name("lee-spec-kit").description(
|
|
|
619
721
|
initCommand(program);
|
|
620
722
|
featureCommand(program);
|
|
621
723
|
statusCommand(program);
|
|
724
|
+
updateCommand(program);
|
|
622
725
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lee-spec-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Project documentation structure generator for AI-assisted development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
"dist",
|
|
13
13
|
"templates"
|
|
14
14
|
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"dev": "tsup --watch",
|
|
18
|
+
"lint": "eslint src",
|
|
19
|
+
"format": "prettier --write .",
|
|
20
|
+
"prepublishOnly": "pnpm build"
|
|
21
|
+
},
|
|
15
22
|
"keywords": [
|
|
16
23
|
"docs",
|
|
17
24
|
"template",
|
|
@@ -49,10 +56,5 @@
|
|
|
49
56
|
"tsup": "^8.5.1",
|
|
50
57
|
"typescript": "^5.9.3"
|
|
51
58
|
},
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
"dev": "tsup --watch",
|
|
55
|
-
"lint": "eslint src",
|
|
56
|
-
"format": "prettier --write ."
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
+
"packageManager": "pnpm@10.7.0"
|
|
60
|
+
}
|
|
@@ -4,10 +4,38 @@ Operating rules for AI code assistants to perform consistent code generation and
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## 🚨 User Approval Required (MUST)
|
|
8
|
+
|
|
9
|
+
> ⚠️ **The following actions require explicit user approval (OK) before proceeding.**
|
|
10
|
+
> **If approval is not given, stop immediately and request confirmation.**
|
|
11
|
+
|
|
12
|
+
| Action | When to Confirm | What to Share |
|
|
13
|
+
| --------------------- | ------------------------ | ------------------------- |
|
|
14
|
+
| Spec Writing | After writing `spec.md` | Full spec content |
|
|
15
|
+
| Task Execution | Before each task | Execution plan |
|
|
16
|
+
| Commit Creation | Before `git commit` | Commit message, file list |
|
|
17
|
+
| Issue Creation | Before `gh issue create` | Title, body, labels |
|
|
18
|
+
| PR Creation | Before `gh pr create` | Title, body, labels |
|
|
19
|
+
| Assignee Change | When assigning others | Target username |
|
|
20
|
+
| Remote Git Operations | Before `push`, `merge` | Branch, changes |
|
|
21
|
+
|
|
22
|
+
### Approval Process
|
|
23
|
+
|
|
24
|
+
1. **Share** action details with user first
|
|
25
|
+
2. **Wait** for explicit user approval (OK)
|
|
26
|
+
3. **Execute** only after approval
|
|
27
|
+
|
|
28
|
+
> 🚫 **Prohibited**: Proceeding without user response
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## Reference Documents
|
|
8
33
|
|
|
9
34
|
### Core Documents
|
|
10
35
|
|
|
36
|
+
> ⚠️ **Rules in `custom.md` take precedence over all other rules.**
|
|
37
|
+
|
|
38
|
+
- **🔴 Custom Rules (Highest Priority)**: `/docs/agents/custom.md`
|
|
11
39
|
- **Project Principles**: `/docs/agents/constitution.md`
|
|
12
40
|
- **Git Workflow**: `/docs/agents/git-workflow.md`
|
|
13
41
|
- **Issue Template**: `/docs/agents/issue-template.md`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Custom Rules
|
|
2
|
+
|
|
3
|
+
> ⚠️ This document contains **user-defined rules**.
|
|
4
|
+
> It is NOT affected by `npx lee-spec-kit update`.
|
|
5
|
+
> **Rules in this document take precedence over all other agent rules.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Project-Specific Rules
|
|
10
|
+
|
|
11
|
+
(Write your project-specific rules here)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Additional Language/Code Rules
|
|
16
|
+
|
|
17
|
+
(Override default rules or add additional rules here)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Custom Workflows
|
|
22
|
+
|
|
23
|
+
(Write project-specific workflows here)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Other
|
|
28
|
+
|
|
29
|
+
(Write other rules here)
|
|
@@ -73,17 +73,16 @@ main
|
|
|
73
73
|
git checkout -b feat/{issue-number}-{feature-name}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
### 2. Document
|
|
76
|
+
### 2. Document Commit (docs repo)
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
| ------------ | ----------------------- | ------------------------------ |
|
|
80
|
-
| spec.md | After user approval | `docs(#123): write spec` |
|
|
81
|
-
| plan.md | After user approval | `docs(#123): write plan` |
|
|
82
|
-
| tasks.md | After user approval | `docs(#123): break down tasks` |
|
|
83
|
-
| decisions.md | Included in task commit | (no separate commit) |
|
|
78
|
+
> 📌 The docs folder is managed as a separate git, so a separate commit strategy is used.
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
| # | Commit Timing | Included Documents | Commit Message Example |
|
|
81
|
+
| --- | -------------------------------------------------------- | ------------------------------- | ------------------------------- |
|
|
82
|
+
| 1 | **When planning is complete** (spec+plan+tasks approved) | spec.md, plan.md, tasks.md | `docs(#123): spec, plan, tasks` |
|
|
83
|
+
| 2 | **When Feature is complete** (all tasks done) | tasks.md (status), decisions.md | `docs(#123): Feature complete` |
|
|
84
|
+
|
|
85
|
+
> ⚠️ **Do not commit when creating Feature folder.**
|
|
87
86
|
|
|
88
87
|
### 3. Auto Commit on Task Completion
|
|
89
88
|
|
|
@@ -4,10 +4,38 @@ Operating rules for AI code assistants to perform consistent code generation and
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## 🚨 User Approval Required (MUST)
|
|
8
|
+
|
|
9
|
+
> ⚠️ **The following actions require explicit user approval (OK) before proceeding.**
|
|
10
|
+
> **If approval is not given, stop immediately and request confirmation.**
|
|
11
|
+
|
|
12
|
+
| Action | When to Confirm | What to Share |
|
|
13
|
+
| --------------------- | ------------------------ | ------------------------- |
|
|
14
|
+
| Spec Writing | After writing `spec.md` | Full spec content |
|
|
15
|
+
| Task Execution | Before each task | Execution plan |
|
|
16
|
+
| Commit Creation | Before `git commit` | Commit message, file list |
|
|
17
|
+
| Issue Creation | Before `gh issue create` | Title, body, labels |
|
|
18
|
+
| PR Creation | Before `gh pr create` | Title, body, labels |
|
|
19
|
+
| Assignee Change | When assigning others | Target username |
|
|
20
|
+
| Remote Git Operations | Before `push`, `merge` | Branch, changes |
|
|
21
|
+
|
|
22
|
+
### Approval Process
|
|
23
|
+
|
|
24
|
+
1. **Share** action details with user first
|
|
25
|
+
2. **Wait** for explicit user approval (OK)
|
|
26
|
+
3. **Execute** only after approval
|
|
27
|
+
|
|
28
|
+
> 🚫 **Prohibited**: Proceeding without user response
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## Reference Documents
|
|
8
33
|
|
|
9
34
|
### Core Documents
|
|
10
35
|
|
|
36
|
+
> ⚠️ **Rules in `custom.md` take precedence over all other rules.**
|
|
37
|
+
|
|
38
|
+
- **🔴 Custom Rules (Highest Priority)**: `/docs/agents/custom.md`
|
|
11
39
|
- **Project Principles**: `/docs/agents/constitution.md`
|
|
12
40
|
- **Git Workflow**: `/docs/agents/git-workflow.md`
|
|
13
41
|
- **Issue Template**: `/docs/agents/issue-template.md`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Custom Rules
|
|
2
|
+
|
|
3
|
+
> ⚠️ This document contains **user-defined rules**.
|
|
4
|
+
> It is NOT affected by `npx lee-spec-kit update`.
|
|
5
|
+
> **Rules in this document take precedence over all other agent rules.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Project-Specific Rules
|
|
10
|
+
|
|
11
|
+
(Write your project-specific rules here)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Additional Language/Code Rules
|
|
16
|
+
|
|
17
|
+
(Override default rules or add additional rules here)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Custom Workflows
|
|
22
|
+
|
|
23
|
+
(Write project-specific workflows here)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Other
|
|
28
|
+
|
|
29
|
+
(Write other rules here)
|
|
@@ -80,17 +80,16 @@ git checkout -b feat/{issue-number}-{feature-name}
|
|
|
80
80
|
|
|
81
81
|
> When creating/modifying issues/PRs with `gh`, share the title/body/labels first and **wait for user confirmation (OK)** before proceeding.
|
|
82
82
|
|
|
83
|
-
### 2. Document
|
|
83
|
+
### 2. Document Commit (docs repo)
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
| ------------ | ----------------------- | ------------------------------ |
|
|
87
|
-
| spec.md | After user approval | `docs(#123): write spec` |
|
|
88
|
-
| plan.md | After user approval | `docs(#123): write plan` |
|
|
89
|
-
| tasks.md | After user approval | `docs(#123): break down tasks` |
|
|
90
|
-
| decisions.md | Included in task commit | (no separate commit) |
|
|
85
|
+
> 📌 The docs folder is managed as a separate git, so a separate commit strategy is used.
|
|
91
86
|
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
| # | Commit Timing | Included Documents | Commit Message Example |
|
|
88
|
+
| --- | -------------------------------------------------------- | ------------------------------- | ------------------------------- |
|
|
89
|
+
| 1 | **When planning is complete** (spec+plan+tasks approved) | spec.md, plan.md, tasks.md | `docs(#123): spec, plan, tasks` |
|
|
90
|
+
| 2 | **When Feature is complete** (all tasks done) | tasks.md (status), decisions.md | `docs(#123): Feature complete` |
|
|
91
|
+
|
|
92
|
+
> ⚠️ **Do not commit when creating Feature folder.**
|
|
94
93
|
|
|
95
94
|
### 3. Auto Commit on Task Completion
|
|
96
95
|
|
|
@@ -4,10 +4,38 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## 🚨 사용자 확인 필수 규칙 (MUST)
|
|
8
|
+
|
|
9
|
+
> ⚠️ **아래 작업은 반드시 사용자의 명시적 승인(OK)을 받은 후에만 진행합니다.**
|
|
10
|
+
> **확인 없이 진행 시 작업을 즉시 중단해야 합니다.**
|
|
11
|
+
|
|
12
|
+
| 작업 | 확인 시점 | 공유 내용 |
|
|
13
|
+
| ------------- | -------------------- | --------------------------- |
|
|
14
|
+
| 스펙 작성 | `spec.md` 작성 후 | 스펙 내용 전문 |
|
|
15
|
+
| 태스크 실행 | 각 태스크 시작 전 | 실행 계획 |
|
|
16
|
+
| 커밋 생성 | `git commit` 전 | 커밋 메시지, 포함 파일 목록 |
|
|
17
|
+
| 이슈 생성 | `gh issue create` 전 | 제목, 본문, 라벨 |
|
|
18
|
+
| PR 생성 | `gh pr create` 전 | 제목, 본문, 라벨 |
|
|
19
|
+
| Assignee 변경 | 본인 외 지정 시 | 대상 사용자명 |
|
|
20
|
+
| Git 원격 작업 | `push`, `merge` 전 | 브랜치, 변경 사항 |
|
|
21
|
+
|
|
22
|
+
### 확인 프로세스
|
|
23
|
+
|
|
24
|
+
1. 작업 내용을 사용자에게 **먼저 공유**
|
|
25
|
+
2. 사용자의 **명시적 승인(OK)** 대기
|
|
26
|
+
3. 승인 후에만 실행
|
|
27
|
+
|
|
28
|
+
> 🚫 **금지 사항**: 사용자 응답 없이 임의로 진행하는 것
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## 참조 문서
|
|
8
33
|
|
|
9
34
|
### 핵심 문서
|
|
10
35
|
|
|
36
|
+
> ⚠️ **`custom.md`의 규칙은 다른 모든 규칙보다 우선합니다.**
|
|
37
|
+
|
|
38
|
+
- **🔴 커스텀 규칙 (최우선)**: `/docs/agents/custom.md`
|
|
11
39
|
- **프로젝트 원칙**: `/docs/agents/constitution.md`
|
|
12
40
|
- **Git 워크플로우**: `/docs/agents/git-workflow.md`
|
|
13
41
|
- **이슈 템플릿**: `/docs/agents/issue-template.md`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Custom Rules
|
|
2
|
+
|
|
3
|
+
> ⚠️ 이 문서는 **사용자 정의 규칙**입니다.
|
|
4
|
+
> `npx lee-spec-kit update`의 영향을 받지 않습니다.
|
|
5
|
+
> **이 문서의 규칙은 다른 모든 agents 규칙보다 우선합니다.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 프로젝트 특화 규칙
|
|
10
|
+
|
|
11
|
+
(여기에 프로젝트만의 규칙을 작성하세요)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 추가 언어/코드 규칙
|
|
16
|
+
|
|
17
|
+
(기본 규칙을 오버라이드하거나 추가 규칙을 작성하세요)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 커스텀 워크플로우
|
|
22
|
+
|
|
23
|
+
(프로젝트만의 워크플로우가 있다면 작성하세요)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 기타
|
|
28
|
+
|
|
29
|
+
(기타 규칙을 작성하세요)
|
|
@@ -80,17 +80,16 @@ git checkout -b feat/{issue-number}-{feature-name}
|
|
|
80
80
|
|
|
81
81
|
> `gh`로 이슈/PR 생성·수정 시 작성할 제목/본문/라벨을 먼저 공유하고 **반드시** 사용자 확인(OK) 후 진행합니다.
|
|
82
82
|
|
|
83
|
-
### 2. 문서
|
|
83
|
+
### 2. 문서 커밋 (docs 레포)
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
| ------------ | ------------------ | ------------------------ |
|
|
87
|
-
| spec.md | 사용자 승인 후 | `docs(#123): spec 작성` |
|
|
88
|
-
| plan.md | 사용자 승인 후 | `docs(#123): plan 작성` |
|
|
89
|
-
| tasks.md | 사용자 승인 후 | `docs(#123): tasks 분해` |
|
|
90
|
-
| decisions.md | 태스크 커밋에 포함 | (별도 커밋 없음) |
|
|
85
|
+
> 📌 docs 폴더는 별도 git으로 관리되므로 프로젝트와 분리된 커밋 전략을 사용합니다.
|
|
91
86
|
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
| # | 커밋 시점 | 포함 문서 | 커밋 메시지 예시 |
|
|
88
|
+
| --- | ------------------------------------------ | ----------------------------- | ------------------------------------ |
|
|
89
|
+
| 1 | **계획 완료 시** (spec+plan+tasks 승인 후) | spec.md, plan.md, tasks.md | `docs(#123): spec, plan, tasks 작성` |
|
|
90
|
+
| 2 | **Feature 완료 시** (모든 태스크 완료 후) | tasks.md (상태), decisions.md | `docs(#123): Feature 완료` |
|
|
91
|
+
|
|
92
|
+
> ⚠️ **Feature 폴더 생성 시점**에는 커밋하지 않습니다.
|
|
94
93
|
|
|
95
94
|
### 3. 태스크 완료 시 자동 커밋
|
|
96
95
|
|
|
@@ -4,10 +4,38 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## 🚨 사용자 확인 필수 규칙 (MUST)
|
|
8
|
+
|
|
9
|
+
> ⚠️ **아래 작업은 반드시 사용자의 명시적 승인(OK)을 받은 후에만 진행합니다.**
|
|
10
|
+
> **확인 없이 진행 시 작업을 즉시 중단해야 합니다.**
|
|
11
|
+
|
|
12
|
+
| 작업 | 확인 시점 | 공유 내용 |
|
|
13
|
+
| ------------- | -------------------- | --------------------------- |
|
|
14
|
+
| 스펙 작성 | `spec.md` 작성 후 | 스펙 내용 전문 |
|
|
15
|
+
| 태스크 실행 | 각 태스크 시작 전 | 실행 계획 |
|
|
16
|
+
| 커밋 생성 | `git commit` 전 | 커밋 메시지, 포함 파일 목록 |
|
|
17
|
+
| 이슈 생성 | `gh issue create` 전 | 제목, 본문, 라벨 |
|
|
18
|
+
| PR 생성 | `gh pr create` 전 | 제목, 본문, 라벨 |
|
|
19
|
+
| Assignee 변경 | 본인 외 지정 시 | 대상 사용자명 |
|
|
20
|
+
| Git 원격 작업 | `push`, `merge` 전 | 브랜치, 변경 사항 |
|
|
21
|
+
|
|
22
|
+
### 확인 프로세스
|
|
23
|
+
|
|
24
|
+
1. 작업 내용을 사용자에게 **먼저 공유**
|
|
25
|
+
2. 사용자의 **명시적 승인(OK)** 대기
|
|
26
|
+
3. 승인 후에만 실행
|
|
27
|
+
|
|
28
|
+
> 🚫 **금지 사항**: 사용자 응답 없이 임의로 진행하는 것
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## 참조 문서
|
|
8
33
|
|
|
9
34
|
### 핵심 문서
|
|
10
35
|
|
|
36
|
+
> ⚠️ **`custom.md`의 규칙은 다른 모든 규칙보다 우선합니다.**
|
|
37
|
+
|
|
38
|
+
- **🔴 커스텀 규칙 (최우선)**: `/docs/agents/custom.md`
|
|
11
39
|
- **프로젝트 원칙**: `/docs/agents/constitution.md`
|
|
12
40
|
- **Git 워크플로우**: `/docs/agents/git-workflow.md`
|
|
13
41
|
- **이슈 템플릿**: `/docs/agents/issue-template.md`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Custom Rules
|
|
2
|
+
|
|
3
|
+
> ⚠️ 이 문서는 **사용자 정의 규칙**입니다.
|
|
4
|
+
> `npx lee-spec-kit update`의 영향을 받지 않습니다.
|
|
5
|
+
> **이 문서의 규칙은 다른 모든 agents 규칙보다 우선합니다.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 프로젝트 특화 규칙
|
|
10
|
+
|
|
11
|
+
(여기에 프로젝트만의 규칙을 작성하세요)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 추가 언어/코드 규칙
|
|
16
|
+
|
|
17
|
+
(기본 규칙을 오버라이드하거나 추가 규칙을 작성하세요)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 커스텀 워크플로우
|
|
22
|
+
|
|
23
|
+
(프로젝트만의 워크플로우가 있다면 작성하세요)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 기타
|
|
28
|
+
|
|
29
|
+
(기타 규칙을 작성하세요)
|
|
@@ -80,17 +80,16 @@ git checkout -b feat/{issue-number}-{feature-name}
|
|
|
80
80
|
|
|
81
81
|
> `gh`로 이슈/PR 생성·수정 시 작성할 제목/본문/라벨을 먼저 공유하고 **반드시** 사용자 확인(OK) 후 진행합니다.
|
|
82
82
|
|
|
83
|
-
### 2. 문서
|
|
83
|
+
### 2. 문서 커밋 (docs 레포)
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
| ------------ | ------------------ | ------------------------ |
|
|
87
|
-
| spec.md | 사용자 승인 후 | `docs(#123): spec 작성` |
|
|
88
|
-
| plan.md | 사용자 승인 후 | `docs(#123): plan 작성` |
|
|
89
|
-
| tasks.md | 사용자 승인 후 | `docs(#123): tasks 분해` |
|
|
90
|
-
| decisions.md | 태스크 커밋에 포함 | (별도 커밋 없음) |
|
|
85
|
+
> 📌 docs 폴더는 별도 git으로 관리되므로 프로젝트와 분리된 커밋 전략을 사용합니다.
|
|
91
86
|
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
| # | 커밋 시점 | 포함 문서 | 커밋 메시지 예시 |
|
|
88
|
+
| --- | ------------------------------------------ | ----------------------------- | ------------------------------------ |
|
|
89
|
+
| 1 | **계획 완료 시** (spec+plan+tasks 승인 후) | spec.md, plan.md, tasks.md | `docs(#123): spec, plan, tasks 작성` |
|
|
90
|
+
| 2 | **Feature 완료 시** (모든 태스크 완료 후) | tasks.md (상태), decisions.md | `docs(#123): Feature 완료` |
|
|
91
|
+
|
|
92
|
+
> ⚠️ **Feature 폴더 생성 시점**에는 커밋하지 않습니다.
|
|
94
93
|
|
|
95
94
|
### 3. 태스크 완료 시 자동 커밋
|
|
96
95
|
|