feat: reconcile granted ops run closes
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a06bfe-2a55-7ed3-bacd-879977b099bf
This commit is contained in:
parent
b72fdb5452
commit
b63131e863
21 changed files with 1240 additions and 43 deletions
|
|
@ -29,7 +29,9 @@ workplan task file. Not an issue-core or Forgejo ticket.
|
|||
| `approach_hint` | text nullable | **Legacy** definition-matching hint (ACT-ADR-006) |
|
||||
| `harness_profile_ref` | text nullable | Authoritative execution selector, pinned `<id>@<version>` |
|
||||
| `execution_refs` | jsonb | Attribution refs carried through, not authored here |
|
||||
| `repository_grant` | jsonb nullable | Separately typed repository mutation authority; never inferred or stored in `execution_refs` |
|
||||
| `result` | JSONB | Completion metadata |
|
||||
| `close_intent_digest` | text nullable | Digest of the accepted normalized terminal close intent; absent for legacy terminal and reopened rows |
|
||||
| `created_at` / `updated_at` | timestamptz | |
|
||||
|
||||
## API (actcore-api)
|
||||
|
|
@ -62,6 +64,19 @@ workplan task file. Not an issue-core or Forgejo ticket.
|
|||
- Stale claims (`state=claimed` and `lease_until <= now()`) are reopened before select.
|
||||
- Heartbeat, complete, and fail lock the row and require an active lease
|
||||
(`lease_until > now()`). An expired worker cannot revive or close its claim.
|
||||
- A first terminal close returns `close_disposition: applied`. If its response
|
||||
is lost, an exact normalized repeat by the same claim owner returns HTTP 200
|
||||
with `close_disposition: reconciled`; it does not require the cleared lease
|
||||
and does not mutate the row again.
|
||||
- Refusals are machine-distinct. A missing row is HTTP 404 `not_found`;
|
||||
wrong-owner, expired-lease, non-claimed-state, mismatched repository evidence,
|
||||
and different terminal intents are HTTP 409 with codes `wrong_owner`,
|
||||
`expired_lease`, `state_conflict`, `evidence_conflict`, and
|
||||
`terminal_conflict` respectively. A pre-migration terminal row has no close
|
||||
digest and therefore fails closed as `terminal_conflict`.
|
||||
- A failure accepted with `reopen: true` below the attempt ceiling is not
|
||||
terminal: it clears owner/lease/close identity and returns to `open`. A repeat
|
||||
cannot be treated as terminal reconciliation.
|
||||
|
||||
### Complete / fail body
|
||||
|
||||
|
|
@ -112,6 +127,16 @@ prompts, messages, provider responses, credential fields, unknown nested blobs,
|
|||
and undeclared refs are never stored. Read projections normalize historic rows
|
||||
again before returning them.
|
||||
|
||||
Repository transaction evidence is independently allowlisted under
|
||||
`result.repository_transaction`: bounded transaction/correlation identifiers,
|
||||
baseline digests, repository grant and acceptance-policy identifiers, accepted
|
||||
commit/path evidence, and external-metrics identity. Raw grant patterns,
|
||||
provider/tool payloads, and unknown fields are dropped. If an `ops_run` carries
|
||||
a repository grant, completion additionally requires the result's grant id,
|
||||
acceptance-policy id, and positive acceptance evidence to match the queued
|
||||
grant. Failure may omit transaction evidence when setup never began; supplied
|
||||
grant evidence must match.
|
||||
|
||||
## Emit path
|
||||
|
||||
On `emit_tasks` (when `OPS_RUN_QUEUE_ENABLED` is truthy, **default true**):
|
||||
|
|
@ -210,7 +235,8 @@ resolver rather than at emission. That residual gap is accepted and recorded in
|
|||
ACT-ADR-006; closing it needs a scoped glas-harness API, not a local catalogue.
|
||||
|
||||
Task-emitting rules declare the selector and optional attribution refs on the
|
||||
action; instructions use the same fields at instruction level:
|
||||
action; instructions use the same fields at instruction level. Repository
|
||||
authority is a separate, static declaration and is never template-rendered:
|
||||
|
||||
```yaml
|
||||
action:
|
||||
|
|
@ -220,6 +246,11 @@ action:
|
|||
execution_refs:
|
||||
correlation_id: context.request.correlation_id
|
||||
goal_refs: [context.request.goal_ref]
|
||||
repository_grant:
|
||||
version: "1"
|
||||
allowed_paths: [docs/, README.md]
|
||||
commit_count: {min: 1, max: 1}
|
||||
publish: false
|
||||
```
|
||||
|
||||
File sync validates every declared profile structurally and rejects malformed
|
||||
|
|
@ -228,6 +259,14 @@ batch before opening the database or IssueSink. A profile policy failure is a
|
|||
non-retryable activity error; no earlier item in that batch is emitted. Only the
|
||||
allowlisted attribution keys are carried to the queue.
|
||||
|
||||
Repository-grant v1 requires exactly `version`, `allowed_paths`,
|
||||
`commit_count`, and `publish`. It accepts 1–100 unique, repository-relative
|
||||
POSIX path patterns, commit bounds `1 <= min <= max <= 32`, and only
|
||||
`publish: false`; absolute/traversal/backslash/`.git` grants, ambiguous scalar
|
||||
types, unknown fields, and publication are rejected at definition sync and
|
||||
again across the full emission batch. The admitted mapping is copied unchanged
|
||||
to the queue claim/read response and never merged into `execution_refs`.
|
||||
|
||||
`ACTIVITY_CORE_REQUIRE_HARNESS_PROFILE=true` makes a missing profile ref an
|
||||
error both during file sync and emission. Deterministic report-only
|
||||
instructions are exempt because they create no execution request. The flag
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue