Cross-window entity review journal
The local application retrieves candidates, previews exact bounded input, durably prepares one explicitly confirmed invocation, executes the current production API adapter, archives its complete returned result, records a separate human decision, and recovers library publication. The governed prompt and request bytes are pinned. The CLI and Studio review surface expose this workflow. Quality criteria, frozen measurements and review readiness are owned by the separate entity-link evaluation protocol; workflow completion does not establish semantic quality.
1. Identity and candidate boundaries
entity-link-retrieval/v1 applies NFKC, lowercase, and whitespace removal to current entity labels and source mention surfaces. Exact equality retrieves entities from other analysis windows; it never establishes identity, changes an entity UUID, or rewrites knowledge. More than 100 matches fails explicitly; unreadable analyses are reported separately. Unreadable library owners or review files fail the query rather than appearing as an empty healthy catalog.
A preview pins two distinct analysis windows, their entity UUIDs, entity revision IDs and generations, source snapshot/version, selected mention IDs, and each current library owner including its generation/head. An entity can be unowned, or one side can already belong to one library object. Two already owned sides require separate organization maintenance; previews refuse both same-owner and competing-owner pairs.
entity-link-model-input/v1 includes those bindings, each selected entity, its selected saved mention evidence and analysis limitations. It excludes native paths, raw trace envelopes, and unrelated full source text. The actual system plus canonical prompt UTF-8 input is limited to 256 KiB; callers must choose fewer mentions rather than silently truncate evidence. Preview requires current, readable, position-matched evidence. Preview does not reserve or execute a model. A separate prepare command requires explicit content/model confirmation, binds the exact request and invocation budget, and rechecks source/entity/owner heads under the workspace lock.
2. Independent v1 storage
entity-links/<review-id>.json uses storeKind: entity-link-invocation-history, schemaVersion: 1. It replaces the unpublished offline record(capture) protocol; there is no compatibility alias or second reader. Entity history v2, knowledge history v2 and library v1 remain unchanged. The independent extraction-run v5 upgrade and its legacy-run boundary are owned by the extraction specification; it does not change this v1 journal. Unsupported storage fails closed.
The separate human command execution_terminated carries terminationVersion: omk.entity-link-termination/v1. The outer journal stays at schema 1 and old events keep their original bytes and facts; no migration or additional historical reader is introduced. Adding this command is BREAKING-SCHEMA for the event protocol: earlier programs reject a journal containing it. The versioned invocation and workspace-quality projections described below are now v3; entity, knowledge, library and model suggestion Schemas do not change.
Preparation stores both pinned endpoint bindings, the exact governed system/prompt and JSON Schema, prompt/schema hashes, model/executor/output/timeout settings, confirmation digest, retry predecessor and a trusted concrete producer capacity witness. The request digest proves exact request integrity; it does not assert full runtime or credential identity. The actual API builder and executor share one frozen environment; beforeDispatch compares the actual endpoint/body with the prepared witness. No credentials are persisted in the witness. A zero-I/O inspect exposes the nonsecret producerContext during preview, and producerContextDigest participates in content/model confirmation. Endpoint or proof-context changes between preview and prepare fail explicitly. The shared PreviewSchema checks that displayed input matches the plan and returns stable reviewId, prepare requestId and startRequestId.
The unordered pair key binds analysis/entity/revision and snapshot/source-version identities. Name normalization only retrieves candidates; owner changes, mention subsets and side order cannot bypass a human rejection. One workspace may hold one prepared/running invocation. Failed, unknown or human-terminated invocations require an explicit retryOf and renewed confirmation; an active predecessor cannot be retried. Each confirmation authorizes one OMK invocation, whose internal attemptCount is recorded separately.
The append-only lifecycle is prepare → start → execution_recorded → reviewed_v2 → application_applied/application_conflict_v2, with optional proven-owner-exit execution_unknown before recording. A prepared invocation can cancel_before_start. At most six events are permitted. Only the successful CAS start publishes dispatch_once; start acknowledgements, list/read/resume and ordinary reload never dispatch. A start written before a crash may already have been sent, so it consumes the slot even when no result exists. Only a proven exited local PID can mark a running owner unknown; age, remote hosts and missing locks are insufficient. Unknown and post-start cancellation never refund or automatically resend. A separate human termination can close a running invocation without asserting owner exit; it is not the execution_unknown transition.
The complete returned JSON ExecResult is saved before structural admission, including failed partial output, refusal, executor-normalized token/cache counters, usage reported flags, stop reason, failure metadata and extra returned JSON fields. These are executor observations, not a claim that the provider explicitly reported each normalized zero. Unknown exception values are never JSON-stringified or inspected through getters/proxies: a bounded exception-diagnostic/v1 observation records unknown outcome/usage. The one archived outcome is immutable. An unarchived unknown can later save the original recovered result; an archived exception cannot silently be replaced by a second outcome.
The v1 suggestion remains entity-link-suggestion/v1 with same_object, different_objects or insufficient_evidence, exact entity/selected-mention references and rationale. Failed execution, observed tools, invalid JSON/references, token aggregate overflow or reservation overrun cannot be accepted. Original returned counters/output/refusal remain intact; finite negative durationMs observations caused by a wall-clock rollback are archived unchanged rather than corrected for storage. Structural admission does not measure semantic accuracy or establish identity.
API capacity comes from executable producer code, not caller-supplied numbers: a 4 MiB raw HTTP cap, nonfatal UTF-8 replacement up to ×3, three retained output/refusal/stopReason string channels, JSON UTF-8 escaping up to ×6, the inner diagnostic limit and actual frozen credential replacement growth in the outer redactor. Duplicated refusal fallback is included. A bounded fixed-field template covers the rest of the API result/envelope. Codex has no complete trace-derived bound yet and is rejected before preparation with zero dispatch. This does not disable the proven API path.
The product quota is 4096 files and 512 MiB per file/namespace, not an assertion about producer output size. Preparation reserves its proven complete outcome plus five future event slots, each bounded by an explicit maximum command/facts template (including 256 library members, 64 mention IDs, JSON escaping and human decision fields). Recording releases unused outcome capacity while retaining human/terminal space. Human termination releases the workspace-wide logical invocation reservation, but retains the proven producer capacity for an outcome not yet archived; it cannot promise that the original process or provider request stopped. A late archive releases its unused outcome capacity. The termination branch uses prepare → start → execution_terminated → optional execution_recorded, within the existing six-event limit. Intent capacity is checked before recording a human decision. Compact canonical JSON publishes atomically with exclusive creation or CAS replacement; existing identical acknowledgements win before quota checks. Corrupt, redirected, unsupported or unreadable storage is never a healthy empty catalog.
New human decisions append reviewed_v2 (reviewVersion: omk.entity-link-review/v2); new application conflicts append application_conflict_v2 (conflictVersion: omk.entity-link-conflict/v2). The original reviewed/application_conflict branches only interpret saved events. The schema 1 envelope and historical event/digest bytes remain unchanged, with no bulk migration or compatibility reader. Earlier programs reject new events: this is BREAKING-SCHEMA. Model input, prompt, invocation budget, six-event limit and original five-slot capacity reservation remain unchanged. The original maximal event bound also dominates the new bounded replacement receipt, without increasing existing reservations.
3. Human decisions and organization
Only an explicit human actor can authorize preparation, terminate a running invocation or decide identity; execution and archive events record the host actor. accept requires explicit identityConfirmed: true and a nonempty reason. It may override any structurally admitted model assessment, including different_objects or insufficient_evidence; the original recommendation remains visible. This expresses a human organizational decision, not a new model-quality score or proof that a knowledge claim is true. reject appends the human reason and leaves original entity UUIDs, analysis, knowledge, and library unchanged.
For a new library object, accept can supply objectLabel of at most 256 characters. Otherwise the complete left entity label is used only when within the library limit. A longer name requires explicit human naming; it is never truncated. Existing object labels are maintained through the existing library workflow. The chosen label and reason bind the decision digest and stable application intent.
Acceptance links the two original entities through the existing knowledge library. It creates a new library object when both are unowned, or appends to the one pinned owner. Unrelated existing members remain unchanged. It never merges source UUIDs, transfers members between competing owners, copies knowledge bodies, or treats chronology as truth. Both entities must have a proposed identity at the same referential level, which must also match the pinned existing owner’s fixed level; unresolved or incompatible identities require source correction before a new review.
acceptPreview({ reviewId, expectedGeneration, reason, objectLabel? }) and CLI accept-preview show acceptance effects without model calls or writes: frozen endpoints, the existing owner's head/generation, complete old/new participating members, entity revision changes, added/removed mentions and reasons. Mention identities from different entity revisions remain separate, never merged. Selection may explicitly narrow mentions within one revision; prior library revisions remain and unrelated members stay identical.
Any changed existing-member binding, including its reason, additionally requires replacementConfirmed: true and the preview's replacementConfirmationDigest; CLI uses --confirm-replacement <confirmationDigest>. identityConfirmed cannot substitute for it. The digest binds review generation, exact endpoints, owner head/generation, previous participating-member digest, human actor, reason and label. Acceptance recomputes it under the same workspace lock. Changed reasons/labels, CAS or source/owner drift invalidate consent and cannot authorize publication. The new reviewed_v2 stores only a versioned bounded digest receipt; the preview and immutable library revisions retain the complete bindings without duplicating them in the event.
An exact original decision request wins before new checks, then recovers its original intent. A legacy accepted pending reviewed intent requires no retroactive consent or command recomputation. Matching library receipts still precede current-source checks, and lost acknowledgements never duplicate organization or model calls. Reusing a request with a changed reason, label, actor or replacement confirmation conflicts.
4. Publication, conflicts and recovery
Human acceptance first persists one stable library command: request ID, object/revision IDs, author/time/reason, complete draft, and expected library head/generation. It then attempts publication. Entity-link transitions and library publication use the same .knowledge-write.lock; both endpoint source/entity heads, exact mention positions and owner generations/heads are checked inside that lock, including an unchanged member already present in the owner. An external precheck followed by ordinary library save does not satisfy this boundary.
Known source/entity, unresolved identity, owner, stale library and duplicate-pair conflicts produce explicit accepted_conflict terminal facts after the human decision. An existing owner’s referential level remains fixed even if a source entity is later corrected; current classification uses identity_unresolved for unresolved identity and kind_mismatch for an incompatible intent or recovery; either conflict discovered before invocation dispatches nothing. Known prepublication library write capacity rejection (256-revision history, file or namespace) ends with library_capacity; an existing matching receipt is resolved before the history limit is checked. Review intent capacity is checked before persisting the decision, with terminal space reserved. A library listing/read capacity failure, corrupt data or unknown I/O error does not prove publication was rejected and remains retryable rather than becoming a capacity terminal. They do not publish a partial organization or undo history. A new review must be based on current bindings after the underlying problem is resolved. Two different existing owner objects are never automatically merged.
Review and library files are not a multi-file filesystem transaction. An unknown I/O failure leaves the durable accepted intent pending and retryable. If library publication committed but its acknowledgement or review append failed, resume() reuses the exact command; an existing matching library receipt wins before current source revalidation. This records the already committed fact without adding another library revision or calling a model. Before any publication, stale bindings still conflict. Archive I/O failures retain a stable execution identity and in-process raw outcome for resume; after process loss without saved bytes, the state remains running/unknown rather than issuing a fresh request. Entity, entity-link and library filesystem adapters acknowledge fresh publication and exact receipt replay only after synchronizing the file and its directory chain through the explicit workspace. Replay preserves existing bytes and receipts. A synchronization failure, including an unsupported filesystem, remains an unknown I/O failure: visible publication is retained and the exact command can retry without another revision, dispatch or call refund. This file-and-directory synchronization boundary is not a multi-file transaction, a tested power-cut guarantee or remote exactly-once delivery. A terminal result is idempotent; a rejected review cannot be reversed or applied by resume.
4.1 Explicit human termination
When the original owner is live or cannot be proven exited, a human may explicitly terminate the logical invocation after inspecting the saved review. This does not kill a process, cancel a provider request, establish non-delivery or prove zero additional cost. It is an auditable decision to stop using that invocation for admission and organization, rather than an invented process-exit fact.
omk observe entity-links terminate requires the explicit workspace, review --id, stable --request-id, current --generation, frozen --execution-id, frozen --owner-id and nonempty --reason. Read the saved review first and copy its execution and owner identities. The application resolves the complete owner from the frozen start; callers do not supply a replacement host or PID. Under the workspace lock, a human actor, matching running state, CAS generation, execution and complete owner must all agree. An identical request replay returns the existing fact; changed content under that request ID conflicts. A stale generation or a different owner cannot terminate another invocation.
The command appends execution_terminated and makes the review terminal with one invocation consumed and no refund. It does not reread the source, current producer configuration or credentials, and does not call the owner-exit proof. It neither creates an identity decision nor publishes library organization. A failed or unknown acknowledgement requires rereading the same review and original request before another action.
If the original result arrives later, the existing execution identity can archive it once. The review remains execution_terminated; its archive facts use archiveDisposition: terminated, without admission. There is no subsequent review or library application, even for a structurally valid suggestion. Original result/failure/refusal, executor attempts and reported usage remain inspectable as observations. Before an archive exists, those values remain unknown. Read, reload and resume never dispatch again. A new same-pair attempt requires a new review and invocation, explicit retryOf, a fresh preview and renewed content/model confirmation.
The journal retains selected mention text and raw output as user data even after source deletion, without restoring a deleted source or allowing a new application from unavailable evidence. Deleting a source is not deletion of independently retained entity or review history. These files need the same privacy and backup handling as the selected knowledge workspace; they are not repository assets.
5. Versioned projections and workspace observations
The shared invocation view has projectionKind: entity-link-invocation and projectionVersion: omk.entity-link-invocation-projection/v3. It exposes the frozen execution identity and complete termination command, or null when absent; canTerminateExecution is true only while running. A terminated review keeps admission and decision null, canStart and canResumeOrganization false, and consumed invocation budget at one. A late result may supply actual executor attempts and usage without reopening admission or organization.
The workspace projection is omk.entity-link-quality/v3. humanTerminations separately counts total, outcomeUnrecorded and lateOutcomeRecorded; admission counts expose terminatedDispatched. Terminated invocations do not enter the machine admission recorded/admitted/rejected/unrecorded-dispatched denominators or human identity-decision counts. A termination is not a human rejection, model failure or quality label. Native result/exception and actual usage observations can include a late archive; absent usage is never filled with zero. These projections remain operational observations, not the benchmark quality score or proof of semantic correctness.
The v3 invocation projection adds reviewVersion and conflict: { classificationVersion, conflictCode }, or null when absent. Historical events expose legacy/v1; current sources never backfill the actual subreason of an old identity_unresolved. Quality v3 lists organization.conflicts by classificationVersion/conflictCode while retaining invocation, admission and human-decision denominators. Old and new categories are not directly comparable. Finer classification does not establish improved entity accuracy or formal human acceptance.