[EPIC] Durable tool-result projection with public visibility presets #211
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nsaspy/prolog-rlm#211
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Separate tool execution, durable retention, and provider-visible projection for tool results.
Core invariant:
Tool results remain authoritative and retrievable even when they are no longer automatically injected into model context.
Public presets
Expose a small public API of presets that compile to an internal canonical projection policy:
Canonical meanings:
The internal representation should be explicit and extensible, e.g.:
Future presets such as
summarizedmay map onto the same internal policy without changing the public tool invocation API.visibilityis a public/API convenience term. Internally this is projection policy; it must never imply deletion or weakened auditing.Architecture
The immediate tool consumer may need the full result while later turns do not.
onceis therefore the architectural center rather thanhidden.Slices
result_visibility(full|once|reference|hidden)to tool invocation options and persist the complete result regardless of projection.once: full in the immediate continuation, omitted afterward.referenceprojection containing non-secret identity/status/size metadata rather than payload.Safety / authority invariants
Required regressions
projection_preset_full_is_canonicalprojection_preset_once_is_canonicalprojection_preset_reference_is_canonicalprojection_preset_hidden_is_canonicalonceis visible to the immediate continuation onlyonceresult is retrievable after projection expiresRelation to #176
#176 handles tool schema visibility: which registered tools the model sees.
This epic handles the mirror-image problem: tool result visibility after execution.
Together they establish a single provider-projection boundary for both tool affordances and tool observations.
Slice 1 is implemented in #213 on
agent/tool-result-projection-presets.Landed API/data shape in the PR:
Public presets compile to canonical
result_projection{initial,after_consumption,retention:durable,retrievable:true}data. This PR deliberately does not change invocation or context packing yet; that remains slice 2+.Slice 1 recovery — deterministic failure diagnosed and existing PR rebased forward without force
Recovered existing PR #213 rather than creating a replacement transaction.
Regression evidence
Old exact head
fced85495700a0746ce49d7f697db3aab39f408dhad one deterministic failure out of 889 tests:rlm_chain_message_metadata:tool_result_projection_is_canonical_and_groundAll other deterministic tests passed (888/889), and REAL/Paid OpenRouter, Nix, clean-pack and Tree-sitter lanes were green on that old transaction.
Root cause:
canonical_tool_result/2requiredground(Result0)before retagging. The public contract/test passes a normal anonymous SWI dict (_{...}). Anonymous dict tags are variables, so a dict whose key/value payload is fully ground is still notground/1solely because of its tag. Rejecting that shape accidentally made the canonicalizer require callers to invent a named input tag.Design / adversarial decision
GO with the narrower semantic boundary:
is_dict(Result0);Pairswithdict_pairs/3;ground(Pairs)so no model/runtime variable survives in payload data;tool_resulttag;This accepts anonymous input tags while preserving the security/data invariant that projected tool-result payload data is ground. A new negative regression explicitly proves a genuinely nonground payload is still rejected.
Recovery realization
Existing branch
agent/tool-result-projection-presetswas fast-forwarded, without force, to merge/recovery commit99dfc12e6651f69f2e2cac5bf23d1ac224df3e7cwith parents old #213 headfced854...and current canonicalmain267697bef10a3fffff7c093e1435ece770e7444b.The resulting branch is directly based on current
main(behind_by:0) and the complete diff is still only the owned slice:prolog/rlm_tool_projection.pltest/rlm_chain_message_metadata_test.pldocs/tool-result-projection.mdNo invocation, authority/effect, managed-context, provider serialization, token-accounting, or downstream product behavior was pulled into slice 1.
Exact-head verification is now pending on
99dfc12e...; no prior green evidence is being reused for this changed head.Slice 1 exact-head verification — GO / ready for review
Recovered candidate
99dfc12e6651f69f2e2cac5bf23d1ac224df3e7chas now completed the fresh gate against unchanged canonicalmain267697bef10a3fffff7c093e1435ece770e7444b.Exact-head results:
PR #213 remains mergeable and was promoted from draft to ready for review without changing its head. The original anonymous-dict regression is fixed without weakening the ground-payload invariant; the explicit nonground-payload rejection remains covered.
RAGE decision for slice 1 only: GO. Keep #211 open: invocation wiring, managed-context projection,
onceconsumption, durable references, provider causal-pair preservation, and projected-token accounting remain later slices. Repository merge authorization still applies; this verification record is not a merge action.