P4-3: the write path — apply estimate/priority changes to gitea (apply_changes) #41

Merged
christian merged 1 commits from p4/apply-changes into main 2026-07-09 00:25:26 +00:00
Owner

The first write path. Read, forecast, and calibration were all real — now you can manage CommiTea from CommiTea. Estimates/priority are exclusive label axes, so a change is a label swap: proposed, approved, then written. Nothing assumed. (Branch cut from main, targets main — no stacking, per the lesson from the #38/#39 gap.)

Core (@commitea/core)

  • planIssueChange(current, change) — pure diff planner: swaps the est/*|p/* axis, clears on null, dedups a doubled axis; returns the resulting label set + before/after diff + noop. describeChange()est/2d → est/5d.
  • request() seam extended for writes (method/body, JSON, 204). Client gains listLabels() (name→id) and setIssueLabels() (PUT /issues/{n}/labels).

App

  • main bridge gitea:applyChange — resolves plan.labels → ids (cached, refetch on miss), PUTs, returns the plan + fresh issue. Token never leaves main.
  • preload + global.d.ts expose applyChange; useBacklog returns a refetch so a write re-reconciles the board + forecast.
  • Issue screen — an Adjust button (only when configured) opens a propose-approve Dialog: estimate/priority pickers, live est/3d → est/8d consequence, Apply/Cancel. AppShell wires it, reflects the new labels on the open issue immediately, and refetches.

Verified

83 core tests green (7 apply-changes + 2 client-write new) · desktop typecheck clean · 14 fixture e2e green.

The live spec exercises propose + Cancel (so CI never mutates the real repo); the actual PUT was verified once manually — changed #2 est/3d → est/8d (200 OK), confirmed, then reverted clean. Screenshot: the dialog on real issue #2.

Not in this slice (later)

  • The write path currently surfaces as a direct control; routing it through Reginald's chat (apply_changes as an LLM tool call, with the same engine) is the agent-integration slice.
  • capture_work (create issue) and record_directive (append to the pm-state ledger) are the other two write tools.

🤖 Generated with Claude Code

The **first write path**. Read, forecast, and calibration were all real — now you can *manage* CommiTea from CommiTea. Estimates/priority are exclusive label axes, so a change is a label swap: **proposed, approved, then written. Nothing assumed.** (Branch cut from `main`, targets `main` — no stacking, per the lesson from the #38/#39 gap.) ## Core (`@commitea/core`) - **`planIssueChange(current, change)`** — pure diff planner: swaps the `est/*`|`p/*` axis, clears on null, dedups a doubled axis; returns the resulting label set + before/after diff + `noop`. `describeChange()` → `est/2d → est/5d`. - `request()` seam extended for writes (method/body, JSON, 204). Client gains `listLabels()` (name→id) and `setIssueLabels()` (`PUT /issues/{n}/labels`). ## App - **main bridge `gitea:applyChange`** — resolves `plan.labels` → ids (cached, refetch on miss), PUTs, returns the plan + fresh issue. **Token never leaves main.** - preload + `global.d.ts` expose `applyChange`; `useBacklog` returns a `refetch` so a write re-reconciles the board + forecast. - **Issue screen** — an *Adjust* button (only when configured) opens a propose-approve **Dialog**: estimate/priority pickers, live `est/3d → est/8d` consequence, Apply/Cancel. AppShell wires it, reflects the new labels on the open issue immediately, and refetches. ## Verified 83 core tests green (7 `apply-changes` + 2 client-write new) · desktop typecheck clean · 14 fixture e2e green. The live spec exercises **propose + Cancel** (so CI never mutates the real repo); the actual PUT was verified once manually — changed #2 `est/3d → est/8d` (200 OK), confirmed, then reverted clean. Screenshot: the dialog on real issue #2. ## Not in this slice (later) - The write path currently surfaces as a **direct control**; routing it through Reginald's chat (`apply_changes` as an LLM tool call, with the same engine) is the agent-integration slice. - `capture_work` (create issue) and `record_directive` (append to the pm-state ledger) are the other two write tools. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
christian added 1 commit 2026-07-09 00:15:06 +00:00
The first write path. Read, forecast, and calibration were all real; now you can
*manage* CommiTea from CommiTea. Estimates/priority are exclusive label axes, so
a change is a label swap — proposed, approved, then written. Nothing is assumed.

core (@commitea/core):
- planIssueChange(current, change): pure diff planner — swaps the est/*|p/* axis,
  clears on null, dedups a doubled axis; returns the resulting label set + a
  before/after diff + noop flag. describeChange() renders "est/2d → est/5d".
- request() seam extended for writes (method/body, JSON, 204). client gains
  listLabels() (name→id) and setIssueLabels() (PUT /issues/{n}/labels).

app:
- main bridge gitea:applyChange — resolves plan.labels → ids (cached, refetch on
  miss), PUTs, returns the plan + fresh issue. Token never leaves main.
- preload + global.d.ts expose applyChange; useBacklog returns a refetch so a
  write re-reconciles the board + forecast.
- Issue screen: an Adjust button (shown only when configured) opens a
  propose-approve Dialog — estimate/priority pickers, live "est/3d → est/8d"
  consequence, Apply/Cancel. AppShell wires it, reflects new labels on the open
  issue immediately, and refetches.

Verified: 83 core tests green (7 apply-changes + 2 client-write new), desktop
typecheck clean, 14 fixture e2e green. Live spec exercises propose + CANCEL (no
mutation); the real PUT was verified once manually (change #2 est/3d→est/8d→200,
reverted clean). Icon: pencil (no sliders-horizontal in the set).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
christian merged commit e8bf71e970 into main 2026-07-09 00:25:26 +00:00
Sign in to join this conversation.
No description provided.