Intent: an agent refused by the forge reads why and what to do instead.
Today: a planner's PATCH …/issues/N {"state":"closed","reason":"done"} without an "already done on main" note answers 403 "your credentials lack the scope for this action" (handedToPlanner in src/actions/issues.ts returns only false). The same message comes for a drop of a person's ask and a split into issues that are too old.
Done:
Each refusal in the planner's close path answers 403 forbidden with a message naming its rule: done needs an "already done on main" note naming commits on main; dropped is refused because a person's ask stands in it (split, replace or defer); split needs open issues opened after <time>; any other close is not the planner's.
Scope refusals that are really about the token keep today's message.
The OpenAPI route file for PATCH issues lists the new messages.
A test per rule asserts its message.
Files: src/actions/issues.ts, src/http/api.ts, src/contract/openapi/routes for the PATCH, tests.
Intent: an agent refused by the forge reads why and what to do instead.
Today: a planner's PATCH …/issues/N {"state":"closed","reason":"done"} without an "already done on main" note answers 403 "your credentials lack the scope for this action" (
handedToPlannerin src/actions/issues.ts returns only false). The same message comes for a drop of a person's ask and a split into issues that are too old.Done:
forbiddenwith a message naming its rule: done needs an "already done on main" note naming commits on main; dropped is refused because a person's ask stands in it (split, replace or defer); split needs open issues opened after <time>; any other close is not the planner's.Files: src/actions/issues.ts, src/http/api.ts, src/contract/openapi/routes for the PATCH, tests.