头脑风暴、实施、审查三套提示词引用的 /ecc:plan-prd、grill-me、 /ecc:tdd-workflow、/review 在 ECC 2.2.15 里都不存在,会话拿到的是一 条无效命令。审查提示词里的 /ecc:review-pr 走 gh,对 Gitea 不可用。 改为 ECC 实际链路:/ecc:grilling 讨论、/ecc:spec 出设计文档、 /ecc:plan 出计划、/ecc:tdd 实施,审查直接派 ecc:code-reviewer 等子代 理审 git diff。文档路径随 ECC 约定改成 .claude/specs/<stem>.md 与 .claude/plans/<stem>.md,stem 两者共用,不再带 .prd.md / .plan.md 后 缀;deriveSlug 相应改成取文件名 stem,通用文件名才退回目录名。 Claude-Session: https://claude.ai/code/session_01REdhpbaNyqWASF2HWsnTFv
43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { createHash } from 'node:crypto'
|
||
import * as os from 'node:os'
|
||
import * as path from 'node:path'
|
||
|
||
export const DEFAULT_WORKTREE_TEMPLATE = '~/Sources/worktree/$project_name/$feature_name'
|
||
|
||
/**
|
||
* 设计文档 / 计划按 ECC 布局存放:`.claude/specs/<stem>.md`、`.claude/plans/<stem>.md`,
|
||
* 文件名的 stem 就是 slug,两者共用同一个 stem。少数布局把文件名固定成
|
||
* `plan.md` / `spec.md`,这时 slug 退回父目录名;再兜底路径 hash,保证不为空。
|
||
*/
|
||
export function deriveSlug(planFile: string): string {
|
||
const stem = path.basename(planFile).replace(/\.md$/, '')
|
||
if (stem && stem !== 'plan' && stem !== 'spec')
|
||
return stem
|
||
const parent = path.basename(path.dirname(planFile))
|
||
if (parent && parent !== '.' && parent !== '/')
|
||
return parent
|
||
return createHash('sha256').update(planFile).digest('hex').slice(0, 8)
|
||
}
|
||
|
||
/** 实施分支固定形如 `feature/<slug>`;接管方只有分支名,从这里反推 worktree 目录名。 */
|
||
export function slugFromBranch(branch: string): string {
|
||
return branch.startsWith('feature/') ? branch.slice('feature/'.length) : branch
|
||
}
|
||
|
||
/**
|
||
* 把 worktreeDirectory 模板展开成绝对路径。`~` 在这里展开:git/execFile 不经 shell,
|
||
* 不会自己做 tilde 展开。
|
||
*/
|
||
export function resolveWorktreeDir(template: string, workspaceRoot: string, slug: string): string {
|
||
let p = template
|
||
.split('$project_name')
|
||
.join(path.basename(workspaceRoot))
|
||
.split('$project_root')
|
||
.join(workspaceRoot)
|
||
.split('$feature_name')
|
||
.join(slug)
|
||
if (p.startsWith('~'))
|
||
p = path.join(os.homedir(), p.slice(1))
|
||
return path.resolve(p)
|
||
}
|