-
Notifications
You must be signed in to change notification settings - Fork 0
190 lines (165 loc) · 7.13 KB
/
Copy pathvalidate.yml
File metadata and controls
190 lines (165 loc) · 7.13 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# Security note: This workflow uses NO github.event.* inputs and NO ${{ ... }}
# interpolation in `run:` blocks. All dynamic values come from GitHub-provided
# safe env vars ($GITHUB_WORKSPACE) or hard-coded literals. No injection surface.
name: validate
on:
push:
branches: [main, dev]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
fast-tests:
name: Fast self-tests (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 5
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: '20'
- name: Plugin self-consistency (validate-anchor)
run: bash scripts/validate-anchor.sh
- name: Manifest validation (validate-manifests)
run: bash scripts/validate-manifests.sh
- name: Manifest negative fixtures
run: bash scripts/validate-manifests.sh --fixtures tests/manifest-fixtures
# Windows arm runs the curated core subset first release (spec §9); expand once
# proven stable — a flaky gate is worse than none.
- name: Command frontmatter negative fixtures
if: runner.os != 'Windows'
run: bash scripts/check-allowed-tools.sh --fixtures tests/command-fixtures
# Glob, not an enumerated list: a hardcoded list silently omits newly added
# tests (it had already omitted post-tool-use-tidy-fidelity.sh once).
# </dev/null: a hook that reads stdin must not inherit the runner's.
- name: Hook contracts (every tests/hook-contracts/*.sh)
shell: bash
run: |
set -euo pipefail
for t in tests/hook-contracts/*.sh; do
echo "=== $t"
bash "$t" </dev/null
done
- name: POSIX compatibility
if: runner.os != 'Windows'
run: bash tests/posix-compat.sh
- name: Windows compatibility (static invariants, all platforms)
run: bash tests/windows-compat.sh
- name: E2E fixture structural checks
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
FIXTURE_DIR=$(bash tests/e2e-cpp-fixture/bootstrap.sh)
echo "Fixture: $FIXTURE_DIR"
# Verify key files exist
for f in feature_list.json AGENTS.md init.sh PROJECT-TOC.md session-handoff.md progress.md .clang-format .clang-tidy CMakeLists.txt scripts/lint.sh scripts/sanitizer-build.sh; do
test -f "$FIXTURE_DIR/$f"
echo "OK $f present"
done
# Verify feature_list.json parses and validates
python3 -c "
import json, re, sys
with open('$FIXTURE_DIR/feature_list.json') as f:
data = json.load(f)
assert data.get('project'), 'missing project'
assert len(data.get('features', [])) == 3, 'expected 3 features'
for feat in data['features']:
for field in ['id', 'name', 'description', 'status', 'done_criteria']:
assert field in feat, f'missing {field} in {feat.get(\"id\")}'
assert re.match(r'^[a-z0-9][a-z0-9-]*$', feat['id']), f'bad id: {feat[\"id\"]}'
if feat['status'] == 'pass':
assert feat.get('evidence') is not None, f'{feat[\"id\"]} pass but evidence null'
print('OK feature_list.json valid')
"
- name: Context budget measurement
if: runner.os != 'Windows'
run: bash scripts/measure-context.sh
- name: Hook timing benchmark
if: runner.os != 'Windows'
run: bash tests/bench/hook-timing.sh
- name: cpp-detect — fixture coverage
shell: bash
run: |
set -euo pipefail
for fixture in cmake meson make bazel; do
echo "--- ${fixture}-fixture ---"
output=$(bash scripts/cpp-detect.sh --target "tests/cpp-detection/${fixture}-fixture")
echo "${output}" | python3 -m json.tool
EXPECTED_BS="${fixture}" \
python3 -c "
import json, sys, os
expected_bs = os.environ['EXPECTED_BS']
d = json.loads(sys.stdin.read())
assert d['is_cpp_project'] is True, f'{expected_bs}-fixture not detected as cpp project'
assert d['build_system'] == expected_bs, f'{expected_bs}-fixture wrong build_system: ' + d['build_system']
print(f'OK {expected_bs}-fixture: build_system={d[\"build_system\"]}')
" <<< "${output}"
done
- name: index-builder smoke test on temp repo
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
tmp=$(mktemp -d)
cd "${tmp}"
git init -q
git config user.email test@example.com
git config user.name test
echo "// main.c - hello" > main.c
git add -A
git commit -qm init
node "${GITHUB_WORKSPACE}/scripts/index-builder.mjs" --target .
test -f PROJECT-TOC.md
grep -q 'main.c' PROJECT-TOC.md
grep -q 'generated-at-commit' PROJECT-TOC.md
echo "OK index-builder smoke pass"
# Glob for the same reason as the hook-contracts step: enumeration rots.
- name: Script unit tests (every tests/unit/*.sh)
shell: bash
run: |
set -euo pipefail
for t in tests/unit/*.sh; do
echo "=== $t"
bash "$t" </dev/null
done
- name: cpp-detect — negative fixture (non-C/C++ stays dormant)
shell: bash
run: |
set -euo pipefail
out=$(bash scripts/cpp-detect.sh --target tests/cpp-detection/non-cpp-fixture)
echo "${out}" | python3 -m json.tool
echo "${out}" | python3 -c "import json,sys; d=json.load(sys.stdin); assert d['is_cpp_project'] is False, 'non-cpp-fixture wrongly detected as cpp'; print('OK non-cpp-fixture: is_cpp_project=false')"
- name: Skill-triggering coverage (structural, no LLM)
if: runner.os != 'Windows'
run: bash tests/skill-triggering/check-coverage.sh
shellcheck:
name: ShellCheck (lint shell scripts)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install shellcheck
run: sudo apt-get update && sudo apt-get install -y shellcheck
- name: Lint hooks + scripts + tests
shell: bash
run: |
set -uo pipefail
files=()
while IFS= read -r f; do files+=("$f"); done < <(find hooks -type f ! -name '*.json' ! -name '*.cmd'; find scripts tests -type f -name '*.sh'; find templates -type f -name '*.sh.tpl')
printf 'Linting %d files:\n' "${#files[@]}"; printf ' %s\n' "${files[@]}"
echo "== full findings, all levels (informational) =="
shellcheck --severity=style --exclude=SC1091 "${files[@]}" || true
echo "== gate: fail on warning-severity and above =="
shellcheck --severity=warning --exclude=SC1091 "${files[@]}"