feat(worker): project objectives as native WIP objects

This commit is contained in:
2026-10-04 01:28:45 +09:00
parent e2181e9052
commit e5f255b6fd
7 changed files with 1756 additions and 161 deletions
+1
View File
@@ -34,6 +34,7 @@ It is not a dumping ground for external research, old plans, API inventories, or
26. [`design/subjektiv-surface.md`](design/subjektiv-surface.md) — confirmed Memoryから生成するresident surface、availability、append-only restore injection。
27. [`development/subjektiv-product-cutover.md`](development/subjektiv-product-cutover.md) — legacy Workspace Memoryからsubjektivへのoperator cutover、explicit reset、backup/rollback runbook。
28. [`design/worker-wip-mode.md`](design/worker-wip-mode.md) — explicit-opt-in Worker WIP mode, Worldspace projection, authority, cache, and retry contracts.
29. [`design/objective-wip-projection.md`](design/objective-wip-projection.md) — Host-assigned Objective collection/item routes, operation mapping, Backend authority, bounds, and compatibility suppression.
## What belongs here
+55
View File
@@ -0,0 +1,55 @@
# Objective native WIP projection
## Purpose and authority
When a Worker explicitly runs in `wip` mode and the Objective Feature is enabled, the Worker Host projects Objectives as native Worldspace objects. The projection is an adapter over the existing scoped Workspace API. It does not introduce another Objective store, state machine, reference resolver, or audit path.
The Host allocates `/features/objective` to the Feature through `WipMountRegistry`. The Objective Feature then mounts:
```text
/features/objective/objectives
/features/objective/objectives/<objective-reference>
```
`<objective-reference>` is either a canonical `O-<digits>` key or an existing canonical internal alphanumeric ID. Only one direct child segment is accepted. Nested suffixes, Ticket keys, and unrelated or hidden prefixes do not resolve as Objective objects.
The Backend remains authoritative for existence, `O-*`/internal-ID resolution, Workspace scope, validation, audit events, revision generation, pagination, body/event bounds, and linked-Ticket validation. A discovered route is not independent authority; every operation still uses the Worker's current `WorkspaceClient`.
## Current operation inventory
The collection interface is `yoi.objective/collection/v1`:
| Native operation | Existing Tool permission identity | Parameters |
| --- | --- | --- |
| `query` | `QueryObjective` | `query`, `states`, `linked_ticket_id`, `updated_after`, `updated_before`, `sort`, `limit`, `cursor` |
| `create` | `ObjectiveCreate` | `title`, `body_md`, `state`, `linked_tickets` |
The item interface is `yoi.objective/item/v1`:
| Native operation | Existing Tool permission identity | Parameters |
| --- | --- | --- |
| `read` | `ShowObjective` | `event_limit`, `event_cursor` |
| `edit` | `ObjectiveEdit` | `title`, `old_string`, `new_string`, `replace_all` |
| `set_state` | `ObjectiveSetState` | `state` |
| `link_ticket` | `ObjectiveLinkTicket` | `ticket_id` |
| `unlink_ticket` | `ObjectiveUnlinkTicket` | `ticket_id` |
The item operations intentionally do not accept an Objective `id`. The handler is created from the resolved item route and reconstructs the equivalent ordinary Tool permission arguments with that route-bound identity. Descriptor validation rejects a caller attempting to supply a second Objective target.
`deny` and `ask` permission results fail closed before Backend dispatch. Backend 401/403 map to permission denial, 404 to missing target, and deterministic client validation failures to invalid arguments. Transport, server, or response-projection failures after dispatch retain the common unknown-outcome contract; mutating operations must not be retried automatically when the outcome is unknown.
## Bounded reads and references
`query` retains the ordinary Worker limit of 1–100 and returns stable snippets, canonical `O-*` references, linked `T-*` references, `next_cursor`, and `has_more`. Each result also includes its canonical item path. It does not expand Objective bodies, complete events, or Ticket records.
`read` retains the ordinary Worker event limit of 1–50 and projects the Backend-bounded body, `body_truncated`, authoritative `revision`, linked-Ticket summaries, bounded events, and event pagination. Internal Objective, Ticket, and event-storage IDs are removed from model-visible results.
`create` returns the authoritative Objective detail plus its canonical item path. Mutations return the authoritative post-operation detail. The revision observed in a successful read or mutation updates the item's object validator. The common Host validator contract rejects stale object/interface calls before dispatch, and the call response carries the refreshed route validator.
Linked Ticket references remain strings passed to the existing Objective Backend operation. Their presence does not publish a Ticket object, grant Ticket read or mutation authority, or require a Ticket-native WIP projection.
## Compatibility and Tool mode
The native collection/item pair claims all seven Objective compatibility capabilities in WIP mode. Therefore `/tools/QueryObjective`, `/tools/ShowObjective`, and `/tools/Objective*` are not published alongside the native routes. Unrelated enabled tools keep their compatibility projections.
Normal `tools` mode is unchanged: it still exposes the same seven Objective tools with their existing names and input schemas. Both surfaces share the same `WorkspaceHttpObjectiveBackend` and scoped Backend endpoints.
+5 -4
View File
@@ -52,14 +52,15 @@ The interface descriptor uses WIP `Json` for compatibility input and includes th
## Native projection extension and collisions
`worker::wip::WipMountRegistry` is the Host-owned mount allocator. A Feature can independently construct a `WipProjection` with an async `WipOperationHandler`, then pass its aggregate registry through `install_wip_mode_with_mounts` before compatibility finalization.
`worker::wip::WipMountRegistry` is the Host-owned mount allocator. A Feature can independently construct a `WipProjection` with an async `WipOperationHandler`, then pass its aggregate registry through `install_wip_mode_with_mounts` before compatibility finalization. A Feature first requests a Host-owned `/features/<feature>` namespace with `allocate_feature_route`; checked direct-child joins prevent a Feature from claiming an ambient global route.
- Routes must be canonical absolute WIP paths.
- Object names must match the final route segment.
- A projected object exposes exactly its declared interface.
- Unrelated duplicate routes and conflicting interface descriptors fail startup.
- A native projection replaces a compatibility projection only when both declare the same semantic capability (`tool:<registration-name>` for compatibility tools).
- When native is already selected, the compatibility tool is hidden rather than exposed through a second entry.
- Unrelated duplicate routes and conflicting interface descriptors or validators fail startup.
- A bounded dynamic mount may resolve exactly one item segment below an already mounted native collection; deeper paths never fall through to the resolver.
- A native projection replaces a compatibility projection either by the original same-route semantic capability or by an explicit registry capability claim owned by a mounted native route.
- Conflicting native claims fail startup. When native is selected, the claimed compatibility tool is hidden rather than exposed through a second entry. Normal Tool mode is unaffected because it does not install the WIP registry.
`WipInspect` renders the complete descriptor, including descriptor-local named declarations and recursive record, list, enum, and union shapes with required flags and declaration documentation. The unit samples `mount_collision_and_native_replacement_are_explicit` and `native_projection_preserves_descriptor_and_decodes_typed_arguments_end_to_end` demonstrate independent native registration, deterministic replacement, collision rejection, complete descriptor inspection, and a descriptor-typed native invocation.