From e8e112186ef65a23dfb9d66c63627e9061676656 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Thu, 5 Nov 2026 03:48:04 +0000 Subject: [PATCH] Record ArtifactReader ownership decision --- docs/roadmap/audit/catalog.md | 69 ++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/docs/roadmap/audit/catalog.md b/docs/roadmap/audit/catalog.md index 9adc0f2..2d168cb 100644 --- a/docs/roadmap/audit/catalog.md +++ b/docs/roadmap/audit/catalog.md @@ -56,10 +56,11 @@ Sources: [Resources 2](05-resources.md#2-convenience-source-conversion-expands-s **Confirmed race under the documented collaborator contract.** The public reader contract permits buffer reuse after `Read` returns, before PromptKit can finish copying it. Concurrent preparation with a compliant custom reader -can race. Clarify ownership/lifetime per invocation and align adapters, GoDoc, -and concurrency tests. This needs a deliberate public-contract decision before -v1.0: an immediate copy alone cannot guarantee safety if the reader is allowed -to mutate the buffer immediately. No default-reader defect was established. +can race. [Decision 1](#decision-1-artifactreader-result-ownership-and-lifetime) +selects ownership transfer on successful return; implementation remains pending. +Align adapters, GoDoc, and concurrency tests with that rule. An immediate copy +alone cannot guarantee safety under the old immediate-reuse permission. No +default-reader defect was established. Sources: [Interfaces 1](09-interfaces.md#1-artifactreader-permits-buffer-reuse-before-promptkit-can-copy-it). @@ -443,40 +444,48 @@ This is not a second scheduling algorithm or a confirmed concurrency defect. Sources: [Boundaries 1](11-boundaries.md#1-retire-the-test-only-capacity-client-as-a-production-scheduling-surface), [Dead-code retention qualification](12-deadcode.md#intentional-retention-and-related-findings). -## Open Decisions - -Work through the decisions below in this order. These are unresolved choices, -not additional findings or approved changes to public contracts. A decision -blocks its dependent remediation, not unrelated fixes. In particular, updating -the maintainer toolchain need not wait for the consumer-minimum decision. -Implementation details and optional cleanup do not become release gates merely -by appearing in this catalog. +## Resolved Decisions ### Decision 1: ArtifactReader Result Ownership And Lifetime **Related finding:** [4](#4-resolve-the-artifactreader-buffer-ownership-contract). -**Question:** What ownership does a successful `Read` transfer, and when may -an injected reader mutate or reuse the returned storage? +**Status:** Accepted; implementation pending. -**Recommendation:** Transfer an independent result to PromptKit on successful -return. The reader must stop mutating the returned artifact and its body, -including through retained aliases. Fresh per-invocation storage is the simplest -implementation; immutable shared data can remain shared if no collaborator -mutates it. This removes the impossible immediate-reuse permission without -adding synchronization or a release protocol to the interface. Explain the -consumer impact as a deliberate pre-1.0 contract correction. +**Decision:** A successful `Read` transfers the returned artifact and its mutable +body storage to PromptKit. The reader must stop mutating the returned artifact +and body, including through retained aliases. Fresh independent results are the +simplest implementation. A reader may reuse private working buffers if it copies +into independent result storage before returning. -**Alternative:** Permit borrowing until the enclosing preparation/execution -operation returns. This can support application-managed reuse, but a reader -cannot generally observe that lifetime and concurrent calls need independent -storage or caller coordination. If reuse immediately after `Read` returns is -required, an explicit acknowledgement/release API is another viable design; -it enables pooling at the cost of a larger interface and lifecycle change. +Keep the existing interface signature and defensive adapter copy initially. +Removing redundant copies is a separate optimization, not part of this contract +correction. No borrowing lifetime or acknowledgement/release API is introduced. -**Resolve before implementation:** Select the ownership/lifetime rule and update -GoDoc, adapter assumptions, and the regression scenario together. Another -unsynchronized copy is not a remedy for the current permission. +**Rationale:** The reader controls storage until return and can therefore make +that handoff safe. Copying only after return cannot make the current permission +to immediately reuse storage safe; a reader-local mutex also cannot protect the +caller's later copy. + +**Alternatives considered:** Borrowing until the enclosing operation returns +makes the lifetime difficult for a reader to observe and requires coordination +across concurrent calls. An explicit release protocol enables pooling but adds +lifecycle machinery. Caller-provided buffers or streaming would require a +broader interface redesign. None is needed for this correction. + +**Remediation follow-through:** Update GoDoc, adapter assumptions, and concurrency +regressions together. Explain the migration for readers that reuse returned +storage in release notes as a deliberate pre-1.0 contract correction. This +record does not itself implement the change. + +## Open Decisions + +Work through the remaining decisions below in order, retaining their original +numbers. These are unresolved choices, not additional findings or approved +changes to public contracts. A decision blocks its dependent remediation, not +unrelated fixes. In particular, updating the maintainer toolchain need not wait +for the consumer-minimum decision. Implementation details and optional cleanup +do not become release gates merely by appearing in this catalog. ### Decision 2: Provider Submission Of Multi-Resource Schemas