Files
imbad0202__academic-researc…/docs/CONTROL_AVAILABILITY.md
T

128 lines
11 KiB
Markdown
Raw Normal View History

docs: per-channel control-availability matrix (#757) (#768) * docs: per-channel control-availability matrix (#757) Add docs/CONTROL_AVAILABILITY.md — one row per enforcement mechanism, one column per install channel (plugin / skills copy / repo clone / Cowork / claude.ai Project / Claude Science / Pi), with honest active / conditional / absent cells, per-channel notes citing the existing scattered sources (README Requirements, SETUP methods, pi/README.md, hooks/run_guard.sh), and the guard's environment degradation table. Linked from README (Requirements + SETUP pointer) and SETUP (Installation methods intro). Evidence re-verified against the working tree: the channel set has grown past the six named in the issue (SETUP now also documents Cowork and the claude.ai 4a/4b split), so the matrix covers all seven documented channels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * refactor: apply /simplify pass + add CA-1..CA-3 defrift lint (#757) Simplify round (4-agent review, findings deduped): - Drop the 'How to read an integrity claim' section (it had already drifted from the matrix) and the all-identical Upstream row; both replaced by one legend sentence and one paragraph. - Move channel-scoped caveats (Cowork / claude.ai / Claude Science / Pi) from per-cell footnotes into a 'Channel-wide limitation' column of the channel table; notes drop from 11 to 7. - De-drift row labels: no inline allowlist contents (canonical list is pinned by check_tools_allowlist.py), no exhaustive feature list, no hard-coded Claude Code minimum version (lives in SETUP Method 0). - README: single slimmed pointer (second link and both enumerations removed); pointer mirrored to the four translated READMEs and docs/SETUP.zh-TW.md. - Degradations table scoped to actual guard degradations (the slash-form version row was misfiled); registry backpointer added; guard-launcher registry registration split to #769. Lint (per the new-claim-surface-needs-lint-in-same-PR discipline): - scripts/check_control_availability.py — CA-1 links/anchors resolve, CA-2 every SETUP '### Method' heading reachable from the channel table, CA-3 README + SETUP inbound links pinned. Cell semantics stay owned by code review (degradation-registry posture). - 9 mutation tests; wired into spec-consistency.yml + pytest manifest (150 entries). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R1 findings — 4 P2 accuracy corrections (#757) - SessionStart announce/update-reminder row: Conditional, not Active (bash launcher on Windows needs Git Bash; reminder needs curl) — new note 8. - Cross-model note 6 no longer claims credentials+curl universally; the citation-only Codex subscription transport is named as the alternative transport behind the same consent boundary. - Pi channel limitation reworded: the wrapper supplies no orchestration but uses an installed Pi capability when available. - 'Enforcement mechanisms' claim language aligned to 'controls' in the purpose statement and all five README pointers (consistent with note 7's trust-based posture). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R2 findings — lint mis-pass cases + note-8 wording (#757) - CA-1 link grammar accepts optional quoted titles so a titled dead link cannot silently skip the check. - CA-2 counts only fragments on links whose resolved destination IS docs/SETUP.md — a same-slug anchor into a copied file no longer satisfies method coverage. - CA-3 checks resolved link destinations, not a filename substring — a label that keeps the filename while the target moves now fails. - Note 8: singular SessionStart hook (hooks.json defines one; the announce script runs the update check internally). - 3 new mutation tests pinning each mis-pass case (12 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R3 finding — commented-out markdown counts for nothing (#757) Strip HTML comments before extracting links and headings in all three invariants: a commented-out inbound link no longer satisfies CA-3, a commented-out SETUP method heading no longer demands CA-2 coverage, and a commented-out dead link no longer fires CA-1. Two mutation tests pin both directions (14 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R4 finding — GFM type-2 HTML-block semantics (#757) A line beginning with <!-- opens a raw-HTML block through the --> line (including trailing text on the closing line) or to EOF if unclosed; nothing on those lines renders. The comment stripper now models that line-level behavior before the inline-span strip, so a link after --> on a comment line cannot satisfy CA-3 and a dead link after an unclosed comment cannot fire CA-1. Two mutation tests pin both (16 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * test: fix R4 mutation scenario — line-start vs inline comment (#757) The previous commit's CA-3 HTML-block test inserted the comment mid-line (inside the blockquote), where GFM renders the link normally and the lint correctly stays quiet — the test scenario was wrong, not the lint. Replaced with a whole-line mutation that actually begins with <!--, and added the inline-comment symmetry case (link still renders → CA-3 satisfied). 17 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R5 finding — block-quoted HTML-block lines (#757) The type-2 HTML-block rule applies to block-quote content: the stripper now looks through leading '> ' markers before the line-start test, so '> <!-- note --> [link]' cannot satisfy CA-3. Deeper CommonMark laminations are declared out of scope in the docstring (the surfaces do not use them; a full parser is out of proportion for a maintainer-slip guard). 18 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R6 finding — repo-containment on CA-1 targets (#757) A relative link that resolves outside the repository root now fails CA-1 even when the host path exists — an over-deep ../.. slip must not be masked by an existing host file. Mutation test added (19 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R7 finding — fenced code excluded from extraction (#757) Fenced code regions render literally, and README/SETUP use fences today, so they are in-scope: a link inside a fence no longer satisfies CA-3, and a sample "### Method" heading inside a SETUP fence no longer demands CA-2 coverage. Fence stripping runs before the comment pass so a comment opener inside a fence stays literal. Two mutation tests (21 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R8 finding — CommonMark fence-length closing rule (#757) The fence stripper now tracks the opening run character and length: a closer must be a same-character run at least that long with only trailing whitespace, so a four-backtick fence demonstrating an inner triple-backtick block is no longer closed early. Mutation test added (22 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 23:57:07 +08:00
# Control Availability by Install Channel
**Purpose.** ARS documentation names several controls — the write-scope guard, the
citation-verification gate, mandatory checkpoints, the tools allowlist. Which of those
actually operate depends on *how you installed ARS*. This page maps mechanism ×
channel in one place, so a user evaluating an integrity claim can see whether it holds
in their channel. The linked source documents remain authoritative for each fact.
**Origin.** ISO/IEC 42001-spirit gap assessment
([`audits/iso42001-spirit-gap-assessment-2026-08-17.md`](../audits/iso42001-spirit-gap-assessment-2026-08-17.md),
finding T-6, [#757](https://github.com/Imbad0202/academic-research-skills/issues/757)).
Transparency here is one of this repo's distilled operating principles (with informative
anchors to ISO/IEC 42001) — not an ISO-mandated artifact.
## Install channels
| Channel | Documented in | Channel-wide limitation |
|---|---|---|
| **Plugin** — Claude Code plugin install | [SETUP Method 0](SETUP.md#method-0-claude-code-plugin-v370-recommended-for-claude-code-cli--ide-users) | None — the reference channel. |
| **Skills copy** — skill folders copied into a project's `.claude/skills/` or the global `~/.claude/skills/` | [SETUP Method 1](SETUP.md#method-1-as-project-skills-recommended) | Nothing wired by the plugin manifest runs (note 3). |
| **Repo clone** — Claude Code run inside a clone of this repository | [SETUP Method 2](SETUP.md#method-2-as-a-standalone-project) | Nothing wired by the plugin manifest runs (note 3). |
| **Cowork** — skills uploaded to Claude Cowork (desktop) | [SETUP Method 3](SETUP.md#method-3-claude-cowork-desktop) | Each skill runs standalone: no Task-tool subagent dispatch, so the coordinated pipeline — and its staged checkpoints — does not run as designed. |
| **claude.ai Project** — repo attached to a claude.ai Project as retrievable knowledge | [SETUP Method 4](SETUP.md#method-4-use-with-claudeai-web) | Read-only knowledge: Claude can read and cite the skill bodies, but nothing executes — no activation, routing, hooks, scripts, or orchestration. (The Method 4a upload path is documented but not recommended; see SETUP § Method 4a.) |
| **Claude Science** — skills imported via "Import from GitHub" | [SETUP Method 5](SETUP.md#method-5-claude-science-import-v3140) | Methodology layer only; Claude Code-specific machinery does not transfer, and Claude Science substitutes its own agent system (details: SETUP Method 5). Imports are point-in-time snapshots. |
| **Pi port** — community-maintained wrapper for the Pi coding agent | [`pi/README.md`](../pi/README.md) | Two documented boundaries: the wrapper itself supplies no agent isolation or orchestration — an installed Pi orchestration capability is used when available, otherwise roles run sequentially (degraded execution, disclosed, not independent multi-agent review) — and no Claude hooks (write-scope enforcement stays prompt-level). `/ars-pi-doctor` reports what the local environment supplies. |
## Availability matrix
Legend: **Active** = operates as documented · **Conditional** = operates only under the
noted conditions, with a defined degraded state otherwise · **Absent** = does not operate
in this channel. Read down your channel's column: a claim about a mechanism holds only
where its row says Active — or Conditional with the linked note's conditions met — after
applying your channel's channel-wide limitation above.
| Mechanism | Plugin | Skills copy | Repo clone | Cowork | claude.ai Project | Claude Science | Pi port |
|---|---|---|---|---|---|---|---|
| Methodology layer (the four skills' `SKILL.md` protocols) | Active | Active | Active | Active | Conditional | Active | Active |
| Skill auto-routing (trigger keywords → skill activation) | Active | Active | Active | Active | Absent | Conditional | Conditional |
| `/ars-*` slash commands | Active ⁽¹⁾ | Absent | Absent | Absent | Absent | Absent | Conditional |
| SessionStart announce + update reminder | Conditional ⁽⁸⁾ | Absent ⁽³⁾ | Absent ⁽³⁾ | Absent | Absent | Absent | Absent |
| Write-scope guard (`PreToolUse` hook) | Conditional ⁽²⁾ | Absent ⁽³⁾ | Absent ⁽³⁾ | Absent | Absent | Absent | Absent |
| Plugin agents with tools allowlist (#514) ⁽⁴⁾ | Active | Absent ⁽³⁾ | Absent ⁽³⁾ | Absent | Absent | Absent | Absent |
| Subagent orchestration (Task-tool multi-agent dispatch) | Active | Active | Active | Absent | Absent | Absent | Conditional |
| Python-backed opt-in features (repo `scripts/`) | Conditional ⁽⁵⁾ | Conditional ⁽⁵⁾ | Conditional ⁽⁵⁾ | Absent | Absent | Absent | Conditional ⁽⁵⁾ |
| Cross-model verification (consent-gated second model) | Conditional ⁽⁶⁾ | Conditional ⁽⁶⁾ | Conditional ⁽⁶⁾ | Absent | Absent | Absent | Absent |
| Prompt-level checkpoints and integrity gates | Active ⁽⁷⁾ | Active ⁽⁷⁾ | Active ⁽⁷⁾ | Conditional | Absent | Conditional | Conditional |
CI-side checks (mutation-tested lints, content locks, changelog gates) are deliberately
docs: CI workflow enforcement-class table + inventory lint (#755) (#774) * docs: CI workflow enforcement-class table + WC-1/WC-2 lint (#755) docs/ARCHITECTURE.md gains §7.1: all 14 workflows classified by trigger / what it checks / enforcement class (blocking / advisory / administrative / post-push detection) / bypass token, with the honest count line (8 blocking on at least one event class, 2 advisory, 1 administrative, 3 post-push detection) and the explicit statement that tag workflows detect after the push — their stop-power is the maintainer acting on the failure. Per-workflow facts verified against the workflow files (eval-harness ack token + PR-only gating; changelog gate release/** head scope; pytest path filters; the three tag triggers). CONTRIBUTING release-checklist prose now points at the classification instead of implying uniform CI enforcement. Lint (same-PR drift-point discipline): check_workflow_classification.py — WC-1 inventory sync both directions (a new, renamed, or removed workflow fails CI until the table matches; duplicates refused), WC-2 class cells begin with the closed four-term vocabulary. Class semantics stay review-owned (degradation-registry posture). 9 mutation tests; wired into spec-consistency.yml + the pytest manifest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * refactor: apply /simplify + codex R1 — table accuracy + lint hardening (#755) Review round (3 cleanup agents + codex gpt-5.6-sol xhigh R1), findings deduped and applied: Table accuracy (codex 3 P2 + 1 P3, cleanup F2/F3): every trigger cell now states its actual branch/path/tag filters (repository-hygiene and command-invariants had birth-drifted cells; several rows omitted targeting-main scopes); freshness-check reclassified honestly (Advisory for staleness, but malformed protocol metadata is a hard failure); bypass cells say "justification requested, not machine-validated" (both workflows accept the bare token); command-invariants "what it checks" gains its other two enforced checks; bypass column normalized to "none"; the legend absorbs the tag-workflows sentence and the duplicated qualifier prose is trimmed. Lint hardening: section extraction switches to the shared _skill_lint.heading_section (exact full-line heading incl. the #755 anchor, fence-aware — 15 fewer bespoke lines); rows parse once with escaped-pipe-aware cell splitting; the inventory glob covers *.yaml; WC-2 matches vocabulary terms as whole words (Blockingg fails); the arity guard moves under WC-1 with a test; new WC-3 recomputes the bolded count line from the Class column (the honesty sentence can no longer self-invalidate when a workflow is added); new WC-4 pins every [bypass-token] in a Bypass cell to verbatim presence in its workflow file. 14 mutation tests. Surfaces: docs/CONTROL_AVAILABILITY.md corrects its "on every change" claim and links §7.1; the ARCHITECTURE "How to read" §7 bullet indexes the CI sub-view. Skipped with reason: read_or_exit2 exit-2 convention (sibling lints in this fleet use the exit-1 missing-doc violation shape; consistency wins). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R2 findings — .yaml fixture parity + comment-blind WC-4 (#755) - The mutation fixture copies *.yaml alongside *.yml, so a future .yaml workflow with a valid row passes the fixture as it passes the real lint. - WC-4 strips full-comment lines before the token search: a renamed executable token surviving only in a YAML comment no longer satisfies the pin (token in a non-comment echo/log string recorded as an accepted edge). Mutation test added (15 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R3 finding — tag pushes reach three more workflows (#755) GitHub Actions matches tag pushes on unfiltered or paths-only push: triggers (paths filters are not evaluated for tags), so spec-consistency, command-invariants, and freshness-check also run on every v* tag push — where their failures are post-push detection like the tag-only workflows. Trigger cells amended and a subtlety note added above the table; "three tag workflows" narrowed to "three tag-only workflows". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R4 finding — malformed token spellings fail loudly (#755) Any bracketed span in a Bypass cell must be a well-formed [lowercase-hyphen] token: a typo like [skip_cooldown] now yields a WC-4 violation instead of silently falling out of the token grammar. Mutation test added (16 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R5 finding — whitespace token typos caught (#755) The any-bracket span matcher now accepts any non-] content, so [skip cooldown] (space typo) reaches the well-formedness check and fails loudly. Mutation test added (17 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R6 finding — bogus rows fail instead of dropping out (#755) Every pipe row in the section that is not the header or the separator must open with a backticked workflow filename; a malformed row now yields a WC-1 violation instead of silently leaving the inventory and the WC-3 count. Mutation test added (18 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * test: mirror docs/ARCHITECTURE.md into the CA fixture (#755) The new CONTROL_AVAILABILITY link to ARCHITECTURE §7.1 made the #768 test fixture (which mirrors only the files the doc links) miss its target, failing CA-1 in the fixture tree while the real tree passes — caught by CI, not locally, because the local sweep re-ran the lint but not its sibling test file. ARCHITECTURE.md joins the mirrored list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 09:03:53 +08:00
not a matrix row: they run in this repository's GitHub Actions, protecting the
published artifact all channels ship from, and never run on a user machine —
identical for every channel. They do not all enforce at the same strength or fire on
every change: the per-workflow classification (blocking / advisory / administrative /
post-push detection, with triggers and bypass tokens) is
[ARCHITECTURE.md §7.1](ARCHITECTURE.md#71-ci-workflow-enforcement-classes-755). The machine-readable index of the suite's
docs: per-channel control-availability matrix (#757) (#768) * docs: per-channel control-availability matrix (#757) Add docs/CONTROL_AVAILABILITY.md — one row per enforcement mechanism, one column per install channel (plugin / skills copy / repo clone / Cowork / claude.ai Project / Claude Science / Pi), with honest active / conditional / absent cells, per-channel notes citing the existing scattered sources (README Requirements, SETUP methods, pi/README.md, hooks/run_guard.sh), and the guard's environment degradation table. Linked from README (Requirements + SETUP pointer) and SETUP (Installation methods intro). Evidence re-verified against the working tree: the channel set has grown past the six named in the issue (SETUP now also documents Cowork and the claude.ai 4a/4b split), so the matrix covers all seven documented channels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * refactor: apply /simplify pass + add CA-1..CA-3 defrift lint (#757) Simplify round (4-agent review, findings deduped): - Drop the 'How to read an integrity claim' section (it had already drifted from the matrix) and the all-identical Upstream row; both replaced by one legend sentence and one paragraph. - Move channel-scoped caveats (Cowork / claude.ai / Claude Science / Pi) from per-cell footnotes into a 'Channel-wide limitation' column of the channel table; notes drop from 11 to 7. - De-drift row labels: no inline allowlist contents (canonical list is pinned by check_tools_allowlist.py), no exhaustive feature list, no hard-coded Claude Code minimum version (lives in SETUP Method 0). - README: single slimmed pointer (second link and both enumerations removed); pointer mirrored to the four translated READMEs and docs/SETUP.zh-TW.md. - Degradations table scoped to actual guard degradations (the slash-form version row was misfiled); registry backpointer added; guard-launcher registry registration split to #769. Lint (per the new-claim-surface-needs-lint-in-same-PR discipline): - scripts/check_control_availability.py — CA-1 links/anchors resolve, CA-2 every SETUP '### Method' heading reachable from the channel table, CA-3 README + SETUP inbound links pinned. Cell semantics stay owned by code review (degradation-registry posture). - 9 mutation tests; wired into spec-consistency.yml + pytest manifest (150 entries). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R1 findings — 4 P2 accuracy corrections (#757) - SessionStart announce/update-reminder row: Conditional, not Active (bash launcher on Windows needs Git Bash; reminder needs curl) — new note 8. - Cross-model note 6 no longer claims credentials+curl universally; the citation-only Codex subscription transport is named as the alternative transport behind the same consent boundary. - Pi channel limitation reworded: the wrapper supplies no orchestration but uses an installed Pi capability when available. - 'Enforcement mechanisms' claim language aligned to 'controls' in the purpose statement and all five README pointers (consistent with note 7's trust-based posture). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R2 findings — lint mis-pass cases + note-8 wording (#757) - CA-1 link grammar accepts optional quoted titles so a titled dead link cannot silently skip the check. - CA-2 counts only fragments on links whose resolved destination IS docs/SETUP.md — a same-slug anchor into a copied file no longer satisfies method coverage. - CA-3 checks resolved link destinations, not a filename substring — a label that keeps the filename while the target moves now fails. - Note 8: singular SessionStart hook (hooks.json defines one; the announce script runs the update check internally). - 3 new mutation tests pinning each mis-pass case (12 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R3 finding — commented-out markdown counts for nothing (#757) Strip HTML comments before extracting links and headings in all three invariants: a commented-out inbound link no longer satisfies CA-3, a commented-out SETUP method heading no longer demands CA-2 coverage, and a commented-out dead link no longer fires CA-1. Two mutation tests pin both directions (14 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R4 finding — GFM type-2 HTML-block semantics (#757) A line beginning with <!-- opens a raw-HTML block through the --> line (including trailing text on the closing line) or to EOF if unclosed; nothing on those lines renders. The comment stripper now models that line-level behavior before the inline-span strip, so a link after --> on a comment line cannot satisfy CA-3 and a dead link after an unclosed comment cannot fire CA-1. Two mutation tests pin both (16 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * test: fix R4 mutation scenario — line-start vs inline comment (#757) The previous commit's CA-3 HTML-block test inserted the comment mid-line (inside the blockquote), where GFM renders the link normally and the lint correctly stays quiet — the test scenario was wrong, not the lint. Replaced with a whole-line mutation that actually begins with <!--, and added the inline-comment symmetry case (link still renders → CA-3 satisfied). 17 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R5 finding — block-quoted HTML-block lines (#757) The type-2 HTML-block rule applies to block-quote content: the stripper now looks through leading '> ' markers before the line-start test, so '> <!-- note --> [link]' cannot satisfy CA-3. Deeper CommonMark laminations are declared out of scope in the docstring (the surfaces do not use them; a full parser is out of proportion for a maintainer-slip guard). 18 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R6 finding — repo-containment on CA-1 targets (#757) A relative link that resolves outside the repository root now fails CA-1 even when the host path exists — an over-deep ../.. slip must not be masked by an existing host file. Mutation test added (19 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R7 finding — fenced code excluded from extraction (#757) Fenced code regions render literally, and README/SETUP use fences today, so they are in-scope: a link inside a fence no longer satisfies CA-3, and a sample "### Method" heading inside a SETUP fence no longer demands CA-2 coverage. Fence stripping runs before the comment pass so a comment opener inside a fence stays literal. Two mutation tests (21 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R8 finding — CommonMark fence-length closing rule (#757) The fence stripper now tracks the opening run character and length: a closer must be a same-character run at least that long with only trailing whitespace, so a four-backtick fence demonstrating an inner triple-backtick block is no longer closed early. Mutation test added (22 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 23:57:07 +08:00
runtime graceful-degradation mechanisms is
[`shared/contracts/degradation_registry.json`](../shared/contracts/degradation_registry.json).
## Notes
1. Plugin installs namespace commands as `/academic-research-skills:ars-<mode>`; a bare
`/ars-<mode>` alias also works on recent Claude Code versions — the exact minimum
version and the older-version behavior are documented in SETUP Method 0 (#633).
2. The write-scope guard needs a **real Python interpreter** and a `bash` to run its
launcher; missing either produces a *defined degraded state*, never a block — see
the [environment degradations](#environment-degradations-within-a-channel) table.
The guard is optional subagent hardening; core skills are unaffected when it is
inactive (README Requirements).
3. Hooks and plugin agents are wired by the **plugin manifest** (`hooks/hooks.json`,
`agents/`, resolved via `CLAUDE_PLUGIN_ROOT`). A skills-copy or repo-clone install
does not wire them: the `PreToolUse` write-scope guard and the SessionStart announce
do not run, and agent dispatch uses the in-skill prompt templates without the
frontmatter tools allowlist. A user may wire the hook into their own Claude Code
settings manually, at which point the note-2 conditions apply.
4. The allowlist's canonical contents live in the three plugin agents' frontmatter,
pinned in CI by `scripts/check_tools_allowlist.py` — this page deliberately does not
restate the list.
5. These features (e.g. the citation-verification gate CLI, the revision
token-conservation checker, the submission-package verifier, the PDF read preflight,
the cache commands — a non-exhaustive, growing set) shell out to Python scripts at
the repository root (`scripts/`, `shared/`), not inside the four skill folders. They
need (a) a real Python interpreter and (b) the repo checkout present: automatic for
the plugin channel (the plugin root is the repo snapshot) and repo clones; for a
skills-copy install, keep the original clone — the copied skill folders alone cannot
run them. On Pi, they work if Python and the repo are present (`pi/README.md`).
6. Note-5 conditions, plus a transport: provider API credentials and `curl` for the
general transports, or — for the citation-only calls — a Codex CLI
ChatGPT-subscription login (`ARS_CROSS_MODEL_TRANSPORT=codex`). All transports sit
behind the same boundary defined in
[`shared/cross_model_verification.md`](../shared/cross_model_verification.md): the
user's **explicit consent per session** — the `ARS_CROSS_MODEL` environment variable
is configuration, not consent. Unset, the feature is invisible and makes zero
network calls.
7. The MANDATORY checkpoints, integrity gates, and IRON RULE constraints are
**prompt-level, trust-based controls with audit trails**, executed by the session
model following the skill instructions — not coercive runtime enforcement. Documented
overrides require recorded reasoning, and final integrity responsibility stays with
the human researcher (see the
[gap assessment §3](../audits/iso42001-spirit-gap-assessment-2026-08-17.md)).
This row says the *instructions* are present and active in the channel, nothing
stronger.
8. The SessionStart hook is launched through `bash`, so on Windows it needs Git Bash
(the same PowerShell limitation as the guard launcher); its update-reminder path
additionally needs `curl`, stays silent on any failure, and is disabled entirely by
`ARS_UPDATE_CHECK=0` (SETUP Method 0).
## Environment degradations within a channel
feat: register write-scope guard launcher degradations in degradation_registry.json (#769) (#792) * feat: register write-scope guard launcher degradations in the degradation registry (#769) The registry claims to index every graceful-degradation mechanism in the suite, but hooks/run_guard.sh's documented degraded states had no rows, and the #757 prose table in docs/CONTROL_AVAILABILITY.md stood up a second, unpinned authority for those facts. Four write_scope_guard_* rows added (no-python, no-git-bash, no-timeout-binary, subprocess-misbehaves), each with verbatim D3 authority anchors into hooks/run_guard.sh + the README Requirements bullet; pinned_by names scripts/test_run_guard_launcher.py where a CI-executable pin exists (the Windows-without-Git-Bash path never executes the launcher, so its row honestly carries no pin). Registry 1.2.0 -> 1.3.0; _EXPECTED_MECHANISMS updated in the same commit (D5 lock semantics). The CONTROL_AVAILABILITY degradations table now declares itself a convenience summary backpointing at the registry. Closes #769 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq * review: address codex findings on #769 — permission phrasing, no-timeout decision forwarding, launcher-internal failure coverage - Rows no longer claim "writes are never blocked" or relitigate what an 'allow' decision would do: the launcher emits no permissionDecision, so the session's normal permission rules still decide. - The no-timeout row's terminal_policy_effect states that the healthy watchdog fallback forwards the guard's real decision (including deny); only an overrun resolves to pass-through. - The misbehaves row now also covers the two remaining documented launcher-internal degradations (SELF_DIR self-resolution failure and the POSIX payload-length cap on multi-megabyte Writes), with verbatim anchors; CHANGELOG + CONTROL_AVAILABILITY backpointer updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq * review: round-2 codex findings on #769 — per-row quantifiers, actual validity-check shape, payload-edge honesty - terminal_policy_effect now speaks per failure path, not "every degraded path"; the no-Git-Bash row states the hook simply does not run. - The misbehaves row names the launcher's ACTUAL validity check (a JSON object carrying a top-level hookSpecificOutput key — deliberately shallow, not full hook-schema validation). - The multi-megabyte payload edge is recorded as a documented accepted, untested case with no pinned outcome — no deterministic claim. - The no_python row's authority anchor swaps to the no-permissionDecision pass-through line (the launcher's disputed 'allow' comment is pre-existing text this PR neither adds nor endorses). - CONTROL_AVAILABILITY prose quantifier fixed to match ("none of which ever blocks", with the no-timeout forwarding stated). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq * review: round-3 codex findings on #769 — payload edge split into its own no-pinned-outcome row - write_scope_guard_payload_capacity_edge becomes a dedicated row whose every field honestly declares "no pinned outcome" — the misbehaves row's pass-through claims are now unconditionally true for its own failure classes (registry 20 -> 21 rows, D5 lock updated). - CONTROL_AVAILABILITY prose reworded: degraded states never INTRODUCE a block; the no-timeout swap keeps the guard operating normally (real decisions, including deny, still apply). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 12:54:36 +08:00
Independent of install channel, the write-scope guard has documented degraded states.
None of them *introduces* a block: launcher failure paths resolve to **pass-through**,
and a missing `timeout` binary is a bounding-mechanism swap under which the guard keeps
operating normally — its real decisions (including deny) still apply, with only an
overrun resolving to pass-through. The guard is an optional
docs: per-channel control-availability matrix (#757) (#768) * docs: per-channel control-availability matrix (#757) Add docs/CONTROL_AVAILABILITY.md — one row per enforcement mechanism, one column per install channel (plugin / skills copy / repo clone / Cowork / claude.ai Project / Claude Science / Pi), with honest active / conditional / absent cells, per-channel notes citing the existing scattered sources (README Requirements, SETUP methods, pi/README.md, hooks/run_guard.sh), and the guard's environment degradation table. Linked from README (Requirements + SETUP pointer) and SETUP (Installation methods intro). Evidence re-verified against the working tree: the channel set has grown past the six named in the issue (SETUP now also documents Cowork and the claude.ai 4a/4b split), so the matrix covers all seven documented channels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * refactor: apply /simplify pass + add CA-1..CA-3 defrift lint (#757) Simplify round (4-agent review, findings deduped): - Drop the 'How to read an integrity claim' section (it had already drifted from the matrix) and the all-identical Upstream row; both replaced by one legend sentence and one paragraph. - Move channel-scoped caveats (Cowork / claude.ai / Claude Science / Pi) from per-cell footnotes into a 'Channel-wide limitation' column of the channel table; notes drop from 11 to 7. - De-drift row labels: no inline allowlist contents (canonical list is pinned by check_tools_allowlist.py), no exhaustive feature list, no hard-coded Claude Code minimum version (lives in SETUP Method 0). - README: single slimmed pointer (second link and both enumerations removed); pointer mirrored to the four translated READMEs and docs/SETUP.zh-TW.md. - Degradations table scoped to actual guard degradations (the slash-form version row was misfiled); registry backpointer added; guard-launcher registry registration split to #769. Lint (per the new-claim-surface-needs-lint-in-same-PR discipline): - scripts/check_control_availability.py — CA-1 links/anchors resolve, CA-2 every SETUP '### Method' heading reachable from the channel table, CA-3 README + SETUP inbound links pinned. Cell semantics stay owned by code review (degradation-registry posture). - 9 mutation tests; wired into spec-consistency.yml + pytest manifest (150 entries). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R1 findings — 4 P2 accuracy corrections (#757) - SessionStart announce/update-reminder row: Conditional, not Active (bash launcher on Windows needs Git Bash; reminder needs curl) — new note 8. - Cross-model note 6 no longer claims credentials+curl universally; the citation-only Codex subscription transport is named as the alternative transport behind the same consent boundary. - Pi channel limitation reworded: the wrapper supplies no orchestration but uses an installed Pi capability when available. - 'Enforcement mechanisms' claim language aligned to 'controls' in the purpose statement and all five README pointers (consistent with note 7's trust-based posture). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R2 findings — lint mis-pass cases + note-8 wording (#757) - CA-1 link grammar accepts optional quoted titles so a titled dead link cannot silently skip the check. - CA-2 counts only fragments on links whose resolved destination IS docs/SETUP.md — a same-slug anchor into a copied file no longer satisfies method coverage. - CA-3 checks resolved link destinations, not a filename substring — a label that keeps the filename while the target moves now fails. - Note 8: singular SessionStart hook (hooks.json defines one; the announce script runs the update check internally). - 3 new mutation tests pinning each mis-pass case (12 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R3 finding — commented-out markdown counts for nothing (#757) Strip HTML comments before extracting links and headings in all three invariants: a commented-out inbound link no longer satisfies CA-3, a commented-out SETUP method heading no longer demands CA-2 coverage, and a commented-out dead link no longer fires CA-1. Two mutation tests pin both directions (14 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R4 finding — GFM type-2 HTML-block semantics (#757) A line beginning with <!-- opens a raw-HTML block through the --> line (including trailing text on the closing line) or to EOF if unclosed; nothing on those lines renders. The comment stripper now models that line-level behavior before the inline-span strip, so a link after --> on a comment line cannot satisfy CA-3 and a dead link after an unclosed comment cannot fire CA-1. Two mutation tests pin both (16 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * test: fix R4 mutation scenario — line-start vs inline comment (#757) The previous commit's CA-3 HTML-block test inserted the comment mid-line (inside the blockquote), where GFM renders the link normally and the lint correctly stays quiet — the test scenario was wrong, not the lint. Replaced with a whole-line mutation that actually begins with <!--, and added the inline-comment symmetry case (link still renders → CA-3 satisfied). 17 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R5 finding — block-quoted HTML-block lines (#757) The type-2 HTML-block rule applies to block-quote content: the stripper now looks through leading '> ' markers before the line-start test, so '> <!-- note --> [link]' cannot satisfy CA-3. Deeper CommonMark laminations are declared out of scope in the docstring (the surfaces do not use them; a full parser is out of proportion for a maintainer-slip guard). 18 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R6 finding — repo-containment on CA-1 targets (#757) A relative link that resolves outside the repository root now fails CA-1 even when the host path exists — an over-deep ../.. slip must not be masked by an existing host file. Mutation test added (19 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R7 finding — fenced code excluded from extraction (#757) Fenced code regions render literally, and README/SETUP use fences today, so they are in-scope: a link inside a fence no longer satisfies CA-3, and a sample "### Method" heading inside a SETUP fence no longer demands CA-2 coverage. Fence stripping runs before the comment pass so a comment opener inside a fence stays literal. Two mutation tests (21 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R8 finding — CommonMark fence-length closing rule (#757) The fence stripper now tracks the opening run character and length: a closer must be a same-character run at least that long with only trailing whitespace, so a four-backtick fence demonstrating an inner triple-backtick block is no longer closed early. Mutation test added (22 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 23:57:07 +08:00
hardening layer, and a broken guard must not lock a user out of their own files
(maintainer decision recorded in `hooks/run_guard.sh`; user-facing summary in the
feat: register write-scope guard launcher degradations in degradation_registry.json (#769) (#792) * feat: register write-scope guard launcher degradations in the degradation registry (#769) The registry claims to index every graceful-degradation mechanism in the suite, but hooks/run_guard.sh's documented degraded states had no rows, and the #757 prose table in docs/CONTROL_AVAILABILITY.md stood up a second, unpinned authority for those facts. Four write_scope_guard_* rows added (no-python, no-git-bash, no-timeout-binary, subprocess-misbehaves), each with verbatim D3 authority anchors into hooks/run_guard.sh + the README Requirements bullet; pinned_by names scripts/test_run_guard_launcher.py where a CI-executable pin exists (the Windows-without-Git-Bash path never executes the launcher, so its row honestly carries no pin). Registry 1.2.0 -> 1.3.0; _EXPECTED_MECHANISMS updated in the same commit (D5 lock semantics). The CONTROL_AVAILABILITY degradations table now declares itself a convenience summary backpointing at the registry. Closes #769 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq * review: address codex findings on #769 — permission phrasing, no-timeout decision forwarding, launcher-internal failure coverage - Rows no longer claim "writes are never blocked" or relitigate what an 'allow' decision would do: the launcher emits no permissionDecision, so the session's normal permission rules still decide. - The no-timeout row's terminal_policy_effect states that the healthy watchdog fallback forwards the guard's real decision (including deny); only an overrun resolves to pass-through. - The misbehaves row now also covers the two remaining documented launcher-internal degradations (SELF_DIR self-resolution failure and the POSIX payload-length cap on multi-megabyte Writes), with verbatim anchors; CHANGELOG + CONTROL_AVAILABILITY backpointer updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq * review: round-2 codex findings on #769 — per-row quantifiers, actual validity-check shape, payload-edge honesty - terminal_policy_effect now speaks per failure path, not "every degraded path"; the no-Git-Bash row states the hook simply does not run. - The misbehaves row names the launcher's ACTUAL validity check (a JSON object carrying a top-level hookSpecificOutput key — deliberately shallow, not full hook-schema validation). - The multi-megabyte payload edge is recorded as a documented accepted, untested case with no pinned outcome — no deterministic claim. - The no_python row's authority anchor swaps to the no-permissionDecision pass-through line (the launcher's disputed 'allow' comment is pre-existing text this PR neither adds nor endorses). - CONTROL_AVAILABILITY prose quantifier fixed to match ("none of which ever blocks", with the no-timeout forwarding stated). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq * review: round-3 codex findings on #769 — payload edge split into its own no-pinned-outcome row - write_scope_guard_payload_capacity_edge becomes a dedicated row whose every field honestly declares "no pinned outcome" — the misbehaves row's pass-through claims are now unconditionally true for its own failure classes (registry 20 -> 21 rows, D5 lock updated). - CONTROL_AVAILABILITY prose reworded: degraded states never INTRODUCE a block; the no-timeout swap keeps the guard operating normally (real decisions, including deny, still apply). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZwcSFBwiJBZEtsSTcCxq --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 12:54:36 +08:00
README Requirements bullet). This table is a convenience summary, not a second
authority: the indexed rows are the `write_scope_guard_*` mechanisms in
[`shared/contracts/degradation_registry.json`](../shared/contracts/degradation_registry.json)
(#769), whose anchors into `hooks/run_guard.sh` are lint-pinned, and which also cover
two states this table omits — guard subprocess misbehaves or the launcher fails
internally (→ pass-through), and the documented multi-megabyte payload edge (an
accepted, untested case with no pinned outcome):
docs: per-channel control-availability matrix (#757) (#768) * docs: per-channel control-availability matrix (#757) Add docs/CONTROL_AVAILABILITY.md — one row per enforcement mechanism, one column per install channel (plugin / skills copy / repo clone / Cowork / claude.ai Project / Claude Science / Pi), with honest active / conditional / absent cells, per-channel notes citing the existing scattered sources (README Requirements, SETUP methods, pi/README.md, hooks/run_guard.sh), and the guard's environment degradation table. Linked from README (Requirements + SETUP pointer) and SETUP (Installation methods intro). Evidence re-verified against the working tree: the channel set has grown past the six named in the issue (SETUP now also documents Cowork and the claude.ai 4a/4b split), so the matrix covers all seven documented channels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * refactor: apply /simplify pass + add CA-1..CA-3 defrift lint (#757) Simplify round (4-agent review, findings deduped): - Drop the 'How to read an integrity claim' section (it had already drifted from the matrix) and the all-identical Upstream row; both replaced by one legend sentence and one paragraph. - Move channel-scoped caveats (Cowork / claude.ai / Claude Science / Pi) from per-cell footnotes into a 'Channel-wide limitation' column of the channel table; notes drop from 11 to 7. - De-drift row labels: no inline allowlist contents (canonical list is pinned by check_tools_allowlist.py), no exhaustive feature list, no hard-coded Claude Code minimum version (lives in SETUP Method 0). - README: single slimmed pointer (second link and both enumerations removed); pointer mirrored to the four translated READMEs and docs/SETUP.zh-TW.md. - Degradations table scoped to actual guard degradations (the slash-form version row was misfiled); registry backpointer added; guard-launcher registry registration split to #769. Lint (per the new-claim-surface-needs-lint-in-same-PR discipline): - scripts/check_control_availability.py — CA-1 links/anchors resolve, CA-2 every SETUP '### Method' heading reachable from the channel table, CA-3 README + SETUP inbound links pinned. Cell semantics stay owned by code review (degradation-registry posture). - 9 mutation tests; wired into spec-consistency.yml + pytest manifest (150 entries). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R1 findings — 4 P2 accuracy corrections (#757) - SessionStart announce/update-reminder row: Conditional, not Active (bash launcher on Windows needs Git Bash; reminder needs curl) — new note 8. - Cross-model note 6 no longer claims credentials+curl universally; the citation-only Codex subscription transport is named as the alternative transport behind the same consent boundary. - Pi channel limitation reworded: the wrapper supplies no orchestration but uses an installed Pi capability when available. - 'Enforcement mechanisms' claim language aligned to 'controls' in the purpose statement and all five README pointers (consistent with note 7's trust-based posture). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R2 findings — lint mis-pass cases + note-8 wording (#757) - CA-1 link grammar accepts optional quoted titles so a titled dead link cannot silently skip the check. - CA-2 counts only fragments on links whose resolved destination IS docs/SETUP.md — a same-slug anchor into a copied file no longer satisfies method coverage. - CA-3 checks resolved link destinations, not a filename substring — a label that keeps the filename while the target moves now fails. - Note 8: singular SessionStart hook (hooks.json defines one; the announce script runs the update check internally). - 3 new mutation tests pinning each mis-pass case (12 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R3 finding — commented-out markdown counts for nothing (#757) Strip HTML comments before extracting links and headings in all three invariants: a commented-out inbound link no longer satisfies CA-3, a commented-out SETUP method heading no longer demands CA-2 coverage, and a commented-out dead link no longer fires CA-1. Two mutation tests pin both directions (14 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R4 finding — GFM type-2 HTML-block semantics (#757) A line beginning with <!-- opens a raw-HTML block through the --> line (including trailing text on the closing line) or to EOF if unclosed; nothing on those lines renders. The comment stripper now models that line-level behavior before the inline-span strip, so a link after --> on a comment line cannot satisfy CA-3 and a dead link after an unclosed comment cannot fire CA-1. Two mutation tests pin both (16 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * test: fix R4 mutation scenario — line-start vs inline comment (#757) The previous commit's CA-3 HTML-block test inserted the comment mid-line (inside the blockquote), where GFM renders the link normally and the lint correctly stays quiet — the test scenario was wrong, not the lint. Replaced with a whole-line mutation that actually begins with <!--, and added the inline-comment symmetry case (link still renders → CA-3 satisfied). 17 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R5 finding — block-quoted HTML-block lines (#757) The type-2 HTML-block rule applies to block-quote content: the stripper now looks through leading '> ' markers before the line-start test, so '> <!-- note --> [link]' cannot satisfy CA-3. Deeper CommonMark laminations are declared out of scope in the docstring (the surfaces do not use them; a full parser is out of proportion for a maintainer-slip guard). 18 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R6 finding — repo-containment on CA-1 targets (#757) A relative link that resolves outside the repository root now fails CA-1 even when the host path exists — an over-deep ../.. slip must not be masked by an existing host file. Mutation test added (19 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R7 finding — fenced code excluded from extraction (#757) Fenced code regions render literally, and README/SETUP use fences today, so they are in-scope: a link inside a fence no longer satisfies CA-3, and a sample "### Method" heading inside a SETUP fence no longer demands CA-2 coverage. Fence stripping runs before the comment pass so a comment opener inside a fence stays literal. Two mutation tests (21 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc * fix: close codex R8 finding — CommonMark fence-length closing rule (#757) The fence stripper now tracks the opening run character and length: a closer must be a same-character run at least that long with only trailing whitespace, so a four-backtick fence demonstrating an inner triple-backtick block is no longer closed early. Mutation test added (22 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EosnA4RdUYgbF2KmZ1DTmc --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 23:57:07 +08:00
| Condition | Behavior |
|---|---|
| No real Python found (Git Bash / POSIX shell present) | Guard silently no-ops (pass-through); core skills unaffected. On Windows, the 0-byte Microsoft Store `python3` stub is rejected, not mistaken for Python. |
| Windows without Git Bash | Claude Code falls back to PowerShell, which cannot run the `.sh` launcher: guard inactive, and the `PreToolUse` hook logs an error per call (accepted degradation — noisy, never blocking). |
| No `timeout` binary | Portable background-watchdog fallback with the same wall-clock bound and the same pass-through-on-overrun posture. |