@careerchain/stdd 0.1.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 +44 -0
- package/assets/.claude/agents/code-reviewer.md +170 -0
- package/assets/.claude/agents/implementer.md +96 -0
- package/assets/.claude/agents/plan-writer.md +124 -0
- package/assets/.claude/agents/qa-engineer.md +133 -0
- package/assets/.claude/agents/spec-reviewer.md +173 -0
- package/assets/.claude/agents/spec-writer.md +194 -0
- package/assets/.claude/agents/test-reviewer.md +218 -0
- package/assets/.claude/docs/spec-driven-development-guide.md +436 -0
- package/assets/.claude/hooks/pre-push-check.sh +160 -0
- package/assets/.claude/settings.json +67 -0
- package/assets/.claude/skills/auto-implement/SKILL.md +168 -0
- package/assets/.claude/skills/auto-implement/references/github-project.md +54 -0
- package/assets/.claude/skills/auto-implement/references/phases.md +244 -0
- package/assets/.claude/skills/create-pr/SKILL.md +112 -0
- package/assets/.claude/skills/documenting-plans/SKILL.md +217 -0
- package/assets/.claude/skills/documenting-plans/templates/plan.md +182 -0
- package/assets/.claude/skills/documenting-specifications/SKILL.md +300 -0
- package/assets/.claude/skills/documenting-specifications/guides/error-handling.md +78 -0
- package/assets/.claude/skills/documenting-specifications/guides/stdd-violations.md +237 -0
- package/assets/.claude/skills/documenting-specifications/templates/requirements.md +184 -0
- package/assets/.claude/skills/documenting-specifications/templates/screen-items-definition.md +179 -0
- package/assets/.claude/skills/documenting-specifications/templates/tech-design.md +241 -0
- package/assets/.claude/skills/generating-wireframes/SKILL.md +121 -0
- package/assets/.claude/skills/generating-wireframes/examples/tob-form.html +497 -0
- package/assets/.claude/skills/generating-wireframes/examples/tob-list.html +536 -0
- package/assets/.claude/skills/generating-wireframes/examples/toc-form.html +493 -0
- package/assets/.claude/skills/generating-wireframes/examples/toc-list.html +538 -0
- package/assets/.claude/skills/generating-wireframes/guides/from-requirements.md +53 -0
- package/assets/.claude/skills/generating-wireframes/templates/index.html +472 -0
- package/assets/.claude/skills/generating-wireframes/templates/screen.html +480 -0
- package/assets/.claude/skills/introducing-stdd/SKILL.md +185 -0
- package/assets/.claude/skills/introducing-stdd/templates/introduction-plan.md +64 -0
- package/assets/.claude/skills/kaizen/SKILL.md +129 -0
- package/assets/.claude/skills/kaizen/references/code-examples.md +233 -0
- package/assets/.claude/skills/reverse-engineering-common-spec/SKILL.md +137 -0
- package/assets/.claude/skills/reverse-engineering-feature-spec/SKILL.md +463 -0
- package/assets/.claude/skills/reverse-engineering-feature-spec/guides/accuracy.md +215 -0
- package/assets/.claude/skills/reverse-engineering-feature-spec/guides/figma-capture.md +313 -0
- package/assets/.claude/skills/review-pr-with-agents/SKILL.md +159 -0
- package/assets/.claude/skills/searching-existing-solutions/SKILL.md +110 -0
- package/assets/.claude/skills/setup-stdd/SKILL.md +82 -0
- package/assets/.claude/skills/software-architecture/SKILL.md +260 -0
- package/assets/.claude/skills/starting-new-with-stdd/SKILL.md +142 -0
- package/assets/.claude/skills/starting-new-with-stdd/templates/bootstrap-plan.md +73 -0
- package/assets/.claude/skills/tailoring-spec-format/SKILL.md +103 -0
- package/assets/.claude/skills/verifying-consistency/SKILL.md +90 -0
- package/assets/stdd.config.yml.tpl +34 -0
- package/dist/cli.js +148 -0
- package/dist/cli.js.map +1 -0
- package/dist/install.js +121 -0
- package/dist/install.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# STDD 設定ファイル
|
|
2
|
+
# JSON Schema: https://raw.githubusercontent.com/careerchain-ys/stdd/main/packages/core/schema/.stdd.config.schema.json
|
|
3
|
+
# yaml-language-server: $schema=https://raw.githubusercontent.com/careerchain-ys/stdd/main/packages/core/schema/.stdd.config.schema.json
|
|
4
|
+
|
|
5
|
+
version: 1
|
|
6
|
+
|
|
7
|
+
project:
|
|
8
|
+
name: "{{project.name}}"
|
|
9
|
+
language: "ja"
|
|
10
|
+
primary_branch: "main"
|
|
11
|
+
|
|
12
|
+
apps:
|
|
13
|
+
- id: app
|
|
14
|
+
path: "."
|
|
15
|
+
|
|
16
|
+
commands:
|
|
17
|
+
typecheck: "npx tsc --noEmit"
|
|
18
|
+
test: "npm test"
|
|
19
|
+
build: "npm run build"
|
|
20
|
+
|
|
21
|
+
docs:
|
|
22
|
+
layout:
|
|
23
|
+
requirements: "docs/{{feature_path}}/REQUIREMENTS.md"
|
|
24
|
+
tech_design: "docs/{{feature_path}}/TECH_DESIGN.md"
|
|
25
|
+
plan: "docs/{{feature_path}}/plans/{{date}}.md"
|
|
26
|
+
|
|
27
|
+
workflow:
|
|
28
|
+
branch_prefix: "claude/"
|
|
29
|
+
worktree:
|
|
30
|
+
enabled: false
|
|
31
|
+
devcontainer:
|
|
32
|
+
enabled: false
|
|
33
|
+
|
|
34
|
+
plugins: []
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import prompts from "prompts";
|
|
7
|
+
import { install, InstallError } from "./install.js";
|
|
8
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
|
+
const assetsRoot = path.join(packageRoot, "assets");
|
|
10
|
+
const VERSION = readVersion();
|
|
11
|
+
function readVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const raw = fs.readFileSync(path.join(packageRoot, "package.json"), "utf8");
|
|
14
|
+
return JSON.parse(raw).version ?? "0.0.0";
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return "0.0.0";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function printHelp() {
|
|
21
|
+
console.log(`
|
|
22
|
+
stdd v${VERSION} STDD (Spec and Test Driven Development) インストーラ
|
|
23
|
+
|
|
24
|
+
使い方:
|
|
25
|
+
npx @careerchain/stdd init [options] 現在のディレクトリに STDD を導入する(新規・既存どちらも可)
|
|
26
|
+
|
|
27
|
+
options:
|
|
28
|
+
--name <name> .stdd.config.yml の project.name(既定: ディレクトリ名)
|
|
29
|
+
--force 確認なしで既存の .claude/ を上書きする
|
|
30
|
+
--yes, -y 対話プロンプトをスキップし既定値で進める
|
|
31
|
+
--help, -h このヘルプを表示
|
|
32
|
+
--version, -v バージョンを表示
|
|
33
|
+
|
|
34
|
+
導入後の流れ:
|
|
35
|
+
1. claude を起動
|
|
36
|
+
2. 「STDD を導入して」と伝える
|
|
37
|
+
→ 新規 / 既存を自動判定し、適切なスキルが起動します
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
40
|
+
function parseInitFlags(args) {
|
|
41
|
+
const flags = { force: false, yes: false, name: undefined };
|
|
42
|
+
for (let i = 0; i < args.length; i++) {
|
|
43
|
+
const arg = args[i];
|
|
44
|
+
if (arg === "--force")
|
|
45
|
+
flags.force = true;
|
|
46
|
+
else if (arg === "--yes" || arg === "-y")
|
|
47
|
+
flags.yes = true;
|
|
48
|
+
else if (arg === "--name")
|
|
49
|
+
flags.name = args[++i];
|
|
50
|
+
else if (arg.startsWith("--name="))
|
|
51
|
+
flags.name = arg.slice("--name=".length);
|
|
52
|
+
else
|
|
53
|
+
console.warn(` 注意: 未対応のオプションを無視します: ${arg}`);
|
|
54
|
+
}
|
|
55
|
+
return flags;
|
|
56
|
+
}
|
|
57
|
+
function deriveProjectName(cwd, override) {
|
|
58
|
+
const raw = (override ?? path.basename(cwd)).trim();
|
|
59
|
+
// YAML のダブルクォート文字列に埋めるため、安全でない文字は除去する。
|
|
60
|
+
const cleaned = raw.replace(/["\\]/g, "");
|
|
61
|
+
return cleaned.length > 0 ? cleaned : "my-stdd-project";
|
|
62
|
+
}
|
|
63
|
+
const ACTION_LABEL = {
|
|
64
|
+
created: "作成",
|
|
65
|
+
overwritten: "更新",
|
|
66
|
+
kept: "維持(既存を保持)",
|
|
67
|
+
skipped: "スキップ(既存を保持)",
|
|
68
|
+
};
|
|
69
|
+
async function runInit(args) {
|
|
70
|
+
const flags = parseInitFlags(args);
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
const projectName = deriveProjectName(cwd, flags.name);
|
|
73
|
+
console.log("");
|
|
74
|
+
console.log(` stdd v${VERSION} 現在のディレクトリに STDD を導入します`);
|
|
75
|
+
console.log(` 対象: ${cwd}`);
|
|
76
|
+
console.log("");
|
|
77
|
+
// 既存の .claude/ がある場合の上書き可否を決める
|
|
78
|
+
let overwriteClaude = flags.force;
|
|
79
|
+
const claudeExists = fs.existsSync(path.join(cwd, ".claude"));
|
|
80
|
+
if (claudeExists && !flags.force) {
|
|
81
|
+
if (flags.yes || !process.stdout.isTTY) {
|
|
82
|
+
// 非対話時は安全側(既存を保持)に倒す
|
|
83
|
+
overwriteClaude = false;
|
|
84
|
+
console.log(" 既存の .claude/ を検出しました → 保持します(上書きするには --force)");
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const res = await prompts({
|
|
88
|
+
type: "confirm",
|
|
89
|
+
name: "overwrite",
|
|
90
|
+
message: "既存の .claude/ を最新の STDD スキル一式で上書きしますか?",
|
|
91
|
+
initial: true,
|
|
92
|
+
});
|
|
93
|
+
overwriteClaude = res.overwrite === true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
let result;
|
|
97
|
+
try {
|
|
98
|
+
result = await install({ targetDir: cwd, assetsRoot, projectName, overwriteClaude });
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (err instanceof InstallError) {
|
|
102
|
+
console.error(`\n エラー: ${err.message}\n`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
console.log("");
|
|
108
|
+
console.log(" ✔ STDD を導入しました");
|
|
109
|
+
console.log(` .claude/ : ${ACTION_LABEL[result.claude]}`);
|
|
110
|
+
console.log(` .stdd.config.yml : ${ACTION_LABEL[result.config]}`);
|
|
111
|
+
console.log(` docs/ : ${ACTION_LABEL[result.docs]}`);
|
|
112
|
+
console.log("");
|
|
113
|
+
console.log(" 次の手順:");
|
|
114
|
+
const steps = [];
|
|
115
|
+
if (result.config === "created") {
|
|
116
|
+
steps.push(".stdd.config.yml の apps[].path / commands.* を実環境に合わせて調整");
|
|
117
|
+
}
|
|
118
|
+
steps.push("claude を起動");
|
|
119
|
+
steps.push("「STDD を導入して」と伝える # 新規/既存を自動判定して進めます");
|
|
120
|
+
steps.forEach((s, i) => console.log(` ${i + 1}. ${s}`));
|
|
121
|
+
console.log("");
|
|
122
|
+
console.log(" ドキュメント: https://github.com/careerchain-ys/stdd");
|
|
123
|
+
console.log("");
|
|
124
|
+
}
|
|
125
|
+
async function main() {
|
|
126
|
+
const argv = process.argv.slice(2);
|
|
127
|
+
const [command, ...rest] = argv;
|
|
128
|
+
if (command === "--version" || command === "-v") {
|
|
129
|
+
console.log(VERSION);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (command === undefined || command === "--help" || command === "-h" || command === "help") {
|
|
133
|
+
printHelp();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (command === "init") {
|
|
137
|
+
await runInit(rest);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
console.error(` エラー: 不明なコマンド "${command}"`);
|
|
141
|
+
printHelp();
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
main().catch((err) => {
|
|
145
|
+
console.error(err);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export class InstallError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "InstallError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const CLAUDE_DIR = ".claude";
|
|
10
|
+
const CONFIG_FILE = ".stdd.config.yml";
|
|
11
|
+
const CONFIG_TEMPLATE = "stdd.config.yml.tpl";
|
|
12
|
+
const DOCS_DIR = "docs";
|
|
13
|
+
/**
|
|
14
|
+
* カレントプロジェクト(新規・既存いずれも)へ STDD 一式を導入する。
|
|
15
|
+
* - .claude/(skill / agent / hook)を配置
|
|
16
|
+
* - .stdd.config.yml を生成(既存なら維持)
|
|
17
|
+
* - docs/ を用意
|
|
18
|
+
* 既存ファイルを不用意に破壊しない(config は維持、.claude は明示時のみ上書き)。
|
|
19
|
+
*/
|
|
20
|
+
export async function install(opts) {
|
|
21
|
+
const { targetDir, assetsRoot, projectName, overwriteClaude } = opts;
|
|
22
|
+
await assertAssets(assetsRoot);
|
|
23
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
24
|
+
const claude = await installClaude(assetsRoot, targetDir, overwriteClaude);
|
|
25
|
+
const config = await installConfig(assetsRoot, targetDir, projectName);
|
|
26
|
+
const docs = await ensureDocs(targetDir);
|
|
27
|
+
return { claude, config, docs };
|
|
28
|
+
}
|
|
29
|
+
async function assertAssets(assetsRoot) {
|
|
30
|
+
const claudeSrc = path.join(assetsRoot, CLAUDE_DIR);
|
|
31
|
+
const tplSrc = path.join(assetsRoot, CONFIG_TEMPLATE);
|
|
32
|
+
if (!(await isDir(claudeSrc))) {
|
|
33
|
+
throw new InstallError(`配布アセットが見つかりません: ${claudeSrc}\n(パッケージのビルド時に 'npm run sync-assets' が実行されていない可能性があります)`);
|
|
34
|
+
}
|
|
35
|
+
if (!(await isFile(tplSrc))) {
|
|
36
|
+
throw new InstallError(`設定テンプレートが見つかりません: ${tplSrc}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function installClaude(assetsRoot, targetDir, overwrite) {
|
|
40
|
+
const src = path.join(assetsRoot, CLAUDE_DIR);
|
|
41
|
+
const dst = path.join(targetDir, CLAUDE_DIR);
|
|
42
|
+
const exists = await pathExists(dst);
|
|
43
|
+
if (exists && !overwrite)
|
|
44
|
+
return "skipped";
|
|
45
|
+
if (exists)
|
|
46
|
+
await fs.rm(dst, { recursive: true, force: true });
|
|
47
|
+
await copyTree(src, dst);
|
|
48
|
+
return exists ? "overwritten" : "created";
|
|
49
|
+
}
|
|
50
|
+
async function installConfig(assetsRoot, targetDir, projectName) {
|
|
51
|
+
const dst = path.join(targetDir, CONFIG_FILE);
|
|
52
|
+
if (await pathExists(dst))
|
|
53
|
+
return "kept";
|
|
54
|
+
const raw = await fs.readFile(path.join(assetsRoot, CONFIG_TEMPLATE), "utf8");
|
|
55
|
+
const rendered = renderTemplate(raw, { "project.name": projectName });
|
|
56
|
+
await fs.writeFile(dst, rendered);
|
|
57
|
+
return "created";
|
|
58
|
+
}
|
|
59
|
+
async function ensureDocs(targetDir) {
|
|
60
|
+
const dir = path.join(targetDir, DOCS_DIR);
|
|
61
|
+
if (await pathExists(dir))
|
|
62
|
+
return "kept";
|
|
63
|
+
await fs.mkdir(dir, { recursive: true });
|
|
64
|
+
return "created";
|
|
65
|
+
}
|
|
66
|
+
async function copyTree(src, dst) {
|
|
67
|
+
await fs.mkdir(dst, { recursive: true });
|
|
68
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
const srcPath = path.join(src, entry.name);
|
|
71
|
+
const dstPath = path.join(dst, entry.name);
|
|
72
|
+
if (entry.isDirectory()) {
|
|
73
|
+
await copyTree(srcPath, dstPath);
|
|
74
|
+
}
|
|
75
|
+
else if (entry.isSymbolicLink()) {
|
|
76
|
+
const link = await fs.readlink(srcPath);
|
|
77
|
+
await fs.symlink(link, dstPath);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
await fs.copyFile(srcPath, dstPath);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** {{ key }} を vars[key] に置換する。未定義のキーはそのまま残す(実行時プレースホルダ用)。 */
|
|
85
|
+
function renderTemplate(input, vars) {
|
|
86
|
+
return input.replace(/\{\{\s*([a-zA-Z0-9._-]+)\s*\}\}/g, (match, key) => Object.prototype.hasOwnProperty.call(vars, key) ? vars[key] : match);
|
|
87
|
+
}
|
|
88
|
+
async function pathExists(p) {
|
|
89
|
+
try {
|
|
90
|
+
await fs.stat(p);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
if (isErrnoCode(err, "ENOENT"))
|
|
95
|
+
return false;
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function isDir(p) {
|
|
100
|
+
try {
|
|
101
|
+
return (await fs.stat(p)).isDirectory();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function isFile(p) {
|
|
108
|
+
try {
|
|
109
|
+
return (await fs.stat(p)).isFile();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function isErrnoCode(err, code) {
|
|
116
|
+
return (typeof err === "object" &&
|
|
117
|
+
err !== null &&
|
|
118
|
+
"code" in err &&
|
|
119
|
+
err.code === code);
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@careerchain/stdd",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "STDD (Spec and Test Driven Development) を既存・新規プロジェクトに導入する CLI",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"stdd": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"assets",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"sync-assets": "node scripts/sync-assets.mjs",
|
|
20
|
+
"build": "npm run sync-assets && tsc",
|
|
21
|
+
"start": "node dist/cli.js",
|
|
22
|
+
"prepack": "npm run build"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"prompts": "^2.4.2"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.11.0",
|
|
29
|
+
"@types/prompts": "^2.4.9",
|
|
30
|
+
"typescript": "^5.4.0"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"stdd",
|
|
37
|
+
"spec-driven-development",
|
|
38
|
+
"test-driven-development",
|
|
39
|
+
"claude-code",
|
|
40
|
+
"ai-agent"
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/careerchain-ys/stdd.git",
|
|
45
|
+
"directory": "packages/stdd"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/careerchain-ys/stdd"
|
|
48
|
+
}
|