Repository navigation
fix(harness-ops): plugins sync prints every stale project path, and scratch-dir claude runs leave thousands of project records #6182
Description
Problem
A /harness-ops:plugins sync run on 2026-10-04 (harness-ops 3.6.5 running, swept to 3.7.2; WSL, cwd /home/kyle, install_new ask) reported:
Stale project records: 4342 record(s) across 263 path(s) not present on this machine
and then printed one line per path, all 263 of them.
-
The report lists every missing path with no cap or grouping.
skills/plugins/scripts/render-report.jq(3.7.2, line ~192) runs.stale_project_records.by_path[] | " - \(.path): \(.count) record(s)"with no limit. In this runreport.txtwas 59 KB, and the bundled digest line plus report came to 118 KB of stdout, which went past the Bash tool's inline limit and was saved to a file. The skill tells the model to paste the render as printed, and pasting 263 path lines is noise. The digest also carries the fullby_patharray, so the one compact JSON line is large as well. -
One session's scratchpad produced 94% of the records. 4076 of the 4342 records, and 254 of the 263 paths, are under a single session's scratchpad:
/tmp/claude-1000/-home-kyle-worktrees-melodic-software-claude-code-plugins-feat-youtube-digest-.../<session>/scratchpad/, split between two subdirectories:attr/main-plugins_<plugin>_skills_<skill>_SKILL-r<n>-<epoch>: 114 paths, 4 project-scope records each (fleet,harness-config,harness-memory,harness-ops).s4-snapshots/<n>-<rand>: 140 paths, 40 distinct plugins among them.
installedAtspans 2026-10-02T02:00Z to 2026-10-03T21:55Z. The scratchpad is gone, so I could not confirm what made these folders. They look like per-item snapshot directories that aclaudeprocess was started in: Claude Code writes a project-scope install record for a folder whose.claude/settings.jsonenables plugins. Theattr/names look likeattribution:auditjudge or eval runs, but the attribution plugin source does not createattr/ors4-snapshots/itself, so the session probably made them ad hoc.
The skill reports these records and never reaps them (by design: an unmounted volume can also look like a missing path). Since nothing removes them, each such session adds dozens to hundreds of permanent rows to installed_plugins.json and to every later sync report.
Suggested handling
- Render: group
by_pathby common prefix, or cap it (for example the 10 largest paths, then "and N more; full list in<run_dir>/digest.json"). Under/tmpand the scratchpad root, a missing path cannot be an unmounted volume, so those groups could be labeled as safe to remove. - Cause: when a skill or session starts
claudein a scratch copy of a repo, it should either copy the repo without.claude/settings.jsonor startclaudewith--setting-sources user(or an equivalent flag), so that no project-scope install record is written. Decide where that rule lives: a gotcha in the skills that start headless judges, or a guardrails check. - Cleanup: decide whether harness-ops (or disk-hygiene) offers an opt-in, confirm-gated reap of project records whose
projectPathis under the session temp root (/tmp/claude-<uid>/), where the unmounted-volume caveat cannot apply. plugins: project-scope pins accumulate per worktree (15 paths x ~60 plugins, 3 paths gone, 412 cached versions) #3688 and fix(source-control): worktree teardown leaves project-scope plugin install records forever #3113 (closed) covered the worktree version of this; scratch directories are a new source.
Verification
jq -r '[.plugins[][] | select(.projectPath? and (.projectPath|test("/scratchpad/(attr|s4-snapshots)/")))] | length' ~/.claude/plugins/installed_plugins.jsonThis printed 4076 on this machine. Run journal: ~/.claude/plugins/data/harness-ops-melodic-software/plugins-sync/runs/20261004T041542Z.kKt5LZ.
Related: #6055 (the self-update note in the same report names the wrong plugin; it still reproduced here, naming actionlint instead of harness-ops), #5941 and #6056 (other plugins sync report fixes).
🤖 Generated with Claude Code
Activity
github-actions commentedon Oct 4, 2026
Thanks for the report. Automated triage handed this issue to a maintainer.
Automated triage. A maintainer reviews it.
kyle-sexton commentedon Oct 4, 2026
kyle-sexton commentedon Oct 4, 2026
This was generated by AI during attend-queue.
Operator direction (2026-10-04): "go with the recommendations." This records that decision.
Operator ratification: triaged and ratified as C3 (scoped), bug-fix-shaped, priority low, on the render fix only.
Brief for the worker (base: origin/main after #6181, harness-ops 3.7.3; the stale block is at
render-report.jq194-200):stale_project_records.by_pathby parent directory and cap the printed rows, with a "+N more" line. Write the full list to the run directory and name that file in the render.by_patharray from the printed digest line if no consumer reads it from stdout rather thandigest.json. Verify this first; if a stdout consumer exists, keep it and say so in the PR.stale-records-cache-content.txtgolden, which fix(harness-ops): plugins sync report-row wording, coverage labels and timing attribution #6181 already changed at line 12, the context doc and the CHANGELOG, with a version bump.Out of scope:
--setting-sources" gotcha, which rests on an unprobed claim;CLAUDE_CODE_TMPDIRcan move them.Cleanup of records with absent paths belongs with #6185.
Sequencing: #6184 adds a pointer line to the same block and is blocked by this item. Research: attend-queue slice
intake-6182. The issue's counts can no longer be reproduced (both hosts were reset 2026-10-04).kyle-sexton commentedon Oct 4, 2026
This was generated by AI during work-loop.
Ratify autonomous dispatch of this C3 item?
Classification:
work-class: scoped(C3). Intended dispatch: the work-loop worker lane, through/work-items:work, to a draft PR the lane never merges, after its blocked-by edges clear. Harness-ops items run one at a time. The first-drain gate dispatches a C3 item only on a ratification reply to this marker. A decision comment or an operator-ratified note in the body is context, not dispatch authority. So it is queued here, keeping its labels, until/work-items:attend-queuerecords the reply.Lane: work-loop, instance melo-worker-1, cycle 1.
kyle-sexton commentedon Oct 4, 2026
kyle-sexton commentedon Oct 4, 2026
This was generated by AI during attend-queue.
Operator ratification (2026-10-04): ratified as C3, bug-fix-shaped. This replies to the
kind=ratify-c3marker above. The operator's direction was "go with the recommendations, make them agent ready". The brief is in the earlier attend-queue decision comment or in the issue body; follow any blocked-by edge on this item.kyle-sexton commentedon Oct 4, 2026
fix(harness-ops): name the real reason a sync run has no stale-path list