|
| 1 | +// SPDX-License-Identifier: CC-BY-SA-4.0 |
| 2 | +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> |
| 3 | += Estate-wide PMPL → MPL-2.0 licence sweep — delegation runbook |
| 4 | +:toc: left |
| 5 | +:revdate: 2026-06-27 |
| 6 | + |
| 7 | +Organising brief + capabilities/access spec for executing the stray-`PMPL-1.0` |
| 8 | +SPDX-header cleanup across `org:hyperpolymath`. Produced from a complete |
| 9 | +GitHub code-search inventory (3 pages, 271 distinct matches, deduplicated). |
| 10 | + |
| 11 | +IMPORTANT: This is FLAG-AND-PLAN, not a licence change in itself. Per estate |
| 12 | +policy every licence edit is per-file, owner-approval-gated, and NEVER a bulk |
| 13 | +SPDX sweep. This runbook exists so a delegated agent can execute *correctly*. |
| 14 | + |
| 15 | +== 1. The headline: the sweep is NARROW |
| 16 | + |
| 17 | +Of all `SPDX-License-Identifier: PMPL-1.0[-or-later]` headers in the org, the |
| 18 | +overwhelming majority are *legitimate* or *must-not-touch*. The genuinely |
| 19 | +actionable SPDX-header surface is **22 files across 4 repos** (5 atomic + |
| 20 | +17 in `nextgen-databases`, resolved in §4). A much larger *body-text* drift |
| 21 | +surface (236 matches) is template-propagated — see §7. |
| 22 | + |
| 23 | +[cols="3,1,1,4",options="header"] |
| 24 | +|=== |
| 25 | +| Repo | Files | Class | Disposition |
| 26 | + |
| 27 | +| `palimpsest-license` | 126 | 🟢 CARVE-OUT | PMPL is CORRECT here. Leave. |
| 28 | +| `palimpsest-plasma` | 74 | 🟢 CARVE-OUT | PMPL is CORRECT here. Leave. |
| 29 | +| `007` | 5 | 🔴 ARR | DO NOT TOUCH. All-Rights-Reserved. Surface to owner only. |
| 30 | +| `idaptik` | 3 | 🟠 SON-SHARED | → **AGPL-3.0-or-later** (NOT MPL-2.0). Actionable. |
| 31 | +| `developer-ecosystem` | 43 | 🔵 DRIFT | 1 actionable; 42 are vendored `rescript/` fork — leave. |
| 32 | +| `email-octad-experiment`| 1 | 🔵 DRIFT | 1 actionable. |
| 33 | +| `nextgen-databases` | 17 | 🔵 DRIFT | IN SCOPE — estate-authored ReScript clients → MPL-2.0/CC-BY-SA-4.0 (§4). |
| 34 | +| `standards` | 1 | 🔵 DRIFT | `LICENSES/PMPL-1.0-or-later.txt` = licence-exhibit text. Leave. |
| 35 | +| `zotero-tools` | 1 | 🔵 DRIFT | `zotpress/` upstream WordPress fork. Leave. |
| 36 | +|=== |
| 37 | + |
| 38 | +`consent-aware-http` (the 3rd legitimate carve-out) shows **zero** PMPL headers — |
| 39 | +its carve-out is prospective-only per policy, so that is expected and correct. |
| 40 | + |
| 41 | +== 2. The actionable set (22 files, owner-approval-gated) |
| 42 | + |
| 43 | +=== 2a. → MPL-2.0 (sole-owner code) |
| 44 | +* `developer-ecosystem` : `affinescript-ecosystem/rattlescript/affinescript/lib/wasm_encode.ml` |
| 45 | + (OCaml source header `(* SPDX-License-Identifier: PMPL-1.0-or-later *)`). |
| 46 | +* `email-octad-experiment` : `.github/workflows/workflow-linter.yml`. |
| 47 | +* `nextgen-databases` : the 17 `lithoglyph/clients/rescript/…` + |
| 48 | + `verisimdb/connectors/clients/rescript/…` files — `.res` → MPL-2.0, the one |
| 49 | + client `README.md` (prose) → CC-BY-SA-4.0 (estate-authored, see §4). |
| 50 | + |
| 51 | +=== 2b. → AGPL-3.0-or-later (son-shared — NOT MPL-2.0) |
| 52 | +* `idaptik` : `.github/workflows/governance.yml` |
| 53 | +* `idaptik` : `.github/workflows/hypatia-scan.yml` |
| 54 | +* `idaptik` : `.github/workflows/scorecard.yml` |
| 55 | + |
| 56 | +idaptik is co-maintained with Joshua; estate policy fixes son-shared repos at |
| 57 | +AGPL-3.0-or-later. A delegated agent MUST special-case this — flipping idaptik |
| 58 | +to MPL-2.0 would be a policy violation. |
| 59 | + |
| 60 | +== 3. The leave-alone set (DO NOT EDIT — reasons) |
| 61 | + |
| 62 | +* *Carve-outs* (`palimpsest-license`, `palimpsest-plasma`): PMPL is the correct |
| 63 | + licence; 200 files, no action ever. |
| 64 | +* *`007`*: ARR. Out of scope for any normalisation/scan/label. Owner-only. |
| 65 | +* *Vendored `rescript/` forks* (`developer-ecosystem` 42 files): the `rescript/` |
| 66 | + path segment is the estate's upstream-*compiler*-fork carve-out. Never sweep |
| 67 | + upstream fork headers. NOTE: this does NOT cover `nextgen-databases`, whose |
| 68 | + `rescript/` dirs are estate-authored clients, not the vendored compiler (§4). |
| 69 | +* *`zotero-tools/zotpress/`*: upstream WordPress-plugin fork. |
| 70 | +* *Licence-exhibit text* (`standards/LICENSES/PMPL-1.0-or-later.txt`, and within |
| 71 | + the carve-outs: `legal/`, `/exhibits/`, `EXHIBIT-*`, `PMPL-SPEC.adoc`): the |
| 72 | + verbatim Palimpsest licence body. A repo legitimately keeps the PMPL text on |
| 73 | + file regardless of its own licence. |
| 74 | + |
| 75 | +== 4. `nextgen-databases` — RESOLVED (estate-authored → in scope) |
| 76 | + |
| 77 | +The 17 matches sit under `lithoglyph/clients/rescript/...` and |
| 78 | +`verisimdb/connectors/clients/rescript/...`. Evidence settles it: the repo's own |
| 79 | +`verisimdb/llm-warmup-dev.md` reads *"VeriSimDB … Part of the nextgen-databases |
| 80 | +monorepo. License: PMPL-1.0-or-later. **Author: Jonathan D.A. Jewell.**"* These |
| 81 | +are **owner-authored** estate databases and their ReScript *clients*, NOT the |
| 82 | +vendored ReScript-*compiler* fork the `rescript/` carve-out protects. |
| 83 | + |
| 84 | +⇒ **IN SCOPE.** The `.res` client sources → `MPL-2.0`; the client `README.md` |
| 85 | +(prose) → `CC-BY-SA-4.0`. (The estate's ReScript→AffineScript ban is orthogonal: |
| 86 | +these grandfathered `.res` files still get the correct licence now.) This adds |
| 87 | +the 17 `nextgen-databases` files to the actionable set, taking it to **22 files |
| 88 | +across 4 repos**. |
| 89 | + |
| 90 | +== 5. Code vs prose split (which licence per file) |
| 91 | + |
| 92 | +* *Code / config / workflow / source headers* → `MPL-2.0` (or `AGPL-3.0-or-later` |
| 93 | + for idaptik). |
| 94 | +* *Prose docs* (`.adoc`/`.md` narrative: README, guides, EXPLAINME, ROADMAP, |
| 95 | + MAINTAINERS, CONTRIBUTING bodies) → `CC-BY-SA-4.0`. |
| 96 | +* *Machine-readable* (`.a2ml`, `.ncl`, `.scm`, `Justfile`, `Mustfile`) → treat as |
| 97 | + code → `MPL-2.0`. |
| 98 | +* GitHub-required `.md` (SECURITY/CONTRIBUTING/CoC/CHANGELOG) keep `.md` but the |
| 99 | + SPDX line still flips per the code/prose rule above. |
| 100 | + |
| 101 | +== 6. Per-file discipline (the part every prior LLM sweep got wrong) |
| 102 | + |
| 103 | +For each candidate file, OPEN it and flip ONLY a genuine *self-declaration* SPDX |
| 104 | +header. NEVER touch, even when the bytes say `PMPL`: |
| 105 | + |
| 106 | +. Policy/classification tables (a CLAUDE.md that *lists* PMPL as a category). |
| 107 | +. History (CHANGELOG / AUDIT / commit-trail entries describing the old licence). |
| 108 | +. Glossaries / docs that say "PMPL is the FORMER licence". |
| 109 | +. Archived material, incl. any doc embedding an old `sed`-sweep command. |
| 110 | +. Third-party / vendored / forked text and headers. |
| 111 | +. Licence-exhibit / `LICENSES/` / `legal/` verbatim text. |
| 112 | + |
| 113 | +Precedent: in `absolute-zero` #92, 3 stale self-declarations were flipped and |
| 114 | +**10** legitimate PMPL references were deliberately left. Expect a similar |
| 115 | +keep:flip ratio. |
| 116 | + |
| 117 | +== 7. Secondary drift forms (Phase 2 — INVENTORIED) |
| 118 | + |
| 119 | +The §1 inventory covers the canonical `SPDX-License-Identifier:` header. Two |
| 120 | +further org-wide searches quantify what that pass misses: |
| 121 | + |
| 122 | +=== 7a. Body-text `License: PMPL-1.0-or-later` — **236 matches, estate-wide** |
| 123 | +This is the LARGEST drift surface by count, and it is **template-propagated**, |
| 124 | +not hand-written. The bulk come from a shared scaffold replicated across dozens |
| 125 | +of repos: `llm-warmup-dev.md` / `llm-warmup-user.md`, `.well-known/trust.txt` / |
| 126 | +`humans.txt`, REUSE `dep5`, and `CITATION.cff` (many still carrying `{{AUTHOR}}` |
| 127 | +placeholders). Caught absolute-zero's `ai.txt`/`humans.txt`/`.ipkg`; this header |
| 128 | +search does NOT. |
| 129 | + |
| 130 | +**Strategy — fix at the source, not 236 times.** Locate the scaffold generator |
| 131 | +(rsr-template-repo / scaffoldia / the `llm-warmup-*` template) and flip the |
| 132 | +template's licence line to the correct per-category value, THEN re-propagate. |
| 133 | +Doing 236 manual edits invites immediate re-drift on the next scaffold run. |
| 134 | +Exclude carve-outs, `007`, son-shared, and forks from any propagation, exactly |
| 135 | +as in §1/§3. |
| 136 | + |
| 137 | +=== 7b. Banned `MPL-2.0-or-later` → `MPL-2.0` — **25 matches** |
| 138 | +Estate policy is `MPL-2.0` (never `-or-later`). The 25 hits concentrate in |
| 139 | +delicate areas: the `standards` RSR *satellites* (`…/satellites/palimpsest-license/…`, |
| 140 | +`…/consent-aware-http/…`), the carve-out repos themselves, and the `zotpress` |
| 141 | +fork. Few are plain sole-owner code; each needs the §6 per-file eyeball before |
| 142 | +dropping the `-or-later`. Lower priority than 7a. |
| 143 | + |
| 144 | +=== 7c. REUSE files (`.reuse/dep5`, `REUSE.toml`) |
| 145 | +A subset of 7a — mostly template `dep5` files with `{{AUTHOR}}` placeholders. |
| 146 | +Fix with the scaffold, per 7a. |
| 147 | + |
| 148 | +== 8. Per-repo execution procedure |
| 149 | + |
| 150 | +For each actionable repo (developer-ecosystem, email-octad-experiment, idaptik, |
| 151 | +nextgen-databases — all four confirmed in §1/§3/§4): |
| 152 | + |
| 153 | +. Branch `claude/<name>` off latest `main`; never push to main. |
| 154 | +. Open each candidate file; apply §6 discipline; flip only genuine headers to |
| 155 | + the §5 licence. |
| 156 | +. Re-run the repo's own CI locally where it has content-addressed gates |
| 157 | + (e.g. a registry/topology regen — `standards` needed `just registry` after a |
| 158 | + tracked-file edit; expect similar in repos with `.machine_readable/REGISTRY`). |
| 159 | +. Commit per-repo with a clear `chore(licence):` message enumerating files + |
| 160 | + the keep-list. |
| 161 | +. Push `-u origin claude/<name>`; open a **draft** PR; let CI run. |
| 162 | +. Treat pre-existing repo-wide governance/Hypatia-baseline reds as out-of-scope |
| 163 | + (they fail on main too); only fix reds your diff introduced. |
| 164 | +. **Get explicit owner approval on the per-repo change-list BEFORE marking |
| 165 | + ready / merging.** This is the hard gate — owner-only, per repo. |
| 166 | + |
| 167 | +== 9. Capabilities / access a delegated agent needs |
| 168 | + |
| 169 | +[cols="2,5",options="header"] |
| 170 | +|=== |
| 171 | +| Need | Why / specifics |
| 172 | + |
| 173 | +| GitHub MCP scope | Session repo-scope must include the *drift* repos: |
| 174 | + `developer-ecosystem`, `email-octad-experiment`, `idaptik`, |
| 175 | + `nextgen-databases`. (The proof-repo session that produced this runbook is |
| 176 | + scoped to the 10 formal-methods repos — a different set.) Use the session's |
| 177 | + `add_repo` / scope config to add them. Do NOT add `007` (ARR). |
| 178 | +| Write + PR | push to `claude/<name>` branches + open draft PRs (the |
| 179 | + `mcp__github__*` create_pull_request / push path). |
| 180 | +| Read-only verify | `search_code` for the secondary forms in §7; |
| 181 | + `get_file_contents` to apply §6 per-file. |
| 182 | +| Policy doc | This runbook + the estate 5-way licence policy |
| 183 | + (`standards/.claude/CLAUDE.md` §"License Policy — Manual Only"). |
| 184 | +| Toolchain | NONE for the header edits (no proof/build assistant required). |
| 185 | + Only the repo's own CI helpers (e.g. a registry regenerator script) where a |
| 186 | + content-addressed gate exists. |
| 187 | +| NOT needed | Any access to `007`; any bulk-rewrite tooling; any |
| 188 | + cross-repo automated SPDX sweeper (explicitly forbidden). |
| 189 | +|=== |
| 190 | + |
| 191 | +== 10. What this session already did (context) |
| 192 | + |
| 193 | +* `absolute-zero` #92 (merged) — 3 stale PMPL body-declarations → MPL-2.0. |
| 194 | +* `epistemic-types` #13 (merged) — stale "No LICENSE" note corrected. |
| 195 | +* `standards` #433 (MERGED) — `rsr-audit.sh` LICENSE checks MIT/Palimpsest |
| 196 | + → MPL-2.0 (owner-approved discharge of #390's flag). |
| 197 | + |
| 198 | +None of the 10 in-scope proof repos carry stray PMPL *SPDX headers* — only |
| 199 | +`standards` appeared in §1, and its single hit is licence-exhibit text (leave). |
| 200 | + |
| 201 | +== 11. FLAG — `panll` governance conflict (owner decision, do NOT auto-flip) |
| 202 | + |
| 203 | +`panll` carries body-text PMPL (`docs/guides/llm-warmup-user.md`: "License: |
| 204 | +PMPL-1.0-or-later. Author: Jonathan D.A. Jewell") AND its own |
| 205 | +`.claude/CLAUDE.md` still mandates *"PMPL-1.0-or-later on all original source |
| 206 | +files."* By estate policy `panll` is sole-owner ⇒ should be `MPL-2.0`, and is |
| 207 | +NOT one of the three Palimpsest carve-outs — so the local CLAUDE.md is itself |
| 208 | +stale drift. But a repo whose own checked-in governance explicitly mandates PMPL |
| 209 | +must NOT be flipped autonomously: that is a deliberate-looking contradiction |
| 210 | +only the owner can resolve. |
| 211 | + |
| 212 | +**Decision needed:** either (a) `panll` flips to `MPL-2.0` (estate policy) — |
| 213 | +in which case its `CLAUDE.md` licence line flips too, in the same change; or |
| 214 | +(b) `panll` is an intentional PMPL exception — in which case the estate policy's |
| 215 | +carve-out list must be widened to name it. Until the owner rules, `panll` is |
| 216 | +flag-only. (This is the one in-scope proof repo with a body-text PMPL conflict; |
| 217 | +the SPDX-header sweep in §1 is unaffected.) |
0 commit comments