Governed agent work discovery and claim (AD-1187 / #1124)¶
Status: shipped in PR #1403 (merge 0ae79d95); #1124 is closed completed.
Publication and availability¶
The existing Captain create, template-overrides and patch surfaces can publish a standalone WorkItem through its metadata:
Department-only publication uses the authoritative department identifier:
These are exact shapes for the agent_pull member. Missing, malformed or
additional publication keys are private, not an implicit ship grant. Other
WorkItem metadata may coexist but is not exposed by either tool. Publishing is
an explicit decision to share the permitted projection, including descriptions,
with eligible peers. Existing items are not automatically published or migrated.
Both tools register during communication startup only when workforce and its current-authority resolver exist. Workforce's existing default-OFF setting stays unchanged. The catalog scope is engineering, science, medical, security, operations and bridge. All four known ranks (ensign, lieutenant, commander and senior_officer) receive READ for discovery and WRITE for claim. Unknown ranks, out-of-scope departments, current restrictions and LOTO still deny access.
The agentic offer is explicitly permission-filtered. Raw grants do not bypass
the gate. Crew and correction bindings (_crew_session_id or
_crew_work_item_id) exclude both tools from the offer and invocation. This is
not a new queue, scheduler, poller, crew executor or completion mechanism.
Authority and readiness¶
Model parameters never supply identity, rank, department, trust, capacity or permission. The context agent ID must resolve uniquely to the live registry key, agent ID and registered resource ID. Different UUID aliases, ambiguous mappings, inactive resources and malformed authority fail closed. A configured resolver's denial never falls back to a cached resource.
The runtime reuses the existing agentic identity and resource-characteristic owners. Current trust and department are authoritative; capacity and active status remain store-owned. Matching uses current agent type, department and trust characteristics, not a new mesh-capability interpretation.
Ready work is open, unassigned, unexpired and has every dependency in done.
Parental/crew, room/session and scaffold rows are excluded. Discussing, planned
and in-progress rows are not ready. Nonempty resource-requirement department
constraints still apply. Discovery is advisory; fresh claim rechecks readiness,
visibility, current authority and uncapped scheduled/active booking capacity
inside one admission transaction.
Tool contracts¶
Both successful ToolResult.output values are pre-rendered strings containing
Python-literal objects, not raw dictionaries or JSON. This is declared by the
string output schema and tool descriptions. The loop's plain renderer supplies
the string; its normal final truncation path is not exempted.
discover_work_items accepts only:
- optional exact
work_typestring, 1–64 characters; - exact integer
limit, 1–50, default 20 (booleans are not integers here); - exact nonnegative integer
offset, default 0.
Its logical object contains items, next_offset and omitted_fields. Each
item contains id, title, title_truncated, work_type, priority,
description_preview, description_truncated and description_utf8_bytes.
Titles and previews are bounded to 256 Unicode characters with explicit flags.
items[].description is marked preview_only; other nonprojected WorkItem
fields are individually marked not_exposed.
claim_work_item accepts only an exact, complete work_item_id string of
1–128 characters. A stale selection never falls through to another item.
Shared agent-pull readiness enforces the same ID domain, without trimming, so
discovery cannot advertise an identifier that claim cannot submit. This does not
change legacy Captain creation or previously persisted identifiers.
Its ownership object contains:
owned: True;work_item:id,title,title_truncated,description,description_utf8_bytes,work_type,priority,status,assigned_to;booking:id,work_item_id,resource_id,status;omitted_fields, including every nonprojected WorkItem/Booking field.
No arbitrary metadata, steps, verification, schedule or attachment content is
projected. Ordinary misses share {'owned': False, 'reason': 'not_claimable'};
authorization, projection and infrastructure failures are errors, not empty
successes. owned confirms ownership at that operation, not execution, a fresh
mutation or automatic resumption.
Actual invocation budget¶
The frozen ToolResultPresentation carrier lives in tools.protocol. Only
these two tool IDs receive it from AgenticLoop, under the reserved context key
_tool_result_presentation. The loop copies context, overwrites an incoming
reserved value and captures its own constructor-bound result settings. There
is no runtime-config proxy, tool-instance scratch buffer or model budget knob.
Missing, malformed or untrusted carriers deny admission.
render_complete(value) uses the existing plain renderer with max_chars=0,
then the existing truncator with the captured bounds. It returns the complete
unchanged render or None; invalid bounds and rendering failures are errors.
Admission measures rendered characters, including escaping, keys and omission
metadata, not source bytes, tokens or total request size.
Claim descriptions follow this order:
- Strict UTF-8 strings up to 16,384 bytes, including empty strings, remain complete when the full receipt fits.
- Larger descriptions become
None, retaining the original byte count andomitted_fields["work_item.description"] = "size_limit". - An otherwise permitted description whose full receipt exceeds a positive
cap becomes
None, retaining the original byte count and the reasonresult_budget. - If the complete essential receipt still does not fit, reject before any ownership, booking, requirement or timestamp mutation.
IDs, ownership, statuses, counts and omission reasons are not shortened or
dropped to fit. The existing 256-character title rule is not further reduced.
Invalid, non-string or unencodable text is an error, not invented empty
instructions. Cap zero is unbounded presentation, not an exemption from the
UTF-8 ceiling. Budget refusals use work_pull_result_budget if that token fits,
otherwise explicit !, with the contextual reason retained in diagnostics.
Discovery examines at most 200 authorized candidate rows per call. The frozen
ReadyWorkPage appends defaulted item_offsets aligned to eligible returned
items, preserving its first two fields and public listing signature. The adapter
selects the largest whole-row prefix that fits the actual presentation budget.
When a suffix is omitted, next_offset is the first omitted item's recorded
scan offset, with omitted_fields["items"] = "result_budget". It does not rescan,
infer positions from item count, or reuse the scan's end cursor after dropping
rows. True empty pages can retain continuation. A first eligible row that fails
admission produces an error, not a false empty page. Offsets remain advisory
under concurrent board changes.
Transaction, replay and event ownership¶
WorkItemStore owns the write lock, BEGIN IMMEDIATE, guarded ownership update,
booking, requirement fulfillment, timestamp, commit and post-commit events.
Shared internal helpers do not take the lock or commit independently. Public
claim does not call locking public assignment, and public booking/journal
mutations cannot split an admission transaction on the shared connection.
All scheduled/active bookings count toward capacity, not the bounded UI cache.
Pause releases active capacity; resume rechecks capacity atomically.
The appended keyword-only prepare_claim: Callable[[WorkItem, Booking], None] |
None preserves the existing tuple/None return. Shared assignment preparation
allocates the real booking ID and planned assigned state before invoking the
synchronous, read-only callback and before the first mutation statement.
The callback must not do I/O or reenter the store; it cannot select authority
or change the plan. The store knows validation, not LLM presentation.
The adapter keeps its accepted immutable receipt invocation-local and returns it only after successful store completion. CAS refusal, transaction failure or rollback failure never returns a cached success. Exceptions and cancellation roll back and propagate. Post-commit notification failure retains the committed outcome; cancellation/process/provider interruption is not an outbox guarantee. Exact-ID replay recovers an interrupted acknowledgement without another booking.
Replay checks current identity, active resource and permission before ownership
and matching bookings, but before fresh-work capacity/readiness. Exactly one
matching nonterminal booking returns the existing ownership, including paused
on_break state, without resuming or emitting. Publication withdrawal alone
does not revoke owner readback. Terminal, reassigned or missing bookings are
uniform misses; conflicting live bookings are integrity errors. Room/child
exclusions still apply.
Fresh claims emit the existing assignment and claim UI events once after commit and lock release. Governed self-claim suppresses only the redundant assignment TaskEvent. Legacy Captain pull/assignment retains notification, authorization and REST envelopes, with current trust and transactional capacity checks. Resolver-free standalone stores retain their declared-resource legacy behavior; agent pull requires a resolver.
work_item_status remains the separate assignee-only status reader. It is not
extended into a description/metadata retrieval or execution tool. Rollback is
an ordinary code revert with no schema migration or automatic publication to undo.
Status first tries the owned, nonempty raw exact ID, including short or whitespace-
bearing identities. Only afterward does its existing trimmed exact/prefix fallback
require eight characters. Short prefixes do not resolve, ownership remains scoped,
and legacy exact IDs are not given the new claim tool's maximum length.
Measured implementation evidence¶
The parent independently ran the complete 23-file owner/immediate-consumer
selection: 1,272 passed, zero failed or skipped. The run asserted that every
loaded file-backed ProbOS module came from the candidate worktree. Durable
command/stdout and JUnit are
logs/gates/ordinary-1124-parent-focused-20260918T202502191.*;
JUnit SHA-256 cb7f9b7b6ee21fa17cf6cff12758a619362e6f68556d72e3519129919be1d699.
The selection includes actual startup/registry/executor/next-request/persisted
readback, transaction/authority/pagination/projection boundaries and unchanged
adjacent consumers. These are focused implementation checks, not independent
review, canonical full-gate, release or verified closure evidence.
Independent review found two ID-domain seams; parent real-chain probes confirmed
both before repair. The final repaired 25-file focus passed 1,501 tests, with
zero failures or skips, including 433 AD-1187 cases and the unchanged adjacent
default-OFF/delegation contracts. Evidence:
logs/gates/ordinary-1124-id-final-20260918T213457019.*;
JUnit SHA-256 5a0e67f17034e28f4455d53a2488a4abad760497d8b9c79ebe927187bddfcaff.
Prior overlapping counts are historical, not additive.
Scheduled quality limitation¶
Discovery currently issues per-item requirement/dependency queries under its bounded scan. Review measured 200 authorized department-ineligible rows yielding 202 serialized DB calls and 23.56 ms in in-memory SQLite; dependency lists can add calls. This is not a disk/live latency claim. Batching and deterministic query-count evaluation remain recorded on #1124 as a Medium follow-up, preserving privacy, ordering and offsets; no separate issue or unrelated refactor is included here.