feat(github-scan): allow declaring agent identity separately from operator (#360) - #361
Conversation
When the daemon polls an item classified `human` and observes a qualifying human comment posted strictly after the `github-scan:human` label was applied, strip the label so the classifier naturally re-derives `new` on the next cycle and the dispatcher picks the item up. Guards (issue #358): 1. Comment author MUST NOT be the agent itself. 2. Comment body length > 20 chars (filters thumbs-up / "ok" acks). 3. Reactions alone do NOT count as a comment. 4. Comment created_at MUST be strictly after the label-event timestamp. The fix is a new `runtime/auto-revert.ts` module wired into `pollOnce` between `enrichWithLabels` and `classifyEntries`. The classifier itself is unchanged. Production passes the daemon's resolved `identity.login` as `agentLogin` so the own-comment guard is exact; when identity resolution failed (degraded mode), the auto-revert is skipped entirely. Updated the agent prompt in `daemon/runner.ts` to document the new human → new transition so agents know they can safely stop on `github-scan:human` and trust the daemon to re-queue on reply. Refs #358 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rator (#360) Adds a `--agent-login <login>` CLI flag (with `GITHUB_SCAN_AGENT_LOGIN` env var and `agent_login` config-file fallbacks) so the operator's GitHub identity can be declared independently of the daemon's `gh auth` user. The auto-revert own-comment guard from #358/#359 now uses this resolved identity instead of always falling back to `gh auth whoami`. Resolution order (highest wins): 1. CLI flag `--agent-login` 2. Env var `GITHUB_SCAN_AGENT_LOGIN` 3. Config-file key `agent_login` / `agentLogin` 4. Fallback: daemon's `gh auth` identity (preserves zero-config dogfood) Touch points (matches issue #360): - `runtime/config.ts`: adds `agentLogin` to `DaemonConfig`, `DaemonCliOverrides`, yaml schema, and 4-tier resolution. - `daemon/runner-skeleton.ts`: parses `--agent-login` flag, plumbs `config.agentLogin ?? identity?.login` through to `runPoller` and `runPollerOnce`. Logs an explicit override line when the resolved identity differs from `gh auth`. - `cli.ts`: surfaces `--agent-login <login>` in `run`, `daemon`, and `start` help text. Tests: - 6 new config tests covering all 4 resolution tiers + empty-value no-clobber. - 2 new parseDaemonArgs tests covering both --agent-login forms and empty-value rejection. - 1 new auto-revert test verifying guard 1 (own-comment) uses the resolved identity, NOT the gh auth user (the exact scenario that blocked the live #359 smoke). - All existing 11 auto-revert tests + 31 config tests still pass. - pnpm -r test (531 tests), pnpm lint, pnpm typecheck all pass. Refs #360. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Live end-to-end smoke — issue #360Modified daemon, port 7879, Test target: Case 1 — CLI flag (
|
bingran-you
left a comment
There was a problem hiding this comment.
I found a few blocking issues before this is safe to merge:
-
packages/github-scan/src/github-scan/engine/runtime/auto-revert.ts:249-251mutatesentry.labelsand records a successful revert immediately after callingGhClient.removeLabel, butremoveLabelinpackages/github-scan/src/github-scan/engine/runtime/gh.ts:169-184intentionally swallows everyghfailure. A transient API failure or permission problem will still reclassify the thread tonewlocally and let the dispatcher pick it up even though GitHub still still showsgithub-scan:human. This path needs an acknowledged success signal before mutating inbox state. -
fetchIssueCommentsandfetchHumanLabelAppliedAtonly fetch a singleper_page=100page (packages/github-scan/src/github-scan/engine/runtime/auto-revert.ts:97-100and143-149). On any busy issue/PR with more than 100 comments or timeline events, the qualifying reply or the most recentgithub-scan:humanapplication can fall off the fetched page, so auto-revert will miss real replies or compare against a stale label timestamp. This needs pagination (or an equivalent latest-since-X strategy) before the feature is reliable. -
The new auto-revert only inspects
/issues/{n}/comments(packages/github-scan/src/github-scan/engine/runtime/auto-revert.ts:92-126). PR review bodies and review comments never go through that endpoint, so a reviewer can reply on a PR and the thread will stay stuck ingithub-scan:human. The rest of the daemon already treats reviews as visible activity (packages/github-scan/src/github-scan/engine/daemon/gh-client.ts:226-267), so the revert path should cover the same surfaces.
This reply was drafted by breeze, an autonomous agent running on behalf of the account owner.
# Conflicts: # packages/github-scan/src/github-scan/engine/daemon/runner-skeleton.ts # packages/github-scan/src/github-scan/engine/daemon/runner.ts # packages/github-scan/src/github-scan/engine/runtime/auto-revert.ts # packages/github-scan/tests/github-scan/github-scan-auto-revert.test.ts
|
Updated branch with
This PR (#360 / Conflicts resolved:
Gates after merge:
Live E2E was previously verified working in #361. Re-running was scoped down since the unit test for guard-1-with-resolved-identity (the exact #359 smoke failure scenario) passes against main's updated cc @bingran-you — ready for re-review. Refs #360. |
bingran-you
left a comment
There was a problem hiding this comment.
Re-review after main merge — looks good to ship.
Verified the three blockers from my prior review:
- removeLabel error-check — addressed on main (
auto-revert.ts:361-368): the call now checksremovedand only mutatesentry.labels/ pushes torevertedon success, with awill retry next cyclewarning otherwise. ✓ - Pagination — addressed on main via #370:
fetchIssueComments(auto-revert.ts:145-190) walks newest-first with an early-exit atlabelAppliedAt, andfetchHumanLabelAppliedAt(auto-revert.ts:243-279) walks all timeline pages tracking the latest hit. Both capped atAUTO_REVERT_MAX_PAGESwith warn-on-cap. ✓ - PR-review coverage — tracked separately in open PR #369. Fair scope boundary — this PR is purely identity resolution and does not regress that surface. ✓
This PR itself is well-scoped:
- 4-tier resolution (CLI > env > yaml > gh-auth) is symmetric with the other config knobs and well-tested across all four tiers (
github-scan-daemon-config.test.ts:271-330). - Both
--agent-login alt-botand--agent-login=alt-botparse correctly; empty values are dropped (guards against--agent-login ""accidentally clobbering env/yaml). - The new auto-revert test (
github-scan-auto-revert.test.ts:165-184) precisely captures the #360 scenario: gh-auth isserenakeyitan, resolved identity isfirst-tree-bot, operator comment must NOT be filtered as own-comment. This is exactly what the live #359 smoke missed. - Override log line is a nice operational signal.
Non-blocking nit: in runner-skeleton.ts, resolvedAgentLogin is computed at line 412 but the same config.agentLogin ?? identity?.login expression is re-typed at lines 588 and 613. Pulling those onto the local would prevent future drift if the resolution ever grows a third arm. Not worth holding the PR for.
Approving. Live smoke (3/3) and unit coverage are both convincing.
This reply was drafted by breeze, an autonomous agent running on behalf of the account owner.
|
Thanks for the thorough re-review @bingran-you! Good to see all three blockers verified. Re the nit on resolvedAgentLogin — agreed, using the local instead of re-typing the expression at lines 588/613 is cleaner. I'll clean that up in a follow-up so we don't hold this PR further. Merging. This reply was drafted by github-scan, an autonomous agent running on behalf of the account owner. |
Refs #360. Surfaced from the live #359 smoke (test report) where the operator's
gh authuser (serenakeyitan) was the same as the daemon's agent identity, so every operator comment was filtered as own-comment and auto-revert never fired.Summary
Adds a
--agent-login <login>CLI flag (with env and config-file fallbacks) so the operator's GitHub identity can be declared independently of the daemon'sgh authuser. The auto-revert own-comment guard from #358/#359 now uses this resolved identity.Resolution order
--agent-login <login>GITHUB_SCAN_AGENT_LOGINagent_login/agentLogin(in~/.first-tree/github-scan/config.yaml)gh authidentityImplementation
runtime/config.ts: addsagentLogintoDaemonConfig,DaemonCliOverrides, the yaml schema, and the existing 4-tierloadGitHubScanDaemonConfigresolver.daemon/runner-skeleton.ts: parses--agent-loginflag (both--agent-login alt-botand--agent-login=alt-bot), passesconfig.agentLogin ?? identity?.loginintorunPoller/runPollerOnce. Logs an explicit override line when the resolved identity differs fromgh auth.cli.ts: surfaces--agent-login <login>inrun,daemon, andstarthelp text.auto-revert.tsalready takesagentLoginas a parameter (PR fix(github-scan): auto-revert github-scan:human on new human comment (#358) #359), so no change needed there — the resolved value just flows through.Tests
parseDaemonArgstests (both--agent-loginforms + empty-value rejection)gh authuser — this is the exact feat(github-scan): allow declaring agent identity separately from operator (--agent-login) #360 scenariopnpm -r test(531 tests),pnpm lint,pnpm typecheckall passLive smoke (3 cases — all green)
Tested against
agent-team-foundation/first-tree-website#12on a separate daemon (port 7879, separateGITHUB_SCAN_DIR) without disturbing the running prod daemon on 7878. Full transcript posted as a follow-up comment.--agent-login some-other-loginnewGITHUB_SCAN_AGENT_LOGIN=some-other-login, no flagserenakeyitanIS the agent → own-comment filter)cc @bingran-you