dev-playbooks-cn 2.2.1 → 2.3.1

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +1 -0
  3. package/package.json +1 -1
  4. package/scripts/benchmark-scan.sh +67 -0
  5. package/scripts/detect-fancy-words.sh +7 -0
  6. package/skills/_shared/references/AI/350/241/214/344/270/272/350/247/204/350/214/203.md +20 -1
  7. package/skills/_shared/references//344/270/223/345/256/266/345/210/227/350/241/250.md +21 -0
  8. package/skills/_shared/references//345/256/214/345/244/207/346/200/247/346/200/235/347/273/264/346/241/206/346/236/266.md +89 -0
  9. package/skills/devbooks-archiver/SKILL.md +16 -5
  10. package/skills/devbooks-brownfield-bootstrap/SKILL.md +4 -38
  11. package/skills/devbooks-coder/SKILL.md +1 -1
  12. package/skills/devbooks-convergence-audit/SKILL.md +1 -0
  13. package/skills/devbooks-delivery-workflow/SKILL.md +3 -14
  14. package/skills/devbooks-delivery-workflow/scripts/change-check.sh +8 -0
  15. package/skills/devbooks-delivery-workflow/scripts/guardrail-check.sh +39 -10
  16. package/skills/devbooks-design-backport/SKILL.md +2 -4
  17. package/skills/devbooks-design-doc/SKILL.md +5 -3
  18. package/skills/devbooks-docs-consistency/SKILL.md +155 -0
  19. package/skills/devbooks-docs-consistency/references/completeness-dimensions.yaml +25 -0
  20. package/skills/devbooks-docs-consistency/references/doc-classification.yaml +11 -0
  21. package/skills/devbooks-docs-consistency/references/docs-rules-schema.yaml +11 -0
  22. package/skills/devbooks-docs-consistency/scripts/alias.sh +5 -0
  23. package/skills/devbooks-docs-consistency/scripts/completeness-checker.sh +153 -0
  24. package/skills/devbooks-docs-consistency/scripts/doc-classifier.sh +121 -0
  25. package/skills/devbooks-docs-consistency/scripts/git-adapter.sh +32 -0
  26. package/skills/devbooks-docs-consistency/scripts/rules-engine.sh +255 -0
  27. package/skills/devbooks-docs-consistency/scripts/scanner.sh +93 -0
  28. package/skills/devbooks-docs-consistency/scripts/style-checker.sh +123 -0
  29. package/skills/devbooks-entropy-monitor/SKILL.md +3 -35
  30. package/skills/devbooks-impact-analysis/SKILL.md +3 -38
  31. package/skills/devbooks-implementation-plan/SKILL.md +2 -4
  32. package/skills/devbooks-proposal-author/SKILL.md +7 -3
  33. package/skills/devbooks-proposal-challenger/SKILL.md +2 -4
  34. package/skills/devbooks-proposal-judge/SKILL.md +2 -4
  35. package/skills/devbooks-reviewer/SKILL.md +3 -36
  36. package/skills/devbooks-router/SKILL.md +5 -35
  37. package/skills/devbooks-spec-contract/SKILL.md +3 -34
  38. package/skills/devbooks-test-owner/SKILL.md +2 -3
  39. package/skills/devbooks-test-reviewer/SKILL.md +2 -3
  40. package/skills/devbooks-docs-sync/SKILL.md +0 -338
@@ -0,0 +1,155 @@
1
+ ---
2
+ name: devbooks-docs-consistency
3
+ description: devbooks-docs-consistency:检查并维护项目文档与代码的一致性,支持增量扫描、自定义规则与完备性检查。可在变更包内按需运行或全局检查。旧名称 devbooks-docs-sync 保留为别名并输出弃用提示。
4
+ recommended_experts: ["Technical Writer", "System Architect"]
5
+ allowed-tools:
6
+ - Glob
7
+ - Grep
8
+ - Read
9
+ - Edit
10
+ - Write
11
+ - Bash
12
+ ---
13
+
14
+ # DevBooks:文档一致性(Docs Consistency)
15
+
16
+ ## 前置:配置发现(协议无关)
17
+
18
+ 执行前**必须**按以下顺序查找配置(找到后停止):
19
+ 1. `.devbooks/config.yaml`(如存在)→ 解析并使用其中的映射
20
+ 2. `dev-playbooks/project.md`(如存在)→ Dev-Playbooks 协议,使用默认映射
21
+ 3. `project.md`(如存在)→ template 协议,使用默认映射
22
+ 4. 若仍无法确定 → **停止并询问用户**
23
+
24
+ ---
25
+
26
+ ## 兼容与弃用
27
+
28
+ - 旧名称:`devbooks-docs-sync`
29
+ - 当前名称:`devbooks-docs-consistency`
30
+ - 行为:旧名称作为别名继续可用,并输出弃用提示。
31
+ - 运行提示:别名通过软链接指向新目录,可执行 `scripts/alias.sh` 输出提示。
32
+
33
+ 弃用提示示例:
34
+
35
+ ```
36
+ devbooks-docs-sync 已弃用,请使用 devbooks-docs-consistency。
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 角色定义
42
+
43
+ **docs-consistency** 是 DevBooks Apply 阶段的文档一致性检查角色,负责识别文档与代码之间的偏差并生成报告,不直接修改代码。
44
+
45
+ ### 文档分类
46
+
47
+ | 文档类型 | 目标受众 | 是否由本 Skill 检查 | 示例 |
48
+ |----------|----------|:-------------------:|------|
49
+ | **活体文档** | 最终用户 | ✅ | README.md, docs/*.md, API.md |
50
+ | **历史文档** | 最终用户 | ⚠️(只做最低限度检查) | CHANGELOG.md |
51
+ | **概念性文档** | 设计/架构 | ✅(结构性检查) | architecture/*.md |
52
+
53
+ 分类规则可配置,默认规则见 `references/doc-classification.yaml`。
54
+
55
+ ---
56
+
57
+ ## 运行模式
58
+
59
+ ### 模式一:增量扫描(Change-Scoped)
60
+
61
+ **触发条件**:在变更包上下文中运行。
62
+
63
+ **行为**:
64
+ 1. 读取变更范围
65
+ 2. 仅扫描变更文件
66
+ 3. 记录 token 消耗与扫描时间
67
+ 4. 输出检查报告
68
+
69
+ ### 模式二:全量扫描(Global Check)
70
+
71
+ **触发条件**:用户显式请求全局检查(如 `devbooks-docs-consistency --global`)。
72
+
73
+ **行为**:
74
+ 1. 扫描所有用户文档
75
+ 2. 生成差异报告
76
+ 3. 输出改进建议
77
+
78
+ ### 模式三:检查模式(Check Only)
79
+
80
+ **触发条件**:用户使用 `--check` 参数。
81
+
82
+ **行为**:只检查、不修改,输出报告。
83
+
84
+ ---
85
+
86
+ ## 命令示例
87
+
88
+ ```
89
+ # 规则引擎:持续规则
90
+ bash scripts/rules-engine.sh --rules references/docs-rules-schema.yaml --input README.md
91
+
92
+ # 规则引擎:一次性任务
93
+ bash scripts/rules-engine.sh --once "remove:@augment" --input README.md
94
+
95
+ # 文档分类
96
+ bash scripts/doc-classifier.sh README.md
97
+
98
+ # 完备性检查
99
+ bash scripts/completeness-checker.sh --input README.md --config references/completeness-dimensions.yaml --output evidence/completeness-report.md
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 完备性检查
105
+
106
+ 对活体文档执行完备性检查,默认覆盖:环境依赖、安全权限、故障排查、配置说明、API 文档。
107
+
108
+ - 维度配置:`references/completeness-dimensions.yaml`
109
+ - 报告输出:`<change-root>/<change-id>/evidence/completeness-report.md`
110
+ - 方法论参考:[完备性思维框架](../_shared/references/完备性思维框架.md)
111
+
112
+ ---
113
+
114
+ ## 风格偏好
115
+
116
+ 风格偏好读取优先级:命令行参数 > 配置文件 > 默认值。
117
+
118
+ - 文档维护元数据:`dev-playbooks/specs/_meta/docs-maintenance.md`
119
+
120
+ ---
121
+
122
+ ## 输出与报告
123
+
124
+ 默认输出以下报告(变更包上下文):
125
+
126
+ - `evidence/completeness-report.md`
127
+ - `evidence/token-usage.log`
128
+ - `evidence/scan-performance.log`
129
+
130
+ ---
131
+
132
+ ## 与工作流的集成
133
+
134
+ 在归档阶段由 `devbooks-archiver` 触发,在存量初始化时由 `devbooks-brownfield-bootstrap` 生成文档维护元数据。
135
+
136
+ ---
137
+
138
+ ## MCP 说明
139
+
140
+ 本 Skill 不依赖 MCP 服务,无需运行时检测。
141
+
142
+ ---
143
+
144
+ ## 元数据
145
+
146
+ | 字段 | 值 |
147
+ |------|-----|
148
+ | Skill 名称 | devbooks-docs-consistency |
149
+ | 阶段 | Apply(实现后、归档前) |
150
+ | 产物 | 文档一致性检查报告 |
151
+ | 约束 | 只检查、不修改代码 |
152
+
153
+ ---
154
+
155
+ *此 Skill 文档遵循 devbooks-* 规范。*
@@ -0,0 +1,25 @@
1
+ - name: 环境依赖
2
+ patterns:
3
+ - "Node.js"
4
+ - "Python"
5
+ - "依赖"
6
+ - name: 安全权限
7
+ patterns:
8
+ - "权限"
9
+ - "安全"
10
+ - "密钥"
11
+ - name: 故障排查
12
+ patterns:
13
+ - "故障"
14
+ - "排查"
15
+ - "Troubleshooting"
16
+ - name: 配置说明
17
+ patterns:
18
+ - "配置"
19
+ - "config"
20
+ - "配置文件"
21
+ - name: API 文档
22
+ patterns:
23
+ - "API"
24
+ - "接口"
25
+ - "Endpoint"
@@ -0,0 +1,11 @@
1
+ living_docs:
2
+ - "README.md"
3
+ - "docs/**/*.md"
4
+ - "API.md"
5
+ - "docs/*.md"
6
+ history_docs:
7
+ - "CHANGELOG.md"
8
+ - "**/CHANGELOG.md"
9
+ concept_docs:
10
+ - "architecture/*.md"
11
+ - "architecture/**/*.md"
@@ -0,0 +1,11 @@
1
+ rules:
2
+ - id: forbid-smart
3
+ type: persistent
4
+ target: content
5
+ action: check
6
+ pattern: "智能"
7
+ - id: remove-augment
8
+ type: once
9
+ target: content
10
+ action: remove
11
+ pattern: "@augment"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ echo "devbooks-docs-sync 已弃用,请使用 devbooks-docs-consistency。" >&2
5
+ exit 0
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'EOF'
6
+ Usage: completeness-checker.sh --input <file> --config <dimensions.yaml> [--output <report>]
7
+ EOF
8
+ }
9
+
10
+ INPUT_PATH=""
11
+ CONFIG_PATH=""
12
+ OUTPUT_PATH=""
13
+
14
+ while [[ $# -gt 0 ]]; do
15
+ case "$1" in
16
+ --input)
17
+ INPUT_PATH="$2"
18
+ shift 2
19
+ ;;
20
+ --config)
21
+ CONFIG_PATH="$2"
22
+ shift 2
23
+ ;;
24
+ --output)
25
+ OUTPUT_PATH="$2"
26
+ shift 2
27
+ ;;
28
+ -h|--help)
29
+ usage
30
+ exit 0
31
+ ;;
32
+ *)
33
+ echo "Unknown argument: $1" >&2
34
+ usage >&2
35
+ exit 2
36
+ ;;
37
+ esac
38
+ done
39
+
40
+ if [[ -z "$INPUT_PATH" || -z "$CONFIG_PATH" ]]; then
41
+ echo "Missing --input or --config" >&2
42
+ usage >&2
43
+ exit 2
44
+ fi
45
+
46
+ if [[ ! -f "$INPUT_PATH" ]]; then
47
+ echo "input not found: $INPUT_PATH" >&2
48
+ exit 2
49
+ fi
50
+
51
+ if [[ ! -f "$CONFIG_PATH" ]]; then
52
+ echo "config not found: $CONFIG_PATH" >&2
53
+ exit 2
54
+ fi
55
+
56
+ report_line() {
57
+ local name="$1"
58
+ local ok="$2"
59
+ local msg="$3"
60
+ if [[ "$ok" == "1" ]]; then
61
+ printf "- %s: ✓ %s\n" "$name" "$msg"
62
+ else
63
+ printf "- %s: ✗ %s\n" "$name" "$msg"
64
+ fi
65
+ }
66
+
67
+ read_dimension_patterns() {
68
+ local key="$1"
69
+ python3 - "$CONFIG_PATH" "$key" <<'PY'
70
+ import sys
71
+
72
+ config_path = sys.argv[1]
73
+ target = sys.argv[2]
74
+ patterns = []
75
+ current = None
76
+ collecting = False
77
+
78
+ with open(config_path, "r", encoding="utf-8") as fh:
79
+ for raw in fh:
80
+ line = raw.rstrip("\n")
81
+ stripped = line.strip()
82
+ if stripped.startswith("- name:"):
83
+ current = stripped.split(":", 1)[1].strip()
84
+ collecting = False
85
+ continue
86
+ if current == target and stripped.startswith("patterns:"):
87
+ collecting = True
88
+ continue
89
+ if collecting:
90
+ if stripped.startswith("-"):
91
+ value = stripped.lstrip("-").strip().strip('"')
92
+ if value:
93
+ patterns.append(value)
94
+ elif stripped and not stripped.startswith("#"):
95
+ collecting = False
96
+
97
+ for item in patterns:
98
+ print(item)
99
+ PY
100
+ }
101
+
102
+ dimensions=()
103
+ while IFS= read -r line; do
104
+ dimensions+=("$line")
105
+ done < <(python3 - "$CONFIG_PATH" <<'PY'
106
+ import sys
107
+
108
+ config_path = sys.argv[1]
109
+ with open(config_path, "r", encoding="utf-8") as fh:
110
+ for raw in fh:
111
+ stripped = raw.strip()
112
+ if stripped.startswith("- name:"):
113
+ print(stripped.split(":", 1)[1].strip())
114
+ PY
115
+ )
116
+
117
+ if [[ "${#dimensions[@]}" -eq 0 ]]; then
118
+ echo "no dimensions defined" >&2
119
+ exit 2
120
+ fi
121
+
122
+ output=""
123
+ output+="# 完备性检查报告\n\n"
124
+
125
+ for dim in "${dimensions[@]}"; do
126
+ ok=0
127
+ msg=""
128
+ patterns=()
129
+ while IFS= read -r line; do
130
+ patterns+=("$line")
131
+ done < <(read_dimension_patterns "$dim")
132
+ if [[ "${#patterns[@]}" -eq 0 ]]; then
133
+ msg="无匹配规则"
134
+ else
135
+ for pattern in "${patterns[@]}"; do
136
+ if grep -q "$pattern" "$INPUT_PATH"; then
137
+ ok=1
138
+ msg="命中: $pattern"
139
+ break
140
+ fi
141
+ done
142
+ if [[ "$ok" -eq 0 ]]; then
143
+ msg="缺少: ${patterns[*]}"
144
+ fi
145
+ fi
146
+ output+="$(report_line "$dim" "$ok" "$msg")"$'\n'
147
+ done
148
+
149
+ if [[ -n "$OUTPUT_PATH" ]]; then
150
+ printf "%b" "$output" > "$OUTPUT_PATH"
151
+ else
152
+ printf "%b" "$output"
153
+ fi
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ DEFAULT_RULES="${SCRIPT_DIR}/../references/doc-classification.yaml"
6
+
7
+ RULES_PATH="${DOC_CLASSIFICATION_RULES:-$DEFAULT_RULES}"
8
+ DOC_PATH="${1:-}"
9
+
10
+ if [[ -z "$DOC_PATH" ]]; then
11
+ echo "usage: doc-classifier.sh <path>" >&2
12
+ exit 2
13
+ fi
14
+
15
+ if [[ ! -f "$RULES_PATH" ]]; then
16
+ echo "rules file not found: $RULES_PATH" >&2
17
+ exit 2
18
+ fi
19
+
20
+ normalize_path() {
21
+ local input="$1"
22
+ echo "${input#./}"
23
+ }
24
+
25
+ collect_patterns() {
26
+ local key="$1"
27
+ python3 - "$RULES_PATH" "$key" <<'PY'
28
+ import sys
29
+
30
+ rules_path = sys.argv[1]
31
+ key = sys.argv[2]
32
+ patterns = []
33
+ collecting = False
34
+
35
+ with open(rules_path, "r", encoding="utf-8") as fh:
36
+ for raw in fh:
37
+ line = raw.rstrip("\n")
38
+ if line.startswith(f"{key}:"):
39
+ collecting = True
40
+ continue
41
+ if collecting:
42
+ stripped = line.strip()
43
+ if not stripped.startswith("-"):
44
+ if stripped and not stripped.startswith("#"):
45
+ collecting = False
46
+ elif not stripped:
47
+ continue
48
+ if stripped.startswith("-"):
49
+ value = stripped.lstrip("-").strip()
50
+ if value.startswith("\"") and value.endswith("\""):
51
+ value = value[1:-1]
52
+ if value:
53
+ patterns.append(value)
54
+
55
+ for item in patterns:
56
+ print(item)
57
+ PY
58
+ }
59
+
60
+ matches_pattern() {
61
+ local path="$1"
62
+ local pattern="$2"
63
+ python3 - "$path" "$pattern" <<'PY'
64
+ import sys
65
+ from pathlib import PurePosixPath
66
+
67
+ path = PurePosixPath(sys.argv[1])
68
+ pattern = sys.argv[2]
69
+ print("1" if path.match(pattern) else "0")
70
+ PY
71
+ }
72
+
73
+ doc_path=$(normalize_path "$DOC_PATH")
74
+
75
+ living_patterns=()
76
+ history_patterns=()
77
+ concept_patterns=()
78
+ while IFS= read -r line; do
79
+ living_patterns+=("$line")
80
+ done < <(collect_patterns "living_docs")
81
+ while IFS= read -r line; do
82
+ history_patterns+=("$line")
83
+ done < <(collect_patterns "history_docs")
84
+ while IFS= read -r line; do
85
+ concept_patterns+=("$line")
86
+ done < <(collect_patterns "concept_docs")
87
+
88
+ match_types=()
89
+
90
+ for pattern in "${living_patterns[@]:-}"; do
91
+ if [[ -n "$pattern" && $(matches_pattern "$doc_path" "$pattern") == "1" ]]; then
92
+ match_types+=("living")
93
+ break
94
+ fi
95
+ done
96
+
97
+ for pattern in "${history_patterns[@]:-}"; do
98
+ if [[ -n "$pattern" && $(matches_pattern "$doc_path" "$pattern") == "1" ]]; then
99
+ match_types+=("history")
100
+ break
101
+ fi
102
+ done
103
+
104
+ for pattern in "${concept_patterns[@]:-}"; do
105
+ if [[ -n "$pattern" && $(matches_pattern "$doc_path" "$pattern") == "1" ]]; then
106
+ match_types+=("concept")
107
+ break
108
+ fi
109
+ done
110
+
111
+ if [[ "${#match_types[@]}" -eq 0 ]]; then
112
+ echo "unknown"
113
+ exit 0
114
+ fi
115
+
116
+ if [[ "${#match_types[@]}" -gt 1 ]]; then
117
+ echo "conflict: ${match_types[*]}"
118
+ exit 0
119
+ fi
120
+
121
+ echo "${match_types[0]}"
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ command="${1:-}"
5
+
6
+ if [[ -z "$command" ]]; then
7
+ echo "usage: git-adapter.sh <getChangedFiles|getDiff> [ref]" >&2
8
+ exit 2
9
+ fi
10
+
11
+ case "$command" in
12
+ getChangedFiles)
13
+ ref="${2:-HEAD~1}"
14
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
15
+ echo "git not available" >&2
16
+ exit 1
17
+ fi
18
+ git diff --name-only "$ref"
19
+ ;;
20
+ getDiff)
21
+ ref="${2:-HEAD~1}"
22
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
23
+ echo "git not available" >&2
24
+ exit 1
25
+ fi
26
+ git diff "$ref"
27
+ ;;
28
+ *)
29
+ echo "unknown command: $command" >&2
30
+ exit 2
31
+ ;;
32
+ esac