chore: migrate IDE environment from Kiro to Claude Code
- Add CLAUDE.md (root + ETL subdirectory + db subdirectory) consolidating all Kiro steering docs - Add .mcp.json migrated from .kiro/settings/mcp.json (test DBs enabled, prod disabled) - Add .claude/commands/ (audit, doc-sync, db-docs) replacing Kiro skills - Add .claude/hooks/ (session_start, post_edit_audit, stop_audit_check) replacing Kiro hooks - Add .claude/settings.json registering all hooks - Add scripts/audit/prescan.py merging Kiro's audit_flagger + compliance_prescan - Remove .kiro/agents, hooks, scripts, settings, skills, state (migrated or obsolete) - Update .gitignore for Claude Code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
104
.claude/commands/audit.md
Normal file
104
.claude/commands/audit.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# /audit — 变更审计
|
||||
|
||||
回顾本次会话中你所做的所有文件变更,结合自动预扫描结果,执行审计落盘。
|
||||
|
||||
## 执行步骤
|
||||
|
||||
### 第 1 步:运行预扫描脚本(Python,零 token)
|
||||
|
||||
运行:
|
||||
```bash
|
||||
python scripts/audit/prescan.py
|
||||
```
|
||||
|
||||
该脚本自动完成:
|
||||
- 从 git status 获取所有变更文件
|
||||
- 分类高风险文件 + 生成 risk_tags
|
||||
- 合规检查:代码→文档映射、迁移 SQL 检测、DDL 基线检查
|
||||
|
||||
读取输出的 JSON。如果 `audit_required: false`,告知用户"无需审计"并结束。
|
||||
|
||||
**备选**:如果 git status 包含大量非本次会话的历史变更,可以用 `--files` 参数只传入本次会话的文件:
|
||||
```bash
|
||||
python scripts/audit/prescan.py --files "file1.py,file2.sql,..."
|
||||
```
|
||||
文件列表从你的对话记忆(本次会话的 Edit/Write 工具调用)中提取。
|
||||
|
||||
### 第 2 步:补充语义上下文
|
||||
|
||||
预扫描脚本能告诉你"哪些文件变了、是否高风险、文档是否缺失",但它不知道**为什么改**。
|
||||
|
||||
从对话记忆中补充:
|
||||
- 每个变更文件的修改原因(用户的需求是什么)
|
||||
- 改动的技术思路和设计决策
|
||||
- 与其他模块的关联影响
|
||||
|
||||
将预扫描 JSON + 语义上下文合并,作为第 3 步的输入。
|
||||
|
||||
### 第 3 步:委托子代理写审计记录
|
||||
|
||||
用 Agent 工具启动子代理,传入:
|
||||
1. 预扫描 JSON 结果(完整)
|
||||
2. 每个变更的原因和内容概要(你补充的语义上下文)
|
||||
|
||||
子代理的任务指令:
|
||||
|
||||
> 在 `docs/audit/changes/` 目录下创建审计记录文件,文件名格式 `<YYYY-MM-DD>__<英文短标识>.md`。
|
||||
>
|
||||
> 使用以下格式:
|
||||
>
|
||||
> ```markdown
|
||||
> # 变更审计记录:<中文标题>
|
||||
>
|
||||
> | 字段 | 值 |
|
||||
> |------|-----|
|
||||
> | 日期 | YYYY-MM-DD HH:MM:SS |
|
||||
>
|
||||
> ## 操作摘要
|
||||
> <1-3 段,说清楚做了什么、为什么做>
|
||||
>
|
||||
> ## 变更文件
|
||||
> 按新增/修改/删除分组,每个文件一行,简要说明改动内容。
|
||||
>
|
||||
> ## 改动注解
|
||||
> 对每个变更文件写注解:
|
||||
> - 高风险文件(ETL 任务/后端路由/数据库迁移/金额相关):写详细注解(变更类型、原因、思路、结果)
|
||||
> - 普通文件:一行简要说明
|
||||
> - 删除的文件:只记录删除原因
|
||||
>
|
||||
> ## 数据库变更(如有)
|
||||
> 列出新建/修改/删除的表、字段、约束、索引。标注迁移执行状态。
|
||||
>
|
||||
> ## 风险与回滚
|
||||
> - 风险点(标注高/中/低)
|
||||
> - 回滚要点
|
||||
>
|
||||
> ## 验证
|
||||
> - 至少 1 条可执行的验证方式(测试命令 / SQL / 联调步骤)
|
||||
>
|
||||
> ## 合规检查
|
||||
> - 列出文档同步状态(已同步 / 待补齐 / 不适用)
|
||||
> ```
|
||||
>
|
||||
> 当前北京时间通过 `python -c "from datetime import datetime, timezone, timedelta; print(datetime.now(timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S'))"` 获取。
|
||||
>
|
||||
> 审计记录语言使用简体中文。
|
||||
>
|
||||
> 完成后运行 `python scripts/audit/gen_audit_dashboard.py` 刷新审计一览表。
|
||||
>
|
||||
> 最终只返回:done / files_written / next_step。
|
||||
|
||||
### 第 4 步:补齐缺失的文档同步
|
||||
|
||||
根据预扫描 JSON 中 `code_without_docs` 列出的不合规项,逐项补齐:
|
||||
- 读取对应代码文件当前内容
|
||||
- 更新对应文档
|
||||
|
||||
如果补齐工作量大(>3 个文档),委托子代理处理。
|
||||
|
||||
### 第 5 步:向用户报告
|
||||
|
||||
简短回执:
|
||||
- 审计记录文件路径
|
||||
- 合规检查结果(全部通过 / N 项已补齐 / N 项待用户处理)
|
||||
- 下一步建议(如 "commit when ready")
|
||||
63
.claude/commands/db-docs.md
Normal file
63
.claude/commands/db-docs.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# /db-docs — 数据库文档同步
|
||||
|
||||
当 PostgreSQL schema/表结构发生变化时,将变更以审计友好的方式落盘到 `docs/database/`。
|
||||
|
||||
## 触发条件
|
||||
|
||||
- 迁移脚本/DDL 修改(新增/删除/改表、字段、类型、默认值、非空、约束、索引、外键)
|
||||
- 手工执行了 DDL
|
||||
|
||||
## 执行步骤
|
||||
|
||||
### 第 1 步:识别结构性变化
|
||||
|
||||
从本次会话的改动中,列出新增/修改/删除的对象:
|
||||
- schema / table / column / index / constraint / foreign key
|
||||
- 明确变更前后差异(before/after)
|
||||
|
||||
### 第 2 步:更新表结构文档
|
||||
|
||||
对每张受影响的表,更新 `docs/database/` 下对应的文档:
|
||||
- 如果文档已存在:更新字段列表、约束、索引等
|
||||
- 如果文档不存在:基于以下模板创建
|
||||
|
||||
模板:
|
||||
```markdown
|
||||
# <schema>.<table_name>
|
||||
|
||||
## 概述
|
||||
<表的用途说明>
|
||||
|
||||
## 字段
|
||||
|
||||
| 字段名 | 类型 | 可空 | 默认值 | 说明 |
|
||||
|--------|------|------|--------|------|
|
||||
| ... | ... | ... | ... | ... |
|
||||
|
||||
## 约束与索引
|
||||
- PRIMARY KEY: ...
|
||||
- UNIQUE: ...
|
||||
- INDEX: ...
|
||||
|
||||
## 关联
|
||||
- 上游:<数据来源>
|
||||
- 下游:<被哪些模块/表消费>
|
||||
```
|
||||
|
||||
特别注意金额类字段:标注精度、币种、舍入规则。
|
||||
|
||||
### 第 3 步:回滚与验证
|
||||
|
||||
写入审计友好的回滚和验证信息:
|
||||
- DDL 回滚路径(必要时提供反向迁移 SQL)
|
||||
- 至少 3 条验证 SQL(含约束/索引/关键字段检查)
|
||||
|
||||
### 第 4 步:DDL 基线检查
|
||||
|
||||
检查 `docs/database/ddl/` 下的基线文件是否需要合并更新。如需要,更新基线。
|
||||
|
||||
### 第 5 步:输出摘要
|
||||
|
||||
- 更新/创建了哪些文档
|
||||
- 迁移脚本执行状态(已执行 / 待执行)
|
||||
- DDL 基线状态(已合并 / 待合并)
|
||||
55
.claude/commands/doc-sync.md
Normal file
55
.claude/commands/doc-sync.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# /doc-sync — 逻辑改动后文档同步
|
||||
|
||||
检查本次会话中的逻辑改动是否需要同步更新文档,并执行同步。
|
||||
|
||||
## 触发条件
|
||||
|
||||
修改了以下任一类内容时应执行:
|
||||
- 业务规则/计算口径/资金处理(精度、舍入、阈值)
|
||||
- ETL/SQL 清洗聚合映射逻辑
|
||||
- API 行为(返回结构、错误码、鉴权/权限)
|
||||
- 小程序关键交互流程
|
||||
- 数据库表结构
|
||||
|
||||
## 执行步骤
|
||||
|
||||
### 第 1 步:分类
|
||||
|
||||
判断本次会话的改动是否属于"逻辑改动"。如果只是纯格式化/拼写修正/注释调整,告知用户"无逻辑改动,无需文档同步"并结束。
|
||||
|
||||
### 第 2 步:逐项评估需要更新的文档
|
||||
|
||||
根据变更涉及的模块,评估以下文档是否需要更新:
|
||||
|
||||
**各级 README.md**(只更新与本次变更相关的):
|
||||
- `README.md`(根目录):项目总览、快速开始、环境变量、架构概述
|
||||
- `apps/backend/README.md`:后端 API 路由、配置、运行方式
|
||||
- `apps/etl/connectors/feiqiu/README.md`:ETL 任务清单、开发约定
|
||||
- `apps/miniprogram/README.md`:小程序页面结构
|
||||
- `apps/admin-web/README.md`:管理后台功能说明
|
||||
- `apps/tenant-admin/README.md`:租户管理后台功能说明
|
||||
- `packages/shared/README.md`:共享包说明
|
||||
- `db/README.md`:Schema 约定、迁移规范
|
||||
|
||||
规则:如果"对读者理解系统行为有帮助"就应更新。若某个 README 尚不存在但变更涉及该模块,应创建。
|
||||
|
||||
### 第 3 步:执行更新
|
||||
|
||||
对每个需要更新的文档:
|
||||
1. 读取当前内容
|
||||
2. 根据本次变更更新相关段落
|
||||
3. 写入更新后的内容
|
||||
|
||||
如果更新工作量大(>3 个文档),委托子代理处理。
|
||||
|
||||
### 第 4 步:联动检查
|
||||
|
||||
- 如果涉及 DB schema 变化:提醒用户执行 `/db-docs`
|
||||
- 如果涉及 API 变化:检查 `apps/backend/docs/API-REFERENCE.md` 是否已更新
|
||||
|
||||
### 第 5 步:输出摘要
|
||||
|
||||
- Changed:改了哪些文档
|
||||
- Why:原始原因 + 直接原因
|
||||
- Risk:风险点与回归范围
|
||||
- Verify:建议的验证步骤
|
||||
33
.claude/hooks/post_edit_audit_reminder.py
Normal file
33
.claude/hooks/post_edit_audit_reminder.py
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
"""PostToolUse hook: 编辑高风险文件后提醒审计"""
|
||||
import json, re, sys
|
||||
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
|
||||
fp = (data.get("tool_input") or {}).get("file_path", "")
|
||||
if not fp:
|
||||
sys.exit(0)
|
||||
|
||||
# 转相对路径
|
||||
rel = re.sub(r"^.*?NeoZQYY[/\\]", "", fp.replace("\\", "/"))
|
||||
|
||||
HIGH_RISK = [
|
||||
r"^apps/etl/connectors/feiqiu/(tasks|loaders|scd|orchestration|config|database|models|quality)/",
|
||||
r"^apps/backend/app/(routers|services|auth|schemas)/",
|
||||
r"^db/.*/migrations/.*\.sql$",
|
||||
r"^db/.*/schemas/.*\.sql$",
|
||||
r"^packages/shared/",
|
||||
]
|
||||
|
||||
for p in HIGH_RISK:
|
||||
if re.search(p, rel):
|
||||
print(json.dumps({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": f"[audit-reminder] 已编辑高风险文件: {rel} — 完成本轮改动后请执行 /audit"
|
||||
}
|
||||
}))
|
||||
break
|
||||
36
.claude/hooks/session_start_context.py
Normal file
36
.claude/hooks/session_start_context.py
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
"""SessionStart hook: 会话开始时加载项目状态上下文"""
|
||||
import json, subprocess, sys, os
|
||||
|
||||
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
||||
script = os.path.join(project_dir, "scripts", "audit", "prescan.py")
|
||||
|
||||
if not os.path.isfile(script):
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[sys.executable, script],
|
||||
capture_output=True, text=True, timeout=10, cwd=project_dir,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
sys.exit(0)
|
||||
result = json.loads(r.stdout)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
|
||||
audit_required = result.get("audit_required", False)
|
||||
total = result.get("total_files", 0)
|
||||
tags = ", ".join(result.get("risk_tags", []))
|
||||
|
||||
if audit_required:
|
||||
ctx = f"[session-context] 当前工作区有 {total} 个未提交的变更文件,含高风险标签: {tags}。如果这些变更来自之前的会话且未审计,建议先执行 /audit。"
|
||||
else:
|
||||
ctx = "[session-context] 当前工作区状态正常,无高风险未审计变更。"
|
||||
|
||||
print(json.dumps({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": ctx
|
||||
}
|
||||
}))
|
||||
29
.claude/hooks/stop_audit_check.py
Normal file
29
.claude/hooks/stop_audit_check.py
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Stop hook: Claude 结束回复时检查是否有未审计的高风险变更"""
|
||||
import json, subprocess, sys, os
|
||||
|
||||
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
||||
script = os.path.join(project_dir, "scripts", "audit", "prescan.py")
|
||||
|
||||
if not os.path.isfile(script):
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[sys.executable, script],
|
||||
capture_output=True, text=True, timeout=10, cwd=project_dir,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
sys.exit(0)
|
||||
result = json.loads(r.stdout)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
|
||||
high_risk = result.get("high_risk_files", [])
|
||||
if result.get("audit_required", False) and len(high_risk) > 0:
|
||||
print(json.dumps({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "Stop",
|
||||
"additionalContext": f"[audit-check] 当前有 {len(high_risk)} 个高风险文件变更未审计。建议执行 /audit。"
|
||||
}
|
||||
}))
|
||||
45
.claude/settings.json
Normal file
45
.claude/settings.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"permissions": {
|
||||
"additionalDirectories": [
|
||||
"C:\\Users\\Administrator\\.claude",
|
||||
"c:\\NeoZQYY\\.git"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/session_start_context.py\"",
|
||||
"timeout": 15,
|
||||
"statusMessage": "加载项目状态..."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/post_edit_audit_reminder.py\"",
|
||||
"timeout": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop_audit_check.py\"",
|
||||
"timeout": 15
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user