prizmkit 1.0.14 → 1.0.15

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.0.14",
3
- "bundledAt": "2026-03-15T11:21:10.029Z",
4
- "bundledFrom": "94ac498"
2
+ "frameworkVersion": "1.0.15",
3
+ "bundledAt": "2026-03-15T12:24:22.555Z",
4
+ "bundledFrom": "8b809a8"
5
5
  }
@@ -24,9 +24,27 @@ SCRIPTS_DIR="$SCRIPT_DIR/scripts"
24
24
  SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
25
25
  HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
26
26
 
27
- # AI CLI detection
27
+ # AI CLI detection: AI_CLI env > .prizmkit/config.json > CODEBUDDY_CLI > auto-detect
28
28
  if [[ -n "${AI_CLI:-}" ]]; then
29
29
  CLI_CMD="$AI_CLI"
30
+ elif [[ -f ".prizmkit/config.json" ]]; then
31
+ _config_cli=$(python3 -c "
32
+ import json, sys
33
+ try:
34
+ with open('.prizmkit/config.json') as f:
35
+ d = json.load(f)
36
+ v = d.get('ai_cli', '')
37
+ if v: print(v)
38
+ except: pass
39
+ " 2>/dev/null || true)
40
+ CLI_CMD="${_config_cli:-}"
41
+ if [[ -z "$CLI_CMD" ]]; then
42
+ if [[ -n "${CODEBUDDY_CLI:-}" ]]; then CLI_CMD="$CODEBUDDY_CLI"
43
+ elif command -v cbc &>/dev/null; then CLI_CMD="cbc"
44
+ elif command -v claude &>/dev/null; then CLI_CMD="claude"
45
+ else echo "ERROR: No AI CLI found. Set AI_CLI or configure .prizmkit/config.json" >&2; exit 1
46
+ fi
47
+ fi
30
48
  elif [[ -n "${CODEBUDDY_CLI:-}" ]]; then
31
49
  CLI_CMD="$CODEBUDDY_CLI"
32
50
  elif command -v cbc &>/dev/null; then
@@ -34,7 +52,7 @@ elif command -v cbc &>/dev/null; then
34
52
  elif command -v claude &>/dev/null; then
35
53
  CLI_CMD="claude"
36
54
  else
37
- echo "ERROR: No AI CLI found. Install CodeBuddy (cbc) or Claude Code (claude)." >&2
55
+ echo "ERROR: No AI CLI found. Install CodeBuddy (cbc) or Claude Code (claude), or set AI_CLI." >&2
38
56
  exit 1
39
57
  fi
40
58
 
@@ -24,9 +24,27 @@ SCRIPTS_DIR="$SCRIPT_DIR/scripts"
24
24
  SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
25
25
  HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
26
26
 
27
- # AI CLI detection: AI_CLI > CODEBUDDY_CLI > auto-detect
27
+ # AI CLI detection: AI_CLI env > .prizmkit/config.json > CODEBUDDY_CLI > auto-detect
28
28
  if [[ -n "${AI_CLI:-}" ]]; then
29
29
  CLI_CMD="$AI_CLI"
30
+ elif [[ -f ".prizmkit/config.json" ]]; then
31
+ _config_cli=$(python3 -c "
32
+ import json, sys
33
+ try:
34
+ with open('.prizmkit/config.json') as f:
35
+ d = json.load(f)
36
+ v = d.get('ai_cli', '')
37
+ if v: print(v)
38
+ except: pass
39
+ " 2>/dev/null || true)
40
+ CLI_CMD="${_config_cli:-}"
41
+ if [[ -z "$CLI_CMD" ]]; then
42
+ if [[ -n "${CODEBUDDY_CLI:-}" ]]; then CLI_CMD="$CODEBUDDY_CLI"
43
+ elif command -v cbc &>/dev/null; then CLI_CMD="cbc"
44
+ elif command -v claude &>/dev/null; then CLI_CMD="claude"
45
+ else echo "ERROR: No AI CLI found. Set AI_CLI or configure .prizmkit/config.json" >&2; exit 1
46
+ fi
47
+ fi
30
48
  elif [[ -n "${CODEBUDDY_CLI:-}" ]]; then
31
49
  CLI_CMD="$CODEBUDDY_CLI"
32
50
  elif command -v cbc &>/dev/null; then
@@ -34,7 +52,7 @@ elif command -v cbc &>/dev/null; then
34
52
  elif command -v claude &>/dev/null; then
35
53
  CLI_CMD="claude"
36
54
  else
37
- echo "ERROR: No AI CLI found. Install CodeBuddy (cbc) or Claude Code (claude)." >&2
55
+ echo "ERROR: No AI CLI found. Install CodeBuddy (cbc) or Claude Code (claude), or set AI_CLI." >&2
38
56
  exit 1
39
57
  fi
40
58
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "PrizmKit documentation rules"
2
+ description: "PrizmKit .prizm-docs maintenance rules — when/how to update structured AI documentation"
3
3
  globs:
4
4
  - "**/*.ts"
5
5
  - "**/*.tsx"
@@ -11,9 +11,70 @@ globs:
11
11
  - "**/*.java"
12
12
  ---
13
13
 
14
- When modifying source files in this project:
15
- 1. Check if `.prizm-docs/root.prizm` exists
16
- 2. If it does, read it before making changes to understand project structure
17
- 3. After making changes, update affected `.prizm-docs/` files
18
- 4. Follow the Prizm doc format (KEY: value, not prose)
19
- 5. Size limits: L0 = 4KB, L1 = 3KB, L2 = 5KB
14
+ WHEN TO UPDATE .prizm-docs/:
15
+ - Feature development (new interface, new module, new behavior) → UPDATE .prizm-docs/
16
+ - Bug fix (fixing broken logic, no structural change) SKIP, do NOT update
17
+ - Rationale: bugs are incomplete features. Recording bug details causes doc bloat with no AI value.
18
+ - Before modifying any source file, read `.prizm-docs/root.prizm` if it exists to understand project structure.
19
+
20
+ FORMAT RULES (enforced by pre-commit hook — violations block commit):
21
+ - ALL CAPS section headers: MODULE:, FILES:, RESPONSIBILITY:, UPDATED:, etc.
22
+ - KEY: value pairs and dash-prefixed lists only
23
+ - PROHIBITED: prose paragraphs, markdown headers (##/###), code blocks (```), emoji, ASCII art
24
+ - This format is designed for AI token efficiency, not human readability. Do not add human-friendly formatting.
25
+
26
+ SIZE LIMITS (hard — pre-commit hook blocks commits exceeding these):
27
+ - L0 root.prizm: 4KB max
28
+ - L1 module.prizm: 3KB max
29
+ - L2 detail.prizm: 5KB max
30
+
31
+ SIZE OVERFLOW HANDLING:
32
+ - L0 approaching 4KB: consolidate MODULE_INDEX, keep only top-5 RULES, remove PATTERNS detail
33
+ - L1 approaching 3KB: move implementation details to L2, keep only INTERFACES signatures
34
+ - L2 approaching 5KB: archive CHANGELOG entries older than 90 days to changelog-archive.prizm
35
+ - NEVER exceed hard limits — pre-commit hook will block the commit
36
+
37
+ REQUIRED FIELDS PER LEVEL:
38
+
39
+ L0 root.prizm:
40
+ - PRIZM_VERSION
41
+ - PROJECT
42
+ - LANG
43
+ - MODULE_INDEX (with -> pointers to L1 files)
44
+ - RULES (top-level project rules)
45
+ - UPDATED
46
+
47
+ L1 module.prizm:
48
+ - MODULE
49
+ - FILES
50
+ - RESPONSIBILITY
51
+ - INTERFACES (public/exported only)
52
+ - DEPENDENCIES
53
+ - UPDATED
54
+
55
+ L2 detail.prizm:
56
+ - MODULE
57
+ - FILES
58
+ - KEY_FILES
59
+ - DEPENDENCIES
60
+ - TRAPS
61
+ - CHANGELOG
62
+ - UPDATED
63
+
64
+ L2 GENERATION TEMPLATE (use when AI first touches a sub-module with no L2 doc):
65
+
66
+ MODULE: <path>
67
+ FILES: <comma-separated file list>
68
+ RESPONSIBILITY: <one-line>
69
+ KEY_FILES:
70
+ - <file>: <role, line count, complexity note>
71
+ DEPENDENCIES:
72
+ - uses: <lib>: <why>
73
+ - imports: <module>: <what>
74
+ TRAPS:
75
+ - <gotcha, race condition, or non-obvious coupling>
76
+ CHANGELOG:
77
+ - <YYYY-MM-DD> | add: initial L2 documentation
78
+ UPDATED: <YYYY-MM-DD>
79
+
80
+ TRAPS is critical — always record gotchas, race conditions, non-obvious behavior, and surprising coupling between modules.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.14",
2
+ "version": "1.0.15",
3
3
  "skills": {
4
4
  "prizm-kit": {
5
5
  "description": "Full-lifecycle dev toolkit. Covers spec-driven development, Prizm context docs, code quality, debugging, deployment, and knowledge management.",
@@ -293,22 +293,45 @@
293
293
  "frontend": {
294
294
  "label": "前端项目 (React/Vue/Angular)",
295
295
  "base": "core",
296
- "include": ["prizmkit-tool-perf-profiler", "prizmkit-tool-security-audit", "prizmkit-tool-ci-cd-generator"]
296
+ "include": [
297
+ "prizmkit-tool-perf-profiler",
298
+ "prizmkit-tool-security-audit",
299
+ "prizmkit-tool-ci-cd-generator"
300
+ ]
297
301
  },
298
302
  "backend": {
299
303
  "label": "后端服务 (API/微服务)",
300
304
  "base": "core",
301
- "include": ["prizmkit-tool-db-migration", "prizmkit-tool-api-doc-generator", "prizmkit-tool-monitoring-setup", "prizmkit-tool-deployment-strategy", "prizmkit-tool-security-audit", "prizmkit-tool-error-triage", "prizmkit-tool-log-analyzer"]
305
+ "include": [
306
+ "prizmkit-tool-db-migration",
307
+ "prizmkit-tool-api-doc-generator",
308
+ "prizmkit-tool-monitoring-setup",
309
+ "prizmkit-tool-deployment-strategy",
310
+ "prizmkit-tool-security-audit",
311
+ "prizmkit-tool-error-triage",
312
+ "prizmkit-tool-log-analyzer"
313
+ ]
302
314
  },
303
315
  "fullstack": {
304
316
  "label": "全栈项目",
305
317
  "base": "core",
306
- "include": ["prizmkit-tool-db-migration", "prizmkit-tool-api-doc-generator", "prizmkit-tool-ci-cd-generator", "prizmkit-tool-security-audit", "prizmkit-tool-deployment-strategy", "prizmkit-tool-perf-profiler"]
318
+ "include": [
319
+ "prizmkit-tool-db-migration",
320
+ "prizmkit-tool-api-doc-generator",
321
+ "prizmkit-tool-ci-cd-generator",
322
+ "prizmkit-tool-security-audit",
323
+ "prizmkit-tool-deployment-strategy",
324
+ "prizmkit-tool-perf-profiler"
325
+ ]
307
326
  },
308
327
  "library": {
309
328
  "label": "工具库/SDK",
310
329
  "base": "core",
311
- "include": ["prizmkit-tool-api-doc-generator", "prizmkit-tool-ci-cd-generator", "prizmkit-tool-dependency-health"]
330
+ "include": [
331
+ "prizmkit-tool-api-doc-generator",
332
+ "prizmkit-tool-ci-cd-generator",
333
+ "prizmkit-tool-dependency-health"
334
+ ]
312
335
  }
313
336
  },
314
337
  "external_skills": {
@@ -325,21 +348,30 @@
325
348
  "description": "Intelligent file and code search skill",
326
349
  "source": "https://skills.sh/skills/find-skill/SKILL.md",
327
350
  "registry": "skills.sh",
328
- "tags": ["search", "utility"]
351
+ "tags": [
352
+ "search",
353
+ "utility"
354
+ ]
329
355
  },
330
356
  {
331
357
  "name": "uiuxpromax",
332
358
  "description": "UI/UX design review and suggestions",
333
359
  "source": "https://skills.sh/skills/uiuxpromax/SKILL.md",
334
360
  "registry": "skills.sh",
335
- "tags": ["design", "frontend"]
361
+ "tags": [
362
+ "design",
363
+ "frontend"
364
+ ]
336
365
  },
337
366
  {
338
367
  "name": "thinkthought",
339
368
  "description": "Structured reasoning and problem decomposition",
340
369
  "source": "https://skills.sh/skills/thinkthought/SKILL.md",
341
370
  "registry": "skills.sh",
342
- "tags": ["reasoning", "universal"]
371
+ "tags": [
372
+ "reasoning",
373
+ "universal"
374
+ ]
343
375
  }
344
376
  ]
345
377
  }
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "echo 'PRIZMKIT_DOC_UPDATE_REQUIRED: Before committing, you MUST update .prizm-docs/ per Prizm auto-update protocol. Steps: 1) Run git diff --cached --name-status. 2) Map changed files to modules via root.prizm MODULE_INDEX. 3) Read and update affected .prizm files (only changed sections). 4) Append to changelog.prizm. 5) Stage .prizm files with git add .prizm-docs/. 6) Then proceed with commit using prizmkit-committer workflow. RULES: Never rewrite entire .prizm files. Never add prose. Only update affected sections.'"
9
+ "command": "SRC=$(git diff --cached --name-only 2>/dev/null | grep -cE '\\.(ts|tsx|js|jsx|py|go|rs|java)$'); if [ \"$SRC\" -gt 0 ]; then PRIZM=$(git diff --cached --name-only 2>/dev/null | grep -c '^\\.prizm-docs/'); if [ \"$PRIZM\" -gt 0 ]; then echo \"PRIZMKIT_DOC_STATUS: $SRC source file(s) staged | .prizm-docs/ updated ($PRIZM file(s))\"; else echo \"PRIZMKIT_DOC_STATUS: $SRC source file(s) staged | .prizm-docs/ NOT UPDATED update if this is a feature change\"; fi; fi"
10
10
  }
11
11
  ]
12
12
  }
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "echo 'PRIZMKIT_DOC_UPDATE_REQUIRED: Before committing, you MUST update .prizm-docs/ per Prizm auto-update protocol. Steps: 1) Run git diff --cached --name-status. 2) Map changed files to modules via root.prizm MODULE_INDEX. 3) Read and update affected .prizm files (only changed sections). 4) Append to changelog.prizm. 5) Stage .prizm files with git add .prizm-docs/. 6) Then proceed with commit using prizmkit-committer workflow. RULES: Never rewrite entire .prizm files. Never add prose. Only update affected sections.'"
9
+ "command": "SRC=$(git diff --cached --name-only 2>/dev/null | grep -cE '\\.(ts|tsx|js|jsx|py|go|rs|java)$'); if [ \"$SRC\" -gt 0 ]; then PRIZM=$(git diff --cached --name-only 2>/dev/null | grep -c '^\\.prizm-docs/'); if [ \"$PRIZM\" -gt 0 ]; then echo \"PRIZMKIT_DOC_STATUS: $SRC source file(s) staged | .prizm-docs/ updated ($PRIZM file(s))\"; else echo \"PRIZMKIT_DOC_STATUS: $SRC source file(s) staged | .prizm-docs/ NOT UPDATED update if this is a feature change\"; fi; fi"
10
10
  }
11
11
  ]
12
12
  }
@@ -0,0 +1,58 @@
1
+ #!/bin/sh
2
+ # prizm-pre-commit.sh — git pre-commit hook for .prizm-docs validation
3
+
4
+ PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0
5
+
6
+ # Only run in prizm projects
7
+ [ -f "$PROJECT_ROOT/.prizm-docs/root.prizm" ] || exit 0
8
+
9
+ VALIDATE_SCRIPT="$PROJECT_ROOT/dev-pipeline/scripts/validate-prizm-docs.sh"
10
+
11
+ if [ -f "$VALIDATE_SCRIPT" ]; then
12
+ sh "$VALIDATE_SCRIPT" --staged
13
+ exit $?
14
+ fi
15
+
16
+ # Inline fallback: core checks for staged .prizm files
17
+ FILES=$(git diff --cached --name-only 2>/dev/null | grep '\.prizm$')
18
+ [ -z "$FILES" ] && exit 0
19
+
20
+ ERRORS=0
21
+ for FILE in $FILES; do
22
+ [ -f "$FILE" ] || continue
23
+
24
+ if grep -qE '^#{1,6} ' "$FILE"; then
25
+ echo "ERROR: $FILE contains markdown headers (##). Use KEY: value format." >&2
26
+ ERRORS=$((ERRORS + 1))
27
+ fi
28
+
29
+ if grep -q '^```' "$FILE"; then
30
+ echo "ERROR: $FILE contains code blocks. Use file_path:line_number reference." >&2
31
+ ERRORS=$((ERRORS + 1))
32
+ fi
33
+
34
+ SIZE=$(wc -c < "$FILE" | tr -d ' ')
35
+ case "$FILE" in
36
+ *root.prizm) LIMIT=4096 ;;
37
+ *)
38
+ DIR=$(dirname "$FILE")
39
+ if [ "$DIR" = ".prizm-docs" ]; then
40
+ LIMIT=3072
41
+ else
42
+ LIMIT=5120
43
+ fi
44
+ ;;
45
+ esac
46
+
47
+ if [ "$SIZE" -gt "$LIMIT" ]; then
48
+ echo "ERROR: $FILE exceeds size limit (${SIZE}B > ${LIMIT}B)." >&2
49
+ ERRORS=$((ERRORS + 1))
50
+ fi
51
+ done
52
+
53
+ if [ "$ERRORS" -gt 0 ]; then
54
+ echo "PrizmKit: $ERRORS format error(s) in .prizm files. Fix before committing." >&2
55
+ exit 1
56
+ fi
57
+
58
+ exit 0
@@ -0,0 +1,84 @@
1
+ #!/bin/sh
2
+ # validate-prizm-docs.sh — validate .prizm file format and size limits
3
+ # Usage: validate-prizm-docs.sh [--all | --staged]
4
+
5
+ MODE="${1:---staged}"
6
+ ERRORS=0
7
+
8
+ # Not a prizm project — exit silently
9
+ [ -f ".prizm-docs/root.prizm" ] || exit 0
10
+
11
+ # Collect files to check
12
+ if [ "$MODE" = "--all" ]; then
13
+ FILES=$(find .prizm-docs -name '*.prizm' 2>/dev/null)
14
+ elif [ "$MODE" = "--staged" ]; then
15
+ FILES=$(git diff --cached --name-only 2>/dev/null | grep '\.prizm$')
16
+ else
17
+ echo "Usage: validate-prizm-docs.sh [--all | --staged]" >&2
18
+ exit 1
19
+ fi
20
+
21
+ # Nothing to check — exit silently
22
+ [ -z "$FILES" ] && exit 0
23
+
24
+ for FILE in $FILES; do
25
+ [ -f "$FILE" ] || continue
26
+
27
+ # Check markdown headers
28
+ if grep -qE '^#{1,6} ' "$FILE"; then
29
+ echo "ERROR: $FILE contains markdown headers (##). Use KEY: value format." >&2
30
+ ERRORS=$((ERRORS + 1))
31
+ fi
32
+
33
+ # Check code blocks
34
+ if grep -q '^```' "$FILE"; then
35
+ echo "ERROR: $FILE contains code blocks. Use file_path:line_number reference." >&2
36
+ ERRORS=$((ERRORS + 1))
37
+ fi
38
+
39
+ # Size limits — determine level by path depth
40
+ SIZE=$(wc -c < "$FILE" | tr -d ' ')
41
+ case "$FILE" in
42
+ *root.prizm)
43
+ LIMIT=4096; LEVEL="L0"
44
+ HINT="Consolidate MODULE_INDEX, keep top-5 RULES."
45
+ ;;
46
+ *)
47
+ # L1 = direct child of .prizm-docs/, L2 = nested deeper
48
+ DIR=$(dirname "$FILE")
49
+ if [ "$DIR" = ".prizm-docs" ]; then
50
+ LIMIT=3072; LEVEL="L1"
51
+ HINT="Move implementation details to L2."
52
+ else
53
+ LIMIT=5120; LEVEL="L2"
54
+ HINT="Archive CHANGELOG entries older than 90 days."
55
+ fi
56
+ ;;
57
+ esac
58
+
59
+ if [ "$SIZE" -gt "$LIMIT" ]; then
60
+ echo "ERROR: $FILE exceeds $LEVEL limit (${SIZE}B > ${LIMIT}B). $HINT" >&2
61
+ ERRORS=$((ERRORS + 1))
62
+ fi
63
+
64
+ # Required fields in root.prizm
65
+ case "$FILE" in
66
+ *root.prizm)
67
+ if ! grep -q 'PRIZM_VERSION:' "$FILE"; then
68
+ echo "ERROR: $FILE missing required field PRIZM_VERSION:" >&2
69
+ ERRORS=$((ERRORS + 1))
70
+ fi
71
+ if ! grep -q 'MODULE_INDEX:' "$FILE"; then
72
+ echo "ERROR: $FILE missing required field MODULE_INDEX:" >&2
73
+ ERRORS=$((ERRORS + 1))
74
+ fi
75
+ ;;
76
+ esac
77
+ done
78
+
79
+ if [ "$ERRORS" -gt 0 ]; then
80
+ echo "PrizmKit: $ERRORS format error(s) in .prizm files. Fix before committing." >&2
81
+ exit 1
82
+ fi
83
+
84
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,9 +6,9 @@
6
6
  import { execFileSync } from 'child_process';
7
7
 
8
8
  /**
9
- * 允许检测的命令白名单
9
+ * 允许检测的命令白名单(仅用于 which 检测)
10
10
  */
11
- const ALLOWED_COMMANDS = ['cbc', 'claude'];
11
+ const ALLOWED_COMMANDS = ['cbc', 'claude', 'claude-internal'];
12
12
 
13
13
  /**
14
14
  * 检查命令是否存在于 PATH 中
@@ -26,21 +26,33 @@ function commandExists(cmd) {
26
26
  }
27
27
 
28
28
  /**
29
- * 检测已安装的 AI CLI 工具,并返回推荐的默认平台。
30
- * @returns {{ cbc: boolean, claude: boolean, suggested: string }}
29
+ * 检测已安装的 AI CLI 工具,并返回推荐的默认平台和 CLI 命令。
30
+ *
31
+ * 注意:platform 控制目录结构(.codebuddy/ 或 .claude/),
32
+ * suggestedCli 是实际运行的可执行命令,二者相互独立。
33
+ *
34
+ * @returns {{ cbc: boolean, claude: boolean, claudeInternal: boolean, suggested: string, suggestedCli: string }}
31
35
  */
32
36
  export function detectPlatform() {
33
37
  const cbc = commandExists('cbc');
34
38
  const claude = commandExists('claude');
39
+ const claudeInternal = commandExists('claude-internal');
35
40
 
41
+ // platform 建议:基于目录结构,优先 both
36
42
  let suggested = 'codebuddy';
37
- if (cbc && claude) {
43
+ if ((cbc) && (claude || claudeInternal)) {
38
44
  suggested = 'both';
39
- } else if (claude && !cbc) {
45
+ } else if ((claude || claudeInternal) && !cbc) {
40
46
  suggested = 'claude';
41
- } else if (cbc && !claude) {
47
+ } else if (cbc && !claude && !claudeInternal) {
42
48
  suggested = 'codebuddy';
43
49
  }
44
50
 
45
- return { cbc, claude, suggested };
51
+ // CLI 命令建议:优先 cbc,其次 claude-internal,再次 claude
52
+ let suggestedCli = '';
53
+ if (cbc) suggestedCli = 'cbc';
54
+ else if (claudeInternal) suggestedCli = 'claude-internal';
55
+ else if (claude) suggestedCli = 'claude';
56
+
57
+ return { cbc, claude, claudeInternal, suggested, suggestedCli };
46
58
  }
package/src/index.js CHANGED
@@ -33,6 +33,7 @@ export async function runScaffold(directory, options) {
33
33
  const cliStatus = [
34
34
  detected.cbc ? chalk.green('cbc ✓') : chalk.gray('cbc ✗'),
35
35
  detected.claude ? chalk.green('claude ✓') : chalk.gray('claude ✗'),
36
+ detected.claudeInternal ? chalk.green('claude-internal ✓') : chalk.gray('claude-internal ✗'),
36
37
  ].join(' ');
37
38
  console.log(` 检测到的 CLI 工具: ${cliStatus}`);
38
39
  console.log(` 目标目录: ${projectRoot}`);
@@ -64,16 +65,16 @@ export async function runScaffold(directory, options) {
64
65
 
65
66
  // === 交互式模式 ===
66
67
  try {
67
- // 1. 选择平台
68
+ // 1. 选择平台(控制安装的目录结构)
68
69
  const platform = await select({
69
- message: '选择目标平台:',
70
+ message: '选择目标平台 (决定安装的目录结构):',
70
71
  choices: [
71
72
  {
72
- name: `CodeBuddy CLI (cbc)${detected.cbc ? chalk.green(' ← 已检测到') : ''}`,
73
+ name: `CodeBuddy (.codebuddy/)${detected.cbc ? chalk.green(' ← 已检测到 cbc') : ''}`,
73
74
  value: 'codebuddy',
74
75
  },
75
76
  {
76
- name: `Claude Code CLI (claude)${detected.claude ? chalk.green(' ← 已检测到') : ''}`,
77
+ name: `Claude Code (.claude/)${(detected.claude || detected.claudeInternal) ? chalk.green(' ← 已检测到') : ''}`,
77
78
  value: 'claude',
78
79
  },
79
80
  {
@@ -84,11 +85,10 @@ export async function runScaffold(directory, options) {
84
85
  default: detected.suggested,
85
86
  });
86
87
 
87
- // 1.5. AI CLI 命令配置
88
- const defaultCli = detected.cbc ? 'cbc' : detected.claude ? 'claude' : '';
88
+ // 1.5. AI CLI 命令配置(独立于平台,决定实际运行的可执行命令)
89
89
  const aiCli = await input({
90
- message: '底层 AI CLI 可执行命令 (留空自动检测):',
91
- default: defaultCli,
90
+ message: '底层 AI CLI 可执行命令 (可自定义,如 claude-internal --dangerously-skip-permissions):',
91
+ default: detected.suggestedCli,
92
92
  });
93
93
 
94
94
  // 2. 选择技能套件
package/src/scaffold.js CHANGED
@@ -439,6 +439,60 @@ async function installSettings(platform, projectRoot, options, dryRun) {
439
439
  }
440
440
  }
441
441
 
442
+ /**
443
+ * 安装 git pre-commit hook(prizm 格式校验)
444
+ */
445
+ async function installGitHook(projectRoot, dryRun) {
446
+ const gitDir = path.join(projectRoot, '.git');
447
+
448
+ if (dryRun) {
449
+ console.log(chalk.gray(' [dry-run] .git/hooks/pre-commit (prizm format check)'));
450
+ return;
451
+ }
452
+
453
+ if (!fs.existsSync(gitDir)) return;
454
+
455
+ const templatePath = path.join(getTemplatesDir(), 'hooks', 'prizm-pre-commit.sh');
456
+ const hooksDir = path.join(gitDir, 'hooks');
457
+ const preCommitPath = path.join(hooksDir, 'pre-commit');
458
+
459
+ fs.mkdirSync(hooksDir, { recursive: true });
460
+
461
+ if (fs.existsSync(preCommitPath)) {
462
+ const existing = fs.readFileSync(preCommitPath, 'utf8');
463
+ if (existing.includes('PrizmKit')) return;
464
+ const hookContent = fs.readFileSync(templatePath, 'utf8');
465
+ fs.writeFileSync(preCommitPath, existing + '\n\n' + hookContent);
466
+ } else {
467
+ await fs.copy(templatePath, preCommitPath);
468
+ fs.chmodSync(preCommitPath, 0o755);
469
+ }
470
+
471
+ console.log(chalk.green(' ✓ .git/hooks/pre-commit (prizm format check)'));
472
+ }
473
+
474
+ /**
475
+ * 安装 validate-prizm-docs.sh 到 dev-pipeline/scripts/
476
+ */
477
+ async function installValidateScript(projectRoot, dryRun) {
478
+ const sourcePath = path.join(getTemplatesDir(), 'hooks', 'validate-prizm-docs.sh');
479
+ if (!fs.existsSync(sourcePath)) return;
480
+
481
+ const targetDir = path.join(projectRoot, 'dev-pipeline', 'scripts');
482
+ const targetPath = path.join(targetDir, 'validate-prizm-docs.sh');
483
+
484
+ if (dryRun) {
485
+ console.log(chalk.gray(' [dry-run] dev-pipeline/scripts/validate-prizm-docs.sh'));
486
+ return;
487
+ }
488
+
489
+ await fs.ensureDir(targetDir);
490
+ await fs.copy(sourcePath, targetPath);
491
+ fs.chmodSync(targetPath, 0o755);
492
+
493
+ console.log(chalk.green(' ✓ dev-pipeline/scripts/validate-prizm-docs.sh'));
494
+ }
495
+
442
496
  /**
443
497
  * 安装项目记忆文件(CODEBUDDY.md / CLAUDE.md)
444
498
  */
@@ -653,6 +707,16 @@ export async function scaffold(config) {
653
707
  }
654
708
  }
655
709
 
710
+ // 10. Git pre-commit hook
711
+ console.log(chalk.blue(' Git Hook:'));
712
+ await installGitHook(projectRoot, dryRun);
713
+
714
+ // 11. Validate script (only if pipeline enabled)
715
+ if (pipeline) {
716
+ console.log(chalk.blue(' 验证脚本:'));
717
+ await installValidateScript(projectRoot, dryRun);
718
+ }
719
+
656
720
  // === 完成 ===
657
721
  console.log('');
658
722
  console.log(chalk.bold(' ════════════════════════════════════════════════'));
@@ -667,7 +731,8 @@ export async function scaffold(config) {
667
731
  if (!dryRun) {
668
732
  // 打印下一步提示
669
733
  const mainPlatform = platforms.includes('claude') ? 'claude' : 'codebuddy';
670
- const cli = mainPlatform === 'claude' ? 'claude' : 'cbc';
734
+ const defaultCli = mainPlatform === 'claude' ? 'claude' : 'cbc';
735
+ const cli = aiCli || defaultCli;
671
736
 
672
737
  console.log('');
673
738
  console.log(' 下一步:');