fix(docs): correct claims the first fix round asserted without measuring

Why: two blind verifiers re-ran the five preceding commits and found four
defects of the same class this branch exists to close -- a confidently stated
measured claim that does not survive re-measurement -- this time inside the
fixes themselves.

- AGENTS.md:41 still carried both phrasings c68e864 reports having corrected.
  `grep -rn repo-defined` returned exactly one hit repo-wide: that line, in the
  file every session preloads. 4d336bb edited the line directly above it.
- ADR-0021 asserted twice, in the section justifying that no gate is added,
  that the ADR-0020 validators "never open an apm.yml". All three open and
  yaml.safe_load it (skill-size-check.sh:342, both validate.sh). The conclusion
  survives -- none reads the description: key, and their globs are SKILL.md and
  *.agent.md only -- but the stated mechanism is falsified by one grep.
- architecture.md said the ADR directory holds 20 numbered ADRs; c7ba3d2 made
  it 21, and c68e864 audited that file for exactly this class of stale count.
  The number is dropped rather than corrected: `ls docs/adr/` is already the
  index, so a count in prose is a second thing to maintain.
- gates.md's new three-verdict table said `-> name` promotes an unresolved
  target to ERROR. Reproduced with fixtures: NAME_HYPH (skill-size-check.sh:543)
  requires a hyphen, so `-> gitea-prs` is checked and `-> triage` is not
  extracted at all, and the unicode arrow is never recognised. The SUGGESTION
  text advises that spelling, so taking its advice can silence the finding. The
  gap is now documented as a defect; nothing covers it, since the one arrow case
  in test-adr0020-targets.sh happens to use a hyphenated target.

Implementation notes:
- AGENTS.md:48's coverage claim is shrunk rather than chased. Restoring six
  glossary entries did not make it true: 12 more sampled terms are undefined,
  three of them (trigger/capability/boundary clause) used inside CONTEXT.md
  itself. It now says CONTEXT.md is the glossary and is not exhaustive.
- CONTEXT.md's output profile and near-miss entries are corrected against their
  sources. The first stated a false exclusion -- .github/plugin/plugin.json IS
  apm-generated; only the marketplace mirror has no profile. The second
  inverted its source's referent: description-quality.md defines a near-miss as
  a query, not a sibling skill.
- The strict-mode message named jq, which no suite guards on (`command -v jq`
  appears nowhere in tests/), while omitting python3/PyYAML, which three do.
- README's git and gitea bullets now name git-workflow and gitea-workflow.
  ADR-0021 leaves README the only inventory and architecture.md now points at
  it, so the two bullets that were short had to be completed.
- ADR-0018's 2026-08-14 correction is marked superseded in place. It asserted
  machine state in the present tense that its own 2026-08-17 note retracts.
- ADR-0021's remaining errors: six files -> four (measured from de84d1b), the
  wiki description's length 114 -> 96 chars, the codex self-contradiction, the
  cost argument overstating bumps already owed for any skill addition, and two
  claims about files this branch went on to edit.
- The "15 of 17 suites" figure is restored where I had removed it: it is a dated
  record of one incident, not a live count, and four sites now describe it the
  same way.

Impact: 16/16 pre-push hooks pass, suite 24 passed 0 skipped 0 failed. No
behaviour change; every edit is prose or a comment.

Refs: #105

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
This commit is contained in:
2026-08-17 13:18:55 +00:00
parent c68e864159
commit d42f6368fe
9 changed files with 61 additions and 41 deletions

View File

@@ -38,14 +38,14 @@ Fall back to raw shell only when no skill covers it.
- **A `.apm/` edit is not live in this session until it is pushed.** The six dependencies resolve from the holocron remote, unpinned against the default branch. `apm install` deploys from the lock; `apm update` is what re-resolves refs. - **A `.apm/` edit is not live in this session until it is pushed.** The six dependencies resolve from the holocron remote, unpinned against the default branch. `apm install` deploys from the lock; `apm update` is what re-resolves refs.
- **The ADR-0020 skill gates ship hot, with no baseline.** 26 of 39 descriptions and 9 of 39 bodies exceed their FAIL tier, and the `Kyberforge.CompositionNote` Vale rule fires 10 errors across `gitea-issues`, `gitea-labels-milestones`, `gitea-prs` and `gitea-workflow`. Editing any of those skills *for any reason* means retrofitting it to the contract first — a one-line fix cannot be committed until the skill complies. Deliberate; tracked as Gitea issue #99. `skill-size-check` will not warn you about the Vale half, so check both: `pre-commit run --all-files`. - **The ADR-0020 skill gates ship hot, with no baseline.** 26 of 39 descriptions and 9 of 39 bodies exceed their FAIL tier, and the `Kyberforge.CompositionNote` Vale rule fires 10 errors across `gitea-issues`, `gitea-labels-milestones`, `gitea-prs` and `gitea-workflow`. Editing any of those skills *for any reason* means retrofitting it to the contract first — a one-line fix cannot be committed until the skill complies. Deliberate; tracked as Gitea issue #99. `skill-size-check` will not warn you about the Vale half, so check both: `pre-commit run --all-files`.
- **Run `bash tests/run-tests.sh --strict` before considering any change done.** Keep the flag: without it a suite whose dependency is missing exits 77 and is counted SKIPPED rather than failed, so the run goes green having verified less than it claims. - **Run `bash tests/run-tests.sh --strict` before considering any change done.** Keep the flag: without it a suite whose dependency is missing exits 77 and is counted SKIPPED rather than failed, so the run goes green having verified less than it claims.
- **Before pushing, run the whole gate locally:** `pre-commit run --hook-stage pre-push --all-files`. Pushing runs 14 repo-defined hooks, not just the test suite. - **Before pushing, rehearse the gate locally:** `pre-commit run --hook-stage pre-push --all-files`. It runs the 14 pre-push hooks this repo authors itself plus pre-commit's 2 `meta` hooks, so it prints 16; `check-release-needed` passes without checking anything, because it needs a real push to `main`. `docs/spec/gates.md` reconciles both.
- **Pushing without a network** needs `SKIP=apm-marketplace-check,apm-pack-check-clean git push` — those two resolve a remote marketplace entry via `git ls-remote`. Skip only those two; the rest are real local checks, and adding one to `SKIP` disarms it silently. - **Pushing without a network** needs `SKIP=apm-marketplace-check,apm-pack-check-clean git push` — those two resolve a remote marketplace entry via `git ls-remote`. Skip only those two; the rest are real local checks, and adding one to `SKIP` disarms it silently.
- **Author commits with `git-commits`** — it validates Conventional Commits, which `commit-msg` enforces. - **Author commits with `git-commits`** — it validates Conventional Commits, which `commit-msg` enforces.
- **This repo and Gitea are the only source of truth.** All project state, decisions, and working conventions live here. Do not use an external memory system for this project — cached state diverges from the repo and you get a split brain. Before answering any design or architecture question, check `docs/adr/` for an existing decision. - **This repo and Gitea are the only source of truth.** All project state, decisions, and working conventions live here. Do not use an external memory system for this project — cached state diverges from the repo and you get a split brain. Before answering any design or architecture question, check `docs/adr/` for an existing decision.
## Key documents ## Key documents
Read `CONTEXT.md` at the start of every session — it is this repo's domain language, and the terms in it are used unglossed everywhere else. Read `CONTEXT.md` at the start of every session — it is this repo's domain glossary, and the terms it defines are used unglossed everywhere else. It is not exhaustive: terms it does not carry are defined at their point of use, mostly in `docs/spec/`.
Read these on demand: Read these on demand:

View File

@@ -69,10 +69,10 @@ plugin's `.apm/` tree so hosts that convention-scan those paths discover the con
_Avoid_: generated copy, duplicate tree _Avoid_: generated copy, duplicate tree
**Output profile**: **Output profile**:
An `apm pack` target format for a generated manifest; apm has `claude` An `apm pack` target format for a generated *marketplace* manifest; apm has `claude`
(`.claude-plugin/marketplace.json`) and `codex` (the differently-shaped (`.claude-plugin/marketplace.json`) and `codex` (the differently-shaped
`.agents/plugins/marketplace.json`) and none for Copilot CLI's legacy path, which a sync script `.agents/plugins/marketplace.json`), and none for `.github/plugin/marketplace.json` (Copilot CLI's
mirrors instead. Mechanics: `docs/spec/architecture.md`. legacy path), which a sync script mirrors instead. Mechanics: `docs/spec/architecture.md`.
_Avoid_: build target, export format _Avoid_: build target, export format
**Plugin marketplace**: **Plugin marketplace**:
@@ -160,8 +160,9 @@ The directory a gate resolves against — the nearest ancestor of the file being
_Avoid_: repo root, project root _Avoid_: repo root, project root
**Near-miss**: **Near-miss**:
A sibling skill or agent whose plausible queries share keywords with this one but need something A query that shares keywords with this skill but needs a different one — and, by extension, the
different — the only thing a boundary clause should exclude. sibling that would wrongly answer it; boundary clauses exist to exclude genuine near-misses rather
than to enumerate siblings. Detail: `skill-audit/references/description-quality.md`.
_Avoid_: overlap, similar skill _Avoid_: overlap, similar skill
**Vacuous green**: **Vacuous green**:

View File

@@ -18,8 +18,8 @@ Content ships as six installable plugins, each an apm (Agent Package Manager) pa
The six plugins: The six plugins:
- **kyberforge** — skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace - **kyberforge** — skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace
- **git** — conventional commits, branches, history, submodules, worktrees, remotes, and pre-commit hook authoring and running (`pc-author` / `pc-run`) - **git** — conventional commits, branches, history, submodules, worktrees, remotes, pre-commit hook authoring and running (`pc-author` / `pc-run`), and an interactive router (`git-workflow`)
- **gitea** — issues, pull requests, labels, milestones, releases, branches, files - **gitea** — issues, pull requests, labels, milestones, releases, branches, files, and an interactive router (`gitea-workflow`)
- **core** — authoring and auditing a repo's `AGENTS.md` and the provider adapter files that defer to it - **core** — authoring and auditing a repo's `AGENTS.md` and the provider adapter files that defer to it
- **lint** — configuring and running linters - **lint** — configuring and running linters
- **bin** — cross-cutting workflow skills not yet split into a focused plugin: research, documentation, TDD, prototyping, triage, diagnosis, architecture review, requirement grilling, compressed output (`caveman`), and re-orienting mid-task (`zoom-out`) - **bin** — cross-cutting workflow skills not yet split into a focused plugin: research, documentation, TDD, prototyping, triage, diagnosis, architecture review, requirement grilling, compressed output (`caveman`), and re-orienting mid-task (`zoom-out`)

View File

@@ -59,7 +59,9 @@ answers to `git-commits` and `kyberforge:skill-audit` to `skill-audit`. This is
a project skill has no plugin to prefix. `AGENTS.md` and `CONTEXT.md` are updated to name the bare a project skill has no plugin to prefix. `AGENTS.md` and `CONTEXT.md` are updated to name the bare
form, which is what apm deploys and the only form a repo consuming holocron through apm gets. form, which is what apm deploys and the only form a repo consuming holocron through apm gets.
**Correction (2026-08-14): the namespaced form did not stop resolving.** An earlier revision of **Correction (2026-08-14): the namespaced form did not stop resolving.** *Superseded by the
2026-08-17 correction below: the machine state this cites is no longer present. Both are kept
because the pair is the finding — read neither as current.* An earlier revision of
this consequence said every `<plugin>:<skill>` reference "was stale the moment the switch landed", this consequence said every `<plugin>:<skill>` reference "was stale the moment the switch landed",
and `AGENTS.md`/`CONTEXT.md` were written to match. That contradicts the "User scope is untouched, and `AGENTS.md`/`CONTEXT.md` were written to match. That contradicts the "User scope is untouched,
deliberately" consequence below, and the contradiction resolves against it: `~/.claude.json` still deliberately" consequence below, and the contradiction resolves against it: `~/.claude.json` still

View File

@@ -11,10 +11,11 @@ plugin is *for*, and the inventory lives where an inventory can be read off the
## Context ## Context
A plugin's published description is one string authored twice — in `plugins/<name>/apm.yml` and in A plugin's published description is one string authored twice — in `plugins/<name>/apm.yml` and in
the matching `marketplace.packages[]` entry of the root `apm.yml` — and compiled into six files per the matching `marketplace.packages[]` entry of the root `apm.yml` — and compiled into four generated
plugin edit: `.claude-plugin/plugin.json`, `.github/plugin/plugin.json`, files per plugin edit: the plugin's `.claude-plugin/plugin.json` and `.github/plugin/plugin.json`,
`.claude-plugin/marketplace.json`, `.github/plugin/marketplace.json`, and (for the version field plus the repo-wide `.claude-plugin/marketplace.json` and its `.github/plugin/marketplace.json`
only) their codex counterpart. It is the only text a consumer sees in a marketplace listing before mirror. (`.agents/plugins/marketplace.json`, apm's codex profile, carries no per-package
`description` or `version` at all and is unaffected.) It is the only text a consumer sees in a marketplace listing before
installing. It is **not** a SKILL.md `description`: it is never preloaded into an agent's context and installing. It is **not** a SKILL.md `description`: it is never preloaded into an agent's context and
routes nothing at runtime. ADR-0020 governs that other artifact; this one governs this one. The routes nothing at runtime. ADR-0020 governs that other artifact; this one governs this one. The
overlap is a finding, not a scope: ADR-0020 established that capability enumeration in a description overlap is a finding, not a scope: ADR-0020 established that capability enumeration in a description
@@ -70,17 +71,21 @@ unnamed in `git`'s corrected description, though `65bac15`'s own commit message
`gitea`'s. Across the three plugins, 23 of 27 skills are named at the third attempt. `gitea`'s. Across the three plugins, 23 of 27 skills are named at the third attempt.
**Nothing checks any of this.** `scripts/check-manifests.sh` does not contain the string **Nothing checks any of this.** `scripts/check-manifests.sh` does not contain the string
`description`. `scripts/skill-size-check.sh` and the three ADR-0020 validators read SKILL.md and `description`. The three ADR-0020 validators (`scripts/skill-size-check.sh` and skill-audit's and
agent frontmatter and never open an `apm.yml`. `apm audit --ci`, `apm pack --check-clean` and agent-audit's `validate.sh`) gate on SKILL.md and agent frontmatter; they do open `apm.yml`, but only
`scripts/sync-plugin-content.sh --check --all` all compare compiled output against `apm.yml`, so to read `dependencies.apm` when resolving the boundary-target universe — none of them reads the
their entire job is to propagate whatever the description says into six files byte-for-byte and `description:` key, and their hook globs match `SKILL.md` and `*.agent.md` only. `apm audit --ci`,
confirm they match. The `wiki` claim passed every one of the fourteen pre-push hooks, every day it `apm pack --check-clean` and `scripts/sync-plugin-content.sh --check --all` all compare compiled
output against `apm.yml`, so their entire job is to propagate whatever the description says into
those four files byte-for-byte and confirm they match. The `wiki` claim passed every one of the fourteen pre-push hooks, every day it
was published. was published.
**And the obligation is unbounded.** Under enumeration, adding one skill to `bin`, `git` or `gitea` **And the obligation is unbounded.** Under enumeration, adding one skill to `bin`, `git` or `gitea`
means editing two copies of a prose string, a PATCH bump on the package, a bump on means editing two copies of a prose string on top of the version bumps and regeneration any skill
`marketplace.version`, and a regeneration of eight compiled files — a marketplace release, triggered addition already owes under this repo's release policy
by a directory appearing. A skill *rename* triggers the same. 27 of the repo's 39 skills sat behind (`plugins/kyberforge/.apm/skills/apm-workflow/references/marketplace.md`). The bumps are not the
marginal cost — the prose edit is, and it is the half nothing checks. A skill *rename* triggers the
same, for a string no consumer can tell went stale. 27 of the repo's 39 skills sat behind
a description carrying that obligation; the other 12 did not, and their three plugins have generated a description carrying that obligation; the other 12 did not, and their three plugins have generated
no defect of this class. no defect of this class.
@@ -159,7 +164,7 @@ fresh and two prior commits as precedent, is four skills unnamed.
**Cap the description length**, mirroring ADR-0020's 250/400-character tiers, on the theory that a **Cap the description length**, mirroring ADR-0020's 250/400-character tiers, on the theory that a
short description has no room to enumerate. Rejected because length does not measure correspondence: short description has no room to enumerate. Rejected because length does not measure correspondence:
`gitea`'s failing description was 114 characters and asserted a skill that has never existed, while `gitea`'s failing description was 96 characters and asserted a skill that has never existed, while
`bin`'s 176-character enumeration is under the same cap. All six descriptions here, before and after, `bin`'s 176-character enumeration is under the same cap. All six descriptions here, before and after,
sit inside ADR-0020's tiers; the tier would have been silent through all three failures. sit inside ADR-0020's tiers; the tier would have been silent through all three failures.
@@ -183,11 +188,12 @@ field at all, only `name`, `source`, `policy` and `category`.
1.3.5, `gitea` 1.3.5 → 1.3.6, `marketplace.version` 0.4.4 → 0.4.5. 1.3.5, `gitea` 1.3.5 → 1.3.6, `marketplace.version` 0.4.4 → 0.4.5.
**The root `apm.yml` top-level `version:` is restored to lockstep with `marketplace.version`, **The root `apm.yml` top-level `version:` is restored to lockstep with `marketplace.version`,
0.4.2 → 0.4.5.** These two fields have moved together in every one of the eleven commits that have 0.4.2 → 0.4.5.** These two fields have moved together in every commit that has ever touched root
ever touched root `apm.yml` — 0.3.2, 0.3.3, 0.3.4, 0.4.0, 0.4.1, 0.4.2 in both — until `65bac15` and `apm.yml` — 0.3.2, 0.3.3, 0.3.4, 0.4.0, 0.4.1, 0.4.2 in both — until `65bac15` and
`de84d1b` on this branch bumped `marketplace.version` to 0.4.3 and then 0.4.4 while leaving the `de84d1b` on this branch bumped `marketplace.version` to 0.4.3 and then 0.4.4 while leaving the
top-level field at 0.4.2. This is a defect, not a style: `apm.yml`'s own comment above the top-level field at 0.4.2. Lockstep is not folklore: it is stated at
marketplace block records that the top-level `version:` is not inherited into the compiled output `plugins/kyberforge/.apm/skills/apm-workflow/references/marketplace.md`. This is a defect, not a
style: `apm.yml`'s comment inside the marketplace block records that the top-level `version:` is not inherited into the compiled output
"despite being used elsewhere (e.g. by `apm audit`)", so the field is live and was silently two "despite being used elsewhere (e.g. by `apm audit`)", so the field is live and was silently two
releases behind what the marketplace published. Closed here rather than tracked, because the releases behind what the marketplace published. Closed here rather than tracked, because the
correction is one line and the drift is three days old. correction is one line and the drift is three days old.
@@ -199,13 +205,14 @@ duplication to collapse — they have different readers and different lifecycles
says so in its own preamble ("These are routing boundaries, not inventories"). One caveat for whoever says so in its own preamble ("These are routing boundaries, not inventories"). One caveat for whoever
next edits that page: its closing sentence sends a reader to the published description "for what a next edits that page: its closing sentence sends a reader to the published description "for what a
consumer actually gets", which was true against an enumeration and is now a pointer to a second consumer actually gets", which was true against an enumeration and is now a pointer to a second
boundary statement. Neither artifact carries an inventory after this change. That sentence is owned boundary statement. Neither artifact carries an inventory after this change, so that sentence was
by a separate workstream in this change and is deliberately not edited here. rewritten in the same branch to point at `plugins/<name>/.apm/skills/` and `README.md` instead.
**`README.md`'s plugin bullet list becomes the only place an inventory lives, and it still **`README.md`'s plugin bullet list becomes the only place an inventory lives, and it still
enumerates.** Its `bin` and `git` bullets mirror the retired descriptions almost verbatim. This ADR enumerates.** That is deliberate, but it makes the list load-bearing in a way it was not before, so
does not extend to it and does not require it to change: a README is a hand-read document where a its `bin`, `git` and `gitea` bullets were completed in the same branch to name every skill those
list of what you get is the useful thing, it is not compiled into six files, and a stale line in it plugins ship. This ADR does not otherwise extend to it: a README is a hand-read document where a
list of what you get is the useful thing, it is not compiled into four files, and a stale line in it
costs a reader a moment rather than misrepresenting a published package. The tradeoff that makes costs a reader a moment rather than misrepresenting a published package. The tradeoff that makes
enumeration wrong in a marketplace manifest is precisely the one that makes it fine there. enumeration wrong in a marketplace manifest is precisely the one that makes it fine there.

View File

@@ -84,4 +84,4 @@ The stated convention is that files referencing other files declare those refere
## Architectural decisions ## Architectural decisions
Key hard-to-reverse decisions are recorded as ADRs in `docs/adr/`. There is no index file — the directory holds 20 numbered ADRs whose filenames state their decision, so `ls docs/adr/` is the index. Read a superseding ADR before the one it supersedes: ADR-0015 (apm as the authoring source of truth) supersedes ADR-0001 and moots ADR-0006, ADR-0017 corrects ADR-0015's host-discovery gap, and ADR-0019 supersedes one claim in ADR-0018 (that `.claude/settings.json`'s committed content is exactly `{"hooks": {}}`) while keeping the rule behind it. Entry points for the structure described on this page: ADR-0002 (two-tier CLAUDE.md), ADR-0003 (AGENTS.md as the provider-agnostic entry point), ADR-0015 and ADR-0017 (the two compilers behind the plugin roots). Key hard-to-reverse decisions are recorded as ADRs in `docs/adr/`. There is no index file — the directory holds numbered ADRs whose filenames state their decision, so `ls docs/adr/` is the index. Read a superseding ADR before the one it supersedes: ADR-0015 (apm as the authoring source of truth) supersedes ADR-0001 and moots ADR-0006, ADR-0017 corrects ADR-0015's host-discovery gap, and ADR-0019 supersedes one claim in ADR-0018 (that `.claude/settings.json`'s committed content is exactly `{"hooks": {}}`) while keeping the rule behind it. Entry points for the structure described on this page: ADR-0002 (two-tier CLAUDE.md), ADR-0003 (AGENTS.md as the provider-agnostic entry point), ADR-0015 and ADR-0017 (the two compilers behind the plugin roots).

View File

@@ -141,7 +141,7 @@ A boundary-clause target that resolves to no skill or agent has **three** possib
| Verdict | When | | Verdict | When |
|---|---| |---|---|
| **SUGGESTION** — the default | the target does not resolve and neither promotion condition below holds | | **SUGGESTION** — the default | the target does not resolve and neither promotion condition below holds |
| **blocking ERROR** | the target is **terminal** (not a compound modifier) **and** either written in route notation (`/name`, `-> name`) **or** corroborated by another target in the same sentence that *does* resolve | | **blocking ERROR** | the target is **terminal** (not a compound modifier) **and** either written in route notation (`/name` for any name; `-> name` only when the name is hyphenated — see the gap below) **or** corroborated by another target in the same sentence that *does* resolve |
| **INFO, "DID NOT RUN"** | no skill universe could be determined for the path at all — the targets are named and left unchecked, exit 0 | | **INFO, "DID NOT RUN"** | no skill universe could be determined for the path at all — the targets are named and left unchecked, exit 0 |
The default is deliberately soft because a hyphenated word in a boundary clause is as likely to be a The default is deliberately soft because a hyphenated word in a boundary clause is as likely to be a
@@ -149,6 +149,15 @@ tool, a file format or an English compound as a route: "pre-commit hooks" is pro
never reaches the check at all, being a compound modifier rather than a terminal name. The never reaches the check at all, being a compound modifier rather than a terminal name. The
SUGGESTION text says how to opt in — write it as `/name` or `-> name` and it gets checked properly. SUGGESTION text says how to opt in — write it as `/name` or `-> name` and it gets checked properly.
**Known gap: the arrow form only works for hyphenated names.** Target extraction is built on
`NAME_HYPH` (`scripts/skill-size-check.sh:543`), which requires at least one hyphen, and
`ARROW_BOUNDARY` (`:561`) inherits that. So `-> gitea-prs` is extracted and checked, while
`-> triage` is not extracted at all — no ERROR, no SUGGESTION, exit 0. The unicode arrow `→` is not
recognised in either case. This makes the SUGGESTION's own advice unsafe for a single-word skill:
taking it silences the finding rather than checking it. `/name` has no such restriction and is the
form to prefer. Tracked as a defect; `tests/test-adr0020-targets.sh` has one arrow case and its
target happens to be hyphenated, so nothing currently covers this.
Corroboration is what makes the soft default safe: a sentence whose *other* target resolves is Corroboration is what makes the soft default safe: a sentence whose *other* target resolves is
demonstrably a routing sentence, so a sibling that does not resolve is a typo rather than a noun, and demonstrably a routing sentence, so a sibling that does not resolve is a typo rather than a noun, and
gets promoted. gets promoted.

View File

@@ -14,11 +14,12 @@
# into a red run would just train people to ignore red. # into a red run would just train people to ignore red.
# * as a GATE (the run-tests pre-push hook): a skip is a SETUP ERROR, not a # * as a GATE (the run-tests pre-push hook): a skip is a SETUP ERROR, not a
# legitimate state. README.md's Prerequisites table documents vale, apm and # legitimate state. README.md's Prerequisites table documents vale, apm and
# jq as required pre-push dependencies, so a suite that cannot run on the # python3/PyYAML -- the dependencies these suites actually guard on -- as
# machine doing the pushing means the machine is misconfigured -- and # required pre-push, so a suite that cannot run on the machine doing the
# pushing means the machine is misconfigured -- and
# pre-commit prints NOTHING for a passing hook, so the skip list below is # pre-commit prints NOTHING for a passing hook, so the skip list below is
# swallowed entirely. On a vale-less PATH that silently shipped a green # swallowed entirely. On a vale-less PATH that once silently shipped a
# gate having verified 15 of 17 suites. # green gate having verified 15 of the 17 suites that existed then.
# Exactly the vacuous-pass class the rest of this file exists to close. # Exactly the vacuous-pass class the rest of this file exists to close.
# #
# Deliberately its own switch, NOT folded into # Deliberately its own switch, NOT folded into
@@ -259,7 +260,7 @@ fi
# here (not just referenced) because this block goes to stderr and is what a # here (not just referenced) because this block goes to stderr and is what a
# pre-push reader actually gets handed. # pre-push reader actually gets handed.
if [[ "$STRICT" == true && ${#SKIPPED[@]} -gt 0 ]]; then if [[ "$STRICT" == true && ${#SKIPPED[@]} -gt 0 ]]; then
echo "Error: --strict and ${#SKIPPED[@]} suite(s) skipped. Run as a gate, a skip is a SETUP ERROR on this machine, not a legitimate state: README.md's Prerequisites table documents vale, apm and jq as required pre-push dependencies, so every suite is expected to be runnable here. Install what each suite names below and re-run; do not skip the hook." >&2 echo "Error: --strict and ${#SKIPPED[@]} suite(s) skipped. Run as a gate, a skip is a SETUP ERROR on this machine, not a legitimate state: README.md's Prerequisites table documents vale, apm and python3/PyYAML — what these suites guard on — as required pre-push dependencies, so every suite is expected to be runnable here. Install what each suite names below and re-run; do not skip the hook." >&2
sidx=0 sidx=0
for s in ${SKIPPED[@]+"${SKIPPED[@]}"}; do for s in ${SKIPPED[@]+"${SKIPPED[@]}"}; do
echo " $s" >&2 echo " $s" >&2

View File

@@ -395,8 +395,8 @@ fi
# suite exiting 77 means a dependency README.md's Prerequisites table documents # suite exiting 77 means a dependency README.md's Prerequisites table documents
# as required is missing on the pushing machine -- and pre-commit prints nothing # as required is missing on the pushing machine -- and pre-commit prints nothing
# at all for a passing hook, so the skip list this script writes to stdout was # at all for a passing hook, so the skip list this script writes to stdout was
# swallowed whole. A vale-less PATH shipped a green gate having verified 15 of # swallowed whole. A vale-less PATH once shipped a green gate having verified
# 17 suites. # 15 of the 17 suites that existed then.
# #
# The reason is asserted, not just the name: "something was skipped" leaves the # The reason is asserted, not just the name: "something was skipped" leaves the
# reader with no idea which binary to install, which is most of why the swallowed # reader with no idea which binary to install, which is most of why the swallowed