fix(source-control): exclude self-login from babysit new_human_blocking_feedback#494
Conversation
…ng_feedback The babysit delta engine's `new_human_blocking_feedback` and `new_human_feedback` arms counted every non-bot comment as human feedback, with no exclusion for the login the babysit worker itself posts under. For a solo maintainer whose gh login is the configured self-login, the worker's own prior-round classification replies and "Fixed in <sha>" follow-ups (each a new comment id) manufactured a self-inflicted, unsuppressible `new_human_blocking_feedback` dispatch that re-fired every cycle with zero real work. Filter items authored by the configured self-login(s) out of both new-human delta arms, reusing the existing `config.self_logins` seam (gh identity plus `babysit_self_logins` extras) that `detect_foreign_activity` and the merge-gate self-exemption already resolve. This mirrors the self-reply exclusion `review-discipline.md` §1 mandates for the worker and the structural self-filter the bot arms get for free. Scoped to the dispatch deltas only, not `collect_feedback` classification: a self-authored item still classifies as human feedback, so a genuine "do not merge" comment the maintainer posts under their own login keeps the human stop and triage blocker intact and still halts the merge gate. Closes #473 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011V31qpAHP3jfs76B9d5Rfo
|
Claude finished @kyle-sexton's task in 2m 51s —— View job PR Review — fix(source-control): exclude self-login from babysit new_human_blocking_feedback
The fix is correct, well-scoped, and the deliberate scope decision (filtering at the dispatch delta, not at classification) is the right call. A few observations below. CorrectnessThe core logic (lines 364, 407, 667) is correct:
One observation:
|
…n arm The self-login filter over the new-human-feedback delta covers both the blocking and non-blocking human arms (babysit_delta.py line 407), but the existing tests exercised only new_human_blocking_feedback. Add coverage for the non-blocking `human` arm surfaced in new_feedback["human"]: a self-authored non-blocking comment stays classified human yet is excluded from the delta, while a non-blocking comment from any other login still surfaces. Completes the coverage for issue #473's fix (claude[bot] review follow-up). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Babysit worker (login Validated each observation against the head-branch code at
Finding 2's test was a test-only addition (no behavior change), so no further version/CHANGELOG bump. Head is now |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a9c991370
ℹ️ 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".
…uthor filter Autopilot and explicitly widened babysit runs drop `--author`, so `resolve_authors(None)` returns an empty list and `ClassifyConfig.self_logins` derived from it was empty too. The self-login exclusion at babysit_delta.py 364/407/667 then filtered nothing, letting the worker's own classification and follow-up comments re-fire `new_human_blocking_feedback` every widened cycle — the exact self-dispatch loop this PR set out to close, still open on that path. Resolve the authenticated posting identity (`@me`) independently and union it into a dedicated `resolved_self_logins` carrier, leaving the discovery `authors` list untouched so autopilot still sweeps every author. Test at the config layer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…login-exclusion # Conflicts: # plugins/source-control/CHANGELOG.md
|
Claude finished @kyle-sexton's task in 3m 39s —— View job PR Review — fix(source-control): exclude self-login from babysit new_human_blocking_feedback
The fix is correct and the Codex P1 finding (autopilot/widened discovery drops Core filter logic (
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ddfd248f4f
ℹ️ 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".
The comment-hygiene CI check flags issue references embedded in code comments (tracker coupling drifts). The per-test comment repeated the issue number the class docstring already anchors; remove it from the inline comment. Behavior and assertions unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 5m 25s —— View job PR Review — fix(source-control): exclude self-login from babysit new_human_blocking_feedback
Core engine fix (
|
|
Babysit worker (login Conflict resolved. Merged Version slot reassigned → CI hygiene fix ( No new reviewer findings this round; prior threads remain addressed. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a64efe1687
ℹ️ 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".
…gs for babysit snapshot (#882) ## Summary Fixes #511. The babysit PR-queue snapshot derived `self_logins` — the posting identities whose comments self-classification suppresses — from the `--author` discovery filter, conflating two distinct concerns (*which authors' PRs to discover* vs *whose comments to suppress*). That broke in both directions: - **Under-inclusion:** configured extra self identities (`babysit_self_logins`) rode on `--author`, so when autopilot widening drops `--author` entirely, a bot poster's own comments re-fired `new_human_blocking_feedback` every cycle. - **Over-inclusion:** a `--queue --author alice` run authenticated as a different login made `alice` a self-login, suppressing Alice's genuine feedback from the worker-dispatch arm. ## The fix `pr_queue_snapshot.py` now resolves self-identity from dedicated **`--self`** (full override — exactly the given logins, `@me` not added) / **`--extra-self`** (added on top of the authenticated `@me`) flags, mirroring the existing `babysit-readiness-gate.sh` semantics, resolved **independently of `--author`** and before the `--pr`/`--queue` scope split (so single-PR scope is covered too). This supersedes the `@me`-only union added in #494, and the author-derived self fallback in `build_config` is removed so **no discovery author can leak into the self set** in any path. The skill's step-4 invocation and the `babysit_self_logins` userConfig table row now route the configured extras through `--extra-self` instead 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) - Added `SelfIdentityDecouplingTests` asserting both directions at the `build_snapshot` level (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.** - The `resolve_self_logins` unit tests pinned the *old* author-union contract; they are rewritten to the new flag-based contract, and `test_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_unresolved` becomes `test_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 via `engine.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 #860/#839 pass skill-quality-gate), and this change adds zero new ruff errors (32 before == 32 after). - `markdownlint-cli2` on the changed docs — clean; `plugin.json` valid. - Independent fresh-context code review (producer ≠ reviewer). ## Version Per-plugin bump **0.15.9 → 0.16.0** (minor — new `--self`/`--extra-self` CLI surface alongside the behavior fix). `marketplace.json` pins no version for `source-control`, so only `plugin.json` changes. Closes #511 ## Related - #497 — single-`--pr` scope leaves `self_logins` empty (sibling facet of the same seam, triaged blocked-by #511). This change resolves self-identity for `--pr` scope too, but its acceptance is left for the #497 lane to verify — not closed here. - #494 — added the `@me`-only `--queue` union this supersedes. - #473 — engine-level self-filter (related self-dispatch symptom). - #881 — follow-up (filed): the snapshot raises on an unresolvable `@me` where the readiness gate degrades to the `--extra-self` set; tracks whether fail-loud is the intended contract. Surfaced in this PR's review. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
source-control:babysit-prsre-dispatched a worker onto its own prior-round output for a solo maintainer. Thepr_queue_snapshot.pydelta engine (babysit_delta.py) classified every non-bot comment as human feedback with no exclusion for the login the babysit worker posts under. When the PR author login == thegh authidentity == the configured self-login, the worker's own classification replies andFixed in <sha>follow-ups — each a fresh comment id — manufactured anew_human_blocking_feedbackdelta every next cycle. That arm is unsuppressible, so it re-fired forever (confirmed on PR #377, two consecutive cycles, zero real work).Fix
Filter items authored by the configured self-login(s) out of both new-human delta arms —
new_human_blocking_feedbackandnew_human_feedback— inclassify_pr.config.self_loginsalready exists onClassifyConfig, is threaded frompr_queue_snapshot.py's--authorresolution (@me→gh api user --jq .login, plusbabysit_self_loginsextras), and is already consumed bydetect_foreign_activityand the merge-gate self-exemption. The filter mirrors that module's{login.casefold() for login in config.self_logins if login}exactly. Emptyself_loginsis a no-op, preserving current behavior for unconfigured/test callers.reference/review-discipline.md§1 already mandates for the worker's own classification replies, and brings the human delta to parity with the bot arms — which are self-filtered structurally (the engine comments under a human login and never entersfeedback["blocking"]).collect_feedbackclassification. A self-authored item still classifies ashuman_blocking, sohuman_stop["required"]and the triage blocker stay intact — a genuine "do not merge, I found a problem" comment the maintainer posts under their own login still halts the merge gate. Filtering at classification instead would silently strip the solo maintainer's ability to human-stop their own PR (a strictly worse regression). The adjacenthuman_stop-persistence behavior for the worker's own reply is left as-is for that same safety reason; distinguishing a classification reply from a genuine self-block there would require content heuristics out of scope for this deterministic fix.reference/orchestration.md'snew_human_blocking_feedbackarm doc is updated to describe the exclusion, preventing drift.Scope: fixes the
--queuefleet-loop path (the reported reproduction)This closes #473 as scoped — a deterministic engine-level fix. It is live in the
--queuefleet-loop invocation the issue documents (PR #377 across cycles):pr_queue_snapshot.py's discovery branch resolves@me→ gh login and rebuildsClassifyConfigwithself_loginspopulated before classifying, so the filter has its input.Deliberately not bundled — tracked in #497: the single-
--prsnapshot path (/source-control:babysit-prs owner/repo#N) builds its config before author resolution and never rebuilds it, leavingconfig.self_loginsempty — so this filter is dormant there. That is a separate, pre-existing orchestrator seam gap, not an engine defect, and becauseself_loginsis the same fielddetect_foreign_activityreads, populating it in--prmode also activates foreign-activity detection there — a shared-seam behavior change with wider blast radius than this engine fix warrants. Filed as #497 with the fix direction and an integration-test caveat.Verification
scripts/engine.test.sh) — fullunittestdiscover, ruff, and the guarded-wrapper bash checks, all green:SelfLoginHumanFeedbackExclusionTestsintest_babysit_delta.py), all pass:test_self_login_reply_does_not_manufacture_dispatch— with a recent worker check-in (quiet-recheck fallback suppressed), a self-login blocking comment yields nonew_human_blocking_feedbackreason andneeds_workeris False.test_other_login_still_fires_under_same_config— the same config, a comment from another login, still firesnew_human_blocking_feedbackand dispatches (the filter is login-specific, not a blanket mute).test_self_login_item_is_still_classified_human_blocking— the self item stays infeedback["human_blocking"],human_stop["required"]is True, andpr_clean_ready_for_direct_gateis False (locks in the deliberate scope: the halt is respected, only the dispatch is suppressed).test_self_login_match_is_case_insensitive— a differently-cased self login is still recognized.markdownlint-cli2(CHANGELOG.md, orchestration.md):0 issues;typos(all changed files): exit 0.Related
Closes #473
--prsnapshot mode leavesself_loginsempty (self-filter + foreign-activity dormant) #497 — single---prmode leavesself_loginsempty (pre-existing orchestrator gap; deliberately not bundled here).config.self_logins/babysit_self_loginsseam anddetect_foreign_activityself-filter introduced in the babysit-prs engine convergence (feat(source-control): converge babysit-prs tiers + engine (0.8.0) #322).🤖 Generated with Claude Code