docs(claude-ops): record why lanes staleness probe stays a body instruction (#864)#877
Conversation
…uction (#864) Evaluate the lanes skill's git probes against the pinned precompute convention (plugins/playbooks/skills/skill-authoring/reference/precompute-context.md). Findings: - SKILL.md front matter — the two `git rev-parse --show-toplevel` probes are already `!` dynamic-context injections (with `|| echo` fallback and a `shell: bash` declaration). Nothing to convert. - context/refresh.md — the mid-session staleness probe (`git fetch` + `git symbolic-ref` + `git log <lane-launch-commit>..<default>`) fails all four convention conditions and correctly stays a body instruction: conditional (only when weighing a restart, not up front every invocation), needs a computed `<lane-launch-commit>` argument a single-pass injection cannot supply, and its `git fetch` is an unbounded network round-trip that mutates remote-tracking refs (not pure-read). Record that reason inline in refresh.md so the decision is durable, and bump claude-ops to 0.17.3 with a matching CHANGELOG entry (changelog-parity gate). Closes #864 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 42s —— View job PR Review
This is a clean, well-scoped docs + patch-bump PR. Here's what I checked:
|
| Convention condition | Addressed in note |
|---|---|
| Deterministic and read-only | ✅ "updates remote-tracking refs" |
| Needed up front, every time | ✅ "conditional, consulted only when weighing a restart" |
| Independent of Claude's judgement | ✅ "needs a computed argument (<lane-launch-commit>, plus the pathspec …)" |
| Cheap and bounded | ✅ "neither bounded nor pure-read — a network round-trip" |
One minor observation: the note bundles conditions 1 and 4 under a single "neither bounded nor pure-read" phrase while saying the probe "fails every condition." A reader counting reasons (three in the note) against conditions (four in the referenced doc) might need a moment. It's not wrong — both aspects of the git fetch violation are stated — but an explicit split ("not read-only" / "not cheap") would make the four-for-four claim immediately legible. That said, this is durable rationale for a technical audience already familiar with the precompute doc, so I'd leave it to the author's judgement whether to split.
No bugs, no security concerns here.
plugins/claude-ops/CHANGELOG.md
Correctly placed at the top as [0.17.3], ### Changed, Keep a Changelog format. The summary accurately reflects what changed and cites the issue (#864). No issues.
plugins/claude-ops/.claude-plugin/plugin.json
0.17.2 → 0.17.3 is the right semver tier for a documentation-only patch. No other fields changed. ✅
CLAUDE.md guideline alignment
- No hardcoded paths or project-specific values in the new prose ✅
- No PII or secrets ✅
- Version bumped with changelog-parity ✅
- Plugin-form-safe (no
../references, no new file writes to plugin data paths) ✅
Overall: LGTM. The reasoning is accurate, the note is durable, and the mechanics (version + changelog) are correct. The one legibility nit above is optional; the PR is mergeable as-is.
|
Claude finished @kyle-sexton's task in 1m 2s —— View job Security Review
No security issues found. This PR is a documentation-only change with a version bump. The three changed files introduce no new executable code, no new configuration surfaces, and no new trust boundaries. What was reviewed:
No GitHub Actions workflows, hook scripts, MCP server definitions, secret-handling paths, or dependency pins were touched. |
An unrelated claude-ops docs PR (#877, closing #864) merged since this branch's last rebase and landed at exactly 0.17.3 — the same version this branch was claiming. Re-bumped claude-ops to 0.17.4 to clear the exact collision (plugin.json auto-merged to an identical-looking "0.17.3" string without flagging a conflict, since both sides happened to write the same literal text for unrelated reasons; caught by diffing main's version history directly, not by trusting a clean auto-merge). CHANGELOG.md split into two sections (0.17.3 for #877's actual change, 0.17.4 for this PR's). Also swept for new open PRs against all 5 plugins post-merge: #870 (feat/800-audit-instructions) newly touches repo-hygiene (claims 0.4.5) and claude-ops (claims 0.17.2) — both below this branch's current claims (0.4.6 / 0.17.4), no collision. source-control (0.15.11), work-items (0.19.1), and guardrails (0.9.6) re-confirmed against current main and every live open PR (#840 0.15.10, #844 0.17.2, #861 0.19.0) — unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1V3gkrfSf75isB8MiDy3o
Resolves plugin.json/CHANGELOG.md conflicts: keeps this PR's 0.17.4 bump (past main's 0.17.3, landed via #877) and preserves the 0.17.3 changelog entry as-is.
… as deliberate (#853) ## Summary Closes the design fork raised in #820: whether the shell assert-helper duplicated across 5 plugins (and the divergent per-script exit-code taxonomies alongside it) should be consolidated into a shared mechanism, or documented as deliberate. This PR documents. ## Fix - Adds `docs/conventions/shell-test-helpers/README.md` as the owner doc explaining why the duplication and divergence stay as-is, and registers it in `docs/PLUGIN-PHILOSOPHY.md`'s convention registry table. - Adds a one-line pointer comment at each copy site back to the owner doc: `guardrails/hooks/guardrails-test-helpers.sh`, `claude-ops/hooks/claude-ops-test-helpers.sh`, `source-control/scripts/test-helpers.sh`, `repo-hygiene/skills/clean/scripts/lib/test-helpers.sh`, `work-items/tools/work-item-tracker/tests/lib.sh`. - Adds the same kind of pointer to `scripts/check-skill-portability.test.sh`, which opted out for an unrelated reason (it's repo tooling, not a plugin, so no plugin assertion library applies) — noted so the fork's second observation isn't left unexplained. - Bumps `plugin.json` + adds a `CHANGELOG.md` entry for every plugin whose helper file gained the pointer comment. Each has been re-derived from current `main` many times as sibling PRs merged or rebased mid-flight (see Related for the current picture): - `repo-hygiene`: 0.4.4→0.4.6 - `source-control`: 0.15.7→0.16.1 - `claude-ops`: 0.17.1→0.17.5 - `work-items`: 0.18.1→0.20.1 - `guardrails`: 0.9.5→0.9.6 (no open-PR collision at any point so far) No behavior change anywhere — comments and docs only. ## Decision **Chose Option B: document the per-plugin duplication and exit-code divergence as deliberate. No shared helper introduced.** Investigation before deciding: - This repo already has one sanctioned cross-plugin shared-source mechanism: a canonical file under `lib/` (e.g. `lib/hook-utils.sh`), copied — not imported — into each carrying plugin by a dedicated `scripts/sync-*.sh`, tracked in `scripts/cross-plugin-source-registry.txt`, and drift-checked by `scripts/check-cross-plugin-source-drift.sh --check`. - That mechanism is scoped to clusters meant to stay **byte-identical**. Running `check-cross-plugin-source-drift.sh discover` confirms it never even flags the five assert-helper files as a cluster candidate — they live at different paths per plugin and are not byte-identical, so they fall outside that mechanism's scope entirely. - Reading all five files: they are already three genuinely different shapes, not one library that drifted — a hook-contract shape (`guardrails`/`claude-ops`: `ok`/`bad`, `PASS`/`FAIL`, `make_sink`/`wait_for_sink`), a skill-script shape (`source-control`/`repo-hygiene`: `pass`/`fail`, `FAILED`/`CASE_NUM`, file-existence assertions), and a vendored-seam shape (`work-items`: same primitives, but owned by the seam itself so it stays correct wherever the seam is resolved from, independent of this repo's tooling). - Consolidating would mean designing a fourth, unified assertion API and rewriting every existing `*.test.sh` onto it — a bigger, riskier change than the coupling it would remove, and it would cross the plugin-independence boundary `docs/PLUGIN-PHILOSOPHY.md`'s design boundary section already draws (no plugin imports files from a sibling plugin). - Exit-code taxonomies (`remove-path.sh` 0/1/2/3/4, `git-tree-reset-batch.sh` 0/1/2 forwarding a child's 5/7, `check-skill-portability.sh` 0/1/2) encode genuinely different per-script contracts, not arbitrary numbering — each script already documents its own `Exit:` line, and a shared usage/exit helper would either flatten those contracts or grow per-caller branching. - Deferred, not rejected: `guardrails-test-helpers.sh` and `claude-ops-test-helpers.sh` are the one pair that already share a shape closely. If they converge to byte-identical, vendoring just that pair through the existing `lib/` + `sync-*.sh` + registry mechanism is the smaller, precedented move — recorded as the trigger in the owner doc rather than acted on now. ## Verification - `shellcheck` clean on all 6 edited shell files. - Full `check-skill-portability.test.sh` suite: 16/16 pass. - `check-cross-plugin-source-drift.sh --check`: no unregistered or drifted clusters. - `check-changelog-parity.sh --check`: passes with every version bump. - Ran every `*.test.sh` that sources an edited helper (repo-hygiene/clean, guardrails hooks, claude-ops hooks, work-items adapters/lib) — all green, confirming the comment-only edits changed no behavior. - `markdownlint-cli2` and `lychee` clean on the new and modified docs. ## Related - Scope note: issue #820's title says "disk-hygiene/clean", but `disk-hygiene` is Python-only (`hygiene.py`) with no shell assert-helper — the actual duplication lives in the 5 plugins the issue body names (repo-hygiene, source-control, guardrails, claude-ops, work-items) plus root `scripts/`. Treating the title as a triage typo (disk-hygiene vs. repo-hygiene, both "-hygiene" plugins with a `clean` skill) rather than touching disk-hygiene. - **`do-not-merge` held.** This session has had exceptionally heavy concurrent-lane traffic against these same 5 plugins — this PR has been rebased/re-derived nine times as siblings merged (#839, #826, #857, #877, #870, #844) or rebased in place (#840, #882, #861, each more than once). Current picture, last verified fresh at commit `e75e45ed` (`mergeable: MERGEABLE`; all 5 plugins re-checked against current `main` AND every live open PR): - `repo-hygiene` (claims 0.4.6): no open-PR collision. Main is at 0.4.5. - `source-control` (claims 0.16.1): held behind **#882** (`fix/511-babysit-self-identity-decouple`, claims 0.16.0, open) and **#840** (claims 0.15.10, open). Main is at 0.15.9. - `claude-ops` (claims 0.17.5): **no open-PR collision anymore** — #844 (the PR this leg was previously held behind) has merged, landing at exactly 0.17.4; this claim stays one past it. Main is at 0.17.4. - `work-items` (claims 0.20.1): held behind **#861** (`feat/613-mini-sdlc-pipeline-ssot`). #861 itself has re-derived its claim twice as `main` moved — from 0.19.0 up to 0.20.0 (following #857's Jira-adapter minor bump into main) — so this PR's claim moved from 0.19.1 to 0.20.1 to stay ahead. Main is at 0.19.0. - `guardrails` (claims 0.9.6): no open-PR collision. Main is at 0.9.5. - This plugin set has produced a new collision within minutes of nearly every prior check — including siblings re-deriving their own claims upward more than once, an unrelated PR landing at the exact same version by coincidence, and legs clearing and new ones opening. Re-run the full collision protocol (`gh pr list --repo melodic-software/claude-code-plugins --state open --json number,headRefName,files` filtered per plugin, AND a fresh diff of each plugin's version on `main` since this PR's last rebase) immediately before removing `do-not-merge` — do not trust this snapshot. Closes #820 Work-class: C2 (mechanical) — attended triage 2026-07-23, operator-ratified. 🤖 --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
What
Evaluate the lanes skill's deterministic, read-only git probes against the pinned precompute convention (
plugins/playbooks/skills/skill-authoring/reference/precompute-context.md) and either convert each to!dynamic-context injection or record why it fails the four conditions.Per-probe verdict
git rev-parse --show-toplevel(repo root)SKILL.mdfront matter!injection with|| echofallback;shell: bashdeclared.git rev-parse --show-toplevel(lane-config resolution)SKILL.mdfront matter!injection with|| echofallback.git fetch origin+git symbolic-ref+git log <lane-launch-commit>..<default> -- <plugin-path>context/refresh.mdThe two front-matter probes were
!-injected at the skill's creation (#616) and gainedshell: bashin 0.17.2 — already compliant, nothing to convert.Why the staleness probe is not an injection candidate
It fails every convention condition:
git fetchis a network round-trip (latency-variable, can hang) that also updates remote-tracking refs.status/stop/start.<lane-launch-commit>argument (the running lane's launch point) plus the pathspec of whichever plugin the lane runs; a single-pass injection cannot supply either.Recorded inline in
context/refresh.mdso a future reader does not re-litigate it.Automated gate
skill-quality Check 18 (precompute opportunity) scans only
SKILL.mdfenced shell blocks and is silent when the skill already injects with!— lanes does — so the gate was already satisfied; this PR adds no new!blocks.Changes
context/refresh.md— durable "Not an!injection candidate" note next to the staleness probe.claude-opsversion0.17.2→0.17.3+ matching CHANGELOG entry (changelog-parity gate).Verification
check-skill.sh lanes— PASS (0 errors, 0 warnings; markdownlint clean, 163/500 lines)check-changelog-parity.sh --checkand--check-bump origin/main— PASSvalidate-plugins.sh+claude plugin validate .— PASSCloses #864
Related
!conversion of the front-matter probesshell: bash