-
-
Notifications
You must be signed in to change notification settings - Fork 11
184 lines (174 loc) · 8.5 KB
/
Copy pathchecks.yml
File metadata and controls
184 lines (174 loc) · 8.5 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
# Fast governance checks (pipeline Phase 1+). Pure bash, no toolchain —
# feedback in seconds, long before the build workflows finish.
#
# Jobs:
# doctor — enforces "every pipeline asset registers a ./dev verb or carries
# a reasoned exemption" (see scripts/doctor for the contract).
# lint — the NeoHaskell dialect gate: hlint with the dialect-first
# .hlint.yaml (vanilla-module restrictions, banned partials,
# teaching hints). Standalone pinned binary — no nix needed.
name: checks
on:
pull_request:
# ready_for_review included so the spec job's drift gate fires the moment
# a draft (parked spec) is promoted — default types would miss the flip
types: [opened, synchronize, reopened, ready_for_review]
push:
branches: [main]
permissions:
contents: read
concurrency:
group: checks-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
doctor:
name: dev doctor (verb registration)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- run: ./dev doctor
# Static workflow wiring: hidden-artifact upload opt-in + retrospect
# loop stays deterministic/report-only (pure stdlib, no toolchain).
- run: ./dev workflow-check
# ADR-0075 process docs are triplicated by design (formula/skill/ADR
# each self-contained); this catches them drifting apart.
- run: ./dev process-check
secrets:
name: secret scan (gitleaks, deterministic)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Pinned binary, not gitleaks-action (the action needs an org license).
# Scans the working tree, not git history: deterministic on the state
# being merged, no permanent red from historical noise. --redact keeps
# any finding out of public CI logs. ADR-0075: deterministic checks
# live here; agents (verify V9) only check what needs judgment.
- name: Install gitleaks (pinned + checksum)
run: |
curl -sSfL -o gitleaks.tar.gz https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz
echo "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb gitleaks.tar.gz" | sha256sum -c -
tar -xzf gitleaks.tar.gz gitleaks
- run: ./gitleaks dir . --redact --no-banner --exit-code 1
codemap:
name: codemap check (localization ontology)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Same check.py as ./dev codemap-check; runner python + pinned pyyaml
# (pulling the full nix dev shell for a YAML check is not worth 40m —
# the PYTHON override is the sanctioned CI path, like lint's HLINT=).
- run: python3 -c "import yaml" 2>/dev/null || pip3 install pyyaml==6.0.3
- run: PYTHON=python3 ./dev codemap-check
adr-index:
name: adr index (decisions README faithful)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Pure-stdlib python check: every docs/decisions/NNNN-*.md is indexed
# exactly once with a status matching its own `## Status` section.
- run: ./dev adr-check
# Drift gate: the website ADR pages are generated from that same
# (now-audited) index by website/scripts/generate-adrs.mjs (Node, on the
# runner's default toolchain — no pnpm install, the generator is zero-dep).
# Regenerates the gitignored per-ADR pages (proving each still transcribes)
# and fails if the tracked landing page was hand-edited or left stale.
- run: ./dev adr-website --check
spec:
name: spec check (contract-delta gate)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# spec-drift --pr diffs against the merge base — needs history
fetch-depth: 0
# Structure gate: every committed spec (incl. TEMPLATE.md, which is a
# validated instance) parses and machine-joins. Runs on drafts too —
# this is what the maintainer's gate decision reads.
- run: ./dev spec-check
# Drift gate: at PR-READY only, the specs this PR touches must be
# honored by the generated API surface (codemap-sync proves committed
# signatures == code; this proves signatures == promise). A draft is
# still implementing its spec — drift there is expected, not an error.
- name: Spec drift (PR-ready only)
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
env:
# env-var indirection, not inline ${{ }} in run: — the standard
# template-injection defense-in-depth for workflow expressions
BASE_REF: ${{ github.base_ref }}
run: ./dev spec-drift --pr "origin/${BASE_REF}"
# Review-record gate: at PR-ready, every COMMITTED design review a changed
# spec ROUTES (touches ∩ perf-sensitive) must have its committed record.
# Security reviews are local-only (gitignored, never pushed — they map
# attack surface; ADR-0069), enforced on the dev machine via
# `spec-check --reviews-local`, so CI's --reviews-pr gates only perf.
- name: Design-review records present (PR-ready only)
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
env:
BASE_REF: ${{ github.base_ref }}
run: ./dev spec-check --reviews-pr "origin/${BASE_REF}"
# Changelog gate: at PR-ready, every changed spec must have a CHANGELOG.md
# entry (breaking ones with a migration note) — the changelog is generated,
# not hand-written (Phase 6, task 3).
- name: Changelog entries present (PR-ready only)
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
env:
BASE_REF: ${{ github.base_ref }}
run: ./dev changelog --check "origin/${BASE_REF}"
# DoD criterion-test gate: at PR-ready, every criterion in a changed spec
# must name a proving test that RESOLVES (a real .hurl or *.hs spec module)
# — a criterion can't cite a test that was never written (Phase 6, task 1).
- name: Criterion proving-tests resolve (PR-ready only)
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
env:
BASE_REF: ${{ github.base_ref }}
run: ./dev spec-check --criteria-tests "origin/${BASE_REF}"
expectations:
name: expectation guard (test-contract diff)
# PRs only (drafts included — weakening a test is never OK); never on push.
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# census-diffs committed test files against the merge base
fetch-depth: 0
- name: Expectation census (maintainer label overrides)
env:
BASE_REF: ${{ github.base_ref }}
# a maintainer-only PR label — labels need write access, so the agent
# cannot self-apply it (unlike the local, gitignored marker). This is
# the load-bearing approval signal.
EXPECTATIONS_APPROVED: ${{ contains(github.event.pull_request.labels.*.name, 'expectations-approved') }}
run: python3 .claude/hooks/expectation-guard.py --pr-diff "origin/${BASE_REF}"
lint:
name: hlint (dialect gate)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install hlint 3.10 (pinned binary + checksum)
run: |
curl -sSfL -o hlint.tar.gz \
https://github.com/ndmitchell/hlint/releases/download/v3.10/hlint-3.10-x86_64-linux.tar.gz
echo "ccabc8802a58154699a3583b8dddc5ea2e6d65753a62c45c0e80088ebb16b42b hlint.tar.gz" | sha256sum -c -
tar xzf hlint.tar.gz
- name: Dialect gate
run: HLINT=./hlint-3.10/hlint ./dev lint