diff --git a/docs/reorg/2026-10-14-tidy/WORK-ORDERS-2026-10-19.adoc b/docs/reorg/2026-10-14-tidy/WORK-ORDERS-2026-10-19.adoc new file mode 100644 index 000000000..5c2785fad --- /dev/null +++ b/docs/reorg/2026-10-14-tidy/WORK-ORDERS-2026-10-19.adoc @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += Work orders, 2026-10-19: the first execution wave +Jonathan D.A. Jewell (hyperpolymath) +v1.2.0, 2026-10-19 +:toc: left +:toclevels: 2 +:sectnums: +:icons: font + +[.lead] +Eight work orders for a sonnet-tier executor, planned at the top tier so +the executor never has to rediscover a fact. Every fact below was measured +against `main` at `75bd5994` on 2026-10-19, and re-checked against the +first two reviews of this file. Each order names its goal, its authority, the +files, the steps, the acceptance commands, and the exact conditions under +which the executor stops and asks instead of deciding. + +Read first: link:README.adoc[the plan] (_Guardrails for every packet_), +then link:HANDOVER.adoc[the handover note], then this file. Where the two +earlier documents say Deno is retired, this file wins: Deno is permitted +at tier 2 since #1249 (ruled 2026-10-14); A2ML remains retired. Where the +handover note says the repo-wide link-rot guard reports two findings, this +file wins too: it reports 443 on `main` from a checkout named `standards`, +which is what CI uses (see _Session mechanics_ for why the name matters). + +== Session mechanics for this wave + +* *Executor:* this session, switched to the sonnet tier. Effort *medium* + for WO-8, WO-1, WO-3 and WO-6; *high* for WO-2, WO-4, WO-5 and WO-7, + which edit validators, CI or many files. +* *One order, one branch, one PR.* Branch `tidy/wo-N-` from the + current `origin/main`. Never reuse a merged branch. The owner has to + grant this session permission to push to `tidy/*` branches once; until + then the executor stops before the first push and says so. WO-1 is the + one exception: it changes nothing in the tree, so it has no branch and + no PR, and its acceptance transcript goes into the issue comment. +* *Never:* merge, force-push, admin-override, touch a licence file or an + SPDX header (a typo in one is still the owner's to fix), edit anything + under `9-archive/` (one exception, granted here: WO-4 creates the new + index file `9-archive/README.adoc`, which describes the district and is + not archived content) or `3-practice/outreach/`, create or extend a + `.a2ml`, edit a descriptile by hand (D313), run + `scripts/registry-readiness.sh` (it rewrites licence text and SPDX + headers; it is a remediation for other repositories, not a check), or + sweep. +* *Before every push, all of:* `bash scripts/check-standards-map.sh`, + `bash scripts/check-canon-lockstep.sh`, + `bash scripts/run-mustfile.sh .machine_readable/contractiles/must/Mustfile.a2ml`, + `bash scripts/run-debtfile.sh .machine_readable/Debtfile.a2ml`, + `bash scripts/link-rot-guard.sh .`, + `bash scripts/link-rot-guard.sh `, + `bash scripts/check-canonical-names.sh origin/main`, + `bash scripts/check-launcher-standard-currency.sh --root .`, + `git diff --check`, plus the order's own acceptance block. +* *Two known reds on `main` that are not yours to sweep.* The Debtfile + probe `deno-residue` is BREACHED (3 against a ceiling of 1) since #1249; + WO-8 retires it and runs first, and until WO-8 merges every other order + records that breach in its PR body instead of being blocked by it. The + repo-wide link-rot guard reports 443 broken internal links (exit 1) on `main` + (439 before #1272 added four; 285 under `docs/`) when run from a + checkout whose directory is named `standards`, as CI's is: the guard + prunes `9-archive/` only under that basename (`link-rot-guard.sh` line + 31), and from a directory of any other name it reports 684, the extra + 241 being inside the frozen archive. Measure from a checkout named + `standards`, or compare before-and-after counts within one checkout, + never across the two. Record the repository-wide output, finding count + and exit status in the PR body against that baseline, alongside the + touched-directory results; investigate any new findings. The 443 are + a packet of their own; leave those existing broken links alone. +* *PR body:* the order id, the authority line per change, the acceptance + block with every result pasted verbatim, a "not done" list. Open as a + draft; mark ready when the acceptance block is green; watch CI; fix + reds; stop at merge. +* *Stop and ask* whenever an order's _Escalate if_ condition is met. A + stop is a one-paragraph message naming the order, the condition, both + arms with the elegant one first, and what you did meanwhile. +* *Order and concurrency* (at most three PRs open at once): + WO-8 first, because it unblocks the Debtfile gate; then WO-1 (issue + only, it holds no PR slot); then WO-2 + and WO-3 in parallel; then WO-4, WO-5 and WO-6 strictly in that + sequence (all three edit `.hypatia-baseline.json`); WO-7 may run beside + WO-4. P1.2, P1.3, P1.6 and P1.9 are not in this wave: they wait on the + owner items at the end. + +== WO-8: the handover note and the Debtfile after #1249 + +*Goal.* The handover note, the plan and the Debtfile stop treating Deno +as banned, and the Debtfile measure is green again. + +*Authority.* #1249, ruled 2026-10-14: Bun > Deno > pnpm > npm; Deno tier +2, "notice only" for a repository that authors in Deno; the refusal +ledger retired; A2ML unchanged. + +*Facts measured.* `HANDOVER.adoc` lines 205, 224 and 281 say Deno is +retired or that "Deno first" is wrong because Deno is retired; its +_Session model_ section also claims the repo-wide link-rot guard reports +two findings (it reports 443 from a checkout named `standards`; see +_Session mechanics_). The plan's `README.adoc` has rows whose +premise was the Deno ban (the P2.3 acceptance line, the contradictions +register). In `.machine_readable/Debtfile.a2ml`, `deno-residue` (line 92) +counts `denoland/setup-deno`, `deno run`, `deno test`, `deno fmt` and +`deno lint` in workflows and scripts; it measures 3 against a ceiling of +1 because #1249 added exactly those uses, which the ruling permits. +`deno-artefacts` (line 102) counts Deno-named files and was written for +the same ban. `ci-pipeline.yml` (lines 454 to 482) treats `deno.json(c)` +as permitted tier-2 configuration and only emits a notice. + +*Steps.* +. Rewrite the three handover lines: A2ML is retired; Deno is permitted at + tier 2 by #1249, Bun stays first, so "Deno first" in the briefing files + is still wrong, for a different reason. Replace the "two findings" + sentence with the 443 figure, the checkout-name caveat from _Session + mechanics_, and the rule that the guard runs repository-wide, recording + the known baseline, alongside checks on touched directories. +. In the plan, do not rewrite history: add a dated one-line note under + each affected row ("2026-10-19: Deno is tier 2 since #1249; this row's + Deno clause is withdrawn"). +. Retire both Debtfile entries, `deno-residue` and `deno-artefacts`: the + condition they measured is no longer debt. Do not re-scope them to + `deno.json`, which #1249 permits. Do not delete + `scripts/check-ts-allowlist.deno.js`; pinned consumers still invoke it, + and its fate is task #59, not this order. Removing an entry needs a + declaration in the commit message, one line per entry: + `Debt-exception: deno-residue — retired, Deno is tier 2 since #1249` + and the same for `deno-artefacts`. +. Grep both prose files for "Deno" and list every hit with its + disposition in the PR body. + +*Acceptance.* +---- +grep -n -i 'deno' docs/reorg/2026-10-14-tidy/HANDOVER.adoc -> no line says retired or banned +bash scripts/run-debtfile.sh .machine_readable/Debtfile.a2ml -> 0 breached, 0 broken-probe +bash scripts/check-debtfile-structure.sh .machine_readable/Debtfile.a2ml -> structure OK +bash scripts/link-rot-guard.sh docs/reorg/2026-10-14-tidy -> all links resolve +On the PR: governance / Debt ratchet green (it reads the declarations). +---- + +*Escalate if* a plan row's whole purpose was the Deno ban (not just a +clause); then the row is struck with a note, and the owner is told. + +== WO-1: close out #1290 (lockfile self-SHA refs) + +*Goal.* Finish issue #1290 with evidence. The outage it describes is +already repaired on `main`, and the guard and its negative test already +exist; what remains is the re-measurement the issue asks for and the +evidence comment. This order is issue-only: no branch, no push, no PR. +The acceptance transcript is pasted into the #1290 comment instead of a +PR body. + +*Authority.* #1290 acceptance criteria 1 to 4, owner-filed. + +*Facts measured.* The four leaf entries now carry tag refs in +`.github/workflows/actions.lock`: `github/codeql-action` v4.38.0, +`goto-bus-stop/setup-zig` v2.2.1, `swatinem/rust-cache` v2.9.2, +`webfactory/ssh-agent` v0.10.0. No third-party entry's `ref:` equals its +own key SHA any more. `scripts/lock-selfcheck.sh` reports such an entry +as POISON (its `self_sha_deps` pass, exit 1) and the Lock Self-Check +workflow is green on `main`. `scripts/tests/lock-selfcheck-test.sh` +already carries the negative control: the case named "self-SHA ref in +dependencies is POISON (standards#1271)" builds a dependency whose `ref:` +is its own SHA and expects exit 1 with the text `self-SHA ref`. + +*Steps.* +. Find the commits that corrected the four refs: + `git log --format='%h %s' -8 -- .github/workflows/actions.lock`. +. Run `bash scripts/tests/lock-selfcheck-test.sh` and confirm the + self-SHA case passes. Prove the guard once: comment out the + `self_sha_deps` block in `lock-selfcheck.sh`, watch that case fail, + restore the file, run again. Nothing in the tree changes. +. Re-measure one caller: find any estate repository whose workflow pins a + standards reusable at or after the fixing commit and whose latest run + passed Set up job. Record repository, run id, pin. If none exists yet, + say so; do not push to a repository outside this session's scope. +. Comment on #1290 with a four-row table (entry, ref now, fixing commit), + the name of the existing negative test, the re-measurement, and the + acceptance transcript below pasted verbatim. Close the issue only if + the owner has given the P1.2 approval; otherwise leave it open with the + evidence. + +*Acceptance.* +---- +bash scripts/tests/lock-selfcheck-test.sh -> all cases pass +bash scripts/lock-selfcheck.sh "$(git rev-parse origin/main)" -> SELF-CONSISTENT +git status --porcelain -> empty (the tree is as it was) +---- + +*Escalate if* any entry other than the four still carries a self-SHA ref +(then the guard is not catching it, which is a second bug), or if the +re-measured caller is still dying at Set up job. + +== WO-2: mirror honesty (P1.5; #950, #1002) + +*Goal.* The Mirror to Git Forges run on `main` is green or honestly +skipped, and the reusable can no longer hide a failure. + +*Authority.* Plan row P1.5; D261 for the destinations; applied-unless-struck (D113). + +*Facts measured.* Run 39242703018 on `75bd5994`: all seven forge jobs ran, +so all seven `*_MIRROR_ENABLED` repository variables are `true`. GitLab +and Radicle succeeded. Sourcehut, Disroot and Gitea failed at their +"Verify SSH host" step. Codeberg and Bitbucket passed the host +check and failed at the push step. The reusable is +`.github/workflows/mirror-reusable.yml` (445 lines). The GitLab job +(lines 78 to 140) is the pattern the others copy, and it carries two +failure suppressions: `continue-on-error: true` on the job (line 80) and +on its push step (line 126), so a GitLab failure shows green with a +warning. Line 441 is `rad sync --announce || echo "Radicle sync +attempted"`, which turns a failed sync into a green step. The caller in +this repository is `.github/workflows/mirror.yml`, pinned to the +reusable at `427eb35c`. + +*Steps.* +. Read the failing steps' logs for the five red jobs and record the + reason per forge in the PR body (fingerprint variable absent, host key + mismatch, destination repository missing, key refused). +. Remove the `|| echo` on line 441. A failed Radicle sync fails the step. +. Remove both GitLab `continue-on-error: true` lines (80 and 126). The + comment above line 126 explains that GitLab branch protection may block + the force-push; that is a real failure and must show red, with the + owner action the comment already names. GitLab passes today, so this + does not redden `main` by itself. +. Add a destination probe to each forge job, before its push step, + guarded by the same key-presence check: run `git ls-remote "$REMOTE_URL"` + with no ref argument and capture its stderr. Exit 0 means reachable, + including an empty repository awaiting its first push (do not add + `--exit-code`, which fails on an empty repository), so the push + proceeds. The probe skips the push, with a `::notice::` naming the + forge and D261, in exactly one case: a non-zero exit accompanied by + forge-specific evidence that the repository is absent. Record that + evidence and its source in the PR body; for example, an authenticated + forge API check with access sufficient to distinguish an absent + repository from a private one. Generic stderr such as `not found`, + `does not exist` or GitLab's `could not be found` is insufficient: + GitLab can use the same wording for a missing repository and denied + access. An API 404 alone is likewise insufficient if the forge masks + denied access that way. If the probe cannot distinguish absence from + denied access, print the captured stderr and fail the job red. Every + other non-zero exit, including a refused or revoked key, a host-key + problem, a transport failure or a DNS miss, also prints the captured + stderr and fails the job red. `git ls-remote` returns the same status + (128) for all of these; neither that status nor ambiguous wording + proves absence, and the default without conclusive evidence is red. A + reachable destination that refuses the push stays red. +. Add an empty-host guard: when the resolved mirror organisation or host + is empty, skip with a `::notice::`, never push to an empty path. +. Keep the SSH fingerprint verification exactly as strict as it is. +. Do not edit `actions.lock` unless a `uses:` line changed; if one did, + regenerate with the repository's own relock tooling, never by hand. +. In the PR body, list the five variables the owner flips to `false` on + this repository until D261 provisions the forges: + `SOURCEHUT_MIRROR_ENABLED`, `DISROOT_MIRROR_ENABLED`, + `GITEA_MIRROR_ENABLED`, `CODEBERG_MIRROR_ENABLED`, + `BITBUCKET_MIRROR_ENABLED`. Variables are not in the tree; the executor + cannot set them. + +*Acceptance.* +---- +test "$(grep -c '|| *echo' .github/workflows/mirror-reusable.yml)" -eq 0 -> no matches (exit 0) +test "$(grep -c 'continue-on-error' .github/workflows/mirror-reusable.yml)" -eq 0 -> no matches (exit 0) +bash scripts/check-workflow-duplicate-keys.sh -> clean +bash scripts/lock-selfcheck.sh "$(git rev-parse HEAD)" -> SELF-CONSISTENT (after push) +Mirror to Git Forges on main after merge: GitLab and Radicle green; every +other forge skipped with a notice (once the variables are flipped) or red +with a named reason, never green on a failure. +---- + +*Escalate if* any forge fails on a host-key fingerprint mismatch (a +security condition the owner decides), or if making a step honest would +turn `main` permanently red before the owner can flip the variables; in +that case open the PR as a draft and say so. + +== WO-3: community health files (P1.8) + +*Goal.* GitHub's community profile shows a code of conduct, contributing +guide and citation file, each pointing at the canonical source. + +*Authority.* Plan row P1.8; the docs rule that GitHub-required files are +Markdown; applied-unless-struck (D113). + +*Facts measured.* Root has `SECURITY.md` and `READINESS.md`. Root has no +`CODE_OF_CONDUCT.md`, `CONTRIBUTING.md` or `CITATION.cff`. The sources are +`3-practice/CODE_OF_CONDUCT.adoc` and `3-practice/CONTRIBUTING.adoc`. +`standards-map.toml` has `entry_count = 129`. The Debtfile probe +`docs-md-not-adoc` counts only `docs/`, so root Markdown does not move it. +`canon.lock` records `version = "2.1.2"` and `released = "2026-09-30"`. + +*Steps.* +. Write `CODE_OF_CONDUCT.md` and `CONTRIBUTING.md`: a title, two or three + sentences, and a link to the `3-practice/` source. No duplicated + content. SPDX comment at the top as `SECURITY.md` does it. +. Write `CITATION.cff` (`cff-version: 1.2.0`): `message` (one sentence + asking readers to cite the canon; CFF 1.2.0 requires the key, and + GitHub does not render "Cite this repository" for a file that fails + its schema), `title`, the owner as the one entry under `authors`, + `repository-code`, `license: MPL-2.0`, and `version` and + `date-released` copied together from `canon.lock` (2.1.2 and + 2026-09-30), never today's date, so the citation names a real release. +. Add three `[[entry]]` blocks to `standards-map.toml` after the + `SECURITY.md` block, `district = "root"`, `kind = "onramp"`, + `lifecycle = "versioned"`, `canonical = false`, and raise `entry_count` + by three. + +*Acceptance.* +---- +bash scripts/check-standards-map.sh -> GATE D PASSED +grep -c -E '^(cff-version|message|title|authors):' CITATION.cff -> 4 (the keys CFF 1.2.0 requires) +link_rot="$(bash scripts/link-rot-guard.sh .)" || test "$?" -eq 1 +printf '%s\n' "$link_rot" | awk '/^BROKEN/ {n++} END {print n+0}' -> the same count as on origin/main in this checkout (443 when it is named standards) +bash scripts/run-debtfile.sh .machine_readable/Debtfile.a2ml -> docs-md-not-adoc unchanged +GitHub community profile after merge: all items present, and the repository +page shows "Cite this repository" (GitHub renders it only for a valid file). +---- + +*Escalate if* the map's root district refuses a new `kind`, or if the +docs-format workflow rejects a root `.md`; both would mean the rule in +the plan is wrong, which is the owner's to settle. + +== WO-4: the archive is frozen (P1.4) + +*Goal.* No policy validator or language job scans `9-archive/`, and the +archive carries a banner saying so. Security scanners keep scanning it: +a leaked secret is a leak wherever it sits. + +*Authority.* Plan row P1.4; the exemption contract in +`docs/EXEMPTION-MECHANISMS.adoc`; applied-unless-struck (D113). + +*Facts measured.* No `.hypatia-ignore` exists in this repository, and the +exemption contract forbids creating one with a directory or wildcard +line: `docs/EXEMPTION-MECHANISMS.adoc` (_Anti-patterns to reject_) +requires one full path per line, and `scripts/check-exemption-ratchet.sh` +treats the file as a migration ledger that may only shrink. Eighteen +baseline entries have a path under `9-archive/`; under that contract they +are the correct Layer 2 mechanism and stay. The Hypatia scan workflow +offers no path-exclusion input. There is no `9-archive/README.adoc`; the +district holds `REORGANIZATION-PLAN.adoc` and +`rhodium-standard-repositories/`, both mapped. In `ci-pipeline.yml` the +`detect` job counts files with a `count` helper built on git pathspecs +(around line 129); the per-language jobs reuse the same pathspecs. Ten +local gate scripts walk this tree without an archive exclusion: +`check-canon-lockstep.sh`, `check-descriptile-policy.sh`, +`check-inline-python.sh`, `check-launcher-standard-currency.sh`, +`check-licence-consistency.sh`, `check-trusted-base.sh`, +`check-ts-allowlist.sh`, `fix-workflow-duplicates.sh`, +`kyaml-migrate.sh`, `verify-claims.sh`. Two of the ten write: +`kyaml-migrate.sh` rewrites every YAML file it reformats unless given +`--check`, and `fix-workflow-duplicates.sh` generates wrapper workflows +under every nested `.github/workflows/` it finds, with no dry-run flag. +An earlier revision of this order listed `scripts/registry-readiness.sh` +as an eleventh; it is not a validator of this tree but a licence-rewriting +remediation meant to be run inside a Julia package (its header says so), +and the never-list forbids running it here. The `language-policy` job of +`governance-reusable.yml` also gathers candidates repo-wide: `git +ls-files` for the banned languages at lines 609 to 638, `find` for the +package anti-patterns at lines 662 to 665. It is a reusable workflow, so +an exclusion written into its body would apply to every estate +repository that calls it; this repository calls it by local path from +`governance.yml`. The archive holds no file either block matches today, +so the job is green and the exclusion is prospective: it exists so that a +later policy expansion cannot be failed by frozen content. The secret +scanners (`secret-scanner-reusable.yml`, the security policy step in +`governance-reusable.yml`) walk the whole tree, by design. + +*Steps.* +. Do not create `.hypatia-ignore`. Leave the eighteen archive acks in the + baseline. +. In `ci-pipeline.yml`, add `':!9-archive/**'` to the `count` pathspecs + and to every per-language job pathspec that mirrors them, so archive + files cannot flip a `has_` output or feed a job. +. Create `9-archive/README.adoc`, the one write under the archive this + wave permits (granted in the never-list above), with one paragraph: + frozen, not edited, excluded from policy validators, still + secret-scanned; pointers to the plan and the map entries. The link-rot + guard prunes the archive in CI, so check that file's links by eye. +. Discover without mutating. Run the eight check-only scripts against + `main`: `check-canon-lockstep.sh`, `check-descriptile-policy.sh`, + `check-inline-python.sh`, `check-launcher-standard-currency.sh --root .`, + `check-licence-consistency.sh`, `check-trusted-base.sh`, + `check-ts-allowlist.sh`, `verify-claims.sh`. Run + `bash scripts/kyaml-migrate.sh --check` and nothing else from that + script. Do not run `fix-workflow-duplicates.sh`; read its `find` (the + function near line 60 that lists nested `.github/workflows/` + directories) and judge from the text whether it reaches the archive. + Then `git status --porcelain` must be empty before you edit anything. + Where a script reports a finding whose path is under `9-archive/`, or + the generator's walk reaches it, add the exclusion in that script's own + idiom (a `:!9-archive/**` pathspec, or a prune on the `find`) and + record it. Where one reports nothing under the archive, leave it alone + and record that too. Put the ten-row table in the PR body. Never touch + the secret scanners. +. Give `governance-reusable.yml` an opt-in input, + `policy_exclude_pathspec` (type string, default empty), and append it + to each `git ls-files` call of the banned-language block (lines 609 to + 638). The empty default keeps every other caller exactly as strict as + today. In `governance.yml`, which calls the reusable by local path so + both halves land in one PR, pass + `policy_exclude_pathspec: ':!9-archive/**'`. Leave the three `find` + calls of the package anti-pattern block (lines 662 to 665) as they are: + they match only lockfile names, the frozen archive holds none, and a + second idiom for the same input is not worth its lines; record them in + the table. Leave the hygiene walks later in the same workflow + (`.git/config`, executable scripts, large files) untouched and list + them. The elegant arm is this input; the other arm, leaving the + workflow alone because the archive matches nothing today, is named in + the PR body for the owner to prefer if they wish. +. In the PR body, draft the follow-up for the owner: a hypatia-side order + (opus tier, separate PR in `hyperpolymath/hypatia`) that adds the + `9-archive/` district to the scanner's built-in exclusions in + `lib/hypatia/scanner_suppression.ex`, after which the eighteen acks can + be dropped under the exemption contract. + +*Acceptance.* +---- +jq '[.[] | select((.file // .path // "") | startswith("9-archive/"))] | length' .hypatia-baseline.json -> 18 (unchanged) +test ! -f .hypatia-ignore +git status --porcelain (right after the discovery step, before any edit) -> empty +bash scripts/check-workflow-duplicate-keys.sh -> clean +grep -c 'policy_exclude_pathspec' .github/workflows/governance-reusable.yml -> at least 2 (the input and its use) +grep -c "policy_exclude_pathspec: ':!9-archive/\*\*'" .github/workflows/governance.yml -> 1 +On the PR: ci-pipeline, hypatia-scan, Validate Hypatia Baseline, Exemption ratchet and +governance / Language / package anti-pattern policy green; the ten-row validator table in the body. +---- + +*Escalate if* any of the ten scripts reports an archive finding that +its idiom cannot exclude without changing what it checks elsewhere, if a +per-language job's pathspec is shared with a consumer input, or if the +new reusable input changes any job's behaviour for a caller that does +not pass it (the default must be a no-op; a second consumer in the tree +that calls the reusable proves it). + +== WO-5: delete the Python deed tools (P1.10; D313, #944) + +*Goal.* `deed_lint.js` is the only validator; no Python in the tree; no +live document tells anyone to run the Python one. + +*Authority.* D313 (conversion is kyX's first front end; Python is +banned); plan row P1.10. + +*Facts measured.* `1-formats/deed/tools/` holds `a2ml_to_deed.py`, +`deed_lint.py`, `migrate_a2ml_to_deed.sh`, `deed_lint.js`, +`deed_lint.test.js`, `fixtures/`, `README.adoc`. The README describes the +Python tools at lines 10 to 18, 45, 51 to 68 and 84. The baseline carries +one ack each for `a2ml_to_deed.py` and `deed_lint.py`. These are the only +`.py` files outside the archive. The mapping specification +`1-formats/deed/mappings/launcher-standard-to-praxis-deed.adoc` names +`deed_lint.py` at lines 46, 211, 271 and 316, including a runnable +`python3 … deed_lint.py` verification command at line 271 and mutant +evidence measured with the Python tool. + +*Steps.* +. `git rm` the two `.py` files and the migration shell script in one + commit; no content change in that commit. +. In a second commit, rewrite the tools README: `deed_lint.js` is the sole + validator; conversion is deferred to kyX (D313); drop the Python usage + blocks and the fixture note that referred to `deed_lint.py`. +. In the same commit, update the mapping specification: the verification + command at line 271 becomes the `bun 1-formats/deed/tools/deed_lint.js` + form and is re-run so its "OK" is a measured result; the mutant + sentences at lines 46, 211 and 316 are either re-measured against + `deed_lint.js` or marked as historical evidence from the retired tool. + Never claim the JS validator was mutated unless you ran the mutant. +. Remove the two acks from the baseline, byte-identical formatting. +. Run the JS tests the way the README says; if it does not say, run + `bun 1-formats/deed/tools/deed_lint.test.js` and record the command. + +*Acceptance.* +---- +git ls-files '*.py' | awk '!/^9-archive\// {print; found=1} END {exit found}' -> empty (exit 0) +git grep -n 'deed_lint\.py' -- . ':!9-archive' ':!docs/reorg' || test "$?" -eq 1 -> empty or only lines marked historical +bun 1-formats/deed/tools/deed_lint.js 0-AI-MANIFEST.deed -> OK +bash scripts/check-inline-python.sh -> clean +bash scripts/tests/apply-baseline-test.sh -> pass +On the PR: deed-conformance, language policy and Validate Hypatia Baseline green. +---- + +*Escalate if* anything outside the tools directory and the mapping +specification imports or calls the deleted files (grep the tree for +their names first), or if a test fixture only the Python linter +understood would be orphaned. + +== WO-6: `.github/` hygiene (P1.7) + +*Goal.* No never-filed issue drafts, no unpinned agent config, a correct +CODEOWNERS, and a pull-request template with the lockfile checkbox. + +*Authority.* Plan row P1.7; applied-unless-struck (D113). + +*Facts measured.* `.github/ISSUES/` holds seven Markdown drafts dated +2026-06-05, never filed. `.github/copilot/coding-agent.yml` configures a +Copilot coding agent with an unpinned `npx … @latest` and a plain-HTTP +localhost URL; the baseline carries one ack for it. `CODEOWNERS` line 2 +reads `SPFX-License-Identifier: CC-SA-BY-4.0` (two typos in an SPDX +header, which the executor does not edit); it names a `Makefile` +(banned) and `3-practice/SECURITY.md` (GitHub reads only the root file); +`1-formats/contractiles/` exists, keep it. `dependabot.yml` has a long +HOLD comment on `codeql-action`; nothing in it contradicts the weekly +interval on a first reading. There is no pull-request template. + +*Steps.* +. `git rm -r .github/ISSUES/`. Before that, list the seven titles in the + PR body; any item still live is re-filed by the owner through the + campaign template, not by the executor. +. `coding-agent.yml`, by the owner's answer: "not in use" means delete it + and its baseline ack; "in use" means pin the package to a version and + keep the ack; no answer by the time the rest is ready means push + everything else, leave the file and its ack untouched, and say so. The + default on silence is defer, never delete. +. `CODEOWNERS`: drop the `Makefile` and `3-practice/SECURITY.md` lines; + add `SECURITY.md @hyperpolymath`. Leave line 2 as it is and list it for + the owner: an SPDX header is the owner's to correct, typo or not. +. `dependabot.yml`: compare every comment with the schedule it sits next + to; correct a comment only where it states something the file does not + do. If nothing is wrong, write that in the PR body and change nothing. +. Add `.github/PULL_REQUEST_TEMPLATE.md`: What and why; Authority + (ruling id, map target, or applied-unless-struck D113 with the arm + named); Acceptance block; a checklist with "actions.lock regenerated + with the repo tooling if any workflow changed", "no licence text or + SPDX header touched", "no .a2ml created or extended". + +*Acceptance.* +---- +test ! -d .github/ISSUES && test -f .github/PULL_REQUEST_TEMPLATE.md +git diff --unified=0 origin/main -- .github/CODEOWNERS | awk '/^[+-].*License-Identifier/ {print; found=1} END {exit found}' -> empty (exit 0) +bash scripts/tests/apply-baseline-test.sh -> pass +On the PR: labels and label-triage workflows green; Validate Hypatia Baseline green. +---- + +*Escalate if* any of the seven drafts describes work that is still open +and unfiled (list them; the owner decides). + +== WO-7: follow the manifest rename through (after #1272) + +*Goal.* The repository's own references to its machine front door name +the file that exists. + +*Authority.* #1272 renamed `0-AI-MANIFEST.a2ml` to `0-AI-MANIFEST.deed` +by hand on 2026-10-17; the file lints clean as a deed and the Mustfile +already expects the new name. Path repairs that a move makes necessary +are allowed by the plan's guardrails. Everything estate-facing is the +owner's (see bucket B). + +*Facts measured.* Sixty-three files outside `9-archive/` still name the +old file. The rename also added four broken links to the repo-wide +link-rot count. They fall into three buckets. + +* *Bucket A, fix now: this repository's own pointers to its own file.* + `Justfile` lines 139 and 140 (the fallback `cat` now names a missing + file), `AGENTS.adoc` 4, `EXPLAINME.adoc` 11 (a link), `ROADMAP.adoc` + 103, `QUICKSTART-DEV.adoc` 10, 62 and 113, `llm-warmup-dev.adoc` 4, + `llm-warmup-user.adoc` 4, `3-practice/ai-instruction/README.adoc` 73 (a + link whose target must become `../../0-AI-MANIFEST.deed`: the file sits + two directories down, and its present `../` target never resolved), + `docs/wikis/README.adoc` 27, `TOPOLOGY.adoc` 18 (a link). +* *Bucket B, do not touch; put to the owner as the D338 follow-through:* + anything that tells the estate what file to have or grades it on + having one: `0-canon/rsr/rsr-criteria-v2.a2ml` criterion 2.3.1, + `0-canon/GOVERNANCE.adoc` 56, `0-canon/TEMPLATE-APPLICABILITY-POLICY.adoc`, + `.machine_readable/template-capability-gates.toml`, + `scripts/registry-readiness.sh`, `scripts/check-manifest-ply.sh` and its + test, `3-practice/immaculate-guide/IMMACULATE-GUIDE.adoc`, + `3-practice/TEST-NEEDS.adoc`, + `3-practice/testing-and-benchmarking/TESTING-TAXONOMY.adoc`, + `component-readiness-grades/COMPONENT-READINESS-GRADES.adoc` 210, + `component-readiness-grades/SELF-ASSESSMENT.adoc` 41, + `toolchain-readiness-grades/TOOLCHAIN-READINESS-GRADES.adoc` 198 and + 470, `docs/wikis/users/index.adoc` 28, + `2-protocols/overlay/scripts/check-conformance.sh`, + `2-protocols/k9-coordination/README.adoc` and its spec table, + `.machine_readable/MUST.contractile` line 66, + `.machine_readable/contractiles/dust/Dustfile.a2ml` line 28, and every + `AGENTIC.a2ml` descriptile (D313 forbids hand edits). The question for + the owner: accept both names estate-wide during the transition, or + revert #1272 until the manifest family has its ruling (D338 proposed + manifest clauses on the repo deed, not a standalone file). +* *Bucket C, leave: historical and spec text.* The AI-gatekeeper protocol + documents and examples, the ensaid specification, the overlay + specification, `docs/reorg/` (dated records), `docs/archive/`, + `.machine_readable/archive/`, `standards-update/`. + +*Steps.* +. Edit bucket A only. In `Justfile`, the fallback becomes + `cat 0-AI-MANIFEST.deed` and the echo names the deed. Links point at + `0-AI-MANIFEST.deed` by the relative path that resolves from each file; + a rename alone is not enough for the nested one, which needs + `../../0-AI-MANIFEST.deed`. Run the link-rot guard on each touched + directory and confirm the manifest link resolves. +. In the PR body, paste bucket B as a table (file, line, what it asserts) + under the heading "D338 follow-through, owner decision". +. Post the same table as one comment on #1234, booking no id, with the + two arms. + +*Acceptance.* +---- +for f in ; do test "$(grep -c '0-AI-MANIFEST\.a2ml' "$f")" -eq 0 || exit 1; done -> no old-name references (exit 0) +link_rot="$(bash scripts/link-rot-guard.sh .)" || test "$?" -eq 1 +printf '%s\n' "$link_rot" | awk '/^BROKEN/ {n++} END {print n+0}' -> 439 or fewer from a checkout named standards (the four from #1272 gone; 680 or fewer from any other name) +test "$(printf '%s\n' "$link_rot" | grep -c '0-AI-MANIFEST')" -eq 0 -> no broken manifest links (exit 0) +bash scripts/check-launcher-standard-currency.sh --root . -> no stale references +bash scripts/run-mustfile.sh .machine_readable/contractiles/must/Mustfile.a2ml -> 14 passed +---- + +*Escalate if* a bucket A file turns out to state an estate rule rather +than a self-reference (move it to bucket B), or if any bucket B tool +is red on `main` because of the rename (then the owner's answer is +urgent, and the PR body says which gate is red). + +== Owner items this wave depends on + +. Grant this session permission to push `tidy/*` branches, one line. +. Flip the five mirror variables to `false` on this repository (WO-2), or + provision the forges under D261. +. Answer the Copilot coding-agent question (WO-6): delete, or pin and + keep. Silence means the file stays. +. Fix the SPDX header typo on `CODEOWNERS` line 2 yourself (WO-6 flags + it; agents do not edit SPDX headers). +. Answer the D338 follow-through (WO-7): both manifest names estate-wide + during the transition, or revert #1272. +. Approve the dispositions table so P1.2, P1.3 and P1.9 can run, and so + WO-1 may close #1290. +. Post the decision sheet (plan, _Owner decision sheet_) to #1234. +. Close #1287 and #1288 (probes) and #1289 (its PR merged on 2026-10-19). +. Decide whether the 443 broken internal links on `main` outside the + archive become a packet of their own (241 more sit inside the frozen + archive, where the guard prunes them in CI and nothing can be fixed). +. Prefer an arm for the archive carve-out in `governance-reusable.yml` + (WO-4): the opt-in `policy_exclude_pathspec` input, a new surface on a + reusable every estate repository calls but a no-op by default, or no + change because the archive matches nothing today. The order ships the + input unless you say otherwise.