3b: export the nine per-verb apt_<verb>() commit API - #9
Merged
Merged
Conversation
The exported public API that completes the commit lifecycle. Each apt_<verb>(preview, ...) takes the pkgops_preview its apt_<verb>_preview() twin produced and drives .commit_session for it, returning a pkgops_outcome or signaling a typed condition. This is the increment that makes pkgops mutation-capable. .commit_verb() adds the two checks the verb-agnostic .commit_session cannot make -- the argument is a pkgops_preview, and its verb is the one this function commits (apt_install() refuses an apt.remove preview: a verb/preview mismatch) -- both before any capability call or intent, then delegates. The plan_hash the preview carries stays the integrity authority (the helper re-validates it under the dpkg lock); pkgops does not re-derive it at the R layer. interactive defaults to interactive(): an R console commits through the pkexec prompt, a script or CI run commits in machine mode (pkcheck). lock_timeout/deadline_ms/socket_path pass through to the session. Updates the DESCRIPTION: mutation is no longer out of scope. Hermetic tests cover the verb match, the nine-verb surface, the non-ok/non-preview refusals, parameter pass-through, and both authorization modes.
This was referenced Aug 18, 2026
# Conflicts: # CLAUDE.md # NEWS.md
A left-open intent exists precisely so it can be reconciled later, which needs its correlation_id. But a commit that RAISED (a mid-flight kill -- the G-INT case) was re-signaled as the raw runix condition with NO cid: the cid lived only on the outcome object .commit_and_classify discards. A lost-result effect_unknown whose delivered frame dropped its correlation_id had the same gap. .ensure_cid(cond, cid) attaches the session correlation_id to a condition that reaches the caller on a left-open / effect-unknown path, PRESERVING its class and every structured field and ADDING the cid only when the condition does not already carry a usable one (never overwriting a cid a lower layer set). Applied in .commit_and_classify to both the raised-commit condition and any classified condition, so every open intent the caller sees is reconcilable. The classified helper-refusal conditions already carried commit$correlation_id, so this is a no-op for them; it fills the two gaps (raised commit, lost cid). 756 tinytest.
…und) .ensure_cid now stamps the session correlation_id whenever the condition's existing cid is not ALREADY a well-formed broker cid (reusing .valid_broker_cid), so an empty, NA, malformed, or non-scalar value is replaced -- not just a missing or NA one. A valid cid a lower layer set correctly is still kept, and a non-well-formed session cid is never stamped (no replacing one bad cid with another). This keeps a left-open / effect-unknown intent (G-INT) reconcilable even when the raw condition carried a garbage cid. Regression tests: a direct .ensure_cid unit test (empty/malformed/non-scalar replaced, valid kept, class+message preserved) and a G-INT end-to-end case (a raised commit whose condition carries "", a malformed cid, or NA still leaves a reconcilable open intent). 778 tests pass. CLAUDE.md: correct the stale "34 gates via pkgops" Part B wording to describe membership (every functional gate via pkgops; G12-G14 + G15 via rab-exercise; G11a/G11b via direct pkexec; G9/G-OWN are pkgops preview-side refusals).
Contributor
Author
Brings the merged coarse-`outcome` conformance fix (0.0.1.9) under the exported apt_<verb>() commit API. R/commit.R + test_commit.R auto-merged (the outcome-record and mutation-API changes are disjoint); DESCRIPTION/NEWS/CLAUDE.md reconciled by hand. Bump to 0.0.1.10. 788 tinytest green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The public API that completes the commit lifecycle -- the increment that makes pkgops mutation-capable. Each `apt_(preview, ...)` commits the `pkgops_preview` its `apt__preview()` twin produced.
What lands
Then it delegates to the already-reviewed `.commit_session` (committability gate, capability, polkit, open, commit, verify, write-outcome, signal).
Design points for review
Scope boundary
Deferred to the VM-gated increment: the durable outcome-record grammar (the `observed`/`changed` post-state fields), the plain-intent refusal record grammar, and the exact pkcheck rc->outcome split, all pinned against a real broker/polkit. The combined `apt__run()` (plan+commit) convenience is optional and not built here. Then slice 4 (`rctl` apt.*).
Verification
Held as a draft for review.