Skip to content

feat: auto-assign issue to current user during lifecycle start#1167

Merged
stack72 merged 1 commit intomainfrom
worktree-shiny-floating-robin
Apr 12, 2026
Merged

feat: auto-assign issue to current user during lifecycle start#1167
stack72 merged 1 commit intomainfrom
worktree-shiny-floating-robin

Conversation

@stack72
Copy link
Copy Markdown
Contributor

@stack72 stack72 commented Apr 12, 2026

Summary

  • Wire auto-assignment into the start() method of the @swamp/issue-lifecycle extension model
  • When triage begins, reads the current user's username from local auth (~/.config/swamp/auth.json), resolves it to a userId via the eligible-assignees endpoint, and PATCHes the issue's assignees additively
  • All assignment failures are best-effort warnings — the triage flow never breaks
  • Bumps model version to 2026.04.12.1

Changes

  • extensions/models/_lib/swamp_club.ts: Export loadAuthFile (now returns optional username); add fetchEligibleAssignees(), resolveUserId(), updateAssignees() to SwampClubClient; extend FetchedIssue with assignees field
  • extensions/models/issue_lifecycle.ts: Wire assignment block into start() after context/state writes; add version upgrade entry
  • extensions/models/issue_lifecycle_test.ts: 6 new unit tests with fetch stub infrastructure covering happy path, additive merge, idempotent, missing username, 403 on lookup, PATCH failure
  • extensions/models/README.md: Update start description in methods table
  • .claude/skills/issue-lifecycle/references/triage.md: Add auto-assignment documentation section

Test Plan

  • All 28 extension model tests pass (6 new + 22 existing)
  • Full test suite: 4292 passed, 0 failed
  • deno check — clean
  • deno lint — clean
  • deno fmt — clean
  • deno run compile — binary built
  • Changes synced to systeminit/swamp-extensions and systeminit/swamp-club

Closes swamp-club#86

🤖 Generated with Claude Code

When `start` is called on an issue-lifecycle model, the method now
reads the authenticated username from local auth (~/.config/swamp/auth.json),
resolves it to a userId via the swamp-club eligible-assignees endpoint,
and PATCHes the issue's assignees additively. All assignment failures
are best-effort warnings — the triage flow never breaks.

Changes:
- Export `loadAuthFile` from swamp_club.ts, now returns optional `username`
- Add `fetchEligibleAssignees`, `resolveUserId`, `updateAssignees` to
  SwampClubClient
- Extend `FetchedIssue` with `assignees` field
- Wire assignment into `start()` after context/state writes
- Bump model version to 2026.04.12.1
- 6 new unit tests covering happy path, additive merge, idempotent,
  missing username, 403 on lookup, PATCH failure

Closes swamp-club#86

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
stack72 added a commit to systeminit/swamp-extensions that referenced this pull request Apr 12, 2026
Sync from systeminit/swamp#1167. When `start` is called, the method
reads the authenticated username from local auth, resolves it to a
userId via the eligible-assignees endpoint, and PATCHes the issue's
assignees additively. All assignment failures are best-effort warnings.

Bumps model version to 2026.04.12.1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Blocking Issues

None.

Suggestions

  1. Double loadAuthFile() call (issue_lifecycle.ts:493): During start(), loadAuthFile() is called twice — once internally by createSwampClubClient() (for apiKey/serverUrl) and once directly by start() (for username). A future cleanup could have createSwampClubClient return the username alongside the client, or have the client store it. Not blocking since it's a minor I/O redundancy on a local file.

Notes

  • DDD: SwampClubClient is the right home for fetchEligibleAssignees/resolveUserId/updateAssignees — it stays within its infrastructure service responsibility. EligibleAssignee is a clean value object. The orchestration in start() keeps assignment as a best-effort side effect after the core lifecycle transition, which is the correct application-layer pattern.
  • CLAUDE.md compliance: No any types, all promises awaited, AbortSignal.timeout on every outbound call, license headers present, named exports used. No libswamp import boundary violations (extensions don't import from src/libswamp).
  • Test coverage: 6 new tests cover the key paths well — happy path, additive merge, idempotency, missing username, 403 on lookup, and PATCH failure. The fetch stub infrastructure is clean and reusable.
  • Security: API key stays in the private #apiKey field, auth file is read from the well-known XDG/HOME config path, no user input is interpolated into sensitive contexts.

@stack72 stack72 merged commit 78d2b36 into main Apr 12, 2026
10 checks passed
@stack72 stack72 deleted the worktree-shiny-floating-robin branch April 12, 2026 00:05
stack72 added a commit to systeminit/swamp-extensions that referenced this pull request Apr 12, 2026
…#65)

Sync from systeminit/swamp#1167. When `start` is called, the method
reads the authenticated username from local auth, resolves it to a
userId via the eligible-assignees endpoint, and PATCHes the issue's
assignees additively. All assignment failures are best-effort warnings.

Bumps model version to 2026.04.12.1.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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