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.
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/assets/templates/ai/_common/company/coding-standard.md +35 -0
- package/assets/templates/ai/_common/company/git-workflow.md +40 -0
- package/assets/templates/ai/_common/company/review-policy.md +30 -0
- package/assets/templates/ai/_common/company/security.md +25 -0
- package/assets/templates/ai/_common/project/architecture.md.hbs +29 -0
- package/assets/templates/ai/_common/project/conventions.md +24 -0
- package/assets/templates/ai/_common/project/overview.md.hbs +37 -0
- package/assets/templates/ai/_common/project/testing.md +32 -0
- package/assets/templates/ai/claude/CLAUDE.md.hbs +65 -0
- package/assets/templates/ai/codex/CODEX.md.hbs +60 -0
- package/assets/templates/base/.env.example +4 -0
- package/assets/templates/base/README.md.hbs +73 -0
- package/assets/templates/features/discord/.env.example.patch +3 -0
- package/assets/templates/features/discord/package.json.patch +5 -0
- package/assets/templates/features/docker/Dockerfile.hbs +38 -0
- package/assets/templates/features/docker/docker-compose.yml.hbs +11 -0
- package/assets/templates/features/eslint/eslint.config.js +14 -0
- package/assets/templates/features/eslint/package.json.patch +11 -0
- package/assets/templates/features/github-actions/.github/workflows/ci.yml.hbs +51 -0
- package/assets/templates/features/lark/.env.example.patch +3 -0
- package/assets/templates/features/lark/package.json.patch +5 -0
- package/assets/templates/features/line-bot/.env.example.patch +2 -0
- package/assets/templates/features/line-bot/package.json.patch +5 -0
- package/assets/templates/features/prettier/.prettierignore +3 -0
- package/assets/templates/features/prettier/.prettierrc +7 -0
- package/assets/templates/features/prettier/package.json.patch +9 -0
- package/assets/templates/features/react/index.html.hbs +12 -0
- package/assets/templates/features/react/package.json.patch +17 -0
- package/assets/templates/features/react/src/web/App.tsx.hbs +8 -0
- package/assets/templates/features/react/src/web/main.tsx +9 -0
- package/assets/templates/features/react/vite.config.ts +6 -0
- package/assets/templates/features/react-laravel/package.json.patch +19 -0
- package/assets/templates/features/react-laravel/resources/js/app.jsx.hbs +17 -0
- package/assets/templates/features/react-laravel/vite.config.js +13 -0
- package/assets/templates/features/vitest/package.json.patch +10 -0
- package/assets/templates/features/vitest/tests/index.test.ts.hbs +7 -0
- package/assets/templates/features/vitest/vitest.config.ts +11 -0
- package/assets/templates/languages/laravel/.env.example.patch +12 -0
- package/assets/templates/languages/laravel/composer.json.hbs +41 -0
- package/assets/templates/languages/laravel/docs/SETUP.md.hbs +24 -0
- package/assets/templates/languages/typescript/package.json.patch +20 -0
- package/assets/templates/languages/typescript/src/index.ts.hbs +1 -0
- package/assets/templates/languages/typescript/tsconfig.json +17 -0
- package/assets/workflow/.ai/prompts/session-workflow.md +72 -0
- package/assets/workflow/.ai/templates/session/design.md +21 -0
- package/assets/workflow/.ai/templates/session/questions.md +34 -0
- package/assets/workflow/.ai/templates/session/requirements.md +25 -0
- package/assets/workflow/.ai/templates/session/summary.md +21 -0
- package/assets/workflow/.ai/templates/session/tasks.md +13 -0
- package/assets/workflow/.ai/templates/session/test.md +15 -0
- package/assets/workflow/.ai/workflows/bugfix.md +19 -0
- package/assets/workflow/.ai/workflows/development.md +27 -0
- package/assets/workflow/.ai/workflows/feature.md +20 -0
- package/assets/workflow/.ai/workflows/review.md +19 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +89 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.js +64 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +94 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/session.d.ts +8 -0
- package/dist/commands/session.js +96 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/update.d.ts +13 -0
- package/dist/commands/update.js +64 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/workflow.d.ts +7 -0
- package/dist/commands/workflow.js +64 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/core/assets.d.ts +8 -0
- package/dist/core/assets.js +29 -0
- package/dist/core/assets.js.map +1 -0
- package/dist/core/config.d.ts +17 -0
- package/dist/core/config.js +31 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/copier.d.ts +25 -0
- package/dist/core/copier.js +103 -0
- package/dist/core/copier.js.map +1 -0
- package/dist/core/fetcher.d.ts +10 -0
- package/dist/core/fetcher.js +56 -0
- package/dist/core/fetcher.js.map +1 -0
- package/dist/core/logger.d.ts +7 -0
- package/dist/core/logger.js +15 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/sync.d.ts +26 -0
- package/dist/core/sync.js +69 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/doctor/checks.d.ts +5 -0
- package/dist/doctor/checks.js +97 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/deep.d.ts +39 -0
- package/dist/doctor/deep.js +144 -0
- package/dist/doctor/deep.js.map +1 -0
- package/dist/doctor/rc.d.ts +13 -0
- package/dist/doctor/rc.js +31 -0
- package/dist/doctor/rc.js.map +1 -0
- package/dist/doctor/runner.d.ts +3 -0
- package/dist/doctor/runner.js +39 -0
- package/dist/doctor/runner.js.map +1 -0
- package/dist/doctor/types.d.ts +32 -0
- package/dist/doctor/types.js +3 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/registry/templates.d.ts +18 -0
- package/dist/registry/templates.js +45 -0
- package/dist/registry/templates.js.map +1 -0
- 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":"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"}
|
|
@@ -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,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":"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"}
|
|
@@ -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;
|