Skip to content

Commit 8e6ba7d

Browse files
perf(hypatia-scan): cache built scanner keyed on Hypatia HEAD + shallow clone (#380)
## What Cache the Hypatia scanner build in `hypatia-scan-reusable.yml`, keyed on Hypatia's HEAD SHA, plus a Hex/Mix cache and a shallow clone. ## Why The reusable rebuilds Hypatia from source on **every** run — the full clone and `mix escript.build` dominate wall-clock, so even a trivial Dependabot bump triggers a full neurosymbolic build (the `[ ! -d ]` / `[ ! -f ]` guards never hit on ephemeral runners). ## How - **Resolve Hypatia version** via `git ls-remote … HEAD` (cheap, no clone). - **Cache built scanner** (`~/hypatia`) on an **exact-SHA key, NO restore-keys**: a fresh clone+build happens only when Hypatia actually changes; otherwise the prebuilt escript is restored and the existing guards short-circuit. No restore-keys is deliberate — a partial hit would leave a stale `~/hypatia` and the repo would be analysed with old rules. - **Cache Hex/Mix** package cache (restore-keys; content-addressed, safe to reuse). - **Shallow-clone** Hypatia (`--depth 1`) — building the escript needs no history (same pattern already used for the gitbot-fleet clone in this file). ## Effect When Hypatia is unchanged (common case across estate scans), clone+build short-circuit → the ~20-min pipeline collapses to roughly scan-time only. When Hypatia changes, the build is correctly refreshed. ## Safety No change to scan behaviour or output. `actions/cache` pinned to the estate-standard SHA (`27d5ce7…`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 426368b commit 8e6ba7d

2 files changed

Lines changed: 61 additions & 28 deletions

File tree

.github/workflows/hypatia-scan-reusable.yml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,43 @@ jobs:
111111
elixir-version: '1.18'
112112
otp-version: '27'
113113

114+
# --- Hypatia build caching (perf) ---------------------------------------
115+
# The scanner is rebuilt from source on every run; the clone and
116+
# `mix escript.build` dominate wall-clock (a full neurosymbolic build on
117+
# every push, including trivial Dependabot bumps). Key the build cache on
118+
# Hypatia's HEAD so a fresh clone+build happens ONLY when Hypatia actually
119+
# changes; otherwise the prebuilt escript is restored and the clone/build
120+
# steps short-circuit on their existing `[ ! -d ]` / `[ ! -f ]` guards.
121+
- name: Resolve Hypatia version
122+
id: hypatia_ref
123+
run: echo "sha=$(git ls-remote https://github.com/hyperpolymath/hypatia.git HEAD | cut -f1)" >> "$GITHUB_OUTPUT"
124+
125+
- name: Cache Hex/Mix package cache
126+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4
127+
with:
128+
path: |
129+
~/.hex
130+
~/.mix
131+
~/.cache/hex
132+
key: hypatia-hexmix-${{ runner.os }}-otp27-elixir1.18-${{ steps.hypatia_ref.outputs.sha }}
133+
restore-keys: |
134+
hypatia-hexmix-${{ runner.os }}-otp27-elixir1.18-
135+
136+
- name: Cache built Hypatia scanner
137+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4
138+
with:
139+
path: ~/hypatia
140+
# Exact-SHA key, NO restore-keys on purpose: an exact match guarantees
141+
# we run the scanner built from that Hypatia commit. A partial (restore-
142+
# keys) hit would leave a STALE ~/hypatia in place, the `[ ! -d ]` guard
143+
# would then skip the re-clone, and the repo would be analysed with old
144+
# rules. On a miss we simply re-clone+rebuild that commit.
145+
key: hypatia-build-${{ runner.os }}-otp27-elixir1.18-${{ steps.hypatia_ref.outputs.sha }}
146+
114147
- name: Clone Hypatia
115148
run: |
116149
if [ ! -d "$HOME/hypatia" ]; then
117-
git clone https://github.com/hyperpolymath/hypatia.git "$HOME/hypatia"
150+
git clone --depth 1 https://github.com/hyperpolymath/hypatia.git "$HOME/hypatia"
118151
fi
119152
120153
- name: Build Hypatia scanner (if needed)

.machine_readable/REGISTRY.a2ml

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ name = "A2ML — Attested Markup Language"
3636
stream = "foundation"
3737
home = "a2ml/"
3838
canonical_doc = "a2ml/README.adoc"
39-
source_hash = "sha256:2612d2f66eaefe1aedd2f783c748f85eec80cdc09147fb87593086041a670e07"
39+
source_hash = "sha256:d911a6dfe0b61cbaadc0e39badf248d0b727ae26686a0f56dc3652e7d8301171"
4040
route = "the typed/verified machine-readable document format"
4141

4242
[[spec]]
@@ -45,7 +45,7 @@ name = "K9 Self-Validating Components"
4545
stream = "foundation"
4646
home = "k9-svc/"
4747
canonical_doc = "k9-svc/README.adoc"
48-
source_hash = "sha256:c368125fbfb026c89d83b4b2b9d249024e83295e75ac49ab2889b8d7c1989dcd"
48+
source_hash = "sha256:6820b8054e44669ce0193f730d6dbb3e4680d4b0207b54b97576b21d8b17ba4f"
4949
route = "self-validating components with embedded contracts + deploy logic"
5050

5151
[[spec]]
@@ -54,7 +54,7 @@ name = "Contractiles (Must/Trust/Dust/Intend)"
5454
stream = "foundation"
5555
home = "contractiles/"
5656
canonical_doc = "contractiles/README.adoc"
57-
source_hash = "sha256:628efcbff607cc7382280b52bf662c2c79801ae8f01b902f3aebe84b08dd79ad"
57+
source_hash = "sha256:5cd3214144ae7f1385f1ea689ac43cf5edb65bbe69a48015fa32e66725bf66bd"
5858
route = "policy-enforcement primitives the K9 layer is built from"
5959

6060
[[spec]]
@@ -63,7 +63,7 @@ name = "META.a2ml spec"
6363
stream = "foundation"
6464
home = "meta-a2ml/"
6565
canonical_doc = "meta-a2ml/README.adoc"
66-
source_hash = "sha256:fd41c8f7c2f4d2dd6dceb11bffaabc8905a9da33c2aa76ab8360da6ee9e3a0b4"
66+
source_hash = "sha256:bd0f10114fb753377708b2fa07c5995a000060aa50472d02e067f890f005ab53"
6767
route = "architecture decisions / governance metadata format"
6868

6969
[[spec]]
@@ -72,7 +72,7 @@ name = "STATE.a2ml spec"
7272
stream = "foundation"
7373
home = "state-a2ml/"
7474
canonical_doc = "state-a2ml/README.adoc"
75-
source_hash = "sha256:21d88102987bae7853cf8d642aeeba13efdeb1a105bbd4d89e7064ef15ce8b9d"
75+
source_hash = "sha256:a9396d04d530329257d4739b488427383ca4d50ef581c617159cd679e012dd47"
7676
route = "project-state metadata format (drives this registry's topology)"
7777

7878
[[spec]]
@@ -81,7 +81,7 @@ name = "ECOSYSTEM.a2ml spec"
8181
stream = "foundation"
8282
home = "ecosystem-a2ml/"
8383
canonical_doc = "ecosystem-a2ml/README.adoc"
84-
source_hash = "sha256:46b529c177ddc2166bc2cdfdccc55fef8650e03f8d6b3a1ee25d70a494fb1626"
84+
source_hash = "sha256:258b20df64d5eefb6164ce673f55df24b2336044691a4ffddf4aca62bc925b22"
8585
route = "ecosystem-positioning metadata format"
8686

8787
[[spec]]
@@ -90,7 +90,7 @@ name = "AGENTIC.a2ml spec"
9090
stream = "foundation"
9191
home = "agentic-a2ml/"
9292
canonical_doc = "agentic-a2ml/README.adoc"
93-
source_hash = "sha256:31832029e8e989e200b4022075ed0c8807bb95f55baa0cda11ce079d1bd5b900"
93+
source_hash = "sha256:489382852061480707944ea771cfc361205a2292c0eec152f0e26e97054a08aa"
9494
route = "AI-agent operational gating / entropy budgets"
9595

9696
[[spec]]
@@ -99,7 +99,7 @@ name = "NEUROSYM.a2ml spec"
9999
stream = "foundation"
100100
home = "neurosym-a2ml/"
101101
canonical_doc = "neurosym-a2ml/README.adoc"
102-
source_hash = "sha256:62bbea52b4b57bb582cc79b320b97d2fced2bef41a77c33590211cbf4ddbd224"
102+
source_hash = "sha256:e264ce526d5149e501529aa4460057320f629ac5db41f6874f4ed8441d45695f"
103103
route = "symbolic semantics / proof obligations"
104104

105105
[[spec]]
@@ -108,7 +108,7 @@ name = "PLAYBOOK.a2ml spec"
108108
stream = "foundation"
109109
home = "playbook-a2ml/"
110110
canonical_doc = "playbook-a2ml/README.adoc"
111-
source_hash = "sha256:b00cd658fe367314735c9f2689579820263b26d1853252dc72a0fee3d784db63"
111+
source_hash = "sha256:b88c04050eebda9d0e888fe0f4b39dc01d8f98bd1ec456ff6aa90e177a620825"
112112
route = "executable operational runbooks"
113113

114114
[[spec]]
@@ -117,7 +117,7 @@ name = "ANCHOR.a2ml spec"
117117
stream = "foundation"
118118
home = "anchor-a2ml/"
119119
canonical_doc = "anchor-a2ml/README.adoc"
120-
source_hash = "sha256:2a88233f201c3d2c05dd4d2530cc0fe33423ce9540a0fc2aa21556233074f4fb"
120+
source_hash = "sha256:4492cb76436f0a077a290cee621dba43f4cc22ff447b42fc889d6a1cc1a0d214"
121121
route = "project-recalibration intervention format"
122122

123123
[[spec]]
@@ -126,7 +126,7 @@ name = "0-AI Gatekeeper Protocol"
126126
stream = "protocol"
127127
home = "0-ai-gatekeeper-protocol/"
128128
canonical_doc = "0-ai-gatekeeper-protocol/README.adoc"
129-
source_hash = "sha256:d3157a30fde9e78ab2374e7b6a8c733e6a9b21492ee426bdd26695522624b646"
129+
source_hash = "sha256:82c873694f1ddb581900794b26503225cc491e8cc5b2edf0d3043308272411a1"
130130
route = "the AI-agent entry/gating protocol behind 0-AI-MANIFEST"
131131

132132
[[spec]]
@@ -135,7 +135,7 @@ name = "K9 Coordination Protocol"
135135
stream = "protocol"
136136
home = "k9-coordination-protocol/"
137137
canonical_doc = "k9-coordination-protocol/README.adoc"
138-
source_hash = "sha256:9c856a0ed99f92ab3f8f6049df918fe023422dc6688cbc6110190c122ab28f97"
138+
source_hash = "sha256:ee8521e5db1ebd5156b0a866bfe6990ab18f62885c7133e0d66ebf038a370b84"
139139
route = "multi-agent coordination on top of K9"
140140

141141
[[spec]]
@@ -144,7 +144,7 @@ name = "AVOW Protocol"
144144
stream = "protocol"
145145
home = "avow-protocol/"
146146
canonical_doc = "avow-protocol/README.adoc"
147-
source_hash = "sha256:556e42c1fc34c277a18b16bc2553f202ced9365b196d5c17649dda4a1a31e545"
147+
source_hash = "sha256:ac360b0e415c40cab67f70cc3a06473eccdcc79f718558cfca23ea2bf9498a5c"
148148
route = "consent-attested messaging / origin attribution"
149149

150150
[[spec]]
@@ -153,7 +153,7 @@ name = "AXEL Protocol"
153153
stream = "protocol"
154154
home = "axel-protocol/"
155155
canonical_doc = "axel-protocol/README.adoc"
156-
source_hash = "sha256:2b20dddef2d9405f6eb35eaca0006e097bab31e88360b8cfed2fa239bebb911c"
156+
source_hash = "sha256:6867f73559b0497e9f3bb51ba8d57023c7c8122f2af09f54ee708d9e7f8d3540"
157157
route = "age-gating + explicit-content enforcement"
158158

159159
[[spec]]
@@ -162,7 +162,7 @@ name = "Overlay Protocol"
162162
stream = "protocol"
163163
home = "overlay-protocol/"
164164
canonical_doc = "overlay-protocol/.machine_readable/6a2/ECOSYSTEM.a2ml"
165-
source_hash = "sha256:4e490e20401ef888930d7b72fe151bc89e4d084606252a1d6344df2c1dc904e1"
165+
source_hash = "sha256:e39ef8666b33f6b4f4c2626af2a4f24146db0bca7a43aade01fc734ead9675da"
166166
route = "layered overlay composition spec"
167167

168168
[[spec]]
@@ -180,7 +180,7 @@ name = "ARG — Adoption Readiness Grades"
180180
stream = "readiness"
181181
home = "adoption-readiness-grades/"
182182
canonical_doc = "adoption-readiness-grades/README.adoc"
183-
source_hash = "sha256:036055fcb1c66320015e5dfca56438d8c87fa078c527c4c6226ec9e16803b4e0"
183+
source_hash = "sha256:77e3c0d74e9fd037b57dc883804501be1117ac12534d3d817654f2c96919a0e8"
184184
route = "per-language adoption-maturity profile templates"
185185

186186
[[spec]]
@@ -189,7 +189,7 @@ name = "FRG — Foundations Readiness Grades"
189189
stream = "readiness"
190190
home = "foundations-readiness-grades/"
191191
canonical_doc = "foundations-readiness-grades/README.adoc"
192-
source_hash = "sha256:a0e205de918a34d731e65d76e0a87d879dfd07b4e7cefc9b9c59cf8e81a051cb"
192+
source_hash = "sha256:af968fdd30947f20898895497dcba7b40850e84d35b5b384ef6d0e509ab6afbd"
193193
route = "per-language foundational-maturity profile templates"
194194

195195
[[spec]]
@@ -198,7 +198,7 @@ name = "CRG — Component Readiness Grades"
198198
stream = "readiness"
199199
home = "component-readiness-grades/"
200200
canonical_doc = "component-readiness-grades/README.adoc"
201-
source_hash = "sha256:47e5a756220c6f2e1c7274f6814fdbd8fe5a235b808eb638f83f80994d0843e8"
201+
source_hash = "sha256:edf1d1b8035fcb67d2c27aba50b9e953ea2cb502ffbdc60fe96c147e9b1631d4"
202202
route = "the X..A grading system for components"
203203

204204
[[spec]]
@@ -207,7 +207,7 @@ name = "TRG — Toolchain Readiness Grades"
207207
stream = "readiness"
208208
home = "toolchain-readiness-grades/"
209209
canonical_doc = "toolchain-readiness-grades/README.adoc"
210-
source_hash = "sha256:26a5399a7b83ccd95e9eee574b90c92ed238fb671f9eb0e284bd7a0b0e109f36"
210+
source_hash = "sha256:c1741ef15ee180179c04529dc1378675fff55b245915d2b20b9cab89cc466092"
211211
route = "per-toolchain readiness profile templates"
212212

213213
[[spec]]
@@ -216,7 +216,7 @@ name = "RSR — Rhodium Standard Repositories"
216216
stream = "governance"
217217
home = "rhodium-standard-repositories/"
218218
canonical_doc = "rhodium-standard-repositories/README.adoc"
219-
source_hash = "sha256:16937c23fe261963c80f611e827d987f924d87169e79a388958b1bd53a11d7cc"
219+
source_hash = "sha256:87c5f1efdbd12b2621f5ec1cc9cde7d5f47c98b23db8534c308ab1068772b431"
220220
route = "the repository-compliance standard every repo is graded against"
221221

222222
[[spec]]
@@ -225,7 +225,7 @@ name = "Session Management Standards"
225225
stream = "governance"
226226
home = "session-management-standards/"
227227
canonical_doc = "session-management-standards/README.adoc"
228-
source_hash = "sha256:86a7739ac5cfd12aa34b1be1505c169e41b53e01bd1b3e3b7be308cd3b06d6b3"
228+
source_hash = "sha256:4b1a97d2ef91578b2c262f1af5b93577cb36d53d234c330947538f4eafc01a6c"
229229
route = "continuity / verify / handover protocols"
230230

231231
[[spec]]
@@ -234,7 +234,7 @@ name = "ENSAID Config"
234234
stream = "governance"
235235
home = "ensaid-config/"
236236
canonical_doc = "ensaid-config/README.adoc"
237-
source_hash = "sha256:f6cc431368df4cea795ca24eafb26ae42e6ff6bb17a02d8c4c3d75218709d0b1"
237+
source_hash = "sha256:1a5b75d3459b63bf7f3ced7eb8b7e7372c08c3b1d6fbaac6da98d008250d9020"
238238
route = "the ensaid configuration standard"
239239

240240
[[spec]]
@@ -243,7 +243,7 @@ name = "Accessibility Standard"
243243
stream = "governance"
244244
home = "accessibility/"
245245
canonical_doc = "accessibility/STANDARD.a2ml"
246-
source_hash = "sha256:2286b68bb6ededf8534e90ad52f3ae5f7d25e4193f890ce5c740686171a4db2b"
246+
source_hash = "sha256:73898902f539078297c9c1d952e403dc62ddcb39c1d0282442fdf4c22bea330b"
247247
route = "estate accessibility requirements"
248248

249249
[[spec]]
@@ -252,7 +252,7 @@ name = "Publication Pre-Flight"
252252
stream = "governance"
253253
home = "publication-pre-flight/"
254254
canonical_doc = "publication-pre-flight/ESTATE-AUDIT-BASELINE-2026-03-30.adoc"
255-
source_hash = "sha256:5bcf21e86a10248b20bf37fa8480a16d3ab3604a784f3cdb23e2ec351329975b"
255+
source_hash = "sha256:8e1f3bb0515e80636046332b99639346655d87412e1f2f3613903854213025a1"
256256
route = "submission gate (HOL + Zenodo checklists)"
257257

258258
[[spec]]
@@ -261,7 +261,7 @@ name = "Release Pre-Flight (V1 Gate)"
261261
stream = "governance"
262262
home = "release-pre-flight/"
263263
canonical_doc = "release-pre-flight/V1-GATE.adoc"
264-
source_hash = "sha256:790505e07de1cc1f3a22eed1e9ee0be0c75e28f9adbdec0aa9833253d9030a4a"
264+
source_hash = "sha256:9159e5e8c810df80754f35b81a58d291bd046991cdfda9ad20d8b1bf5cf0d1a5"
265265
route = "hard v1.0.0 audit requirements"
266266

267267
[[spec]]
@@ -270,7 +270,7 @@ name = "Standards Hypatia Rules"
270270
stream = "integration"
271271
home = "hypatia-rules/"
272272
canonical_doc = "hypatia-rules/README.adoc"
273-
source_hash = "sha256:797f42c3ac24cf610e1e0da0e9e019f3f0dce527d1f80857ab2adb85741159d3"
273+
source_hash = "sha256:4b8d3d957c74aca64825e337b4e9edcd94be2ca04da55abeb9046cb217040528"
274274
route = "the dogfooding rules that scan THIS repo (incl. drift detection)"
275275

276276
[[spec]]
@@ -279,7 +279,7 @@ name = "A2ML Templates"
279279
stream = "integration"
280280
home = "a2ml-templates/"
281281
canonical_doc = "a2ml-templates/STATE.a2ml.v2.spec.adoc"
282-
source_hash = "sha256:629d74f76ad2d79448564e1aed0ef580027ad4a330f614a2d075401716cc9093"
282+
source_hash = "sha256:9dac88195c1f35af8755a1bead420c80490d3da7bc613083208cb95a822c6c00"
283283
route = "copy-in templates for the 7 A2ML files"
284284

285285
[[spec]]

0 commit comments

Comments
 (0)