Skip to content

feat(qa): auto-expire + test fix (v1.2.55)#18

Merged
topcoder1 merged 3 commits into
mainfrom
qa-autoexpire-and-mcp-fix
Apr 20, 2026
Merged

feat(qa): auto-expire + test fix (v1.2.55)#18
topcoder1 merged 3 commits into
mainfrom
qa-autoexpire-and-mcp-fix

Conversation

@topcoder1

Copy link
Copy Markdown
Owner

Summary

Two tasks, small diff:

1. test(mcp-bridge) — fix mock path mismatch (cd69566)

Mock was @ai-sdk/mcp/stdio, source imports @ai-sdk/mcp/mcp-stdio. Mismatched path → mock never applied → vitest tried to resolve for real → 4 tests failed on every host build (the dep lives in container/agent-runner/package.json, not root). One-line fix.

2. feat(qa) — auto-expire stuck proposals after 48h (97900a2)

Three QA proposals had been sitting in Telegram for up to 9 hours, each pinning a stale worktree + branch. This adds a cron that cleans them up.

  • QaProposal gets expiresAt + 'expired' resolution, with shared QA_PROPOSAL_TTL_MS = 48h. Producer stamps expiresAt = createdAt + TTL on new proposals.
  • scripts/qa/expire-proposals.ts — scans data/qa-proposals/*.json, expires unresolved ones past their TTL, removes worktree + local + remote branch, marks resolution: 'expired'. Posts a Telegram digest summarizing what was cleaned up. Idempotent. Supports QA_EXPIRE_DRY_RUN=1 and QA_EXPIRE_DISABLED=1.
  • Legacy proposals without expiresAt derive one from createdAt + TTL so pre-upgrade records don't linger.
  • scripts/qa/com.nanoclaw.qa-expire-proposals.plist — launchd agent, StartInterval=3600 (hourly). Install with cp scripts/qa/com.nanoclaw.qa-expire-proposals.plist ~/Library/LaunchAgents/ && launchctl load ~/Library/LaunchAgents/com.nanoclaw.qa-expire-proposals.plist.
  • resolutionLabel in qa-approval.ts shows expired ⏰ for auto-cleaned proposals.

Test plan

  • npm run build clean at v1.2.55
  • npx vitest run src/llm/mcp-bridge.test.ts — 4/4 pass (was 0/4)
  • Integration test of expire script: synthetic proposal with expiresAt: 0 → expired correctly. Second run = scanned=1 expired=0 (idempotent).
  • Dry-run mode respects QA_EXPIRE_DRY_RUN=1.

Known pre-existing follow-up

src/index.test.ts fails to load because its vi.mock('./channels/registry.js') doesn't export registerChannel — an issue that predates this PR. Full suite: 1611/1611 individual tests pass; only the module-load error remains. Small separate PR worth doing.

🤖 Generated with Claude Code

topcoder1 and others added 3 commits April 19, 2026 18:16
The test was mocking `@ai-sdk/mcp/stdio` but the source imports from
`@ai-sdk/mcp/mcp-stdio`. Path mismatch meant the mock never applied and
vitest tried to resolve the real subpath — which isn't in the root
node_modules (the dep lives in container/agent-runner/package.json) —
failing all 4 tests in the file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QA autopilot proposals that never got [✓ Merge] or [✕ Close] tapped
were piling up indefinitely — three were sitting in the chat for 9-48h
before this landed, each pinning a stale worktree + branch.

- Add `expiresAt` field + `'expired'` resolution to QaProposal, with a
  shared QA_PROPOSAL_TTL_MS constant (48h). Producer now stamps
  expiresAt = createdAt + TTL on every new proposal.
- scripts/qa/expire-proposals.ts — scans data/qa-proposals/*.json,
  finds unresolved proposals past their expiry, removes the worktree +
  local branch + (if pushed) the remote branch, marks the record
  `resolution: 'expired'`, and posts a Telegram digest summarizing
  what was cleaned up. Idempotent: resolved proposals are skipped on
  subsequent runs. Supports QA_EXPIRE_DRY_RUN=1 for observation-only
  runs and QA_EXPIRE_DISABLED=1 for maintenance windows.
- Legacy proposals missing `expiresAt` derive one from createdAt + TTL
  so pre-upgrade records don't linger.
- com.nanoclaw.qa-expire-proposals.plist — launchd agent that runs
  `npm run qa:expire-proposals` every 3600s (install with
  `launchctl load`, same pattern as qa-monitor).
- Consumer `resolutionLabel` in qa-approval.ts shows `expired ⏰`
  when a proposal got cleaned up by the cron.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@topcoder1 topcoder1 merged commit a8175b4 into main Apr 20, 2026
@topcoder1 topcoder1 deleted the qa-autoexpire-and-mcp-fix branch April 20, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant