lee-spec-kit 0.1.5 → 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 +134 -30
- package/package.json +10 -8
- package/templates/en/fullstack/agents/agents.md +36 -0
- package/templates/en/fullstack/agents/custom.md +29 -0
- package/templates/en/fullstack/agents/git-workflow.md +14 -3
- package/templates/en/fullstack/agents/issue-template.md +18 -0
- package/templates/en/fullstack/agents/pr-template.md +21 -0
- package/templates/en/fullstack/features/feature-base/spec.md +2 -0
- package/templates/en/single/agents/agents.md +36 -0
- package/templates/en/single/agents/custom.md +29 -0
- package/templates/en/single/agents/git-workflow.md +14 -3
- package/templates/en/single/agents/issue-template.md +20 -0
- package/templates/en/single/agents/pr-template.md +21 -0
- package/templates/en/single/features/feature-base/spec.md +2 -0
- package/templates/ko/fullstack/agents/agents.md +36 -0
- package/templates/ko/fullstack/agents/custom.md +29 -0
- package/templates/ko/fullstack/agents/git-workflow.md +14 -3
- package/templates/ko/fullstack/agents/issue-template.md +18 -0
- package/templates/ko/fullstack/agents/pr-template.md +21 -0
- package/templates/ko/fullstack/features/feature-base/spec.md +2 -0
- package/templates/ko/single/agents/agents.md +36 -0
- package/templates/ko/single/agents/custom.md +29 -0
- package/templates/ko/single/agents/git-workflow.md +14 -3
- package/templates/ko/single/agents/issue-template.md +18 -0
- package/templates/ko/single/agents/pr-template.md +21 -0
- package/templates/ko/single/features/feature-base/spec.md +2 -0
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
|
}
|
|
@@ -330,7 +330,7 @@ async function getConfig(cwd) {
|
|
|
330
330
|
|
|
331
331
|
// src/commands/feature.ts
|
|
332
332
|
function featureCommand(program2) {
|
|
333
|
-
program2.command("feature <name>").description("Create a new feature folder").option("-r, --repo <repo>", "Repository type: be | fe (fullstack only)").option("--id <id>", "Feature ID (default: auto)").action(async (name, options) => {
|
|
333
|
+
program2.command("feature <name>").description("Create a new feature folder").option("-r, --repo <repo>", "Repository type: be | fe (fullstack only)").option("--id <id>", "Feature ID (default: auto)").option("-d, --desc <description>", "Feature description for spec.md").action(async (name, options) => {
|
|
334
334
|
try {
|
|
335
335
|
await runFeature(name, options);
|
|
336
336
|
} catch (error) {
|
|
@@ -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 = {
|
|
@@ -410,7 +410,8 @@ async function runFeature(name, options) {
|
|
|
410
410
|
"YYYY-MM-DD": (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
411
411
|
"{be|fe}": repo || "",
|
|
412
412
|
"git-dungeon-{be|fe}": repoName,
|
|
413
|
-
"{\uC774\uC288\uBC88\uD638}": ""
|
|
413
|
+
"{\uC774\uC288\uBC88\uD638}": "",
|
|
414
|
+
"{{description}}": options.desc || ""
|
|
414
415
|
};
|
|
415
416
|
if (lang === "en") {
|
|
416
417
|
replacements["\uAE30\uB2A5 ID"] = "Feature ID";
|
|
@@ -441,8 +442,8 @@ async function getNextFeatureId(docsDir, projectType) {
|
|
|
441
442
|
scanDirs.push(featuresDir);
|
|
442
443
|
}
|
|
443
444
|
for (const dir of scanDirs) {
|
|
444
|
-
if (!await
|
|
445
|
-
const entries = await
|
|
445
|
+
if (!await fs6.pathExists(dir)) continue;
|
|
446
|
+
const entries = await fs6.readdir(dir, { withFileTypes: true });
|
|
446
447
|
for (const entry of entries) {
|
|
447
448
|
if (!entry.isDirectory()) continue;
|
|
448
449
|
const match = entry.name.match(/^F(\d+)-/);
|
|
@@ -482,18 +483,18 @@ async function runStatus(options) {
|
|
|
482
483
|
const scopes = projectType === "fullstack" ? ["be", "fe"] : [""];
|
|
483
484
|
for (const scope of scopes) {
|
|
484
485
|
const scanDir = scope ? path3.join(featuresDir, scope) : featuresDir;
|
|
485
|
-
if (!await
|
|
486
|
-
const entries = await
|
|
486
|
+
if (!await fs6.pathExists(scanDir)) continue;
|
|
487
|
+
const entries = await fs6.readdir(scanDir, { withFileTypes: true });
|
|
487
488
|
for (const entry of entries) {
|
|
488
489
|
if (!entry.isDirectory()) continue;
|
|
489
490
|
if (entry.name === "feature-base") continue;
|
|
490
491
|
const featureDir = path3.join(scanDir, entry.name);
|
|
491
492
|
const specPath = path3.join(featureDir, "spec.md");
|
|
492
493
|
const tasksPath = path3.join(featureDir, "tasks.md");
|
|
493
|
-
if (!await
|
|
494
|
-
if (!await
|
|
495
|
-
const specContent = await
|
|
496
|
-
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");
|
|
497
498
|
const id = extractSpecValue(specContent, "\uAE30\uB2A5 ID") || extractSpecValue(specContent, "Feature ID") || "UNKNOWN";
|
|
498
499
|
const name = extractSpecValue(specContent, "\uAE30\uB2A5\uBA85") || extractSpecValue(specContent, "Feature Name") || entry.name;
|
|
499
500
|
const repo = extractSpecValue(specContent, "\uB300\uC0C1 \uB808\uD3EC") || extractSpecValue(specContent, "Target Repo") || (scope ? `{{projectName}}-${scope}` : "{{projectName}}");
|
|
@@ -583,7 +584,7 @@ async function runStatus(options) {
|
|
|
583
584
|
),
|
|
584
585
|
""
|
|
585
586
|
].join("\n");
|
|
586
|
-
await
|
|
587
|
+
await fs6.writeFile(outputPath, content, "utf-8");
|
|
587
588
|
console.log(chalk.green(`\u2705 ${outputPath} \uC0DD\uC131 \uC644\uB8CC`));
|
|
588
589
|
}
|
|
589
590
|
}
|
|
@@ -610,6 +611,108 @@ function countTasks(content) {
|
|
|
610
611
|
}
|
|
611
612
|
return { total, done, doing, todo };
|
|
612
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
|
+
}
|
|
613
716
|
|
|
614
717
|
// src/index.ts
|
|
615
718
|
program.name("lee-spec-kit").description(
|
|
@@ -618,4 +721,5 @@ program.name("lee-spec-kit").description(
|
|
|
618
721
|
initCommand(program);
|
|
619
722
|
featureCommand(program);
|
|
620
723
|
statusCommand(program);
|
|
724
|
+
updateCommand(program);
|
|
621
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`
|
|
@@ -69,6 +97,14 @@ docs/
|
|
|
69
97
|
3. Transition status: `[TODO]` → `[DOING]` → `[DONE]`
|
|
70
98
|
4. Commit immediately after task completion
|
|
71
99
|
|
|
100
|
+
### 4. Handling Requests Outside Tasks
|
|
101
|
+
|
|
102
|
+
> When user requests **work not in tasks.md**:
|
|
103
|
+
|
|
104
|
+
1. Ask user if this should be **added to tasks.md**
|
|
105
|
+
2. If approved: Add to tasks.md then execute
|
|
106
|
+
3. If declined: Proceed as temporary work (still included in commit)
|
|
107
|
+
|
|
72
108
|
---
|
|
73
109
|
|
|
74
110
|
## 📋 ADR (Architecture Decision Records)
|
|
@@ -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,14 +73,25 @@ main
|
|
|
73
73
|
git checkout -b feat/{issue-number}-{feature-name}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
### 2.
|
|
76
|
+
### 2. Document Commit (docs repo)
|
|
77
|
+
|
|
78
|
+
> 📌 The docs folder is managed as a separate git, so a separate commit strategy is used.
|
|
79
|
+
|
|
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.**
|
|
86
|
+
|
|
87
|
+
### 3. Auto Commit on Task Completion
|
|
77
88
|
|
|
78
89
|
```bash
|
|
79
90
|
git add .
|
|
80
91
|
git commit -m "{type}(#{issue}): {task-description}"
|
|
81
92
|
```
|
|
82
93
|
|
|
83
|
-
###
|
|
94
|
+
### 4. Create PR on Feature Completion
|
|
84
95
|
|
|
85
96
|
```bash
|
|
86
97
|
git push origin feat/{issue-number}-{feature-name}
|
|
@@ -89,7 +100,7 @@ gh pr create --title "feat(#{issue}): {feature-title}" \
|
|
|
89
100
|
--base main
|
|
90
101
|
```
|
|
91
102
|
|
|
92
|
-
###
|
|
103
|
+
### 5. Merge
|
|
93
104
|
|
|
94
105
|
```bash
|
|
95
106
|
git checkout main
|
|
@@ -82,6 +82,24 @@ In GitHub Issues, use different link formats **based on file location**:
|
|
|
82
82
|
| `frontend` | FE related |
|
|
83
83
|
| `priority:high` | High priority |
|
|
84
84
|
|
|
85
|
+
> ⚠️ If a label does not exist, create it first:
|
|
86
|
+
>
|
|
87
|
+
> ```bash
|
|
88
|
+
> gh label create "label-name" --description "description" --color "color-code"
|
|
89
|
+
> ```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Assignee Rules
|
|
94
|
+
|
|
95
|
+
- Default: Self-assign (`--assignee @me`)
|
|
96
|
+
- When assigning others, **confirm with user** first
|
|
97
|
+
- Examples:
|
|
98
|
+
```bash
|
|
99
|
+
gh issue create --assignee @me ...
|
|
100
|
+
gh issue create --assignee username ...
|
|
101
|
+
```
|
|
102
|
+
|
|
85
103
|
---
|
|
86
104
|
|
|
87
105
|
## Body Input Rules (Shell Execution Prevention)
|
|
@@ -67,6 +67,27 @@ Closes #{issue-number}
|
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
70
|
+
## Label Rules
|
|
71
|
+
|
|
72
|
+
- Specify appropriate labels when creating PR (`--label`)
|
|
73
|
+
- If a label does not exist, create it first:
|
|
74
|
+
```bash
|
|
75
|
+
gh label create "label-name" --description "description" --color "color-code"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Assignee Rules
|
|
81
|
+
|
|
82
|
+
- Default: Self-assign (`--assignee @me`)
|
|
83
|
+
- Use `--reviewer` option to specify reviewers
|
|
84
|
+
- Examples:
|
|
85
|
+
```bash
|
|
86
|
+
gh pr create --assignee @me --reviewer reviewer-username ...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
70
91
|
## Body Input Rules (Shell Execution Prevention)
|
|
71
92
|
|
|
72
93
|
- PR body should use **`--body-file` by default**.
|
|
@@ -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`
|
|
@@ -56,6 +84,14 @@ docs/
|
|
|
56
84
|
3. Status transition: `[TODO]` → `[DOING]` → `[DONE]`
|
|
57
85
|
4. Commit on task completion
|
|
58
86
|
|
|
87
|
+
### 3. Handling Requests Outside Tasks
|
|
88
|
+
|
|
89
|
+
> When user requests **work not in tasks.md**:
|
|
90
|
+
|
|
91
|
+
1. Ask user if this should be **added to tasks.md**
|
|
92
|
+
2. If approved: Add to tasks.md then execute
|
|
93
|
+
3. If declined: Proceed as temporary work (still included in commit)
|
|
94
|
+
|
|
59
95
|
---
|
|
60
96
|
|
|
61
97
|
## 📋 ADR (Architecture Decision Records)
|
|
@@ -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,7 +80,18 @@ 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.
|
|
83
|
+
### 2. Document Commit (docs repo)
|
|
84
|
+
|
|
85
|
+
> 📌 The docs folder is managed as a separate git, so a separate commit strategy is used.
|
|
86
|
+
|
|
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.**
|
|
93
|
+
|
|
94
|
+
### 3. Auto Commit on Task Completion
|
|
84
95
|
|
|
85
96
|
When a task is completed:
|
|
86
97
|
|
|
@@ -91,7 +102,7 @@ git commit -m "{type}(#{issue}): {task-description}"
|
|
|
91
102
|
|
|
92
103
|
> Before running `git commit`, share the commit message and file list first and **wait for user confirmation (OK)** before proceeding.
|
|
93
104
|
|
|
94
|
-
###
|
|
105
|
+
### 4. Create PR on Feature Completion
|
|
95
106
|
|
|
96
107
|
When all tasks are completed:
|
|
97
108
|
|
|
@@ -102,7 +113,7 @@ gh pr create --title "feat(#{issue}): {feature-title}" \
|
|
|
102
113
|
--base main
|
|
103
114
|
```
|
|
104
115
|
|
|
105
|
-
###
|
|
116
|
+
### 5. Merge
|
|
106
117
|
|
|
107
118
|
When all reviews are resolved:
|
|
108
119
|
|
|
@@ -86,6 +86,24 @@ In GitHub Issues, use different link formats **based on file location**:
|
|
|
86
86
|
| `frontend` | FE related |
|
|
87
87
|
| `priority:high` | High priority |
|
|
88
88
|
|
|
89
|
+
> ⚠️ If a label does not exist, create it first:
|
|
90
|
+
>
|
|
91
|
+
> ```bash
|
|
92
|
+
> gh label create "label-name" --description "description" --color "color-code"
|
|
93
|
+
> ```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Assignee Rules
|
|
98
|
+
|
|
99
|
+
- Default: Self-assign (`--assignee @me`)
|
|
100
|
+
- When assigning others, **confirm with user** first
|
|
101
|
+
- Examples:
|
|
102
|
+
```bash
|
|
103
|
+
gh issue create --assignee @me ...
|
|
104
|
+
gh issue create --assignee username ...
|
|
105
|
+
```
|
|
106
|
+
|
|
89
107
|
---
|
|
90
108
|
|
|
91
109
|
## Body Input Rules (Shell Execution Prevention)
|
|
@@ -94,3 +112,5 @@ In GitHub Issues, use different link formats **based on file location**:
|
|
|
94
112
|
- If the body contains backticks (`) or `$()`and is placed directly in`"..."`, it may be **interpreted by the shell**.
|
|
95
113
|
- For multi-line bodies, use **single-quoted heredoc** like `cat <<'EOF'`,
|
|
96
114
|
and handle variables via **placeholder → sed substitution**.
|
|
115
|
+
|
|
116
|
+
and handle variables via **placeholder → sed substitution**.
|
|
@@ -83,6 +83,27 @@ gh pr create \
|
|
|
83
83
|
|
|
84
84
|
---
|
|
85
85
|
|
|
86
|
+
## Label Rules
|
|
87
|
+
|
|
88
|
+
- Specify appropriate labels when creating PR (`--label`)
|
|
89
|
+
- If a label does not exist, create it first:
|
|
90
|
+
```bash
|
|
91
|
+
gh label create "label-name" --description "description" --color "color-code"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Assignee Rules
|
|
97
|
+
|
|
98
|
+
- Default: Self-assign (`--assignee @me`)
|
|
99
|
+
- Use `--reviewer` option to specify reviewers
|
|
100
|
+
- Examples:
|
|
101
|
+
```bash
|
|
102
|
+
gh pr create --assignee @me --reviewer reviewer-username ...
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
86
107
|
## Body Input Rules (Shell Execution Prevention)
|
|
87
108
|
|
|
88
109
|
- PR body should use **`--body-file` by default**.
|
|
@@ -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`
|
|
@@ -92,6 +120,14 @@ docs/
|
|
|
92
120
|
1. 분석 리포트 작성 (현재 상태, 문제점, 제안, 영향)
|
|
93
121
|
2. 변경 필요시 새 기능/태스크 생성 권장
|
|
94
122
|
|
|
123
|
+
### 5. 태스크 외 요청 처리
|
|
124
|
+
|
|
125
|
+
> 사용자가 **tasks.md에 없는 작업**을 요청하면:
|
|
126
|
+
|
|
127
|
+
1. 해당 작업을 **tasks.md에 반영할지** 사용자에게 확인
|
|
128
|
+
2. 승인 시: tasks.md에 추가 후 실행
|
|
129
|
+
3. 거부 시: 임시 작업으로 진행 (커밋에는 포함)
|
|
130
|
+
|
|
95
131
|
---
|
|
96
132
|
|
|
97
133
|
## 📋 ADR (Architecture Decision Records) 규칙
|
|
@@ -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,7 +80,18 @@ git checkout -b feat/{issue-number}-{feature-name}
|
|
|
80
80
|
|
|
81
81
|
> `gh`로 이슈/PR 생성·수정 시 작성할 제목/본문/라벨을 먼저 공유하고 **반드시** 사용자 확인(OK) 후 진행합니다.
|
|
82
82
|
|
|
83
|
-
### 2.
|
|
83
|
+
### 2. 문서 커밋 (docs 레포)
|
|
84
|
+
|
|
85
|
+
> 📌 docs 폴더는 별도 git으로 관리되므로 프로젝트와 분리된 커밋 전략을 사용합니다.
|
|
86
|
+
|
|
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 폴더 생성 시점**에는 커밋하지 않습니다.
|
|
93
|
+
|
|
94
|
+
### 3. 태스크 완료 시 자동 커밋
|
|
84
95
|
|
|
85
96
|
태스크 하나가 완료되면:
|
|
86
97
|
|
|
@@ -91,7 +102,7 @@ git commit -m "{type}(#{issue}): {task-description}"
|
|
|
91
102
|
|
|
92
103
|
> `git commit` 실행 전 커밋 메시지와 포함될 파일 목록을 먼저 공유하고 **반드시** 사용자 확인(OK) 후 진행합니다.
|
|
93
104
|
|
|
94
|
-
###
|
|
105
|
+
### 4. Feature 완료 시 PR 생성
|
|
95
106
|
|
|
96
107
|
모든 태스크 완료 시:
|
|
97
108
|
|
|
@@ -102,7 +113,7 @@ gh pr create --title "feat(#{issue}): {feature-title}" \
|
|
|
102
113
|
--base main
|
|
103
114
|
```
|
|
104
115
|
|
|
105
|
-
###
|
|
116
|
+
### 5. 머지
|
|
106
117
|
|
|
107
118
|
모든 리뷰 해결 시:
|
|
108
119
|
|
|
@@ -86,6 +86,24 @@ GitHub Issue에서 링크는 **파일 위치에 따라** 다르게 작성:
|
|
|
86
86
|
| `frontend` | FE 관련 |
|
|
87
87
|
| `priority:high` | 높은 우선순위 |
|
|
88
88
|
|
|
89
|
+
> ⚠️ 라벨이 존재하지 않으면 먼저 생성합니다:
|
|
90
|
+
>
|
|
91
|
+
> ```bash
|
|
92
|
+
> gh label create "라벨명" --description "설명" --color "색상코드"
|
|
93
|
+
> ```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Assignee 규칙
|
|
98
|
+
|
|
99
|
+
- 기본값: 본인 할당 (`--assignee @me`)
|
|
100
|
+
- 다른 담당자 지정 시 **사용자에게 확인** 후 진행
|
|
101
|
+
- 예시:
|
|
102
|
+
```bash
|
|
103
|
+
gh issue create --assignee @me ...
|
|
104
|
+
gh issue create --assignee username ...
|
|
105
|
+
```
|
|
106
|
+
|
|
89
107
|
---
|
|
90
108
|
|
|
91
109
|
## 본문 입력 규칙 (셸 실행 방지)
|
|
@@ -81,6 +81,27 @@ gh pr create \
|
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
84
|
+
## 라벨 규칙
|
|
85
|
+
|
|
86
|
+
- PR 생성 시 적절한 라벨 지정 (`--label`)
|
|
87
|
+
- 라벨이 존재하지 않으면 먼저 생성:
|
|
88
|
+
```bash
|
|
89
|
+
gh label create "라벨명" --description "설명" --color "색상코드"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Assignee 규칙
|
|
95
|
+
|
|
96
|
+
- 기본값: 본인 할당 (`--assignee @me`)
|
|
97
|
+
- 리뷰어 지정 시 `--reviewer` 옵션 사용
|
|
98
|
+
- 예시:
|
|
99
|
+
```bash
|
|
100
|
+
gh pr create --assignee @me --reviewer reviewer-username ...
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
84
105
|
## 본문 입력 규칙 (셸 실행 방지)
|
|
85
106
|
|
|
86
107
|
- PR 본문은 **`--body-file` 사용을 기본**으로 한다.
|
|
@@ -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`
|
|
@@ -69,6 +97,14 @@ docs/
|
|
|
69
97
|
3. 상태 전환: `[TODO]` → `[DOING]` → `[DONE]`
|
|
70
98
|
4. 태스크 완료 직후 커밋
|
|
71
99
|
|
|
100
|
+
### 3. 태스크 외 요청 처리
|
|
101
|
+
|
|
102
|
+
> 사용자가 **tasks.md에 없는 작업**을 요청하면:
|
|
103
|
+
|
|
104
|
+
1. 해당 작업을 **tasks.md에 반영할지** 사용자에게 확인
|
|
105
|
+
2. 승인 시: tasks.md에 추가 후 실행
|
|
106
|
+
3. 거부 시: 임시 작업으로 진행 (커밋에는 포함)
|
|
107
|
+
|
|
72
108
|
---
|
|
73
109
|
|
|
74
110
|
## 📋 ADR (Architecture Decision Records) 규칙
|
|
@@ -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,7 +80,18 @@ git checkout -b feat/{issue-number}-{feature-name}
|
|
|
80
80
|
|
|
81
81
|
> `gh`로 이슈/PR 생성·수정 시 작성할 제목/본문/라벨을 먼저 공유하고 **반드시** 사용자 확인(OK) 후 진행합니다.
|
|
82
82
|
|
|
83
|
-
### 2.
|
|
83
|
+
### 2. 문서 커밋 (docs 레포)
|
|
84
|
+
|
|
85
|
+
> 📌 docs 폴더는 별도 git으로 관리되므로 프로젝트와 분리된 커밋 전략을 사용합니다.
|
|
86
|
+
|
|
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 폴더 생성 시점**에는 커밋하지 않습니다.
|
|
93
|
+
|
|
94
|
+
### 3. 태스크 완료 시 자동 커밋
|
|
84
95
|
|
|
85
96
|
태스크 하나가 완료되면:
|
|
86
97
|
|
|
@@ -91,7 +102,7 @@ git commit -m "{type}(#{issue}): {task-description}"
|
|
|
91
102
|
|
|
92
103
|
> `git commit` 실행 전 커밋 메시지와 포함될 파일 목록을 먼저 공유하고 **반드시** 사용자 확인(OK) 후 진행합니다.
|
|
93
104
|
|
|
94
|
-
###
|
|
105
|
+
### 4. Feature 완료 시 PR 생성
|
|
95
106
|
|
|
96
107
|
모든 태스크 완료 시:
|
|
97
108
|
|
|
@@ -102,7 +113,7 @@ gh pr create --title "feat(#{issue}): {feature-title}" \
|
|
|
102
113
|
--base main
|
|
103
114
|
```
|
|
104
115
|
|
|
105
|
-
###
|
|
116
|
+
### 5. 머지
|
|
106
117
|
|
|
107
118
|
모든 리뷰 해결 시:
|
|
108
119
|
|
|
@@ -86,6 +86,24 @@ GitHub Issue에서 링크는 **파일 위치에 따라** 다르게 작성:
|
|
|
86
86
|
| `frontend` | FE 관련 |
|
|
87
87
|
| `priority:high` | 높은 우선순위 |
|
|
88
88
|
|
|
89
|
+
> ⚠️ 라벨이 존재하지 않으면 먼저 생성합니다:
|
|
90
|
+
>
|
|
91
|
+
> ```bash
|
|
92
|
+
> gh label create "라벨명" --description "설명" --color "색상코드"
|
|
93
|
+
> ```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Assignee 규칙
|
|
98
|
+
|
|
99
|
+
- 기본값: 본인 할당 (`--assignee @me`)
|
|
100
|
+
- 다른 담당자 지정 시 **사용자에게 확인** 후 진행
|
|
101
|
+
- 예시:
|
|
102
|
+
```bash
|
|
103
|
+
gh issue create --assignee @me ...
|
|
104
|
+
gh issue create --assignee username ...
|
|
105
|
+
```
|
|
106
|
+
|
|
89
107
|
---
|
|
90
108
|
|
|
91
109
|
## 본문 입력 규칙 (셸 실행 방지)
|
|
@@ -81,6 +81,27 @@ gh pr create \
|
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
84
|
+
## 라벨 규칙
|
|
85
|
+
|
|
86
|
+
- PR 생성 시 적절한 라벨 지정 (`--label`)
|
|
87
|
+
- 라벨이 존재하지 않으면 먼저 생성:
|
|
88
|
+
```bash
|
|
89
|
+
gh label create "라벨명" --description "설명" --color "색상코드"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Assignee 규칙
|
|
95
|
+
|
|
96
|
+
- 기본값: 본인 할당 (`--assignee @me`)
|
|
97
|
+
- 리뷰어 지정 시 `--reviewer` 옵션 사용
|
|
98
|
+
- 예시:
|
|
99
|
+
```bash
|
|
100
|
+
gh pr create --assignee @me --reviewer reviewer-username ...
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
84
105
|
## 본문 입력 규칙 (셸 실행 방지)
|
|
85
106
|
|
|
86
107
|
- PR 본문은 **`--body-file` 사용을 기본**으로 한다.
|