foundruu 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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/assets/templates/ai/_common/company/coding-standard.md +35 -0
  4. package/assets/templates/ai/_common/company/git-workflow.md +40 -0
  5. package/assets/templates/ai/_common/company/review-policy.md +30 -0
  6. package/assets/templates/ai/_common/company/security.md +25 -0
  7. package/assets/templates/ai/_common/project/architecture.md.hbs +29 -0
  8. package/assets/templates/ai/_common/project/conventions.md +24 -0
  9. package/assets/templates/ai/_common/project/overview.md.hbs +37 -0
  10. package/assets/templates/ai/_common/project/testing.md +32 -0
  11. package/assets/templates/ai/claude/CLAUDE.md.hbs +65 -0
  12. package/assets/templates/ai/codex/CODEX.md.hbs +60 -0
  13. package/assets/templates/base/.env.example +4 -0
  14. package/assets/templates/base/README.md.hbs +73 -0
  15. package/assets/templates/features/discord/.env.example.patch +3 -0
  16. package/assets/templates/features/discord/package.json.patch +5 -0
  17. package/assets/templates/features/docker/Dockerfile.hbs +38 -0
  18. package/assets/templates/features/docker/docker-compose.yml.hbs +11 -0
  19. package/assets/templates/features/eslint/eslint.config.js +14 -0
  20. package/assets/templates/features/eslint/package.json.patch +11 -0
  21. package/assets/templates/features/github-actions/.github/workflows/ci.yml.hbs +51 -0
  22. package/assets/templates/features/lark/.env.example.patch +3 -0
  23. package/assets/templates/features/lark/package.json.patch +5 -0
  24. package/assets/templates/features/line-bot/.env.example.patch +2 -0
  25. package/assets/templates/features/line-bot/package.json.patch +5 -0
  26. package/assets/templates/features/prettier/.prettierignore +3 -0
  27. package/assets/templates/features/prettier/.prettierrc +7 -0
  28. package/assets/templates/features/prettier/package.json.patch +9 -0
  29. package/assets/templates/features/react/index.html.hbs +12 -0
  30. package/assets/templates/features/react/package.json.patch +17 -0
  31. package/assets/templates/features/react/src/web/App.tsx.hbs +8 -0
  32. package/assets/templates/features/react/src/web/main.tsx +9 -0
  33. package/assets/templates/features/react/vite.config.ts +6 -0
  34. package/assets/templates/features/react-laravel/package.json.patch +19 -0
  35. package/assets/templates/features/react-laravel/resources/js/app.jsx.hbs +17 -0
  36. package/assets/templates/features/react-laravel/vite.config.js +13 -0
  37. package/assets/templates/features/vitest/package.json.patch +10 -0
  38. package/assets/templates/features/vitest/tests/index.test.ts.hbs +7 -0
  39. package/assets/templates/features/vitest/vitest.config.ts +11 -0
  40. package/assets/templates/languages/laravel/.env.example.patch +12 -0
  41. package/assets/templates/languages/laravel/composer.json.hbs +41 -0
  42. package/assets/templates/languages/laravel/docs/SETUP.md.hbs +24 -0
  43. package/assets/templates/languages/typescript/package.json.patch +20 -0
  44. package/assets/templates/languages/typescript/src/index.ts.hbs +1 -0
  45. package/assets/templates/languages/typescript/tsconfig.json +17 -0
  46. package/assets/workflow/.ai/prompts/session-workflow.md +72 -0
  47. package/assets/workflow/.ai/templates/session/design.md +21 -0
  48. package/assets/workflow/.ai/templates/session/questions.md +34 -0
  49. package/assets/workflow/.ai/templates/session/requirements.md +25 -0
  50. package/assets/workflow/.ai/templates/session/summary.md +21 -0
  51. package/assets/workflow/.ai/templates/session/tasks.md +13 -0
  52. package/assets/workflow/.ai/templates/session/test.md +15 -0
  53. package/assets/workflow/.ai/workflows/bugfix.md +19 -0
  54. package/assets/workflow/.ai/workflows/development.md +27 -0
  55. package/assets/workflow/.ai/workflows/feature.md +20 -0
  56. package/assets/workflow/.ai/workflows/review.md +19 -0
  57. package/dist/cli.d.ts +2 -0
  58. package/dist/cli.js +89 -0
  59. package/dist/cli.js.map +1 -0
  60. package/dist/commands/doctor.d.ts +6 -0
  61. package/dist/commands/doctor.js +64 -0
  62. package/dist/commands/doctor.js.map +1 -0
  63. package/dist/commands/init.d.ts +8 -0
  64. package/dist/commands/init.js +94 -0
  65. package/dist/commands/init.js.map +1 -0
  66. package/dist/commands/session.d.ts +8 -0
  67. package/dist/commands/session.js +96 -0
  68. package/dist/commands/session.js.map +1 -0
  69. package/dist/commands/update.d.ts +13 -0
  70. package/dist/commands/update.js +64 -0
  71. package/dist/commands/update.js.map +1 -0
  72. package/dist/commands/workflow.d.ts +7 -0
  73. package/dist/commands/workflow.js +64 -0
  74. package/dist/commands/workflow.js.map +1 -0
  75. package/dist/core/assets.d.ts +8 -0
  76. package/dist/core/assets.js +29 -0
  77. package/dist/core/assets.js.map +1 -0
  78. package/dist/core/config.d.ts +17 -0
  79. package/dist/core/config.js +31 -0
  80. package/dist/core/config.js.map +1 -0
  81. package/dist/core/copier.d.ts +25 -0
  82. package/dist/core/copier.js +103 -0
  83. package/dist/core/copier.js.map +1 -0
  84. package/dist/core/fetcher.d.ts +10 -0
  85. package/dist/core/fetcher.js +56 -0
  86. package/dist/core/fetcher.js.map +1 -0
  87. package/dist/core/logger.d.ts +7 -0
  88. package/dist/core/logger.js +15 -0
  89. package/dist/core/logger.js.map +1 -0
  90. package/dist/core/sync.d.ts +26 -0
  91. package/dist/core/sync.js +69 -0
  92. package/dist/core/sync.js.map +1 -0
  93. package/dist/doctor/checks.d.ts +5 -0
  94. package/dist/doctor/checks.js +97 -0
  95. package/dist/doctor/checks.js.map +1 -0
  96. package/dist/doctor/deep.d.ts +39 -0
  97. package/dist/doctor/deep.js +144 -0
  98. package/dist/doctor/deep.js.map +1 -0
  99. package/dist/doctor/rc.d.ts +13 -0
  100. package/dist/doctor/rc.js +31 -0
  101. package/dist/doctor/rc.js.map +1 -0
  102. package/dist/doctor/runner.d.ts +3 -0
  103. package/dist/doctor/runner.js +39 -0
  104. package/dist/doctor/runner.js.map +1 -0
  105. package/dist/doctor/types.d.ts +32 -0
  106. package/dist/doctor/types.js +3 -0
  107. package/dist/doctor/types.js.map +1 -0
  108. package/dist/registry/templates.d.ts +18 -0
  109. package/dist/registry/templates.js +45 -0
  110. package/dist/registry/templates.js.map +1 -0
  111. package/package.json +50 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/core/assets.ts"],"names":[],"mappings":";;;;;AAQA,gCAMC;AAED,sCAEC;AAED,oCAEC;AAtBD,gDAAwB;AACxB,4CAAoB;AAEpB;;;;GAIG;AACH,SAAgB,UAAU;IACxB,MAAM,IAAI,GAAG,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,aAAa;IAC3B,OAAO,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AAED,SAAgB,YAAY;IAC1B,OAAO,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,17 @@
1
+ export declare const CONFIG_FILE = "foundruu.json";
2
+ export interface FoundruuConfig {
3
+ version: string;
4
+ template?: string;
5
+ projectName?: string;
6
+ installedAt?: string;
7
+ workflow?: {
8
+ version: string;
9
+ installedAt: string;
10
+ /** 管理ファイルの相対パス → 導入時の sha256(update 時のユーザー編集検出に使用) */
11
+ files?: Record<string, string>;
12
+ };
13
+ }
14
+ export declare function configPath(cwd: string): string;
15
+ export declare function readConfig(cwd: string): FoundruuConfig | null;
16
+ export declare function writeConfig(cwd: string, config: FoundruuConfig): void;
17
+ export declare function cliVersion(): string;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CONFIG_FILE = void 0;
7
+ exports.configPath = configPath;
8
+ exports.readConfig = readConfig;
9
+ exports.writeConfig = writeConfig;
10
+ exports.cliVersion = cliVersion;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ exports.CONFIG_FILE = "foundruu.json";
14
+ function configPath(cwd) {
15
+ return path_1.default.join(cwd, exports.CONFIG_FILE);
16
+ }
17
+ function readConfig(cwd) {
18
+ const file = configPath(cwd);
19
+ if (!fs_1.default.existsSync(file))
20
+ return null;
21
+ return JSON.parse(fs_1.default.readFileSync(file, "utf8"));
22
+ }
23
+ function writeConfig(cwd, config) {
24
+ fs_1.default.writeFileSync(configPath(cwd), JSON.stringify(config, null, 2) + "\n");
25
+ }
26
+ function cliVersion() {
27
+ // dist/core/config.js からも src/core/config.ts からも ../../package.json
28
+ const pkg = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, "..", "..", "package.json"), "utf8"));
29
+ return pkg.version;
30
+ }
31
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":";;;;;;AAkBA,gCAEC;AAED,gCAIC;AAED,kCAEC;AAED,gCAMC;AAtCD,4CAAoB;AACpB,gDAAwB;AAEX,QAAA,WAAW,GAAG,eAAe,CAAC;AAe3C,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAW,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,UAAU,CAAC,GAAW;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAmB,CAAC;AACrE,CAAC;AAED,SAAgB,WAAW,CAAC,GAAW,EAAE,MAAsB;IAC7D,YAAE,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC5E,CAAC;AAED,SAAgB,UAAU;IACxB,oEAAoE;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACtD,CAAC;IACzB,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface TemplateContext {
2
+ projectName: string;
3
+ description: string;
4
+ language: string;
5
+ languageLabel: string;
6
+ aiProviders: string[];
7
+ aiProviderLabels: string[];
8
+ features: string[];
9
+ featureLabels: string[];
10
+ year: number;
11
+ }
12
+ export interface CopyResult {
13
+ written: string[];
14
+ skipped: string[];
15
+ }
16
+ /**
17
+ * srcDir 以下を destDir へ再帰コピーする。
18
+ * - `*.hbs` : Handlebars でレンダリングし拡張子を外して書き出す
19
+ * - `*.patch` : 同名ファイル(拡張子を外した先)へ JSON ディープマージ
20
+ * - それ以外 : そのままコピー
21
+ * - 既存ファイルは overwrite=false ならスキップ
22
+ */
23
+ export declare function copyTree(srcDir: string, destDir: string, ctx: TemplateContext, options?: {
24
+ overwrite?: boolean;
25
+ }): CopyResult;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.copyTree = copyTree;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const handlebars_1 = __importDefault(require("handlebars"));
10
+ function createHandlebars(ctx) {
11
+ const hbs = handlebars_1.default.create();
12
+ hbs.registerHelper("hasFeature", (id) => ctx.features.includes(id));
13
+ hbs.registerHelper("hasAi", (id) => ctx.aiProviders.includes(id));
14
+ hbs.registerHelper("eq", function (a, b, options) {
15
+ if (options && typeof options.fn === "function") {
16
+ return a === b ? options.fn(this) : options.inverse(this);
17
+ }
18
+ return a === b;
19
+ });
20
+ return hbs;
21
+ }
22
+ function deepMerge(target, source) {
23
+ const out = { ...target };
24
+ for (const [key, value] of Object.entries(source)) {
25
+ const existing = out[key];
26
+ if (value && typeof value === "object" && !Array.isArray(value) &&
27
+ existing && typeof existing === "object" && !Array.isArray(existing)) {
28
+ out[key] = deepMerge(existing, value);
29
+ }
30
+ else if (Array.isArray(value) && Array.isArray(existing)) {
31
+ out[key] = [...new Set([...existing, ...value])];
32
+ }
33
+ else {
34
+ out[key] = value;
35
+ }
36
+ }
37
+ return out;
38
+ }
39
+ /**
40
+ * srcDir 以下を destDir へ再帰コピーする。
41
+ * - `*.hbs` : Handlebars でレンダリングし拡張子を外して書き出す
42
+ * - `*.patch` : 同名ファイル(拡張子を外した先)へ JSON ディープマージ
43
+ * - それ以外 : そのままコピー
44
+ * - 既存ファイルは overwrite=false ならスキップ
45
+ */
46
+ function copyTree(srcDir, destDir, ctx, options = {}) {
47
+ const overwrite = options.overwrite ?? false;
48
+ const hbs = createHandlebars(ctx);
49
+ const result = { written: [], skipped: [] };
50
+ const walk = (src, dest) => {
51
+ for (const entry of fs_1.default.readdirSync(src, { withFileTypes: true })) {
52
+ const srcPath = path_1.default.join(src, entry.name);
53
+ if (entry.isDirectory()) {
54
+ walk(srcPath, path_1.default.join(dest, entry.name));
55
+ continue;
56
+ }
57
+ if (entry.name.endsWith(".patch")) {
58
+ const destPath = path_1.default.join(dest, entry.name.replace(/\.patch$/, ""));
59
+ // patch 内にも {{projectName}} 等のテンプレート変数を書けるようレンダリングしてから解釈する
60
+ const rendered = hbs.compile(fs_1.default.readFileSync(srcPath, "utf8"))(ctx);
61
+ fs_1.default.mkdirSync(dest, { recursive: true });
62
+ if (destPath.endsWith(".json")) {
63
+ // JSON はディープマージ
64
+ const patch = JSON.parse(rendered);
65
+ const base = fs_1.default.existsSync(destPath)
66
+ ? JSON.parse(fs_1.default.readFileSync(destPath, "utf8"))
67
+ : {};
68
+ fs_1.default.writeFileSync(destPath, JSON.stringify(deepMerge(base, patch), null, 2) + "\n");
69
+ }
70
+ else {
71
+ // テキスト(.env.example 等)は末尾へ追記(既に含まれていればスキップ)
72
+ const base = fs_1.default.existsSync(destPath) ? fs_1.default.readFileSync(destPath, "utf8") : "";
73
+ if (base.includes(rendered.trim())) {
74
+ result.skipped.push(destPath);
75
+ continue;
76
+ }
77
+ const sep = base.length && !base.endsWith("\n") ? "\n" : "";
78
+ fs_1.default.writeFileSync(destPath, base + sep + rendered.trimEnd() + "\n");
79
+ }
80
+ result.written.push(destPath);
81
+ continue;
82
+ }
83
+ const isHbs = entry.name.endsWith(".hbs");
84
+ const destPath = path_1.default.join(dest, isHbs ? entry.name.replace(/\.hbs$/, "") : entry.name);
85
+ if (fs_1.default.existsSync(destPath) && !overwrite) {
86
+ result.skipped.push(destPath);
87
+ continue;
88
+ }
89
+ fs_1.default.mkdirSync(dest, { recursive: true });
90
+ if (isHbs) {
91
+ const rendered = hbs.compile(fs_1.default.readFileSync(srcPath, "utf8"))(ctx);
92
+ fs_1.default.writeFileSync(destPath, rendered);
93
+ }
94
+ else {
95
+ fs_1.default.copyFileSync(srcPath, destPath);
96
+ }
97
+ result.written.push(destPath);
98
+ }
99
+ };
100
+ walk(srcDir, destDir);
101
+ return result;
102
+ }
103
+ //# sourceMappingURL=copier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copier.js","sourceRoot":"","sources":["../../src/core/copier.ts"],"names":[],"mappings":";;;;;AA2DA,4BAiEC;AA5HD,4CAAoB;AACpB,gDAAwB;AACxB,4DAAoC;AAmBpC,SAAS,gBAAgB,CAAC,GAAoB;IAC5C,MAAM,GAAG,GAAG,oBAAU,CAAC,MAAM,EAAE,CAAC;IAChC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,UAAyB,CAAU,EAAE,CAAU,EAAE,OAAiC;QACzG,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,OAAO,GAAwB,CAAC;AAClC,CAAC;AAED,SAAS,SAAS,CAAC,MAA+B,EAAE,MAA+B;IACjF,MAAM,GAAG,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;IACnD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1B,IACE,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAC3D,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EACpE,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,QAAmC,EAAE,KAAgC,CAAC,CAAC;QAC9F,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ,CACtB,MAAc,EACd,OAAe,EACf,GAAoB,EACpB,UAAmC,EAAE;IAErC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,MAAM,GAAe,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAExD,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,IAAY,EAAQ,EAAE;QAC/C,KAAK,MAAM,KAAK,IAAI,YAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACjE,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,OAAO,EAAE,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC3C,SAAS;YACX,CAAC;YAED,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;gBACrE,2DAA2D;gBAC3D,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACpE,YAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACxC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC/B,gBAAgB;oBAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAA4B,CAAC;oBAC9D,MAAM,IAAI,GAAG,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;wBAClC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAA6B;wBAC5E,CAAC,CAAC,EAAE,CAAC;oBACP,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBACrF,CAAC;qBAAM,CAAC;oBACN,4CAA4C;oBAC5C,MAAM,IAAI,GAAG,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;wBACnC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC9B,SAAS;oBACX,CAAC;oBACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5D,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,GAAG,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;gBACrE,CAAC;gBACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC9B,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAExF,IAAI,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC1C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC9B,SAAS;YACX,CAAC;YAED,YAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACpE,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACrC,CAAC;YACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * GitHub 上の最新アセット(assets/workflow)を取得し、そのパスを返す。
3
+ * 取得できない場合(オフライン等)は CLI 同梱アセットへフォールバックする。
4
+ */
5
+ export declare function fetchWorkflowAssets(options?: {
6
+ local?: boolean;
7
+ }): {
8
+ root: string;
9
+ source: "remote" | "bundled";
10
+ };
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchWorkflowAssets = fetchWorkflowAssets;
7
+ const child_process_1 = require("child_process");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const assets_1 = require("./assets");
12
+ const logger_1 = require("./logger");
13
+ const ASSETS_REPO = "https://github.com/Ruu5LP/RuunFoundry.git";
14
+ function cacheDir() {
15
+ return path_1.default.join(os_1.default.homedir(), ".foundruu", "cache", "RuunFoundry");
16
+ }
17
+ /**
18
+ * GitHub 上の最新アセット(assets/workflow)を取得し、そのパスを返す。
19
+ * 取得できない場合(オフライン等)は CLI 同梱アセットへフォールバックする。
20
+ */
21
+ function fetchWorkflowAssets(options = {}) {
22
+ if (options.local) {
23
+ return { root: (0, assets_1.workflowRoot)(), source: "bundled" };
24
+ }
25
+ const cache = cacheDir();
26
+ try {
27
+ if (fs_1.default.existsSync(path_1.default.join(cache, ".git"))) {
28
+ (0, child_process_1.execFileSync)("git", ["-C", cache, "fetch", "--depth", "1", "origin", "main"], {
29
+ stdio: "pipe",
30
+ timeout: 30_000,
31
+ });
32
+ (0, child_process_1.execFileSync)("git", ["-C", cache, "reset", "--hard", "origin/main"], {
33
+ stdio: "pipe",
34
+ timeout: 30_000,
35
+ });
36
+ }
37
+ else {
38
+ fs_1.default.rmSync(cache, { recursive: true, force: true });
39
+ fs_1.default.mkdirSync(path_1.default.dirname(cache), { recursive: true });
40
+ (0, child_process_1.execFileSync)("git", ["clone", "--depth", "1", ASSETS_REPO, cache], {
41
+ stdio: "pipe",
42
+ timeout: 60_000,
43
+ });
44
+ }
45
+ const remoteWorkflow = path_1.default.join(cache, "assets", "workflow");
46
+ if (fs_1.default.existsSync(remoteWorkflow)) {
47
+ return { root: remoteWorkflow, source: "remote" };
48
+ }
49
+ logger_1.log.warn("リモートリポジトリに assets/workflow が見つかりません。同梱アセットを使用します。");
50
+ }
51
+ catch {
52
+ logger_1.log.warn("GitHub から最新アセットを取得できませんでした(オフライン?)。同梱アセットを使用します。");
53
+ }
54
+ return { root: (0, assets_1.workflowRoot)(), source: "bundled" };
55
+ }
56
+ //# sourceMappingURL=fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../../src/core/fetcher.ts"],"names":[],"mappings":";;;;;AAiBA,kDAoCC;AArDD,iDAA6C;AAC7C,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AACxB,qCAAwC;AACxC,qCAA+B;AAE/B,MAAM,WAAW,GAAG,2CAA2C,CAAC;AAEhE,SAAS,QAAQ;IACf,OAAO,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,UAA+B,EAAE;IAInE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,IAAA,qBAAY,GAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACrD,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,IAAI,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YAC5C,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;gBAC5E,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,MAAM;aAChB,CAAC,CAAC;YACH,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE;gBACnE,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,MAAM;aAChB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,YAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE;gBACjE,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,MAAM;aAChB,CAAC,CAAC;QACL,CAAC;QACD,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC9D,IAAI,YAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACpD,CAAC;QACD,YAAG,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,YAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAA,qBAAY,GAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare const log: {
2
+ info: (msg: string) => void;
3
+ step: (msg: string) => void;
4
+ success: (msg: string) => void;
5
+ warn: (msg: string) => void;
6
+ error: (msg: string) => void;
7
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.log = void 0;
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
+ exports.log = {
9
+ info: (msg) => console.log(msg),
10
+ step: (msg) => console.log(picocolors_1.default.cyan(`▸ ${msg}`)),
11
+ success: (msg) => console.log(picocolors_1.default.green(`✔ ${msg}`)),
12
+ warn: (msg) => console.log(picocolors_1.default.yellow(`⚠ ${msg}`)),
13
+ error: (msg) => console.error(picocolors_1.default.red(`✖ ${msg}`)),
14
+ };
15
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":";;;;;;AAAA,4DAA4B;AAEf,QAAA,GAAG,GAAG;IACjB,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7C,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAC7D,OAAO,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACjE,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAE,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAC/D,KAAK,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAE,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;CAChE,CAAC"}
@@ -0,0 +1,26 @@
1
+ export type FileHashes = Record<string, string>;
2
+ export interface SyncPlanEntry {
3
+ relPath: string;
4
+ status: "add" | "update" | "unchanged" | "user-modified";
5
+ }
6
+ export interface SyncResult {
7
+ plan: SyncPlanEntry[];
8
+ /** 書き込み後の管理ファイルハッシュ(foundruu.json へ記録する) */
9
+ hashes: FileHashes;
10
+ }
11
+ export declare function hashFile(filePath: string): string;
12
+ export declare function listFiles(dir: string, base?: string): string[];
13
+ /**
14
+ * srcDir(最新アセット)を destDir へ同期する計画を立て、dryRun でなければ適用する。
15
+ *
16
+ * 判定(recorded = 前回導入時に記録したハッシュ):
17
+ * - 導入先に無い → add
18
+ * - 最新と同一 → unchanged
19
+ * - 導入先 == recorded(ユーザー未編集) → update(安全に上書き)
20
+ * - 導入先 != recorded(ユーザーが編集済み) → user-modified(force 時のみ上書き)
21
+ * - recorded が無い(旧バージョン導入等) → user-modified 扱いで保護
22
+ */
23
+ export declare function syncTree(srcDir: string, destDir: string, recorded: FileHashes, options?: {
24
+ force?: boolean;
25
+ dryRun?: boolean;
26
+ }): SyncResult;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.hashFile = hashFile;
7
+ exports.listFiles = listFiles;
8
+ exports.syncTree = syncTree;
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ function hashFile(filePath) {
13
+ return crypto_1.default.createHash("sha256").update(fs_1.default.readFileSync(filePath)).digest("hex");
14
+ }
15
+ function listFiles(dir, base = dir) {
16
+ const out = [];
17
+ for (const entry of fs_1.default.readdirSync(dir, { withFileTypes: true })) {
18
+ const full = path_1.default.join(dir, entry.name);
19
+ if (entry.isDirectory())
20
+ out.push(...listFiles(full, base));
21
+ else
22
+ out.push(path_1.default.relative(base, full));
23
+ }
24
+ return out;
25
+ }
26
+ /**
27
+ * srcDir(最新アセット)を destDir へ同期する計画を立て、dryRun でなければ適用する。
28
+ *
29
+ * 判定(recorded = 前回導入時に記録したハッシュ):
30
+ * - 導入先に無い → add
31
+ * - 最新と同一 → unchanged
32
+ * - 導入先 == recorded(ユーザー未編集) → update(安全に上書き)
33
+ * - 導入先 != recorded(ユーザーが編集済み) → user-modified(force 時のみ上書き)
34
+ * - recorded が無い(旧バージョン導入等) → user-modified 扱いで保護
35
+ */
36
+ function syncTree(srcDir, destDir, recorded, options = {}) {
37
+ const { force = false, dryRun = false } = options;
38
+ const plan = [];
39
+ const hashes = {};
40
+ for (const relPath of listFiles(srcDir).sort()) {
41
+ const srcPath = path_1.default.join(srcDir, relPath);
42
+ const destPath = path_1.default.join(destDir, relPath);
43
+ const srcHash = hashFile(srcPath);
44
+ let status;
45
+ if (!fs_1.default.existsSync(destPath)) {
46
+ status = "add";
47
+ }
48
+ else {
49
+ const destHash = hashFile(destPath);
50
+ if (destHash === srcHash)
51
+ status = "unchanged";
52
+ else if (recorded[relPath] && destHash === recorded[relPath])
53
+ status = "update";
54
+ else
55
+ status = "user-modified";
56
+ }
57
+ plan.push({ relPath, status });
58
+ const willWrite = status === "add" || status === "update" || (status === "user-modified" && force);
59
+ if (willWrite && !dryRun) {
60
+ fs_1.default.mkdirSync(path_1.default.dirname(destPath), { recursive: true });
61
+ fs_1.default.copyFileSync(srcPath, destPath);
62
+ }
63
+ // 記録するハッシュ: 書き込んだ(または既に最新の)ファイルは srcHash、保護したファイルは従来の記録を維持
64
+ hashes[relPath] =
65
+ willWrite || status === "unchanged" ? srcHash : recorded[relPath] ?? hashFile(destPath);
66
+ }
67
+ return { plan, hashes };
68
+ }
69
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":";;;;;AAiBA,4BAEC;AAED,8BAQC;AAYD,4BAqCC;AA9ED,oDAA4B;AAC5B,4CAAoB;AACpB,gDAAwB;AAexB,SAAgB,QAAQ,CAAC,QAAgB;IACvC,OAAO,gBAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACrF,CAAC;AAED,SAAgB,SAAS,CAAC,GAAW,EAAE,IAAI,GAAG,GAAG;IAC/C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,YAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,WAAW,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;;YACvD,GAAG,CAAC,IAAI,CAAC,cAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,QAAQ,CACtB,MAAc,EACd,OAAe,EACf,QAAoB,EACpB,UAAiD,EAAE;IAEnD,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAClD,MAAM,IAAI,GAAoB,EAAE,CAAC;IACjC,MAAM,MAAM,GAAe,EAAE,CAAC;IAE9B,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAElC,IAAI,MAA+B,CAAC;QACpC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACpC,IAAI,QAAQ,KAAK,OAAO;gBAAE,MAAM,GAAG,WAAW,CAAC;iBAC1C,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,KAAK,QAAQ,CAAC,OAAO,CAAC;gBAAE,MAAM,GAAG,QAAQ,CAAC;;gBAC3E,MAAM,GAAG,eAAe,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAE/B,MAAM,SAAS,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,KAAK,eAAe,IAAI,KAAK,CAAC,CAAC;QACnG,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;YACzB,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrC,CAAC;QACD,2DAA2D;QAC3D,MAAM,CAAC,OAAO,CAAC;YACb,SAAS,IAAI,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { DoctorCheck } from "./types";
2
+ /**
3
+ * 診断ルール定義。チェックの追加はこの配列に1エントリ足すだけでよい。
4
+ */
5
+ export declare const checks: DoctorCheck[];
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checks = void 0;
4
+ /**
5
+ * 診断ルール定義。チェックの追加はこの配列に1エントリ足すだけでよい。
6
+ */
7
+ exports.checks = [
8
+ {
9
+ id: "readme",
10
+ label: "README",
11
+ category: "ドキュメント",
12
+ severity: "error",
13
+ hint: "README.md を作成し、プロジェクトの目的・セットアップ手順を書いてください",
14
+ check: (ctx) => ctx.existsAny(["README.md", "README"]),
15
+ },
16
+ {
17
+ id: "license",
18
+ label: "LICENSE",
19
+ category: "ドキュメント",
20
+ severity: "warn",
21
+ hint: "LICENSE ファイルを追加してください",
22
+ check: (ctx) => ctx.existsAny(["LICENSE", "LICENSE.md", "LICENSE.txt"]),
23
+ },
24
+ {
25
+ id: "gitignore",
26
+ label: ".gitignore",
27
+ category: "リポジトリ設定",
28
+ severity: "error",
29
+ hint: ".gitignore を作成してください(foundruu init で導入できます)",
30
+ check: (ctx) => ctx.exists(".gitignore"),
31
+ },
32
+ {
33
+ id: "env-example",
34
+ label: ".env.example",
35
+ category: "リポジトリ設定",
36
+ severity: "warn",
37
+ hint: ".env.example を作成し、必要な環境変数の一覧を共有してください",
38
+ check: (ctx) => ctx.existsAny([".env.example", ".env.sample"]),
39
+ },
40
+ {
41
+ id: "package-manifest",
42
+ label: "package.json / composer.json",
43
+ category: "リポジトリ設定",
44
+ severity: "warn",
45
+ hint: "package.json(Node.js)または composer.json(PHP)が見つかりません",
46
+ check: (ctx) => ctx.existsAny(["package.json", "composer.json"]),
47
+ },
48
+ {
49
+ id: "docker",
50
+ label: "Docker",
51
+ category: "実行環境",
52
+ severity: "warn",
53
+ hint: "Dockerfile または docker-compose.yml を追加すると環境を再現しやすくなります",
54
+ check: (ctx) => ctx.existsAny(["Dockerfile", "docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"]),
55
+ },
56
+ {
57
+ id: "github-actions",
58
+ label: "GitHub Actions",
59
+ category: "CI/CD",
60
+ severity: "warn",
61
+ hint: ".github/workflows/ に CI ワークフローを追加してください",
62
+ check: (ctx) => ctx.exists(".github/workflows"),
63
+ },
64
+ {
65
+ id: "ai-rules",
66
+ label: "AI Rules",
67
+ category: "AI開発",
68
+ severity: "error",
69
+ hint: "CLAUDE.md / CODEX.md / .ai/rules がありません(foundruu init で導入できます)",
70
+ check: (ctx) => ctx.existsAny(["CLAUDE.md", "CODEX.md", "AGENTS.md", ".ai/rules", "docs/ai"]),
71
+ },
72
+ {
73
+ id: "workflow",
74
+ label: "Workflow",
75
+ category: "AI開発",
76
+ severity: "error",
77
+ hint: ".ai/workflows がありません(foundruu workflow install で導入できます)",
78
+ check: (ctx) => ctx.exists(".ai/workflows"),
79
+ },
80
+ {
81
+ id: "prompt",
82
+ label: "Prompt",
83
+ category: "AI開発",
84
+ severity: "error",
85
+ hint: ".ai/prompts がありません(foundruu workflow install で導入できます)",
86
+ check: (ctx) => ctx.exists(".ai/prompts"),
87
+ },
88
+ {
89
+ id: "foundruu-config",
90
+ label: "FoundRuu 設定 (foundruu.json)",
91
+ category: "AI開発",
92
+ severity: "warn",
93
+ hint: "foundruu.json がありません(foundruu init / workflow install で生成されます)",
94
+ check: (ctx) => ctx.exists("foundruu.json"),
95
+ },
96
+ ];
97
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/doctor/checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * DevDoctor (Ruu5LP/DevDoctor) のスコアリングルールを移植した diff ベース品質診断。
3
+ * docs/ と .ai/sessions/ のドキュメントを分析し、AI開発プロセスの品質をスコア化する。
4
+ */
5
+ export type DocCategory = "requirements" | "design" | "test" | "aiInstructions";
6
+ export interface DeepRule {
7
+ category: DocCategory;
8
+ label: string;
9
+ pattern: RegExp;
10
+ improvement: string;
11
+ }
12
+ export interface CategoryScore {
13
+ category: DocCategory;
14
+ label: string;
15
+ docPath?: string;
16
+ score: number;
17
+ failed: {
18
+ label: string;
19
+ improvement: string;
20
+ }[];
21
+ }
22
+ export interface DeepReport {
23
+ since: string;
24
+ diff: {
25
+ files: number;
26
+ insertions: number;
27
+ deletions: number;
28
+ };
29
+ scores: CategoryScore[];
30
+ overall: number;
31
+ }
32
+ /** DevDoctor rules.ts 由来のキーワードルール */
33
+ export declare const deepRules: DeepRule[];
34
+ /** docs/ ・リポジトリ直下・最新の .ai/sessions/ からカテゴリ別ドキュメントを収集する */
35
+ export declare function scanDocs(cwd: string): Map<DocCategory, {
36
+ path: string;
37
+ content: string;
38
+ }>;
39
+ export declare function runDeepDoctor(cwd: string, since: string): DeepReport;