@tyyyho/treg 1.0.0 → 1.0.2

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 CHANGED
@@ -9,11 +9,11 @@ downloads](https://img.shields.io/npm/dm/%40tyyyho%2Ftreg)](https://www.npmjs.co
9
9
 
10
10
  ## Overview
11
11
 
12
- **treg** is a CLI tool that injects an **engineering immune system** into your project.
12
+ **Treg** is a CLI tool that injects an **engineering immune system** into your project.
13
13
 
14
14
  When humans and AI collaborate and iterate rapidly, repositories often
15
15
  accumulate inconsistent tooling, style drift, and fragile workflows.\
16
- `treg` helps maintain balance by establishing a clean and consistent
16
+ `Treg` helps maintain balance by establishing a clean and consistent
17
17
  development baseline.
18
18
 
19
19
  It focuses only on **infrastructure setup**, not application logic.
@@ -22,7 +22,7 @@ It focuses only on **infrastructure setup**, not application logic.
22
22
 
23
23
  ## Features
24
24
 
25
- `treg` can configure:
25
+ `Treg` can configure:
26
26
 
27
27
  - **TypeScript**
28
28
  - **ESLint**
@@ -105,7 +105,7 @@ Default formatter:
105
105
 
106
106
  ## AI Skills
107
107
 
108
- `treg` can update AI guidance files for development tools.
108
+ `Treg` can update AI guidance files for development tools.
109
109
 
110
110
  Tool File
111
111
 
@@ -125,7 +125,7 @@ Behavior:
125
125
 
126
126
  ## Philosophy
127
127
 
128
- `treg` is intentionally minimal.
128
+ `Treg` is intentionally minimal.
129
129
 
130
130
  It does not generate application architecture.\
131
131
  It focuses only on establishing the engineering infrastructure that
package/README.npm.md CHANGED
@@ -9,11 +9,11 @@ downloads](https://img.shields.io/npm/dm/%40tyyyho%2Ftreg)](https://www.npmjs.co
9
9
 
10
10
  ## Overview
11
11
 
12
- **treg** is a CLI tool that injects an **engineering immune system** into your project.
12
+ **Treg** is a CLI tool that injects an **engineering immune system** into your project.
13
13
 
14
14
  When humans and AI collaborate and iterate rapidly, repositories often
15
15
  accumulate inconsistent tooling, style drift, and fragile workflows.\
16
- `treg` helps maintain balance by establishing a clean and consistent
16
+ `Treg` helps maintain balance by establishing a clean and consistent
17
17
  development baseline.
18
18
 
19
19
  It focuses only on **infrastructure setup**, not application logic.
@@ -22,7 +22,7 @@ It focuses only on **infrastructure setup**, not application logic.
22
22
 
23
23
  ## Features
24
24
 
25
- `treg` can configure:
25
+ `Treg` can configure:
26
26
 
27
27
  - **TypeScript**
28
28
  - **ESLint**
@@ -105,7 +105,7 @@ Default formatter:
105
105
 
106
106
  ## AI Skills
107
107
 
108
- `treg` can update AI guidance files for development tools.
108
+ `Treg` can update AI guidance files for development tools.
109
109
 
110
110
  Tool File
111
111
 
@@ -125,7 +125,7 @@ Behavior:
125
125
 
126
126
  ## Philosophy
127
127
 
128
- `treg` is intentionally minimal.
128
+ `Treg` is intentionally minimal.
129
129
 
130
130
  It does not generate application architecture.\
131
131
  It focuses only on establishing the engineering infrastructure that
package/README.zh-hant.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://capsule-render.vercel.app/api?type=waving&color=0:0F172A,30:1D4ED8,70:7C3AED,100:22C55E&height=260&section=header&text=treg&fontSize=72&fontColor=ffffff&animation=fadeIn&fontAlignY=38&desc=Inject%20an%20immune%20system%20into%20your%20codebase&descSize=20&descAlignY=58" width="100%" />
3
+ <img src="https://capsule-render.vercel.app/api?type=waving&color=0:0F172A,30:1D4ED8,70:7C3AED,100:22C55E&height=260&section=header&text=Treg&fontSize=72&fontColor=ffffff&animation=fadeIn&fontAlignY=38&desc=Inject%20an%20immune%20system%20into%20your%20codebase&descSize=20&descAlignY=58" width="100%" />
4
4
 
5
5
  # @tyyyho/treg(繁體中文)
6
6
 
@@ -18,19 +18,19 @@
18
18
 
19
19
  ## 概覽
20
20
 
21
- **treg**
21
+ **Treg**
22
22
 
23
23
  它是一個為專案注入「免疫系統」的 CLI 工具。
24
24
  當開發者與 AI 高速協作時,程式碼庫很容易出現規範不一致、規則重複、流程脆弱等問題。
25
- `treg` 的角色就像調節型 T 細胞:協助恢復平衡、抑制可避免的混亂,讓專案維持 **乾淨、可維護、可擴展**。
25
+ `Treg` 的角色就像調節型 T 細胞:協助恢復平衡、抑制可避免的混亂,讓專案維持 **乾淨、可維護、可擴展**。
26
26
 
27
- `treg` 不產生產品商業邏輯,而是專注於建立可長期保持穩定的工程基線。
27
+ `Treg` 不產生產品商業邏輯,而是專注於建立可長期保持穩定的工程基線。
28
28
 
29
29
  > **先規範開發流程,才不會被流程反過來牽制。**
30
30
 
31
31
  ---
32
32
 
33
- ## 為什麼需要 treg
33
+ ## 為什麼需要 Treg
34
34
 
35
35
  在 AI 輔助開發時代,專案速度可以很快。
36
36
  但速度若缺少約束,通常會留下看不見的技術債:
@@ -41,13 +41,13 @@
41
41
  - 測試覆蓋缺漏
42
42
  - AI 使用規則不清
43
43
 
44
- `treg` 透過一次初始化流程,把一致的工程基線套用到既有 repository。
44
+ `Treg` 透過一次初始化流程,把一致的工程基線套用到既有 repository。
45
45
 
46
46
  ---
47
47
 
48
- ## treg 會建立什麼
48
+ ## Treg 會建立什麼
49
49
 
50
- `treg` 可配置:
50
+ `Treg` 可配置:
51
51
 
52
52
  - **TypeScript**
53
53
  - **Linting**(ESLint)
@@ -94,7 +94,7 @@ npx @tyyyho/treg add --features lint,format
94
94
 
95
95
  ## init 互動流程
96
96
 
97
- 執行 `init` 時,`treg` 會依序詢問:
97
+ 執行 `init` 時,`Treg` 會依序詢問:
98
98
 
99
99
  1. **Package manager**
100
100
  `pnpm | npm | yarn | bun`
@@ -205,7 +205,7 @@ nuxt -> next -> react -> vue -> svelte -> node
205
205
 
206
206
  ## AI Skills 行為
207
207
 
208
- `treg` 可更新所選 AI 工具的說明文件:
208
+ `Treg` 可更新所選 AI 工具的說明文件:
209
209
 
210
210
  | Tool | File |
211
211
  | ------ | ----------- |
@@ -224,7 +224,7 @@ nuxt -> next -> react -> vue -> svelte -> node
224
224
 
225
225
  ## 核心理念
226
226
 
227
- `treg` 的設計刻意保持單一職責。
227
+ `Treg` 的設計刻意保持單一職責。
228
228
 
229
229
  它 **不** 是完整專案產生器。
230
230
  它 **不** 取代團隊判斷。
@@ -19,6 +19,7 @@ const AI_TOOL_CHOICES = [
19
19
  { value: "claude", label: "Claude" },
20
20
  { value: "codex", label: "Codex" },
21
21
  { value: "gemini", label: "Gemini" },
22
+ { value: "skip", label: "skip (disable AI skill guidance)" },
22
23
  ];
23
24
  const FEATURE_CHOICES = [
24
25
  { value: "lint", label: "lint" },
@@ -67,13 +68,25 @@ async function promptSingleChoice(message, choices, defaultValue) {
67
68
  const result = await prompts.select(defaultChoice ? { ...options, initialValue: defaultChoice } : options);
68
69
  return unwrapPromptResult(result, prompts).value;
69
70
  }
70
- async function promptMultiChoice(message, choices, defaultValues) {
71
+ function resolveAiToolSelection(selected) {
72
+ if (selected.includes("skip")) {
73
+ return {
74
+ skills: false,
75
+ aiTools: [],
76
+ };
77
+ }
78
+ return {
79
+ skills: selected.length > 0,
80
+ aiTools: selected,
81
+ };
82
+ }
83
+ async function promptMultiChoice(message, choices, defaultValues, required = false) {
71
84
  const prompts = await getPrompts();
72
85
  const result = await prompts.multiselect({
73
86
  message,
74
87
  options: mapChoiceOptions(choices),
75
88
  initialValues: choices.filter(choice => defaultValues.includes(choice.value)),
76
- required: false,
89
+ required,
77
90
  });
78
91
  return unwrapPromptResult(result, prompts).map(choice => choice.value);
79
92
  }
@@ -124,9 +137,12 @@ export async function collectInitPrompts(defaults) {
124
137
  let aiTools = [];
125
138
  let skills = featureSelection.skills;
126
139
  if (skills) {
127
- aiTools = await promptMultiChoice("5) AI tools", AI_TOOL_CHOICES, []);
128
- if (aiTools.length === 0) {
129
- skills = false;
140
+ const aiToolAnswers = await promptMultiChoice("5) AI tools (Space to select, A to toggle all)", AI_TOOL_CHOICES, [], true);
141
+ const aiToolSelection = resolveAiToolSelection(aiToolAnswers);
142
+ skills = aiToolSelection.skills;
143
+ aiTools = aiToolSelection.aiTools;
144
+ if (!skills) {
145
+ console.log("AI skill guidance disabled by selection: skip");
130
146
  }
131
147
  }
132
148
  else {
@@ -143,4 +159,5 @@ export async function collectInitPrompts(defaults) {
143
159
  }
144
160
  export const __testables__ = {
145
161
  toFeatureSelection,
162
+ resolveAiToolSelection,
146
163
  };
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { promises as fs } from "node:fs";
3
3
  import path from "node:path";
4
- const SKILL_SECTION_HEADING = "## treg AI Skills";
4
+ const SKILL_SECTION_HEADING = "## Treg AI Skills";
5
5
  const SKILLS_BASE_DIR = "skills";
6
6
  const AI_TOOL_DOCS = {
7
7
  claude: "CLAUDE.md",
@@ -10,7 +10,7 @@ const AI_TOOL_DOCS = {
10
10
  };
11
11
  const FEATURE_SKILLS = {
12
12
  format: {
13
- name: "treg/format",
13
+ name: "Treg/format",
14
14
  description: "Run and verify formatting rules.",
15
15
  when: "Before committing or after broad edits, normalize formatting across the codebase.",
16
16
  checklist: [
@@ -20,7 +20,7 @@ const FEATURE_SKILLS = {
20
20
  ],
21
21
  },
22
22
  husky: {
23
- name: "treg/husky",
23
+ name: "Treg/husky",
24
24
  description: "Verify and maintain git hook automation.",
25
25
  when: "When pre-commit and pre-push checks must stay enforced and consistent.",
26
26
  checklist: [
@@ -30,7 +30,7 @@ const FEATURE_SKILLS = {
30
30
  ],
31
31
  },
32
32
  lint: {
33
- name: "treg/lint",
33
+ name: "Treg/lint",
34
34
  description: "Run and validate lint rules.",
35
35
  when: "After adding rules or changing tooling, verify lint consistency.",
36
36
  checklist: [
@@ -40,7 +40,7 @@ const FEATURE_SKILLS = {
40
40
  ],
41
41
  },
42
42
  test: {
43
- name: "treg/test",
43
+ name: "Treg/test",
44
44
  description: "Validate test runner setup and execution.",
45
45
  when: "When test rules are added or test configuration changes.",
46
46
  checklist: [
@@ -50,7 +50,7 @@ const FEATURE_SKILLS = {
50
50
  ],
51
51
  },
52
52
  typescript: {
53
- name: "treg/typescript",
53
+ name: "Treg/typescript",
54
54
  description: "Validate TypeScript strictness and config.",
55
55
  when: "When tsconfig or strict typing rules are changed.",
56
56
  checklist: [
@@ -1,5 +1,6 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
+ import { readFileSync } from "node:fs";
3
4
  import path from "node:path";
4
5
  export function detectPackageManager(projectDir) {
5
6
  if (existsSync(path.join(projectDir, "pnpm-lock.yaml"))) {
@@ -63,8 +64,62 @@ export function installPackages(pm, projectDir, packages, isDev, dryRun = false)
63
64
  command = `yarn add ${isDev ? "-D " : ""}${list}`;
64
65
  }
65
66
  else {
66
- command = `npm install ${isDev ? "-D " : ""}${list}`;
67
+ const useLegacyPeerDeps = shouldUseNpmLegacyPeerDeps(projectDir);
68
+ if (useLegacyPeerDeps) {
69
+ console.log(`${dryRun ? "[dry-run] " : ""}Detected react-scripts with TypeScript >= 5; using --legacy-peer-deps for npm compatibility`);
70
+ }
71
+ command = `npm install ${isDev ? "-D " : ""}${list}${useLegacyPeerDeps ? " --legacy-peer-deps" : ""}`;
67
72
  }
68
73
  console.log(`${dryRun ? "[dry-run] " : ""}Installing ${isDev ? "dev " : ""}dependencies: ${packages.join(", ")}`);
69
74
  runCommand(command, projectDir, dryRun);
70
75
  }
76
+ function shouldUseNpmLegacyPeerDeps(projectDir) {
77
+ const packageJson = readPackageJson(projectDir);
78
+ if (!packageJson)
79
+ return false;
80
+ const reactScriptsVersion = getDeclaredVersion(packageJson, "react-scripts");
81
+ if (!reactScriptsVersion)
82
+ return false;
83
+ const typescriptVersion = getDeclaredVersion(packageJson, "typescript");
84
+ if (!typescriptVersion)
85
+ return false;
86
+ const major = extractMajorVersion(typescriptVersion);
87
+ return major !== null && major >= 5;
88
+ }
89
+ function readPackageJson(projectDir) {
90
+ const packageJsonPath = path.join(projectDir, "package.json");
91
+ if (!existsSync(packageJsonPath))
92
+ return null;
93
+ try {
94
+ return JSON.parse(readFileSync(packageJsonPath, "utf8"));
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ function getDeclaredVersion(packageJson, packageName) {
101
+ const fromDependencies = packageJson.dependencies?.[packageName];
102
+ if (fromDependencies)
103
+ return fromDependencies;
104
+ const fromDevDependencies = packageJson.devDependencies?.[packageName];
105
+ if (fromDevDependencies)
106
+ return fromDevDependencies;
107
+ const fromPeerDependencies = packageJson.peerDependencies?.[packageName];
108
+ if (fromPeerDependencies)
109
+ return fromPeerDependencies;
110
+ const fromOptionalDependencies = packageJson.optionalDependencies?.[packageName];
111
+ if (fromOptionalDependencies)
112
+ return fromOptionalDependencies;
113
+ return null;
114
+ }
115
+ function extractMajorVersion(rawVersion) {
116
+ const match = rawVersion.match(/\d+/);
117
+ if (!match)
118
+ return null;
119
+ const major = Number.parseInt(match[0], 10);
120
+ return Number.isNaN(major) ? null : major;
121
+ }
122
+ export const __testables__ = {
123
+ shouldUseNpmLegacyPeerDeps,
124
+ extractMajorVersion,
125
+ };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@tyyyho/treg",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Treg is a CLI tool that injects an engineering immune system into existing projects.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/TyyyHo/treg"
8
+ "url": "https://github.com/TyyyHo/Treg"
9
9
  },
10
10
  "bin": {
11
11
  "treg": "dist/init-project.js"