feat(ticket): decouple audited lifecycle decisions from MR integration

T-718: unify state, completion, close and reopen with explicit CAS and operation receipts; keep MR integration proofs independent. Queue only the explicitly selected Ticket and fence target edits against active Worker grants. Align REST, Worker/WIP, evidence projection and generated contracts.

Validation: root cargo check; full ticket, merge-request, client, worker, yoi-workspace-server and server-api tests; server-api typescript feature; OpenAPI and six generated API checkers; Svelte check and 36 narrow Web tests; fmt and diff checks.
This commit is contained in:
2026-10-08 19:12:39 +09:00
parent e939cd4e4b
commit df390f02e9
25 changed files with 4596 additions and 2292 deletions
+5 -6
View File
@@ -24,7 +24,6 @@ Collection interface `yoi.merge-request/collection/v1`:
| Native operation | Existing Tool | Preserved authority inputs |
| --- | --- | --- |
| `open` | `OpenMergeRequest` | Ticket, repository key, source selector, target selector, summary |
| `complete_ticket` | `CompleteTicket` | Ticket, operation ID, current item revision, exact linked-MR result set, requirement approval event |
Item interface `yoi.merge-request/item/v1`:
@@ -39,9 +38,9 @@ Typical role surfaces are therefore:
- Coder: collection `open`; item `read`.
- Reviewer: item `read` and `review`.
- Orchestrator: collection `complete_ticket`; item `read`, `check_readiness`, and `complete`.
- Orchestrator: item `read`, `check_readiness`, and `complete`.
`complete_ticket` is deliberately collection-scoped because its subject is a Ticket and an exact set of linked Merge Request results rather than one route-bound MR. It keeps those identities explicit. The review descriptor never contains the injected capability token, and a review item route must exactly match the Merge Request captured by that capability before the ordinary review Tool can run.
`CompleteTicket` belongs to the Ticket Feature and route-bound Ticket item `complete`, alongside state and close decisions. It takes current item/state CAS, a replay key, reason, and optional references; it requires neither an MR result set nor a Reviewer approval. The former MR collection `complete_ticket` operation is not published. The review descriptor never contains the injected capability token, and a review item route must exactly match the Merge Request captured by that capability before the ordinary review Tool can run.
## Preserved review and integration gates
@@ -55,8 +54,8 @@ The native projection delegates to the same ordinary tools and REST endpoints. I
- source movement invalidating source approval while target-only movement preserves unchanged-source review;
- unresolved request-change and revoked/stale approval rejection;
- current target observation, target-before/after proof, strategy, and conflict-resolution checks;
- Orchestrator-only Merge Request and Ticket completion;
- immutable integration/result evidence and exact linked-result-set Ticket completion.
- Orchestrator-only Merge Request integration;
- immutable integration/result evidence and exact linked-result-set requirement attestation.
The Worldspace adapter performs no Git or provider integration. A visible `complete` operation remains unusable without the ordinary Backend's authenticated online Orchestrator source and integration evidence.
@@ -64,7 +63,7 @@ The Worldspace adapter performs no Git or provider integration. A visible `compl
`read` exposes the existing bounded thread page with optional `after` and a `1..=200` limit. Responses keep linked Tickets as references/data, so Ticket or Objective native projections are not prerequisites. Descriptors never expand repository diffs, unbounded thread history, credentials, or capability material.
A successful item read records a response fingerprint. A successful item mutation advances a local mutation generation. Opening records the returned MR and adds its native path to the result. Ticket completion invalidates every MR route named in its exact result set because releasing the assignment can change later ref observations. The common WIP Host rejects calls made with stale object/interface validators; callers must rediscover before deciding whether to call again.
A successful item read records a response fingerprint. A successful item mutation advances a local mutation generation. Opening records the returned MR and adds its native path to the result. Ticket decisions advance the Ticket provider's object generation, not the MR integration state or proofs. Ending Ticket work can affect later live source observation, so clients reread MR authority before MR actions; Backend checks remain authoritative. The common WIP Host rejects calls made with stale object/interface validators; callers must rediscover before deciding whether to call again.
Optional fields preserve ordinary JSON-input semantics: omission remains omission and explicit WIP unit/null remains JSON `null` for schema and permission matching. The reconstructed object is validated against the original Tool JSON Schema before the Tool executes.
+4 -2
View File
@@ -12,11 +12,13 @@ A merged MR's review status/timestamps describe **integration approval**, not a
## Current requirements
`merge_request::requirement_approval` is shared by CompleteTicket and Ticket reads. It validates an effective Reviewer approval of the current item revision and the **exact complete linked MR/source snapshot**, including the hosting MR's own source and corresponding ReviewRequested event. There is no primary-MR fallback, comment-derived approval, or timestamp-only freshness rule. A post-integration review may attest a new revision/snapshot without replacing MergeResult or its integration approval.
`merge_request::requirement_approval` evaluates Ticket read-side MR evidence; it is not a Ticket completion gate. It validates an effective Reviewer approval of the current item revision and the **exact complete linked MR/source snapshot**, including the hosting MR's own source and corresponding ReviewRequested event. There is no primary-MR fallback, comment-derived approval, or timestamp-only freshness rule. A post-integration review may attest a new revision/snapshot without replacing MergeResult or its integration approval.
`approved_current_subject` describes valid source/integration approvals. `review_after_rescope` retains its wire name but now describes exact current requirement attestation, not ordering of wall-clock timestamps. `approved_review` query filtering requires that current attestation. `stale_after_rescope` requires substantive item-edit history and a known source-approved snapshot lacking current attestation; unknown observations are only `missing_evidence`.
`complete_for_integration` means the summary has valid source approvals and current requirement evidence, including for partially or fully integrated sets. It is not a claim that open repositories have been integrated, that target integration readiness has been checked, or that Ticket completion is authorized. CompleteTicket additionally requires all linked results merged and validates explicit approval identity, lifecycle, and assignment transactionally.
`complete_for_integration` means a nonempty linked MR set has valid source approvals and current requirement evidence, including for partially or fully integrated sets. It is not a claim that open repositories have been integrated, that target integration readiness has been checked, or that Ticket completion is authorized. An MRless Ticket has no applicable MR evidence: `missing` is empty, `review_status` is null, and approval/integration flags remain false. It does not match `missing_evidence` or `approved_review` merely because its state is done.
CompleteTicket belongs to the Ticket domain. It records the authenticated actor's reason/result and optional references using current item revision/state CAS and an operation receipt. It needs no MR or Reviewer approval, and does not create or modify those proofs. State setting, completion, close, and reopen share the same transactional update boundary. Exact replay returns current Ticket authority without reapplying a historical decision or appending an event. Historical MR-based `ticket_completion` records remain readable and distinct from new judgment receipts.
Writable targets authorize deliverables, not mandatory MRs for every target. Every linked MR remains part of the exact requirement snapshot; no arbitrary latest-review or single-repository shortcut is used.
@@ -0,0 +1,15 @@
# T-718: SubWorker の cwd・参照コンテキストに関する障壁
## 観測
T-718 の実装を `crates/ticket` / `crates/worker` / `crates/merge-request` に分担した。SubWorkerSpawn の cwd を各 crate に設定すると、子のファイル tool は `src/lib.rs` 等で成功する一方、親で使える repository-root-relative な `crates/<crate>/src/...` は crate prefix が二重になって失敗した。cwd 未指定の Glob は一部の子で transient bash-output 側のパスを logical path として扱い失敗した。
また builtin default の子には ShowTicket が公開されず、別途 read scope に含めたテスト規則の親 root-relative path も子の cwd から参照できなかった。親が authoritative Ticket とテスト規則を先に読み、要件・規則・インターフェースを本文で転送して作業を継続した。
## 改善案
- 子の startup context に実際の Workdir attachment alias・logical root・tool cwd を明示する。
- cwd と path root の関係を tool schema / Spawn 説明と一致させ、cwd 外に委譲した read-only scope の参照方法も示す。
- Ticket implementation の子へ typed Ticket read を委譲できない場合は、親に authoritative item revision と本文を渡す責任があることを明示する。
本件では委譲 scope を広げたり Backend storage を直接操作する回避はしていない。製品要件の追加ではなく、分担時の tooling/context で発生した調整コストの記録である。