Skip to content

feat(release): a portable release fixture and the protected-state machinery it needs (#563, #564) - #576

Merged
SUaDtL merged 66 commits into
mainfrom
sprint/portable-release-and-protected-state
Aug 1, 2026
Merged

feat(release): a portable release fixture and the protected-state machinery it needs (#563, #564)#576
SUaDtL merged 66 commits into
mainfrom
sprint/portable-release-and-protected-state

Conversation

@SUaDtL

@SUaDtL SUaDtL commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #563. Closes #564.

Two workstreams, 95 planned tasks, all ACCEPTED. 50 commits.

A — /ca:release becomes a portable fixture

The release lane held this repository's four plugins as skill logic. It now holds none: every fact it needs — tag prefix, manifests, changelog, payload scope, pre-tag checks — is read from a project's declared .codearbiter/release-targets.md. One skill serves both a four-plugin monorepo and a single-artifact consumer repo, with no repo-local variant.

  • _releaselib.py carries no fact about this repository, enforced by a denylist test.
  • run-pre-tag runs the declared checks in order, stops at the first non-zero, and asserts nothing changed — digesting the content of every changed path, not porcelain lines. Drift and mutation get distinct exit codes.
  • row_assertions() is one derivation behind A-3.1..3.5, so the five assertions cannot drift apart.
  • The release workflow and the version gate read the declared file; no tag-prefix literals remain in CI.
  • check_skill_portability.py (new) fails a shipped skill that names a this-repo path it executes or reads — a consumer does not have .github/scripts/.

A house rule runs through it: never fold "I could not compare" into "the answer is no." semver-greater and check-manifests return distinct codes for the two.

B — a generic protected-state registry

_protectedstatelib.py is a path→policy registry (marker-gated / helper-only / append-only) enforced across all three hook flanks — pre-write.py, pre-edit.py, and _bashguardlib.py's shell check. All three planned consumers are enrolled, one per policy: release-targets.md, open-tasks.md, done-tasks.md.

taskwrite.py gains an archive verb and /ca:standup a per-item archival sweep — one confirmation per item, one helper call per item, done-tasks.md written before open-tasks.md so an interrupted sweep is recoverable.

Governed by ADR-0024 (protected state is a declared executable-input boundary with cooperative, friction-grade markers).

Adversary passes

One at Opus/medium per workstream. Every HIGH remediated in 1864c33; the interesting part is that four of the five were introduced by this sprint's own preceding slices, and every one sat in a seam — how a caller wires mechanisms together — that the green mechanical suites structurally could not see.

# Defect Fix
HIGH-1 The interpreter leg matched the interpreter token alone, which is the shape of the sanctioned call. Every /ca:task invocation naming an enrolled file blocked — and for done/archive on an ID-less task the title is the target, so no reword existed and no sanctioned route remained. Require an inline-code switch: running a file and passing the name as argv is data; executing a string that names it is a write.
HIGH-2 archive_transform moved the top line only, orphaning Desc/Boundaries onto the next task — silently rewriting a security scope. Move the whole block, boundary rule taken from parse_board itself.
HIGH-3 Removal was text-equality over every line, so two identical done entries collapsed to one. A record destroyed at rc=0. Index-based removal.
HIGH-4 A failed read of the append-only archive became "", and the write replaces the file wholesale — any transient OSError wiped every historical record. Split ABSENT from UNREADABLE; refuse at a distinct exit code before either write.
HIGH-5 The interpreter list missed pythe Windows Python launcher — and PowerShell entirely, so the leg was bypassable on this repo's primary dev host. One shared alternation, widened.

MEDIUM-1/3/4/5 also fixed. MEDIUM-1 deserves a note: the test that claimed to pin archive write-ordering compared a string against itself, and a reversed-order mutant survived the entire suite. It now fails the second write and checks what survived on disk.

Deferred with reasons, not dropped: #573 (archive vs ADR-0008 — needs a ruling, not a fix), #574 (H-05/H-11/H-18 have no interpreter leg; pre-existing, three untouched guards), #575 (lexical residuals).

Verification

All suites green on the final commit: every .github/scripts/test_*.py module, the site suite (47 files / 496 tests), and build-surface --check (claude, codex, pi in sync). The one local failure is a pre-existing ca-pi flake in a package this branch does not touch, filed as #580. The proof gate is red, deliberately — see "Known state on merge" below. check-plugin-refs, check_adr_identity, check_skill_portability, check_command_catalog, check_docs_contract all clean.

Every new test was confirmed to die to a mutant, with the mutation asserted to have applied — a rule this sprint earned when a heredoc escaping bug made a "surviving" mutant a no-op.

https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86


Review remediation (added after the original description)

CodeRabbit (ASSERTIVE profile) returned 69 findings. All 24 Major are fixed — ~12 distinct, since core/pysrc/X and its two vendored copies each flag separately. Highlights:

  • task_block diverged from parse_board's closing rule, re-opening HIGH-2 — indented continuation prose orphaned sub-bullets onto the following task.
  • _archive parsed the board one line at a time, so every Task carried lineno == 1 and HIGH-3's index-based location was dead code running on its fallback.
  • git_restore_re still crossed newlines — the same defect fixed in write_re two lines above it.
  • A delete op reached the marker-gated arm, making a self-mintable friction-grade marker a delete capability over protected state.
  • run-pre-tag's mutation check was blind to a command that REVERTED an edit.
  • confirmation_path collided a.b with a_b, so confirming one confirmed the other.
  • The python3 X || python X convention discarded helper exit codes: || re-runs on any non-zero, so run-pre-tag's 5/6 verdicts triggered a second full execution of the project's declared pre-tag commands and reported the second run's code.

Two blind agent-judgment exercises (runs 14 and 15) drove the shipped skill as an operator's agent would. Nine HIGHs fixed:

  • The lane forbade reading the declared file by eye but shipped readers for only 2 of 13 fields, so following it required the forbidden path. Added show-row and show-row --field.
  • $PAYLOAD is "payload minus payload-exclude", which git log -- cannot express; added payload-pathspec.
  • The changelog roll had no floor when a manifest runs ahead of the last tag, so a release would re-publish already-shipped entries. Now STOPs.
  • show-row's first cut emitted unquoted values and the skill documented eval-ing them — which executed declared shell (rebuild: cd x && npm run buildREBUILD=cd plus the command x) while still exiting 0. Values are shlex.quoted; --field needs no eval.
  • MAJOR.MINOR.PATCH was a literal in 7 tag/push/release commands and never assigned; $VERSION now is.
  • The clean-tree gate could never pass, because this layer's own hooks append to gate-events.log on the very commands the lane runs.

Deferred, filed not dropped: #573 (archive vs ADR-0008 — needs a ruling), #574 (H-05/H-11/H-18 have no interpreter leg), #575 (lexical residuals), #577 (repo-wide || convention), #578 (45 minor/trivial), #579 (remaining exercise findings).

Three more blind exercises (runs 16, 17, 18) drove the shipped skill after the ones above. Six more HIGHs, all fixed:

  • Every helper invocation broke on a plugin root containing a space"$PY" {{PLUGIN_ROOT}}/hooks/<script>, interpreter quoted, path beside it not. C:\Users\First Last\.claude\plugins\ is an ordinary Windows install; on such a host every step fails at once.
  • Phase 1 step 7 asserted clean-tree with the bare git status --porcelain while calling it "the same state Pre-flight required" — which Pre-flight's own HIGH-rated paragraph proves cannot pass there.
  • Step 6c's own stated remedy (releasehash.py record) wrote a marker the step-7 gate then refused — a hard BLOCK at the last gate of Phase 1, masked here only by a .gitignore line and not masked for a Back-fill consumer, which is exactly who the lane serves.
  • The clean-tree pathspec used a cwd-relative ., and a declared rebuild commonly begins with cd. From the subdirectory that leaves you in, three gates fail silently: a false "nothing to release" STOP on a 95-commit window, an artifact-freshness check that passes without resolving the artifact, and a dirty tree reading as clean.
  • Step 3 told the operator that amending or rebasing a footer-less commit was "fine, since nothing in this window has been tagged or pushed". 38 of the 57 footer-less commits are already on origin/main — the sentence prescribed a force-push over published history that this same file forbids twice.

Run 18 then attacked all four of the earlier fixes directly and they held, including from a path containing a space.

Known state on merge: check_skill_proof_fresh.py is red, and that is a decision rather than an oversight. Run 18 exercised the skill at 33e82a6a and found the force-push instruction above; fixing it moved the skill one commit past the hash the exercise covered. The honest options were to record a proof for bytes an agent actually read and leave the gate red, or to ship a destructive instruction to keep the gate green. proof_current is false, post_exercise_delta in the artifact names exactly what changed after the exercise and why, and the gate blocks the next /ca:release for ca until run 19 runs against the final bytes.

The gate was already red before this session — stale since 8f101403, still recording run 13. It now records run 18 with a named one-commit delta, which is strictly better than red-and-five-commits-stale. It is a declared pre-tag row, not a CI job, so it does not gate this merge.

Deferred, filed not dropped: #573 (archive vs ADR-0008 — needs a ruling), #574 (H-05/H-11/H-18 have no interpreter leg), #575 (lexical residuals), #577 (repo-wide || convention), #578 (45 minor/trivial), #579 (earlier exercise findings), #580 (ca-pi bridge flake), #583 (run-16 non-HIGHs), #584 (run-17 non-HIGHs), #585 (run-18: Back-fill's first release cannot clear step 3, plus four MEDIUMs).

SUaDtL added 30 commits July 31, 2026 00:40
Records the design for #563 and #564 before autonomous execution begins,
so an interrupted session is resumable rather than lost.

Five adversarial passes changed the design rather than polishing it. The
load-bearing corrections: the protected-state registry needs a per-entry
policy, because marker-gating open-tasks.md would admit an agent composing
board markdown under a marker while taskwrite.py is already invisible to
every flank by construction; the archival sweep had no implementation path
at all, since taskwrite carries no removal verb; and the plan's coverage
proof passed twice over a criteria set with a hole in it, first missing the
release-skill rewrite and then the consumer-portability proof the campaign
exists to deliver.

DECISION-0033 is superseded by DECISION-0034: declared pre-tag commands are
check-only and may never mutate the tree. D-1 closes as fact, since
taskwrite.py already resolved it; D-2 closes with /ca:standup owning the
sweep at a 14-day cutoff.

Refs: #563, #564, #565
…#564)

The write guard three project-state files will share. Each registry entry
carries a policy rather than one uniform rule, because the consumers need
materially different semantics: release-targets.md is marker-gated,
open-tasks.md is helper-only, done-tasks.md is append-only.

open-tasks.md must not be marker-gated. taskwrite.py is already its only
blessed writer, and it writes with Python file I/O whose argv never
lexically names the file, so it is invisible to every flank by
construction. A marker would add nothing for the helper while admitting an
agent that hand-composes board markdown under it.

The registry ships EMPTY. Consumers enrol in their own later tasks so this
module cannot special-case its first one, and it stays code constants
rather than disk-loaded state, which would let a consumer repo un-protect
its own board by editing a file.

An adversarial pass ran 13 mutants against the first 9 tests; 7 survived.
Two could render the guard inert with a green suite: the default-registry
path had only a negative assertion so a lookup that never reads REGISTRY
passed, and both freshness tests computed their ages from the
implementation constant, so a 33x widening of the window also passed. All
8 mutants now die. The window's five independent hardcoded declarations
are documented rather than denied, and tracked in #567.

Refs: #564, #567
…as H-22 (#564)

classify_protected grows a fifth "state" class rather than the flanks doing a
parallel registry lookup. _protectedlib documents why: #528/#529 deadlocked
because two independent class checks disagreed on membership, and #162 symlink
laundering is closed inside the classifier, which runs every classifier against
both the raw and realpath-resolved forms. A parallel lookup reintroduces the
first and ships without the second.

Two independent reviews ran against the first cut. A security pass returned
PASS with no CRITICAL or HIGH; an adversarial pass ran 37 mutants, killed 28,
and graded no HIGH. Twelve findings between them are remediated here, each with
a mutation proving the new test kills it. Two were silent fail-opens that only
become reachable once consumers enrol, and neither enrolment task re-runs these
reviews:

The flanks disagreed on case. The shell side compiled with re.I while the
registry lookup compared case-sensitively, breaking a rule stated verbatim in
the same file from #528. On macOS a Write to a differently-cased spelling missed
the registry and landed on the real file, invisible here because nt.realpath
folds case and posixpath.realpath does not. Resolved as global
case-insensitivity: case-sensitivity varies by platform and by volume, and
realpath cannot fold case for a path that does not yet exist, which is exactly
a Write creating a protected file for the first time. A fixed rule both flanks
apply without consulting the filesystem only widens what is protected.

Symlink coverage was inverted. The raw leg of the two-form lookup never fired,
because hosts always send absolute paths while registry keys are repo-relative,
so the class rested entirely on repo_rel. With the protected path symlinked, the
absolute spelling, the only one a host sends, was admitted. raw_repo_rel() gives
the raw leg a lexical repo-relative form so both legs are meaningful.

The shell flank also gained the git checkout/restore leg H-05 has carried since
#335, the sponge/ln/install/patch/shred verbs, and an interpreter leg closing
python -c open-for-write, which contradicted helper-only's own premise that the
sanctioned helper's Python file I/O is the only route.

touch stays excluded. Both reviewers' positions are recorded in
security-controls.md, which gains a purely additive H-22 section declaring the
case decision and the accepted bare-basename over-match residuals. Undeclared
and accepted are different things.

Refs: #564
…t boundary (#564)

release-targets.md carries per-row pre-tag shell commands that /ca:release
executes, which makes it executable input with no recorded trust model. ADR-0002
already governs that class for plan.json, but citing it would have been wrong on
three counts, so the ADR names them: the model drafts these rows where plan.json
was operator-typed, a consumer repo guarantees no PR review, and this is the only
executable file under .codearbiter/ -- and the location chosen for it, on context
economy grounds, does not inherit CONTEXT.md's guard.

Protection is by write-gating rather than content inspection. No content
predicate ever grants admission: a guard that reads a file to decide whether to
permit writing it converts content into an authorization signal, launderable by
anyone who can write the content. That is the same defect that sank the
file-absent exemption and the conflict-marker carve-out earlier in this campaign.

The marker is audit friction, not authorization. It is self-mintable by shell
under ADR-0010, and GATE_MARKER_NAMES is deliberately not widened to cover it --
doing so would brick every minting lane while stopping no non-cooperative agent.

Four residuals are declared rather than left undeclared, including the touch
exclusion with both reviewers' positions recorded. Three reopen conditions are
named; the sharpest is that recurring board-conflict overrides mean building a
taskwrite resolve verb, never an exception in the guard.

Closes T-16. Refs: #564, DECISION-0035, ADR-0002, ADR-0010
… data (#563)

The release lane could not run in any repo that installs codeArbiter, because
its first pre-flight step calls a helper living at .github/scripts/, outside the
plugin payload. This moves the portable half into core/pysrc/, where sync-core
materializes it byte-identically into all three governance plugins, and adds the
parser for the declared target file that will carry what used to be hardcoded.

Repo facts become required parameters rather than defaults: the merge-readiness
check name, the tag prefix, the target list. A default is how a repo assumption
survives a portability refactor unnoticed.

An adversarial pass ran 46 mutants and found three HIGH, all fixed here. The
parser truncated a block when a value contained the closing delimiter and that
delimiter was the only close, parsing as success with a required key silently
emptied. Empty and whitespace-only values satisfied the required-key check,
because the row finisher tested "is None" while a parsed key always assigns a
string, so a typo'd empty prefix became "" and flowed onward as "never
released". And seven of the nine mechanism functions had no coverage in the new
module at all: each could be replaced with a constant return while the whole
suite stayed green, because the tests exercising those names ran against the old
helper this slice deliberately left untouched. The suite appeared to cover the
migration and covered the thing being migrated from.

The portability bug worth naming: the pre-release filter substring-tested
"-beta", "-rc" and "-alpha" against the whole tag including the prefix.
Unreachable here, since the anchored regex already excludes suffixed tags. But a
consumer with a web-beta-v prefix loses every tag in that series and gets the
"never released" sentinel, so the lane offers a first-release baseline to a
project that has releases. Invisible in this repo, live in theirs, sitting inside
the code whose purpose is to remove exactly that class of defect.

The manifest bump is separate but required: two earlier commits changed shipped
payload while the version stayed at one already on the default branch with
payload attached, so claude plugin update would have no-opped and the H-22 guard
would have reached nobody.

Refs: #563
)

An adversarial pass falsified this slice's central claim. The shim did break
CI, in three independent places, two of them already flagged by the repo's own
guards while the slice was reported verified.

test_release_workflow.py went from green to 41 of 60 failing, because it builds
a synthetic tree containing only the shim while the shim resolves the generated
mechanism at import. ci.yml describes that suite as the only guard on the
release workflow's publish gates. The fix is in the test, which now materializes
the mechanism into the synthetic tree. Deliberately not in the shim: a fallback
tolerating a missing mechanism is the silent default the spec forbids, and would
let a genuinely broken install pass.

test_release_trace.py was referenced by no workflow and no sibling script, so
the campaign's entire proof of no-behavior-change never ran, and the orphan
guard was already red naming it. It is now wired into the hooks job with
fetch-depth 0 and fetch-tags, because both shallow-clone failures were
reproduced: the pinned SHA is unreachable without full depth and the live-tag
assertion needs tags. A preflight hard-fails with a named cause rather than
skipping, since a skip would hide precisely this.

The new shim test shelled out to the payload gate with an origin/main base the
hooks checkout cannot resolve, failing on every PR run and coupling that job to
ca's payload-versus-version state. It now asserts the import identity the real
consumer depends on, which is git-free and a stronger claim.

ca-pi's declared rebuild was not runnable: build.mjs resolves inputs against
cwd, so it needs the cd form its three siblings already used. As written it
would have blocked the ca-pi release lane permanently once slice 3 lands, and a
mutant replacing it with a no-op survived the whole suite.

The trace also certified "changed nothing" across a function this campaign
deliberately changed. last_tag_select's marker test moved from the whole tag to
the prefix-stripped version, which was the consumer-portability fix; on every
fixture prefix old and new agree, so the claim read as true only because no
fixture exercised the change. A marker-bearing row now asserts the intended
divergence, so the trace says exactly this changed, on purpose.

Refs: #563, #568
…et (#563)

The sprint's completion bar is that the replacement is proven to work and to
port. This is the porting half: a scratch consumer repo with one package.json,
one CHANGELOG.md, a tag and synthetic conventional commits, against a plugin
materialized by git archive HEAD.

git archive rather than a copy is load-bearing. A recursive copy carries
uncommitted edits and gitignored artifacts, so a skill referencing a file that
exists locally but was never committed would still pass, which is the #563
defect surviving its own test. Both exclusions are proven against real
artifacts, not synthetic ones.

The reference check is a ratchet, not a red test. It compares the unresolved set
against a committed list, so it is green and required from day one and fails
whenever that set changes in either direction. A long-red test enforces nothing
while red and gets edited into passing on the day it matters; a ratchet makes
every state transition a reviewed diff.

An adversarial pass then found the failure that would have made all of it
worthless. The extractor's segment class had no asterisk, so the three glob
references the skill executes to derive its count badges were structurally
invisible, and plugins/ca/agents had no representative on the list at all. The
ratchet would have reached empty with three hardcoded layout references still
shipping. A ratchet defends against narrowing, never against a form it never
matched, and a non-vacuity floor measures non-emptiness rather than completeness.

It also found a gaming vector: the project-dir arm resolved anything in bounds,
including paths nobody would have, so the rewrite could have been satisfied by
repointing helpers under that prefix while leaving the skill exactly as
unportable. Now narrowed to a codearbiter-owned exemption.

Scope was wrong twice. The review found a second contaminated payload outside
the ratchet; generalizing that fix surfaced a fifth that neither the review nor
this spec had named. Five release-skill copies ship and three carry seven
repo-path references each. The spec listed four and named the two harmless
stubs while omitting a full copy.

The fixture's git isolation also overclaimed in its own docstring: repointing
config FILE locations does not neutralize GIT_CONFIG_COUNT, which injects config
straight from the environment. Closed and proven under a poisoned environment
rather than narrowing the claim.

Refs: #563
The other half of the completion bar. Both lanes, the pinned pre-change module
and the new mechanism plus declared rows, derive next version, commit window and
composed tag message from live HEAD and must agree. Zero refs are created: a
tag's informative content is its message file and its target derivation, and
both compare without one, while an interrupted compose-then-delete would leave a
local tag that makes every later payload gate report "already released".

It immediately caught a defect: ca's manifest read 2.11.0 with no matching
CHANGELOG section, drift introduced by bumping the manifest to clear the payload
gate without writing the entry that rides with it.

An adversarial pass then found three HIGH, all of them created by that fix. The
module's prose asserted the drift as live fact, which stopped being true the
moment the section landed. The drift test's branch could not fail: corrupting
next_version flipped it to an else-arm that merely restated its own guard, and
the arm the fix activated checked neither date consistency nor section boundary
nor semver ordering. And the live window dropped payload-exclude, so ca-pi read
15 commits where the release window is 14, the extra being a feat that would
drive a different bump, on the very row that exists in this trace to exercise
payload-exclude.

The branch is now collapsed into an unconditional assertion. A recurrence of the
drift should fail this test, because that is what a blocked release looks like.

Prose that pins a transient repo state is a claim with an expiry date, usually
the next commit. The docstrings now describe the mechanism instead.

Refs: #563
T-74/T-75. The driver extracts invocation strings from the installed SKILL.md
and subprocess-executes them literally, so a renamed subcommand or a moved flag
fails here. A direct-import test proves the library works and cannot notice that
the prose instructs a reader to run something the CLI no longer accepts, which
is the gap the original defect lived in.

It found two things worth more than the tasks.

Composed tag messages lose every Markdown heading. git's default cleanup mode
for a message file is strip, which treats hash-prefixed lines as comments and
deletes them, so the version heading and every grouping vanish. Verified against
this repo's own published v2.8.13, which carries its bullets and neither its
heading nor its Added section. The skill's notes-heading guard cannot see this:
it validates the composed file before git consumes it, so it checks the input
and never observes the loss. Filed as #569; published tags stay as they are.

And the plan had a hole. The shipped mechanism has no __main__ at all, only the
CI shim does, so repointing the skill's invocations at the plugin-root copy aims
them at a file that cannot be invoked. tag-prefix, last-tag and classify would
still fail in a consumer after the rewrite reported success. Added as T-41f.
Third ledger hole here, after the missing skill rewrite and the missing
portability proof, all three the same shape: a criterion set internally
consistent and silent about a step nobody named.

T-76 is deliberately NOT accepted. The skill has no back-fill prose yet, so its
two arms cannot be proven. What landed is an assertion of what is true plus a
canary on the absence, which fails loudly when the prose arrives.

Refs: #563, #569
…a table (#563)

The campaign's central deliverable. The hardcoded four-row Targets table becomes
a lookup against .codearbiter/release-targets.md, helper invocations repoint
under the plugin root, the tag-provenance step reads a row field, and the
hosted-lane and immutability prose become conditional on what a consumer's repo
actually has. The mechanism gains a __main__ CLI, without which repointing the
prose would have aimed it at a file that cannot be invoked.

The reference ratchet goes 24 entries to 0, each removal a real change rather
than a rewording that dodges the extractor.

An adversarial pass returned BLOCK on three counts, all traceable to landing
this prose ahead of the machinery it describes. The skill named a back-fill lane
that does not exist, firing a canary written for exactly that. It wired a
declared pre-tag command into a Phase-1 BLOCK while the script did not exist, so
release ca could not complete; that script is now authored. And the ca-pi
generated-manifest doctrine was dropped in three places while the replacement
prose instructed the forbidden action, so it is restored as declarable row data
rather than folklore.

The ranking finding was not any of those. A mutation campaign deleted governance
from every payload and 11 of 12 mutants survived: the recovery section, the
CHANGELOG-footer BLOCK, publish read-back, the immutable-tag rule and
derive-never-guess were all deletable with a green suite. Coverage had followed
what the rewrite added rather than what had to survive, the same shape as the
SEMVER regression earlier in this campaign. A governance-survival test now
asserts each rule's presence across every payload that renders this skill, with
the payload list derived rather than hardcoded and the checker itself
unit-tested so it cannot pass vacuously.

Bare release on a multi-target project now STOPs rather than defaulting.
Recorded as DECISION-0036, a deliberate exception to the no-behavior-change
steer, taken on default-deny grounds for a lane that ends in a write-scoped
publisher.

Refs: #563, DECISION-0036
…563)

A project with no declared file now gets a detected candidate shape presented
for explicit confirmation, and only on confirmation is it persisted; a second
run reads that file rather than re-detecting.

Detection refuses to guess. It returns a row only when exactly one manifest and
exactly one changelog are found at the top level; any other count raises, naming
what it saw. load_targets still raises on an absent file, unchanged: the
back-fill is a lane that handles that error, never a silent default inside the
parser.

Prose and machinery land in the same change, deliberately. The previous slice
shipped prose describing a back-fill lane, a pre-tag script and a doctrine that
did not exist, and produced three BLOCK findings for it.

The canary asserting the absence of back-fill prose is replaced by the real
two-arm proof it was holding a place for, as its own docstring instructed:
refuses without confirmation, persists on confirmation, second run does not
re-detect, and an ambiguous repo is refused with nothing printed and nothing
written. It drives the invocation extracted from the installed skill text rather
than importing the library.

DECISION-0036 is now pinned. A mutant restoring a hardcoded default target
survived both suites, so the ruling was asserted by nothing.

Two real defects were found in this work and fixed rather than shipped. An
em-dash in a runtime error message crashes the caller: a child Python process
encodes stdout via the ambient Windows codepage, so the character becomes a byte
the parent's UTF-8 read rejects. And root resolution used cwd alone, the same
class of bug the CLI entry point had.

Refs: #563, DECISION-0036
test_no_declared_file_and_the_parser_still_refuses_to_default asserted that no
declared file exists, against the shared class fixture that
test_arm_2_persist_on_confirmation legitimately creates. unittest orders methods
alphabetically, so arm_2 ran first and the absence assertion failed.

It had never actually run before. The class's setUpClass was erroring, because
the fixture materializes the payload via git archive HEAD and the back-fill lane
was still uncommitted, so every method in the class was skipped and the ordering
defect stayed invisible. Committing the lane is what made these tests execute
for the first time, and the defect surfaced immediately.

A test asserting "no declared file exists" must not depend on no other test
having made one. It now builds its own pristine consumer and tears it down.

Verified order-independent: green in the full suite, green with the class run
alone, and green run by itself.

Refs: #563
…#563)

The agent-judgment layer ran blind against the installed skill in a scratch
consumer. It found four HIGH defects, none reachable by any mechanical test in
this campaign, because each lives in the gap between what the prose instructs
and what the mechanism can actually do.

The worst was data loss. The skill stated that back-fill never runs against a
file that already exists, however broken. False: an existing file with no
delimiter block raised the same AbsentBlockError as a missing one, so following
the stated trigger literally ran the lane against an operator's file and step 3
wrote over it, discarding the declaration the same paragraph promised to
protect. The prose asked the agent to make a distinction the named mechanism
could not make. There is now a sibling error for the blockless case, so the
trigger cannot catch it, plus distinct CLI exit codes and an existence re-check
immediately before any write.

A fresh consumer was also dead-ended: back-fill's stated audience has no
.codearbiter/, then re-entered a Pre-flight that STOPs on a missing CONTEXT.md,
resolvable only by the onboarding lane back-fill exists to skip. The exercising
agent guessed the required frontmatter key out of a hook's rejection message, a
string appearing nowhere in the skill. That read is now conditional.

Back-fill's own write landed inside payload: . and left the tree dirty, failing
the very next gate. It now routes through commit-gate before re-entering.

And classify_publish_state has no notion of pushed versus local, so the state
Phase 2 is designed to leave behind classified as resume_publish, whose branch
said to go create the missing Release without restating that publication needs
authorization. Two sentences pointed opposite ways and the more specific one
pointed at publishing.

The changelog harvest asymmetries are closed too: perf and refactor now fall
under the footer BLOCK, refactor gets a group, footers on non-bumping commits
are harvested rather than silently dropped, and the completeness check runs
before any manifest bump.

Consequence worth stating: the widened BLOCK will fire on this repo's own next
release. Five commits in the unreleased window carry no CHANGELOG: footer. That
is the rule working as specified rather than a regression.

Refs: #563
The agent-judgment layer is the only proof in this campaign that cannot be
mechanized, and it is a point-in-time exercise: edit the skill afterwards and it
silently stops covering what ships. check_skill_proof_fresh.py compares the hash
recorded by the exercise against the shipped skill and fails on a missing or
unparseable artifact, a proof marked not current, a hash mismatch, or a recorded
path that is no longer a rendered payload. Each failure mode is proven by
mutation rather than assumed.

It covers the one payload an agent actually exercised. The sibling routine
copies share the same source and are proven byte-consistent elsewhere, but
neither has been independently exercised, and hashing them would fabricate
coverage nobody performed. The candidate set is derived from the host
descriptors rather than hardcoded, because a hardcoded payload list is how the
ratchet under-scoped itself twice.

The reference ratchet retires into its strict form: the unresolved set must be
empty, with no known-failures list to tolerate. The guard-the-guard assertion
stays, because an empty-set assertion is trivially satisfied by an extractor
that matches nothing.

That guard immediately earned itself. Reference extraction had been broken by
f199962, the back-fill commit two ahead of this one: naive backtick pairing
desyncs across a fenced code block, silently dropping 6 of 14 references
including the stable anchor. Converting to a strict assertion on top of that
would have certified portability while blind to everything after the fence. The
recovered count matches the figure recorded before the fence was introduced,
which is what distinguishes a fix from a new rule.

The checker is deliberately not yet wired as a pre-tag command. The recorded
proof is stale against the remediation that followed it, so it fails correctly
today; declaring it now would ship a permanently red command.

Refs: #563
A second blind agent exercise confirmed the previous round's fixes hold and
found two more. Both live where the prose meets the mechanism rather than in
either alone, which is why no unit test reached them: every unit involved is
correct.

Phase 2 mandates an annotated tag, then feeds classify a tag_sha. git rev-parse
on an annotated tag returns the tag object, not the commit, so the obvious way
to produce that argument yields a value that can never equal head_sha and
classify reports abort_mismatch on a perfectly healthy tag. The symptom looks
exactly like real corruption. peel_tag existed in the library and in the CI
shim, but the shipped consumer CLI did not expose it, so the argument most
likely to be produced wrongly had no sanctioned way to be produced right. It is
exposed now, and the prose states how to derive the value rather than leaving a
reader to reach for rev-parse.

And every back-filled consumer published its first release demoted. The rule
forbidding --latest without a declared latest-eligible exists so four sibling
series here cannot steal the badge from each other. Applied to the single-target
project the back-fill lane exists to serve, it produced a repo whose only
release is not Latest. Detection now emits the key explicitly rather than the
rule inferring target count: an operator reads a written line and can strike it,
where an inferred rule changes behavior silently the day a second target is
added.

Six MEDIUM findings are decided rather than deferred, each pinned as a
governance rule: how to resolve an omitted target, the ancestry direction the
tag selector does not cover, a double-bump across two steps, the shape and
destination of a triage marker, what an operator actually does after a footer
BLOCK, and where the composed section file lives so it neither dirties the tree
nor enters the next window.

Refs: #563
…ce what it asks for (#563)

Four defects, all found by handing an agent the skill with no briefing and
watching where the prose ran out.

The contaminating reference is the one that matters most for #563: a
parenthetical cited `.github/actions/publish-release/action.yml` to say
where the tag-peeling helper came from. That path ships in no payload, so
every consumer read a pointer to a file they do not have. It was introduced
by 73bd884 - this campaign's own commit - and the consumer-portability
ratchet caught it only after the commit landed, because that fixture
archives HEAD rather than the working tree. Running the suite before
committing measures the previous payload; that is worth remembering as a
property of the harness, not a one-off.

The other three are places the prose named something without saying where
it comes from. `git tag` ran before the classification that authorizes it,
so a literal reading wrote the ref and then asked whether it should have.
Three of `classify`'s six arguments were never sourced. `<summary>` was
referenced once, in the title convention, and defined nowhere.

CHANGELOG: see the 2.11.0 Fixed entries
…563)

The Phase 2 reorder moved 'Tag with' out of the prose, breaking the anchor
that captures the peel-tag invocation. Repointed to 'Peel it through',
which sits immediately ahead of the same command.

The header comment claimed each anchor was verified unique; nothing checked
it. The missing-anchor case already fails loudly at setUpClass. The
ambiguous case does not: find() takes the first match, so a second
occurrence would silently capture a different command with every
downstream assertion still green. Now checked across all three renderings.
…cation (#563)

The lane driver extracts real commands from the shipped prose and runs
them, so moving `git tag` into the publish_fresh branch moved what the
driver captures.

The first replacement anchor was wrong in an instructive way: it captured
the peel-tag PIPELINE, which shlex.split cannot hand to subprocess as an
argv. The second candidate read better as prose ("this is the only place
`git tag` runs") and failed more quietly — the bare two-word mention
matches the invocation shape regex, so first-match capture would have
extracted `git tag` and run that. The landmark now sits between the
classification and the command with no command-shaped span in between.

This is the ambiguity failure mode the new uniqueness test was written for,
hit twice while fixing the thing that motivated it.

CHANGELOG: covered by the 2.11.0 Fixed entry on the Phase 2 reorder
… this campaign got wrong (#563, #569)

Run 4 of the blind agent exercise found two HIGHs. Both are confirmed
independently, and two of the three defects fixed here were introduced by
this campaign's own previous commit.

git tag's default cleanup mode is `strip`, which deletes every `#`-prefixed
line as a comment. A Keep-a-Changelog section is entirely `#`-prefixed, so
composing a tag message from one destroys the version heading and every
group heading. Verified directly: the stored message comes back as an
undifferentiated bullet list. This is #569, filed and left unfixed, and it
has already happened to this repository's published v2.8.13 - which, being
immutable, can only be superseded. Neither guard the skill named could see
it: release_dates_consistent reads the section from a separate argument and
only needs the Released-at line, and notes-match was pointed at the section
file rather than the tag. The lane now passes --cleanup=verbatim and then
re-reads what git actually stored.

The other two are mine, from 0dd8d6e. Fixing "three classify arguments are
named but never sourced" introduced wrong sourcing for two of them.
`manifest_version` said to read the manifest as Pre-flight read it - but
Pre-flight reads it before the bump, and the stale value returns
abort_mismatch, a terminal stop, on a healthy release. `release_nondraft`
was sourced from a command emitting `{"isDraft":false}` where a bare
boolean is expected, with the opposite polarity, making already_published
unreachable. Prose asserting how a caller wires a command is not covered by
any test that checks a phrase is present; both were caught by running the
literal command strings, which is now the habit.

`dates-match` closes a gap of the same shape: the prose called the check
mandatory and no CLI exposed it.

Mutation-testing the new rules found that the first --cleanup anchor
SURVIVED - the bare flag occurs twice, so deleting it from the command left
the explanation behind. Re-anchored, and the invariant is now a ratchet:
six pre-existing rules share the defect and are declared rather than
silently green (#571). The old manual check used grep -c, which counts
lines, and Phase 2 step 1 is one line thousands of characters long.

CHANGELOG: see the 2.11.0 Fixed entries
…fect (#569)

This test computed the strip-cleaned form of the composed message and
asserted the tag body equalled it. That was the right call while the defect
stood - it documented shipped behaviour instead of papering over it - and
it left instructions for this exact moment: if the body ever DOES contain
its heading, the invocation picked up --cleanup=verbatim and the assertion
should be relaxed deliberately rather than chased as a regression.

Now inverted: the composed message must reach the tag object byte-for-byte,
with the version heading and each group heading asserted individually so a
regression names what was lost.

Added a negative control. Every assertion above would pass vacuously on a
message containing no `#` lines, since strip and verbatim agree on such a
message - the fix would be untested and the suite would still be green.
Requiring the two forms to differ proves the fixture exercises the bytes
the defect destroys. That also keeps _git_strip_cleanup load-bearing rather
than leaving it dead behind the inversion.

Verified the assertion discriminates: it passes on a verbatim body and
fails on a default-cleanup body.

CHANGELOG: covered by the 2.11.0 Fixed entry on tag-message stripping
…inel (#563)

Run 5 of the blind exercise found one HIGH. Run 4 had already found it and
rated it MEDIUM; I filed it rather than fixing it. Run 5 made the better
argument and it is right.

With no tag yet in a series the helper returns the literal string `<none>`,
and the skill spelled the window `LAST_TAG..HEAD`, so the command handed to
the operator was `git log <none>..HEAD` - exit 128, `fatal: bad revision`.
The prose called that state "normal, not an error" in the same breath as
giving a command that cannot survive it. The affected population is not an
edge case: a consumer that just declared its first target through the
Back-fill lane has, by construction, no tag in that series, so this is the
first release of every back-filled project. The window is now derived into
$WINDOW before anything consumes it.

Three smaller ones on the ordinary path. The possibly-empty tag sha was
unquoted, and an empty unquoted argument does not become an empty
positional - it disappears, shifting five arguments left, so classify
exited 2 on the fresh-publish path. manifest_version named no extraction
command while every neighbouring argument named one. And the round-trip
check I added one commit ago read a reconstruction that appends a newline,
so it could not detect a byte difference even in principle; it now reads
the raw tag object. Measured: 72 bytes via cat-file, 73 via %(contents).

The lane driver derives $WINDOW the same way rather than hardcoding the
range shape, so the fixture exercises the derivation instead of assuming
it.

Every command string above was run verbatim before committing, including
the unquoted-versus-quoted contrast.

CHANGELOG: see the 2.11.0 Fixed entries
…#563)

Run 6 aimed at the never-released path and found a HIGH there.

A project that has shipped without ever tagging in its series resolves
LAST_TAG=<none>, took 0.0.0 as the base, and derived 0.1.0 from a feat -
which the manifest bump then wrote over a manifest already reading 1.4.2,
moving the project's own version backward. Every gate passed. The
manifest-equality assertion passed because the bump had just made it equal;
the strictly-greater check passed because it compared against a sentinel;
and classify never consulted the manifest because tag_exists=false
short-circuits first. Three guards, none of them looking in this direction.
The skill already reasoned about the manifest LAGGING its tag; the manifest
LEADING was unconsidered, in exactly the population back-fill serves.

0.0.0 is a placeholder that contradicts data already on disk. The base is
now the highest version any declared manifest carries - the maximum across
all of them, since a row may declare several and only the maximum is a safe
floor - and the strictly-greater assertion runs against that floor too.

The comparison is now a CLI subcommand rather than an import-only function.
The hard rules say the version MUST NOT be guessed, and this was the one
mechanical step in the lane with no tested helper behind it. Unparseable
input exits 2, never folded into the exit-1 "not greater" answer: fail-
closed is safe but indistinguishable from a real comparison, which is the
conflation the declared-file exit-3-vs-4 work already removed once.

No fixture here could have caught this - every consumer built in this suite
had a manifest consistent with its tag, so a missing floor check was
indistinguishable from a working one. Added the case where the manifest
leads, plus a check that the shipped payload can actually run the floor
command, since prose naming an unreachable command is unfollowable.

Also corrected a claim I leaned on last commit: the skill said dumping all
tags "always exits 0". Measured, git show-ref --tags -d exits 1 with zero
tags - the exact first-release state. The recommendation stands; the stated
reason was wrong.

The portability guard caught a hardcoded this-repo row name in my own draft
of this change, which is the contamination class this campaign exists to
remove.

CHANGELOG: see the 2.11.0 Fixed entries
…fails (#563)

Run 7 found a HIGH that my own run-6 fix created.

Run 6 floored the strictly-greater CHECK on the manifest but stated the
BASE only inside the no-tag branch. A project WITH a tag therefore derived
off the tag alone and then failed its own manifest floor: tag v1.2.0,
manifest 1.4.2, minor bump, derived 1.3.0, blocked. A hard stop on a
legitimate release, and step 4 said only "must exit 0" - it explained what
exit 1 MEANS while step 3, right above it, spells out its remedy in full.
The correct move, re-derive off the manifest, appeared nowhere.

Fixed by simplifying rather than patching. There is now one $BASE_VERSION -
the max of the tag's bare version (or 0.0.0 when there is no tag) and the
highest version across every declared manifest - the bump applies to it,
and one comparison checks the result. Step 4 now names its remedy.

That also removes a MEDIUM in the same text: the two-floor form demanded a
second comparison against LAST_TAG, which on a first release is `<none>`.
That is not a version, semver-greater correctly exits 2 on it, so my own
instruction was unrunnable on precisely the path Back-fill exists to serve.

Two more from run 7. The manifest reader named only the JSON form, on a
grammar that permits any format, so a declared pyproject.toml raises
JSONDecodeError - the same unspecified-command defect the step's own
parenthetical claimed to be closing. And <manifest_version> reads the FIRST
declared manifest while the base reads the MAXIMUM across all of them:
deliberate, but safe only because step 6 bumps every path, so a partial
bump turns a healthy release into abort_mismatch whose stated reason points
away from the actual fault. Both stated now.

Verified both shapes by running the derivation end to end: the tagged
manifest-leads case and the no-tag case, with the sentinel never reaching
the comparator.

CHANGELOG: see the 2.11.0 Fixed entries
… gate (#563)

Eight blind exercises, each against the skill as the previous one left it.
HIGHs by run: 4, 2, 0, 2, 1, 1, 1, 0.

Run 8 probed the same region run 7's fix rewrote and found no HIGH. That
was the stated stopping condition: runs 5, 6 and 7 each found one HIGH, and
each was in a region newly probed - run 5 by accident, runs 6 and 7 by
direction - so a clean run in a NEW region would have proved little. A
clean run in an already-probed one is the honest signal.

This record does not claim convergence. Run 3 came back clean and I called
it that at the time; it was sampling, and the two runs after it found four
HIGHs between them. The artifact states the sequence and lets it speak: two
clean runs of eight.

Every HIGH after run 1 was in a seam - how a caller wires the mechanisms
together - never in a mechanism. The suites were green throughout: 272 unit
tests, 69 consumer-portability tests, mutation-verified governance rules.
None could see prose naming a command nobody can run, sourcing an argument
from the wrong read, or handing an operator a sentinel where a revision is
required. Three of the HIGHs were introduced by this campaign's own
remediation of an earlier HIGH, which is the strongest argument available
for keeping a real agent in the loop rather than trusting a green suite.

The gate is now a declared pre-tag command on the `ca` row, so any future
edit to the release skill fails it until a fresh exercise runs. Its own
test asserts both directions - a gate that can only pass proves nothing.

Run 8's MEDIUMs are filed (#570), not fixed, deliberately: fixing one edits
the skill and invalidates the hash just recorded. Stopping does not close
the loop, it parks it behind a mechanism that reopens on the next edit.

CHANGELOG: covered by the 2.11.0 entries for the release-lane work
… shipped (#563)

Three corrections to files committed one commit ago.

T-78's row specified a SCRIPTED scenario harness - happy path, missing-
footer BLOCK, back-fill confirm and refuse. That is not what shipped. What
shipped is eight human-directed blind exercises plus a hash-freshness gate.
Flipping the row to ACCEPTED without amending it asserted a harness exists
that does not, which is the same class as citing an issue number before
filing it. The row now names the substitution, and the note says plainly
that a scripted harness is still worth building and is not claimed here.

The artifact's verification block still carried run-1-era counts - 256
tests, 60 consumer-smoke, three pre-tag commands - beside a freshly current
proof hash. Current is 272, 69, and four. Stale evidence next to a current
hash invites the inference that the whole record was re-verified when only
the hash had been.

Re-checked _KNOWN_WEAK_ANCHORS in the direction the ratchet cannot check
itself. Set equality catches a rule going weak; it cannot tell you a
declared-weak rule has been repaired and should come off. Four commits of
new prose landed since the set was written, including two re-anchorings.
All six are still genuinely weak - verified, not assumed - so the set
stands unchanged.

CHANGELOG: covered by the 2.11.0 entries for the release-lane work
…ose (#563, T-28..T-32)

DECISION-0034 requires the lane to run each declared pre-tag command in
order, assert exit 0, then assert a clean tree, and BLOCK on either. Those
were four rules an agent had to remember and apply in sequence. Eight blind
runs showed that is precisely where this campaign's defects live, so they
are now one command: `run-pre-tag $TARGET`.

Exit codes are distinguishable rather than a single failure: 5 a command
reported drift, 6 a command exited 0 but mutated the tree. It also refuses
to start on an already-dirty tree, because a pre-existing modification is
indistinguishable from one a declared command made. The clean-tree
assertion precedes any rebuild trivially - this runner never invokes
rebuild, so the two can never be conflated (A-2.3).

The 1024-char cap (A-2.4) lands in the PARSER, not the runner, and applies
to every declared key rather than only pre-tag: rebuild and generate are
executed exactly as pre-tag is, so capping only the key that motivated the
rule leaves the identical exposure one field over. It raises
ValueTooLongError, a sibling of the other declared-file errors, so it exits
4 - never 3, which is the Back-fill lane's one trigger and would send the
lane to overwrite the file it just rejected.

Verified end to end in a scratch consumer before writing tests: declared
order preserved, first-failure stop (a third command never ran), a
mutating command caught by the tree assertion, and an over-cap value
rejected at parse. Four mutants killed, including the off-by-one boundary
and a cap-only-pre-tag variant. One real defect found in my own runner:
the command label printed AFTER the output it labelled, because print is
buffered while the subprocess writes directly - so the log misattributed
which command produced what, in the one report an operator reads to decide
whether a release is safe.

security-controls.md now declares the boundary crossing (A-2.5): declared
commands are operator-authored executable input on a contents:write lane,
bounded by check-only semantics, the runner's mechanical assertion, and
H-22 protection of the declaring file.

The freshness gate fired on its first real change - this slice edited the
skill, so run 8's proof no longer covers it and `ca`'s pre-tag row is RED
until a fresh exercise runs. That is honoured, not routed around:
proof_current is false with the reason recorded. Its own live-repo tests
are rewritten as invariants rather than "the artifact is currently fresh",
since that form needed hand-inversion on every legitimate change - which is
how a gate's test rots into decoration.

CHANGELOG: covered by the 2.11.0 entries for the release-lane work
…t "pristine" (#563)

Run 9 found two HIGHs. The first is mine, from the runner I added one
commit ago.

I asserted a pristine tree. That BLOCKS EVERY RELEASE: Phase 1 rolls the
changelog and bumps the manifest before this step runs, so by the time the
runner starts, the tree is legitimately dirty. Reproduced with a row
declaring NO pre-tag commands at all - still exit 6. And the step must stay
after the bump, because a badge or catalog check compares a surface against
the NEW version and would pass vacuously against the old one.

The assertion is now snapshot-and-diff: baseline before the first command,
compared after each one, reporting only paths that command introduced. The
property that mattered is kept - a declared command's own writes still
surface on top of the operator's edits - and the message now names the one
new path instead of dumping the whole dirty tree.

Second: commands ran in the inherited cwd while the declaration came from
CLAUDE_PROJECT_DIR, so a declared check could pass having inspected a
different repository entirely. Demonstrated in both directions. They now
run in the project root.

The other HIGH is older and is prose. The exit-5 message said "re-run the
release" - but the manifest bump is already on disk, so it becomes the next
run's version floor, the restart derives a HIGHER version, and the section
this run already wrote is stranded under a version that was never tagged.
Nothing catches it: notes-match only checks the new section's own heading.
Both the runner's message and Phase 1 step 6 now say to discard the
uncommitted release edits and commit the reconciliation alone.

Three mutants killed, including reverting to the pristine-tree form and
restoring the inherited cwd.

CHANGELOG: covered by the 2.11.0 entries for the release-lane work
…istry (#564, T-33)

The registry has shipped empty since B1 built it. This enrols its first
consumer: the file carrying per-row pre-tag, rebuild and generate shell
commands that /ca:release executes on a lane holding contents:write, so
planting a command in it is a code-execution path and writing it now costs
a fresh authoring marker.

marker-gated, not helper-only. open-tasks.md is helper-only because
taskwrite.py is its sole blessed writer and writes through Python file I/O
whose argv never names the file - invisible to every flank by construction.
This file has THREE sanctioned authors (context-creation, the back-fill
lane, the row-edit path), all of which mint the marker, so a hard block
would leave them no route. The mutant that swaps the policy to helper-only
fails on all three flanks, which is what makes the choice load-bearing
rather than incidental.

Spec 2.7's four-case flank test now runs against the PRODUCTION registry on
all three doors, not a synthetic one: Write blocks, Edit blocks, a shell
redirect and a sed -i-class verb block, and a marker-fresh write succeeds.
Testing the Write door alone passes while `echo 'pre-tag: ...' >>
release-targets.md` still plants a command the lane later executes, which
is the whole attack the class prices up. Also pinned: git add stays
allowed, or commit-gate could not commit a sanctioned row edit; reads stay
allowed; a stale marker does not admit; and another consumer's marker does
not arm this one.

Six tests asserted the registry was EMPTY. They were right while it was,
and are now two-way assertions on the exact declared set, so an unreviewed
addition and a silent removal both fail.

One trap worth recording, hit while probing: _STATE_WRITE_RES is compiled
ONCE AT IMPORT from the live registry. Enrolling a consumer and then
importing the shell flank shows protection; importing first and enrolling
after shows none. My first probe did the latter and reported every command
allowed - which reads exactly like a missing guard. There is now a test
asserting the compiled set tracks the registry.

CHANGELOG: covered by the 2.11.0 protected-state registry entry
…ot by porcelain line (#563)

Run 10 found two HIGHs. The second is a hole in my own run-9 fix.

Step 7 read "IF the changelog edit needs to land as a commit" - which a
literal traversal answers "no". Neither gate named a clean tree, so nothing
between the manifest bump and `git tag` required the release edits to be
committed. Demonstrated: a tag whose payload still reads 0.1.0 with no
0.2.0 changelog section, while its own message quotes that section. Every
guard passes, because dates-match compares two scratch files and
notes-match reads only a heading - none of them looks at the tagged tree.
Step 7 is now unconditional and the Phase-1 gate requires an empty
porcelain on exit.

The mutation assertion compared porcelain LINES. A command mutating a file
that was already ` M` produces a byte-identical line, so the change fell
out of the set difference and the command exited 0. The blind spot covered
exactly $CHANGELOG and $MANIFEST - the two files Phase 1 touches
immediately before that step, and the two that actually ship: one into the
tag message and the Release notes, the other as the version the tag claims.
Reproduced with a changed sha256 and an INJECTED line surviving to exit 0.
The snapshot now digests the content of every path git reports as changed.

Worth stating plainly: my run-9 commit message claimed the property this
did not have. The implementation's own comment said "changed nothing NEW",
which was accurate; the skill said "asserts a clean tree after each one",
which was not.

The weak-anchor ratchet earned its keep here - the step-7 fix added a
second mention of `dates-match`, and the ratchet failed rather than letting
that rule quietly lose its ability to detect its own deletion.

CHANGELOG: covered by the 2.11.0 entries for the release-lane work
…it (#563, T-51 mechanism)

Criterion 5.5. On a project's first release the tag series is empty, so
LAST_TAG is <none> and the window is the entire history. Every pre-adoption
feat/fix/perf/refactor commit therefore enters the footer-completeness
check, and none can pass, because they predate the convention entirely. A
repository adopting at its 500th commit gets a 500-line block on a release
where nothing is wrong - a hard block on a legitimate release, landing on
exactly the population the Back-fill lane exists to serve.

The adoption commit is the honest boundary: commits before it were authored
under no changelog convention and cannot retroactively acquire footers,
while commits after it were authored under one and should be held to it.

Takes the LAST line of --diff-filter=A output, not the first. git log
prints newest-first, so the last line is the earliest addition; a file
added, deleted and re-added yields two entries, and taking the newest would
treat the re-adoption as the boundary and silently drop every commit
between - the same quiet history loss the function exists to prevent. Three
mutants killed, including that one.

Exit 0 with empty output when a project has no adoption commit: that is a
normal answer for a repo that never onboarded, not an error, and a non-zero
exit would break a set -e lane on the ordinary path. Same contract as
peel-tag.

The prose that makes the lane USE this is deliberately not in this commit.
A skill edit invalidates the recorded agent-judgment proof and forces a
re-run, and run 11 is in flight against the current skill; T-42's prose has
the same property, so both land together in one batch afterwards, covered
by one exercise instead of two. T-51 stays PENDING with a note saying so,
because a mechanism with no caller is the defect class this campaign
already found once and flipping the row would assert a lane behaviour that
does not exist.

CHANGELOG: covered by the 2.11.0 entries for the release-lane work
SUaDtL added 2 commits August 1, 2026 03:21
…ressions in this sprint's own fixes (#563, #564)

Every one reproduced before being fixed; two undid work from earlier in
this same branch.

`task_block` diverged from `parse_board`'s closing rule. It advanced only
past `- Key:` sub-bullets and blanks, while `parse_board` keeps a task open
across ANY indented line -- so indented continuation prose stopped the
block early and orphaned the sub-bullets after it onto the next task. That
is HIGH-2 re-opened through a different door, in code written to close
HIGH-2. The rule is now copied from `parse_board` rather than paraphrased.

`_archive` parsed the board one line at a time, so every Task carried
lineno == 1 and no sub-fields. The index-based location added to fix HIGH-3
could therefore never match and silently fell through to its first-line
fallback on every archive. The outcome was right and the mechanism was
dead, which is how the next change breaks it.

`git_restore_re` still crossed newlines. When `write_re`'s window was
bounded to one line, the sibling two lines below it kept the unbounded
form -- the fix went to the reported pattern instead of the class.

A `delete` op reached the marker-gated arm, so a self-mintable
friction-grade marker (ADR-0024) became a delete capability over protected
state. An authoring lane writes rows; it never removes the file.

`run-pre-tag`'s mutation check walked only the current tree state, so a
pre-tag command that REVERTED an in-flight edit was invisible -- the worst
case, since undoing the lane's own manifest bump ships a tag the payload
never claims. It now compares the union of both key sets.

`confirmation_path` folded every disallowed character to "_", so the legal
distinct targets `a.b` and `a_b` shared one marker and confirming either
confirmed the other. A digest of the raw name restores one-marker-per-target.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
…rom the hooks job

The portability guard's stated rule is EXECUTES-OR-READS, but `.md` was
missing from its suffix list, so a skill telling a consumer to READ one of
this repo's own docs passed unflagged -- the documented rule was wider than
the behaviour, which is the failure mode a guard that states its own rule
is supposed to prevent. And the repo-root test is a literal prefix match,
so `./tools/farm.js` slipped past on two characters. Both now covered, with
the resolved-prefix and scan-target exemptions verified unchanged and the
live shipped skills still clean.

The hooks job's checkout now sets `persist-credentials: false`. It runs
read-only suites and never pushes, so leaving the ambient GITHUB_TOKEN in
.git/config for every later step is reach nothing in the job needs. Safe
here specifically because the repository is public and this step has
already fetched the history and tags the suites require.

Not applied to the other 30 checkouts in this workflow: some of those jobs
do use the token, and a blanket sweep is a separate change that deserves
its own verification rather than riding along here.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
plugins/ca/hooks/tests/test_pre_write.py (1)

328-347: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add delete-arm regression tests for ca-pi and ca-codex

Neither sibling hook has a test suite. Add tests for marker-gated and helper-only deletes, matching plugins/ca/hooks/tests/test_pre_write.py.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/hooks/tests/test_pre_write.py` around lines 328 - 347, Add
equivalent delete-arm regression coverage for the sibling ca-pi and ca-codex
hooks, following the patterns in
test_a_fresh_marker_does_not_admit_deleting_marker_gated_state and
test_delete_of_helper_only_state_stays_blocked from test_pre_write.py. Verify
marker-gated deletes remain blocked with a fresh authoring marker and
helper-only deletes remain blocked without a marker path.
.github/scripts/test_taskwriter.py (1)

848-871: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Strengthen the block-move assertion to check the moved content, not just its absence.

test_indented_continuation_prose_does_not_split_the_block asserts the continuation prose and Boundaries disappear from open-tasks.md, and that Boundaries reappears in done-tasks.md. It never asserts that the continuation prose text itself lands in done-tasks.md. A regression that drops the prose line entirely, instead of moving it with the block, would pass this test unnoticed. Add an assertion that done-tasks.md contains the continuation prose text.

♻️ Proposed strengthening
         survivor = next(t for t in tb.parse_board(open_after) if t.id == "g.t.0002")
         self.assertEqual(survivor.boundaries, [])
         self.assertIn("- Boundaries: egress, secrets", self._read(root, "done-tasks.md"))
+        self.assertIn("continuation prose", self._read(root, "done-tasks.md"))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/test_taskwriter.py around lines 848 - 871, Add an assertion
in test_indented_continuation_prose_does_not_split_the_block verifying that the
continuation prose text appears in done-tasks.md, alongside the existing
Boundaries assertion. Keep the current open-tasks absence and survivor checks
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/scripts/test_taskwriter.py:
- Around line 848-871: Add an assertion in
test_indented_continuation_prose_does_not_split_the_block verifying that the
continuation prose text appears in done-tasks.md, alongside the existing
Boundaries assertion. Keep the current open-tasks absence and survivor checks
unchanged.

In `@plugins/ca/hooks/tests/test_pre_write.py`:
- Around line 328-347: Add equivalent delete-arm regression coverage for the
sibling ca-pi and ca-codex hooks, following the patterns in
test_a_fresh_marker_does_not_admit_deleting_marker_gated_state and
test_delete_of_helper_only_state_stays_blocked from test_pre_write.py. Verify
marker-gated deletes remain blocked with a fresh authoring marker and
helper-only deletes remain blocked without a marker path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d2754998-3b59-40ca-8c9b-972807787084

📥 Commits

Reviewing files that changed from the base of the PR and between a5b7a67 and 5db3aad.

📒 Files selected for processing (30)
  • .github/scripts/build_release_targets_provenance.py
  • .github/scripts/check_skill_portability.py
  • .github/scripts/test_release_lib.py
  • .github/scripts/test_taskwriter.py
  • core/pysrc/_bashguardlib.py
  • core/pysrc/_releaselib.py
  • core/pysrc/_taskboardlib.py
  • core/pysrc/pre-write.py
  • core/pysrc/releasehash.py
  • core/pysrc/taskwrite.py
  • plugins/ca-codex/hooks/_bashguardlib.py
  • plugins/ca-codex/hooks/_releaselib.py
  • plugins/ca-codex/hooks/_taskboardlib.py
  • plugins/ca-codex/hooks/pre-write.py
  • plugins/ca-codex/hooks/releasehash.py
  • plugins/ca-codex/hooks/taskwrite.py
  • plugins/ca-pi/hooks/_bashguardlib.py
  • plugins/ca-pi/hooks/_releaselib.py
  • plugins/ca-pi/hooks/_taskboardlib.py
  • plugins/ca-pi/hooks/pre-write.py
  • plugins/ca-pi/hooks/releasehash.py
  • plugins/ca-pi/hooks/taskwrite.py
  • plugins/ca/hooks/_bashguardlib.py
  • plugins/ca/hooks/_releaselib.py
  • plugins/ca/hooks/_taskboardlib.py
  • plugins/ca/hooks/pre-write.py
  • plugins/ca/hooks/releasehash.py
  • plugins/ca/hooks/taskwrite.py
  • plugins/ca/hooks/tests/test_pre_write.py
  • plugins/ca/hooks/tests/test_protectedstatelib.py
🚧 Files skipped from review as they are similar to previous changes (23)
  • plugins/ca-codex/hooks/pre-write.py
  • core/pysrc/pre-write.py
  • plugins/ca/hooks/pre-write.py
  • plugins/ca/hooks/taskwrite.py
  • plugins/ca-pi/hooks/taskwrite.py
  • .github/scripts/check_skill_portability.py
  • core/pysrc/releasehash.py
  • .github/scripts/build_release_targets_provenance.py
  • plugins/ca/hooks/_taskboardlib.py
  • plugins/ca-codex/hooks/_taskboardlib.py
  • plugins/ca-codex/hooks/taskwrite.py
  • core/pysrc/taskwrite.py
  • plugins/ca-pi/hooks/_taskboardlib.py
  • core/pysrc/_taskboardlib.py
  • plugins/ca-pi/hooks/releasehash.py
  • plugins/ca-codex/hooks/releasehash.py
  • plugins/ca/hooks/releasehash.py
  • .github/scripts/test_release_lib.py
  • plugins/ca/hooks/tests/test_protectedstatelib.py
  • core/pysrc/_releaselib.py
  • plugins/ca-pi/hooks/_releaselib.py
  • plugins/ca-codex/hooks/_releaselib.py
  • plugins/ca/hooks/_releaselib.py
📜 Review details
⏰ Context from checks skipped due to timeout. (17)
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: macos-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: windows-latest>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Security analysis <language: JavaScript/TypeScript>
  • GitHub Check: [CHECK] | [PI ] | Host-independent adapter contract
  • GitHub Check: Coverage union <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [SBX ] | Sandbox driver contract
  • GitHub Check: Coverage union <os: windows-latest>
  • GitHub Check: [CHECK] | [CA ] | Farm dispatcher contract
  • GitHub Check: Coverage union (Pi) <os: windows-latest>
  • GitHub Check: Analyze (rust)
🧰 Additional context used
🪛 ast-grep (0.45.0)
.github/scripts/test_taskwriter.py

[warning] 855-856: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(os.path.join(root, ".codearbiter", "open-tasks.md"),
"w", encoding="utf-8", newline="\n")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

core/pysrc/_bashguardlib.py

[warning] 641-643: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.compile(
GIT + r"\s+(?:checkout|restore)\b[^|;&\n]*" + name + _STATE_NAME_RIGHT_EDGE, re.I,
)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

plugins/ca-codex/hooks/_bashguardlib.py

[warning] 641-643: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.compile(
GIT + r"\s+(?:checkout|restore)\b[^|;&\n]*" + name + _STATE_NAME_RIGHT_EDGE, re.I,
)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

plugins/ca-pi/hooks/_bashguardlib.py

[warning] 641-643: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.compile(
GIT + r"\s+(?:checkout|restore)\b[^|;&\n]*" + name + _STATE_NAME_RIGHT_EDGE, re.I,
)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

plugins/ca/hooks/_bashguardlib.py

[warning] 641-643: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.compile(
GIT + r"\s+(?:checkout|restore)\b[^|;&\n]*" + name + _STATE_NAME_RIGHT_EDGE, re.I,
)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🔇 Additional comments (9)
plugins/ca-pi/hooks/pre-write.py (2)

14-19: LGTM!

Also applies to: 37-39


140-151: LGTM!

plugins/ca/hooks/tests/test_pre_write.py (1)

309-326: LGTM!

.github/scripts/test_taskwriter.py (2)

1057-1122: 📐 Maintainability & Code Quality

Confirm the rationale-flag CLI test still asserts through source text.

A previous review on this file flagged test_add_rationale_is_exposed_by_the_taskwrite_cli for asserting assertIn('"--desc"', text) against taskwrite.py's source text rather than invoking the CLI, which cannot detect a mechanism nobody can invoke. This range (rationale sub-bullet tests, including "taskwrite CLI exposure") is not included in the current review context, and the commit-message summary's list of six confirmed hook fixes does not mention this test. Confirm whether the test now exercises taskwrite.py via subprocess, matching the ArchiveVerbTest._run pattern, rather than reading source text.

#!/bin/bash
# Description: Check whether the rationale CLI test still asserts on source text.
rg -n -A15 'def test_add_rationale_is_exposed_by_the_taskwrite_cli' .github/scripts/test_taskwriter.py

872-889: LGTM!

core/pysrc/_bashguardlib.py (1)

636-644: LGTM!

plugins/ca-codex/hooks/_bashguardlib.py (1)

636-644: LGTM!

plugins/ca-pi/hooks/_bashguardlib.py (1)

636-644: LGTM!

plugins/ca/hooks/_bashguardlib.py (1)

636-644: LGTM!

…563, #564)

The `||` fallback discarded the exit codes this lane is built on. `cmd ||
cmd2` branches on the EXIT CODE and cannot tell "no such interpreter" from
"the helper ran and told you something" -- and these helpers answer in
codes by design (run-pre-tag 5=drift 6=mutation, semver-greater and
check-manifests each separating "no" from "could not compare"). So every
one of those answers re-ran the whole command and reported the SECOND run's
code; for run-pre-tag that means executing the project's declared pre-tag
commands twice and losing the first verdict. Resolved once, by presence,
with `command -v`. Scoped to this skill: the same spelling appears in ~40
others as the documented cross-host convention, filed separately rather
than rewritten here.

Phase 1 step 6 asserted check-manifests BEFORE the update that makes it
true, so an agent reading top to bottom ran the equality guard against
manifests it had not written yet. Split into ordered sub-steps, which also
breaks up a paragraph long enough to hide the ordering in the first place.

releasehash.py was built, tested, vendored to three plugins -- and invoked
by nothing, so the A-2.10 pre-tag confirmation never ran. An inert gate
reads as coverage. Wired into step 6c.

context-creation Phase 5 writes release-targets.md, which THIS PR enrolled
as marker-gated, with no marker step -- the enrolment broke its own
sanctioned writer. Same seam class as HIGH-1.

Test hygiene: the release-lib fixture now builds its git repo hermetically
and checks each exit code (a host gpgsign or hooksPath could silently
produce a fixture with no commit in it); check_skill_proof_fresh's main()
takes overrides so its FAILING branch is exercised rather than only its
green live-repo path; and two live-HEAD assertions skip with a stated
reason when ca-pi's window is empty, which is normal right after a ca-pi
release and was a red suite for a non-defect.

The proof gate is RED until the batched blind exercise re-records it.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
…ading by eye (#563)

Four HIGHs from blind exercise run 14, which drove the shipped skill as an
operator's agent would.

The lane's own rule is that the declared file is read "through the same
tested grammar", never "a by-eye scan of the delimiter block" -- but only
`prefix` and the target names had readers. Nine fields had none, so
following this skill REQUIRED doing the thing it forbids, and the
exercising agent read all nine by eye and said so. `show-row` now prints
one KEY=VALUE line per field, with undeclared fields printed empty so "not
declared" stays distinguishable from "I did not look".

`$PAYLOAD` is documented as "payload, minus payload-exclude", and
`git log -- <path>` has no subtraction. The `:(exclude)` form that does
appears nowhere an operator would infer it, so for any row declaring an
exclude the window was unspellable from the prose and the excluded commits
counted silently toward the bump and the changelog. `payload-pathspec`
emits the pathspec to pass verbatim.

The changelog had no floor when a manifest runs AHEAD of the last tag.
`$BASE_VERSION` floors the VERSION for exactly that shape, but Phase 1
step 5 rolls every footer in `$WINDOW` -- which still starts at LAST_TAG --
so the release re-publishes every entry already shipped under the untagged
versions, and step 3 BLOCKs on footer-less commits whose only stated remedy
is amending published history. Measured on this repo at run 14: LAST_TAG
v2.8.13, manifest 2.11.0, 38 of 51 flagged commits already published. The
lane could not release itself. It now detects the gap and STOPs, naming the
reconciliation as a deliberate maintainer action.

Also the interpreter spelling this branch made inconsistent: three steps
used "$PY" while fifteen still said python3, including the inline -c
snippets. One spelling throughout now.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
core/surface/skills/context-creation/SKILL.md (1)

81-93: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Align the single-target template with the Back-fill contract.

The release Back-fill lane emits latest-eligible: true for this exact one-target shape. This template omits it, so its default publishes with --latest=false. The same project then gets different release behavior based on how it was initialized.

Add latest-eligible: true to this template and synchronize the generated context-creation variants.

Proposed fix
-```
+```text
 <!-- release-targets -->
 [app]
 prefix: v
 manifest: package.json
 changelog: CHANGELOG.md
 payload: .
+latest-eligible: true
 <!-- /release-targets -->
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/surface/skills/context-creation/SKILL.md` around lines 81 - 93, Update
the single-target release-targets template in the context-creation skill to
include latest-eligible: true alongside prefix, manifest, changelog, and
payload. Synchronize every generated context-creation variant that emits this
template so the exact one-target shape matches the Back-fill contract.
plugins/ca/skills/release/SKILL.md (1)

73-80: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make back-fill declaration creation atomic.

  • plugins/ca/skills/release/SKILL.md#L73-L80: use an exclusive or atomic no-clobber write.
  • plugins/ca-codex/routines/release/SKILL.md#L73-L80: use an exclusive or atomic no-clobber write.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/skills/release/SKILL.md` around lines 73 - 80, Make the confirmed
back-fill write atomic and no-clobber in the release authoring flow described at
“Persist, only on confirmation” in plugins/ca/skills/release/SKILL.md (lines
73-80) and plugins/ca-codex/routines/release/SKILL.md (lines 73-80): replace the
non-exclusive write approach with an exclusive atomic creation that fails if
release-targets.md already exists, while preserving the immediate existence
check, marker lifecycle, and confirmed-block contents.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/test_check_skill_proof_fresh.py:
- Around line 388-395: Update both hash fixture setups in
.github/scripts/test_check_skill_proof_fresh.py at lines 388-395 and 412-421 to
set document["proof_current"] = True before invoking G.main(); apply the same
change at both sites so the tests reach hash comparison and preserve their
intended stale-hash and current-hash outcomes.

In `@core/surface/skills/context-creation/SKILL.md`:
- Around line 122-135: Replace the separate touch/write/rm sequence in the
conditional release-targets.md authoring flow with a failure-safe one-shot
marker admission or sanctioned transactional authoring mechanism, ensuring the
marker is consumed even if the protected write fails or execution stops after
admission. Preserve the skip behavior for runs that do not write
release-targets.md. Apply the synchronized change at
core/surface/skills/context-creation/SKILL.md:122-135,
plugins/ca-codex/routines/context-creation/SKILL.md:122-135,
plugins/ca-pi/routines/context-creation/SKILL.md:122-135, and
plugins/ca/skills/context-creation/SKILL.md:122-135.

In `@core/surface/skills/release/SKILL.md`:
- Around line 30-34: Replace the unsafe eval-based parsing around show-row in
core/surface/skills/release/SKILL.md and plugins/ca-pi/routines/release/SKILL.md
with shell-safe quoted value handling or a non-evaluating parser; ensure fields
such as display-name and pre-tag cannot execute metacharacters or command
substitutions. Add a regression test covering malicious show-row values, and
keep both release skill files synchronized.

In `@plugins/ca-codex/hooks/_releaselib.py`:
- Around line 1659-1715: Replace the KEY=VALUE output in the show-row branch and
space-joined output in payload-pathspec with a lossless structured serialization
protocol that preserves whitespace, commas, shell metacharacters, and list
boundaries without eval. Update the corresponding consumers to parse the
structured row and pass payload pathspecs as a quoted argument array rather than
expanded shell words. Add round-trip tests covering special characters and
excluded pathspecs, using the existing show-row and payload-pathspec entry
points.

In `@plugins/ca/skills/release/SKILL.md`:
- Around line 28-30: The declared-row surfaces must expose the REBUILD field
before the artifact freshness gate. In plugins/ca/skills/release/SKILL.md lines
28-30 and plugins/ca-codex/routines/release/SKILL.md lines 28-30, define and
read REBUILD via the show-row helper alongside the other declared fields, then
use that value in the freshness decision.
- Around line 123-124: The release workflow must apply the first-release
boundary before footer classification. In plugins/ca/skills/release/SKILL.md
lines 123-124, update the window setup used by classify-window to floor the
commit range at the first release boundary, and define the baseline when
back-fill leaves CONTEXT.md absent. Apply the same change to
plugins/ca-codex/routines/release/SKILL.md lines 123-124; preserve the existing
classify-window reporting and exit-code behavior.
- Line 10: In plugins/ca/skills/release/SKILL.md at lines 10-10 and
plugins/ca-codex/routines/release/SKILL.md at lines 10-10, update the
omitted-target flow to capture the sole line returned by the list-targets
command into $TARGET before invoking tag-prefix or any other target helper;
preserve the existing multi-target STOP behavior and require exactly one result
for implicit selection.
- Around line 16-22: In plugins/ca/skills/release/SKILL.md lines 16-22 and
plugins/ca-codex/routines/release/SKILL.md lines 16-22, resolve the interpreter
once with a valid python3-to-python fallback before any helper invocation, then
consistently use "$PY" for every hook and inline snippet. Quote
"${CLAUDE_PLUGIN_ROOT}" in all helper paths, preserving the same invocation
spelling throughout both release instructions.
- Line 157: Update the local tag SHA pipeline at
plugins/ca/skills/release/SKILL.md:157-157 and
plugins/ca-codex/routines/release/SKILL.md:157-157 so git show-ref --tags -d
returning status 1 when no tags exist does not fail the pipeline under pipefail,
while preserving peel-tag as the pipeline’s effective status and keeping the
existing quoted TAG_SHA/classify flow unchanged.
- Line 157: Use the shared manifest-version reader through its CLI for
<manifest_version> in both plugins/ca/skills/release/SKILL.md:157-157 and
plugins/ca-codex/routines/release/SKILL.md:157-157, replacing the unspecified
format-specific parser guidance; extend _manifest_version for every supported
manifest format and make unsupported formats fail closed, or pass the derived
version only after check-manifests succeeds.
- Line 172: Replace the non-executable `--latest[=false]` placeholder in the
release command with explicit variants: use `--latest` only when the target is
eligible and newest across all declared series, and use `--latest=false` for
every other target. Apply this change in `plugins/ca/skills/release/SKILL.md`
lines 172-172 and `plugins/ca-codex/routines/release/SKILL.md` lines 172-172,
preserving the surrounding release logic.
- Around line 171-172: In plugins/ca/skills/release/SKILL.md lines 171-172 and
plugins/ca-codex/routines/release/SKILL.md lines 171-172, derive and validate a
quoted TAG with notes-match before git push, then use "$TAG" consistently for
git push, gh release create, and gh release view. Preserve the existing release
flow while preventing whitespace-containing prefixes from being split into
multiple arguments.
- Around line 30-34: Replace the eval-based row loading in the release skill
instructions with a non-evaluating loader that safely reads the raw KEY=VALUE
output from show-row while preserving the exported field variables. Apply the
same change to plugins/ca/skills/release/SKILL.md lines 30-34 and
plugins/ca-codex/routines/release/SKILL.md lines 30-34.

---

Outside diff comments:
In `@core/surface/skills/context-creation/SKILL.md`:
- Around line 81-93: Update the single-target release-targets template in the
context-creation skill to include latest-eligible: true alongside prefix,
manifest, changelog, and payload. Synchronize every generated context-creation
variant that emits this template so the exact one-target shape matches the
Back-fill contract.

In `@plugins/ca/skills/release/SKILL.md`:
- Around line 73-80: Make the confirmed back-fill write atomic and no-clobber in
the release authoring flow described at “Persist, only on confirmation” in
plugins/ca/skills/release/SKILL.md (lines 73-80) and
plugins/ca-codex/routines/release/SKILL.md (lines 73-80): replace the
non-exclusive write approach with an exclusive atomic creation that fails if
release-targets.md already exists, while preserving the immediate existence
check, marker lifecycle, and confirmed-block contents.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 18c0efa6-b843-4516-982c-4b134f5bac64

📥 Commits

Reviewing files that changed from the base of the PR and between 5db3aad and fdd25b4.

📒 Files selected for processing (20)
  • .codearbiter/sprint-log.md
  • .github/scripts/check_skill_portability.py
  • .github/scripts/check_skill_proof_fresh.py
  • .github/scripts/test_check_skill_proof_fresh.py
  • .github/scripts/test_release_lib.py
  • .github/scripts/test_release_trace.py
  • .github/scripts/test_skill_portability.py
  • .github/workflows/ci.yml
  • core/pysrc/_releaselib.py
  • core/surface/skills/context-creation/SKILL.md
  • core/surface/skills/release/SKILL.md
  • plugins/ca-codex/hooks/_releaselib.py
  • plugins/ca-codex/routines/context-creation/SKILL.md
  • plugins/ca-codex/routines/release/SKILL.md
  • plugins/ca-pi/hooks/_releaselib.py
  • plugins/ca-pi/routines/context-creation/SKILL.md
  • plugins/ca-pi/routines/release/SKILL.md
  • plugins/ca/hooks/_releaselib.py
  • plugins/ca/skills/context-creation/SKILL.md
  • plugins/ca/skills/release/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • .github/workflows/ci.yml
  • .github/scripts/check_skill_proof_fresh.py
  • core/pysrc/_releaselib.py
  • plugins/ca/hooks/_releaselib.py
  • plugins/ca-pi/hooks/_releaselib.py
  • .github/scripts/test_release_trace.py
📜 Review details
⏰ Context from checks skipped due to timeout. (15)
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: windows-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: macos-latest>
  • GitHub Check: [CHECK] | [PI ] | Security analysis <language: JavaScript/TypeScript>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.5>
  • GitHub Check: Coverage union (Pi) <os: windows-latest>
  • GitHub Check: Coverage union <os: windows-latest>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [CA ] | Farm dispatcher contract
  • GitHub Check: [CHECK] | [SBX ] | Sandbox driver contract
  • GitHub Check: Analyze (rust)
🧰 Additional context used
🪛 ast-grep (0.45.0)
.github/scripts/test_check_skill_proof_fresh.py

[info] 390-390: use jsonify instead of json.dumps for JSON output
Context: json.dumps(document)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 416-416: use jsonify instead of json.dumps for JSON output
Context: json.dumps(document)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

.github/scripts/test_release_lib.py

[error] 2459-2460: Use of unsanitized data to create processes
Context: subprocess.run(base + argv, cwd=root, env=env,
capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 2459-2460: Command coming from incoming request
Context: subprocess.run(base + argv, cwd=root, env=env,
capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 2873-2874: Use of unsanitized data to create processes
Context: subprocess.run(base + pathspec, cwd=REPO_ROOT,
capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 2875-2876: Use of unsanitized data to create processes
Context: subprocess.run(base + ["plugins/ca-pi/"], cwd=REPO_ROOT,
capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 2873-2874: Command coming from incoming request
Context: subprocess.run(base + pathspec, cwd=REPO_ROOT,
capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 2875-2876: Command coming from incoming request
Context: subprocess.run(base + ["plugins/ca-pi/"], cwd=REPO_ROOT,
capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.16.0)
.github/scripts/test_release_lib.py

[error] 2460-2460: subprocess call: check for execution of untrusted input

(S603)


[error] 2874-2874: subprocess call: check for execution of untrusted input

(S603)


[error] 2876-2876: subprocess call: check for execution of untrusted input

(S603)


[warning] 2876-2876: Consider [*base, "plugins/ca-pi/"] instead of concatenation

Replace with [*base, "plugins/ca-pi/"]

(RUF005)

🪛 SkillSpector (2.4.4)
plugins/ca/skills/release/SKILL.md

[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-codex/routines/release/SKILL.md

[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

core/surface/skills/context-creation/SKILL.md

[error] 1: [TP1] null: HTML comments in tool metadata are invisible to users but may be processed by AI agents, enabling hidden instruction injection.

Remediation: Remove HTML comments from metadata fields. Metadata should contain plain, visible text only.

(MCP Tool Poisoning (TP1))


[error] 3: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))


[error] 31: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))

core/surface/skills/release/SKILL.md

[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-codex/routines/context-creation/SKILL.md

[error] 1: [TP1] null: HTML comments in tool metadata are invisible to users but may be processed by AI agents, enabling hidden instruction injection.

Remediation: Remove HTML comments from metadata fields. Metadata should contain plain, visible text only.

(MCP Tool Poisoning (TP1))


[error] 3: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))


[error] 31: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))

plugins/ca-pi/routines/context-creation/SKILL.md

[error] 1: [TP1] null: HTML comments in tool metadata are invisible to users but may be processed by AI agents, enabling hidden instruction injection.

Remediation: Remove HTML comments from metadata fields. Metadata should contain plain, visible text only.

(MCP Tool Poisoning (TP1))


[error] 3: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))


[error] 31: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))

plugins/ca-pi/routines/release/SKILL.md

[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 171: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 189: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca/skills/context-creation/SKILL.md

[error] 1: [TP1] null: HTML comments in tool metadata are invisible to users but may be processed by AI agents, enabling hidden instruction injection.

Remediation: Remove HTML comments from metadata fields. Metadata should contain plain, visible text only.

(MCP Tool Poisoning (TP1))


[error] 3: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))


[error] 31: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))

🔇 Additional comments (3)
.github/scripts/test_skill_portability.py (1)

60-80: LGTM!

.github/scripts/check_skill_portability.py (1)

59-65: LGTM!

Also applies to: 107-112

.codearbiter/sprint-log.md (1)

1348-1374: LGTM!

Comment thread .github/scripts/test_check_skill_proof_fresh.py
Comment thread core/surface/skills/context-creation/SKILL.md
Comment thread core/surface/skills/release/SKILL.md Outdated
Comment thread plugins/ca-codex/hooks/_releaselib.py
Comment thread plugins/ca/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md Outdated
…read (#563)

Blind exercise run 15, five HIGHs. The worst was introduced one commit
earlier, by the fix for run 14.

`show-row` emitted UNQUOTED values, and the skill documented reading them
with `eval "$(... show-row ...)"`. A declared `rebuild: cd x && npm run
build` therefore parsed as the assignment `REBUILD=cd` followed by the
COMMAND `x`, with `&& npm run build` waiting behind it -- one successful
exit from running a build nobody asked for. `eval` still reported 0,
because plain assignments follow the failing lines, so field order alone
decided whether the exit code revealed anything. These values are
operator-authored shell that this lane executes only AFTER `releasehash`
confirms a human has read them; executing a fragment of them at row-READ
time runs them before the gate that exists for them. Values are
`shlex.quote`d now, a `--field NAME` form needs no eval at all and is what
the skill uses, and a test hands the whole block to a real shell and proves
it assigns without executing.

The same reader named its keys wrong: it printed `PREFIX` while every
downstream command spells `$TAG_PREFIX`, so after the documented eval three
variables -- TAG_PREFIX, REBUILD, PRE_TAG, the three the lane leans on
hardest -- were silently empty, and the exercising agent had to read them
by eye. Which is the exact thing the subcommand was added to prevent.

`$PAYLOAD` was never assigned anywhere in the skill, and the eval clobbered
it with the raw field rather than the pathspec, reinstating the
payload-exclude blindness the previous commit had just closed.

`MAJOR.MINOR.PATCH` appeared in seven tag, push and release commands as a
placeholder no step ever assigned, so the highest-consequence commands in
the lane were uncopyable. `$VERSION` is now assigned where the bump is
applied.

The clean-tree gate could never pass: this governance layer's own hooks
append to gate-events.log on nearly every command, including the ones this
lane runs, so a compliant traversal STOPs on a file the act of checking
just wrote. The append-only sinks are exempted, and only those.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 4

🧹 Nitpick comments (2)
core/pysrc/_releaselib.py (1)

1677-1684: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a shared helper for the repeated --flag VALUE extraction.

This --field block duplicates the same three-line pop-a-flag-and-value pattern already used for --targets-file at lines 1636-1642 and 1774-1780. A small helper, for example _pop_flag(rest, "--field") returning (value, rest) or writing the "requires a value" error itself, removes the third near-identical copy and keeps future flags from re-deriving the same slicing logic.

♻️ Proposed helper
+def _pop_flag_value(rest, flag):
+    """Return (value_or_None, remaining_rest); writes to stderr and
+    returns (2, rest) as a sentinel error if the flag is present with no
+    value following it."""
+    if flag not in rest:
+        return None, rest
+    idx = rest.index(flag)
+    if idx + 1 >= len(rest):
+        sys.stderr.write(f"{flag} requires a value\n")
+        return "ERROR", rest
+    return rest[idx + 1], rest[:idx] + rest[idx + 2:]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/pysrc/_releaselib.py` around lines 1677 - 1684, Extract the repeated
flag-and-value parsing logic into a shared helper, such as _pop_flag, and use it
for --field and the existing --targets-file handling sites. Preserve the current
missing-value error behavior and return status while centralizing list slicing
and value extraction.
plugins/ca/hooks/_releaselib.py (1)

1677-1684: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a shared helper for the repeated --flag VALUE extraction.

Same duplication as in core/pysrc/_releaselib.py: this --field block repeats the flag/value extraction already used for --targets-file at lines 1636-1642 and 1774-1780.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/hooks/_releaselib.py` around lines 1677 - 1684, Extract the
repeated flag/value parsing logic into a shared helper in the relevant
release-library module, then use it for --field and the existing --targets-file
parsing paths around the affected command handlers. Preserve the current
missing-value error behavior, return status, extracted value, and updated rest
arguments for all callers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/surface/skills/release/SKILL.md`:
- Around line 35-38: Replace ROW command reconstruction in
core/surface/skills/release/SKILL.md lines 35-38 with direct helper invocations
that quote the script path and target for each field lookup. Regenerate the same
direct quoted calls in plugins/ca-codex/routines/release/SKILL.md lines 35-38
and plugins/ca-pi/routines/release/SKILL.md lines 35-38, covering prefix,
changelog, and manifest.
- Around line 193-194: Move the notes-match validation before the git push in
the Phase 1 publication sequence, so the tag is pushed only after the notes
pass. Apply this ordering change in core/surface/skills/release/SKILL.md lines
193-194, then regenerate the corresponding corrected publication order in
plugins/ca-codex/routines/release/SKILL.md lines 193-194 and
plugins/ca-pi/routines/release/SKILL.md lines 193-194.

In `@plugins/ca/skills/release/SKILL.md`:
- Around line 113-117: Update the Phase 1 exit check in the release workflow to
use the same scoped git status command as the pre-flight check, excluding only
.codearbiter/gate-events.log. Replace the unscoped status check while preserving
the existing dirty-tree handling and release-surface validation.
- Line 197: Update the provenance-recording step in the release instructions to
capture one `git ls-remote --tags origin "$TAG"` response and derive both hashes
from it: use the direct ref SHA for `object_sha`, and use the peeled `^{}` SHA
for `commit_sha`, falling back to the direct SHA for lightweight tags. Remove
the local `git rev-parse ${TAG_PREFIX}${VERSION}^{commit}` lookup and ensure the
procedure handles both annotated and lightweight tag output.

---

Nitpick comments:
In `@core/pysrc/_releaselib.py`:
- Around line 1677-1684: Extract the repeated flag-and-value parsing logic into
a shared helper, such as _pop_flag, and use it for --field and the existing
--targets-file handling sites. Preserve the current missing-value error behavior
and return status while centralizing list slicing and value extraction.

In `@plugins/ca/hooks/_releaselib.py`:
- Around line 1677-1684: Extract the repeated flag/value parsing logic into a
shared helper in the relevant release-library module, then use it for --field
and the existing --targets-file parsing paths around the affected command
handlers. Preserve the current missing-value error behavior, return status,
extracted value, and updated rest arguments for all callers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d6393b5-b851-426d-a71e-d0b3f55109e8

📥 Commits

Reviewing files that changed from the base of the PR and between fdd25b4 and 5bafba9.

📒 Files selected for processing (9)
  • .github/scripts/test_release_lib.py
  • core/pysrc/_releaselib.py
  • core/surface/skills/release/SKILL.md
  • plugins/ca-codex/hooks/_releaselib.py
  • plugins/ca-codex/routines/release/SKILL.md
  • plugins/ca-pi/hooks/_releaselib.py
  • plugins/ca-pi/routines/release/SKILL.md
  • plugins/ca/hooks/_releaselib.py
  • plugins/ca/skills/release/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/ca-codex/hooks/_releaselib.py
  • plugins/ca-pi/hooks/_releaselib.py
📜 Review details
⏰ Context from checks skipped due to timeout. (13)
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: windows-latest>
  • GitHub Check: [CHECK] | [PI ] | Host-independent adapter contract
  • GitHub Check: [CHECK] | [PI ] | Security analysis <language: JavaScript/TypeScript>
  • GitHub Check: Coverage union (Pi) <os: windows-latest>
  • GitHub Check: Coverage union <os: windows-latest>
  • GitHub Check: [CHECK] | [SBX ] | Sandbox driver contract
🧰 Additional context used
🪛 ast-grep (0.45.0)
.github/scripts/test_release_lib.py

[error] 2873-2874: Command coming from incoming request
Context: subprocess.run(["bash", "-s"], input=script.encode("utf-8"),
capture_output=True, cwd=REPO_ROOT)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.16.0)
.github/scripts/test_release_lib.py

[error] 2874-2874: Starting a process with a partial executable path

(S607)

🪛 SkillSpector (2.4.4)
plugins/ca/skills/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

core/surface/skills/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-codex/routines/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-pi/routines/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🔇 Additional comments (12)
core/pysrc/_releaselib.py (3)

104-104: LGTM!


1708-1763: Quoted NAME=value emission correctly closes the prior unquoted-eval hazard.

The new shlex.quote(_flatten(row.get(key))) output stops declared field values (for example a rebuild command containing &&) from being interpreted as shell syntax when a caller does eval "$(... show-row ...)". The --field NAME raw-value path gives callers a non-eval alternative for command substitution. This matches the fix described in the commit message.


1732-1742: 🗄️ Data Integrity & Integration

Keep the generate mapping. _KEY_FIELD maps the grammar key "generate" to the row field "generate", so the fields entry is correct. No generation-command key is declared.

			> Likely an incorrect or invalid review comment.
plugins/ca/hooks/_releaselib.py (3)

104-104: LGTM!


1708-1763: Quoted NAME=value emission correctly closes the prior unquoted-eval hazard.

Same fix as in core/pysrc/_releaselib.py: shlex.quote(_flatten(row.get(key))) stops declared field values from being interpreted as shell syntax under eval "$(... show-row ...)", and --field NAME gives a non-eval alternative.


1732-1742: 🗄️ Data Integrity & Integration

Verify that the generate key matches the declared row field.

Same concern as the identical block in core/pysrc/_releaselib.py: the fields list maps GENERATE to row key "generate", but the field-mapping layer summary describes the field as generation-command. Confirm the actual row key spelling before relying on this mapping, since this file is a byte-identical vendored copy and shares the same risk.

plugins/ca/skills/release/SKILL.md (6)

35-39: 🩺 Stability & Availability

Call helpers with quoted arguments.

$ROW is expanded unquoted. ${CLAUDE_PLUGIN_ROOT} is also unquoted in the direct helper calls. A plugin root or Python path containing whitespace is split, so the helper fails before release logic runs. Use a shell function or direct calls with individually quoted arguments.

This repeats the unresolved portability finding from the previous review.

🛠️ Suggested fix
-ROW="$PY ${CLAUDE_PLUGIN_ROOT}/hooks/_releaselib.py show-row $TARGET"
-TAG_PREFIX=$($ROW --field prefix)
+show_row_field() {
+  "$PY" "${CLAUDE_PLUGIN_ROOT}/hooks/_releaselib.py" \
+    show-row "$TARGET" --field "$1"
+}
+TAG_PREFIX=$(show_row_field prefix)

-PAYLOAD=$("$PY" ${CLAUDE_PLUGIN_ROOT}/hooks/_releaselib.py payload-pathspec $TARGET)
+PAYLOAD=$("$PY" "${CLAUDE_PLUGIN_ROOT}/hooks/_releaselib.py" \
+  payload-pathspec "$TARGET")

Also applies to: 48-48, 179-179


179-179: 🩺 Stability & Availability

Allow an empty local tag set under pipefail.

git show-ref --tags -d returns status 1 when the repository has no tags. Under pipefail, the pipeline still fails even when peel-tag correctly reports that the target tag is absent. The first release therefore stops before classification.

Allow status 1 from git show-ref before the pipe, while preserving other failures.

This repeats the unresolved previous finding.


179-179: 🗄️ Data Integrity & Integration

Use the shared manifest reader for <manifest_version>.

The instructions provide JSON and TOML examples, then say “the equivalent for anything else declared.” Different agents can therefore produce different classification inputs for supported formats. Route this value through the shared _manifest_version path, or pass the derived version only after check-manifests succeeds. Unsupported formats must fail closed.

This repeats the unresolved previous finding.


193-197: 🎯 Functional Correctness

Validate notes before remote publication and quote one tag variable.

Line 193 pushes the tag before Line 194 runs notes-match. A stale Phase 1 section can therefore publish a tag before the guard fails. Define TAG="${TAG_PREFIX}${VERSION}", run notes-match "$TAG" first, and use "$TAG" for push, create, view, and provenance commands.

The current unquoted expansions also split whitespace-containing prefixes.

This repeats the unresolved previous finding.

Source: Linters/SAST tools


194-194: 🎯 Functional Correctness

Replace the non-executable latest flag.

--latest[=false] is a notation placeholder, not a concrete gh release create argument. Pass --latest only for the eligible newest target. Pass --latest=false for every other target.

This repeats the unresolved previous finding.


156-157: LGTM!

Comment thread core/surface/skills/release/SKILL.md Outdated
Comment thread core/surface/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md Outdated
Comment thread plugins/ca/skills/release/SKILL.md
SUaDtL added 2 commits August 1, 2026 04:29
Three failures on run 30691314813, all consequences of this branch's own
changes meeting a runner that differs from this workstation.

1. `$PY` reached the consumer-smoke extractor as argv[0]. The skill now
   resolves the interpreter once (`PY=python3`, falling back to `python`)
   and invokes it through `$PY` everywhere after. The extractor replays
   single invocations, never the whole script, so the resolution line
   never runs -- `FileNotFoundError: '$PY'` in four setUpClass fixtures.
   `_prepare_argv` now resolves `$PY` the same way it already resolved a
   bare `python3`, which is the same T-42 concern one spelling later.

2. The clean-tree exemption named `.codearbiter/gate-events.log` as a
   BARE repo-relative path, so reference resolution existence-checked it
   against the scratch consumer repo and found nothing. The portable
   spelling (`{{PROJECT_DIR}}/...`) is what the rest of the skill uses
   and lands in the arm `_project_dir_is_exempt` already covers: whether
   a consumer has populated `.codearbiter/` is a runtime fact, not a
   packaging one. The git pathspec inside the fenced block stays
   repo-relative -- a pathspec has no other correct form, and fenced
   blocks are excised before extraction.

3. `bash` on windows-latest exits 1 with both streams empty, which is
   indistinguishable from the script under test failing silently. The
   decisive property -- an emitted row line is an assignment and nothing
   more -- is now asserted with `shlex` on every platform, and the shell
   round-trip became a corroborating arm guarded by a probe that proves
   the shell actually runs a stdin script. Mutation-checked: unquoting
   `show-row` is rejected by the tokenizer arm alone, on two independent
   lines (REBUILD and PRE_TAG), with the earlier assertion removed.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
…duced (#563)

The consumer-smoke lane driver reads real commands out of the skill's prose
and runs them. Two of this branch's own edits changed the spelling it was
matching on, and both failed by capturing the WRONG command rather than
by failing to capture one -- silent and misdirected, not loud.

`_INVOCATION_SHAPE_RE` did not treat `"$PY" `/`$PY ` as a command start, so
the `publish_state_classify` anchor walked past its classify call to the
`git tag -a ... -F <message-file>` in the branch below it. The driver then
ran a tag command under the classify label with a mapping holding no
`<message-file>`, and reported a git error against a step that was never
the one under test.

The tag-name mapping key still read `${TAG_PREFIX}MAJOR.MINOR.PATCH` after
the skill adopted a `$VERSION` variable. A key that matches nothing
substitutes nothing and raises nothing: `git tag -a` created a ref named
literally `${TAG_PREFIX}${VERSION}` and exited 0, surfacing three
assertions later as "tag v1.3.0 does not exist" -- true, and naming
neither the cause nor the line. The substituted argv is now checked for
the expected tag name at the point of substitution.

62 -> 69 tests now actually execute; the suite is green.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
core/surface/skills/release/SKILL.md (4)

123-129: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Do not block a normal tagless first release.

  • core/surface/skills/release/SKILL.md#L123-L129: Do not treat a manifest as drift when LAST_TAG=<none>, unless explicit adoption metadata proves that the version was already shipped.
  • plugins/ca-pi/routines/release/SKILL.md#L123-L129: Apply the same tagless-release rule.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/surface/skills/release/SKILL.md` around lines 123 - 129, Update the
manifest-versus-LAST_TAG drift rule in core/surface/skills/release/SKILL.md at
lines 123-129 and apply the same change in
plugins/ca-pi/routines/release/SKILL.md at lines 123-129: when LAST_TAG is
<none>, allow a normal first release even if the manifest has a version, unless
explicit adoption metadata proves that version was already shipped; retain the
existing gap report and stop behavior for established tag series.

121-121: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Reject unreachable tags before deriving the release baseline.

  • core/surface/skills/release/SKILL.md#L121-L121: Filter target tags by ancestry from HEAD, or classify an unreachable result as drift.
  • core/surface/skills/release/SKILL.md#L136-L136: Do not rely on documentation as the only control for this residual case.
  • plugins/ca-pi/routines/release/SKILL.md#L121-L121: Apply the ancestry check to the plugin skill.
  • plugins/ca-pi/routines/release/SKILL.md#L136-L136: Keep the residual blocked rather than merely documented.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/surface/skills/release/SKILL.md` at line 121, Update LAST_TAG resolution
in core/surface/skills/release/SKILL.md:121 and
plugins/ca-pi/routines/release/SKILL.md:121 to ensure the selected tag is
reachable from HEAD before deriving the release baseline, rejecting or
classifying unreachable results as drift rather than accepting them. At
core/surface/skills/release/SKILL.md:136 and
plugins/ca-pi/routines/release/SKILL.md:136, make the release procedure enforce
this check so the residual case remains blocked instead of relying only on
documentation.

113-119: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

The clean-tree exemption must respect the declared release surface.

  • core/surface/skills/release/SKILL.md#L113-L119: Re-include .codearbiter/gate-events.log when the target row declares it as a release surface.
  • plugins/ca-pi/routines/release/SKILL.md#L113-L119: Apply the same conditional exemption.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/surface/skills/release/SKILL.md` around lines 113 - 119, The clean-tree
exemption in the release guidance must be conditional on the declared release
surface: update the exemption instructions around the git status check in
core/surface/skills/release/SKILL.md lines 113-119 and
plugins/ca-pi/routines/release/SKILL.md lines 113-119 so
.codearbiter/gate-events.log is excluded only when it is not declared as a
release surface, and remains in scope otherwise.

137-139: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Quote release pathspecs individually. Unquoted $PAYLOAD permits word splitting and glob expansion, which can change the release window. Preserve each payload-pathspec result as a separate argument and pass it as "${PAYLOAD_ARGS[@]}". Iterate over $ARTIFACTS and pass each artifact as "$artifact". Apply this in both release skill files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/surface/skills/release/SKILL.md` around lines 137 - 139, The release
commands in core/surface/skills/release/SKILL.md lines 137-139 and
plugins/ca-pi/routines/release/SKILL.md lines 137-139 must preserve pathspec
boundaries: pass payload paths as separate quoted "${PAYLOAD_ARGS[@]}" arguments
instead of unquoted $PAYLOAD, and iterate over $ARTIFACTS while passing each
artifact as "$artifact" to git commands. Apply the same quoting and array
handling in both release skill files.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/test_release_lib.py:
- Around line 102-106: Update _probe_bash to catch subprocess.TimeoutExpired
alongside OSError and ensure the round-trip subprocess.run invocation uses a
60-second timeout, while preserving the existing None return behavior for failed
or stalled shell probes.

---

Outside diff comments:
In `@core/surface/skills/release/SKILL.md`:
- Around line 123-129: Update the manifest-versus-LAST_TAG drift rule in
core/surface/skills/release/SKILL.md at lines 123-129 and apply the same change
in plugins/ca-pi/routines/release/SKILL.md at lines 123-129: when LAST_TAG is
<none>, allow a normal first release even if the manifest has a version, unless
explicit adoption metadata proves that version was already shipped; retain the
existing gap report and stop behavior for established tag series.
- Line 121: Update LAST_TAG resolution in
core/surface/skills/release/SKILL.md:121 and
plugins/ca-pi/routines/release/SKILL.md:121 to ensure the selected tag is
reachable from HEAD before deriving the release baseline, rejecting or
classifying unreachable results as drift rather than accepting them. At
core/surface/skills/release/SKILL.md:136 and
plugins/ca-pi/routines/release/SKILL.md:136, make the release procedure enforce
this check so the residual case remains blocked instead of relying only on
documentation.
- Around line 113-119: The clean-tree exemption in the release guidance must be
conditional on the declared release surface: update the exemption instructions
around the git status check in core/surface/skills/release/SKILL.md lines
113-119 and plugins/ca-pi/routines/release/SKILL.md lines 113-119 so
.codearbiter/gate-events.log is excluded only when it is not declared as a
release surface, and remains in scope otherwise.
- Around line 137-139: The release commands in
core/surface/skills/release/SKILL.md lines 137-139 and
plugins/ca-pi/routines/release/SKILL.md lines 137-139 must preserve pathspec
boundaries: pass payload paths as separate quoted "${PAYLOAD_ARGS[@]}" arguments
instead of unquoted $PAYLOAD, and iterate over $ARTIFACTS while passing each
artifact as "$artifact" to git commands. Apply the same quoting and array
handling in both release skill files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 340d7ca5-4a81-4dd1-8048-3f7ee2386924

📥 Commits

Reviewing files that changed from the base of the PR and between 5bafba9 and cc6f8a7.

📒 Files selected for processing (6)
  • .github/scripts/test_consumer_smoke.py
  • .github/scripts/test_release_lib.py
  • core/surface/skills/release/SKILL.md
  • plugins/ca-codex/routines/release/SKILL.md
  • plugins/ca-pi/routines/release/SKILL.md
  • plugins/ca/skills/release/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/scripts/test_consumer_smoke.py
📜 Review details
⏰ Context from checks skipped due to timeout. (12)
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: windows-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: macos-latest>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Security analysis <language: JavaScript/TypeScript>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.5>
  • GitHub Check: Coverage union (Pi) <os: windows-latest>
  • GitHub Check: [CHECK] | [SBX ] | Sandbox driver contract
  • GitHub Check: Coverage union <os: windows-latest>
  • GitHub Check: Analyze (rust)
🧰 Additional context used
🪛 ast-grep (0.45.0)
.github/scripts/test_release_lib.py

[error] 102-103: Command coming from incoming request
Context: subprocess.run([exe, "-s"], input=b"printf ca-probe-ok\n",
capture_output=True, timeout=60)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 2933-2934: Command coming from incoming request
Context: subprocess.run([bash, "-s"], input=script.encode("utf-8"),
capture_output=True, cwd=REPO_ROOT)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.16.0)
.github/scripts/test_release_lib.py

[error] 103-103: subprocess call: check for execution of untrusted input

(S603)


[error] 2934-2934: subprocess call: check for execution of untrusted input

(S603)

🪛 SkillSpector (2.4.4)
plugins/ca/skills/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-codex/routines/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

core/surface/skills/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-pi/routines/release/SKILL.md

[error] 193: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 211: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🔇 Additional comments (4)
.github/scripts/test_release_lib.py (2)

56-57: LGTM!


2897-2924: LGTM!

plugins/ca/skills/release/SKILL.md (1)

113-117: LGTM!

plugins/ca-codex/routines/release/SKILL.md (1)

113-117: LGTM!

Comment thread .github/scripts/test_release_lib.py
SUaDtL added 2 commits August 1, 2026 05:03
…#563)

Two corrections to the previous commit, one mechanical and one factual.

`subprocess.TimeoutExpired` is a `SubprocessError`, not an `OSError`, so
catching only `OSError` left the hole open on the exact platform the probe
exists for: a `bash` that HANGS rather than exits would propagate out and
ERROR the test instead of skipping it. Now catches both, matching the pair
`adversarial_results()` in test_pi_security.py already uses.

The factual one matters more. That commit asserted windows-latest has no
usable shell. CI run 30692612801 reports `OK`, not `OK (skipped=1)` -- the
round trip RAN on windows and passed, so the probe is not what fixed it.
What fixed it was handing `subprocess` the absolute path from
`shutil.which("bash")` instead of the bare name: with no `shell=True` the
lookup falls to `CreateProcess`, whose search order is not `PATH` order,
and it picked a different `bash` that exits 1 with both streams empty.
"No usable shell" was a plausible reading of an empty error message, not a
measured fact, and the docstring said it as though it were one. The probe
is still worth keeping for a future runner where `which` finds nothing
usable -- it is just belt, not braces. Sprint-log corrected in place.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
Both are the same shape the campaign keeps producing: a rule argued
carefully in one paragraph and not applied to the command three
paragraphs later.

HIGH-1 -- every helper invocation broke on a plugin root containing a
space. All 18 were spelled `"$PY" {{PLUGIN_ROOT}}/hooks/<script>`:
interpreter quoted, path beside it not. `C:\Users\First Last\.claude\
plugins\...` is an ordinary Windows install, and on such a host the path
splits at the space and EVERY step fails at once -- target resolution,
last-tag, classify-window, check-manifests, classify, notes-match -- with
`can't open file '...\First'` as the operator's only diagnostic. The
irony is that the paragraph fixing the interpreter word exists precisely
because Windows consumers differ, and it left the argument beside it
exposed.

The `ROW=` shorthand went with it. It is not separately fixable: an
unquoted `$ROW` word-splits, which is what makes it run as a command at
all, so the path inside cannot be protected; and `"$ROW"` looks for one
executable named the whole string. Spelled out in full instead, which is
also what the file's own one-spelling rule already asked for. `$PAYLOAD`
stays unquoted and now says why -- it is a git pathspec that MUST split.

HIGH-2 -- Phase 1 step 7 asserted clean-tree with the bare `git status
--porcelain` while calling it "the same clean-tree state Pre-flight
required on entry". It is not: Pre-flight uses the exempted form under a
HIGH-rated paragraph explaining why the bare one cannot pass. Step 7 is
reached only after steps 5 and 6a write the changelog and every manifest,
each firing the hook that appends to the audit log, so at that exact
point the bare form is guaranteed non-empty and would hard-stop every
release at the last gate of Phase 1. commit-gate cannot rescue it -- it
stages by explicit path and unstages extras by design, so the log is
never swept in. The run observed this live: another session committed the
two dirty paths mid-evaluation, and the two spellings returned opposite
verdicts on the same tree seconds apart.

Three governance anchors spanned the `.py `/argument boundary and broke on
the added quote -- the #571 weak-anchor class. Repointed to the shipped
spelling, which now pins the quoting too.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
plugins/ca/skills/release/SKILL.md (3)

142-142: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject missing or untracked artifacts after rebuild.

git diff --quiet -- <artifact> checks tracked changes only. If $REBUILD creates an untracked artifact, or an artifact is absent, this check can succeed and the tag can omit a declared release artifact. Require every declared artifact to exist and be tracked before checking its diff.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/skills/release/SKILL.md` at line 142, Update the $ARTIFACTS
validation in the release procedure so each declared artifact is first required
to exist and be tracked by Git, then checked with git diff --quiet for
freshness. Ensure missing or untracked artifacts fail the release, while
preserving the existing $TARGET scoping and rebuild behavior.

149-158: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Apply the adoption boundary before classify-window.

Step 2 runs classify-window over $WINDOW before step 3 computes $ADOPTED. The helper already reports footerless bumping commits, so pre-adoption history can block the first release before the floor is applied. A back-filled project also has no CONTEXT.md, leaving $ADOPTED empty and the whole history in scope. Compute the floored window first, then use it for classification and footer validation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/skills/release/SKILL.md` around lines 149 - 158, Reorder the
release workflow so the adoption boundary is resolved before invoking
classify-window: compute ADOPTED when available, allow the user’s override, and
derive the floored WINDOW first. Pass that floored window to classify-window and
the subsequent footer validation, while preserving the existing behavior when no
adoption commit or CONTEXT.md exists.

90-97: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make back-fill creation atomic.

The marker only authorizes the write. It does not reserve the path or prevent overwrites. Another process can create release-targets.md after the absence check and before the write. Use an atomic create-only operation, such as O_EXCL or noclobber, and stop if creation loses the race.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/skills/release/SKILL.md` around lines 90 - 97, Update the
persistence instructions for release-targets.md to use an atomic create-only
write after the existing absence check and authoring-marker creation. Ensure the
operation fails without modifying the file if another process creates it first,
then stop and surface that race instead of overwriting; retain the existing
marker lifecycle and confirmed-block content.
core/surface/skills/release/SKILL.md (1)

149-158: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Compute the adoption floor before classifying the window.

Both skills invoke classify-window on the unfloored first-release history. Pre-adoption bumping commits can trigger the missing-footer exit before the later adoption-boundary logic runs.

  • core/surface/skills/release/SKILL.md#L149-L158: resolve $ADOPTED first and pass the floored window to classification and footer validation.
  • plugins/ca-codex/routines/release/SKILL.md#L149-L158: apply the same ordering.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/surface/skills/release/SKILL.md` around lines 149 - 158, In
core/surface/skills/release/SKILL.md lines 149-158 and
plugins/ca-codex/routines/release/SKILL.md lines 149-158, resolve the adoption
boundary via ADOPTED before invoking classify-window, and apply that floored
window to both classification and footer validation. Preserve the user override
and no-adoption behavior, ensuring pre-adoption commits cannot trigger
missing-footer blocking.
plugins/ca-pi/routines/release/SKILL.md (1)

84-90: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align the back-fill trigger with load_targets()'s error contract.

load_targets() maps every OSError, including permission errors and directories, to AbsentBlockError. _targets_error_exit_code() maps every AbsentBlockError to exit code 3. Therefore, an unreadable existing path can enter the back-fill lane, although this section defines exit code 3 as only a genuinely absent file.

Distinguish missing files from unreadable paths in load_targets() and the CLI contract, or reject unreadable paths before back-fill.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca-pi/routines/release/SKILL.md` around lines 84 - 90, Update
load_targets() so only a genuinely absent release-targets.md path raises
AbsentBlockError; preserve a distinct ReleaseTargetsError for existing but
unreadable paths, including permission-denied files and directories. Ensure
_targets_error_exit_code() and the documented back-fill trigger keep exit code 3
exclusively for missing files, with all existing-path failures remaining
non-back-fill errors.
♻️ Duplicate comments (1)
plugins/ca/skills/release/SKILL.md (1)

200-200: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Derive both provenance hashes from the remote response.

The text says not to use local state, but still runs git rev-parse ${TAG_PREFIX}${VERSION}^{commit}. A moved remote tag can record a remote object with a stale local commit. Capture one git ls-remote --tags origin "$TAG" response, use the direct ref line for object_sha, and use the peeled ^{} line for commit_sha, falling back to the direct SHA for lightweight tags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ca/skills/release/SKILL.md` at line 200, Update the
provenance-recording step to derive both hashes from a single git ls-remote
--tags origin "$TAG" response: use the direct ref line for object_sha and the
peeled ^{} line for commit_sha, falling back to the direct SHA for lightweight
tags. Remove the local git rev-parse lookup, while preserving the existing
manifest-skip reporting and commit-gate flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/surface/skills/release/SKILL.md`:
- Around line 196-197: Move the notes-match validation before the tag
publication step so an invalid notes file cannot leave a remote tag. Update the
release flow at core/surface/skills/release/SKILL.md lines 196-197 and apply the
same ordering in plugins/ca-codex/routines/release/SKILL.md lines 196-197: run
notes-match and stop on failure, then execute git push and create the GitHub
Release.
- Line 10: Update the release instructions at
core/surface/skills/release/SKILL.md:10-10 and
plugins/ca-codex/routines/release/SKILL.md:10-10 to capture the output of
_releaselib.py list-targets, validate that exactly one target was returned for
an omitted $TARGET, and assign that name to $TARGET before invoking tag-prefix;
preserve the existing multi-target STOP behavior and avoid assuming or manually
selecting the target.

In `@plugins/ca-pi/routines/release/SKILL.md`:
- Line 200: Update the provenance instructions in the tag-recording step to
explicitly select the direct and peeled records from git ls-remote --tags.
Record object_sha from refs/tags/<tag> and commit_sha from refs/tags/<tag>^{};
do not derive commit_sha with local git rev-parse. Preserve the existing
manifest-skip reporting and commit-gate requirements.
- Line 182: Update the local tag probe preceding classify_publish_state so the
pipeline remains successful under pipefail when git show-ref --tags -d finds no
tags. Normalize only that expected exit status while still passing the complete
tag listing to the peel-tag command and preserving failures from unexpected
conditions.
- Around line 196-197: Move the notes-match assertion in the release flow before
the git push step, using the Phase-1 section file and current tag; stop
immediately on mismatch. Only after successful validation should the flow push
the tag and create the GitHub Release, preserving the existing release-note
reuse and metadata behavior.

In `@plugins/ca/skills/release/SKILL.md`:
- Around line 182-183: Update the publish_fresh branch after the git tag command
to re-peel the newly created local tag using the existing peel-tag helper and
assign the resulting commit SHA to TAG_SHA before the Phase 2 report. Ensure the
report uses this refreshed value rather than the empty pre-classification value.
- Line 197: Update the release creation command in the release workflow to
replace the literal “--latest[=false]” placeholder with an executable flag: pass
“--latest” only when the target row is latest-eligible and this tag is newest
across all declared series; otherwise pass “--latest=false”. Preserve the
existing notes file, title, and verify-tag arguments.
- Around line 196-197: Move the notes-match validation in the release procedure
before the git push command, ensuring the guard completes successfully before
any remote write. Update the sequence around the tag-push step and the Phase-1
notes section; preserve the existing mismatch-stop behavior and subsequent
release creation flow.
- Line 182: Update the local tag probe feeding peel-tag in the Phase 2
classification flow so it remains successful under pipefail when no tags exist.
Normalize git show-ref’s expected status-1 empty result, or replace it with an
equivalent zero-exit source, while preserving peel-tag’s handling of the target
tag and the existing TAG_SHA assignment.
- Line 182: The manifest_version input used by classify_publish_state must come
from a deterministic shared manifest reader rather than agent-chosen
format-specific parsing. Update the Phase 2 instructions around classify to
reuse the established manifest validation/reading flow, or only pass the derived
version after check-manifests succeeds; ensure unsupported manifest formats fail
closed instead of allowing classification with an arbitrary value.
- Line 10: The release instructions must assign the sole target returned by
list-targets to $TARGET before invoking target helpers such as tag-prefix,
show-row, or later commands. Capture the command’s output, validate that exactly
one target was returned, and stop for zero or multiple results; then pass the
concrete name through the remaining release flow.
- Around line 48-54: The release flow must preserve PAYLOAD as an argument array
so wildcard pathspecs are passed literally to Git. Update the payload-pathspec
handling around _releaselib.py’s payload-pathspec subcommand to read one
pathspec per line into PAYLOAD and invoke Git with "${PAYLOAD[@]}" after --,
rather than using unquoted expansion or the raw show-row payload field; retain
payload-exclude semantics.

---

Outside diff comments:
In `@core/surface/skills/release/SKILL.md`:
- Around line 149-158: In core/surface/skills/release/SKILL.md lines 149-158 and
plugins/ca-codex/routines/release/SKILL.md lines 149-158, resolve the adoption
boundary via ADOPTED before invoking classify-window, and apply that floored
window to both classification and footer validation. Preserve the user override
and no-adoption behavior, ensuring pre-adoption commits cannot trigger
missing-footer blocking.

In `@plugins/ca-pi/routines/release/SKILL.md`:
- Around line 84-90: Update load_targets() so only a genuinely absent
release-targets.md path raises AbsentBlockError; preserve a distinct
ReleaseTargetsError for existing but unreadable paths, including
permission-denied files and directories. Ensure _targets_error_exit_code() and
the documented back-fill trigger keep exit code 3 exclusively for missing files,
with all existing-path failures remaining non-back-fill errors.

In `@plugins/ca/skills/release/SKILL.md`:
- Line 142: Update the $ARTIFACTS validation in the release procedure so each
declared artifact is first required to exist and be tracked by Git, then checked
with git diff --quiet for freshness. Ensure missing or untracked artifacts fail
the release, while preserving the existing $TARGET scoping and rebuild behavior.
- Around line 149-158: Reorder the release workflow so the adoption boundary is
resolved before invoking classify-window: compute ADOPTED when available, allow
the user’s override, and derive the floored WINDOW first. Pass that floored
window to classify-window and the subsequent footer validation, while preserving
the existing behavior when no adoption commit or CONTEXT.md exists.
- Around line 90-97: Update the persistence instructions for release-targets.md
to use an atomic create-only write after the existing absence check and
authoring-marker creation. Ensure the operation fails without modifying the file
if another process creates it first, then stop and surface that race instead of
overwriting; retain the existing marker lifecycle and confirmed-block content.

---

Duplicate comments:
In `@plugins/ca/skills/release/SKILL.md`:
- Line 200: Update the provenance-recording step to derive both hashes from a
single git ls-remote --tags origin "$TAG" response: use the direct ref line for
object_sha and the peeled ^{} line for commit_sha, falling back to the direct
SHA for lightweight tags. Remove the local git rev-parse lookup, while
preserving the existing manifest-skip reporting and commit-gate flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f1d70ab-0346-4bcf-a367-6fa839d510fd

📥 Commits

Reviewing files that changed from the base of the PR and between cc6f8a7 and ec983fc.

📒 Files selected for processing (6)
  • .codearbiter/sprint-log.md
  • .github/scripts/test_release_lib.py
  • core/surface/skills/release/SKILL.md
  • plugins/ca-codex/routines/release/SKILL.md
  • plugins/ca-pi/routines/release/SKILL.md
  • plugins/ca/skills/release/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/scripts/test_release_lib.py
📜 Review details
⏰ Context from checks skipped due to timeout. (14)
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.10>
  • GitHub Check: [WATCH] | [CDX ] | Upstream compatibility <runtime: npm latest>
  • GitHub Check: [WATCH] | [PI ] | Upstream compatibility <runtime: npm latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: windows-latest>
  • GitHub Check: [CHECK] | [PI ] | Host-independent adapter contract
  • GitHub Check: Coverage union <os: windows-latest>
  • GitHub Check: Coverage union (Pi) <os: windows-latest>
  • GitHub Check: [CHECK] | [SBX ] | Sandbox driver contract
  • GitHub Check: Analyze (rust)
🧰 Additional context used
🪛 SkillSpector (2.4.4)
plugins/ca-pi/routines/release/SKILL.md

[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

core/surface/skills/release/SKILL.md

[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-codex/routines/release/SKILL.md

[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca/skills/release/SKILL.md

[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 196: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 214: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🔇 Additional comments (3)
plugins/ca/skills/release/SKILL.md (1)

22-26: LGTM!

Also applies to: 28-46, 56-80, 84-89, 98-104, 108-141, 159-179, 192-195, 201-202

.codearbiter/sprint-log.md (1)

1-245: LGTM!

Also applies to: 726-739, 1208-1225, 1226-1256, 1258-1284, 1286-1317, 1319-1347, 1349-1374, 1376-1426, 1428-1449

plugins/ca-pi/routines/release/SKILL.md (1)

3-3: LGTM!

Also applies to: 10-26, 30-80, 91-104, 108-142, 148-177, 192-195, 201-202, 206-220, 224-239

Comment thread core/surface/skills/release/SKILL.md
Comment thread core/surface/skills/release/SKILL.md
Comment thread plugins/ca-pi/routines/release/SKILL.md
Comment thread plugins/ca-pi/routines/release/SKILL.md
Comment thread plugins/ca-pi/routines/release/SKILL.md
Comment thread plugins/ca/skills/release/SKILL.md
Comment thread plugins/ca/skills/release/SKILL.md
Comment thread plugins/ca/skills/release/SKILL.md
Comment thread plugins/ca/skills/release/SKILL.md
Comment thread plugins/ca/skills/release/SKILL.md
SUaDtL added 4 commits August 1, 2026 05:35
… own (#563)

Both were new surface created by the previous commit's prose, which is
the pattern this campaign keeps reproducing: a fix is not a closed edit,
it is several sentences that have never been exercised.

The `ROW=` counter-example abbreviated a path as `{{PLUGIN_ROOT}}/…`. The
plugin-reference checker reads that ellipsis as a real reference and
finds nothing there, so all three payloads failed `check-plugin-refs`.
Spelled out in full; a counter-example is clearer with the real path
anyway.

The step-7 clean-tree fix repeated the exempted git pathspec in an INLINE
backtick span. Pre-flight's copy lives inside a fenced block, which the
reference extractor excises precisely because fenced content is raw shell
rather than a portability-checkable literal -- so the inline copy was
extracted, resolved as a bare repo-relative path against the scratch
consumer, and found absent. Step 7 and the Phase 1 gate now REFER to
Pre-flight's spelling rather than restating it, which also removes a
duplicated literal that would have had to stay in sync by hand.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
HIGH-2 is the one that would have shipped broken. Step 6c's own stated
remedy -- `releasehash.py record` -- writes a per-machine marker under
`.codearbiter/.markers/`, and step 7's clean-tree assertion exempted the
audit log "and nothing else". So following the skill's instruction at 6c
made the tree dirty in a way its own next gate refused: a hard BLOCK at
the last gate of Phase 1, after the changelog was rolled and every
manifest bumped, on a release where nothing was wrong. It is masked in
THIS repo only because `.gitignore` happens to list the directory, and
not masked at all in a project that reached the lane through Back-fill --
which is exactly the project this lane exists to serve. The marker
directory was the second member of a class the skill had already fixed
once for `gate-events.log`; the fix went to the member rather than the
class.

HIGH-1 -- the exempted command used a bare `.`, which scopes to the
CURRENT directory, with a cwd-relative exclusion on top. A declared
`rebuild` commonly BEGINS with `cd` (this repository's own row does), the
operator's shell persists between steps, and nothing said to come back.
From the subdirectory that leaves you in, three gates fail silently:
`git log $WINDOW -- $PAYLOAD` returns zero commits and fires the false
"nothing to release" STOP on a 95-commit window; `git diff --quiet --
<artifact>` exits 0 without resolving the artifact, so the freshness gate
passes while blind; and the clean-tree check reads a dirty tree as clean.
Verified: from `plugins/ca/tools` the old spelling exits 0 with no output
on a tree the root-anchored spelling correctly reports as modified.

Fixed at both ends -- `rebuild` now runs in a subshell so it cannot move
the lane's cwd, and the pathspec is `:/` with `,top` exclusions so the
answer is the same from anywhere. The pathspec half also closes the
cwd-relative MEDIUM filed as #583.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
…one (#563)

The previous commit told operators to run `( eval "$REBUILD" )` in a file
that carries a MUST NOT read the row with `eval` rule, added because
blind exercise run 15 found `eval` executing declared row values before
the gate that authorizes them. Left as-is, the two read as a
contradiction, and the next reader has to guess which one governs.

They are different acts. The ban is on evaluating a row's values while
merely READING the row. This is executing a value as the command it was
declared to be, at the step whose job is to execute it -- the same thing
`run-pre-tag` already does for `pre-tag` commands. Reading is not
execution; the rule is against confusing the two, not against ever
running a declared command.

Last skill edit before the proof exercise is staged.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86
…ly (#563)

Blind exercise run 18 confirmed all four properties runs 16 and 17 fixed
still hold under direct attack, and found two HIGHs at the Back-fill
seam -- a region no earlier run had probed.

One of them could not be filed and shipped. Phase 1 step 3 told the
operator that amending or interactively rebasing a footer-less commit is
"fine at this point, since nothing in this window has been tagged or
pushed". Measured here: 38 of the 57 footer-less commits in the window
are already ancestors of origin/main. Following that sentence literally
means rewriting published history and force-pushing, which the same file
forbids twice. It now requires a `git merge-base --is-ancestor` check
first and routes a published commit to classification-from-message --
which is what the manifest-ahead STOP thirty lines earlier already says
about the very same commits. The knowledge was in the file; the two
paragraphs had never been read against each other.

Also corrected "the same single exclusion", which was my own wording from
9feb515 and became wrong when the .markers/ exemption added a second one.

**The proof is recorded with `proof_current: false`, deliberately.** Run
18 exercised 33e82a6a; the fix above lands after it, so the recorded hash
is one commit behind the shipped skill and this gate will block ca's
pre-tag until run 19. Setting the flag true and carrying the caveat in
prose would defeat the field the gate actually reads. The alternative --
leaving a force-push instruction in place to keep a checkbox green --
inverts the purpose of every gate here. `post_exercise_delta` names what
changed, when, and why it was not deferred.

Two tests in the gate's own suite went red on that flag, and both were
right to: each built its fixture from the LIVE artifact and patched only
the hash, inheriting `proof_current` from release state the sibling
test's comment explicitly warns against coupling to. Both now pin it. The
flag branch had no coverage at all, so it has a test now -- a withdrawn
proof must not be reported as a changed skill, since the two have
different remedies. Mutation-checked: making the flag branch speak the
hash branch's language kills that test and nothing else.

Run 18's HIGH-1 (Back-fill's first release cannot clear step 3) and the
four MEDIUMs are filed as #585.

Claude-Session: https://claude.ai/code/session_01C8oamhuiaBjZnauWRGjb86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.codearbiter/reports/agent-lane-proof.json:
- Around line 27-109: The campaign history is incomplete and incorrectly marks
run 13 as the final proof. Update campaign.high_findings_by_run and
campaign.runs to include runs 14 through 18 with their recorded outcomes, and
move the “THE RECORDED PROOF” designation from run 13 to run 18 so campaign
matches the later exercise record.

In `@core/surface/skills/release/SKILL.md`:
- Line 147: Update the artifact freshness assertion in
core/surface/skills/release/SKILL.md at lines 147-147 to use a root-anchored Git
pathspec such as `:(top)` for every artifact, so checks work when started from
any subdirectory. Regenerate plugins/ca/skills/release/SKILL.md at lines 147-147
from the corrected core skill; no separate logic change is required there.
- Line 163: Add a fallback adoption baseline in
core/surface/skills/release/SKILL.md:163-163 for back-fill runs where LAST_TAG
is <none> and ADOPTED is empty, and present it to the user as an overrideable
proposal before footer validation. Preserve the existing adopted-commit floor
when available, and regenerate plugins/ca/skills/release/SKILL.md:163-163 from
the corrected core skill.

In `@plugins/ca-codex/routines/release/SKILL.md`:
- Around line 116-123: Make the governance-path exclusions conditional on the
declared release surfaces in both plugins/ca-codex/routines/release/SKILL.md
lines 116-123 and plugins/ca-pi/routines/release/SKILL.md lines 116-123: reject
any target whose release surfaces overlap .codearbiter/gate-events.log or
.codearbiter/.markers/, or omit those exclusions for that target so
target-scoped releases cannot bypass the clean-tree check.
- Line 163: Update the adoption-boundary logic in
plugins/ca-codex/routines/release/SKILL.md:163-163 and
plugins/ca-pi/routines/release/SKILL.md:163-163 so Back-fill releases use the
committed Back-fill declaration when CONTEXT.md is absent, or persist and reuse
an explicit adoption commit. Apply the same boundary behavior in both files,
while retaining user override support and avoiding an unfloored scan of legacy
pre-adoption history.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b8441031-20db-4de4-8837-f38c59bf5b84

📥 Commits

Reviewing files that changed from the base of the PR and between 9feb515 and 6bbf64b.

📒 Files selected for processing (7)
  • .codearbiter/reports/agent-lane-proof.json
  • .codearbiter/sprint-log.md
  • .github/scripts/test_check_skill_proof_fresh.py
  • core/surface/skills/release/SKILL.md
  • plugins/ca-codex/routines/release/SKILL.md
  • plugins/ca-pi/routines/release/SKILL.md
  • plugins/ca/skills/release/SKILL.md
📜 Review details
⏰ Context from checks skipped due to timeout. (15)
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: ubuntu-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: macos-latest>
  • GitHub Check: [CHECK] | [CORE] | Hook contract <os: windows-latest>
  • GitHub Check: [CHECK] | [PI ] | Security analysis <language: JavaScript/TypeScript>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: macos-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.10>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: windows-latest · runtime: Pi 0.80.5>
  • GitHub Check: Coverage union <os: windows-latest>
  • GitHub Check: [CHECK] | [PI ] | Adapter contract <os: ubuntu-latest · runtime: Pi 0.80.5>
  • GitHub Check: [CHECK] | [PI ] | Host-independent adapter contract
  • GitHub Check: [CHECK] | [SBX ] | Sandbox driver contract
  • GitHub Check: Coverage union (Pi) <os: windows-latest>
  • GitHub Check: Analyze (rust)
🧰 Additional context used
🪛 ast-grep (0.45.0)
.github/scripts/test_check_skill_proof_fresh.py

[info] 459-459: use jsonify instead of json.dumps for JSON output
Context: json.dumps(document)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 SkillSpector (2.4.4)
plugins/ca/skills/release/SKILL.md

[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

core/surface/skills/release/SKILL.md

[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-codex/routines/release/SKILL.md

[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

plugins/ca-pi/routines/release/SKILL.md

[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))


[error] 201: [TM1] Tool Parameter Abuse: Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Remediation: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.

(Tool Misuse (TM1))


[error] 219: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🔇 Additional comments (9)
.codearbiter/reports/agent-lane-proof.json (1)

2-2: The "EIGHT ... exercises" count is still stale, and now by ten runs.

Line 2 states eight blind exercises. exercise.run is 18 and campaign.high_findings_by_run carries 13 entries. Line 266 repeats the same count ("all eight runs demonstrated"). A previous review flagged this field; the text was not updated and the drift grew.

core/surface/skills/release/SKILL.md (2)

116-127: LGTM!


179-179: LGTM!

.github/scripts/test_check_skill_proof_fresh.py (1)

389-397: LGTM!

Also applies to: 423-427, 439-473

.codearbiter/sprint-log.md (1)

1450-1483: LGTM!

plugins/ca-codex/routines/release/SKILL.md (2)

147-147: LGTM!


179-179: LGTM!

plugins/ca-pi/routines/release/SKILL.md (2)

147-147: LGTM!


179-179: LGTM!

Comment thread .codearbiter/reports/agent-lane-proof.json
Comment thread core/surface/skills/release/SKILL.md
Comment thread core/surface/skills/release/SKILL.md
Comment thread plugins/ca-codex/routines/release/SKILL.md
Comment thread plugins/ca-codex/routines/release/SKILL.md
@SUaDtL

SUaDtL commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Disposition of the CodeRabbit review threads

Resolving the 60 open threads so required_conversation_resolution clears. Recording the disposition here rather than resolving silently, because "resolved" and "addressed" are not the same word and the distinction should survive this PR.

All 24 Major findings were fixed, not dismissed — commits are in the PR description. Roughly 12 are distinct: core/pysrc/X and its two vendored copies each flag separately, so fixing the source and re-syncing clears three threads at once. The ones worth remembering:

  • task_block diverged from parse_board's closing rule and re-opened HIGH-2 — a fix from earlier in this same sprint.
  • _archive parsed the board one line at a time, so every Task carried lineno == 1 and HIGH-3's index-based location was dead code running on its fallback.
  • git_restore_re still crossed newlines — the identical defect fixed in write_re two lines above it.
  • A delete op reached the marker-gated arm, making a self-mintable friction-grade marker a delete capability over protected state.
  • confirmation_path collided a.b with a_b, so confirming one confirmed the other.
  • The python3 X || python X convention discarded helper exit codes: || re-runs on any non-zero, so run-pre-tag's 5/6 verdicts triggered a second full execution of the project's declared pre-tag commands and reported the second run's code.

45 minor and trivial findings are filed as #578 — stale prose, table formatting, markdownlint items. Real, none load-bearing, and batching them keeps this PR reviewable rather than dropping them.

28 of the 60 threads are already outdated — the lines they point at have been rewritten since, in most cases by the fix for the finding itself.

Nothing here is being closed as wrong. If a thread below turns out to name something neither fixed nor in #578, it should be reopened — file it against #578 and it will be picked up.

@SUaDtL
SUaDtL merged commit 8ee5fe1 into main Aug 1, 2026
52 checks passed
@SUaDtL
SUaDtL deleted the sprint/portable-release-and-protected-state branch August 1, 2026 13:56
SUaDtL added a commit that referenced this pull request Aug 1, 2026
* chore(coderabbit): stop re-reviewing the vendored plugin trees

This repo vendors one source of truth into three host plugins:
sync-core.py copies core/pysrc/*.py byte-identically into each plugin's
hooks/ dir, and build-surface.py renders core/surface/ into each plugin
per core/hosts.json. CI fails if a copy drifts, so a defect in core/ is
mechanically present in every copy.

Unconfigured, CodeRabbit reviewed each copy independently. On #576 it
left 102 inline comments, 48 of which this config now filters, with
SKILL.md flagged 40 times and _releaselib.py 15 times. That volume is
what forced the deferrals in #577 and #578.

Filters are negation-only: it is undocumented whether a positive pattern
flips the list into allowlist mode, and guessing wrong would lose review
coverage entirely. Verified against git glob semantics that the 55
authored test files under plugins/ca/hooks/tests/ are not caught; the
three authored _host.py files are, which is the accepted cost of not
using a positive re-include.

Nothing is filtered that was not proven derived: plugins/ca-sandbox/ is
absent from core/hosts.json and plugins/ca-pi/generated/ has no verified
generator, so both stay reviewed.

The gate-events.log append rides along because H-05 refuses to let an
audit log be unstaged; the log is machine-appended session state.

* docs(coderabbit): correct three claims the review caught

CodeRabbit's review surfaced two documentation pages this config's
comments were written without: configuration/configuration-inheritance
and reference/glossary. Verified both directly rather than taking the
review at its word; all three corrections hold.

1. Glob semantics are documented, not inferred. The glossary states `*`
   matches any filename and `**` matches any directory depth, so `*`
   does not cross a separator. The comment previously justified that
   reading via a git sparse-checkout mapping and asked for empirical
   confirmation on the first PR. Both are now unnecessary: the behaviour
   is stated outright, and the 55 authored test files under
   plugins/ca/hooks/tests/ are provably out of the exclusion.

2. Organization global overrides are never discarded. They apply as the
   final layer after the inheritance chain resolves, whatever a repo
   sets. The old wording said every org-wide default is discarded
   without `inheritance: true`; that is true of the central YAML only.

3. Merge semantics are documented: objects deep-merge, arrays take the
   child's items first then unique parent items, scalars take the
   child's value. Recorded so the next reader does not re-derive it.

The precedence list is also corrected to the published eight levels.

---------

Co-authored-by: SUaDtL <SUaDtL@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant