feat(source-control): dedicated --self/--extra-self self-identity flags for babysit snapshot - #882
Conversation
…gs for babysit snapshot The babysit snapshot derived `self_logins` (the posting identities whose comments self-classification suppresses) from the `--author` discovery filter, conflating two distinct concerns. That broke in both directions (#511): configured extra self identities were dropped whenever autopilot widening drops `--author` (a bot poster's own comments re-fired `new_human_blocking_feedback` every cycle), and a discovery `--author` for a different login was wrongly treated as self (suppressing that author's genuine feedback from the worker-dispatch arm). `pr_queue_snapshot.py` now resolves self-identity from dedicated `--self` (full override) / `--extra-self` (added to `@me`) flags, mirroring `babysit-readiness-gate.sh`'s flag semantics, independent of `--author` and for both `--queue` and `--pr` scope. This supersedes the `@me`-only union from #494 and removes the author-derived self fallback in `build_config` (and the now-dead `resolved_authors` carrier), so no discovery author can leak into the self set. Red-green regression tests assert both directions at the `build_snapshot` level. The `resolve_self_logins` unit tests that pinned the old author-union contract are rewritten to the new flag-based contract. Structural parity with the gate, not exact on one edge: an unresolvable `@me` raises (fail-loud) rather than degrading to the extras; that parity decision is tracked in #881. Per-plugin bump 0.15.9 -> 0.16.0 (minor: new CLI surface) + CHANGELOG. Closes #511 Refs #881 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 54s —— View job PR Review — feat(source-control): dedicated --self/--extra-self self-identity flags for babysit snapshot
SummaryThis is a clean, well-scoped fix for #511. The conceptual separation of discovery authors from self-identity is correct and the implementation follows through cleanly. The regression test structure — asserting both the under-inclusion and over-inclusion directions at the Observations1.
self_login = gh.resolve_author("@me")
if self_login:
source.append(self_login)The docstring (L113–114) says:
But the The test 2.
if self_csv:
source = _csv_list(self_csv)
else:
source = _csv_list(extra_self_csv)
...When both 3. Minor duplication between def _csv(value: str | None) -> frozenset[str]:
return frozenset(
part.strip() for part in (value or "").split(",") if part.strip()
)
def _csv_list(value: str | None) -> list[str]:
return [part.strip() for part in (value or "").split(",") if part.strip()]Near-identical bodies with only the container type differing. 4. SKILL.md step 4 — unquoted The value could contain commas ( What's correct
|
|
Claude finished @kyle-sexton's task in 3m 10s —— View job Security Review — PR #882
SummaryNo CRITICAL or IMPORTANT vulnerabilities found in this diff. The core change — decoupling SUGGESTION —
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20f974366a
ℹ️ 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".
claude-ops: #844 rebased and re-derived its claim from 0.17.2 to 0.17.4, colliding exactly with this branch's prior 0.17.4. Bump to 0.17.5. source-control: a new PR, #882 (fix/511-babysit-self-identity-decouple), claims 0.16.0 — a minor bump above this branch's prior 0.15.11 and above #840's 0.15.10. Bump to 0.16.1 to stay ahead of both. repo-hygiene (0.4.6), guardrails (0.9.6), and work-items (0.19.1) were re-verified fresh against current main and every live open PR (main: repo-hygiene 0.4.5, guardrails 0.9.5, work-items 0.19.0; #861 0.19.0) and remain correct, no change needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1V3gkrfSf75isB8MiDy3o
#844 (claude-ops) merged into main at exactly 0.17.4, which this branch's prior 0.17.5 was already one past — kept as-is, no re-bump needed for the number itself, just resolved the resulting plugin.json/CHANGELOG.md conflict. Full fresh collision sweep after the merge found claude-ops now has NO open-PR collision at all. It also found #861 (work-items) re-derived its own claim from 0.19.0 to 0.20.0 since the last check (following #857's Jira-adapter minor bump into main) — colliding with this branch's prior 0.19.1. Re-bumped work-items to 0.20.1. source-control (0.16.1, held behind #882's 0.16.0 and #840's 0.15.10), repo-hygiene (0.4.6, no collision), and guardrails (0.9.6, no collision) re-verified against current main and all live open PRs — unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1V3gkrfSf75isB8MiDy3o
`resolve_self_logins` tested `self_csv` for truthiness, so an explicit
`--self ""` (flag supplied, empty value) fell through to the "flag
omitted" branch and resolved/added `@me` -- silently contradicting the
documented full-override contract ("`@me` is NOT added"). Switch the
guard to `is not None` so only an actually-omitted flag falls through.
Also document that `--self` takes precedence over `--extra-self` when
both are supplied, and drop `plugin.json`'s stale `babysit_self_logins`
description clause: self-identity no longer feeds discovery scope after
the `--author`/self decoupling in this branch.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 1s —— View job
Review — follow-up commit
|
|
Claude finished @kyle-sexton's task in 1m 48s —— View job Security Review — PR #882
SummaryNo CRITICAL or IMPORTANT vulnerabilities found. The two SUGGESTION-level findings from the prior security review on commit Prior findings: both resolvedSUGGESTION 1 — Commit SUGGESTION 2 — stale "discovery scope" in Resolved: the Residual observation
self_login = gh.resolve_author("@me")
if self_login:
source.append(self_login)The docstring states Notes on non-findings
|
(The "No CRITICAL or IMPORTANT vulnerabilities found" line earlier in this comment is prose, not a live finding — not tabulated.) |
|
…discovery filter (#897) Author ruling on the #897 discovery-contract fork (Codex flagged on #882): filter and stopped joining babysit_self_logins onto --author, but the userConfig `description` still listed "discovery scope" first — code and documented contract disagreed. and "a distinct concern from --author (which authors' PRs to discover)," and its fix direction explicitly drops the `--author @me,<self-logins>` extension. So the pre-#511 discovery-widening was an incidental side effect of the old author-derived self set, not a stated goal. Ruling: keep the discovery-drop (option B); babysit_self_logins is a suppression/classification/merge-exemption set only — which authors' PRs the queue discovers stays --author's job. Correct the userConfig description to match; no code change (the code already behaves this way post-#511). Part of the unreleased 0.16.0 (#511) entry. Refs #511 #897 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 23s —— View job PR Review — commit
|
|
Claude finished @kyle-sexton's task in 2m 16s —— View job Security Review — PR #882
SummaryNo CRITICAL or IMPORTANT vulnerabilities found. This review covers the full three-commit diff, including the latest docs-only commit Prior SUGGESTION findings: both resolvedSUGGESTION 1 —
SUGGESTION 2 — stale "discovery scope" language in Fully resolved across two commits: Residual note (informational, pre-existing, not a security finding)
self_login = gh.resolve_author("@me")
if self_login:
source.append(self_login)The docstring (L113–114) and Notes on non-findings
|
#882 (source-control) merged into main at 0.16.0, which this branch's prior 0.16.1 was already one past — resolved the resulting plugin.json/CHANGELOG.md conflict, kept as-is. Full fresh collision sweep after the merge found source-control now carries TWO additional open PRs beyond #840: #895 (fix/548-babysit-worktree-head-safety, claims 0.15.10) and #898 (feat/399-shared-worktree-helper, claims 0.17.0 — a minor bump above this branch's prior 0.16.1). Re-bumped source-control to 0.17.1 to stay ahead of all three (#898's 0.17.0, #895's and #840's 0.15.10). claude-ops (0.17.5, no collision), work-items (0.20.1, held behind #861's 0.20.0), repo-hygiene (0.4.6, no collision), and guardrails (0.9.6, no collision) re-verified against current main and all live open PRs — unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1V3gkrfSf75isB8MiDy3o
Integrate the latest main (source-control advanced to 0.16.0 via #511's pr_queue_snapshot self-identity work, plus #882). Re-derived this PR's bump to 0.16.1 (one past current main) and re-labeled the CHANGELOG entry from 0.15.10 to 0.16.1, stacked above the merged-in 0.16.0 entry. safety.md, orchestration.md, review-discipline.md, and SKILL.md auto-merged (my bin/-path edits and the upstream changes touch distinct regions); babysit-prs skill-quality gate green at 499/500 lines.
…utate; merge-only, upstream refspec push (#895) ## Summary Fixes #548. A babysit PR worker can be assigned a git worktree in **detached HEAD** — because the PR branch is already checked out in a sibling/foreign worktree — or on a **stale local branch tip** behind the PR head. The checkout/freshness mechanics then merged and pushed from that tip, so a stale-tip integration could **silently revert the newest branch commit** — a near-miss where safety depended on the assigned `HEAD` happening to match, not on a guard. The initial reviewer pass confirmed the safety.md contract text was sound but raised a **CRITICAL**: the actual worker mechanics (loop.md/SKILL.md/orchestration.md) were unreconciled, so an agent following the literal steps still hit the failure. This PR fixes the contract **and** the mechanics that implement it. ## The fix - **`reference/safety.md` Checkout And Push Invariants** — assert the assigned worktree's `HEAD` equals the **true PR head** (`gh pr view <N> --json headRefOid`; equal to `origin/<headRefName>` for a same-repo PR) before any merge/edit/push; **stop** on a stale/detached mismatch. Push by explicit refspec to the branch's configured upstream `git push "$(git config --get branch.<headRefName>.remote)" HEAD:<headRefName>` (fast-forward by construction, never `--force`/`--force-with-lease`). The reuse rule is reconciled so it permits the detached-HEAD path under the same assertion (no self-contradiction). - **`reference/loop.md` §5.1.2** — acquire the head via `gh pr checkout` (heals a behind-origin local branch; `--detach` for a sibling-locked branch; resolves fork PRs), assert `HEAD == PR_HEAD` (the live `headRefOid`) in every checkout path, degrade to read-only on mismatch. `SKILL.md` Step 0.2 + the cross-tier invariants and `reference/orchestration.md`'s conflict-worker follow the same assertion + refspec push. `worktrees.md` gets a one-line pointer (not a duplicate). - **Freshness is now merge-only.** The prior loop.md path rebased-and-`--force-with-lease`d linear-history branches — which both violated the skill's own never-force-push invariant (`safety.md` "Never Do Automatically", `orchestration.md`) and was the silent-revert vector. Behind-default branches now always integrate via `git merge` + a fast-forward refspec push. **Behavior change:** linear-history branches now carry an interim merge commit during freshness instead of being rebased (the final squash merge still flattens history). ## Scope decisions (called out for review) - **Fork/cross-repo heads (Option B — upstream-aware push).** The push targets the branch's *configured upstream* — `git push "$(git config --get branch.<headRefName>.remote)" HEAD:<headRefName>` — which resolves to `origin` for a same-repo head and to the fork's remote for a **write-allowed in-owner fork** head (a real supported case: `branch_write_allowed=true` for cross-repo heads under `<watched-owners>`). An earlier revision hardcoded `origin`, which the re-review flagged as a regression that would silently write a same-named branch on the base repo for a fork PR; this fixes it while keeping the origin refspec for same-repo heads. An external-fork head *outside* watched owners remains safety.md's read-only stop-and-ask case. The assertion uses the live `headRefOid`, correct for any PR type. - **Enforcement stays agent discipline.** Whether the head assertion belongs in a deterministic push-safety guard (rather than prose the worker follows) is filed as follow-up **#885**. ## Verification (local gates) - `check-skill-portability.sh origin/main` — PASS (5 skill files). - `check-changelog-parity.sh --check-bump origin/main` — PASS (0.15.10 entry present). - `markdownlint-cli2` on the changed docs — clean; SKILL.md 499/500 lines; `evals.json` (id 6 updated to the merge-only + upstream-refspec contract) valid; `plugin.json` valid. - Python unittest suite unaffected (no code changed) — 339 tests OK. - Two independent fresh-context review rounds: round 1 raised a CRITICAL (the mechanics docs were unreconciled with the safety.md contract) — fixed by reconciling loop.md/SKILL.md/orchestration.md; round 2 raised a CRITICAL (hardcoded-origin push broke in-owner forks) — fixed by Option B (upstream-aware push). ## Version Per-plugin bump **0.15.9 → 0.15.10** (patch). `marketplace.json` pins no version for `source-control`, so only `plugin.json` changes. > **Ordering note for the merge lane:** my open PR #882 (#511) bumps `source-control` to **0.16.0** and is unmerged. If #882 merges first, re-bump this **above 0.16.0 (→ 0.16.1)** during recompose — do not keep 0.15.10. Closes #548 ## Related - #885 — follow-up (filed): promote the head assertion from prose to a deterministic push-safety guard. - #524 — worker-lease cross-session exclusivity (distinct: *which session* may work a PR; this is the *git mechanics* of the assigned worktree). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… 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>
…lved self set (#1395) Closes #497 *This was generated by AI during autonomous /work-items:work-loop execution.* ## Summary #497 reported that `pr_queue_snapshot.py` assembled its `ClassifyConfig` before any author resolution, so a single-`--pr` invocation classified with `config.self_logins` empty — silently disabling both the `new_human_feedback` self-exclusion and `detect_foreign_activity`. **The ordering fix itself already shipped**, in #882 (`0.16.0`). On `main` today, `resolve_self_logins` runs at `pr_queue_snapshot.py:187`, above the single `build_config` call (`:190`) and above the `--pr` / `--queue` scope split (`:195`), so both scopes share one resolved config. #882 deliberately left #497's acceptance to be verified separately — that is what this PR does. **No production code changes here.** The remaining gap was coverage, not behavior. Every existing `--pr` test stopped the per-PR loop before `classify_pr` (stubbing `view_pr` to raise), so nothing proved that the arms which actually read `config.self_logins` fire in single-PR mode. Two tests now drive a real classification end to end through `build_snapshot`: - a self-authored human comment stays human-blocking (a maintainer keeps the ability to human-stop their own PR) but is excluded from `new_feedback.human`, so it cannot self-inflict a worker re-dispatch; - `detect_foreign_activity` fires on a self-authored trigger-phrase comment absent from the mutation ledger. Because the change is tests-only it ships **no version bump**: per `docs/MIGRATION-PLAYBOOK.md` ("Version pinning and update delivery") the bump is the consumer *delivery vehicle*, and a consumer never runs the plugin's unit tests. `plugin.json` and `CHANGELOG.md` are byte-identical to `main`, so the shipped diff is the test file alone. (The bump slipped back in once, when the `main` merge resolved a `0.26.4` / `0.26.8` conflict to `0.26.9`; `5a348a63` re-dropped it.) ## Test plan - **Full engine suite**, as #497's verification note explicitly requires (the whole suite including `test_integration.py`, not just `test_babysit_delta.py`): `uv run --with pytest pytest -q` from `plugins/source-control/skills/babysit-prs/scripts/` — **374 passed, 63 subtests passed**. - **Mutation check** that the two new tests are genuine guards rather than vacuous: forcing `resolve_self_logins` to return `[]` (the pre-#882 condition) fails both new tests; restoring it passes them. This is stronger evidence than the tests merely passing. - `git merge-tree` against current `main` reports no conflict. ## Related - Refs #882 — shipped the ordering fix and deferred this acceptance verification. - Refs #473, #494 — the engine-level self-filter that this coverage exercises. - Refs #601 — shipped `0.26.4` independently while this branch was open. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
Fixes #511. The babysit PR-queue snapshot derived
self_logins— the posting identities whose comments self-classification suppresses — from the--authordiscovery filter, conflating two distinct concerns (which authors' PRs to discover vs whose comments to suppress). That broke in both directions:babysit_self_logins) rode on--author, so when autopilot widening drops--authorentirely, a bot poster's own comments re-firednew_human_blocking_feedbackevery cycle.--queue --author alicerun authenticated as a different login madealicea self-login, suppressing Alice's genuine feedback from the worker-dispatch arm.The fix
pr_queue_snapshot.pynow resolves self-identity from dedicated--self(full override — exactly the given logins,@menot added) /--extra-self(added on top of the authenticated@me) flags, mirroring the existingbabysit-readiness-gate.shsemantics, resolved independently of--authorand before the--pr/--queuescope split (so single-PR scope is covered too). This supersedes the@me-only union added in #494, and the author-derived self fallback inbuild_configis removed so no discovery author can leak into the self set in any path.The skill's step-4 invocation and the
babysit_self_loginsuserConfig table row now route the configured extras through--extra-selfinstead of overloading--author @me,<self-logins>; because self-identity no longer rides on--author, it survives autopilot widening.Tests (red-green, with transparency on the rewritten spec)
SelfIdentityDecouplingTestsasserting both directions at thebuild_snapshotlevel (extra-self survives a dropped--author; a discovery author is not treated as self). Verified these fail against the pre-fix author-union code and pass after the fix.resolve_self_loginsunit tests pinned the old author-union contract; they are rewritten to the new flag-based contract, andtest_discovery_authors_are_unioned_with_the_self_login(which asserted the over-inclusion behavior now fixed) is deleted.test_raw_author_fallback_drops_me_when_unresolvedbecomestest_missing_resolved_self_logins_yields_empty_not_author. These are a ratified spec change (the issue's converged decision), not test weakening.Verification (local gates)
python -m unittest discover -s tests -p 'test_*.py'(the CI entry viaengine.test.sh) — 341 tests OK.check-changelog-parity.sh --check-bump origin/main— PASS (0.16.0 entry present).check-skill-portability.sh origin/main— PASS.check-changed-skills.sh— SKILL.md 499/500 lines (under the hard cap); the one reported "engine.test.sh failed" is the pre-existing repo-wide ruff E402 quirk that does not reproduce in CI (main is green; merged babysit PRs chore: declare shell: bash on every skill with dynamic-context injections #860/fix(source-control): actionable owner/repo diagnostic on readiness-gate fetch failure #839 pass skill-quality-gate), and this change adds zero new ruff errors (32 before == 32 after).markdownlint-cli2on the changed docs — clean;plugin.jsonvalid.Version
Per-plugin bump 0.15.9 → 0.16.0 (minor — new
--self/--extra-selfCLI surface alongside the behavior fix).marketplace.jsonpins no version forsource-control, so onlyplugin.jsonchanges.Closes #511
Related
--prsnapshot mode leavesself_loginsempty (self-filter + foreign-activity dormant) #497 — single---prscope leavesself_loginsempty (sibling facet of the same seam, triaged blocked-by babysit-prs: decouple self-identity from --author so configured self-login extras survive autopilot widening #511). This change resolves self-identity for--prscope too, but its acceptance is left for the babysit-prs: single---prsnapshot mode leavesself_loginsempty (self-filter + foreign-activity dormant) #497 lane to verify — not closed here.@me-only--queueunion this supersedes.@mewhere the readiness gate degrades to the--extra-selfset; tracks whether fail-loud is the intended contract. Surfaced in this PR's review.🤖 Generated with Claude Code