强制遵守三套开发文档:README @import + PreToolUse 提醒 hook
把"必须严格遵守 docs 三套文档"从软指令变成硬机制,同时消除 SSOT 重复: - CLAUDE.md 用 @import 把三份 README(含各自红线速查/一页纸总则) 常驻每次会话上下文,删掉手写的红线摘要——红线以 README 权威源为准, 不再在 CLAUDE.md 另抄一份 - 新增 .claude/hooks/remind-docs.js:PreToolUse 钩子,编辑 client/**、 server/** 前按路径把"必须遵守的对应编号文档 + 红线"注入上下文(非阻塞) - 新增 .claude/settings.json 注册该 hook(matcher Edit|Write|MultiEdit); 已 pipe-test 各路径分支 + sentinel 验证 hook 实际触发 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
// PreToolUse hook:编辑 client/** 或 server/** 前,按路径把「必须遵守的文档」
|
||||||
|
// 注入到上下文,作为硬提醒。非阻塞——只追加 additionalContext,不拦截操作。
|
||||||
|
// 权威说明见根目录 CLAUDE.md「文档」一节与各 README 红线速查。
|
||||||
|
|
||||||
|
var chunks = [];
|
||||||
|
process.stdin.on('data', function (c) { chunks.push(c); });
|
||||||
|
process.stdin.on('end', function () {
|
||||||
|
var reminder = '';
|
||||||
|
try {
|
||||||
|
var input = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}');
|
||||||
|
var p = (input.tool_input && input.tool_input.file_path) || '';
|
||||||
|
p = String(p).replace(/\\/g, '/');
|
||||||
|
|
||||||
|
if (/\/docs\//.test(p)) {
|
||||||
|
// 改文档本身不提醒
|
||||||
|
reminder = '';
|
||||||
|
} else if (/\/codes\/shared\//.test(p)) {
|
||||||
|
reminder =
|
||||||
|
'你在改 codes/shared/(服务端 shared/ 的只读同步副本)。红线:前端侧不改,' +
|
||||||
|
'只改服务端权威源再跑同步脚本。详见 client 05 §「shared 只读」/ server 04 §8。';
|
||||||
|
} else if (/\/client\/js\/gameabc-framework\//.test(p)) {
|
||||||
|
reminder =
|
||||||
|
'你在改 gameabc-framework/(可复用框架)。必须遵守:框架保持游戏中立,' +
|
||||||
|
'禁渗入任何具体玩法逻辑/常量;依赖严格单向。权威见 client 01、client 05 红线速查,' +
|
||||||
|
'设计通则见 games/engineering。动手前请先读对应编号文档。';
|
||||||
|
} else if (/\/client\/js\/01_subgame\//i.test(p) || /\/client\/js\//.test(p)) {
|
||||||
|
reminder =
|
||||||
|
'你在改客户端子游戏/前端代码。必须遵守 client development-guide:' +
|
||||||
|
'架构与加载顺序(01)、渲染与组件(02)、事件/动画/音频/Spine(03)、网络对接(04)、' +
|
||||||
|
'红线速查(05)、接入模式(06);工程通则见 games/engineering。' +
|
||||||
|
'红线:严格 ES5、精灵只走 SpriteManager、常量集中禁硬编码、成败只认 data.success、' +
|
||||||
|
'服务端权威前端只展示、组件走 BaseComponent、数据优先表现延后。动手前先读对应编号文档。';
|
||||||
|
} else if (/\/server\//.test(p)) {
|
||||||
|
reminder =
|
||||||
|
'你在改服务端代码。必须遵守 server development-guide:环境与框架(01)、' +
|
||||||
|
'子游戏接入(02)、通信协议(03)、红线速查(04);工程通则见 games/engineering。' +
|
||||||
|
'红线:严格 ES5、require 只在文件头守卫块、成败标志 data.success(推送包自带)、' +
|
||||||
|
'数据权威缺失显式报错、模块职责单一、房间隔离(房间+seat 为 key)、' +
|
||||||
|
'自动操作复用真人链路、下发包携带前端所需全部核心数据。动手前先读对应编号文档。';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reminder = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reminder) {
|
||||||
|
process.stdout.write(JSON.stringify({
|
||||||
|
hookSpecificOutput: {
|
||||||
|
hookEventName: 'PreToolUse',
|
||||||
|
additionalContext: reminder
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PreToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Edit|Write|MultiEdit",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/remind-docs.js\"",
|
||||||
|
"timeout": 10,
|
||||||
|
"statusMessage": "校验开发文档红线…"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
本文件为 Claude Code(claude.ai/code)在本仓库中工作时提供指导。**它只是入口与红线缓存,不复述规范细节**——权威、完整的规范在 `docs/` 三套文档里(见下「文档」一节),改动前先读对应文档。
|
本文件为 Claude Code(claude.ai/code)在本仓库中工作时提供指导。**它是入口与强制指引**:三套文档的 README(含各自「红线速查 / 一页纸总则」)已通过 `@import` 常驻上下文(见下「文档」一节),**红线以它们为权威、始终在上下文里,本文件不再另抄一份**;规范的完整细节在 `docs/` 编号文档里,改动前先读对应文档。
|
||||||
|
|
||||||
## 这是一个什么仓库
|
## 这是一个什么仓库
|
||||||
|
|
||||||
@@ -44,26 +44,21 @@ client/scripts/build_spine_data.cmd # 内部调用 build_spine_data.ps1
|
|||||||
| `01_SubGame/codes/`(除 `shared/`)、`server/<游戏容器目录>/<游戏>/` | 子游戏自由开发区 |
|
| `01_SubGame/codes/`(除 `shared/`)、`server/<游戏容器目录>/<游戏>/` | 子游戏自由开发区 |
|
||||||
| `01_SubGame/codes/shared/` | 服务端 `shared/` 的只读同步副本;改服务端一侧后再同步 |
|
| `01_SubGame/codes/shared/` | 服务端 `shared/` 的只读同步副本;改服务端一侧后再同步 |
|
||||||
|
|
||||||
## 红线摘要
|
|
||||||
|
|
||||||
> always-on 缓存,**权威与完整清单见各 README 红线速查(client 05 / server 04)与 games/engineering 一页纸总则**;每条都对应过真实事故,冲突时一律以文档为准。
|
|
||||||
|
|
||||||
- **严格 ES5**:`var`/`function`、继承用 `Object.create`;禁 `let/const`/箭头函数/模板字符串/`class`/解构/`Promise`。服务端 `require` 只能写在文件开头 `if (typeof require !== 'undefined') { ... }` 守卫块内,禁止函数体内中途 `require`。
|
|
||||||
- **成败只认推送包 `data.success`**(布尔值,主动推送的 `data` 必须自带)——绝不用 `status`/`code`,不写两者都判的兼容兜底。
|
|
||||||
- **权威数据缺失要显式报错**:影响发牌/庄家/手牌/计分/重连的权威数据禁止 `|| 0`/`|| []`/`|| ''` 兜底掩盖;默认值仅允许用于纯展示/日志字段。
|
|
||||||
- **房间隔离**:对局状态挂 `o_room.o_desk.data.*`,缓存/定时器/决策表以 `房间 + seat` 为 key(非仅 `seat`);禁止模块级单例/全局变量存对局态,小局结束/解散/开新局时清理干净。
|
|
||||||
- **一个职能只在一个模块实现**:需要某能力时调用其所属模块,而不是在别处重造一份。
|
|
||||||
- **自动操作复用真人链路**:服务端代玩家执行的操作(AI 托管、超时等)必须走与真人完全相同的 handler → 广播链路,客户端不为其单开解析分支。
|
|
||||||
|
|
||||||
## 文档(改动前先读——这三套是权威源)
|
## 文档(改动前先读——这三套是权威源)
|
||||||
|
|
||||||
本仓库开发**必须遵守**以下三套文档;改哪块就先读对应 README 与编号文档,而不是从代码反推约定:
|
本仓库开发**必须严格遵守**以下三套文档;改哪块就先读对应 README 与编号文档,而不是从代码反推约定:
|
||||||
|
|
||||||
- `docs/client/development-guide/`(01→06)、`docs/server/development-guide/`(01→04)——项目专属的平台接入规范与红线。
|
- `docs/client/development-guide/`(01→06)、`docs/server/development-guide/`(01→04)——项目专属的平台接入规范与红线。
|
||||||
- `docs/games/engineering/`(01→03)——位于两者之上、与平台无关的工程方法论(SSOT、单向依赖、职责单一、OCP、配置优先于硬编码、显式失败优于隐式兜底)。
|
- `docs/games/engineering/`(01→03)——位于两者之上、与平台无关的工程方法论(SSOT、单向依赖、职责单一、OCP、配置优先于硬编码、显式失败优于隐式兜底)。
|
||||||
|
|
||||||
三者互补不冲突:engineering 讲「该怎么设计、怎么长久演进」,dev-guide 讲「平台怎么接、红线是什么」;硬红线冲突时以 dev-guide 为准。
|
三者互补不冲突:engineering 讲「该怎么设计、怎么长久演进」,dev-guide 讲「平台怎么接、红线是什么」;硬红线冲突时以 dev-guide 为准。
|
||||||
|
|
||||||
|
以下三份 README(含各自「红线速查 / 一页纸总则」)通过 `@import` **自动加载进每次会话的上下文**——红线以它们为权威,无需在本文件另抄一份;改动具体区域时再深入读对应编号文档:
|
||||||
|
|
||||||
|
@docs/client/development-guide/README.md
|
||||||
|
@docs/server/development-guide/README.md
|
||||||
|
@docs/games/engineering/README.md
|
||||||
|
|
||||||
各编号对应主题(改哪块查哪篇):
|
各编号对应主题(改哪块查哪篇):
|
||||||
|
|
||||||
| 文档 | 编号与主题 |
|
| 文档 | 编号与主题 |
|
||||||
|
|||||||
Reference in New Issue
Block a user