forked from chilli-axe/mpc-autofill
-
Notifications
You must be signed in to change notification settings - Fork 0
211 lines (201 loc) · 10.9 KB
/
Copy pathdocs-lint.yml
File metadata and controls
211 lines (201 loc) · 10.9 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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
name: Docs lint
# Mechanical checks over docs/: internal link resolution (both [[wiki-link]]
# and markdown [text](path) styles) and backtick-quoted repo-path
# existence. Plus, HARD-FAIL (flipped 2026-07-23 via --strict, see
# docs/documentation-process.md's 'Interconnection lint' section) interconnection
# rules for the post-2026-07-23 model (decisions live in prose in their
# subject doc; the D-number decision-label convention is abolished): no new
# D-number decision labels, every doc reachable from the index chain, every
# SUPERSEDED marker carries a pointer, same-subject proposals cross-
# reference. Annotates failures inline (::error file=...,line=...::) —
# NEVER auto-fixes anything, and never touches doc content.
#
# KNOWN LIMITATION, stated plainly rather than buried: this can only catch
# BROKEN links/paths. It cannot tell a stale STATUS CLAIM ("not yet built"
# for something now shipped, a date stamp that's drifted, a claim
# contradicted by a sibling doc) from a true one — that class of rot is
# exactly what the quarterly judgment coherence pass exists for; see
# docs/documentation-process.md. This workflow and that pass are
# deliberately two different tools for two different problems.
on:
pull_request:
paths:
- "docs/**"
- ".github/scripts/**"
- ".github/wiki-publish-map.json"
- ".github/workflows/docs-lint.yml"
- "readme.md"
- "NOTICE"
# PROTECTED CORE roster (check_protected_core_license.py): the roster
# is DERIVED from license-provenance.md's marker region (covered by
# `docs/**` above), but the FILES it gates must trigger too — a PR
# that pastes AGPL-marked code into the decrypt tool touches no doc
# and no cardpicker module, and would otherwise miss this lint
# entirely until the weekly cron. `federation-hash-tool/**` below is
# the same entry for the other standalone trust-anchor tool.
- "decrypt-saved-deck-export/**"
- "MPCAutofill/cardpicker/vote_consensus.py"
- "MPCAutofill/cardpicker/printing_consensus.py"
- "MPCAutofill/cardpicker/tag_consensus.py"
- "MPCAutofill/cardpicker/artist_consensus.py"
- "MPCAutofill/cardpicker/local_phash.py"
- "MPCAutofill/cardpicker/local_fallback.py"
# Roster tether (check_calculator_roster_tether, added 2026-07-29):
# the calculator roster is DERIVED from every `*_ANONYMOUS_ID`
# declared anywhere in MPCAutofill/cardpicker/*.py, so a PR that
# declares a NEW calculator has to run this lint even when it
# touches no doc at all. Without this glob the tether would only
# fire on the weekly cron — i.e. the new calculator would land
# undocumented and unchecked, which is the exact gap it exists to
# close. Supersedes the individual cardpicker entries above; those
# are kept because they name the files the extractable-primitives
# tether cares about.
#
# `**`, not `*.py` (widened 2026-07-29 with the roster scan itself): a
# single `*` does NOT match a slash in a GitHub path filter, so
# `cardpicker/*.py` never matched `cardpicker/management/commands/`.
# That is the same one-directory hole the scan had — leaving it here
# would mean the widened scan still only ran on the weekly cron for
# exactly the PRs that introduce the problem.
- "MPCAutofill/cardpicker/**"
- "federation-hash-tool/**"
# Extractor-manifest tether (check_extractor_manifest_sync.py, added
# 2026-07-29): image_evidence.py is the SOURCE of the manifest and
# run_image_evidence_cohort.py re-types it, so a PR touching either
# side alone is exactly the PR that can put them out of sync. The
# cohort command sits one directory below the `cardpicker/*.py` glob
# above, and a single `*` does not match a slash — so it needs
# naming explicitly rather than being assumed covered.
- "MPCAutofill/cardpicker/image_evidence.py"
- "MPCAutofill/cardpicker/management/commands/run_image_evidence_cohort.py"
schedule:
# Weekly, independent of any PR — catches rot introduced by a change
# OUTSIDE docs/ (e.g. a component move that a doc's path reference
# didn't follow), which a docs/**-scoped PR trigger alone would miss.
- cron: "0 6 * * 1"
push:
branches: ["master"]
paths:
- "docs/**"
- ".github/wiki-publish-map.json"
- ".github/scripts/**"
# `**` for the same reason as the pull_request filter above.
- "MPCAutofill/cardpicker/**"
workflow_dispatch:
permissions:
contents: read
jobs:
lint:
name: Lint docs/ (links + path references)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run docs lint
run: python3 .github/scripts/docs_lint.py --strict
docs-lint-rules:
name: docs_lint.py rule unit tests (decisions-register + interconnection)
# Fixture + real-repo tests for the no-letter-labels / orphan /
# supersession / cross-reference rules. The `lint` job above runs docs_lint.py in its
# default SOFT mode (new rules warn, never fail master); this job proves
# the rules themselves behave. Stdlib only.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run docs_lint.py rule unit tests
run: python3 .github/scripts/tests/test_docs_lint.py
link-rewrite-parity:
name: Link-rewrite parity fixtures (publish_wiki.py transform_links)
# Runs the shared fixture set (.github/scripts/testdata/link_rewrite/)
# through both modes of publish_wiki.py's transform_links() - the
# SINGLE link-rewrite implementation in this repo (single-transform
# architecture, docs/proposals/proposal-i-docs-as-site-source.md).
# frontend/src/features/guide/docsSite.test.ts separately smoke-tests
# that publish_site.py's emitted artifacts exist and render, via
# test-frontend.yml. This job needs nothing beyond stdlib Python -
# publish_wiki.py has no third-party dependencies.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run publish_wiki.py link-rewrite parity fixtures
run: python3 .github/scripts/tests/test_publish_wiki_link_rewrite.py
readme-parity:
name: readme.md parity (publish_readme.py)
# readme.md is generated-and-COMMITTED, not gitignored like the site
# emit — GitHub renders it directly from the default branch with no
# build step in between (docs/proposals/proposal-i-readme-pipeline.md
# §2). This job is the correctness gate in place of a build-time
# regenerate: run the emit fresh and fail the PR if the committed file
# has drifted from it, so a hand-edit to readme.md (should have gone
# into a docs/ source region) or a source-region edit whose author
# forgot to rerun the script are both caught here instead of shipping
# silently stale.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run publish_readme.py unit + parity tests
run: python3 .github/scripts/tests/test_publish_readme.py
- name: Regenerate readme.md and diff against the committed file
run: |
cp readme.md /tmp/readme-committed.md
python3 .github/scripts/publish_readme.py .
if ! diff -u /tmp/readme-committed.md readme.md; then
echo "::error::readme.md is out of date - rerun \`python3 .github/scripts/publish_readme.py .\` and commit the result"
exit 1
fi
protected-core-license:
name: PROTECTED CORE license lint (docs/upstreaming/license-provenance.md)
# Fails if a PROTECTED CORE file (federation/hash-tool/vote-consensus
# modules) carries, or locally imports, code marked AGPL via a
# `# PROVENANCE:` header comment - see license-provenance.md §2 for the
# exact file list and why "no AGPL-derived code" is the real invariant,
# not "everything here must be GPL-3.0" (the hash tool is deliberately
# MIT). AST-based, stdlib only - reads source text, never imports or
# executes it, so no Django/third-party deps needed in this job.
# Passes with zero findings today; exists to catch the day that changes.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run protected-core license lint unit tests
run: python3 .github/scripts/tests/test_check_protected_core_license.py
- name: Run protected-core license lint against the real repo
run: python3 .github/scripts/check_protected_core_license.py
extractor-manifest-sync:
name: Extractor manifest sync (image_evidence.py -> cohort constants)
# CODE-TO-CODE tether. image_evidence.py declares the
# `*_EXTRACTOR_VERSION` constants and writes them into each row's
# `extractor_versions` manifest; run_image_evidence_cohort.py RE-TYPES
# the same key set and version strings as two module-level literals,
# held in sync only by a prose comment saying "keep this set in sync".
# Drift is silent at runtime and expensive both ways: a stale version
# marks already-extracted rows current (never re-extracted), a version
# nothing writes marks every row incomplete (re-pays fetch+OCR across
# ~220k cards). AST-based, stdlib only - reads source text, never
# imports or executes it, so no Django/third-party deps in this job.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run extractor-manifest tether unit tests
run: python3 .github/scripts/tests/test_check_extractor_manifest_sync.py
- name: Run extractor-manifest tether against the real repo
run: python3 .github/scripts/check_extractor_manifest_sync.py
extractor-ownership-totality:
name: Extractor ownership totality (image_evidence.py's own call graph -> EXTRACTOR_OWNERSHIP)
# CODE-TO-CODE tether, one layer below extractor-manifest-sync above: the
# eleven `*_EXTRACTOR_VERSION` constants only cover code that bumps a
# KEY's own version. Module-private helpers in image_evidence.py, and
# callables it imports from collector_line_artist.py/local_ocr.py/
# local_image_quality.py, help decide what compute_card_evidence stores
# but carry no version of their own - a change to any of them can
# silently change a stored field while MANIFEST_EXTRACTOR_CURRENT_VERSIONS
# stays put. AST-based, stdlib only - reads source text, never imports or
# executes it, so no Django/third-party deps in this job. Imports
# check_extractor_manifest_sync.py directly for its owning-key cross-check
# (see that script's own module docstring), so this job also needs that
# sibling script present.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run extractor-ownership-totality tether unit tests
run: python3 .github/scripts/tests/test_check_extractor_ownership_totality.py
- name: Run extractor-ownership-totality tether against the real repo
run: python3 .github/scripts/check_extractor_ownership_totality.py