feat(release): a portable release fixture and the protected-state machinery it needs (#563, #564) - #576
Conversation
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
…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
There was a problem hiding this comment.
🧹 Nitpick comments (2)
plugins/ca/hooks/tests/test_pre_write.py (1)
328-347: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd delete-arm regression tests for
ca-piandca-codexNeither 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 winStrengthen the block-move assertion to check the moved content, not just its absence.
test_indented_continuation_prose_does_not_split_the_blockasserts the continuation prose andBoundariesdisappear fromopen-tasks.md, and thatBoundariesreappears indone-tasks.md. It never asserts that the continuation prose text itself lands indone-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 thatdone-tasks.mdcontains 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
📒 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.pycore/pysrc/_bashguardlib.pycore/pysrc/_releaselib.pycore/pysrc/_taskboardlib.pycore/pysrc/pre-write.pycore/pysrc/releasehash.pycore/pysrc/taskwrite.pyplugins/ca-codex/hooks/_bashguardlib.pyplugins/ca-codex/hooks/_releaselib.pyplugins/ca-codex/hooks/_taskboardlib.pyplugins/ca-codex/hooks/pre-write.pyplugins/ca-codex/hooks/releasehash.pyplugins/ca-codex/hooks/taskwrite.pyplugins/ca-pi/hooks/_bashguardlib.pyplugins/ca-pi/hooks/_releaselib.pyplugins/ca-pi/hooks/_taskboardlib.pyplugins/ca-pi/hooks/pre-write.pyplugins/ca-pi/hooks/releasehash.pyplugins/ca-pi/hooks/taskwrite.pyplugins/ca/hooks/_bashguardlib.pyplugins/ca/hooks/_releaselib.pyplugins/ca/hooks/_taskboardlib.pyplugins/ca/hooks/pre-write.pyplugins/ca/hooks/releasehash.pyplugins/ca/hooks/taskwrite.pyplugins/ca/hooks/tests/test_pre_write.pyplugins/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 QualityConfirm 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_clifor assertingassertIn('"--desc"', text)againsttaskwrite.py's source text rather than invoking the CLI, which cannot detect a mechanism nobody can invoke. This range (rationale sub-bullet tests, including "taskwriteCLI 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 exercisestaskwrite.pyviasubprocess, matching theArchiveVerbTest._runpattern, 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
There was a problem hiding this comment.
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.
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 winAlign the single-target template with the Back-fill contract.
The release Back-fill lane emits
latest-eligible: truefor 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: trueto 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 liftMake 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
📒 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.ymlcore/pysrc/_releaselib.pycore/surface/skills/context-creation/SKILL.mdcore/surface/skills/release/SKILL.mdplugins/ca-codex/hooks/_releaselib.pyplugins/ca-codex/routines/context-creation/SKILL.mdplugins/ca-codex/routines/release/SKILL.mdplugins/ca-pi/hooks/_releaselib.pyplugins/ca-pi/routines/context-creation/SKILL.mdplugins/ca-pi/routines/release/SKILL.mdplugins/ca/hooks/_releaselib.pyplugins/ca/skills/context-creation/SKILL.mdplugins/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!
…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
There was a problem hiding this comment.
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.
Actionable comments posted: 4
🧹 Nitpick comments (2)
core/pysrc/_releaselib.py (1)
1677-1684: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract a shared helper for the repeated
--flag VALUEextraction.This
--fieldblock duplicates the same three-line pop-a-flag-and-value pattern already used for--targets-fileat 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 winExtract a shared helper for the repeated
--flag VALUEextraction.Same duplication as in
core/pysrc/_releaselib.py: this--fieldblock repeats the flag/value extraction already used for--targets-fileat 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
📒 Files selected for processing (9)
.github/scripts/test_release_lib.pycore/pysrc/_releaselib.pycore/surface/skills/release/SKILL.mdplugins/ca-codex/hooks/_releaselib.pyplugins/ca-codex/routines/release/SKILL.mdplugins/ca-pi/hooks/_releaselib.pyplugins/ca-pi/routines/release/SKILL.mdplugins/ca/hooks/_releaselib.pyplugins/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: QuotedNAME=valueemission correctly closes the prior unquoted-evalhazard.The new
shlex.quote(_flatten(row.get(key)))output stops declared field values (for example arebuildcommand containing&&) from being interpreted as shell syntax when a caller doeseval "$(... show-row ...)". The--field NAMEraw-value path gives callers a non-evalalternative for command substitution. This matches the fix described in the commit message.
1732-1742: 🗄️ Data Integrity & IntegrationKeep the
generatemapping._KEY_FIELDmaps the grammar key"generate"to the row field"generate", so thefieldsentry is correct. Nogeneration-commandkey is declared.> Likely an incorrect or invalid review comment.plugins/ca/hooks/_releaselib.py (3)
104-104: LGTM!
1708-1763: QuotedNAME=valueemission correctly closes the prior unquoted-evalhazard.Same fix as in
core/pysrc/_releaselib.py:shlex.quote(_flatten(row.get(key)))stops declared field values from being interpreted as shell syntax undereval "$(... show-row ...)", and--field NAMEgives a non-evalalternative.
1732-1742: 🗄️ Data Integrity & IntegrationVerify that the
generatekey matches the declared row field.Same concern as the identical block in
core/pysrc/_releaselib.py: thefieldslist mapsGENERATEto row key"generate", but the field-mapping layer summary describes the field asgeneration-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 & AvailabilityCall helpers with quoted arguments.
$ROWis 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 & AvailabilityAllow an empty local tag set under
pipefail.
git show-ref --tags -dreturns status 1 when the repository has no tags. Underpipefail, the pipeline still fails even whenpeel-tagcorrectly reports that the target tag is absent. The first release therefore stops before classification.Allow status 1 from
git show-refbefore the pipe, while preserving other failures.This repeats the unresolved previous finding.
179-179: 🗄️ Data Integrity & IntegrationUse 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_versionpath, or pass the derived version only aftercheck-manifestssucceeds. Unsupported formats must fail closed.This repeats the unresolved previous finding.
193-197: 🎯 Functional CorrectnessValidate 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. DefineTAG="${TAG_PREFIX}${VERSION}", runnotes-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 CorrectnessReplace the non-executable latest flag.
--latest[=false]is a notation placeholder, not a concretegh release createargument. Pass--latestonly for the eligible newest target. Pass--latest=falsefor every other target.This repeats the unresolved previous finding.
156-157: LGTM!
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
There was a problem hiding this comment.
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.
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 liftDo not block a normal tagless first release.
core/surface/skills/release/SKILL.md#L123-L129: Do not treat a manifest as drift whenLAST_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 liftReject unreachable tags before deriving the release baseline.
core/surface/skills/release/SKILL.md#L121-L121: Filter target tags by ancestry fromHEAD, 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 winThe clean-tree exemption must respect the declared release surface.
core/surface/skills/release/SKILL.md#L113-L119: Re-include.codearbiter/gate-events.logwhen 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 winQuote release pathspecs individually. Unquoted
$PAYLOADpermits word splitting and glob expansion, which can change the release window. Preserve eachpayload-pathspecresult as a separate argument and pass it as"${PAYLOAD_ARGS[@]}". Iterate over$ARTIFACTSand 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
📒 Files selected for processing (6)
.github/scripts/test_consumer_smoke.py.github/scripts/test_release_lib.pycore/surface/skills/release/SKILL.mdplugins/ca-codex/routines/release/SKILL.mdplugins/ca-pi/routines/release/SKILL.mdplugins/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!
…#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
There was a problem hiding this comment.
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.
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 winReject missing or untracked artifacts after rebuild.
git diff --quiet -- <artifact>checks tracked changes only. If$REBUILDcreates 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 liftApply the adoption boundary before
classify-window.Step 2 runs
classify-windowover$WINDOWbefore 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 noCONTEXT.md, leaving$ADOPTEDempty 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 winMake 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.mdafter the absence check and before the write. Use an atomic create-only operation, such asO_EXCLornoclobber, 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 winCompute the adoption floor before classifying the window.
Both skills invoke
classify-windowon 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$ADOPTEDfirst 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 winAlign the back-fill trigger with
load_targets()'s error contract.
load_targets()maps everyOSError, including permission errors and directories, toAbsentBlockError._targets_error_exit_code()maps everyAbsentBlockErrorto exit code3. Therefore, an unreadable existing path can enter the back-fill lane, although this section defines exit code3as 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 liftDerive 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 onegit ls-remote --tags origin "$TAG"response, use the direct ref line forobject_sha, and use the peeled^{}line forcommit_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
📒 Files selected for processing (6)
.codearbiter/sprint-log.md.github/scripts/test_release_lib.pycore/surface/skills/release/SKILL.mdplugins/ca-codex/routines/release/SKILL.mdplugins/ca-pi/routines/release/SKILL.mdplugins/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
… 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
There was a problem hiding this comment.
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.
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
📒 Files selected for processing (7)
.codearbiter/reports/agent-lane-proof.json.codearbiter/sprint-log.md.github/scripts/test_check_skill_proof_fresh.pycore/surface/skills/release/SKILL.mdplugins/ca-codex/routines/release/SKILL.mdplugins/ca-pi/routines/release/SKILL.mdplugins/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.runis 18 andcampaign.high_findings_by_runcarries 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!
Disposition of the CodeRabbit review threadsResolving the 60 open threads so All 24 Major findings were fixed, not dismissed — commits are in the PR description. Roughly 12 are distinct:
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 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. |
* 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>
Closes #563. Closes #564.
Two workstreams, 95 planned tasks, all ACCEPTED. 50 commits.
A —
/ca:releasebecomes a portable fixtureThe 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.pycarries no fact about this repository, enforced by a denylist test.run-pre-tagruns 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.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-greaterandcheck-manifestsreturn distinct codes for the two.B — a generic protected-state registry
_protectedstatelib.pyis 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.pygains anarchiveverb and/ca:standupa per-item archival sweep — one confirmation per item, one helper call per item,done-tasks.mdwritten beforeopen-tasks.mdso 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./ca:taskinvocation naming an enrolled file blocked — and fordone/archiveon an ID-less task the title is the target, so no reword existed and no sanctioned route remained.archive_transformmoved the top line only, orphaningDesc/Boundariesonto the next task — silently rewriting a security scope.parse_boarditself."", and the write replaces the file wholesale — any transientOSErrorwiped every historical record.py— the Windows Python launcher — and PowerShell entirely, so the leg was bypassable on this repo's primary dev host.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_*.pymodule, the site suite (47 files / 496 tests), andbuild-surface --check(claude, codex, pi in sync). The one local failure is a pre-existingca-piflake 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_contractall 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/Xand its two vendored copies each flag separately. Highlights:task_blockdiverged fromparse_board's closing rule, re-opening HIGH-2 — indented continuation prose orphaned sub-bullets onto the following task._archiveparsed the board one line at a time, so everyTaskcarriedlineno == 1and HIGH-3's index-based location was dead code running on its fallback.git_restore_restill crossed newlines — the same defect fixed inwrite_retwo lines above it.deleteop 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_pathcollideda.bwitha_b, so confirming one confirmed the other.python3 X || python Xconvention discarded helper exit codes:||re-runs on any non-zero, sorun-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:
show-rowandshow-row --field.$PAYLOADis "payload minus payload-exclude", whichgit log --cannot express; addedpayload-pathspec.show-row's first cut emitted unquoted values and the skill documentedeval-ing them — which executed declared shell (rebuild: cd x && npm run build→REBUILD=cdplus the commandx) while still exiting 0. Values areshlex.quoted;--fieldneeds no eval.MAJOR.MINOR.PATCHwas a literal in 7 tag/push/release commands and never assigned;$VERSIONnow is.gate-events.logon 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:
"$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.git status --porcelainwhile calling it "the same state Pre-flight required" — which Pre-flight's own HIGH-rated paragraph proves cannot pass there.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.gitignoreline and not masked for a Back-fill consumer, which is exactly who the lane serves.., and a declaredrebuildcommonly begins withcd. 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.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.pyis red, and that is a decision rather than an oversight. Run 18 exercised the skill at33e82a6aand 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_currentisfalse,post_exercise_deltain the artifact names exactly what changed after the exercise and why, and the gate blocks the next/ca:releaseforcauntil 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 declaredpre-tagrow, 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-pibridge 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).