Completes #24 — the propose-approve write path goes from label-only (est/p) to a unified mutation tool covering estimate, priority, assignee, and milestone, wired end-to-end: pure model → gitea client → bridge → in-app dialog + Reginald's tool. Assignee/milestone are exactly the gaps the dogfood run surfaced.
Engine (commit 1)
IssueChange gains assign + remilestone; planIssueChange typed to label kinds; isLabelChange narrows; pure summarizeChange gives one confirm line for any kind.
propose_change tool + system prompt accept assignee/milestone; proposalsFor + new ProposalContext skip no-ops and label the milestone; ChangeProposal.summary (always present) drives the chat proposal cards.
Client listCollaborators()prepends the repo owner (/collaborators omits them — a solo-owner repo would otherwise have nobody assignable). New gitea:collaborators bridge.
The issue Adjust dialog gains Assignee + Milestone pickers (current values from the reconciled backlog); pending changes flow through the existing apply path.
live-backlog e2e now drives the pickers on real gitea (owner prepended, unassign diff renders). Fixed stale P2 assertions there (P2 is shipped → correctly off the runway).
Base
Off main; touches issue-screen.tsx + global.d.ts, which PR #52 also edits in different regions — small rebase expected once #52 lands.
Completes **#24** — the propose-approve write path goes from label-only (est/p) to a **unified mutation tool** covering estimate, priority, **assignee**, and **milestone**, wired end-to-end: pure model → gitea client → bridge → **in-app dialog + Reginald's tool**. Assignee/milestone are exactly the gaps the dogfood run surfaced.
## Engine (commit 1)
- `IssueChange` gains `assign` + `remilestone`; `planIssueChange` typed to label kinds; `isLabelChange` narrows; pure `summarizeChange` gives one confirm line for any kind.
- Client `setIssueAssignees` / `setIssueMilestone`; `gitea:applyChange` branches label-swap vs field-write; `ApplyChangeResult.plan` optional.
## In-app + agent (commit 2)
- `propose_change` tool + system prompt accept `assignee`/`milestone`; `proposalsFor` + new `ProposalContext` skip no-ops and label the milestone; `ChangeProposal.summary` (always present) drives the chat proposal cards.
- Client `listCollaborators()` **prepends the repo owner** (`/collaborators` omits them — a solo-owner repo would otherwise have nobody assignable). New `gitea:collaborators` bridge.
- The issue **Adjust dialog** gains Assignee + Milestone pickers (current values from the reconciled backlog); pending changes flow through the existing apply path.
## Tests / verification
- +9 core tests (assign/milestone proposals with no-op skip; collaborators owner-prepend). **138 core green**; core + desktop typecheck clean; **14 fixture e2e** green.
- **live-backlog** e2e now drives the pickers on real gitea (owner prepended, unassign diff renders). Fixed stale P2 assertions there (P2 is shipped → correctly off the runway).
## Base
Off `main`; touches `issue-screen.tsx` + `global.d.ts`, which PR #52 also edits in different regions — small rebase expected once #52 lands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
christian
added 1 commit 2026-07-09 15:31:43 +00:00
The write path handled only the est/* and p/* label axes. Extend it to the two
mutations dogfooding proved were missing — assignee and milestone — behind one
unified change model:
- IssueChange gains `assign` and `remilestone` kinds. `planIssueChange` is now
typed to LabelChange (the label kinds only); `isLabelChange` narrows, and a new
pure `summarizeChange(change, currentLabels?)` gives one confirm line for ANY
kind (label kinds delegate to describeChange; field writes describe directly).
- GiteaClient gains `setIssueAssignees` / `setIssueMilestone` (PATCH /issues/{n},
returning the updated issue; milestone 0 clears).
- The main `gitea:applyChange` handler branches: label swaps resolve ids +
setIssueLabels as before; field writes call the new client methods. Snapshot
invalidated either way so board + forecast catch up. ApplyChangeResult.plan is
now optional (absent for field writes).
- issue-screen uses summarizeChange for its diff preview.
Tests: +5 covering isLabelChange, and summarizeChange for assign/unassign,
milestone set-by-title / by-id / removal, and label delegation. Full core suite
132 green; core + desktop typecheck clean.
Follow-up (rest of #24): surface assignee/milestone pickers in the Adjust dialog
and extend the agent's propose_change tool so Reginald can propose them too.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
christian
added 1 commit 2026-07-09 15:54:06 +00:00
Surfaces the assign/milestone mutations end-to-end so they're usable in-app and
by the agent — the rest of #24.
Agent path:
- propose_change tool + system prompt now accept `assignee` (login/null) and
`milestone` (id/null). ProposeChangeArgs + proposalsFor extended: a new
ProposalContext (current assignee/milestone + milestones list) lets a proposal
skip no-ops and label the milestone. ChangeProposal gains an always-present
`summary` (plan is now label-only) — chat-panel, use-chat, and the model
executor render `summary`, so non-label proposals display correctly.
Dialog path:
- Client `listCollaborators()` (prepends the repo owner — /collaborators omits
them, so a solo-owner repo still has an assignable person). New
`gitea:collaborators` bridge. The Adjust dialog gains Assignee + Milestone
pickers (current values from the reconciled backlog); pending assign/remilestone
changes flow through the existing apply path.
Tests: +4 core (assign/milestone proposals with no-op skip; collaborators
owner-prepend + no-double-add). 138 core green; core + desktop typecheck clean;
14 fixture e2e green; live-backlog now drives the pickers on real data.
Fixed stale P2 refs in live-backlog (P2 is shipped → correctly off the runway).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
christian
changed title from apply_changes: unify the mutation tool with assign + milestone (#24) to apply_changes: unified mutation tool — estimate/priority/assign/milestone, in-app + agent (#24)2026-07-09 15:54:26 +00:00
christian
added 1 commit 2026-07-09 19:23:46 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Completes #24 — the propose-approve write path goes from label-only (est/p) to a unified mutation tool covering estimate, priority, assignee, and milestone, wired end-to-end: pure model → gitea client → bridge → in-app dialog + Reginald's tool. Assignee/milestone are exactly the gaps the dogfood run surfaced.
Engine (commit 1)
IssueChangegainsassign+remilestone;planIssueChangetyped to label kinds;isLabelChangenarrows; puresummarizeChangegives one confirm line for any kind.setIssueAssignees/setIssueMilestone;gitea:applyChangebranches label-swap vs field-write;ApplyChangeResult.planoptional.In-app + agent (commit 2)
propose_changetool + system prompt acceptassignee/milestone;proposalsFor+ newProposalContextskip no-ops and label the milestone;ChangeProposal.summary(always present) drives the chat proposal cards.listCollaborators()prepends the repo owner (/collaboratorsomits them — a solo-owner repo would otherwise have nobody assignable). Newgitea:collaboratorsbridge.Tests / verification
Base
Off
main; touchesissue-screen.tsx+global.d.ts, which PR #52 also edits in different regions — small rebase expected once #52 lands.🤖 Generated with Claude Code
The write path handled only the est/* and p/* label axes. Extend it to the two mutations dogfooding proved were missing — assignee and milestone — behind one unified change model: - IssueChange gains `assign` and `remilestone` kinds. `planIssueChange` is now typed to LabelChange (the label kinds only); `isLabelChange` narrows, and a new pure `summarizeChange(change, currentLabels?)` gives one confirm line for ANY kind (label kinds delegate to describeChange; field writes describe directly). - GiteaClient gains `setIssueAssignees` / `setIssueMilestone` (PATCH /issues/{n}, returning the updated issue; milestone 0 clears). - The main `gitea:applyChange` handler branches: label swaps resolve ids + setIssueLabels as before; field writes call the new client methods. Snapshot invalidated either way so board + forecast catch up. ApplyChangeResult.plan is now optional (absent for field writes). - issue-screen uses summarizeChange for its diff preview. Tests: +5 covering isLabelChange, and summarizeChange for assign/unassign, milestone set-by-title / by-id / removal, and label delegation. Full core suite 132 green; core + desktop typecheck clean. Follow-up (rest of #24): surface assignee/milestone pickers in the Adjust dialog and extend the agent's propose_change tool so Reginald can propose them too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>apply_changes: unify the mutation tool with assign + milestone (#24)to apply_changes: unified mutation tool — estimate/priority/assign/milestone, in-app + agent (#24)