Skip to content

Commit e0fae51

Browse files
fix(ci): resolve the four standing CI/CD failures at their roots (#29)
Every one of these was red on `main` on **every push**. Fixed at source, not suppressed. | Check | Root cause | Fix | |---|---|---| | 🟡 Estate rules | `flake.nix` not on the root allowlist | removed (Guix-only ruling) | | 🟡 OpenSSF best-practices | unfilled `{{PLACEHOLDER}}` tokens in 3 required files | filled / removed | | 🟡 RSR self-use (dogfooding) | two `uses:` actions that **404** | replaced with inline checks | | Dependabot `github_actions` | same 404 actions — the updater cannot resolve them | same fix | ## 1. `flake.nix` — the sole `estate-rules` blocker `scripts/check-root-shape.sh` reported exactly one offender. `flake.nix` is debris from the 07-21 sweep and contradicts the **2026-05-18 ruling** that the estate is Guix-primary with the Nix fallback retired — the file even documents itself as *"the Nix fallback tier"*. Removed. `build/guix.scm` is untouched, so `🔴 Gate: Guix-only package policy` is unaffected (it only checks for the presence of `*.scm`). Now: `PASS: root matches allowlist (45 entries, 46 permitted)`. If you would rather keep it, the alternative is `git mv flake.nix build/` — say the word and I will swap the approach. ## 2. Placeholder tokens - **`.github/SECURITY.md`** still carried its own *"TEMPLATE INSTRUCTIONS (delete this block before publishing)"* header, and advertised a PGP key that does not exist (`{{PGP_KEY_URL}}`, `{{PGP_FINGERPRINT}}`). Both removed — pointing users at an unfetchable key is worse than saying plainly that there isn't one. - **`STATE.a2ml` / `ECOSYSTEM.a2ml`** were verbatim copies of `rsr-template-repo`'s manifests: `project = "rsr-template-repo"`, the template's purpose, and `phase = maintenance` / `maturity = production`. They now describe Haec (`0.1.0`, design/experimental) and its real pipeline position (workbench → **haec** → trope-checker). This is the **template self-name leak** — it misdirects any tooling that keys off these files. ## 3. Two actions that do not exist ``` hyperpolymath/a2ml-validate-action → HTTP 404 hyperpolymath/k9-validate-action → HTTP 404 ``` They failed at **"Set up job"** on every push, so they never validated anything — `continue-on-error: true` merely hid that they were inert. An unresolvable action *also* breaks Dependabot's `github_actions` updater, which is why that job was failing as well: **one root cause, two symptoms**. Replaced with inline checks of the envelope contract that genuinely exists: - non-empty, valid UTF-8, `SPDX-License-Identifier` present; - for K9, the magic first line — `K9!` for `.k9`, `# K9!` for `.k9.ncl` so `nickel typecheck` still parses the file. **Their limits are stated in the workflow itself:** they do *not* parse the A2ML grammar or typecheck Nickel. That still needs the real validators. This is a smaller claim than the 404'd actions implied, but unlike them it actually runs. Also added SPDX headers to **6 `.a2ml` manifests** that had none — REUSE compliance, and it stops the new check being vacuous. ## Verified locally ``` root-shape .................. PASS (45/46) openssf placeholder check ... PASS A2ML envelope check ......... PASS (119 manifests) K9 envelope check ........... PASS (10 contracts) workflow YAML ............... ALL OK (every file has ≥1 live job) ``` ## Deliberately not changed `CLADE.a2ml` still declares `canonical-name = "rsr-template-repo"` with the template's registry UUID (`a5ea1382-…`), clade prefix `rm`, and forge URLs pointing at the template. Those are assigned by `gv-clade-index`; inventing replacements would corrupt that registry, so Haec needs a **real clade assignment**. Flagging rather than guessing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 56e207e commit e0fae51

11 files changed

Lines changed: 92 additions & 104 deletions

File tree

.github/0.1-AI-MANIFEST.a2ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
13
# AI Manifest - Level 1: .github

.github/SECURITY.md

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,6 @@ Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
44
-->
55
# Security Policy
66

7-
<!--
8-
============================================================================
9-
TEMPLATE INSTRUCTIONS (delete this block before publishing)
10-
============================================================================
11-
Replace all {{PLACEHOLDER}} values with your information:
12-
Haec - Your project name
13-
hyperpolymath - GitHub username or org (e.g., hyperpolymath)
14-
haec - Repository name
15-
j.d.a.jewell@open.ac.uk - Security contact email
16-
{{PGP_FINGERPRINT}} - Your PGP key fingerprint (40 chars, no spaces)
17-
{{PGP_KEY_URL}} - URL to your public PGP key
18-
https://github.com/hyperpolymath/haec - Your website/domain
19-
2026 - Current year for copyright
20-
21-
Optional: Remove sections that don't apply (e.g., PGP if you don't use it)
22-
============================================================================
23-
-->
24-
257
We take security seriously. We appreciate your efforts to responsibly disclose vulnerabilities and will make every effort to acknowledge your contributions.
268

279
## Table of Contents
@@ -56,26 +38,16 @@ This method ensures:
5638
- Coordinated disclosure tooling
5739
- Automatic credit when the advisory is published
5840

59-
### Alternative: Encrypted Email
41+
### Alternative: Email
6042

6143
If you cannot use GitHub Security Advisories, you may email us directly:
6244

6345
| | |
6446
|---|---|
6547
| **Email** | j.d.a.jewell@open.ac.uk |
66-
| **PGP Key** | [Download Public Key]({{PGP_KEY_URL}}) |
67-
| **Fingerprint** | `{{PGP_FINGERPRINT}}` |
68-
69-
```bash
70-
# Import our PGP key
71-
curl -sSL {{PGP_KEY_URL}} | gpg --import
7248

73-
# Verify fingerprint
74-
gpg --fingerprint j.d.a.jewell@open.ac.uk
75-
76-
# Encrypt your report
77-
gpg --armor --encrypt --recipient j.d.a.jewell@open.ac.uk report.txt
78-
```
49+
No PGP key is published for this project. If you need to send an encrypted
50+
report, say so in a first plaintext message and a key will be exchanged.
7951

8052
> **⚠️ Important:** Do not report security vulnerabilities through public GitHub issues, pull requests, discussions, or social media.
8153
@@ -374,7 +346,6 @@ When using Haec, we recommend:
374346

375347
## Additional Resources
376348

377-
- [Our PGP Public Key]({{PGP_KEY_URL}})
378349
- [Security Advisories](https://github.com/hyperpolymath/haec/security/advisories)
379350
- [Changelog](CHANGELOG.md)
380351
- [Contributing Guidelines](CONTRIBUTING.md)

.github/workflows/dogfood-gate.yml

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,65 @@ jobs:
4848
echo "::warning::Found $config_count config files but no K9 contracts"
4949
fi
5050
51-
- name: Validate A2ML manifests
51+
# hyperpolymath/a2ml-validate-action and hyperpolymath/k9-validate-action
52+
# do not exist — both 404. The steps therefore failed at "Set up job" on
53+
# every push, and an unresolvable action also breaks Dependabot's
54+
# github_actions updater. Validated inline until those are published.
55+
#
56+
# Scope is deliberately limited and stated honestly: these assert the
57+
# file-level envelope contract (encoding, non-emptiness, SPDX header, and
58+
# the K9 magic first line). They do NOT parse the A2ML grammar or
59+
# typecheck Nickel — that still needs the real validators.
60+
- name: Validate A2ML manifest envelopes
5261
id: a2ml
5362
if: steps.inventory.outputs.a2ml_count != '0'
54-
continue-on-error: true
55-
uses: hyperpolymath/a2ml-validate-action@05bcb78917c09702e90ed18004298a6728753914 # main
56-
with:
57-
path: '.'
58-
strict: 'false'
63+
shell: bash
64+
run: |
65+
set -euo pipefail
66+
fail=0
67+
while IFS= read -r -d '' f; do
68+
if [ ! -s "$f" ]; then
69+
echo "::error file=$f::empty A2ML manifest"; fail=1; continue
70+
fi
71+
if ! iconv -f UTF-8 -t UTF-8 "$f" >/dev/null 2>&1; then
72+
echo "::error file=$f::not valid UTF-8"; fail=1; continue
73+
fi
74+
if ! grep -qE 'SPDX-License-Identifier:' "$f"; then
75+
echo "::error file=$f::missing SPDX-License-Identifier header"; fail=1
76+
fi
77+
done < <(find . -name '*.a2ml' -not -path './.git/*' -print0)
78+
[ "$fail" -eq 0 ] || { echo "::error::A2ML envelope check failed"; exit 1; }
79+
echo "A2ML envelope check: OK"
5980
60-
- name: Validate K9 contracts
81+
- name: Validate K9 contract envelopes
6182
id: k9
6283
if: steps.inventory.outputs.k9_count != '0'
63-
continue-on-error: true
64-
uses: hyperpolymath/k9-validate-action@bddcd9109ee96f9ea3fdb4bf51084fe9cd0909ce # main
65-
with:
66-
path: '.'
67-
strict: 'false'
84+
shell: bash
85+
run: |
86+
set -euo pipefail
87+
fail=0
88+
while IFS= read -r -d '' f; do
89+
if [ ! -s "$f" ]; then
90+
echo "::error file=$f::empty K9 contract"; fail=1; continue
91+
fi
92+
if ! iconv -f UTF-8 -t UTF-8 "$f" >/dev/null 2>&1; then
93+
echo "::error file=$f::not valid UTF-8"; fail=1; continue
94+
fi
95+
first=$(head -1 "$f")
96+
case "$f" in
97+
# .k9.ncl must comment the magic so `nickel typecheck` still parses.
98+
*.k9.ncl) want='# K9!' ;;
99+
*) want='K9!' ;;
100+
esac
101+
if [ "$first" != "$want" ]; then
102+
echo "::error file=$f::first line must be '$want' (found: '$first')"; fail=1
103+
fi
104+
if ! grep -qE 'SPDX-License-Identifier:' "$f"; then
105+
echo "::error file=$f::missing SPDX-License-Identifier header"; fail=1
106+
fi
107+
done < <(find . \( -name '*.k9' -o -name '*.k9.ncl' \) -not -path './.git/*' -print0)
108+
[ "$fail" -eq 0 ] || { echo "::error::K9 envelope check failed"; exit 1; }
109+
echo "K9 envelope check: OK"
68110
69111
- name: Scan for invisible characters
70112
id: empty_lint

.machine_readable/6a2/0-AI-MANIFEST.a2ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
13
# AI Manifest for 6a2 Directory
24

35
## Purpose

.machine_readable/6a2/ECOSYSTEM.a2ml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
# SPDX-License-Identifier: MPL-2.0
2-
# ECOSYSTEM.a2ml — Ecosystem position (META-TEMPLATE)
2+
# ECOSYSTEM.a2ml — Ecosystem position for Haec.
33
#
4-
# This is the ECOSYSTEM file for rsr-template-repo itself. It records the
5-
# TEMPLATE's own position in the estate. When consumed by a new project,
6-
# replace these fields with the target project's ecosystem position and
7-
# related projects (see the NOTE FOR CONSUMERS at the bottom).
4+
# Instantiated from the rsr-template-repo meta-template; the fields below
5+
# describe Haec's own position in the estate.
86

97
[metadata]
10-
project = "rsr-template-repo"
8+
project = "haec"
119
ecosystem = "hyperpolymath"
1210

1311
[position]
14-
type = "repository-template"
15-
purpose = "Canonical RSR-compliant repository template: scaffolding (CI/CD, AI manifests, ABI/FFI standards, container ecosystem, governance) that new hyperpolymath projects are instantiated from."
12+
type = "language"
13+
purpose = "Writes and type-checks Haec programs and emits Trope IR. Haec is deliberately not the tropechecker (trope-checker) and not the vocabulary (trope-particularity-workbench)."
1614

1715
[pipeline]
18-
position = "foundation"
19-
chain = "standards → rsr-template-repo → (every estate repo)"
20-
notes = "rsr-template-repo turns the RSR standard into runnable scaffolding. New repos are created from it via `just init`, which substitutes the {{PLACEHOLDER}} tokens."
16+
position = "producer"
17+
chain = "trope-particularity-workbench (vocabulary) → haec (emits Trope IR) → trope-checker (verdict)"
18+
notes = "Haec produces a record of graded effects; the checker consumes that IR and returns a verdict against each consumer's declared use-model. The checker never executes a Haec program, so Rice's theorem is no obstacle: an unbounded lossy loop simply gets an honest top grade."
2119
coordination = "standards"
2220

2321
[related-projects]

.machine_readable/6a2/STATE.a2ml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
# SPDX-License-Identifier: MPL-2.0
22
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
33
#
4-
# STATE.a2ml — Project state checkpoint (META-TEMPLATE)
4+
# STATE.a2ml — Project state checkpoint for Haec.
55
#
6-
# This is the STATE file for rsr-template-repo itself.
7-
# When consumed by a new project, replace {{PLACEHOLDER}} tokens
8-
# and customize sections below for the target project.
6+
# Instantiated from the rsr-template-repo meta-template. Identity and
7+
# project-context below describe Haec; sections further down are still
8+
# inherited from the template and need review (see NOTE, bottom).
99

1010
[metadata]
11-
project = "rsr-template-repo"
12-
version = "0.2.0"
11+
project = "haec"
12+
version = "0.1.0"
1313
last-updated = "2026-02-28"
1414
status = "active" # active | paused | archived
1515

1616
[project-context]
17-
name = "rsr-template-repo"
18-
purpose = "Canonical RSR-compliant repository template providing scaffolding for all hyperpolymath projects — including CI/CD, AI manifests, ABI/FFI standards, container ecosystem, and governance infrastructure."
19-
completion-percentage = 95
17+
name = "Haec"
18+
purpose = "A Turing-complete language whose type discipline is trope-particularity: every operation over a property-instance carries a loss-shape grade, emitted as Trope IR for a separate, language-independent tropechecker to verdict."
19+
completion-percentage = 10 # rough: design stage, see README status '0.1 (design)'
2020

2121
[position]
22-
phase = "maintenance" # design | implementation | testing | maintenance | archived
23-
maturity = "production" # experimental | alpha | beta | production | lts
22+
phase = "design" # design | implementation | testing | maintenance | archived
23+
maturity = "experimental" # experimental | alpha | beta | production | lts
2424

2525
[route-to-mvp]
2626
milestones = [
@@ -58,7 +58,7 @@ part-of = ["RSR Framework", "stapeln ecosystem"]
5858
depends-on = ["stapeln", "selur-compose", "cerro-torre", "svalinn", "vordr", "k9-svc"]
5959

6060
# ---------------------------------------------------------------------------
61-
# NOTE FOR CONSUMERS: When using this template to create a new repo, reset
62-
# the fields above to your project's values and replace all {{PLACEHOLDER}}
63-
# tokens. The milestones above describe the TEMPLATE's evolution, not yours.
61+
# NOTE: the milestones and depends-on above are still the meta-template's,
62+
# not Haec's, and are pending a rewrite. Identity, purpose, phase and
63+
# maturity have been corrected to describe this project.
6464
# ---------------------------------------------------------------------------

.machine_readable/6a2/anchors/0-AI-MANIFEST.a2ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
13
# AI Manifest for Anchor Directory
24

35
## Purpose

.machine_readable/ai/AI.a2ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
1+
# SPDX-License-Identifier: MPL-2.0
2+
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
23
# AI Assistant Instructions
34

45
## Repository Focus

examples/0.1-AI-MANIFEST.a2ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
13
# AI Manifest - Level 1: examples

flake.nix

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)