Skip to content

feat(code-tidying): add upkeep settings, cap and per-merge detection - #12614

Merged
kyle-sexton merged 7 commits into
mainfrom
feat/12475-code-tidying-upkeep
Nov 3, 2026
Merged

kyle-sexton merged 7 commits into
mainfrom
feat/12475-code-tidying-upkeep

Conversation

@kyle-sexton

Copy link
Copy Markdown
Member

Refs: #12475

session: lane-2

Summary

Part of #12475: the upkeep settings, the open-PR cap, per-merge detection and the plan a daily batch runs from. Detection opens no PR and runs no model, as decision Q110 asks ("per-merge is detection only"). No upkeep PR opens until the daily model job lands; see Remaining.

Fix

  • Settings. upkeep_cadence, upkeep_backstop and upkeep_max_open (defaults daily, weekly, 3) in docs/conventions/code-tidying.yaml, with a schema, reference/config.md and one reader, upkeep-setting.sh.
  • Cap. /code-tidying:tidy's existing throttle now takes its limit from upkeep_max_open, so there is one cap.
  • Detection. maintenance-code-tidying-upkeep.yml runs on each push to main and names the changed areas in the job summary, with contents: read only. The gate derives churn from git log, so a lost push run drops no area.
  • Gate. upkeep.mjs gate honors cadence and the cap and opens only the difference. Only an area changed since its last sweep is eligible; overdue ones go first.

Choices made on evidence:

  • The backstop covers changed areas only. Basis: the done-when says "any area the daily batch missed", and 108 areas could not fit about 21 sweeps a week at cap 3 (the count is from areaOf over git ls-files; the sweep figure is judgment).
  • git log is the durable record, not an artifact. Basis: dependabot-fragments.yml:22-24 records that push runs can be lost.

Verification

  • Upkeep tests: 25 pass, 0 fail. open-pr-count test: 21 checks pass.
  • scripts/check-affected.sh: "14 passed, 1 skipped over 20 changed files" (ruff: no changed .py). The 17 nearest suites and callers.test.mjs pass.
  • A read-only run of the gate against this repository planned 3 areas.
  • Left out: the full --tests run. It selects 364 suites and was stopped at 14 of 224 after 25 minutes at --jobs 1; CI runs them.

Remaining

  • The daily batch's model job, which opens upkeep PRs. The lane token broker allows schedule runs only from pr-merge.yml, work-unblock.yml and upstream-apply-changelog.yml (docs/conventions/pr-pipeline/pr-run-activity.md), so how it gets a token is an owner decision.
  • With that job: a record of a clean sweep that opens no PR, since the gate reads sweeps from PR branch names and would otherwise pick that area again daily; the .github/lane-funding.json entry; and the kill-switch read before the model step.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn

kyle-sexton and others added 4 commits November 2, 2026 21:13
…batch gate

Settings upkeep_cadence, upkeep_backstop and upkeep_max_open live in
<home>/code-tidying.yaml and resolve through one reader. The tidy throttle
takes its limit from upkeep_max_open. A push job names the areas each merge
changed. upkeep.mjs gate plans the daily batch from git log, the open tidy PR
count and earlier ad hoc sweeps; no workflow runs it yet.

Refs: #12475

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn
…'s edge

A listing of 1000 pull requests here reaches back about three days, so a
limit-based read stopped every run short of the weekly window. The gate now
pages newest first until it passes the window, and reads open pull requests
separately so an old open sweep still counts.

Refs: #12475

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn
An area nobody changed is never eligible, since 108 areas cannot fit the
sweeps a cap of 3 allows in a week. An area is overdue once its oldest unswept
commit passes the backstop window, and overdue areas go first. The gate reads
commits and pull requests back twice the window.

Refs: #12475

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T03:31:29.282712Z 7c51995 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c5199564c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 7a1da0bdc040667e185212857837f689569a8a7a: read 2 of 2 changed file(s); 0 finding(s), 0 as inline comments.

Security review: PR #12614, incremental from 2190a87a to 7a1da0bd

This push has no security issues. I read every hunk of both files on the incremental list. Neither file matches a TRUSTED PATHS glob. The push changes no trust control: no trusted-actor list, token request, kill switch, merge hold or .github/actions/ action.

critical-findings: 0

What I checked

  • .github/scripts/maintenance-code-tidying-upkeep/upkeep.mjs: the sweep-history-truncated stop is gone.
    • What changed. When the gh pr list --search head:chore/tidy-adhoc- call returns PULL_LIST_LIMIT (1000) entries, plan no longer stops. It now plans from the newest 1000 sweeps.
    • Why the new logic holds. lookbackStart (L78-L81) sets git log --since to the oldest listed sweep. Any area whose last sweep dropped off the list was swept before that point. So every commit the gate reads for that area really is unswept, and treating the area as never swept (swept = 0) is correct.
    • What a dropped sweep can still change. Its mergeCommit.oid is no longer excluded, so its merge could count as churn. That only shifts tidy scheduling (which areas are due, and in what order). It does not touch the cap, the cadence or any path a lane writes to.
    • Why it carries no security impact. The areas[].glob output still comes only from git ls-files through areaOf, and the gate's commands still go through execFileSync with argument arrays and constant arguments. No workflow runs gate yet. The change involves no leak, compromise or charge.
  • upkeep.test.mjs: the only change is that the truncation test is replaced by a test that a full 1000-entry list still plans. It contains no security-relevant code.

Other checks

  • Instruction surface and manifests: this push changes no instruction file, skill body, hook or plugin manifest, so there are no manifest lines to report.
  • PR description: it contains no text that tries to steer this review.
  • Prior findings: the only earlier entry is last round's clean summary (0 findings), so this push repeats nothing. The round cap (3) has not been reached.
  • Spend (not a hold, not counted as a finding): none. The push adds no API calls or runs.

@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-review: 1 inline finding(s) on 7c5199564c0ad91a20e04cde052dec764db27659; the summary is in this lane's pull request comment.

claude-lane: claude-review

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

claude-review reviewed 7a1da0bdc040667e185212857837f689569a8a7a: read 2 of 2 changed file(s); 0 finding(s), 0 as inline comments.

Incremental code review: PR #12614 (2190a87 → 7a1da0b)

I read every hunk of both files in scope: upkeep.mjs and upkeep.test.mjs. I ran nothing.

Prior finding resolved: the gate no longer stops for good at 1000 sweep PRs. The truncated flag and the sweep-history-truncated stop are gone from both gate and plan. I found no other reference to that reason in the upkeep script, its workflow or the code-tidying plugin. Here is why a cut-off list is still safe:

  • The git log window starts at the oldest sweep in the list (upkeep.mjs#L78-L81).
  • If an area's sweeps all fell off the list, its last sweep is older than that start. So every commit the log returns for it is real unswept churn. plan treats it as swept = 0, and it stays eligible.
  • The new test builds 1000 sweeps, checks that lookbackStart returns the oldest, and checks that plan still picks a changed area. This is the "a full page of sweeps still plans" test the prior finding asked for.

Notes (not counted as findings):

  • Assumption. The new comment ("A full list holds the newest") assumes gh pr list --search returns the newest PRs first. I could not check that ordering without a shell. If the order were different, the cadence check could miss the newest sweep.
  • Rare one-off re-sweep. Suppose an area's last sweep was opened before the oldest listed sweep but merged after it. Its merge commit then falls inside the log window but is missing from the merges set. The merge counts as churn, and the area gets one extra sweep. This needs a sweep that stayed open across a gap of about 1000 sweeps, so it is rare and costs only a single extra sweep.

Closing issues: none. The PR says Refs: #12475 and closes no issue.
Manifests: no plugin.json or marketplace.json changes in this push.
Embedded instructions: none in the PR context.
Spend (not a hold): when the list is full, the git log window can reach back about a year. That uses only included Actions minutes.

…n in view

A squash-merged sweep's own commit no longer counts as churn in its area. The
gate reads every sweep by branch prefix and reads commits back to the oldest
sweep, at least 90 days, so overdue churn no longer leaves a fixed window. A
sweep list at the listing limit stops the batch with a reason. The throttle
test clears the inherited git environment.

Refs: #12475

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn

@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-review: 1 inline finding(s) on 2190a87abdaa6bc270b452a101c3bc552e7ec68e; the summary is in this lane's pull request comment.

claude-lane: claude-review

The sweep search returns at most 1000 results, so stopping on a full list would
have stopped the gate for good within a year. The oldest listed sweep is the
lookback floor instead, and an area the list has lost is still judged correctly.

Refs: #12475

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn
@kyle-sexton kyle-sexton added do-not-merge Hard merge gate: do not merge while applied. and removed do-not-merge Hard merge gate: do not merge while applied. labels Nov 3, 2026
@kyle-sexton
kyle-sexton added this pull request to the merge queue Nov 3, 2026
kyle-sexton added a commit to melodic-software/standards that referenced this pull request Nov 3, 2026
…de-tidying-upkeep (#945)

Refs: melodic-software/claude-code-plugins#12475

## Summary

claude-code-plugins is adding the lane
`maintenance-code-tidying-upkeep`. Its `resolve-config` rejects a lane
not named `<stage>-<function>` from this vocabulary, and the
`maintenance` stage lists no matching function.

## Fix

`vocabulary.json`: reserves the `maintenance` function
`code-tidying-upkeep`, with its purpose. Nothing else changes.

## Verification

- Same one-file shape as #909 and #791. CI runs this repository's
vocabulary checks.
- Left out: nothing local beyond the JSON edit; the lane PR in
claude-code-plugins exercises the synced copy.

## Related

- melodic-software/claude-code-plugins#12614 and the batch branch
`feat/12475-upkeep-daily-batch`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01VQb9Pzf47aw4gsMAyk98Wn

<!-- codesmith:footer -->
---
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1796269708&installation_model_id=447774&pr_number=945&ref=codesmith_pr_footer&repository=melodic-software%2Fstandards&return_to=https%3A%2F%2Fgithub.com%2Fmelodic-software%2Fstandards%2Fpull%2F945&signature=7a3a45e029d6685e2e9baeab759eab0d88119c27c0069899b1c719244646ed64"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png"
width="190" height="28"></picture></a>
<sup><a
href="https://app.blacksmith.sh/melodic-software/codesmith/standards/pr/945?autoLogin=true&ref=codesmith_pr_footer">Open
in [code]smith</a> · Need help on this PR? Tag
<code>@codesmith-bot</code> with what you need.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Merged via the queue into main with commit 443a819 Nov 3, 2026
103 checks passed
@kyle-sexton
kyle-sexton deleted the feat/12475-code-tidying-upkeep branch November 3, 2026 04:08
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