Skip to content

feat(pr-pipeline): tidy a small single-area change inside resolve-issue before its one push - #10224

Merged
melodic-automation-lanes[bot] merged 9 commits into
mainfrom
work-resolve-issue/issue-8485-40284731507-1
Oct 28, 2026
Merged

melodic-automation-lanes[bot] merged 9 commits into
mainfrom
work-resolve-issue/issue-8485-40284731507-1

Conversation

@melodic-automation-lanes

@melodic-automation-lanes melodic-automation-lanes Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Refs: #8485

Summary

Opened by the work-resolve-issue lane. The run's own summary:

resolve-issue now tidies its own change in the run, before its last check run and before its review, so a lane PR reaches review already tidied with no extra push, review run or token mint (Phase 1 of #8485, owner decisions of 2026-10-19 and 2026-10-26). A new pipeline field tidy (entry, passes, turn-share, cutoffs) is validated by the schema, carried by resolve-config and staged by collect-base-activity, which allows exactly the named quality skills and their scripts and names the cutoffs (10 files, 300 lines, one area, no shared path) and a 25% turn budget in the preamble. A new diff-scoped skill, /code-tidying:tidy-diff, takes a file-and-line list instead of a base ref, so it works on the lane's detached head, and the work skill's CI mode measures the change and calls it only within the cutoffs.

Remaining work

  • Phase 2: a change over the cutoffs gets separate per-area tidy runs after the PR opens, with the AI review waiting until they finish; its thresholds come from the lane baseline
  • Retune the Phase 1 cutoffs and turn share in pr-pipeline.yaml's resolve-issue tidy block from the baseline after the first week

Not verified

  • The node tests touched (collect-base-activity.test.mjs, resolve.test.mjs, live-config.test.mjs) and the shell test allowed-tools-pairing.test.sh were not run: this run has no test runner wrapper, so they are left to the PR's CI
  • plugins/code-tidying/skills/tidy-diff/scripts/change-shape.sh was written without the executable bit; the issue patch row's script-exec-bit sets it when apply-issue-patch commits, and allowed-tools-pairing.test.sh checks it on the PR
  • The skill eval cases added (tidy-diff 1-4, work case 16) were checked for quality but not executed against a model
  • The live lane behavior is unverified until a resolve-issue run uses it: that the CLI loads the extra plugin dirs, resolves the nested Skill calls, and that the docs-hygiene write skills stay within the allowed skills
  • Baseline metrics (rounds per PR, re-verifications per PR, minutes per merged PR) before and after: a person takes them; the issue lists them as checks a person runs
  • The PR changes docs/conventions/pr-pipeline.yaml and .github/actions/resolve-config/resolve.mjs, which are on ci-status's hold-path floor, so it waits for a trusted person's approval of the head
  • This change widens what the issue lane may invoke (owner decision (a), 2026-10-19, limited to these quality skills); the security review lane should judge the widening
  • Ten untracked dotfiles (.bashrc, .gitconfig, .idea, .mcp.json and others) show in git status inside the Bash sandbox but do not exist outside it; they are sandbox placeholders this run did not create and are not part of the change

Fix

  • docs/conventions/pr-pipeline/pr-pipeline.schema.json: new tidy leaf property (entry, passes, turn-share 1-50, cutoffs with max-files, max-lines, max-areas, shared-paths); allowed only on a read skill with applied-by.patch and no prepare
  • .github/actions/resolve-config/resolve.mjs: carries tidy onto the selected activity
  • docs/conventions/pr-pipeline.yaml: resolve-issue sets tidy: entry code-tidying:tidy-diff, passes docs-hygiene:write-for-agents, docs-hygiene:write-for-humans, ai-slop:audit, turn-share 25, cutoffs 10 files / 300 lines / 1 area and the shared paths .github/, .claude/, .claude-plugin/, scripts/, lib/,
  • .github/actions/collect-base-activity/action.yml: new stage_plugin and skill_script_rules helpers (the ai-slop:audit rules and the web-access research-plugin staging now use them, same rules and order); a tidy gate that fails red outside an issue lane's no-prepare patch skill on run-claude-cli; a ti
  • .github/actions/collect-base-activity/collect-base-activity.test.mjs: tests for tidy staging, its absence, its six refusal cases and its refusal on claude-code-action
  • .github/actions/resolve-config/resolve.test.mjs: tidy added to the edit-runner carry/refuse loop; new test that tidy with a prepare mode fails the schema
  • .github/actions/resolve-config/live-config.test.mjs: pins the live resolve-issue tidy config and that no other activity tidies
  • plugins/code-tidying/skills/tidy-diff/SKILL.md: new skill; simplify pass and proven class-A comment deletions on code lines, docs-hygiene write rules and ai-slop fix on markdown lines, scoped by a file-and-line list, with an optional --turns budget
  • plugins/code-tidying/skills/tidy-diff/scripts/change-shape.sh: skill-local exec wrapper for the plugin's change-shape.py token proof
  • plugins/code-tidying/skills/tidy-diff/evals/evals.json: four eval cases (listed lines only, markdown-only passes, budget stop, dropped rows)
  • plugins/code-tidying/scripts/allowed-tools-pairing.test.sh: covers tidy-diff's grant
  • plugins/code-tidying/README.md and plugins/code-tidying/.claude-plugin/plugin.json: list tidy-diff (description kept under 500 characters)
  • docs/catalog.md and docs/skill-cheat-sheet.md: regenerated rows for the new skill and description
  • plugins/work-items/skills/work/SKILL.md: CI mode step 4 measures the change after the checks and, within the runner's tidy cutoffs, writes a lines file and invokes the tidy entry with a bounded --turns, keeping a turn reserve, then reruns the checks before the review; records tidy in steps and a ski
  • plugins/work-items/skills/work/evals/evals.json: eval case 16 for tidy within and over the cutoffs
  • docs/conventions/pr-pipeline/README.md and pr-run-activity.md: document the tidy field and its launcher staging
  • .changes/pr-pipeline, .changes/code-tidying, .changes/work-items: one minor fragment each

Verification

The runner ran each check from the base copy against a21c5ac:

  • scripts/check-changelog-fragments.sh --check: passed

The run reports:

  • /home/runner/work/claude-code-plugins/claude-code-plugins/.lane/checks/bin/check-changelog-fragments: all 5 fragments valid
  • /home/runner/work/claude-code-plugins/claude-code-plugins/.lane/checks/bin/check-affected: 10 passed, 6 skipped over 22 changed files (first run failed on the code-tidying description over 500 characters, the second on a stale skill cheat sheet; both fixed)
  • check-evals-quality on plugins/code-tidying/skills/tidy-diff/evals/evals.json and plugins/work-items/skills/work/evals/evals.json: PASS, 0 warnings
  • read https: //code.claude.com/docs/en/skills: a skill's injected !command that a deny rule matches, or that is not allowed outside auto mode, aborts the whole skill invocation; so the tidy passes are only skills with no pre-compute line or one whose script the lane allows (docs-hygiene:audit-noise
  • fresh-context review subagent over the whole diff: no bash or test bugs found; five findings fixed (turn reserve before tidy, prove-then-edit comment deletions, schema gate narrowed to read+patch+no prepare, one-line hunk headers, skip reason into not_done)
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/40284731507

Left out: the items under Not verified.

Related

#8485

Cost decision: #10224 (comment)

Cost decision: #10224 (comment)

Cost decision: #10224 (comment)

Lane-Activity: work-resolve-issue/resolve-issue

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

claude-security-review: 1 inline finding(s) on a21c5aca8a93f871130b4b7596ad1f3ea37eae66; the summary is in this lane's pull request comment.

claude-lane: claude-security-review

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review reviewed bad82b1b5663f224160b0542610ebcaacb8480a7: 0 finding(s), 0 as inline comments.

Security review: PR #10224 (tidy in resolve-issue, Phase 1 of #8485)

critical-findings: 0

I found no security issues. The PR does touch trust controls. It adds four skills to what the resolve-issue session may invoke, through resolve.mjs, pr-pipeline.yaml and collect-base-activity. I read each and checked whether any of them widens what the session can do.

What the widening is. The resolve-issue session reads untrusted issue text, and it already has Edit, Write and Agent, web access to any domain, and several allowed scripts. It can now also call Skill(code-tidying:tidy-diff), Skill(docs-hygiene:write-for-agents), Skill(docs-hygiene:write-for-humans) and Skill(ai-slop:audit). Nothing else is added to its allowlist.

Why I found no widening in authority.

  • Staging comes from the trusted base. stage_plugin copies from $BASE_PATH/plugins/<name>, the base copy and not the PR head. The .lane/plugins/** tree stays read-only, since NotebookEdit(./.lane/plugins/**) stays denied and the new test pins Edit(./.lane/plugins/**) and Write(./.lane/plugins/**) as denied. The stage fails red if any staged plugin holds a symlink. A missing skill also fails the stage.
  • The three plugins load no hooks or MCP servers. code-tidying, docs-hygiene and ai-slop have no hooks/, .mcp.json, mcpServers, monitors or lspServers (checked by file glob and by grep of each plugin.json). stage_plugin writes an empty .mcp.json when one is absent. The docs-hygiene agent compare-labeler is limited to Read, Grep, Glob.
  • The new script grants add no new reach. The only new executable is tidy-diff/scripts/change-shape.sh. It passes "$@" to python3 …/change-shape.py after the script path, so there is no interpreter-flag injection. Python puts the read-only staged script directory on sys.path, not the workspace. It prints a verdict for two files, so it reads nothing the allowed read-only commands (cat and similar) don't already reach. The ai-slop:audit rules (detect.sh, rubric-fanout.sh, the emit and cross-check scripts, sha256sum, mkdir -p $lane/scratch/*) are moved into skill_script_rules with the same rules in the same order. The user-scope.sh and Bash(git *) denies still apply, and a deny wins over the skill's own allowed-tools (git, mkdir, user-scope.sh). mkdir adds nothing the lane's unrestricted Write doesn't already give.
  • The launcher gate fails closed. tidy resolves only for a read skill with applied-by.patch and no prepare, which the schema requires. The launcher also requires run-claude-cli and an issue number. Otherwise it fails red before any output, and the new tests cover six refusal cases plus claude-code-action.
  • The preamble inputs come from the base config. The turn share and cutoffs are validated by regex before they reach the preamble. Shared paths are limited to [A-Za-z0-9_./ -], and the cutoffs must be positive integers. The schema pattern on shared-paths agrees.
  • The model-side cutoffs don't gate any authority. The cutoffs, the shared-path exclusions and the HARD exclusions are applied by the model, not by a tool. They only decide whether tidy runs. The lane already has unrestricted Edit and Write, and the patch still goes through apply-issue-patch with the protected-path rules (apply-patch, patch-rules.json). Skipping a cutoff therefore grants nothing new.
  • Token and kill-switch controls are unchanged. The lane token scope, trusted-actor checks and kill switch are untouched. effect: read and the no-write-token design for resolve-issue stay, and live-config.test.mjs still tests the refusal of a write effect.

Manifest.

  • manifest plugins/code-tidying/.claude-plugin/plugin.json description: pass (inert field). Version, userConfig and every other field are unchanged, and marketplace.json is untouched.

Instruction surfaces. plugins/work-items/skills/work/SKILL.md only gains a CI-mode tidy step. No instruction is deleted, narrowed or softened, so the instruction exception register was not needed.

Spend (not a hold). Tidy spends up to 25% of the lane's existing turn cap (prepaid or subscription usage), plus the extra check re-run. It adds no billed resource or plan change.

Not verified. The PR says the node tests and the shell pairing test were not run. This review checked logic only, and I executed nothing. I did not read the docs-hygiene write skills' bodies. The PR flags that they stay within the allowed skills as untested. Even if they try another skill, the Skill(...) allowlist blocks it.

@github-actions github-actions Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

claude-security-review holds this pull request for a person (critical-security) at a21c5aca8a93f871130b4b7596ad1f3ea37eae66.

Trust-control change: .github/actions/resolve-config/resolve.mjs and docs/conventions/pr-pipeline.yaml (loaded by the token broker's signer process) change without a diff that shows narrowing. The change adds a tidy field that lets the issue lane call 4 more skills and their scripts. I found no token-scope widening, but the lane rule treats this as CRITICAL and needs a trusted person's approval of the head.

claude-lane: claude-security-review

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

claude-review reviewed bad82b1b5663f224160b0542610ebcaacb8480a7: 0 finding(s), 0 as inline comments.

No findings. I read the full diff (22 files) and the PR context, and did not run any tests or checks, because this lane has no shell.

What I checked

  • collect-base-activity/action.yml
    • The stage_plugin and skill_script_rules helpers keep the old ai-slop:audit rules and order.
    • The new tidy gate reads $edits, $PREPARE and $LAUNCHER, which are all set earlier (action.yml lines 392-403). $plugin is set at line 434, before either helper is called.
    • Plugin staging and the symlink check are unchanged. Skills are allowed one by one as Skill(<plugin>:<skill>), with no wildcard. The skill-name regex and the shared-path and cutoff regexes keep odd values out of the preamble.
    • The turn budget is max-turns * share / 100. The tests expect 37 from 150 turns at 25%, which matches.
  • Schema and resolve.mjs. tidy is limited to a read skill with applied-by.patch and no prepare. The launcher gate is stricter: it also requires an issue lane on run-claude-cli. The new tests cover each of those refusals.
  • tidy-diff skill. The files it links to all exist: tidy/reference/exclusions.md, bundled-simplify.md, the dissolve-comments triage and safety references, the plugin-level change-shape.py and added-lines.sh. Its change-shape.sh is committed executable (mode 100755).
  • work skill CI mode. The git-read subcommands it calls (diff, status) are in the wrapper's allowed set (action.yml line 532).
  • Staged plugins. code-tidying, docs-hygiene and ai-slop ship no hooks, no .mcp.json and no bin/ entries in their directories, and their plugin.json files declare no hooks or MCP servers. The only pre-compute line among the three passes is ai-slop:audit's detect.sh, which the new rules allow.
  • Manifest. The code-tidying description now names tidy-diff and the README lists it. The three fragments are bump: minor, which fits a new skill and a new optional field.
    • manifest description: pass
    • manifest version bump: pass (changelog fragments, all minor)
    • No userConfig field is added, changed or removed.
  • Closing issue. pr-pipeline: tidy a lane's diff inside resolve-issue before its one push #8485 is referenced as Refs, so the PR context has no closing-issue section and no acceptance criteria to check.

Unverified by me (the PR also lists these as not run)

  • The node and shell tests the PR touched.
  • Whether the live lane loads the extra plugin dirs, resolves the nested Skill calls, and keeps the docs-hygiene write skills within the allowed skills.
  • The new eval cases.

Notes, not counted as findings

  • The PR body calls the new work eval "case 16", but the diff adds it as id: 18. Cosmetic.
  • The cutoffs, the shared-path rule and the "listed lines only" scope are enforced by the model's own measurement and instructions, not by the runner. The runner enforces only the skill allowlist and the script rules. This is the PR's stated design, and the patch-apply protected-path rules still gate the result.
  • This widens which skills the issue lane may invoke, as owner decision (a) of 2026-10-19 allows. It is limited to the named quality skills.
  • Spend: tidy uses up to 25% of the resolve-issue run's turn cap, plus the extra check run. That is prepaid-credit spend only, so there is no cost hold.

@kyle-sexton kyle-sexton removed the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 26, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

Unattended merge: native auto-merge leaves this pull request unarmed at head 790239ccc271c2ad26a81dc112fe6081060d547a. A person must clear this reason, so the pr-merge lane added the needs-human label: fix the reason, then remove the label, and the next scheduled run judges it again.

it changes .github/actions/resolve-config/live-config.test.mjs, a hold path

@melodic-automation-lanes melodic-automation-lanes Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 26, 2026
@kyle-sexton kyle-sexton removed the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 26, 2026
kyle-sexton
kyle-sexton previously approved these changes Oct 27, 2026

@kyle-sexton kyle-sexton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Owner decision 2026-10-26 ~22:3xZ in the hub session: merge the PRs currently held for the owner, security-flagged or otherwise. Approving head 790239c under that decision; this lifts its hold paths (resolve-config) per merge-holds.mjs. Still open: no ci-lanes success on this head, and the CRITICAL review-lane thread on resolve.mjs (tidy field) is unaddressed in code.

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 27, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 27, 2026
@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 27, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 27, 2026
kyle-sexton and others added 2 commits October 27, 2026 02:22
main now builds an issue lane's protected-path rules from the base's apply-patch
and patch-rules.json; the tidy tests' own base lacked them. One helper now
copies them for every issue-lane base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

claude-security-review holds this pull request for a person (critical-security) at 1f6d28bed7e2b9bad9eb2db4194e470502b84149.

Trust-control change: docs/conventions/pr-pipeline.yaml and .github/actions/resolve-config/resolve.mjs feed the token broker, and the diff does not narrow what the broker grants. The code shows no grant widening (effect stays read; tidy is only carried onto the selected activity), but it does widen which skills the untrusted-input issue lane may invoke. A person should confirm owner decision (a) covers exactly these skills.

claude-lane: claude-security-review

# Conflicts:
#	plugins/code-tidying/.claude-plugin/plugin.json

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

claude-security-review: 1 inline finding(s) on ea2394196396d78ee224d28b46842ccea8f928dc; the summary is in this lane's pull request comment.

claude-lane: claude-security-review

@kyle-sexton
kyle-sexton enabled auto-merge October 27, 2026 23:31
Lane-Activity: pr-unblock/resolve-conflicts
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

Unattended merge: native auto-merge leaves this pull request unarmed at head bad82b1b5663f224160b0542610ebcaacb8480a7. A person must clear this reason, so the pr-merge lane added the needs-human label: fix the reason, then remove the label, and the next scheduled run judges it again.

it changes .github/actions/resolve-config/live-config.test.mjs, a hold path

@melodic-automation-lanes melodic-automation-lanes Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 27, 2026
@kyle-sexton kyle-sexton removed the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 28, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

Unattended merge: native auto-merge leaves this pull request unarmed at head bad82b1b5663f224160b0542610ebcaacb8480a7. A person must clear this reason, so the pr-merge lane added the needs-human label: fix the reason, then remove the label, and the next scheduled run judges it again.

pr-merge's gate holds it on its risk score (cost-review-required: docs/conventions/pr-pipeline.yaml: tidy:; entry: code-tidying:tidy-diff; passes:; - docs-hygiene:write-for-agents; - docs-hygiene:write-for-humans; - ai-slop:audit; turn-share: 25; cutoffs:; max-files: 10; max-lines: 300; max-areas: 1; shared-paths:; - .github/; - .claude/; - .claude-plugin/; - scripts/; - lib/; - docs/conventions/; - docs/standards/; - AGENTS.md; - CLAUDE.md; cite the owner's `**Decision recorded.**` comment on the closing issue or this pull request in the body to clear it)

@melodic-automation-lanes melodic-automation-lanes Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 28, 2026
@kyle-sexton kyle-sexton removed the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 28, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

The unattended merge path armed native auto-merge at head bad82b1b5663f224160b0542610ebcaacb8480a7.

@melodic-automation-lanes
melodic-automation-lanes Bot added this pull request to the merge queue Oct 28, 2026
@melodic-automation-lanes
melodic-automation-lanes Bot removed this pull request from the merge queue due to a manual request Oct 28, 2026
@melodic-automation-lanes
melodic-automation-lanes Bot added this pull request to the merge queue Oct 28, 2026
@melodic-automation-lanes
melodic-automation-lanes Bot removed this pull request from the merge queue due to a manual request Oct 28, 2026
@melodic-automation-lanes
melodic-automation-lanes Bot added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 5c9baab Oct 28, 2026
115 of 119 checks passed
@melodic-automation-lanes
melodic-automation-lanes Bot deleted the work-resolve-issue/issue-8485-40284731507-1 branch October 28, 2026 02:46
@github-actions

Copy link
Copy Markdown
Contributor

Post-merge mutation testing

Killed 0, survived 1, timeout 0, no coverage 0, invalid 0, not run 3.
Covered-code score 0%; mutation score 0%.

File Killed Survived Timeout No coverage Invalid Not run
.github/actions/resolve-config/resolve.mjs 0 0 0 0 0 1
plugins/code-tidying/skills/tidy-diff/scripts/change-shape.sh 0 1 0 0 0 2

Surviving mutants

Location Operator Disposition Cause
plugins/code-tidying/skills/tidy-diff/scripts/change-shape.sh:6 SBR unclassified unclassified

The run's summary has the full report.

@kyle-sexton

Copy link
Copy Markdown
Member

Decision recorded. Cost: approve the resolve-issue tidy block (turn-share 25, cutoffs 10 files / 300 lines / 1 area) in docs/conventions/pr-pipeline.yaml for #10224, at head bad82b1. pr-unblock's merge of main at that head moved the plugins/code-tidying version line in the net diff (0.30.7 to 0.30.8), so the decision recorded at 22:17Z no longer covers the head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant