-
Notifications
You must be signed in to change notification settings - Fork 11
151 lines (141 loc) · 6.01 KB
/
Copy pathcontent-validation.yaml
File metadata and controls
151 lines (141 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
name: Content Validation
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'scripts/**'
pull_request:
branches: [main]
paths:
- 'docs/**'
- 'scripts/**'
workflow_dispatch:
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout docs repo
uses: actions/checkout@v4
- name: Checkout PACK-personal repo
uses: actions/checkout@v4
with:
repository: aisystant/PACK-personal
path: PACK-personal
token: ${{ secrets.PACK_READ_TOKEN || secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install pyyaml python-frontmatter
- name: Markdown lint (validate.py)
run: |
python3 scripts/convert_word/validate.py docs/ru/personal-design/
- name: Ontology drift check
run: |
python3 scripts/sync-guide-to-ontology.py --check \
--ontology PACK-personal/ontology.md \
--guides docs/ru/personal-design/
env:
PYTHONPATH: ${{ github.workspace }}
- name: Broken cross-repo link detection
run: |
echo "Checking for broken ../../../PACK-personal/ontology.md# links..."
python3 << 'EOF'
import os, re
ontology_path = "PACK-personal/ontology.md"
if not os.path.exists(ontology_path):
print("⚠️ SKIP: PACK-personal/ontology.md not found — link check skipped")
exit(0)
# Build set of anchors from ontology headings
anchors = set()
with open(ontology_path, "r", encoding="utf-8") as fh:
for line in fh:
m = re.match(r"^(#{1,6})\s+(.+)$", line)
if m:
heading = m.group(2).strip()
# GitHub-style anchor: lowercase, spaces->-, remove punctuation
anchor = heading.lower().replace(" ", "-")
anchor = re.sub(r"[^\w\-]", "", anchor)
anchors.add(anchor)
errors = []
for root, dirs, files in os.walk("docs/ru/personal-design"):
for f in files:
if not f.endswith(".md"):
continue
path = os.path.join(root, f)
with open(path, "r", encoding="utf-8") as fh:
content = fh.read()
for match in re.finditer(r'\.\./\.\./\.\./PACK-personal/ontology\.md#([^ )\]]+)', content):
link_anchor = match.group(1)
# Normalize anchor
normalized = link_anchor.lower().replace("%20", "-").replace(" ", "-")
normalized = re.sub(r"[^\w\-]", "", normalized)
if normalized not in anchors:
errors.append(f"{path}: broken anchor '#{link_anchor}'")
if errors:
print("❌ FAIL: Broken cross-repo links found:")
for e in errors:
print(f" - {e}")
exit(1)
else:
print("✅ PASS: No broken cross-repo links found")
EOF
- name: Frontmeta completeness check
run: |
python3 << 'EOF'
import os, re, yaml
errors = []
required_fields = [
"title", "order", "introduces", "uses", "prerequisites",
"can_do", "cp_check", "bh_check", "format_version",
"pack_refs", "time_reading", "time_practice",
"word_count_target", "status"
]
for root, dirs, files in os.walk("docs/ru/personal-design"):
for f in files:
if not f.endswith(".md"):
continue
# Пропускаем index.md и файлы без subsection-семантики
if f == "index.md":
continue
path = os.path.join(root, f)
with open(path, "r", encoding="utf-8") as fh:
content = fh.read()
m = re.match(r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL)
if not m:
# Файлы без frontmatter — не подразделы, пропускаем
continue
try:
fm = yaml.safe_load(m.group(1)) or {}
except Exception as e:
errors.append(f"{path}: invalid YAML: {e}")
continue
# Проверяем только файлы с 'introduces' — это подразделы v4
if "introduces" not in fm:
continue
missing = [field for field in required_fields if field not in fm]
if missing:
errors.append(f"{path}: missing fields: {', '.join(missing)}")
if errors:
print("❌ Frontmatter completeness FAIL:")
for e in errors:
print(f" - {e}")
exit(1)
else:
print("✅ Frontmatter completeness PASS")
EOF
- name: Didactic language check (UB-1)
run: |
echo "Checking for didactic language (UB-1)..."
# Проверяем docs/ru/personal-design/ на запрещённые слова
# «шаг» и «step» — легитимные слова в блоке «Минимальный шаг», исключены.
# «урок», «внедрить», «за N дней», «lesson», «implement» — признаки дидактики.
PATTERNS="урок|внедрить|за [0-9]+ дней|implement|lesson"
if grep -riE "$PATTERNS" docs/ru/personal-design/; then
echo "⚠️ WARN: Potential didactic language found (see above). Review manually."
else
echo "✅ PASS: No didactic language detected"
fi