create-takt-sdd 0.6.0 → 0.8.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/dist/cli.js CHANGED
@@ -8,6 +8,9 @@ import { install } from "./install.js";
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = dirname(__filename);
10
10
  const packageRoot = resolve(__dirname, "..");
11
+ function isLayout(value) {
12
+ return value === "auto" || value === "modern" || value === "legacy";
13
+ }
11
14
  function parseArgs(argv) {
12
15
  const args = {
13
16
  lang: "en",
@@ -18,6 +21,7 @@ function parseArgs(argv) {
18
21
  tag: undefined,
19
22
  withoutSkills: false,
20
23
  refsPath: "references/takt",
24
+ layout: "auto",
21
25
  };
22
26
  for (let i = 0; i < argv.length; i++) {
23
27
  const arg = argv[i];
@@ -58,6 +62,15 @@ function parseArgs(argv) {
58
62
  args.refsPath = value;
59
63
  break;
60
64
  }
65
+ case "--layout": {
66
+ const value = argv[++i];
67
+ if (!value || !isLayout(value)) {
68
+ console.error(`Error: --layout requires "auto", "modern", or "legacy". Got: ${value ?? "(empty)"}`);
69
+ process.exit(1);
70
+ }
71
+ args.layout = value;
72
+ break;
73
+ }
61
74
  case "-h":
62
75
  case "--help":
63
76
  args.help = true;
@@ -92,6 +105,7 @@ async function main() {
92
105
  tag: args.tag,
93
106
  withoutSkills: args.withoutSkills,
94
107
  refsPath: args.refsPath,
108
+ layout: args.layout,
95
109
  cwd: process.cwd(),
96
110
  });
97
111
  }
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by scripts/embed-takt-ref.js — do not edit
2
- export const TAKT_REF_HASH = "a89099e819af7b6982c520e7729b17e08de8246a";
2
+ export const TAKT_REF_HASH = "d2c4acd3de2bd383f753905bc7cb7efac3c92d4c";
package/dist/i18n.js CHANGED
@@ -23,6 +23,7 @@ const en = {
23
23
  taktRefsInstalled: "Installed takt references (builtins, docs)",
24
24
  taktRefsSkipped: "Takt references already exist, skipping",
25
25
  taktRefsError: "Warning: Failed to download takt references. Skills may not find style guides.",
26
+ layoutDetected: (layout) => `Using ${layout} layout`,
26
27
  fileAdded: (path) => `Added: ${path}`,
27
28
  fileUpdated: (path) => `Updated: ${path}`,
28
29
  fileSkippedCustomized: (path) => `Skipped (customized): ${path}`,
@@ -35,6 +36,7 @@ Options:
35
36
  --force Overwrite existing .takt/ directory (ignored if manifest exists)
36
37
  --dry-run Preview without writing files
37
38
  --without-skills Skip installing takt skills to .agent/skills/
39
+ --layout <mode> Directory layout: auto, modern, legacy (default: auto)
38
40
  --refs-path <path> Path for takt references (default: references/takt)
39
41
  -h, --help Show this help
40
42
  -v, --version Show version`,
@@ -77,6 +79,7 @@ const ja = {
77
79
  taktRefsInstalled: "takt リファレンスをインストールしました(builtins, docs)",
78
80
  taktRefsSkipped: "takt リファレンスは既に存在するためスキップしました",
79
81
  taktRefsError: "警告: takt リファレンスのダウンロードに失敗しました。スキルがスタイルガイドを参照できない可能性があります。",
82
+ layoutDetected: (layout) => `${layout} レイアウトを使用します`,
80
83
  fileAdded: (path) => `追加: ${path}`,
81
84
  fileUpdated: (path) => `更新: ${path}`,
82
85
  fileSkippedCustomized: (path) => `スキップ(カスタマイズ済み): ${path}`,
@@ -89,6 +92,7 @@ const ja = {
89
92
  --force 既存の .takt/ を上書き(マニフェストがある場合は無視)
90
93
  --dry-run プレビューのみ(ファイル書き込みなし)
91
94
  --without-skills takt スキルのインストールをスキップ
95
+ --layout <mode> ディレクトリレイアウト: auto, modern, legacy(デフォルト: auto)
92
96
  --refs-path <path> takt リファレンスのパス(デフォルト: references/takt)
93
97
  -h, --help ヘルプを表示
94
98
  -v, --version バージョンを表示`,
package/dist/install.js CHANGED
@@ -20,14 +20,49 @@ const REPO = "j5ik2o/takt-sdd";
20
20
  const TAKT_REPO = "nrslib/takt";
21
21
  const TARGET_DIR = ".takt";
22
22
  const DEFAULT_REFS_PATH = "references/takt";
23
- const FACET_DIRS = [
24
- "pieces",
23
+ const PIECE_DIR = "pieces";
24
+ const FACET_TYPES = [
25
25
  "personas",
26
26
  "policies",
27
27
  "instructions",
28
28
  "knowledge",
29
29
  "output-contracts",
30
30
  ];
31
+ function srcFacetPath(facetType) {
32
+ return `facets/${facetType}`;
33
+ }
34
+ function destFacetPath(facetType, layout) {
35
+ return layout === "modern" ? `facets/${facetType}` : facetType;
36
+ }
37
+ function detectLayout() {
38
+ try {
39
+ const output = execSync("takt --version", {
40
+ encoding: "utf-8",
41
+ stdio: ["pipe", "pipe", "ignore"],
42
+ }).trim();
43
+ const match = output.match(/(\d+)\.(\d+)\.(\d+)/);
44
+ if (match) {
45
+ const [, major, minor] = match.map(Number);
46
+ if (major > 0 || (major === 0 && minor >= 22))
47
+ return "modern";
48
+ return "legacy";
49
+ }
50
+ }
51
+ catch { /* takt not installed */ }
52
+ return "modern";
53
+ }
54
+ function rewritePiecePathsForLegacy(piecesDir) {
55
+ if (!existsSync(piecesDir))
56
+ return;
57
+ for (const file of readdirSync(piecesDir).filter(f => f.endsWith(".yaml"))) {
58
+ const filePath = join(piecesDir, file);
59
+ let content = readFileSync(filePath, "utf-8");
60
+ for (const type of FACET_TYPES) {
61
+ content = content.replaceAll(`../facets/${type}/`, `../${type}/`);
62
+ }
63
+ writeFileSync(filePath, content, "utf-8");
64
+ }
65
+ }
31
66
  const TAKT_SKILLS = [
32
67
  "takt-analyze",
33
68
  "takt-facet",
@@ -238,14 +273,25 @@ export async function install(options) {
238
273
  if (!existsSync(extractedTakt)) {
239
274
  errorExit(msg.archiveError);
240
275
  }
276
+ const resolvedLayout = options.layout === "auto" ? detectLayout() : options.layout;
277
+ info(msg.layoutDetected(resolvedLayout));
241
278
  // dry-run: ファイル一覧のみ表示
242
279
  if (options.dryRun) {
243
280
  info(msg.dryRunHeader);
244
- for (const dir of FACET_DIRS) {
245
- const srcDir = join(extractedTakt, options.lang, dir);
281
+ // pieces
282
+ const piecesSrcDry = join(extractedTakt, options.lang, PIECE_DIR);
283
+ if (existsSync(piecesSrcDry)) {
284
+ for (const file of collectFiles(piecesSrcDry, piecesSrcDry)) {
285
+ console.log(msg.dryRunItem(join(TARGET_DIR, PIECE_DIR, file)));
286
+ }
287
+ }
288
+ // facets
289
+ for (const facetType of FACET_TYPES) {
290
+ const srcDir = join(extractedTakt, options.lang, srcFacetPath(facetType));
246
291
  if (existsSync(srcDir)) {
247
- for (const file of collectFiles(srcDir, join(extractedTakt, options.lang))) {
248
- console.log(msg.dryRunItem(join(TARGET_DIR, file)));
292
+ const destPrefix = destFacetPath(facetType, resolvedLayout);
293
+ for (const file of collectFiles(srcDir, srcDir)) {
294
+ console.log(msg.dryRunItem(join(TARGET_DIR, destPrefix, file)));
249
295
  }
250
296
  }
251
297
  }
@@ -275,14 +321,32 @@ export async function install(options) {
275
321
  info(isUpdate ? msg.updating : msg.installing);
276
322
  mkdirSync(targetPath, { recursive: true });
277
323
  const allFiles = {};
278
- for (const dir of FACET_DIRS) {
279
- const srcDir = join(extractedTakt, options.lang, dir);
324
+ // pieces(legacy時はsync前にソースのパスを書き換え)
325
+ const piecesSrc = join(extractedTakt, options.lang, PIECE_DIR);
326
+ if (existsSync(piecesSrc)) {
327
+ const piecesDest = join(targetPath, PIECE_DIR);
328
+ if (!isUpdate && existsSync(piecesDest)) {
329
+ rmSync(piecesDest, { recursive: true });
330
+ }
331
+ let effectiveSrc = piecesSrc;
332
+ if (resolvedLayout === "legacy") {
333
+ const legacyTmp = join(tmpDir, "legacy-pieces");
334
+ cpSync(piecesSrc, legacyTmp, { recursive: true });
335
+ rewritePiecePathsForLegacy(legacyTmp);
336
+ effectiveSrc = legacyTmp;
337
+ }
338
+ const result = syncDirectory(effectiveSrc, piecesDest, effectiveSrc, piecesDest, isUpdate ? manifest : null, msg, options.cwd);
339
+ Object.assign(allFiles, result.files);
340
+ }
341
+ // facets
342
+ for (const facetType of FACET_TYPES) {
343
+ const srcDir = join(extractedTakt, options.lang, srcFacetPath(facetType));
280
344
  if (existsSync(srcDir)) {
281
- const destDir = join(targetPath, dir);
345
+ const destDir = join(targetPath, destFacetPath(facetType, resolvedLayout));
282
346
  if (!isUpdate && existsSync(destDir)) {
283
347
  rmSync(destDir, { recursive: true });
284
348
  }
285
- const result = syncDirectory(srcDir, destDir, join(extractedTakt, options.lang), targetPath, isUpdate ? manifest : null, msg, options.cwd);
349
+ const result = syncDirectory(srcDir, destDir, srcDir, destDir, isUpdate ? manifest : null, msg, options.cwd);
286
350
  Object.assign(allFiles, result.files);
287
351
  }
288
352
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-takt-sdd",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Installer for takt-sdd: Spec-Driven Development workflow for takt",
5
5
  "type": "module",
6
6
  "bin": {