@winspan/claude-forge 8.0.0 → 8.11.0
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 +64 -5
- package/dist/claudemd/convention-extractor.d.ts +11 -0
- package/dist/claudemd/convention-extractor.d.ts.map +1 -0
- package/dist/claudemd/convention-extractor.js +59 -0
- package/dist/claudemd/convention-extractor.js.map +1 -0
- package/dist/claudemd/resume-manager.d.ts.map +1 -1
- package/dist/claudemd/resume-manager.js +8 -2
- package/dist/claudemd/resume-manager.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +1 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/rules.d.ts +8 -0
- package/dist/cli/commands/rules.d.ts.map +1 -0
- package/dist/cli/commands/rules.js +89 -0
- package/dist/cli/commands/rules.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +79 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/template.d.ts +8 -0
- package/dist/cli/commands/template.d.ts.map +1 -0
- package/dist/cli/commands/template.js +68 -0
- package/dist/cli/commands/template.js.map +1 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +25 -0
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +26 -0
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/types.d.ts +3 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.d.ts +6 -1
- package/dist/daemon/handlers/pre-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.js +45 -46
- package/dist/daemon/handlers/pre-tool-use.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +4 -1
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +32 -13
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +37 -3
- package/dist/daemon/index.js.map +1 -1
- package/dist/engine/conventions/basic-security.yaml +15 -0
- package/dist/engine/conventions/database-safety.yaml +74 -0
- package/dist/engine/conventions/docker-safety.yaml +69 -0
- package/dist/engine/conventions/git-safety.yaml +12 -0
- package/dist/engine/conventions/go-best-practices.yaml +84 -0
- package/dist/engine/conventions/python-best-practices.yaml +96 -0
- package/dist/engine/conventions/react-best-practices.yaml +96 -0
- package/dist/engine/dsl/parser.d.ts.map +1 -1
- package/dist/engine/dsl/parser.js +7 -1
- package/dist/engine/dsl/parser.js.map +1 -1
- package/dist/engine/dsl/types.d.ts +26 -1
- package/dist/engine/dsl/types.d.ts.map +1 -1
- package/dist/engine/rule-engine.d.ts +2 -1
- package/dist/engine/rule-engine.d.ts.map +1 -1
- package/dist/engine/rule-engine.js +56 -20
- package/dist/engine/rule-engine.js.map +1 -1
- package/dist/skills/matcher.d.ts +17 -1
- package/dist/skills/matcher.d.ts.map +1 -1
- package/dist/skills/matcher.js +92 -2
- package/dist/skills/matcher.js.map +1 -1
- package/dist/skills/registry.d.ts +26 -5
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +100 -10
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/semantic-matcher.d.ts +58 -0
- package/dist/skills/semantic-matcher.d.ts.map +1 -0
- package/dist/skills/semantic-matcher.js +189 -0
- package/dist/skills/semantic-matcher.js.map +1 -0
- package/dist/templates/template-manager.d.ts +52 -0
- package/dist/templates/template-manager.d.ts.map +1 -0
- package/dist/templates/template-manager.js +129 -0
- package/dist/templates/template-manager.js.map +1 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +129 -2
- package/dist/web/server.js.map +1 -1
- package/dist/web/static/index.html +342 -0
- package/package.json +1 -1
|
@@ -17,6 +17,9 @@ forbidden:
|
|
|
17
17
|
level: block
|
|
18
18
|
message: "禁止强制推送到受保护分支 {{git.branch}}"
|
|
19
19
|
suggestion: "使用 --force-with-lease 或创建新分支"
|
|
20
|
+
operator_guidance: "Git 安全规范:受保护分支禁止强制推送;如需改写历史,请在新分支完成并通过 PR 合并。"
|
|
21
|
+
doc_ref: "CLAUDE.md#Git 安全规范"
|
|
22
|
+
tags: ["git", "protected-branch", "history-rewrite"]
|
|
20
23
|
|
|
21
24
|
- id: "warn-force-push"
|
|
22
25
|
when: |
|
|
@@ -26,6 +29,9 @@ forbidden:
|
|
|
26
29
|
level: warn
|
|
27
30
|
message: "检测到 git push --force,请确认这是有意为之"
|
|
28
31
|
suggestion: "force push 会覆盖远程仓库的提交历史"
|
|
32
|
+
operator_guidance: "优先使用 --force-with-lease,避免覆盖他人刚推送的提交。"
|
|
33
|
+
doc_ref: "CLAUDE.md#Git 安全规范"
|
|
34
|
+
tags: ["git", "force-push"]
|
|
29
35
|
|
|
30
36
|
- id: "no-rm-rf-root"
|
|
31
37
|
when: |
|
|
@@ -33,6 +39,9 @@ forbidden:
|
|
|
33
39
|
&& args.command.match(/rm\s+-[^\s]*r[^\s]*f[^\s]*\s+\//).ok()
|
|
34
40
|
level: block
|
|
35
41
|
message: "禁止 rm -rf / 操作"
|
|
42
|
+
operator_guidance: "这是不可逆的高危删除命令;先缩小目标路径,并用 ls 或 dry-run 确认作用范围。"
|
|
43
|
+
doc_ref: "CLAUDE.md#基础安全规范"
|
|
44
|
+
tags: ["filesystem", "destructive"]
|
|
36
45
|
|
|
37
46
|
- id: "no-sudo-rm"
|
|
38
47
|
when: |
|
|
@@ -48,6 +57,9 @@ forbidden:
|
|
|
48
57
|
level: block
|
|
49
58
|
message: "禁止设置 777 权限(安全风险)"
|
|
50
59
|
suggestion: "使用更安全的权限设置,如 755 或 644"
|
|
60
|
+
operator_guidance: "按最小权限原则收紧权限;可执行文件通常使用 755,普通文件通常使用 644。"
|
|
61
|
+
doc_ref: "CLAUDE.md#基础安全规范"
|
|
62
|
+
tags: ["permissions", "security"]
|
|
51
63
|
|
|
52
64
|
- id: "no-drop-database"
|
|
53
65
|
when: |
|
|
@@ -55,6 +67,9 @@ forbidden:
|
|
|
55
67
|
&& args.command.lower().includes("drop database")
|
|
56
68
|
level: block
|
|
57
69
|
message: "禁止 DROP DATABASE 操作"
|
|
70
|
+
operator_guidance: "删库属于不可逆操作;先确认环境、库名和备份,再考虑使用更小粒度的数据变更命令。"
|
|
71
|
+
doc_ref: "CLAUDE.md#基础安全规范"
|
|
72
|
+
tags: ["database", "destructive"]
|
|
58
73
|
|
|
59
74
|
- id: "warn-drop-table"
|
|
60
75
|
when: |
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
id: "database-safety"
|
|
2
|
+
name: "数据库安全规范"
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "数据库操作安全规则,防止 SQL 注入、数据丢失和性能问题"
|
|
5
|
+
triggers: ["sql", "database", "mysql", "postgres", "mongodb", "数据库", "查询"]
|
|
6
|
+
|
|
7
|
+
variables:
|
|
8
|
+
sql_file_patterns: [".sql"]
|
|
9
|
+
dangerous_sql_keywords: ["DROP", "TRUNCATE", "DELETE", "UPDATE"]
|
|
10
|
+
orm_patterns: ["execute", "raw", "query"]
|
|
11
|
+
|
|
12
|
+
forbidden:
|
|
13
|
+
- id: "no-sql-injection"
|
|
14
|
+
when: |
|
|
15
|
+
tool.in(["Write", "Edit"])
|
|
16
|
+
&& (args.content ?? args.new_string ?? "").match(/(?:execute|query|raw)\s*\([^)]*\+[^)]*\)/).ok()
|
|
17
|
+
level: block
|
|
18
|
+
message: "检测到 SQL 字符串拼接,存在 SQL 注入风险"
|
|
19
|
+
suggestion: "使用参数化查询或 ORM 的安全 API"
|
|
20
|
+
operator_guidance: "字符串拼接无法防止 SQL 注入;使用 ? 占位符或 ORM 的参数绑定。"
|
|
21
|
+
doc_ref: "https://owasp.org/www-community/attacks/SQL_Injection"
|
|
22
|
+
tags: ["database", "sql-injection", "security"]
|
|
23
|
+
|
|
24
|
+
- id: "warn-delete-without-where"
|
|
25
|
+
when: |
|
|
26
|
+
tool.in(["Write", "Edit", "Bash"])
|
|
27
|
+
&& (args.content ?? args.new_string ?? args.command ?? "").lower().match(/delete\s+from\s+\w+\s*;/).ok()
|
|
28
|
+
level: block
|
|
29
|
+
message: "检测到无 WHERE 条件的 DELETE,会删除全表数据"
|
|
30
|
+
suggestion: "添加 WHERE 条件限定删除范围,或使用 TRUNCATE"
|
|
31
|
+
operator_guidance: "无条件 DELETE 是不可逆操作;先用 SELECT 验证条件,再执行 DELETE。"
|
|
32
|
+
tags: ["database", "data-loss"]
|
|
33
|
+
|
|
34
|
+
- id: "warn-update-without-where"
|
|
35
|
+
when: |
|
|
36
|
+
tool.in(["Write", "Edit", "Bash"])
|
|
37
|
+
&& (args.content ?? args.new_string ?? args.command ?? "").lower().match(/update\s+\w+\s+set\s+[^;]*;/).ok()
|
|
38
|
+
&& !(args.content ?? args.new_string ?? args.command ?? "").lower().match(/where/).ok()
|
|
39
|
+
level: block
|
|
40
|
+
message: "检测到无 WHERE 条件的 UPDATE,会修改全表数据"
|
|
41
|
+
suggestion: "添加 WHERE 条件限定更新范围"
|
|
42
|
+
operator_guidance: "无条件 UPDATE 会覆盖所有行;先用 SELECT 验证条件,确认影响行数。"
|
|
43
|
+
tags: ["database", "data-loss"]
|
|
44
|
+
|
|
45
|
+
- id: "warn-select-star"
|
|
46
|
+
when: |
|
|
47
|
+
tool.in(["Write", "Edit"])
|
|
48
|
+
&& (args.content ?? args.new_string ?? "").match(/SELECT\s+\*\s+FROM/i).ok()
|
|
49
|
+
level: warn
|
|
50
|
+
message: "检测到 SELECT *,可能影响性能和可维护性"
|
|
51
|
+
suggestion: "显式列出需要的字段,避免传输不必要的数据"
|
|
52
|
+
operator_guidance: "SELECT * 传输所有列,增加网络开销;显式列出字段提升性能和可读性。"
|
|
53
|
+
tags: ["database", "performance"]
|
|
54
|
+
|
|
55
|
+
- id: "no-drop-production"
|
|
56
|
+
when: |
|
|
57
|
+
tool == "Bash"
|
|
58
|
+
&& args.command.lower().match(/drop\s+(database|table)/).ok()
|
|
59
|
+
&& (args.command.includes("prod") || args.command.includes("production"))
|
|
60
|
+
level: block
|
|
61
|
+
message: "禁止在生产环境执行 DROP 操作"
|
|
62
|
+
operator_guidance: "生产环境的 DROP 操作必须经过审批和备份;先在测试环境验证。"
|
|
63
|
+
tags: ["database", "production", "destructive"]
|
|
64
|
+
|
|
65
|
+
escalation: []
|
|
66
|
+
|
|
67
|
+
deliverables: []
|
|
68
|
+
|
|
69
|
+
principles: |
|
|
70
|
+
## 数据库安全规范
|
|
71
|
+
- 禁止 SQL 字符串拼接,使用参数化查询
|
|
72
|
+
- DELETE/UPDATE 必须带 WHERE 条件
|
|
73
|
+
- 避免 SELECT *,显式列出字段
|
|
74
|
+
- 生产环境禁止 DROP 操作
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
id: "docker-safety"
|
|
2
|
+
name: "Docker/容器安全规范"
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "容器化应用安全规则,覆盖镜像构建、运行时安全和资源管理"
|
|
5
|
+
triggers: ["docker", "dockerfile", "container", "镜像", "容器"]
|
|
6
|
+
|
|
7
|
+
variables:
|
|
8
|
+
dockerfile_patterns: ["Dockerfile", ".dockerfile"]
|
|
9
|
+
dangerous_base_images: ["latest", "alpine:latest"]
|
|
10
|
+
|
|
11
|
+
forbidden:
|
|
12
|
+
- id: "no-latest-tag"
|
|
13
|
+
when: |
|
|
14
|
+
tool.in(["Write", "Edit"])
|
|
15
|
+
&& file_path != null
|
|
16
|
+
&& (file_path.endsWith("Dockerfile") || file_path.includes("Dockerfile"))
|
|
17
|
+
&& (args.content ?? args.new_string ?? "").match(/FROM\s+[^:]+:latest/).ok()
|
|
18
|
+
level: warn
|
|
19
|
+
message: "Dockerfile 使用 :latest 标签,可能导致构建不可复现"
|
|
20
|
+
suggestion: "使用具体版本号,如 node:18.20.0-alpine"
|
|
21
|
+
operator_guidance: "latest 标签会随时间变化;固定版本号确保构建可复现。"
|
|
22
|
+
tags: ["docker", "reproducibility"]
|
|
23
|
+
|
|
24
|
+
- id: "warn-run-as-root"
|
|
25
|
+
when: |
|
|
26
|
+
tool.in(["Write", "Edit"])
|
|
27
|
+
&& file_path != null
|
|
28
|
+
&& (file_path.endsWith("Dockerfile") || file_path.includes("Dockerfile"))
|
|
29
|
+
&& !(args.content ?? args.new_string ?? "").match(/USER\s+\w+/).ok()
|
|
30
|
+
level: warn
|
|
31
|
+
message: "Dockerfile 未指定 USER,容器将以 root 运行"
|
|
32
|
+
suggestion: "添加 USER 指令切换到非 root 用户"
|
|
33
|
+
operator_guidance: "以 root 运行容器增加攻击面;创建专用用户并切换:RUN adduser -D appuser && USER appuser"
|
|
34
|
+
tags: ["docker", "security"]
|
|
35
|
+
|
|
36
|
+
- id: "no-apt-get-without-cleanup"
|
|
37
|
+
when: |
|
|
38
|
+
tool.in(["Write", "Edit"])
|
|
39
|
+
&& file_path != null
|
|
40
|
+
&& (file_path.endsWith("Dockerfile") || file_path.includes("Dockerfile"))
|
|
41
|
+
&& (args.content ?? args.new_string ?? "").match(/apt-get\s+install/).ok()
|
|
42
|
+
&& !(args.content ?? args.new_string ?? "").match(/rm\s+-rf\s+\/var\/lib\/apt\/lists/).ok()
|
|
43
|
+
level: warn
|
|
44
|
+
message: "apt-get install 后未清理缓存,会增大镜像体积"
|
|
45
|
+
suggestion: "在同一 RUN 层添加清理命令:&& rm -rf /var/lib/apt/lists/*"
|
|
46
|
+
operator_guidance: "每个 RUN 层都会保留文件系统快照;在同一层安装和清理可减小镜像体积。"
|
|
47
|
+
tags: ["docker", "optimization"]
|
|
48
|
+
|
|
49
|
+
- id: "warn-expose-sensitive-port"
|
|
50
|
+
when: |
|
|
51
|
+
tool.in(["Write", "Edit"])
|
|
52
|
+
&& file_path != null
|
|
53
|
+
&& (file_path.endsWith("Dockerfile") || file_path.includes("Dockerfile"))
|
|
54
|
+
&& (args.content ?? args.new_string ?? "").match(/EXPOSE\s+(22|3306|5432|6379|27017)/).ok()
|
|
55
|
+
level: warn
|
|
56
|
+
message: "Dockerfile 暴露敏感端口(SSH/数据库),可能存在安全风险"
|
|
57
|
+
suggestion: "确认是否需要暴露该端口,生产环境应通过网络策略限制访问"
|
|
58
|
+
tags: ["docker", "security"]
|
|
59
|
+
|
|
60
|
+
escalation: []
|
|
61
|
+
|
|
62
|
+
deliverables: []
|
|
63
|
+
|
|
64
|
+
principles: |
|
|
65
|
+
## Docker/容器安全规范
|
|
66
|
+
- 使用具体版本号而非 :latest 标签
|
|
67
|
+
- 容器应以非 root 用户运行
|
|
68
|
+
- apt-get install 后清理缓存减小镜像体积
|
|
69
|
+
- 避免暴露敏感端口(SSH、数据库)
|
|
@@ -17,6 +17,9 @@ forbidden:
|
|
|
17
17
|
level: block
|
|
18
18
|
message: "禁止强制推送到受保护分支 {{git.branch}}"
|
|
19
19
|
suggestion: "使用 --force-with-lease 或创建新分支后提交 PR"
|
|
20
|
+
operator_guidance: "公共分支改写历史会影响他人协作;优先通过新分支和 PR 完成修复。"
|
|
21
|
+
doc_ref: "CLAUDE.md#Git 操作安全规范"
|
|
22
|
+
tags: ["git", "protected-branch", "history-rewrite"]
|
|
20
23
|
|
|
21
24
|
- id: "warn-force-push-feature"
|
|
22
25
|
when: |
|
|
@@ -26,6 +29,9 @@ forbidden:
|
|
|
26
29
|
level: warn
|
|
27
30
|
message: "检测到 git push --force,这会覆盖远程历史"
|
|
28
31
|
suggestion: "考虑使用 --force-with-lease 以避免覆盖他人提交"
|
|
32
|
+
operator_guidance: "只有在确认远端无人基于该提交继续工作时,才考虑 force push。"
|
|
33
|
+
doc_ref: "CLAUDE.md#Git 操作安全规范"
|
|
34
|
+
tags: ["git", "force-push"]
|
|
29
35
|
|
|
30
36
|
- id: "no-reset-hard-uncommitted"
|
|
31
37
|
when: |
|
|
@@ -35,6 +41,9 @@ forbidden:
|
|
|
35
41
|
level: block
|
|
36
42
|
message: "禁止在有未提交更改时执行 git reset --hard"
|
|
37
43
|
suggestion: "先使用 git stash 保存更改,或提交后再 reset"
|
|
44
|
+
operator_guidance: "先用 git status 确认工作区,再 stash 或提交,避免本地未保存改动丢失。"
|
|
45
|
+
doc_ref: "CLAUDE.md#Git 操作安全规范"
|
|
46
|
+
tags: ["git", "reset-hard", "uncommitted-changes"]
|
|
38
47
|
|
|
39
48
|
- id: "warn-reset-hard"
|
|
40
49
|
when: |
|
|
@@ -43,6 +52,9 @@ forbidden:
|
|
|
43
52
|
level: confirm
|
|
44
53
|
message: "git reset --hard 会丢弃所有未提交的更改"
|
|
45
54
|
suggestion: "确认这是有意为之,或使用 git stash 保存更改"
|
|
55
|
+
operator_guidance: "执行前先确认 HEAD 目标和工作区状态,必要时先创建临时分支保存现场。"
|
|
56
|
+
doc_ref: "CLAUDE.md#Git 操作安全规范"
|
|
57
|
+
tags: ["git", "reset-hard"]
|
|
46
58
|
|
|
47
59
|
- id: "warn-clean-fd"
|
|
48
60
|
when: |
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
id: "go-best-practices"
|
|
2
|
+
name: "Go 最佳实践"
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "Go 开发规范,覆盖错误处理、并发安全、资源管理和性能"
|
|
5
|
+
triggers: ["go", "golang", "goroutine", "channel", "defer", "panic"]
|
|
6
|
+
|
|
7
|
+
variables:
|
|
8
|
+
go_file_patterns: [".go"]
|
|
9
|
+
dangerous_packages: ["unsafe", "reflect"]
|
|
10
|
+
max_function_lines: 50
|
|
11
|
+
|
|
12
|
+
forbidden:
|
|
13
|
+
- id: "no-panic-in-library"
|
|
14
|
+
when: |
|
|
15
|
+
tool.in(["Write", "Edit"])
|
|
16
|
+
&& file_ext == ".go"
|
|
17
|
+
&& !file_path.includes("_test.go")
|
|
18
|
+
&& (args.content ?? args.new_string ?? "").match(/\bpanic\(/).ok()
|
|
19
|
+
level: warn
|
|
20
|
+
message: "库代码中检测到 panic,应返回 error 而非 panic"
|
|
21
|
+
suggestion: "将 panic 改为返回 error,让调用方决定如何处理"
|
|
22
|
+
operator_guidance: "panic 应只用于不可恢复的错误;库代码应返回 error,由调用方处理。"
|
|
23
|
+
doc_ref: "https://go.dev/blog/error-handling-and-go"
|
|
24
|
+
tags: ["go", "error-handling"]
|
|
25
|
+
|
|
26
|
+
- id: "warn-goroutine-leak"
|
|
27
|
+
when: |
|
|
28
|
+
tool.in(["Write", "Edit"])
|
|
29
|
+
&& file_ext == ".go"
|
|
30
|
+
&& (args.content ?? args.new_string ?? "").match(/go\s+func\s*\(/).ok()
|
|
31
|
+
&& !(args.content ?? args.new_string ?? "").match(/context\./).ok()
|
|
32
|
+
level: warn
|
|
33
|
+
message: "检测到 goroutine 但未使用 context,可能导致泄漏"
|
|
34
|
+
suggestion: "传入 context.Context 参数,监听 ctx.Done() 以优雅退出"
|
|
35
|
+
operator_guidance: "goroutine 泄漏会耗尽资源;用 context 控制生命周期,监听 Done() 信号退出。"
|
|
36
|
+
doc_ref: "https://go.dev/blog/context"
|
|
37
|
+
tags: ["go", "concurrency", "resource-leak"]
|
|
38
|
+
|
|
39
|
+
- id: "no-defer-in-loop"
|
|
40
|
+
when: |
|
|
41
|
+
tool.in(["Write", "Edit"])
|
|
42
|
+
&& file_ext == ".go"
|
|
43
|
+
&& (args.content ?? args.new_string ?? "").match(/for\s+[^{]*\{[^}]*defer\s+/).ok()
|
|
44
|
+
level: warn
|
|
45
|
+
message: "检测到循环中使用 defer,会延迟到函数结束才执行"
|
|
46
|
+
suggestion: "将循环体提取为独立函数,或手动调用清理函数"
|
|
47
|
+
operator_guidance: "defer 在函数返回时执行,不是循环迭代结束;循环中的 defer 会累积,可能导致资源耗尽。"
|
|
48
|
+
doc_ref: "https://go.dev/ref/spec#Defer_statements"
|
|
49
|
+
tags: ["go", "defer", "resource-leak"]
|
|
50
|
+
|
|
51
|
+
- id: "warn-error-ignored"
|
|
52
|
+
when: |
|
|
53
|
+
tool.in(["Write", "Edit"])
|
|
54
|
+
&& file_ext == ".go"
|
|
55
|
+
&& (args.content ?? args.new_string ?? "").match(/\w+\([^)]*\)\s*$/).ok()
|
|
56
|
+
&& (args.content ?? args.new_string ?? "").match(/,\s*err\s*:=/).ok()
|
|
57
|
+
level: warn
|
|
58
|
+
message: "检测到可能未检查的 error 返回值"
|
|
59
|
+
suggestion: "显式检查 error:if err != nil { return err }"
|
|
60
|
+
operator_guidance: "Go 的错误处理依赖显式检查;忽略 error 会掩盖问题,用 if err != nil 立即处理。"
|
|
61
|
+
tags: ["go", "error-handling"]
|
|
62
|
+
|
|
63
|
+
- id: "no-unsafe-package"
|
|
64
|
+
when: |
|
|
65
|
+
tool.in(["Write", "Edit"])
|
|
66
|
+
&& file_ext == ".go"
|
|
67
|
+
&& (args.content ?? args.new_string ?? "").match(/import\s+.*"unsafe"/).ok()
|
|
68
|
+
level: warn
|
|
69
|
+
message: "检测到 unsafe 包,会绕过 Go 的类型安全"
|
|
70
|
+
suggestion: "除非性能关键场景,避免使用 unsafe"
|
|
71
|
+
operator_guidance: "unsafe 绕过类型安全和内存安全;只在性能瓶颈且充分测试后使用。"
|
|
72
|
+
tags: ["go", "safety"]
|
|
73
|
+
|
|
74
|
+
escalation: []
|
|
75
|
+
|
|
76
|
+
deliverables: []
|
|
77
|
+
|
|
78
|
+
principles: |
|
|
79
|
+
## Go 最佳实践
|
|
80
|
+
- 库代码返回 error 而非 panic
|
|
81
|
+
- goroutine 使用 context 控制生命周期
|
|
82
|
+
- 避免在循环中使用 defer
|
|
83
|
+
- 显式检查所有 error 返回值
|
|
84
|
+
- 谨慎使用 unsafe 包
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
id: "python-best-practices"
|
|
2
|
+
name: "Python 最佳实践"
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "Python 开发规范,覆盖代码风格、类型安全、安全性和性能"
|
|
5
|
+
triggers: ["python", "py", "pip", "django", "flask", "fastapi", "虚拟环境"]
|
|
6
|
+
|
|
7
|
+
variables:
|
|
8
|
+
python_file_patterns: [".py"]
|
|
9
|
+
dangerous_imports: ["pickle", "eval", "exec", "compile", "__import__"]
|
|
10
|
+
max_function_lines: 50
|
|
11
|
+
max_class_lines: 300
|
|
12
|
+
|
|
13
|
+
forbidden:
|
|
14
|
+
- id: "no-pickle-untrusted"
|
|
15
|
+
when: |
|
|
16
|
+
tool.in(["Write", "Edit"])
|
|
17
|
+
&& file_ext == ".py"
|
|
18
|
+
&& (args.content ?? args.new_string ?? "").match(/pickle\.loads?\(/).ok()
|
|
19
|
+
level: warn
|
|
20
|
+
message: "检测到 pickle.load/loads,反序列化不可信数据存在代码执行风险"
|
|
21
|
+
suggestion: "使用 JSON 或其他安全的序列化格式,避免 pickle 处理外部数据"
|
|
22
|
+
operator_guidance: "pickle 可以执行任意代码;只用于可信数据,外部数据优先用 JSON/MessagePack。"
|
|
23
|
+
doc_ref: "https://docs.python.org/3/library/pickle.html#module-pickle"
|
|
24
|
+
tags: ["python", "security", "deserialization"]
|
|
25
|
+
|
|
26
|
+
- id: "no-eval-exec"
|
|
27
|
+
when: |
|
|
28
|
+
tool.in(["Write", "Edit"])
|
|
29
|
+
&& file_ext == ".py"
|
|
30
|
+
&& (args.content ?? args.new_string ?? "").match(/\b(eval|exec)\s*\(/).ok()
|
|
31
|
+
level: block
|
|
32
|
+
message: "禁止使用 eval() 或 exec(),存在代码注入风险"
|
|
33
|
+
suggestion: "使用 ast.literal_eval() 解析字面量,或重新设计避免动态执行"
|
|
34
|
+
operator_guidance: "eval/exec 可执行任意代码;用 ast.literal_eval 安全解析,或用字典映射替代动态执行。"
|
|
35
|
+
doc_ref: "https://docs.python.org/3/library/ast.html#ast.literal_eval"
|
|
36
|
+
tags: ["python", "security", "code-injection"]
|
|
37
|
+
|
|
38
|
+
- id: "warn-bare-except"
|
|
39
|
+
when: |
|
|
40
|
+
tool.in(["Write", "Edit"])
|
|
41
|
+
&& file_ext == ".py"
|
|
42
|
+
&& (args.content ?? args.new_string ?? "").match(/except\s*:/).ok()
|
|
43
|
+
level: warn
|
|
44
|
+
message: "检测到裸 except:,会捕获所有异常包括 KeyboardInterrupt"
|
|
45
|
+
suggestion: "使用 except Exception: 或捕获具体异常类型"
|
|
46
|
+
operator_guidance: "裸 except 会捕获系统退出信号;用 except Exception 或具体异常类型。"
|
|
47
|
+
tags: ["python", "error-handling"]
|
|
48
|
+
|
|
49
|
+
- id: "warn-mutable-default-arg"
|
|
50
|
+
when: |
|
|
51
|
+
tool.in(["Write", "Edit"])
|
|
52
|
+
&& file_ext == ".py"
|
|
53
|
+
&& (args.content ?? args.new_string ?? "").match(/def\s+\w+\([^)]*=\s*(\[\]|\{\})\s*[,)]/).ok()
|
|
54
|
+
level: warn
|
|
55
|
+
message: "检测到可变默认参数([] 或 {}),会在调用间共享"
|
|
56
|
+
suggestion: "使用 None 作为默认值,在函数内部初始化"
|
|
57
|
+
operator_guidance: "可变默认参数只创建一次,多次调用会共享同一对象;用 None 并在函数内 if arg is None: arg = []"
|
|
58
|
+
doc_ref: "https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments"
|
|
59
|
+
tags: ["python", "correctness"]
|
|
60
|
+
|
|
61
|
+
- id: "no-shell-injection"
|
|
62
|
+
when: |
|
|
63
|
+
tool.in(["Write", "Edit"])
|
|
64
|
+
&& file_ext == ".py"
|
|
65
|
+
&& (args.content ?? args.new_string ?? "").match(/subprocess\.(call|run|Popen)\([^)]*shell\s*=\s*True/).ok()
|
|
66
|
+
level: warn
|
|
67
|
+
message: "检测到 subprocess 使用 shell=True,存在命令注入风险"
|
|
68
|
+
suggestion: "使用列表形式传递参数,避免 shell=True"
|
|
69
|
+
operator_guidance: "shell=True 会通过 shell 解析命令,存在注入风险;用列表传参:['ls', '-la']"
|
|
70
|
+
doc_ref: "https://docs.python.org/3/library/subprocess.html#security-considerations"
|
|
71
|
+
tags: ["python", "security", "command-injection"]
|
|
72
|
+
|
|
73
|
+
- id: "warn-requirements-no-version"
|
|
74
|
+
when: |
|
|
75
|
+
tool.in(["Write", "Edit"])
|
|
76
|
+
&& file_path != null
|
|
77
|
+
&& file_path.endsWith("requirements.txt")
|
|
78
|
+
&& (args.content ?? args.new_string ?? "").match(/^\w+\s*$/m).ok()
|
|
79
|
+
level: warn
|
|
80
|
+
message: "requirements.txt 中存在未固定版本的依赖"
|
|
81
|
+
suggestion: "使用 == 固定版本号,确保构建可复现"
|
|
82
|
+
operator_guidance: "未固定版本会导致不同环境安装不同版本;用 pip freeze 生成精确版本。"
|
|
83
|
+
tags: ["python", "dependency", "reproducibility"]
|
|
84
|
+
|
|
85
|
+
escalation: []
|
|
86
|
+
|
|
87
|
+
deliverables: []
|
|
88
|
+
|
|
89
|
+
principles: |
|
|
90
|
+
## Python 最佳实践
|
|
91
|
+
- 禁止 pickle 反序列化不可信数据
|
|
92
|
+
- 禁止 eval/exec 动态执行代码
|
|
93
|
+
- 使用 except Exception 而非裸 except
|
|
94
|
+
- 避免可变默认参数
|
|
95
|
+
- subprocess 避免 shell=True
|
|
96
|
+
- requirements.txt 固定依赖版本
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
id: "react-best-practices"
|
|
2
|
+
name: "React 最佳实践"
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "React/前端开发规范,覆盖组件设计、状态管理、性能优化和安全性"
|
|
5
|
+
triggers: ["react", "jsx", "tsx", "component", "hook", "useState", "useEffect", "组件", "前端"]
|
|
6
|
+
|
|
7
|
+
variables:
|
|
8
|
+
react_file_patterns: [".jsx", ".tsx"]
|
|
9
|
+
hook_names: ["useState", "useEffect", "useCallback", "useMemo", "useRef", "useContext", "useReducer"]
|
|
10
|
+
dangerous_html_props: ["dangerouslySetInnerHTML", "innerHTML"]
|
|
11
|
+
max_component_lines: 300
|
|
12
|
+
max_useEffect_deps: 5
|
|
13
|
+
|
|
14
|
+
forbidden:
|
|
15
|
+
- id: "no-dangerously-set-inner-html"
|
|
16
|
+
when: |
|
|
17
|
+
tool.in(["Write", "Edit"])
|
|
18
|
+
&& file_ext.in(vars.react_file_patterns)
|
|
19
|
+
&& (args.content ?? args.new_string ?? "").match(/dangerouslySetInnerHTML/).ok()
|
|
20
|
+
level: warn
|
|
21
|
+
message: "检测到 dangerouslySetInnerHTML,存在 XSS 风险"
|
|
22
|
+
suggestion: "使用 React 的默认转义机制,或使用 DOMPurify 清理 HTML"
|
|
23
|
+
operator_guidance: "dangerouslySetInnerHTML 绕过了 React 的 XSS 防护;如必须使用,需先用 DOMPurify.sanitize() 清理内容。"
|
|
24
|
+
doc_ref: "https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html"
|
|
25
|
+
tags: ["react", "xss", "security"]
|
|
26
|
+
|
|
27
|
+
- id: "no-inline-function-in-jsx"
|
|
28
|
+
when: |
|
|
29
|
+
tool.in(["Write", "Edit"])
|
|
30
|
+
&& file_ext.in(vars.react_file_patterns)
|
|
31
|
+
&& (args.content ?? args.new_string ?? "").match(/onClick=\{(?:\(\)|function)/).ok()
|
|
32
|
+
level: warn
|
|
33
|
+
message: "检测到 JSX 中的内联函数,可能导致不必要的重渲染"
|
|
34
|
+
suggestion: "使用 useCallback 包裹函数,或将函数提取到组件外"
|
|
35
|
+
operator_guidance: "每次渲染都会创建新函数引用,导致子组件不必要的重渲染;用 useCallback 缓存函数引用。"
|
|
36
|
+
tags: ["react", "performance"]
|
|
37
|
+
|
|
38
|
+
- id: "warn-missing-key-prop"
|
|
39
|
+
when: |
|
|
40
|
+
tool.in(["Write", "Edit"])
|
|
41
|
+
&& file_ext.in(vars.react_file_patterns)
|
|
42
|
+
&& (args.content ?? args.new_string ?? "").match(/\.map\([^)]*=>\s*<[A-Z]/).ok()
|
|
43
|
+
&& !(args.content ?? args.new_string ?? "").match(/key=/).ok()
|
|
44
|
+
level: warn
|
|
45
|
+
message: "检测到 map 渲染列表但可能缺少 key 属性"
|
|
46
|
+
suggestion: "为列表项添加唯一的 key 属性,避免使用数组索引"
|
|
47
|
+
operator_guidance: "key 帮助 React 识别哪些元素改变了;使用稳定的唯一标识符(如 id),不要用数组索引。"
|
|
48
|
+
doc_ref: "https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key"
|
|
49
|
+
tags: ["react", "performance", "correctness"]
|
|
50
|
+
|
|
51
|
+
- id: "warn-useEffect-missing-deps"
|
|
52
|
+
when: |
|
|
53
|
+
tool.in(["Write", "Edit"])
|
|
54
|
+
&& file_ext.in(vars.react_file_patterns)
|
|
55
|
+
&& (args.content ?? args.new_string ?? "").match(/useEffect\([^,]+,\s*\[\s*\]\s*\)/).ok()
|
|
56
|
+
level: warn
|
|
57
|
+
message: "检测到 useEffect 使用空依赖数组,可能遗漏依赖"
|
|
58
|
+
suggestion: "检查 effect 中使用的所有外部变量是否都在依赖数组中"
|
|
59
|
+
operator_guidance: "空依赖数组意味着 effect 只在挂载时运行一次;如果 effect 内部使用了 props/state,应添加到依赖数组。"
|
|
60
|
+
doc_ref: "https://react.dev/reference/react/useEffect#specifying-reactive-dependencies"
|
|
61
|
+
tags: ["react", "hooks", "correctness"]
|
|
62
|
+
|
|
63
|
+
- id: "no-direct-state-mutation"
|
|
64
|
+
when: |
|
|
65
|
+
tool.in(["Write", "Edit"])
|
|
66
|
+
&& file_ext.in(vars.react_file_patterns)
|
|
67
|
+
&& (args.content ?? args.new_string ?? "").match(/\bstate\.[a-zA-Z_]+\s*=/).ok()
|
|
68
|
+
level: block
|
|
69
|
+
message: "禁止直接修改 state,必须使用 setState"
|
|
70
|
+
suggestion: "使用 setState 或 useState 返回的 setter 函数更新状态"
|
|
71
|
+
operator_guidance: "直接修改 state 不会触发重渲染,且违反 React 的不可变性原则;始终通过 setState 更新。"
|
|
72
|
+
doc_ref: "https://react.dev/learn/updating-objects-in-state"
|
|
73
|
+
tags: ["react", "state", "correctness"]
|
|
74
|
+
|
|
75
|
+
escalation:
|
|
76
|
+
- id: "large-component-warning"
|
|
77
|
+
when: |
|
|
78
|
+
tool == "Write"
|
|
79
|
+
&& file_ext.in(vars.react_file_patterns)
|
|
80
|
+
&& (args.content ?? "").split("\n").length > vars.max_component_lines
|
|
81
|
+
action: warn
|
|
82
|
+
message: "组件超过 {{vars.max_component_lines}} 行,建议拆分"
|
|
83
|
+
suggestion: "将大组件拆分为多个小组件,提升可维护性"
|
|
84
|
+
operator_guidance: "大组件难以理解和测试;按功能或 UI 区域拆分,每个组件专注单一职责。"
|
|
85
|
+
tags: ["react", "maintainability"]
|
|
86
|
+
|
|
87
|
+
deliverables: []
|
|
88
|
+
|
|
89
|
+
principles: |
|
|
90
|
+
## React 最佳实践
|
|
91
|
+
- 禁止使用 dangerouslySetInnerHTML,防止 XSS 攻击
|
|
92
|
+
- 避免 JSX 中的内联函数,使用 useCallback 优化性能
|
|
93
|
+
- 列表渲染必须添加唯一 key,不使用数组索引
|
|
94
|
+
- useEffect 依赖数组必须完整,避免遗漏依赖
|
|
95
|
+
- 禁止直接修改 state,必须通过 setState 更新
|
|
96
|
+
- 组件超过 300 行时建议拆分
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/engine/dsl/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/engine/dsl/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,YAAY,CAAC;AA6DpB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,cAAc,CAAS;gBAEnB,cAAc,CAAC,EAAE,MAAM;IAWnC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IAkBvC,OAAO,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;IAyBlC,kBAAkB,CAChB,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GACtC,UAAU;IAiBb,OAAO,CAAC,gBAAgB;IAsDxB,OAAO,CAAC,cAAc;CAkBvB"}
|
|
@@ -18,6 +18,9 @@ const RuleSchema = z.object({
|
|
|
18
18
|
level: z.enum(['allow', 'warn', 'confirm', 'block']),
|
|
19
19
|
message: z.string(),
|
|
20
20
|
suggestion: z.string().optional(),
|
|
21
|
+
operator_guidance: z.string().optional(),
|
|
22
|
+
doc_ref: z.string().optional(),
|
|
23
|
+
tags: z.array(z.string()).optional(),
|
|
21
24
|
enabled: z.boolean().optional().default(true),
|
|
22
25
|
});
|
|
23
26
|
const EscalationRuleSchema = z.object({
|
|
@@ -26,6 +29,9 @@ const EscalationRuleSchema = z.object({
|
|
|
26
29
|
action: z.enum(['allow', 'warn', 'confirm', 'block']),
|
|
27
30
|
message: z.string(),
|
|
28
31
|
suggestion: z.string().optional(),
|
|
32
|
+
operator_guidance: z.string().optional(),
|
|
33
|
+
doc_ref: z.string().optional(),
|
|
34
|
+
tags: z.array(z.string()).optional(),
|
|
29
35
|
enabled: z.boolean().optional().default(true),
|
|
30
36
|
});
|
|
31
37
|
const DeliverableSchema = z.object({
|
|
@@ -33,7 +39,7 @@ const DeliverableSchema = z.object({
|
|
|
33
39
|
pattern: z.string().optional(),
|
|
34
40
|
command: z.string().optional(),
|
|
35
41
|
required: z.boolean(),
|
|
36
|
-
check_at: z.enum(['session_end', 'before_commit', 'on_demand']),
|
|
42
|
+
check_at: z.enum(['session_end', 'before_commit', 'on_demand', 'ci']),
|
|
37
43
|
condition: z.string().optional(),
|
|
38
44
|
});
|
|
39
45
|
const RuleOverrideSchema = z.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/engine/dsl/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,oBAAoB;AAEpB,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC9C,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACrD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC9C,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/engine/dsl/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,22 @@ export interface GovernanceDecision {
|
|
|
14
14
|
reason?: string;
|
|
15
15
|
suggestion?: string;
|
|
16
16
|
}
|
|
17
|
+
export interface RuleMetadata {
|
|
18
|
+
operator_guidance?: string;
|
|
19
|
+
doc_ref?: string;
|
|
20
|
+
tags?: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface MatchedRule extends RuleMetadata {
|
|
23
|
+
id: string;
|
|
24
|
+
level: DecisionLevel;
|
|
25
|
+
reason: string;
|
|
26
|
+
suggestion?: string;
|
|
27
|
+
source_convention: string;
|
|
28
|
+
}
|
|
29
|
+
export interface RuleEvaluationResult {
|
|
30
|
+
decision: GovernanceDecision;
|
|
31
|
+
matches: MatchedRule[];
|
|
32
|
+
}
|
|
17
33
|
export interface Convention {
|
|
18
34
|
id: string;
|
|
19
35
|
name: string;
|
|
@@ -34,6 +50,9 @@ export interface Rule {
|
|
|
34
50
|
level: DecisionLevel;
|
|
35
51
|
message: string;
|
|
36
52
|
suggestion?: string;
|
|
53
|
+
operator_guidance?: string;
|
|
54
|
+
doc_ref?: string;
|
|
55
|
+
tags?: string[];
|
|
37
56
|
enabled?: boolean;
|
|
38
57
|
}
|
|
39
58
|
export interface EscalationRule {
|
|
@@ -42,6 +61,9 @@ export interface EscalationRule {
|
|
|
42
61
|
action: DecisionLevel;
|
|
43
62
|
message: string;
|
|
44
63
|
suggestion?: string;
|
|
64
|
+
operator_guidance?: string;
|
|
65
|
+
doc_ref?: string;
|
|
66
|
+
tags?: string[];
|
|
45
67
|
enabled?: boolean;
|
|
46
68
|
}
|
|
47
69
|
export interface Deliverable {
|
|
@@ -49,7 +71,7 @@ export interface Deliverable {
|
|
|
49
71
|
pattern?: string;
|
|
50
72
|
command?: string;
|
|
51
73
|
required: boolean;
|
|
52
|
-
check_at: 'session_end' | 'before_commit' | 'on_demand';
|
|
74
|
+
check_at: 'session_end' | 'before_commit' | 'on_demand' | 'ci';
|
|
53
75
|
condition?: string;
|
|
54
76
|
}
|
|
55
77
|
export interface RuleOverride {
|
|
@@ -103,6 +125,9 @@ export interface CompiledRule {
|
|
|
103
125
|
level: DecisionLevel;
|
|
104
126
|
message: string;
|
|
105
127
|
suggestion?: string;
|
|
128
|
+
operator_guidance?: string;
|
|
129
|
+
doc_ref?: string;
|
|
130
|
+
tags?: string[];
|
|
106
131
|
evaluate: CompiledExpression;
|
|
107
132
|
render: (ctx: RuleContext) => string;
|
|
108
133
|
source_convention: string;
|