Changelog
All notable changes to the Pretorin CLI are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.28.9 - 2026-08-28
Fixed
- Authenticated caller identification (#438, PR #447). Authenticated API
requests now identify direct CLI and initialized MCP callers through the
bounded
X-Pretorin-Clientheader while leaving unauthenticated probes and the existingUser-Agentunchanged. Header normalization now strips non-ASCII input so an untrusted MCP client name cannot crash request setup. - Safe active-system name resolution (#441, PR #448). A single guarded
cached-name decision now covers plan, recipe, preflight, workflow, STIG, and
MCP context paths. API-environment, credential, and
PRETORIN_SYSTEM_IDdrift can no longer rewrite or authorize work against the wrong system, and local context displays no longer pair an overridden ID with a stale name. - Recipe preflight verification on evidence (#444, PR #449). Recipe evidence now carries a fresh source-verification snapshot derived from the recipe’s required preflight bindings, with the legacy attestation snapshot as a fallback. Recipe context, exact version, complete declared capabilities, source identity, and batch-wide snapshot agreement are required before the client reports the source as verified.
0.28.8 - 2026-08-28
Added
- First-class assessment-objective CLI workflow (#445). New
pretorin objectivecommands list and inspect objective readiness, initialize rows, start work, author narrative drafts, approve/reopen leaves, and link/unlink evidence through governed public endpoints. Rich and JSON reads keep objective-linked evidence separate from explicit expectation coverage and unconfirmed suggestions;control contextnow renders per-objective blockers while retaining its legacy fallback for older platforms. Structured API errors preserve approval codes and missing prerequisites.
0.28.7 - 2026-08-23
Added
- Privacy-bounded Plan execution post-mortems (#422). Terminal Plan transitions now submit durable, size-bounded execution telemetry grounded in observed categorical signals and Plan history. Raw arguments, outputs, prompts, and customer content are never retained; invalid model findings fall back to deterministic analysis, and delivery remains best-effort, sanitized, and idempotently retryable.
- Customer-managed deployment operations and runbooks (#425–#427, #432).
New
pretorin deploymentcommands manage persistent deployment identity, signed offline-license request/install/status flows, and staged Flux bootstrap, inspection, suspension, and approval. Public connected, air-gapped, licensing, operations, and troubleshooting guides document immutable signed release sources, explicit cluster contexts, hot license renewal, system-limit behavior, lifecycle banners, and optional Prometheus/Alertmanager rules. - Stable assessment-objective IDs and governed MCP workflows (#430, #434). Control references and CLI output now expose stable CMMC/NIST 800-171A objective IDs with legacy fallback. Agents can list, inspect, work on, approve, and link evidence to individual objective implementations, while control context includes per-objective status and evidence expectations.
- Signed self-update for standalone Linux x86_64 binaries (#428, PRs #429,
#435, and #436).
pretorin updateon a directly downloaded Linux x86_64 binary now verifies and replaces the running executable in place instead of printing manual guidance. The only trust anchor is the release-signing public key embedded in the binary at build time: it verifies the release’s signedSHA256SUMS, which in turn binds the newRELEASE-TAGasset (so a genuinely signed prerelease’s assets can no longer answer for the stable release of the same version) and the binary’s checksum; the downloaded binary is then asked what version it is. Nothing downloaded runs before the signature and checksum checks pass, the install is a single atomic rename, and any failure leaves the installed executable byte-identical — reported with a machine-readable category (sig-invalid,digest-mismatch,tag-binding,manifest-cutoff, …). Where the target is not writable (a root-owned/usr/local/bin), Pretorin never escalates: it retains the verified binary under~/.pretorin/updates/and prints one privileged command that re-verifies its own copy before installing it. No argument never downgrades and never installs a prerelease; an explicit version may, which is what makes prerelease and rollback installs possible. Homebrew still routes tobrew upgrade pretorin(brew owns the file), and macOS or other-architecture binaries keep manual guidance. RELEASE-TAGrelease asset and an embedded-key release gate (#428). Every release now shipsRELEASE-TAG, one line naming the release tag, written before the checksum step so its digest is covered by the signed manifest. The release pipeline’s signing job gates on the exported HSM key matching the key embedded in the CLI, so a drifted key stops the release instead of shipping a binary that would reject it.- Structured upgrade fields on the MCP CLI-status surfaces (#428).
get_cli_statusandstatus://clinow returnupgrade_requires_human_approval,upgrade_restart_required, and a route-specificupgrade_notealongsideupgrade_command, so a host knows that the command mutates the local install, must be surfaced to the operator rather than executed, and that the running MCP server keeps serving the previous version until it restarts.
Fixed
- Bounded single-rule MCP and CCI reads (monorepo #3188).
get_workflownow supports compact validation-equivalent schemas and complete Markdown section slices;get_test_manifestsupports exactrule_idfiltering plus paginated summary mode; andcci showfilters and pages linked STIG rules. Every bounded response reports explicit selection, pagination, and truncation metadata instead of relying on host-side result clipping. - Release builds tolerate transient Debian mirror failures (#421). Linux binary builds now retry package-index and dependency downloads instead of aborting the entire signed-artifact and Homebrew publication pipeline after a one-off connection reset.
0.28.6 - 2026-08-18
Added
- Consent (Privacy/ToS) re-acceptance handling (monorepo #3113). The CLI and
MCP server now consume the advisory
GET /consentendpoint and act on it with two deliberately different behaviors. The CLI is advisory: an interactive run shows a prominent reminder to log in to the web app and re-affirm, but the command still runs; a CI / non-interactive /--jsonrun prints the reminder to stderr and exits 0 — automation is never broken by default. The MCP server is a hard-stop: it refuses to run any tool while consent is definitively stale, returning a clearconsent_requiredresult (never a crash), gated once at the tool-dispatch layer with a ~60s TTL cache so mid-session bumps eventually block and re-affirms eventually unblock. Public grounding tools (check_context, etc.) stay exempt. Only a200is an answer — a404(endpoint not yet deployed / air-gapped),401/403/5xx, or a timeout are all indeterminate and fail open (the MCP never blocks, the CLI stays silent). The client only ever reads this signal; re-acceptance is recorded solely by the web app.
Changed
- Dependency, maintainability, and reference sweep. Updated supported dependency floors, consolidated local Markdown writer behavior, removed unused helpers, and synchronized the CLI, MCP, agent, workflow, and framework documentation with the shipped interfaces.
Fixed
- Cross-version and release automation reliability. Made MCP error-result assertions work with both supported SDK generations, hardened Codex runtime pin updates across Linux and macOS, and added regression checks for version, changelog, link, and generated-documentation consistency.
0.28.5 - 2026-08-14
Fixed
- Evidence expectation unbinding now requires platform confirmation. CLI,
MCP, and built-in-agent link operations forward an explicit
unbound_reasonand fail closed unless the platform confirms the binding was intentionally cleared, preventing local plans from recording an unbind that did not occur remotely.
0.28.4 - 2026-08-12
Added
- Deterministic Plan trajectory evaluations (#406). Added an opt-in P1-P8 cross-harness suite for real-agent Plan declaration, scope isolation, read-before-write behavior, recipe recovery, structured-error handling, step bookkeeping, premature-completion rejection, and fresh-session resume. Privacy-bounded traces retain only normalized operational metadata, and exact scenario intent markers constrain evaluation Plan cleanup.
Fixed
- Bounded, approval-safe
get_control_issuesreads (#395). The MCP and built-in-agent tools now filter bystatus, page withlimit/offset, compact Issue bodies to snippets by default, and put open Issues before closed history. Responses report page counts separately from matched counts, and the global MCP guard recognizes Issue result lists and gives tool-specific recovery guidance instead of allowing a positional head/tail excerpt to hide every open Issue. - Recipe content drift can be re-pinned (#394). Re-running
pretorin recipe activate <id>(orset_active_recipesinaddmode) now accepts reviewed content-hash drift when the recipe version and loader source are unchanged, reports the old and new hashes, and persists the refreshed pin. Version and loader-source drift still require removing the old pin before activating the current recipe, so upgrades and shadowing takeovers cannot silently inherit prior audit standing. - Agent and scripting paths are deterministic (#396).
--jsonnow emits structured usage and command errors without leaking JSON mode into later in-process invocations, plan-scoped custom control IDs compare case-insensitively, control status/context accept positional framework IDs while retaining--framework-id, and recipe-gap payloads distinguish ready sources from missing active recipes without repeating the host-wide ready set.
0.28.2 - 2026-08-08
Fixed
- Maintenance and documentation accuracy sweep. Corrected drift across the published documentation — the CLI and MCP command/tool references now match the live surface, the recipe authoring paths, framework catalog counts, campaign examples, agent environment semantics,
llms.txtpage list, and docs changelog are accurate, and a cross-reference test guards internal links, anchors, andSUMMARY.mdcoverage against future rot. - Correctness and packaging fixes surfaced by the sweep. The legacy agent runner honors declared turn budgets,
recipe validateflags unedited scaffold placeholders and rejects script names that cannot become MCP tool names, the PEP 561py.typedmarker ships so downstream consumers see types, and thepypdfandcryptographyadvisories are patched.
0.28.1 - 2026-08-06
Added
- Calibrated evidence-gap Issues (#402). Required active-tier evidence expectations that remain unobserved after a complete scoped search can now be tracked as clearly labeled, non-blocking Issues with expectation and search provenance, while open duplicates are suppressed and demonstrated control deficiencies retain their blocking behavior.
Changed
- SSP-aware recipe selection (#403).
ssp-gap-analysisnow requires an actual or explicitly designated SSP corpus. Generic repository documents route to workspace capture, and owner-attested review records can use the manual-attestation path.
Fixed
- CI formatting and generated-doc synchronization. Corrected the Ruff formatting mismatch and refreshed the committed mdBook output using the pinned CI toolchain.
0.28.0 - 2026-08-05
Added
- Bounded Issue Create and Issue Evaluate recipes (#397).
issue-createnow admits at most one independently supported gap against one stable expectation, requires a risk basis plus an explicit clearance condition and minimum evidence, derives a stable expectation-scoped idempotency key, and creates a minimal draft treatment plan after the Issue lands.issue-evaluatekeeps work on one existing Issue and ends in governed verification, one next action, time-bounded risk acceptance, an explicit void candidate, or an already-terminal result while surfacing plan, action, expiry, and review dates. Lifecycle precedence handles existing data honestly: an active acceptance does not require a remediation plan, every nonterminal source-owned Issue stays on its exact RFI/finding/AI-review workflow through verification, and planless non-source Issues must be reopened before treatment is added. Campaign apply uses the same admission contract, reuses matching Issues, and leaves malformed evidence or source/recipe gaps as proposal warnings instead of manufacturing Issues.
Changed
- Canonical Issue recipe terminology and compatibility boundary (#397). Recipe manifests can declare
produces: issues; normal recipe discovery and provisioning hide the deprecatedcontrol-note-attestationrecipe unless explicitly requested, while old recipe ids,produces: notes, legacy proposal input, and note tool aliases remain readable compatibility paths. Canonical MCP and campaign outputs now sayissuesandissue_countrather than emitting new note aliases.
0.27.2 - 2026-08-04
Added
-
First-class custom policy definitions across CLI and MCP (#366). Explicit YAML/JSON/stdin definitions now support validated preview-first creation and revision-safe configuration; ready custom policies share generation, review, mapping, submission, questionnaire, narrative, reopen, analytics, and campaign paths with core policies. Seven bounded MCP tools provide definition, suggestion, mapping, and submission parity, while approval remains human-only and Evidence Locker content is never promoted into a policy.
-
Non-interactive recipe execution (#368).
pretorin recipe executeruns a recipe without prompts, resolves manifest-declared platform inputs, creates a durable recipe execution anchor, and routes declared outputs through the inventory-diff, evidence, narrative, or inventory-attestation write path. CI consumers can use--json; exit codes are0for clean/submitted,2for detected inventory drift, and1for execution or submission errors.
Fixed
- Abandoned plan drafts remain prunable (#369).
pretorin plan prunenow removes unactivated drafts older than the shared age threshold, measured fromcreated_at, while preserving recent drafts, malformed activated-draft records, and all active plans. Dry-run and JSON output identify draft removals separately from terminal plans.
0.27.1 - 2026-08-04
Changed
- Evidence-to-expectation mapping and bounded narrative-quality gates for single-control agents (#387).
start_tasknow seeds a workflow-required mapping step and an immutable 800-character narrative completion criterion into every single-control Plan; activation preserves mapping immediately beforeevidence-narrative-compose, and later structural mutations cannot remove, duplicate, reorder, or weaken the workflow-owned gates. The mapping step cannot complete without an internally consistent structured record of active-tier expectation keys, non-empty evidence bindings for every covered key, intentionally unbound artifacts/reasons, and an exact post-link covered/uncovered/unbound read-back. Plan-attributed narrative writes refuse until that mapping record exists and return its coverage result in the normal handoff.link_evidencerequires an expectation binding or explicitunbound_reasonand records the choice in the Plan audit chain. Agent prompts now target concise 150–300 word narratives with an implementation overview, an exact populated expectation/behavior/evidence table, and supported operating detail; built-in drafting automatically retries one weak narrative and refuses a second short, bullet-only, empty-table, or unrelated-table result. Narrative review remains off by default and now requiresreview_requested_by_user=truealongsidetrigger_review=true; explicit overrides re-read coverage after the write, return a visible warning, and require exact-generation analysis.ai_analysisis explanatory read-only output: the platform reconciler owns AI finding Issues, and agents create Issues only from independently observed workspace/source gaps. - Headerless generated SSP bodies (#387). Generated control narratives and evidence now start directly with substantive content. Markdown, HTML, setext, and legacy standalone-bold section labels are removed across draft, recipe, agent, MCP, CLI, model, and API write paths; prompts prohibit new labels, fenced code and ordinary bold claims remain intact, and local evidence files no longer inject their own bold title.
0.27.0 - 2026-08-03
Added
-
Vendor TPRM reporting dashboard — CLI (#321). Adds
pretorin vendor dashboardwith bounded posture, tier/provider, residual-risk heatmap, and expiry reporting from the organization-wide vendor dashboard endpoint.--horizon-daysaccepts 1–365 days and--jsonpreserves the response body; 403 responses identify the required organization-scoped entitlement. -
Vendor TPRM reporting dashboard — MCP tool (#321). Adds
get_vendor_dashboardwith the same validated horizon and actionable 403 posture as the CLI; the response omits heatmap vendor rosters when needed to stay within the MCP result budget while retaining counts and discovery guidance. -
Server idempotency keys in campaign apply (#342). Campaign checkpoints now carry a per-run
run_idUUID, and every campaign create write — each evidence batch item and control-issue creation — sends a derivedidempotency_key({run_id}:{item_id}:{artifact_type}:{revision}:{index}). A resumed or retried run reuses the samerun_id, so the platform replays writes it already committed instead of duplicating them; a deliberate fresh campaign mints a new one.run_idis stored beside the checkpoint’sidentityrather than inside it, so resume identity validation is unchanged. Submitting a new proposal over an item that already has receipts bumps itsproposal_revision(and retires those receipts), so re-drafting a failed item writes under fresh keys instead of colliding with content the platform already bound to the old ones. Apply also probesGET /capabilitiesonce per run and recordsidempotency_support(supported/unsupported/unknown) in the checkpoint — an error response isunknown, neverunsupported, and keys are sent regardless of the result. Per-item"replayed"responses are recorded as successes carrying the original resource ids (still citable by the narrative, still skipped on resume) but do not re-trigger downstream steps, so a pure-replay run reports no material change and never re-posts the completion note.idempotency_key_conflictis a hard per-item failure that surfaces the platform’s remediation plus the CLI-side escape hatch, and now leaves a durable receipt. Also fixes issue receipts recordingissue_id: nullon the issues endpoint, which returns the record under anissueenvelope. Platform versions predating the feature ignore the field, so local receipts still only narrow — rather than close — the crash/retry duplication window until the CLI claims the guarantee from the capability probe. -
Canonical Issue lifecycle, treatment, and POA&M parity (monorepo #2745, #2853). The platform’s Issue model is no longer just an open/closed flag — it carries a versioned risk history, versioned corrective plans, ordered plan actions, POA&M facts, and its own lifecycle and approval-gate state.
pretorin issues listnow shows each Issue’s id, lifecycle status, gate status, whether it blocks approval, and its source; previously it printed only content, which left every treatment subcommand unaddressable because thecontrol_implementation_idandissue_idthey take were never displayed. A single control’s listing prints the shared implementation id once in the header. Newpretorin issues inboxlists issues across a whole system/framework instead of one control at a time, with--status,--source,--control, and pagination, and prints a Treatment IDs key so the full untruncated ids stay copy-pasteable. Newpretorin issues updateedits content, pinned state, or an existing closure note without touching resolution state — the resolution field is omitted from the request entirely, so editing a closed Issue can no longer reopen it as a side effect.plan-getandaction-getread one plan version (with its full approval lifecycle) or one action.plan-create/plan-updateaccept the CMMC Operational Plan of Action fields (--opa-basis,--review-frequency-days,--next-review-at) with the platform’s kind and pairing rules enforced before the call.poam-setnow reaches the five fields that were pinned to constants —--false-positive,--deviation-rationale,--operational-requirement,--operational-requirement-id, and an explicit--vendor-dependency— and documents that it is a full replacement rather than a patch.action-transition --statusis validated against the server enum, and--noteis required for theblockedandcancelledtransitions the platform rejects without one. -
get_system_issues,get_issue_plan, andget_issue_actionMCP tools. An agent could list one control’s issues but had no way to find remediation work across a system without walking every control, and no way to read a single plan version or action.get_system_issuesfilters by status, source, or one control with pagination, and normalizes through the same path asget_control_issuesso the two tools report the same blocking/non-blocking split rather than disagreeing about what gates approval; its page-scoped counts are reported alongside a separatematched_totalfor everything the filter matched server-side. All three are registered in thecontrol_issue_trackingcapability, sosearch_platform_capabilitiessurfaces them. -
Risk framing in local issue files.
pretorin issues createaccepts--title,--likelihood,--impact, and--risk-basis, and stores them in the file’s YAML frontmatter sopretorin issues pushintakes the Issue with the assessment its author intended. Every locally-authored issue previously landed on the platform as moderate/moderate with the body reused as the risk basis. Files written before these fields existed still read, defaulting to moderate. -
Governed canonical Issue lifecycle for WRITE/ADMIN tokens (#376, monorepo #2894). A WRITE or ADMIN API token is now a first-class governed actor for the whole Issue lifecycle, not just the authoring half. Nine operations land across the CLI, MCP, and client:
pretorin issues risk-confirmrecords the risk determination (distinct fromrisk-add, which stays provisional — confirming supersedes any active acceptance, recomputes gate status, and can demote the control’s approval gate);acceptandacceptance-revokerecord and withdraw a formal risk acceptance;plan-approve,plan-reject,plan-opa-review, andplan-completegovern a submitted treatment plan;verifycloses an Issue andvoidretires a finding that was never valid. The matching MCP tools areconfirm_issue_risk_evaluation,accept_issue_risk,revoke_issue_risk_acceptance,approve_issue_plan,reject_issue_plan,review_issue_opa,complete_issue_plan,verify_issue, andvoid_issue, each carrying its lifecycle precondition in the tool description. The full sequence an agent can now drive end to end is: add the Issue, confirm its risk, create and submit a plan, have it approved, transition every action to completed, complete the plan (which moves the Issue toverification_pending, not closed), then verify it (which closes it).plan-completeandverifyremain deliberately distinct steps. Void requires explicit--force/force=trueconfirmation on every client surface because the public treatment-plan listing does not safely expose the Issue lifecycle state; this prevents a verified closure from being irreversibly replaced with “this was never valid”. The built-in agent now exposes the same risk, acceptance, plan, action, verification, and void lifecycle. Two determinations stay interactive-only:poam-set --false-positiveand--operational-requirementare still rejected for API tokens.
Fixed
- Issue lifecycle parity hardening. Void operations now require explicit confirmation across the client, CLI, MCP, and built-in agent; the built-in agent exposes the complete canonical lifecycle; resource-level 404s no longer masquerade as unsupported platforms; and paired acceptance timestamps are normalized by instant.
- Campaign apply is evidence-first (#340). Accepted evidence now lands before AI narratives, and narrative writes cite the created evidence ids; narratives-only AI apply refuses without prior evidence receipts. Apply receipts remain durable across failures so retries do not duplicate evidence or issues.
- Issue listing filters no longer drop or widen results. The system-issues listing sent a comma-joined
control_idsto an endpoint that takes a singularcontrol_id, so the filter was accepted and silently ignored, and afamily_idthe platform now rejects outright with a 400 — which brokepretorin campaign controls --all-open-issues --issue-familyand made--issue-controlsa no-op. A family selector is now resolved to its member control ids first, and a family and explicit controls together intersect rather than widen. The family expansion also re-filters client-side on the family-scoped call, because a backend that ignores the family argument returns every control, which is indistinguishable from success and previously widened the selector to the entire framework. Listings page to exhaustion instead of capping silently at one 500-row page, and the client-side control filter reads control ids as leniently as every other consumer of those records, so a row is no longer dropped by a filter that the downstream reader would have kept. - Issue closure now works at all (#376).
pretorin issues resolveclosed an Issue by sendingis_resolved=truethrough the generic control-issue PATCH, which the platform rejects withissue_verification_required— so closure had never actually worked from the CLI, theresolve_control_issueMCP tool, the agent tools, or campaign apply, and no test covered the path. Closure now routes to the Issue verification endpoint: it resolves the Issue’scontrol_implementation_idfrom the control listing (which in the same call confirms the Issue exists under that control) and pre-flightslifecycle_status, so an untreated Issue reports the governed path to follow instead of a bare server conflict.pretorin issues verify <control_impl_id> <issue_id>is the canonical closure command andresolve’s closing behavior is a documented compatibility wrapper.--reopenand metadata-only updates keep using PATCH, which remains the supported path for both, and the client now refusesis_resolved=trueoutright so the dead path cannot be reintroduced. Campaign apply records a proposed closure as askippedreceipt naming the verification command rather than attempting a write that cannot succeed. Against a platform that predates these endpoints the CLI fails with an actionable compatibility error and never falls back — detection cannot key on 404 alone, because creating a risk acceptance answers 405 whereGETalready occupies the path, and confirming risk answers 403 from a guard on a route that always existed.
Changed
- Canonical Issue terminology corrected (#376). Risk confirmation, risk acceptance, plan approval/rejection/review/completion, verification, and voiding are no longer described anywhere as human-only or web-UI-only; they are WRITE/ADMIN token operations governed by server-side lifecycle rules.
is_blockingis now documented as the always-true compatibility flag it is: the canonical Issue domain has no non-blocking Issue, historicalfalserows were converted in place, and above-target AI-review advice is never filed as an Issue at all. The always-yes“Blocking” column is gone frompretorin issues list, whileis_blocking,blocking_total, andnon_blocking_totalare retained on the wire for clients that read them (non_blocking_totalis always 0). Above-target suggestions are described in their real home,ai_analysis.gaps_detail, whereis_blockinggenuinely can be false.verification_pendingremains distinct fromclosedthroughout.
Added
- Single-context Plan execution contract (#330). Routed work now starts as a scope-pinned draft, requires the calling agent to declare and activate executable steps before attributed writes, rejects vacuous completion with structured
plan_incompletedetails, returns only exact system/framework resume candidates with their next unfinished step, and supports optimistic-locked structural mutations with actor, reason, version increments, and immutable post-change snapshots. - Exact-context Plan resume in
start_task(#330). Repeatedstart_taskcalls no longer accumulate duplicate Plans. Before creating one,start_tasklooks for non-terminal Plans in the identical execution context — same workflow, same scope (system, framework, control, and any workflow-specific targets kept inscope.extra, such as questionnaire question ids or a campaign’s control filter), same intent verb, and the same prompt text ignoring case and whitespace. Matches are returned inresume_candidatesusing the same summary shape aslist_recent_plans; a single candidate is adopted and its id returned asplan_id, while two or more leave the choice to the caller. The new top-levelcreate_new_plan=trueargument forces a separate Plan. Candidates never cross a system or framework boundary.
Changed
- Plan schema documentation. Plan references now distinguish implemented fields from proposed
expected_outputs,deviations, andevaluator_results, and document thedraft → active → completed/cancelledlifecycle.
0.26.15 - 2026-07-25
Changed
- Automated maintenance and documentation sync (#339). Lint/type-check fixes, test-coverage improvements, dead-code removal, and dependency patches, plus a full documentation sync — CLI, MCP, and agent references regenerated against the actual codebase state,
llms.txtmanifests and mdBook output rebuilt, and stale references and broken links fixed.
0.26.14 - 2026-07-21
Fixed
- Guard-aware large policy reads (#319). The
get_policy_narrativeMCP tool now emits complete section content in bounded, self-describing pages, supports compact index and single-section reads, and fails explicitly when one section cannot fit the MCP budget.get_org_policy_questionnairegains aninclude_guidance=falseprojection for retrieving large questionnaires without static template guidance.
0.26.13 - 2026-07-21
Added
get_policy_narrativeread tool for safe surgical policy edits (#312, monorepo #2282). Adds the MCP toolget_policy_narrative, the CLI commandpretorin policy narrative, and the client methodPretorianClient.get_policy_narrative, all readingGET /org-policies/{id}/sections— the read counterpart toupdate_policy_narrative. Returns the ordered generated sections (section_id,order,title,content, review/framework metadata) so an agent can read the current narrative, modify or append one section, and write the full list back without dropping existing sections. Previously the only read wasget_org_policy_questionnaire(the Q&A template, not the generated sections), forcing a blind full-replace. Requires the monorepo backend endpoint from PR #2345. Unblocks monorepo #2283.- Vendor assessment portal lifecycle. Added
pretorin vendor assessment send|resend|revoketo mirror the public vendor-assessment portal lifecycle endpoints. Send/resend support repeatable recipient emails, configurable 1–365 day expiry, and an optional message; revoke accepts an optional audit reason. Human output shows delivery and token metadata, while JSON mode preserves the platform entitlement envelope. - Vendor Management Phase 4 vendor↔system mapping & residual-acceptance. New
pretorin vendor systemscommand group (list/attach/detach) andpretorin vendor residual-acceptance signmirror the platform’s SR-5 / SA-9 vendor↔system endpoints, backed by four MCP tools (list_vendor_systems,attach_vendor_systems,detach_vendor_system,sign_vendor_residual_acceptance).attachtakes one or more--system-idvalues;signrecords authorizing-official acceptance of a vendor’s residual risk for one attached system and is idempotent per(vendor, system). Signing is gated on the org’s evidence attestation-envelope capability and attestation process mode — when disabled the platform returns HTTP 503, which the CLI and MCP surface as an actionable message rather than a raw error. SR-6 (review-record) and SA-9/SR-5 (contract-record) evidence continues to be synthesized and signed server-side during the review/contract flows. - Vendor Management Phase 3 contacts & contracts. New
pretorin vendor contactandpretorin vendor contractcommand groups (list/add/update/delete) and eight matching MCP tools (list_vendor_contacts,create_vendor_contact,update_vendor_contact,delete_vendor_contact,list_vendor_contracts,create_vendor_contract,update_vendor_contract,delete_vendor_contract) mirror the platform’s vendor contact and contract/SLA/DPA sub-resources. Contacts carryname,email,title,phone,is_primary(auto-demotes the prior primary), andnotes. Contracts carryname,contract_type(contract/sla/dpa/order_form), date/renewal/notice/termination fields, and a linked document evidence item; the server-derivedstatusandis_expiredare rendered read-only and cannot be set. All contact/contract endpoints require the server-sidevendor.piiscope (or an admin token). - Vendor Management Phase 3 core. New
pretorin vendor lifecycle <vendor_id> <target_status>command andset_vendor_lifecycleMCP tool transition vendors betweenonboarding/active/inactivewith a required audit--reason(≤500 chars); the endpoint requires the server-sidevendor.piiscope (or an admin token).vendor list/list_vendorsgain--include-inactiveand--lifecycle-statusfilters, and vendor listings/details now surface lifecycle status and document-expiry flags (has_expired_document,has_expiring_document).vendor upload-doc/upload_vendor_documentaccept--expires-atand--refresh-cadence-daysfor document expiry and refresh reminders, andvendor list-docsnow showsexpires_atandis_expired.vendor assessment launchprints an actionable message when a vendor is inactive.
Changed
- Backward-compatibility call-out:
pretorin vendor list(and thelist_vendorsMCP tool) now omit inactive vendors by default. Pass--include-inactive(CLI) orinclude_inactive=true(MCP) to restore the prior behavior of listing every vendor. Evidence citation / inheritance likewise excludes inactive-vendor evidence.
0.26.12 - 2026-07-19
Changed
- Automated maintenance and documentation sync (#309). Lint/type-check fixes, test-coverage improvements, dead-code removal, and dependency patches, plus a full documentation sync — CLI, MCP, and agent references regenerated against the actual codebase state,
llms.txtmanifests and mdBook output rebuilt, and stale references and broken links fixed.
0.26.11 - 2026-07-16
Fixed
- Scoped preflight source discovery (#306). CLI and MCP preflight now discover scoped local, provider, IaC, and Pretorin system-of-record bindings, verify Pretorin feature resolvers against authenticated system access, and merge discovered coverage without replacing manually authored resolvers. Explicit declarations remain partial, and only live probes or verified Pretorin features satisfy source capabilities, preventing false unmapped or degraded results.
- K8s asset inventory node OS + explicit namespace environment (#304).
asset-inventory-k8s-baselinenow captures each node’s OS fromstatus.nodeInfo.osImageintoos_ios_fw_version(guarded — left unset, never fabricated, when a node omits it), so SOC 2 System Description DC 3.x component tables carry real OS values instead of[INSERT: operating system].pretorin scope artifacts inventory scan k8sgains a--namespace-envoption that threads an explicit namespace→environment map (e.g.{"pretorin":"dev","pretorin-prod":"prod"}) into the recipe, layering over the built-in namespace defaults so dev components stop defaulting toprod. Invalid or non-k8s uses of the flag fail loudly. Pairs with the monorepo generation-side fix (#2162).
0.26.10 - 2026-07-15
Fixed
- Baseline expectation MCP contract (#301, #302). MCP workflow and analytics tool descriptions now document the platform’s unmet baseline-tier expectation count, while family review results document optional
expectation_tierandtier_labelmetadata. Regression coverage confirms the additive response fields pass through the MCP andstart_tasksurfaces unchanged.
0.26.9 - 2026-07-13
Fixed
- Scope-document type evidence surfacing (#293). Evidence models, CLI listings, and MCP search responses now preserve the platform’s
scope_document_type_labelandscope-template:<id>tags, deriving a clear NIST SSP or SOC 2 System Description label without parsing evidence names.
0.26.8 - 2026-07-12
Changed
- Automated maintenance and documentation sync (#297). Lint/type-check fixes, test-coverage improvements, dead-code removal, and dependency patches, plus a full documentation sync — CLI, MCP, and agent references regenerated against the actual codebase state,
llms.txtmanifests and mdBook output rebuilt, and stale references and broken links fixed.
0.26.7 - 2026-07-11
Fixed
- STIG-less capture-plan routing (#288). Capture plans now use
workspace-capturefor generic manual-review and attestation expectations whenmanual-attestationhas no concrete STIG id or does not apply to the control/framework scope. Scoped STIG expectations retain the manual-attestation recipe.
0.26.6 - 2026-07-10
Added
- Framework-aware scope document surfacing (#291).
ScopeResponsenow carries the platform’s additivetemplate_id,template_label, anddocument_titlefields, so the CLI and MCPget_scopepassthrough can tell which document a system is scoping (SOC 2 System Description vs NIST SSP scope).pretorin scope showprints aDocument:header line when the platform supplies a label, and thescopehelp text notes that the question set and section labels are framework-dependent. Purely additive —scope_narrative/scope_qa_responsesstay opaque and older platforms that omit the fields render unchanged.
0.26.5 - 2026-07-06
Fixed
- Narrative markdown validation (#286). Narrative writes now accept the natural “prose plus one structural element” shape: a single list, table, or code block satisfies the auditor-ready richness requirement. Tool descriptions, agent prompts, docs, and validation errors now point authors at that actionable fix instead of requiring throwaway inline markdown.
- Family recipe contexts for multi-control authoring (#286).
start_recipewithout acontrol_idnow opens a family context scoped tosystem_id+framework_id, allowing one narrative or issue-attestation context to stamp writes for multiple controls in the same scope. Single-control contexts still pin writes to one control, and each platform write continues to name its owncontrol_idfor per-control audit metadata.
0.26.4 - 2026-07-05
Documentation
- Service Description page (#282). Added a customer-facing Service Description covering data categories and sensitivity, shared responsibilities, support, and security-concern reporting, linked from the docs nav and LLM indexes.
Fixed
start_recipefriendly system-name regression coverage (#283). Added regression tests provingstart_recipeaccepts the active system’s friendly name and older configs can resolve that name through the platform fallback before writing the recipe execution.
0.26.3 - 2026-07-04
Fixed
- Compact
search_evidenceparity (#277). The API client, MCP tool, built-in agent tool, and CLI search command now mirror the platform’s compact-by-default evidence search contract: RAG query mode defaults to 5 results, preservesmetadata_key_count/control_mapping_count/ truncation markers from compact responses, and exposesinclude_metadata(plus the MCP/agentinclude_full_detailalias) to opt into full per-result metadata and control mappings when needed. The CLI and tool wrappers also forwardsnippet_charsto the server-side search endpoint while keeping local response compaction as a guard for older or oversized responses. - Kubernetes asset inventory normalization (#276).
asset-inventory-k8s-baselinenow emits platform-validasset_typevalues (containerfor workload controllers andendpointfor LoadBalancer Services), infers environment from labels or namespace defaults such aspretorin -> devandpretorin-prod -> prod, and leaves unknown environments unset instead of guessingprod. Shared inventory enum constants now drive recipe normalization and MCP tool docs, and the AWS/Azure recipe descriptions now match their v0.1.0 EC2/Compute VM scope.
0.26.2 - 2026-07-03
Fixed
- Single-control
start_taskMCP result size (#273). A single-controlstart_taskresponse no longer overflows the MCP result token cap (it was ~75 KB and forced the host to spill to disk, breaking the documented “callstart_taskfirst” entrypoint). The compact capture plan now drops the top-levelrecipe_gapsarray — a verbatim duplicate of the per-itemrecipe_gap— in favour of arecipe_gap_count(the per-itemrecipe_gapstays canonical); lifts the hostready_source_kinds/ready_alternative_recipe_idslists (identical on every gap) to one top-levelready_alternativesobject each gap points at; and drops the per-itemreasonwhen it is a verbatim copy ofrecipe_gap.reason. The routed/ambiguousstart_taskresponse also summarizesinspect_summary.org_policiesto anorg_policies_count(calllist_org_policiesfor the full list), and the compactresponse_modepath now applies to single-control the same way it already did to multi-control. Realistic single-control responses drop from tens of KB to a few KB; full per-item detail is always available inline or viacheck_sources/list_org_policies. - Global MCP response-size guard (#273). Every MCP tool result is now measured against a byte budget (
PRETORIN_MCP_MAX_RESULT_BYTES, default 40 KB) at the server dispatch boundary before it is returned, so no handler — current or future — can overflow the cap. When a success result is over budget the guard reuses the existing response compactor to bound result lists (with explicit{key}_truncated_countmarkers) and, only as a last resort, returns a compact summary naming what was truncated and how to retrieve the full data. It never silently drops audit-critical or record-internal data (record-internal lists such as control mappings are never bounded), leaves error results untouched, and is idempotent with each handler’s own per-path compaction.
0.26.1 - 2026-07-02
Added
- CI/CD evidence capture recipe (#273). Added the first-party
ci-evidence-capturerecipe for code-native change-management and SDLC controls, covering GitHub Actions workflow runs, required checks, branch protection/rulesets, and deployment environment protection. Capture planning now ranksci_cd_platformandcode_repositoryahead of ticket/document hints for clearly code-native expectations, so ready CI/CD sources no longer fall through to weak manual-attestation suggestions. - Preflight unbind command (#273). Added
pretorin preflight unbind <kind> --name <resolver>to remove stale resolver bindings without editing the local artifact by hand.
Fixed
- Preflight completeness and honesty (#273). Preflight artifacts now expose a
source_profilesummary over platform-recommended source kinds, and CLI/MCP/provisioning/capture-plan output surfaces unmapped, unverified, and missing recommended kinds as explicit gaps. “All recommended sources ready” now means all platform-recommended kinds are ready, not merely all locally bound kinds. - Command probe execution (#273). Resolver
params.probestrings now run throughsh -c, so shell operators and environment expansion behave as users expect; explicitparams.commandargv lists still run directly. - MCP write-path robustness (#273). Workflow, recipe, and vendor/responsibility handlers now resolve system names to IDs before platform writes where needed, and
code_line_numbersis validated as a single line or range with clear guidance to usesource_locatorfor multi-range or multi-file provenance instead of surfacing a platform 500.
0.26.0 - 2026-07-02
Added
- Platform-seeded preflight (#242, #243).
get_preflightnow also reads the platform’s in-scope recommended source kinds for the scope when authenticated and seeds them into the local artifact (persisting only when the profile actually changed something; offline it stays a pure local read).get_source_manifestfalls through to the platform’s recommended source kinds when no local manifest exists, and confirmed scope scale (cached_scale_tier) surfaces inpretorin context list,pretorin scope show, and system reads.pretorin preflight initseeds platform recommendations for the scope and restricts default bindings to them. Platformscope_incompleterefusals now stopstart_task/get_control_context/check_sourceswith the platform’s own message instead of degrading into an empty capture plan. - Preflight binding scope reaches recipe execution (#240). Resolver bindings gain first-class
constraints(free-text usage note) andscope(structured usage intent, e.g.subscription/region) viapretorin preflight bind --constraint/--scope. Binding-derived scope becomes recipe param defaults on both surfaces — MCPstart_recipereports them assource_params,pretorin recipe runprints the applied defaults — with explicit caller params always winning. Scope never crosses cloud providers (anaz-identifiable binding won’t feed an AWS-kind recipe), and only binding-derived scope acts as a script default — caller-supplied recipe params never silently become a later script call’s default. - Recipe activation layer — the cookbook → active-set model (RFC 0002). Recipes are now two layers: the full cookbook (every loadable recipe) and a per-
(system, framework)active set — the curated subset provisioned for one compliance effort, persisted on the scope’s preflight artifact and seeded during preflight from the ready source kinds. New MCP toolsget_active_recipes(active set + candidates + coverage gaps + version drift) andset_active_recipes(replace/add/remove); new CLIpretorin recipe activate/deactivate/active,pretorin recipe list --active, andpretorin preflight provision [--apply].list_recipesannotates each recipe with anactiveflag and acceptsactive_only. Once a scope is provisioned,start_reciperefuses recipes outside the active set (force=truefor a one-off), and the capture plan draws candidates from it. Preflight artifact schema bumped to v2; v1 artifacts auto-migrate (unprovisioned scopes fall back to the whole cookbook — non-breaking). - Public STIG checklist import/export (
.ckl/.cklb/XCCDF) (#189). Newpretorin stigsubcommands wrap the platform’s STIG Checklist Workspace public surface:checklists(list per-asset checklists),create-checklist(bind a benchmark + asset),export <checklist-id> [--format ckl|cklb](download a regenerated DISA checklist and print its SHA-256), andimport <checklist-id> <file> [--format auto|ckl|cklb|xccdf](push a review-axis.ckl/.cklbfile, or route--format xccdfto the system test axis). The same surface is exposed over MCP (list_stig_checklists,create_stig_checklist,export_stig_checklist,import_stig_checklist,import_stig_checklist_xccdf) so agents can drive it as tools. Theopenscap-baselinerecipe now surfaces its XCCDF results path so a scanner run can land a reviewable checklist that round-trips back out via export for the air-gapped eMASS handoff.
Removed
list_connected_sourcesMCP tool. Source availability is decided by the local preflight verdict (get_preflight/verify_preflight), not the platform connection registry, so this read no longer drove any decision. Useget_source_manifestandcheck_sourcesfor source preflight.
Fixed
- MCP result sizes on hot paths (#247). Multi-control
start_tasknow returns a bounded per-control capture-plan summary (counts, statuses, atop_capture_hintper control — full per-expectation detail viacheck_sources), and RAGsearch_evidencerequests are clamped to 10 results across MCP, CLI--json, andpretorin agent run. The response compactor bounds only result lists (marked with{key}_truncated_count) — record-internal lists such as control mappings are never silently truncated. The CLI gains--full-body/--max-body-chars/--snippet-charsparity with the MCP knobs, and the interactive table honors--limitunclamped. - Capability semantics are consistent everywhere. An up resolver that declares no capabilities is general-purpose (satisfies required capabilities) across kind rollups, capture-plan gap detection, and recipe availability — matching
matching_resolvers’ documented opt-in rule. Defaultpreflight initbindings no longer flip to permanentlydegradedthe moment the platform seeds capability-annotated kinds; a resolver that does declare capabilities is held to them. Re-seeding never erases a stored required-capability gate with an empty platform value, and alias merges keep the strongest requirement level rather than last-writer-wins. - STIG checklist surface hardening. Export refuses to clobber an existing file under a server-chosen name without
--force(CLI) oroverwrite=true(MCP, which also refuses symlinked targets — its only local file write is no longer an arbitrary-overwrite primitive). Checklist writes enforce the active-context system boundary; a non-reconciling import returns an error result over MCP just like the CLI machine path; theContent-Dispositionbasename sanitizer also strips Windows drive-relative prefixes (C:evil.bat); and import transport failures surface asPretorianClientErrorlike every other client call. Theopenscap-baselinerecipe accepts aprofileparam (SSG datastreams select rules per profile — without one the scan evaluated an empty selection) and cleans up its temp results file when a scan is cancelled. - Provisioning engine hardening.
replacemode can no longer destroy data on unresolvable ids: already-active ids the caller listed are preserved even when the cookbook can’t resolve them, a replace naming only unknown ids aborts untouched (no active-set wipe, no unprovisioned→provisioned-empty flip), and dropped ids are reported asdeactivated. The activation content digest streams full file content (no 1 MB blind spot), refuses non-regular files and script paths outside the recipe directory, and length-frames every field so boundary shifts can’t collide. No-op provisioning calls (typo’d ids) no longer create and persist empty preflight artifacts, andpretorin recipe activatewith only unknown ids exits non-zero. check_sources/ capture-planrecipe_gapdead-ends (#248). A control whoseai_guidancesource hints point at a source kind no recipe covers (e.g. enterprise-SaaS kinds likesiem_log_platform) no longer returns a bare “no installed recipe can produce evidence” dead-end.recipe_gapnow reconciles against the preflight ready-set — it reports the host’s ready source kinds and the recipes that can substitute, and, on a provisioned scope, reframes as “no active recipe covers this; activate or add one.” The capture plan draws candidates from the scope’s active recipe set when provisioned.- Structured API refusals now surface a readable reason (mirrors the monorepo per-framework control-scope gate).
_handle_errorpreviously passed a dictdetailstraight through as the error text, so a structured 409 refusal (scope_incomplete, and the new per-frameworkcontrols_scope_not_approvedgate) rendered as a stringified dict inerror.message— e.g. the capture-plan control-context read showed{'code': ..., 'message': ...}instead of the human sentence. The client now extracts the refusal’smessageas the error text and keeps the full payload (includingcodeandscope_page) inerror.details, so callers and the agent see the actual reason (“approve control scope for this framework on the platform…”) and can still branch oncode. Likescope_incomplete,controls_scope_not_approvedis a human/platform action the CLI cannot self-serve. - MCP hot-path response sizes (#221).
start_task.suggested_capture_planandcheck_sourcesnow compact verbose per-expectationsource_hintsby default, returningsource_hint_countplus apreferred_source_hintsummary unlessinclude_source_hints=trueis requested. RAGsearch_evidenceresponses now replace body-sized fields such asartifact_contentandmatched_textwith snippets and omitted-character counts by default; callers can opt into capped body content withsnippet_only=falseandmax_body_chars. - Recipe-context evidence tally follow-up (#201).
create_evidencenow reconcilesEvidenceUpsertResult.createdwith the platform’soperation_status, so platform idempotency responses such asreused/already_linkedno longer bumpevidence_countor appendproduced_evidence_idsafter a stale client-side dedupe miss. The batch tally path is pinned to the confirmed platform contract: only per-itemstatus: "created"counts as a produced row; generic success strings do not. generate_inheritance_narrativesent no request body. The client posted only aframework_idquery param and no JSON body, so the platform returnedbody: Field requiredand inheritance narratives could not be generated via MCP/CLI. It now sends a populated body (control_id+framework_id); the backend derives the responsibility fields from the stored edge. (#1558)
0.25.1 - 2026-06-29
Added
- Preflight setup bootstrap. Added
pretorin preflight init, a local-only bootstrap that binds sensible defaults for the current workspace and common host tools (gh,az,aws,kubectl), skips existing mappings unless--replaceis supplied, and verifies by default.
Changed
- CLI recipe discovery can use preflight availability.
pretorin recipe list --system <id-or-name>now applies the same local preflight source gating as MCPlist_recipes, including--framework,--produces, and--include-unavailable.
Fixed
- Preflight hardening follow-ups. Secret-shaped strings are now redacted from resolver params, success command details, verification results, CLI JSON output, and MCP
get_preflight/verify_preflightsummaries before they can be persisted or returned. JSON probe output now surfaces a useful identity instead of a bare{, andpretorin preflight showdisplays details forunverifiedrows such as rejected workspace markers. - Typed CLI
--paramvalues.pretorin preflight bind --param key=valuenow coerces numeric/boolean values to JSON scalars, so--param timeout=60is honored (previously stored as the string"60"and silently ignored, falling back to the 30s default). Path, glob, probe, and name values stay strings.
0.25.0 - 2026-06-29
Added
- Searchable Platform Capability Index for MCP agents. Added
search_platform_capabilities, a public, unauthenticated discovery tool that lets agents ask whether Pretorin already has a product system of record for a compliance requirement before creating local trackers, spreadsheets, registers, or placeholder artifacts. The local catalog is product-facing only, covers MCP-exposed, MCP-readable, and platform-UI-only surfaces such as vendor assessments, formal assessments, reports, eMASS, and SPRS, and is pinned by tests so advertised MCP tools stay in sync. - Preflight — CLI-local source resolution and verification (#203, #210). A new layer that fixes the root cause behind locally-reachable sources being reported as “not connected.” The platform recommends canonical source kinds per framework, but only the CLI host can verify reachability — so availability is now decided by a local preflight verdict, not the platform connection registry.
- Open resolver layer (
pretorin.resolvers). Each recommended source kind maps to a collection of host-local resolvers (each tells a distinct piece of the evidence story). A resolver has an opentype+params; its only hard contract is “can I be verified?”. Built-in verifiers:workspace_path,cli_tool(gh/az/aws/kubectlauth probes),command(generic),manual/attested(user-asserted, never silently “connected”), plus probe-or-unverifiedformcp/connected_api/pretorin_feature. The registry fails open — unknown types with a declared probe run it, otherwise reportunverified. - Preflight artifact + store (
pretorin.preflight). A local-only, per-(system, framework)index under~/.pretorin/preflight/(atomic writes, schema-versioned). Per-kind rollup: all resolvers up →ready, some →degraded, none →missing, none-probed →unverified, none-bound →unmapped. preflightworkflow +pretorin preflightCLI + MCP tools. The interactive workflow maps recommended kinds to resolver collections, verifies them, and reports the verdict.pretorin preflight show / verify / bindis the human surface;get_preflight/verify_preflight/update_preflightare the agent surface.- Recipe
capabilities+ executor grain.SourceRequirementgains an optionalcapabilitieslist.start_recipenow consults preflight and refuses to open a context when a required source kind is verified missing (overridable withforce=true); unknown/unverified fails open, so planner and executor agree.
- Open resolver layer (
Changed
- Source availability now reads the preflight verdict, not the platform registry.
capture_plan,list_recipes, andcheck_sourcesdecide availability from the local verdict. An absent/empty verdict reads assource_unknown(a soft “verify before capture”), and only a verified-missing kind reads assource_unavailable— the old empty-registry false-negative is gone.list_connected_sourcesremains as an informational platform read but no longer drives availability.
Fixed
- Preflight hardening. Probe stdout/stderr captured in preflight artifacts is now redacted and length-capped before persistence, probe timeouts are clamped, workspace marker globs reject absolute paths and parent traversal, and local preflight artifact files are written with owner-only permissions.
- Narrative markdown validation (#204). The gap-discussion guard now stays scoped to gap-framing labels such as
Gap:,Not yet:,Should:, andTODO:while allowing legitimate security-control vocabulary like remediation SLAs, exceptions, risk acceptance, findings, breach containment, and closure evidence. Narrative rich-element docs now also call out inline code, matching the validator. set_control_responsibilityMCP tool — sends a complete request body. The client previously sent onlyresponsibility_mode,source_type, andvendor_provider_id, missing thecontrol_id,framework_id, andsource_control_idfields the platform’sCreateResponsibilityEdgeRequestrequires and using the wrong key name for the vendor (vendor_provider_idinstead ofsource_provider_id). The platform returned 422 and the agent could not set inheritance edges via MCP — observed on the SOC 2 PTR-SOC2-AVL-007 walkthrough and again on PTR-SOC2-AI-003. The client now constructs the full body, normalizessource_control_id(defaulting to the target control id for the common vendor-inheritance case where the source covers the same control concept), mapsvendor_idtosource_provider_id, and accepts an explicitsource_system_idfor org-system inheritance. The MCP tool schema exposessource_control_idandsource_system_idas optional inputs and the handler forwards them to the client.
Removed
- Dead registry-availability machinery.
recipe_source_availability,ConnectedSourcesResult.connected_kinds/connected_recipe_kinds/connected_capabilities, and the recipe-alias expansion helpers inpretorin.sources(superseded by the preflight verdict). The never-built_probes/library promised in RFC 0001 is dropped in favour of the open resolver layer.
0.24.2 - 2026-06-28
Changed
- Maintenance sweep — code health and documentation sync. No user-facing CLI, MCP, or schema changes. Extracted the duplicated
override_system_mismatch/override_reasonvalidation in the evidence MCP handlers into a sharedresolve_override_or_errorhelper; added unit coverage for the InSpec and OpenSCAP scanners (0% → ~95%/98%); refresheduv.lock(no vulnerabilities, dropped the now-unusedtypes-requeststransitive); and appliedruff formatto a handful of test files. The accompanying documentation audit re-synced every reference surface against live CLI/MCP behaviour — README,CLI.md/MCP.md, the CLI command reference and feature pages, the MCP tool counts (129 static + 22 per-recipe-script), framework pages, environment variables, and thellms.txtmanifests — then rebuilt the committed mdBook output with no remaining dead or unresolved internal references.
0.24.1 - 2026-06-27
Fixed
- Binary distribution follow-ups. The release pipeline now mirrors the air-gap OCI archive and SBOMs to the public tap, includes every shipped SBOM in the signed
SHA256SUMS, and verifies the air-gap archive token-free from the tap before declaring a stable release customer-ready. - Keyed cosign verification docs and gates. Binary-distribution docs now include the required
--insecure-ignore-tlog=trueflag for keyed signatures without Rekor entries. - Release hardening. The reusable binary build receives only explicit Apple notarization secrets, the Homebrew formula renderer fails closed when a real release manifest omits a platform asset, release tap pushes retry safely after rebase failures, and
pretorin link --forceno longer auto-removes a directory at the canonical MCP path.
0.24.0 - 2026-06-26
Added
- Scope artifacts — “scope” is now more than the questionnaire (epic #212). A complete capability to produce and connect the system-spec scope artifacts (authorization boundary, network data-flow diagram, PPSM, interconnection, and the asset inventory) so they appear attested on the platform’s scope page rather than as orphaned evidence rows.
scope-artifactsworkflow +scope_artifactsintent verb.start_taskroutes scope-artifact intent to a dedicated workflow (distinct from theanswerquestionnaire loop) that walks each system-spec kind: produce → upload → link → attest.- Three system_spec MCP write tools —
link_spec_snapshot,attest_spec_snapshot,attest_spec_inventory— wrapping the platform’s/spec/snapshots/*and/spec/inventory/attestendpoints.kindis free-form (validated againstlist_artifact_requirements) so the CLI can’t drift from the platform’s kind registry. All three are workflow-tier writes that threadplan_id/step_indexand recordPlanArtifacts (new kindsspec_snapshot_link,spec_attestation) into the plan’sproduced_artifacts[]audit chain. - Plan completion gate
all_required_spec_kinds_attested. A new typedAcceptanceCriterionKindwhose evaluator refusescomplete_planuntil every required (non-toggled-off) system_spec kind on the system is attested — turning the epic’s Definition of Done into a machine-checkable gate. It fails closed: a read failure or malformed response refuses completion rather than passing vacuously. Workflows declare default gate criteria via a newacceptance_criteriafield on the workflow manifest, andstart_taskseeds them onto the plan at instantiation. - General-purpose HTML evidence composer (
pretorin.evidence.html). A reusable sibling to the markdown composer:compose_html_documentwraps a body fragment (inline SVG diagram, a table) in a self-contained, design-consistent Pretorin-branded document shell (inline brand CSS, no external resources, no web-app chrome) with a provenance footer;render_tablerenders escaped brand-styled tables. Markdown stays the default; HTML is the opt-in path for rich-visual evidence. A documented SVG class vocabulary keeps agent-authored diagrams consistent without a layout engine. scope-artifact-composerecipe — the first consumer of the composer; produces each snapshot-kind document (diagram or table) from reachable sources with redaction and provenance, ready for the workflow to upload + link + attest.- Richer diagram vocabulary + completeness guidance. The brand kit gained
pt-cluster/pt-external/pt-actor/pt-flow-mgmtclasses so boundary and network/DFD artifacts can represent the compute substrate, external systems, human actors (incl. developers/operators), and the management/control plane — not a “users → app → db” sketch. The recipe and workflow carry a Completeness checklist (actors, compute substrate, management plane, CI/CD, every external integration/identity provider, data stores, ingress/egress, public-vs-private connectivity) and direct the agent to reconcile the diagrams against the scope narrative (get_scope). - Clean, full-size diagrams. The recipe documents a generic layout technique — trust-tier lanes (actors → edge → compute substrate → managed services → externals), orthogonal connectors routed in the gutters, services columns ordered to match their consumers, and bundled egress trunks — so connectors and labels don’t cross. Out-of-scope systems are kept out of the diagram view (they belong in the scope narrative, not the boundary). A new wide document mode (
compose_html_document(wide=True)→pt-doc-wide+ a horizontally-scrollingpt-figure, plus awideparam on the compose recipe script) renders a large boundary/DFD at full size instead of squeezing it into the 760px prose column. An optional geometry helperpretorin.evidence.svg_layout(SvgCanvas+anchor+route_*) implements the layout moves — boxes, zone/cluster/boundary containers, orthogonal connectors with arrowheads, collision-aware labels, all emitting thept-*classes — so agents don’t hand-roll diagram geometry; it’s an authoring aid, not an auto-router, and hand-written SVG stays fully supported.
Fixed
start_taskvalidation errors are now path-qualified — fixes walkthrough Bug #15. When a calling MCP agent omitted a required field from insideentities(e.g.intent_verborraw_prompt), the handler previously returnedentities failed schema validation: <pydantic-default-string>. Pydantic’s default string puts the missing-field name on a separate line, and most calling agents read only the first line — so the agent saw a bare'intent_verb' is a required property, addedintent_verbat the top level (the wrong place), and looped through several retries before discovering the nesting requirement. The handler now parsesValidationError.errors()and emits oneentities.<path>: <msg>line per error, plus a one-line reminder that all prompt-derived fields must live inside theentitieswrapper. Bug #9 (PR #198, 2026-06-24) was supposed to close this in docs; the recurrence on 2026-06-25 showed docs alone weren’t enough — the error string is what the agent actually reads. Two regression tests added intests/test_mcp_engagement_handler.py(test_missing_intent_verb_error_is_path_qualified,test_missing_raw_prompt_error_is_path_qualified).end_recipeacceptsrecipe_context_idfor parity with sibling tools — fixes walkthrough Bug #16.update_narrative,add_control_issue,resolve_control_issueall accept the recipe-execution handle asrecipe_context_id, butend_recipewas the lone exception that requiredcontext_id. Calling agents that closed the lifecycle in sequence hit a validation wall on the last call every time. The schema and handler now accept the canonicalrecipe_context_id; the legacycontext_idparameter is still accepted with a deprecation warning logged throughlogger.warning(...)so no existing caller breaks. Empty or null context arguments now receive the canonical missing-argument error instead of being stringified into misleading unknown context ids, and the MCP reference/workflow examples now teachrecipe_context_id. Four regression tests added intests/test_mcp_recipe_handlers.py(test_end_recipe_accepts_recipe_context_id_for_parity,test_end_recipe_legacy_context_id_still_works,test_end_recipe_missing_context_argument_errors,test_end_recipe_empty_context_argument_errors). Discovered during the SOC 2 CONF-002 walkthrough onpretorin-public-platform.- Pending-question routing dead-end (#208).
start_taskrouted a completed scope to the dead-endscope-questionworkflow because the router ranbool()on theget_pending_*_questionsdict (always truthy) instead of readingpending_count. Fixed for both the scope and policy paths, and the scope-artifact intent now has a real destination. answer_scope_question/answer_policy_questiondoc mismatch (#209). The scope-q-answer / policy-q-answer recipes and the scope-question / policy-question workflows instructed the agent to pass arecipe_context_idthe tools don’t accept; reconciled all four bodies to the actual schema (the active recipe context is applied server-side).- Stale system_spec client payloads.
link_snapshotsentevidence_id(server wantsevidence_item_id);attest_snapshot/attest_inventorysentrationaleinstead of the requiredsufficiencyenvelope. Corrected to the platform contract. - MCP schema enum drift. The
start_taskintent_verbenum and thecreate_planacceptance-criterionkindenum are now pinned by tests to their Python source-of-truth (theIntentVerbLiteral /ACCEPTANCE_CRITERION_KINDS) so a newly-added verb or kind can’t silently become unreachable over MCP. - System-spec DX fixes (from live SOC 2 dogfooding).
submit_asset_inventory_diffnow documents the platform-validated enums forasset_type/environment/data_classification(a wrong value 422s); thesufficiency.canonical_source_idfield is documented as requiring a bound-source reference (a free-form string is rejected by the platform — the other sufficiency fields are accepted on their own); andpretorin scope artifacts inventory scanno longer loses the[cloud-inventory]extra to Rich markup, so the SDK-missing hint correctly readspip install 'pretorin[cloud-inventory]'.
Documentation
- Rewrote
docs/src/workflows/system-spec.mdto cover the new CLI/MCP path for producing and connecting the four snapshot kinds (no longer platform-UI-only) and corrected the stale kind taxonomy. - Documented the three new MCP tools and the
scope-artifactsworkflow across the tool and workflow references.
0.23.10 - 2026-06-25
Fixed
-
Recipe-context evidence tally and produced-evidence ids (
end_recipe) — fixes walkthrough Bug #14 whereend_recipereturnedevidence_count: 6after the agent’s 3 actual evidence creations andevidence_ids: []despite those creations. Two bugs collapsed into one:ContextStore.record_evidence_writewas called inside_build_audit_metadata_for_writebefore the platform write happened. Every retry, every dedupe-hit, every payload-validation failure bumped the count without producing a row. The bump has moved to the handler’s post-write path and is now gated onEvidenceUpsertResult.created is Truefor the single-evidence path and on the batch result’s per-itemstatus == "created"for the batch path. Dedupe reuses, link-only reuses, and errored items no longer move the count.ExecutionContext.evidence_idswas an input-only field (evidence the caller passed tostart_recipefor narrative-citing recipes), butRecipeResult.evidence_idsreturned the same list, conflating “supplied” and “produced”. A newproduced_evidence_ids: list[str]field carries the ids of new rows the recipe actually created, in creation order. The inputevidence_idsfield is preserved unchanged so existing narrative-recipe callers continue to work.
-
Updated
record_evidence_writesignature — now accepts an optionalevidence_idkeyword that, when supplied, also appends the id toctx.produced_evidence_ids. The legacy id-less form (count-only bump) is preserved for tests. -
Docstrings on
ExecutionContext.evidence_countand the twoevidence_idsfields rewritten to spell out the dedupe-exclusion semantics and the input-vs-produced distinction so future readers can’t recreate the same confusion. -
4 new regression tests in
tests/test_mcp_recipe_handlers.py: dedupe hits don’t bump the count, mixed create/dedupe scenarios count only created rows, input and produced id lists stay distinct end-to-end, and the batch path counts only items whose platform status iscreated. Full pytest suite green: 3105 passed. -
Plans Phase B3 —
step_index=0on campaign-workflow plans no longer short-circuits the B3 audit chain.resolve_plan_coordinatespreviously raisedPlanStepError(“step_index 0 out of range; plan has 0 step(s)”) whenever a caller passed anystep_indexon a plan that didn’t pre-populateplan.steps— which is every campaign-workflow plan, because campaigns list their controls inscope.extra.control_filterrather than as explicit steps. The error short-circuited the handler beforerecord_plan_artifact_safelycould append toproduced_artifacts[], silently breaking the B3 audit chain for every multi-control walkthrough in production. Discovered during the SOC 2 walkthrough onpretorin-public-platform: 13 successful MCP writes (status, link_evidence, create_evidence, update_narrative, resolve_control_issue) all carryingplan_id+step_index=0produced zeroproduced_artifacts[]entries; the underlying record path was fine, the bounds check was wrong. The fix only enforcesstep_index < len(plan.steps)when the plan has at least one explicit step; for stepless plans (campaigns and anything similar), the write proceeds andstep_indexis dropped toNonerather than stored as a pointer to a step that doesn’t exist — so the audit chain never claims an artifact came from a fictional step. Negative-integer rejection, bool rejection, and the in-range bounds check on plans that do declare steps are all preserved. Two regression tests added intests/test_mcp_plan_coordinates.py. -
MCP tool schema docs —
start_task/start_recipe/create_evidence/create_evidence_batch. Clarified three documentation gaps surfaced during the SOC 2 walkthrough:start_task: tool description and theentitiesproperty description now explicitly call out that all prompt-derived fields (intent_verb,raw_prompt,system_id,framework_id,control_ids,scope_question_ids,policy_question_ids) must be nested inside theentitiesobject, with onlyactive_system_id/active_framework_id/skip_inspectat the top level. Flattening prompt entities was a common caller bug; such top-level copies are ignored by the handler (not rejected), so the route is decided fromentitiesalone.start_recipe: therecipe_versionproperty description now points callers atget_recipe(recipe_id).manifest.version(or theversionfield returned bylist_recipes) and warns against hard-coded values that will break when the recipe registry advances.create_evidence/create_evidence_batch: thesource_locatorproperty description now explains the platform-side audit-metadata contract (issue #701), the handler’s auto-derive-from-code_line_numbersfallback, and that non-code sources (policy excerpts, docs, vendor reports, dashboards) must pass an explicit locator likesection 3.7/page 4 paragraph 2, otherwise the platform rejects the write withMissing: source_locator.
Docs-only change — no schema shape, handler, or platform-contract changes. The three issues were observed during the SOC 2 CONF-001 walkthrough on
pretorin-public-platform; the descriptions surface at MCP tool introspection time, so future agent callers see them without code changes.
Added
pretorin plan prune— manual housekeeping for~/.pretorin/plans/. Removes terminal plans (completedorcancelled) whose terminal timestamp is older than--older-than-days(default 30). Active plans are NEVER pruned regardless of age. Defaults to interactive confirmation;--yesskips the prompt,--dry-runpreviews the action without touching disk,--include-corruptopts the operator into deleting unparseable plan files (the default reports them only). The correspondingPlansStore.prune(*, older_than_days, include_corrupt, dry_run, now)API returns a typedPruneResultcarrying the deleted ids, the skipped-active / skipped-recent / missing-terminal-timestamp counts, and any corrupt paths encountered — both the unit suite and the CLI tests assert against that structured payload. 13 new store-level tests and 6 new CLI tests covering each branch (eligible delete, dry-run, refused confirmation, JSON mode, corrupt files with and without--include-corrupt, non-plan files left alone).
0.23.9 - 2026-06-19
Added
- Plans Phase B4 polish —
MAX_ACCEPTANCE_CRITERIAcap (32). The Plan model rejects anyacceptance_criterialist longer than the cap via a@field_validatorthat fires at both create time and load time, with matching early-rejection guards inPlansStore.createandhandle_create_planso an over-cap input never reaches per-item Pydantic validation. The MCPcreate_planinputSchemaadvertisesmaxItems: 32so MCP clients can reject locally without a round-trip. Together these layers close a fan-out DoS surface where an agent (or hand-edited plan file) could declare thousands of criteria and forcecomplete_planto make a corresponding number of platform reads. - Plans Phase B4 polish — log-on-exception in the acceptance fetcher adapter.
_PretorianClientAcceptanceFetcher.get_narrativeandget_evidence_count_for_controlpreviously swallowed everyPretorianClientexception silently and returned the fail-safe value (None/0). They now also emit alogger.warning(...)carrying sanitized metadata — exception type plus HTTP status code when the exception is aPretorianClientError— but never the raw exception message, which could leak platform response bodies, validation values, URLs, or attacker-controlled newlines (log-injection surface). The fail-safe behaviour is unchanged: the acceptance evaluator still surfaces “no narrative found” / “0 evidence linked” failures so the gate stays deterministic, while transient platform / network issues now leave a debuggable trail. - Plans Phase B3 —
plan_id+step_indexflow into every platform write;Plan.produced_artifacts[]audit chain. Every Tier-1 MCP write tool (create / link / upload / delete evidence, create_evidence_batch, link_evidence_to_cci_implementation, link_evidence_to_stig_rule_workflow, update_narrative, update_control_status, add/resolve control_issue, push_monitoring_event, patch_scope_qa, patch_org_policy_qa) now accepts optionalplan_id+step_indexparameters. Each handler runs aresolve_plan_coordinatespreflight that validates the plan id shape, loads the plan, refuses non-activeplans, and bounds-checksstep_index. After a successful platform write,record_plan_artifact_safelyappends a typedPlanArtifact(one of eight kinds:evidence,evidence_link,narrative,control_issue,control_status,monitoring_event,scope_qa,policy_qa) to the plan’sproduced_artifacts[]list — the local audit chain a future auditor reads to trace every artifact this plan produced.plan_id/step_indexare also forwarded to the platform request body (or query params for multipart upload / DELETE) for forward-compatibility; the platform’s existing Pydantic models accept the new fields viaextra="ignore"until indexing-by-plan ships server-side. PlanArtifactmodel +PlansStore.record_artifact()method. New typed model with kind enum, optionalstep_index(≥ 0), optionalcontrol_id, requiredartifact_locator(1-300 chars),recorded_attimestamp, and a JSON-serialisableextrapayload capped at 2 KiB.record_artifactrequires the plan to beactive(terminal plans refuse to accept further artifacts so finalized audit chains stay finalized), honoursexpected_versionfor optimistic locking, but does not bumpPlan.versionitself — appending an artifact is runtime progress, not a structural edit (RFC Decision 2; same logic asupdate_plan_stepstatus changes). Theproduced_artifactslist is capped atMAX_PRODUCED_ARTIFACTS = 500per plan, enforced via a@field_validatorat both create and load time plus aPlanArtifactLimitErrorraised fromrecord_artifact— well above any realistic plan size while keeping the worst-case plan-file size well underMAX_PLAN_FILE_BYTES = 1 MiB.- MCP schemas advertise the new fields. Each of the 14 wired Tier-1 tool definitions in
mcp/tools.pyexposesplan_id(string) andstep_index(integer, minimum 0) as optional properties so MCP-client agents discover the parameters via tool introspection. Neither field is inrequired; omitting them keeps pre-B3 call semantics (no plan attached, no audit-chain entry). - CLI render:
pretorin plan showadds aProduced artifactssection listing each artifact’s kind, step pointer, control id, recorded timestamp, locator, and truncatedextrablob; the full payload is preserved in--jsonmode. The section is elided when the list is empty so pre-B3 plans render unchanged.
Changed
- Backward compatible: no MCP / CLI / schema-shape changes. Existing plan files with ≤ 32 criteria load unchanged; plan files with > 32 criteria would now fail to load with a clear error citing the cap and the actual count — accepted regression to close the DoS surface, no such plans exist in practice today.
- Maintenance: shared control-annotation sync helpers.
pretorin notesandpretorin issuesare two CLI command groups over the same underlying platform concept (a control annotation) and their list/add/resolve flows were near-identical copies. The shared logic now lives insrc/pretorin/cli/_control_annotations.py— a frozenAnnotationKinddescriptor (NOTE/ISSUE) parameterises the platform-client method names and display terminology, andissues.py/notes.pyshrink to thin call-throughs (≈169 lines each removed). No CLI surface, flag, or output change; the refactor exists to prevent the two groups drifting apart. - Maintenance sweep: coverage, lint, version consistency, and a full documentation audit. Raised
cli/issues.pyfrom 17% to 100% line coverage with a newtests/test_cli_issues_coverage.pysuite; appliedruff formattotests/evidence/test_audit_metadata.py; and verified the version is aligned acrosspyproject.toml,__init__.py, both changelogs, and the install-doc expected output. The accompanying docs audit re-synced every reference surface against the live CLI/MCP behaviour — README,CLAUDE.md-adjacentCLI.md/MCP.md, the CLI command reference and feature pages, MCP tool counts and the OSCAL artifact category, framework counts and the tier-2 catalog, theUSERenvironment variable, and thellms.txt/llms-full.txtmanifests — then rebuilt the committed mdBook output and confirmed no dead or unresolved internal references remain. - Backward compatible:
PLAN_SCHEMA_VERSIONstays at1. Existing~/.pretorin/plans/*.jsonfiles written before this version load cleanly withproduced_artifacts=[]as the default. Pre-B3 callers that omit the newplan_id/step_indexkwargs continue to send byte-identical request bodies to the platform — no plan attribution, no local audit-chain entry. 121 new regression tests across the model layer, theresolve_plan_coordinateshelper, the_attach_plan_metadataclient helper applied to each of the 14 write methods, and the CLI render ofproduced_artifacts. Full quality gate green: 3073 pytest, ruff/format/mypy strict, MCP smoke 20/20.
0.23.8 - 2026-06-18
Fixed
- MCP
start_taskinspect-status system resolution (#191):inspect_statusnow resolves an explicitly named system to its canonical UUID before reading workflow state, pending families, pending scope questions, and compliance status. Unknown explicit system names fail as top-level MCP errors instead of returning an apparently successful response with per-sectionSystem not founderrors. Active-context UUIDs still use the cheap path when no system is named.
0.23.7 - 2026-06-17
Added
- Plans flow — Phase B4:
Plan.version+ acceptance-criteria gate oncomplete_plan. The Plan model now carries a monotonicversion: intcounter (default1) and anacceptance_criteria: list[AcceptanceCriterion](default empty). All three mutation methods onPlansStore(update_step,complete,cancel) and their MCP handlers accept an optionalexpected_versionfor optimistic locking — mismatched versions return a structuredversion_conflicterror with both expected and actual versions in the JSON body so the caller can reload and retry.complete_planruns a server-side acceptance gate when the plan declares criteria: each criterion is evaluated against current platform state (narrative existence and length, evidence count linked to the control, AI-review status), and any failures return a structuredacceptance_failederror carrying the fullfailed_criteria[]list so the agent fixes every gap in one shot. The plan staysactiveon a failed gate so the agent can address the gap and retry. Emptyacceptance_criteriapreserves pre-B4 behaviour (no gate, last-write-wins). A TOCTOU guard pins the plan version we evaluated against through the actualcomplete()write, so concurrent mutations between gate evaluation and state transition are detected. - Four typed acceptance-criterion kinds (RFC Decision 3):
narrative_min_chars(params:{min_chars: positive int}),every_claim_cites_evidence(no params; first-cut interpretation checks the narrative exists and the control has ≥ 1 linked evidence item),ai_narrative_reviewed(no params; only fires on AI-drafted narratives),min_evidence_count_per_control(params:{min: positive int}). Per-kind params shape is enforced by a pydantic model validator at create and load time (defence-in-depth against hand-edited plan files). - New
pretorin.plans_acceptancemodule with the per-kind evaluator functions and an orchestratorevaluate_plan_acceptance(plan, fetcher)that returns the structured failure list. Evaluators depend on a narrowPlanAcceptancePlatformFetcherprotocol — the production adapter (_PretorianClientAcceptanceFetcherin the handler module) wrapsPretorianClientwith per-call memoisation so multiple criteria over the same scope share one round-trip per signal type; tests pass an in-memory fake. Fail-closed semantics: unknown criterion kind or unexpected evaluator exception is recorded as a failure, never a silent pass. - MCP schema and CLI render:
create_planadvertisesacceptance_criteriaarray on each step item;update_plan_step,complete_plan, andcancel_planadvertiseexpected_version(integer, min 1).pretorin plan showrendersversionnext to the plan id and a dedicatedAcceptance criteriasection listing each criterion with truncated inline params; sections are elided when empty so pre-B4 plans render unchanged. - Vendor public-API parity for Phase 1 TPRM:
pretorin vendor listnow understands the paginated{items,total}vendor-list response introduced by the platform and fetches all matching pages by default; list filters/sorting are exposed across CLI and MCP (search, provider type, residual risk tier, owner, assessment status, sort key/direction). Vendor create/update now supportowner_user_idandinherent_risk, andpretorin vendor historyplus MCPget_vendor_historymirror the public/vendors/{id}/historyendpoint.
Changed
- Backward compatible:
PLAN_SCHEMA_VERSIONstays at1. Existing~/.pretorin/plans/*.jsonfiles written before this version load cleanly with the new defaults applied (version=1,acceptance_criteria=[]), and step-status changes viaupdate_stepdeliberately do not bumpversionper RFC Decision 2 (progress, not structural edit). 73 new regression tests cover the model invariants, the optimistic-locking conflict path, each evaluator’s pass/fail/edge cases, the orchestrator’s fail-closed behaviour, the MCP handler’s gate + structured-error mapping, and the CLI render of the new fields. - Vendor inherent-risk vocabulary: CLI docs, tests, and MCP/skill descriptions now use the canonical four-band vocabulary
low/moderate/high/critical. The deprecated input aliasmediumis accepted by CLI create/update, normalized tomoderate, and warned in human-readable output.
0.23.6 - 2026-06-17
Added
- Public OSCAL artifact list/download (
pretorin oscal artifacts). New read-only command group over the platform’s public OSCAL artifact endpoints, for the machine-readable export path (e.g. the FedRAMP RFC-0024 package pipeline):list(validated artifacts for a system, filterable by--type/--framework/--assessment),show <id>(metadata + two-tier validation report),download <id>(SHA-256-verified againstchecksum_sha256; the file is not written and the command exits non-zero on mismatch), andlatest --type <type> [--download](newest validated artifact of a type; exits non-zero when none exists). Onlygeneration_state=succeeded+validation_status=validartifacts are returned. Presigned download URLs are fetched without the platform token so credentials never reach object storage. Generation stays app-surface — the CLI is consumer-only. Adds read-only MCP toolslist_oscal_artifacts/get_oscal_artifact.
0.23.5 - 2026-06-15
Added
- Plans flow — Phase B2: typed
PlanStepparameters.PlanStepnow carries two new optional fields:recipe_version(string, max 50 chars, only valid whenkind == "recipe") andparams(free-form JSON-serialisable dict, capped at 8 KiB serialised via the newMAX_STEP_PARAMS_BYTESconstant). A pydantic model validator rejectsrecipe_versionon any non-recipe step at both create time and load time (defence-in-depth against hand-edited plan files), so a future auditor can trust that a versioned step actually points at a real recipe. The MCPcreate_planinputSchemaadvertises both new fields on each step item, andpretorin plan showrenders them inline —recipe_versionas av<version>suffix on the step line,paramstruncated to 100 chars on a↳ params:continuation line (the full payload is always available via--json/get_plan).
Changed
- Backward compatible:
PLAN_SCHEMA_VERSIONstays at1. Existing~/.pretorin/plans/*.jsonfiles written before this version load cleanly with the new defaults applied (recipe_version=None,params={}), andupdate_plan_steppreserves both fields across status transitions. New regression tests cover the round-trip, the legacy-load path, the size-cap and JSON-serialisability guards, and the model-validator’s reject-at-load behavior.
0.23.4 - 2026-06-13
Changed
- Automated maintenance + documentation sync: consolidated the duplicated inline error-and-exit pattern in the risk and vendor CLI surfaces onto the shared
exit_with_errorhelper (pretorin risk create/update/attest/link add,pretorin vendor create/update/upload-doc), so validation failures are reported consistently and honor JSON output mode; added regression coverage for evidence audit-metadata handling; and refreshed the dependency lockfile. Doc sources, the MCP tool reference and overview, the CLI command reference, llms.txt manifests, and the rebuilt mdBook output were re-synced against the current CLI/MCP/agent surface. No behavior changes for end users.
0.23.3 - 2026-06-12
Fixed
- Active system/framework context is now enforced on every agent write path. Previously an agent could make platform writes against a system/framework that was not the active context:
start_recipeopened a recipe-execution row with no scope check, an agent could bypass the existing write guards by passingallow_scope_override, and several framework-scoped workflow writes (answer_scope_question,trigger_scope_generation/_review,trigger_family_review,patch_scope_qa) never checked the active context at all. Enforcement is now on by default in the scope resolver (read-only handlers opt out explicitly), agents can no longer self-authorize a cross-context write —allow_scope_overrideis ignored on every agent path and removed from the MCP and built-in-agent tool schemas, remaining a human/CLI-only capability — and the bypassing workflow writes now go through the shared guard. Only switching the active context withpretorin context setmoves the boundary. Scope: this closes the framework axis (same system, different framework); cross-system tools (risks/vendors/STIG/asset-inventory), checkpoint-driven campaign tools, and org-level policy writes are intentionally out of scope.
0.23.2 - 2026-06-11
Changed
- Managed Codex runtime pin: bumped the bundled Codex binary pin from
rust-v0.135.0torust-v0.137.0with refreshed SHA256 checksums for macOS arm64, macOS x64, and Linux x64. - Codex pin automation now opens PRs: the scheduled GitHub Action now writes the generated runtime-pin update to an
automation/codex-runtime-pinbranch and opens or updates a pull request instead of creating a tracking issue. The macOS assessment job also reads annotated constants correctly when extracting the pinned checksum map.
0.23.1 - 2026-06-10
Added
- Plans flow — Phase B1:
start_taskinstantiates a plan and returnsplan_id. When the routing layer settles on a non-ambiguous, non-nullselected_workflow, the engagement handler now persists aPlanrecord from the resolved scope and stamps the newEngagementSelection.plan_idfield. Agents can drive subsequent execution from the plan viaget_plan/update_plan_step/complete_plan.create_planremains agent-callable for advanced cases per the resolved design decision. Backward compatible: every existingEngagementSelectionfield is preserved, agents that don’t readplan_idkeep working unchanged.
Changed
inspect_status, ambiguous routing, and hard cross-check errors continue to skip plan creation (read-only, undecided, and bogus-entity flows respectively). Plan-store failures duringstart_taskare non-fatal: the routing decision still returns cleanly withplan_id=None, so a transient local disk problem doesn’t break the agent’s session.
0.23.0 - 2026-06-10
Added
- Agent-authored work plans (Phase A — plans foundation). Local plan persistence layer under
~/.pretorin/plans/<uuid>.jsonwith atomic writes, traversal-safe UUID-only paths, schema versioning, and a state machine (active → completed | cancelled). The plan model captures workflow id, scope (system/framework/control), intent summary, intent inputs snapshot, ordered typed steps (kinds:recipe,policy_link,issue,note,other), and lifecycle timestamps. - Six new MCP tools for plan lifecycle:
create_plan,get_plan,list_recent_plans,update_plan_step,complete_plan,cancel_plan. All six expose schema-validated input schemas; plan reads (get_plan,list_recent_plans) are reference-tier and the four write tools also classify as reference rather than workflow-tier — in the destination model a plan is the result of routing, not gated behind it. pretorin planCLI surface. Operator-side commandspretorin plan list,pretorin plan show <id-or-prefix>,pretorin plan cancel <id-or-prefix>; plan authorship is deliberately not exposed to the CLI (agent-side concern).- Draft RFC
docs/rfcs/draft-plans-flow.mddocumenting the six-phase platform view (prompt → routing → planning → execution → review → audit), what each of the four workflows does, the plan lifecycle, and three worked examples mapping concrete user prompts to instantiated plan records. Records the three design resolutions:create_planstays agent-callable alongsidestart_task; plans are mutable with monotonicversionbumps;complete_planruns the acceptance-criteria gate server-side. Subsequent phases (B1–B4) land as patch releases.
0.22.19 - 2026-06-07
Changed
- Automated maintenance + documentation sync: lint, format, and mypy strict passes across the source tree; manual scanner test coverage raised from 0% to 100%; refactor that consolidates the duplicated
_require_system_idguard used by the MCP artifact and risk handlers into a shared helper; dead-code removal (unusedYELLOWcolor constant, unreachablecodex_bin_dirproperty, unused client-config field, stale MCP smoke import); dependency lockfile refresh to the latest compatible versions. Doc sources, llms.txt manifests, README, and the rebuilt mdBook output were re-synced against the current CLI/MCP/agent surface — adding the v0.22.18 risk posture and DSSE risk-attestation commands to CLI.md, MCP.md, the CLI command reference, the risks feature page, and the LLM manifest; documenting the cloud-inventory dependency group and the AWS/Azure scanner environment variables; clarifying agent-skill runtime applicability; refreshing framework counts; and validating cross-references across every doc page. No behavior changes for end users.
0.22.18 - 2026-06-04
Added
pretorin risk posture <system_id>— system-scoped risk posture summary mirroring the newGET /api/v1/public/systems/{id}/risks/postureendpoint. Returns inherent + residual distribution buckets, weighted-average residual, overdue-attestation count, and the top 5 risks by residual score.pretorin risk attest <system_id> <risk_id> --type ... --statement ...— produces a DSSE-signed attestation over the current risk state viaPOST /api/v1/public/systems/{id}/risks/{rid}/attest. The signed payload reuses the existing evidence attestation signer + key registry, so verifiers resolve trust uniformly.--typeis validated client-side againstresidual_accepted | mitigation_approved | inherent_validatedso typos don’t waste a network round-trip.pretorin risk attestations <system_id> <risk_id>— lists DSSE envelopes for a risk, newest first.PretorianClient.get_risk_posture,attest_risk,list_risk_attestations.
0.22.16 - 2026-06-01
Fixed
- Asset-inventory scans no longer report a hard failure as an empty result. The
asset-inventory-azure-baselinerecipe (and the AWS, Kubernetes, and IaC-workspace recipes) now distinguish “the scan broke” from “there are genuinely no assets”: failures are surfaced in anerrorslist instead of silently returningscanned: 0.pretorin scope artifacts inventory scannow exits non-zero and prints the cause when a scan reads nothing, and warns (without retiring assets) when a scan is only partial.
Added
- Optional
cloud-inventorydependency group (pip install 'pretorin[cloud-inventory]') declaring the AWS and Azure SDKs the asset-inventory recipes need. Without it, scans return an actionable install hint instead of failing silently. - AWS asset inventory now enumerates all opted-in regions concurrently (EC2 is regional); set
AWS_REGIONto scan a single region. Azure subscription is resolved fromAZURE_SUBSCRIPTION_IDor the logged-inazdefault.
0.22.15 - 2026-05-30
Changed
- Automated maintenance + documentation sync: lint, type-check, and dependency-audit fixes, expanded test coverage on the issues writer/sync surface and API client retry paths, dead-code removal, plus refactor of the CLI’s repeated
print error / sys.exit(1)pattern into a sharedexit_with_errorhelper. Doc sources, llms.txt manifests, README, and the rebuilt mdBook output were re-synced against the current CLI/MCP/agent surface — adding the issues CLI page, evidence search RAG flags, DSSE attestation surfaces, recipe-scoped writes, and refreshed framework/MCP tool counts. No behavior changes for end users.
0.22.14 - 2026-05-29
Fixed
pretorin updateno longer trusts a stale “already latest” check as final: no-argument updates still check PyPI for user-facing context, but they now run the installer when that check reports the current version. This lets uv/pipx/pip confirm with a refreshed/no-cache install path instead of exiting early on stale CDN metadata, while avoiding downgrades when the installed version is newer than PyPI’s latest.- PyPI-confirmed uv updates use an exact refreshed version: when the update check sees a newer version, uv-managed installs now run
uv tool install --force --refresh pretorin==<version>instead ofpretorin@latest. If verification still sees the old version, the manual recovery hint also names that exact refreshed command.
0.22.13 - 2026-05-29
Fixed
pretorin updaterefreshes uv’s package index for latest installs: uv-managed no-argument updates now runuv tool install --force --refresh pretorin@latest, keeping uv as the resolver while forcing it past stale cached index data. This prevents the observed one-version-at-a-time upgrade path where a fresh0.22.12release first resolved only to0.22.11.
0.22.12 - 2026-05-29
Fixed
pretorin updaterestores latest/current feedback without reintroducing uv pinning: no-argument updates check PyPI first and print either “already on the latest version” or the available upgrade, but still dispatch uv’s unpinnedpretorin@latestinstall path so the installer resolves against its own index view. Failed version checks now fall back to attempting the installer update instead of blocking the user.- pipless venvs can update through uv: uv-created virtualenvs, plus other current Python environments that do not have pip but do have uv on PATH, now route
pretorin updatethroughuv pip install --python ... --upgrade --refresh pretorininstead ofpython -m pip. The installer subprocess also preserves detected uv/pipx tool homes for custom tool directories. pretorin updateavoids local import shadowing: installer and verification subprocesses now run from the active venv root (or home directory fallback) and stripPYTHONPATH/PYTHONHOME, preventing untrusted working-directory files such aspip.pyorpretorin.pyfrom shadowing the real packages during self-update.
0.22.11 - 2026-05-29
Changed
- Evidence and narrative guidance plus write validation now keep gaps, missing evidence, ambiguity, and remediation work out of artifact text and record them only as control issues.
- Evidence Markdown now normalizes headings to report-safe bold section labels, with
pretorin evidence format-markdownavailable for file/stdin reformatting.
0.22.10 - 2026-05-29
Added
- Control issues workflow: Added the first-class
pretorin issuesCLI, matching MCP/agent issue tools, local issue writer/sync support, and issue-driven campaign targeting withissues-fixplus--all-open-issuesselectors.
Changed
- Legacy
notescommands and tools remain compatibility aliases while docs, prompts, receipts, and campaign generation now prefer issue terminology for durable gaps and remediation work. Issue and note resolution requests also percent-encode path IDs and require explicit resolution justifications.
0.22.9 - 2026-05-28
Fixed
- MCP recipe-context audit trail hardening (#958, #959, #963, #964):
get_control_implementationnow reports the canonical narrative source, note writes require a dedicatedcontrol-note-attestationrecipe context, narrative writes reject evidence-only or cross-control contexts, and workspace-capture markdown artifacts no longer get wrapped in an extra code fence that breaks nested fences.
0.22.8 - 2026-05-27
Added
- Evidence DSSE attestation: get/verify CLI + MCP (#150): New
pretorin evidence attestation getandpretorin evidence attestation verifysubcommands surface the platform’s DSSE in-toto attestation envelopes (ADR 0003) to auditors and CI pipelines. The verifier independently checks the ECDSA P-256 + SHA-256 signature over the DSSE PAE bytes, resolves the signing key throughGET /api/v1/public/keysrather than trusting any embedded PEM, and honors key validity windows, revocation, and environment labels — exit 0 on success, 1 with a reason on failure. The matchingget_evidence_attestationMCP tool lets external agents fetch the envelope (plus an optional lineage view) for any evidence record. Newcryptography>=42.0.0runtime dependency.
0.22.7 - 2026-05-26
Added
- Scoped evidence RAG search (#148):
search_evidencenow accepts a natural-language query across the CLI, MCP handler, and agent tool surface. Query mode searches attached evidence plus scoped reusable unattached evidence, including policy documents, before agents create new evidence.
Changed
- Agent and workflow guidance now tell control-update flows to search existing evidence semantically, link relevant unattached evidence, and cite those evidence IDs in updated narratives.
0.22.6 - 2026-05-23
Changed
- Automated maintenance + documentation sync (#147): lint/type-check fixes, test coverage and dead-code cleanups, dependency vulnerability patches, and version/registration consistency tweaks across the codebase. Doc sources, llms.txt manifests, and the rebuilt mdBook output were re-synced against the current CLI/MCP/agent surface, including the system-spec workflow entry, STIG/CCI tooling tables, and SOC 2 control-ID format notes. No behavior changes for end users.
0.22.5 - 2026-05-22
Fixed
- System-spec evidence type parity (#145): the CLI now accepts the platform’s five
system_spec_*evidence types (system_spec_inventory_attestation,system_spec_boundary_diagram,system_spec_network_dfd,system_spec_ppsm, andsystem_spec_interconnection) across evidence validation, MCP/agent prompts, audit metadata source-type defaults, and CLI error/help output. This prevents system-spec snapshot evidence returned by the platform from being rejected or hidden by the CLI.
0.22.4 - 2026-05-22
Fixed
- MCP
resolve_control_noteno longer 400’s Claude-based clients: the tool’s input schema declared a top-levelallOfto express “resolution_note is required when is_resolved is true”. Claude’s API rejectsanyOf/oneOf/allOfat the top level of toolinput_schemas, so every Claude Code / Claude Desktop request against any pretorin MCP tool failed before reaching the handler (the schema failure short-circuited the whole tool list). Moved the conditional requirement into the handler — the constraint is preserved, and the schema is now Claude-API compatible. pretorin updatedetects uv/pipx installs outside the default folders: the installer detector now reads uv’suv-receipt.tomland pipx’spipx_metadata.jsonfrom the running venv before falling back to path heuristics. This keeps custom uv/pipx tool installs from falling through topython -m pip, which fails in tool venvs that intentionally omit pip.- Update notices point at
pretorin update: passive CLI/MCP status prompts no longer hardcodepip install --upgrade pretorin, so uv, pipx, and pip users all get the same installer-aware upgrade path.
0.22.3 - 2026-05-22
Fixed
pretorin updateno longer fails right after a fresh release: the previous design pre-resolved the latest version via PyPI’s JSON metadata API and passed it to uv as a strict==X.Y.Zpin. The JSON API can return a version moments before uv’s simple-index resolver sees it, so the pinned install failed with “No solution found … no version of pretorin==X.Y.Z” — reported three releases in a row (v0.22.0, .1, .2). The unpinnedpretorin@latestform was unaffected because it uses uv’s live-resolve path. Nowpretorin updatedispatchesuv tool install --force pretorin@latestdirectly and lets uv be the single source of truth for what “latest” means.- Explicit-version updates use
--refresh:pretorin update X.Y.Znow passes--refreshto uv (and--no-cache-dirto pip/pipx) so the installer invalidates any cached index data before resolving. Same intent as the@latestpath: avoid the dual-index-view race.
Removed
- JSON-API pre-resolution + post-install verify dance:
pretorin updateno longer hits PyPI’s JSON metadata API to pick a target version, and no longer re-spawns Python after the install to verify the installed version string. uv/pipx/pip’s own exit code is the source of truth; the propagated exit code goes straight totyper.Exit. Removes five failure surfaces in favor of one.
0.22.2 - 2026-05-21
Fixed
- Legacy agent — OpenAI strict-mode tool schemas (#136 bug 1): 20 platform tool definitions in
pretorin.agent.toolsdeclared optional parameters inpropertieswithout listing them inrequired. OpenAI’s strict-mode function-calling validator rejected the entiretoolsarray before any model turn ('required' is required to be supplied and to be an array including every key in properties). Added_to_strict_schemawhich normalizes schemas at the SDK boundary: every property gets added torequired, and optional properties become nullable unions (["string", "null"]). Applied into_function_toolso individual ToolDefinition entries stay readable while the OpenAI Agents SDK receives a strict-compliant schema. Regression-tested across every tool the agent registers. - Codex agent — unhelpful “Connection lost” error (#136 bug 2):
pretorin agent run(Codex runtime) was swallowing the exception class and chained cause, surfacing only the bare SDK message. Now prints the exception class,caused bychain, and the active runtime context (model + base_url) so the operator can tell which connection failed; same diagnostic block also wired into the legacy runtime.
0.22.1 - 2026-05-21
Fixed
inventory showalways reported empty (#133 follow-up): the CLI read the response underpayload["assets"]but the platform returns asset rows under"items". Same bug causedinventory scanto misclassify every row asadded(it diffed against an empty existing inventory). Both paths now readpayload["items"].artifacts togglealways 422’d (#133 follow-up): the client posted{"optional": ...}but the server’s PATCH schema is keyed ontoggled_off. Renamed the wire field while keeping the user-facing--optional/--requiredflag unchanged. Theartifacts listrenderer now reads eithertoggled_offor legacyoptionaldefensively.- Added two
TestSystemSpecEndpointsregression tests so the toggle wire shape and diff payload shape can’t drift again.
0.22.0 - 2026-05-21
Added
- System spec CLI + MCP surface (#133): new
pretorin scope artifacts ...command group wraps the platform’s public system-spec endpoints. Operators canartifacts list,inventory show [--as-of T],inventory upload <csv>,inventory scan <source>, andartifacts toggle <kind> --optional --rationale "...". Three matching MCP tools (list_artifact_requirements,get_asset_inventory,submit_asset_inventory_diff) expose the same surface to AI agents. The diff endpoint acceptsrecipe_context_idbut does not require it — the 11-field audit-metadata envelope is reserved for evidence writes. - Four asset-inventory recipes:
asset-inventory-aws-baseline(live EC2 via boto3),asset-inventory-azure-baseline(live Compute VMs via azure-mgmt-compute),asset-inventory-k8s-baseline(kubectl-driven enumeration of nodes + Deployment/StatefulSet/DaemonSet), andasset-inventory-iac-workspace(static parse of.tf/.tf.json/ K8s YAML / CloudFormation files in the cwd — no cloud credentials required). All four ship astier: official.
0.21.5 - 2026-05-19
Fixed
- Recipe context ids were never platform-backed. MCP recipe executions are now persisted through the platform and the returned platform UUID is used as the recipe context id.
- Recipe-produced evidence lost its provenance.
recipe_context_idis now forwarded on recipe-produced evidence writes, including batch evidence. - Narrative citations were rejected. Citations are now sent as
evidence_citationsso the platform can validate the supporting evidence. pretorin updatewas a no-op on uv installs. The resolved target version is now force-installed, so an editable or file install no longer silently skips the upgrade.
0.21.4 - 2026-05-19
Fixed
- MCP start-task routing and capture preflight (#126, #127):
inspect_statusnow returns a bounded no-workflow status bundle without running the full routing cross-check, and platform validation outages now surface as structured upstream errors instead of false “not found” messages. - AI-guidance evidence expectations (#127):
start_task.suggested_capture_plannow falls back from control context toget_control(...).ai_guidance.evidence_expectations, so enriched controls such as AU-04 retain their recipe preflight plan even when the system control-context endpoint is unavailable.
Changed
- Workspace capture fallback (#127):
workspace-captureis now the generic workspace evaluation/capture fallback for broad or unclassified evidence expectations, and capture-plan metadata identifies whether a recipe came from an expectation match or the fallback path.
Removed
- Legacy document requirements API: removed the obsolete
get_document_requirementsclient/MCP surface andpretorin frameworks documentscommand. Evidence requirements are derived from AI guidance.
0.21.3 - 2026-05-19
Fixed
pretorin updateworks on uv tool and pipx installs: the update command now detects howpretorinwas installed by inspectingsys.executableand dispatches touv tool upgrade pretorinorpipx upgrade pretorinwhen appropriate. Previously it always shelled out topython -m pip install --upgrade, which fails withNo module named pipon recentuvversions because tool venvs no longer ship pip. Pinned upgrades (pretorin update X.Y.Z) route touv tool install --force/pipx install --forceso they work on isolated tool venvs too. Failure paths and the post-upgrade “ran but version unchanged” hint now name the right installer.
0.21.2 - 2026-05-18
Changed
- MCP recipe-required telemetry (#121): evidence and narrative producer guardrails now emit a
PRETORIN_TELEMETRY_EVENTwithevent_type="recipe_required"and non-content shape metadata, letting operators compute the combined workflow/recipe bypass rate for the post-v0.21 trigger watch.
0.21.1 - 2026-05-16
Maintenance
- Automated maintenance + documentation sync pass (#122): lint/type-check fixes, test coverage improvements, dead-code removal, dependency vulnerability patches, version/registration consistency, and a repository-wide doc resync against the v0.21 surface (CLI/MCP/agent references, llms.txt manifests, and a fresh mdBook rebuild).
0.21.0 - 2026-05-15
Added
- Recipe/source MCP producer surface (#118): recipes can declare
requires.sources, MCP exposeslist_connected_sourcesandcheck_sources,start_taskreturnssuggested_capture_plan, andlist_recipes(system_id=...)filters to source-eligible recipes while failing open on older platform deployments. - Narrative recipe support (#118):
start_recipeacceptsevidence_ids,update_narrativerequires a narrative-producing recipe context with cited evidence ids, and the built-inevidence-narrative-composerecipe provides the canonical narrative path. - Workspace capture floor recipe (#118):
workspace-capturegeneralizes code capture for readable workspace files such as runbooks, policy drafts, scripts, configs, and exported reports.
Changed
- Recipe-only MCP writes (#118): MCP
create_evidence,create_evidence_batch, andupdate_narrativenow reject agent writes withoutrecipe_context_idusing a structuredrecipe_requirederror.
0.20.1 - 2026-05-15
Fixed
- Control note resolution parity (#760): MCP, CLI, and built-in agent note-resolution tools now expose and forward
resolution_note, matching the platform UI’s audit-trail requirement for closing notes.pretorin notes resolveaccepts--resolution-note/--justification, and local validation prevents closing a note without a justification.
0.20.0 - 2026-05-14
Changed
- MCP tool prefix dropped (#113, phase 3): every server-side tool name lost its leading
pretorin_. Hosts seemcp__pretorin__check_contextinstead ofmcp__pretorin__pretorin_check_context. Recipe-script tools follow the same rule (recipe_<id>__<script>instead ofpretorin_recipe_<id>__<script>). Breaking change for any agent that hardcoded the old names — re-install the bundled skill (pretorin skill install) or update local references. Tier metadata, the intent-verb map, and the workflow-body schema-bundling regex all moved with the rename. The handler function names (handle_create_evidence, etc.) are unchanged — this only affects the wire-level tool identifier.
Added
- Cross-harness MCP tool surface (#113, phases 0-2): the MCP server now ships a small set of cross-harness discovery + grounding tools so Cursor, Codex, vanilla Agents SDK, and any other client can ground a session without depending on the
initializeinstructions block.check_context— cheap, unauthenticated probe. Returns{connected, active_system, active_framework_id, suggested_next, pending_attention}with a deterministic next-step hint. Call once at session start.list_tools— compact catalog. One short record per tool (name,purpose,tier,requires_workflow) plus tier counts. Cross-harness alternative to fetching every tool’s full schema just to browse. Tiers:default,reference,workflow,recipe.get_instructions— callable mirror of the server’sinstructionsblock, for harnesses that don’t render it.- Errors-as-instructions: write tools that fail because there’s no active routing context now return a structured
{error: "workflow_required", message, routing_hint}payload (stillisError=true) instead of plain-text errors.routing_hint.suggested_intent_verbtells the agent the exactstart_taskcall to make. Backed by a newWorkflowRoutingErrorexception class. - Workflow schema bundling:
get_workflownow bundlesrequired_tool_schemas— the full MCPTooldefinitions for every tool the workflow body references. One round trip equips the agent. - Telemetry: structured single-line JSON events emitted on stderr (
PRETORIN_TELEMETRY_EVENT {...}) on successfulstart_taskand onWorkflowRoutingErrorraises. Feeds the phase-4 trigger decision in the RFC. Opt out withPRETORIN_MCP_TELEMETRY_DISABLED=1. pretorin mcp-smoke-testcommand: 16-check end-to-end harness that exercises every new behavior in-process — useful for verifying an install or PR.
0.19.0 - 2026-05-13
Added
- Markdown evidence artifacts and structured provenance (#112): JSON evidence writes now send short
descriptionsummaries plus standalone Markdownartifact_content, with source/capture context inaudit_metadata(source_label,source_locator,source_excerpt,content_hash,capture_method, and related fields). Batch evidence follows the same per-item contract. Addedpretorin evidence validateto compare fresh source-material hashes before re-verifying; drifted sources update the existing evidence artifact with adrift_noteinstead of silently callingmark-current.
0.18.2 - 2026-05-09
Maintenance
- Automated maintenance + documentation sync pass (#111): lint/type-check fixes, test coverage improvements, dead-code removal, dependency vulnerability patches, version/registration consistency, and a repository-wide doc resync against the v0.18 surface (CLI/MCP/agent references, llms.txt manifests, and a fresh mdBook rebuild).
0.18.1 - 2026-05-09
Added
- Continuous compliance —
--cadence-daysflag andmark-currentcommand (#108 PR B):pretorin evidence upsertaccepts--cadence-days <int>to opt new evidence into a refresh cadence; the platform then computesexpires_atserver-side and includes the row in the daily freshness sweep. Newpretorin evidence mark-current <id>subcommand re-affirms that evidence is still current — bumpsexpires_atby the cadence, transitionsexpired→valid, writes are_verifiedlineage row, and auto-resolves any openevidence.expiring/evidence.expiredmonitoring events.EvidenceCreatecarries the newrefresh_cadence_daysfield.PretorianClient.mark_evidence_current()is the corresponding API client method.
0.18.0 - 2026-05-08
Added
- Auditor sufficiency fields on evidence writes (#108):
pretorin evidence upsertgains--coverage-start,--coverage-end, and--capture-queryflags so callers can populate the new auditor sufficiency columns. The MCPcreate_evidencetool accepts the same arguments.EvidenceCreateandEvidenceBatchItemCreatenow carrydata_coverage_start_at,data_coverage_end_at, andcapture_query. Pairs with the platform-side schema; auditors get clear answers to the seven sufficiency questions (source-system, capture-vs-coverage timestamps, producer authority, capture context, in-scope binding, control mapping, reliability) without walking attestation chains.
0.17.8 - 2026-05-08
Fixed
- Evidence audit metadata serialization:
pretorin evidence upsertand MCP evidence writes now serializeaudit_metadata.captured_atusing Pydantic JSON mode before handing payloads tohttpx. Previously, recipe/agent-stamped evidence failed locally withTypeError: Object of type datetime is not JSON serializablebefore the platform request was sent. - Source verification JSON safety: evidence create and batch-create now normalize source-verification snapshots to JSON primitives, so attested contexts with datetime values do not break evidence writes.
0.17.7 - 2026-05-07
Fixed
- MCP recipe-script context resolution (#104): the recipe-script dispatcher (
mcp/handlers/recipe.py) now readsactive_system_id/active_framework_idfromConfiginstead ofPretorianClient(getattr(client, ...)was silently returningNonebecause those attributes live on Config). Every scanner recipe (manual-attestation,inspec-baseline,openscap-baseline,cloud-aws-baseline,cloud-azure-baseline) was failing atfetch_test_manifestwithSystem not foundbecausectx.system_idreached the script asNone. As a side benefit,PRETORIN_SYSTEM_ID/PRETORIN_FRAMEWORK_IDenv-var overrides now flow through end-to-end — CI / MCP environments without a stored CLI context can set those env vars and recipe scripts work. - Recipe import error in scope/policy questionnaire redactors (#103): both
scope-q-answerandpolicy-q-answerrecipe scripts importedredact_secretsfrompretorin.evidence.redact, but the module only exportsredactandRedactionResult(redact_secretsis a kwarg ofredact(), not a symbol). Every invocation failed at import time withcannot import name 'redact_secrets', silently breaking the documented contract that thescope-questionandpolicy-questionworkflows redact answers before submission. Switched both scripts toredact()+ unpack the(str, RedactionResult)return shape, matchingcode-evidence-capture/scripts/redact_secrets.py.
Documentation
- Customer-managed air-gapped install guide: new
docs/src/getting-started/customer-managed-airgap.mdwalks operators of customer-managed / air-gapped Pretorin platform deployments through pointing the CLI at their private platform — non-secret platform validation (smoke test, embedding readiness, AI provider checks), CLI configuration viaPRETORIN_PLATFORM_API_BASE_URL/pretorin login --base-url, and tenant-scoped CLI smoke tests. Linked from the configuration reference.
0.17.6 - 2026-05-06
Added
- Risk-management CLI + MCP surface (#100): you can now populate a system’s risk register directly from the CLI or from any MCP-connected agent — list, create, seed from library templates, update with mitigation, link controls/evidence/vendors as artifacts, and refresh the AI-generated summary. End-to-end wrappers around the platform’s public
/systems/{system_id}/risks*endpoints. Newpretorin riskcommand group:list,show,create,seed,update,refresh-summary,link add/link rm, andlibrary list. Matching MCP tools:list_risks,get_risk,create_risk,seed_risks,update_risk,link_risk_artifact,unlink_risk_artifact,refresh_risk_summary,list_risk_library. Tool descriptions encode the workflow gotchas — risks are system-scoped, control auto-link is opt-in (requiresframework_id+ matching ControlImplementation rows), mitigation is recorded viaupdate_risk(no separate /mitigate endpoint), and AI summary refresh is best-effort (checkai_summary_generated_atto confirm AI ran).
0.17.5 - 2026-05-06
Fixed
pretorin cci implpanel now surfaces the impl row id (theidfield in the platform response) so agents can chain directly intoevidence link-cciwithout re-querying. The previous render hid this UUID.- Panel header now displays the CCI human label (
CCI-000007) by reading the platform’scci_identifierfield, instead of repeating the catalog UUID twice. The earlier code read a non-existentcci_uuidfield and silently fell back to the URL arg. - Removed dead-code rendering loop for
emass_*fields that the platform does not return.
0.17.4 - 2026-05-06
Added
- CCI implementation read endpoint (#97):
pretorin cci impl <cci_uuid>and MCP toolget_cci_implementationwrap the new platformGET /systems/{system_id}/cci-implementations/{cci_uuid}endpoint, returning the live per-system impl row (status, status_source, narrative, evidence_ids, eMASS fields, has_status_conflict). - Evidence link target-type extensions (#97): new sibling commands
pretorin evidence link-cciandpretorin evidence link-stigplus MCP toolslink_evidence_to_cci_implementationandlink_evidence_to_stig_rule_workflow. Both honor the platform’soverride_system_mismatch+override_reasongate for cross-system attachment. The STIG variant lazy-creates the workflow row when none exists. - Agent guidance on STIG-to-CCI traceability: SKILL.md and the
single-controlworkflow playbook now clarify that the STIG-rule → CCI relationship is catalog-level (DISA-defined, immutable, synced during ingestion) — agents should reach forget_cci_chain(nist_control_id, system_id)for “what tests this CCI on this system” instead of any (non-existent) per-system assignment endpoint.
0.17.3 - 2026-05-05
Fixed
- Scope and policy generation MCP tools now request AI review in the same durable generation job by default, matching the platform workflow while preserving an
include_review=falseopt-out.
0.17.2 - 2026-05-02
Documentation
- Repository-wide documentation sync to current v0.17 surfaces: README recipes table, getting-started, CLI/MCP reference, frameworks selection + custom-framework authoring, recipes/workflows, agent overview, env-vars reference, llms.txt manifests, and a fresh mdBook rebuild.
Fixed
- Test isolation:
test_install_default_writes_to_all_known_agentsnow performs filesystem assertions inside thePath.home()patch context so CI runs do not depend on the runner’s real home directory.
0.17.1 - 2026-04-30
Added
- Custom framework authoring CLI (#90): end-to-end build / validate / upload workflow around the platform’s
unified.jsonrevision-lifecycle endpoints. New commands underpretorin frameworks:init-custom <id>— scaffold a minimal validunified.jsontemplate.validate-custom <path>— local JSON Schema pre-flight (the platform runs the authoritative validator on upload).build-custom <input> -f <id>— auto-detect input shape (already-unified passthrough, OSCAL catalog, or known custom catalog) and normalize tounified.json.upload-custom <path> [--publish]— POST a draft custom-framework revision;--publishimmediately promotes the draft. Renders the platform’s structuredvalidation_reporton 400.fork-framework <upstream_id> <new_id>— create a linked-fork draft anchored on the upstream revision.rebase-fork <id>— create a fresh rebase draft against the latest upstream.revisions <id>— list draft and published revisions.export-oscal <unified.json>— regenerate an OSCAL catalog from a unified artifact (lossless when_oscalblocks are preserved).
- Vendored unified-framework toolchain at
pretorin.frameworks: bundled JSON Schema + Draft 2020-12 validator, OSCAL ↔ unified converters with lossless round-trip, and the 12-format custom-catalog converter (control_families, cis_safeguards, domains, control_themes, pci_dss, process_requirement, governance_requirement, framework_catalog, crypto_validation, framework_wrapper, metadata_controls, standards_specs). Public surface:validate.validate_unified,oscal_to_unified.convert,unified_to_oscal.convert,custom_to_unified.convert,templates.minimal_unified. - Framework revision lifecycle client methods on
PretorianClient:create_custom_draft,publish_draft,fork_framework,create_rebase_draft,list_revisions. The platform’s structuredvalidation_reportis preserved throughPretorianClientError.detailson 400. jsonschema>=4.0.0added as a runtime dependency for local artifact validation.
Documentation
- New page
docs/src/frameworks/custom.mdwalking through the end-to-end custom-framework workflow. - CLI reference + installation expected-output updated.
0.17.0 - 2026-04-30
Added
- Recipe extensibility system (RFC 0001): full implementation of the three-layer routing model — engagement → workflow → recipe. Calling AI agents (Claude Code, Codex CLI, custom MCP clients, or
pretorin agent) now route through deterministic Python rules to a workflow playbook, then pick recipes per item from a discoverable menu instead of freelancing. start_taskMCP tool: pure-function rule cascade over agent-extracted entities. Cross-checks against platform state (hallucinated control ids → hard error; wrong-framework / cross-system writes → ambiguous response). Bundles inspect summary into the response so the calling agent gets the routing decision plus the platform state in one round-trip.- Workflow registry + 4 built-in playbooks:
single-control,scope-question,policy-question,campaign. Each is a markdown body the calling agent reads to know how to iterate items in its domain.list_workflowsandget_workflowMCP tools. - Recipe registry + 8 built-in recipes:
code-evidence-capture— pull a snippet, redact secrets, compose audit-grade markdown.inspec-baseline,openscap-baseline,cloud-aws-baseline,cloud-azure-baseline,manual-attestation— scanner recipes replacing the deletedpretorin scancommand.scope-q-answer,policy-q-answer— questionnaire-answer redaction recipes for the new questionnaire workflows.
- Recipe authoring surface:
pretorin recipe list / show / new / validate / runCLI commands. Four loader paths with clear precedence: explicit > project > user > built-in. Scaffolder + validator. Per-script MCP tools auto-registered asrecipe_<safe_id>__<script>. - Recipe execution context:
start_recipe/end_recipeopen a server-side context; every platform write inside the context auto-stampsproducer_kind="recipe", the recipe id, and the recipe version onaudit_metadata. 1-hour idle expiry, nesting forbidden. - Audit-trail metadata model:
EvidenceAuditMetadata(producer_kind, producer_id, producer_version, captured_at, source_type, source_uri, source_version, content_hash, redaction_summary, recipe_selection) is now stamped on every CLI / agent / MCP / campaign-apply evidence write. Build helpers atpretorin.evidence.audit_metadataare the single construction surface. - Recipe selection on every drafting call:
draft_control_artifacts(the campaign hot site) now consults the recipe registry for a(control, framework)attestsmatch before falling through to freelance. The decision is recorded as aRecipeSelectionon the response so audit can trace which recipes drove which artifacts. pretorin.evidence.redact+pretorin.evidence.markdown: shared primitives for secret redaction and audit-grade markdown composition. Used by recipes and the campaign-apply path.- Bundled
pretorinskill v0.17.0: teaches the calling agent about engagement → workflow → recipe routing. New “Engagement (Routing)” section flagsstart_taskas the FIRST call, “Workflow Playbooks” enumerates the four playbooks, “Recipes” enumerates the eight built-ins. - MCP server
instructionsfield updated: explicit routing guidance — the calling agent must callstart_taskfirst when the user references compliance work, and must NOT call evidence/narrative write tools before the workflow + scope are resolved. - Authoring docs at
docs/src/recipes/: index, manifest reference, script contract, writer tools, testing, publishing, workflows, engagement, worked example.
Changed (BREAKING)
pretorin scanCLI command removed. All scanner functionality moved to recipes. Existing automation should migrate topretorin recipe run <recipe-id>(e.g.,pretorin recipe run inspec-baseline --param stig_id=RHEL_9_STIG) or invoke via MCP. The platform-sidesubmit_test_resultsendpoint stays live; only the local CLI surface changed.ScanOrchestratorremoved. The manifest fetch + rule filter + result summary helpers were extracted intopretorin.scanners.manifestand shared across the five scanner recipes.
Removed
src/pretorin/cli/scan.py(296 lines) — the legacypretorin scantyper app.src/pretorin/scanners/orchestrator.py(281 lines) — the legacy multi-scanner dispatch loop.- The deprecated
rejected_invalid_typecampaign-apply telemetry counter (deprecated in 0.16.0).
0.16.3 - 2026-04-26
Fixed
- CCI chain test fix:
test_cci_chain_with_system_statusnow correctly mocksresolve_execution_contextso CCI status rendering is exercised. No production code changes.
0.16.2 - 2026-04-21
Fixed
pretorin campaign controls --familycase-insensitive resolution (#84):--family cc6(or any casing/whitespace variant) now resolves to the canonicalCC6before hitting the backend’s case-sensitivelist_controls(family_id=...). Unknown families raise a structuredPretorianClientErrorwhose message lists available families and points atpretorin frameworks families <framework-id>; MCP clients receiveframework_id,requested_family_id, andavailable_familiesindetailsfor programmatic recovery. Raw user input is preserved on the campaign checkpoint’srequest.family_idfield. Same resolver applied to theprepare_campaignMCP handler.--familyhelp text now references the discovery command.
0.16.1 - 2026-04-21
Added
- Gap questions for policy and scope Q&A: MCP tool descriptions now guide agents through an answer-first workflow — answer from workspace evidence silently, then present structured “gap questions” to the user only for organizational knowledge the workspace can’t provide. Ensures consistent interview formatting across any MCP-connected agent (Claude Code, Codex, Cursor, etc.).
0.16.0 - 2026-04-21
Changed (BREAKING)
evidence_typeis now required on every CLI, MCP, agent, and workflow write path (#79). CLI paths hard-error when the user omits-t/--type; every other path runs a client-side normalizer before submission.pretorin evidence create/pretorin evidence upsertrequire-t/--type. The error lists all 13 canonical values so users can self-correct.create_evidenceMCP tool schema listsevidence_typeinrequiredand removes thepolicy_documentdefault.EvidenceCreateandEvidenceBatchItemCreatepydantic models reject missing and non-canonicalevidence_typevalues via a sharedfield_validator.LocalEvidencedataclass requiresevidence_type. Existing on-disk evidence files missing the frontmatter field will fail to load — add the field manually (canonical values are listed inpretorin.evidence.types.VALID_EVIDENCE_TYPES).upsert_evidence()andbuild_narrative_todo_block()no longer defaultevidence_type/suggested_evidence_typetopolicy_document.
Added
- Evidence provenance fields: CLI now sends
code_file_path,code_line_numbers,code_snippet,code_repository, andcode_commit_hashto the platform on all evidence creation paths (single, batch, campaign). Auditors can trace evidence back to specific source files and commits. - Source verification: CLI maps attested source identities to the platform’s
SourceVerificationPayloadschema with propersource_typeandsource_rolemapping. Sent alongside_provenanceon all evidence writes when session is verified. pretorin evidence upload: New CLI command to upload files (screenshots, PDFs, configs, logs) as evidence. Computes SHA-256 checksum locally, verifies server-side. 25MB max, restricted MIME types.upload_evidenceMCP tool: AI agents and recipes can upload files as evidence via MCP.- File reference validation: Campaign apply validates AI-reported file paths and line numbers before sending to the platform. Reads actual file content as the canonical snippet instead of trusting the agent’s output.
source_roleonSourceIdentity: Each attestation provider declares its compliance role (code, identity, deployment, monitoring). Used for platform source verification mapping.- Git context from snapshot: Evidence creation auto-populates
code_repositoryandcode_commit_hashfrom the attested snapshot instead of separate subprocess calls. - Code provenance on local evidence:
pretorin evidence createandpushnow supportcode_file_path,code_line_numbers,code_repository,code_commit_hashin markdown frontmatter. pretorin.evidence.typesmodule: canonical 13-type enum, AI-drift alias map (EVIDENCE_TYPE_ALIASES), andnormalize_evidence_type(). The normalizer uses a static alias map plusdifflibfuzzy matching (stdlib, zero-cost, deterministic, future-proof) before falling back to"other". Common AI near-misses likeaudit_log→log_file, pluraltest_results→test_result,screenshoot→screenshot,policy_doc→policy_documentnow normalize instead of causing HTTP 400s during campaign apply.campaign.apply.controltelemetry addsevidence_type_normalized(alias + fuzzy hits) andevidence_type_fallback(unknown →"other") counters. The legacyrejected_invalid_typecounter is now always0(the normalizer no longer rejects) and is deprecated; it will be dropped in 0.17.0. Migrate dashboards to the new counters.evidence_type.normalizedstructured log records (INFO for alias/fuzzy matches, WARNING for unknown →"other"fallback) so post-ship telemetry can size the drift map.
Changed
EvidenceCreateandEvidenceBatchItemCreatemodels now include 5 optional code provenance fields.- Campaign evidence batch construction now extracts
code_file_path,code_line_numbers,code_snippet, andrelevance_notesfrom AI recommendations (previously dropped). - AI generation prompt schema includes code provenance fields in
evidence_recommendations. upsert_evidence()acceptscode_contextparameter and creates enriched evidence (with provenance) as a new record rather than reusing a match that lacks provenance.evidence upsertCLI command has new--code-file,--code-lines,--code-repo,--code-commitoptions.
Fixed
- SOC2 campaign batches that previously failed partially because the AI emitted non-canonical
evidence_typestrings (report,procedure,contract,audit_log, pluraltest_results, etc.) now succeed end-to-end. Unknown strings still emit a canonical gap note so reviewers see the drift, but the evidence lands rather than being dropped. - Non-campaign write paths (CLI
evidence create/upsert, MCPcreate_evidence/create_evidence_batch, agent tools,upsert_evidenceworkflow) can no longer silently tag missing-type evidence aspolicy_documentand pollute the platform’s custom-policies page.
0.15.5 - 2026-04-20
Fixed
- Campaign
--applyruns no longer flood the evidence locker with AI-authored summaries typed aspolicy_document(issue #77). The pipeline now wiresrecommended_notesthrough to the platform as real gap notes, rejects evidence recommendations with missing or invalidevidence_type(turning them into synthesized gap notes), and emits a structuredcampaign.apply.controltelemetry line for post-ship measurement. - Partial failures in the per-control notes write now raise
PretorianClientErrorwith the failing indexes, mirroring the existing evidence-batch behavior so checkpoint resumes are idempotent. - Evidence batch result mapping now aligns offsets to the original recommendation index via the accepted-items list and asserts length match, fixing a latent index-drift bug that appeared once any recommendation was rejected mid-loop.
- Completion note now fires when all pending work has landed across runs, not only when something new was written in the current run.
Changed
evidence_typeis now required onEvidenceBatchItemCreate. The campaign batch write path no longer silently tags missing types aspolicy_document; pydantic validation raises instead. Other evidence write paths (CLI, MCP, direct API) keep their existing defaults.- Agent drafting prompts (
_build_generation_task,_draft_control_fix,_WORKFLOW_GUARDRAILS, codex system prompt,[[PRETORIN_TODO]]template) now list all 13 valid evidence types verbatim and state that an emptyevidence_recommendationslist is a valid result — gaps belong inrecommended_notes. _WORKFLOW_GUARDRAILSmerged in the evidence-collection skill’s “concrete, auditable artifacts” language so narrative-generation skill callers inherit the same rules.
0.15.4 - 2026-04-18
Changed
- Updated 6 dependencies to resolve 7 known vulnerabilities (cryptography, pygments, pyjwt, pytest, python-multipart, requests)
- Added CLAUDE.md and AGENTS.md for AI agent context
0.15.3 - 2026-04-18
Fixed
pretorin updatenow checks PyPI before running pip, skipping reinstall when already currentpretorin updateverifies the installed version after pip runs, detecting silent failures in pipx/uv-managed environmentspretorin updateno longer compares against stale in-memory__version__after upgrading
Added
pretorin update [VERSION]accepts an optional version argument to install a specific release
0.15.2 - 2026-04-18
Changed
- Documentation sync: rebuilt all docs to match current codebase
0.15.1 - 2026-04-17
Added
- Evidence delete command:
pretorin evidence delete <evidence-id>with--yesflag for non-interactive workflows - MCP tool
delete_evidencefor programmatic evidence deletion within system scope - API client method
delete_evidencewired to the publicDELETE /systems/{system_id}/evidence/{evidence_id}endpoint
0.15.0 - 2026-04-16
Added
- Source manifest requirement policy (Phase 3 of #64): declare which external sources a system expects and gate compliance writes on their presence
pretorin context manifestcommand for viewing the resolved manifest and evaluating it against detected sources- Manifest loading from four layered sources:
PRETORIN_SOURCE_MANIFESTenv var, repo-local.pretorin/source-manifest.json, per-system user config, or inline config key - Family-level source requirements: manifest can declare that AC controls need AWS, CM controls need git, PS controls need HRIS, etc.
- Three requirement levels (required/recommended/optional) with write blocking on missing required sources and warnings for missing recommended
- Control family extraction for NIST 800-53, CMMC, and 800-171r3 control ID formats
- Anchored identity matching prevents org-name prefix collisions in manifest identity patterns
- Manifest evaluation results in write provenance (
manifest_statusandmissing_required_sourcesfields) control_idthreading through MCPresolve_execution_scopeand 4 API write methods for family-level provenance- Manifest version validation rejects unknown schema versions with a clear warning
- 134 new tests covering manifest models, parsing, loading, matching, evaluation, family extraction, write guard enforcement, and provenance enrichment
Changed
_enforce_source_attestationnow evaluates manifest requirements after the existing MISMATCH checkresolve_execution_contextaccepts an optionalcontrol_idfor family-level manifest enforcementbuild_write_provenanceaccepts an optionalcontrol_idand includes manifest evaluation in provenance metadataTODOS.mdadded to.gitignore
0.14.0 - 2026-04-10
Changed
- MCP and agent write workflows now treat the active CLI context as a strict execution boundary by default, with an explicit
allow_scope_overrideescape hatch for intentional cross-scope writes - Control-scoped MCP and agent workflows now route through one shared scope-validation path so exact control lookup happens in the resolved framework before any write proceeds
- Agent guidance now tells built-in workflows to resolve an exact user-supplied control in the active framework before doing broader discovery
pretorin mcp-servenow emits a non-blocking stderr update prompt when a newer CLI release is available, so MCP-only users can discover upgrades without interrupting active tool calls
Fixed
apply_campaignnow reportsapply: trueafter a successful apply run and persists that state back to the checkpoint summary- Stored active context and campaign checkpoints are now validated against the current API environment before campaign reads or writes proceed
- Control-scoped MCP and agent updates now refuse silent remaps like
cm-04.02to a different control when the exact control does not resolve in the active framework
Added
get_cli_statusand thestatus://cliMCP resource expose local CLI version, update availability, and upgrade guidance to MCP hosts and agents
0.13.1 - 2026-04-07
Added
get_stigMCP tool for STIG benchmark detailget_cci_chainMCP tool for full Control → CCI → SRG → STIG rule traceability
0.13.0 - 2026-04-07
Added
- Complete STIG/CCI MCP tools:
list_stigs,get_stig,list_stig_rules,get_stig_rule,list_ccis,get_cci,get_cci_chain,get_cci_status,get_stig_applicability,infer_stigs,get_test_manifest,submit_test_results - STIG/CCI agent tools for OpenAI Agents SDK
pretorin stigCLI group:list,show,rules,applicable,inferpretorin cciCLI group:list,show,chainpretorin scanCLI group:doctor,manifest,run,results- Scanner orchestration module with support for OpenSCAP, InSpec, AWS/Azure Cloud Scanners, and Manual review
0.12.0 - 2026-04-04
Added
- Vendor management CLI:
pretorin vendor list/create/get/update/delete/upload-doc/list-docs - MCP vendor tools:
list_vendors,create_vendor,get_vendor,update_vendor,delete_vendor,upload_vendor_document,list_vendor_documents,link_evidence_to_vendor - Inheritance/responsibility MCP tools:
set_control_responsibility,get_control_responsibility,remove_control_responsibility,generate_inheritance_narrative,get_stale_edges,sync_stale_edges
0.11.0 - 2026-04-02
Added
- External-agent-first campaign orchestration with shared checkpointed prepare/claim/context/submit/apply/status flows
- Six MCP campaign tools:
prepare_campaign,claim_campaign_items,get_campaign_item_context,submit_campaign_proposal,apply_campaign, andget_campaign_status pretorin campaign status --checkpoint ...for attach/read-only visibility into prepared or running campaigns- Campaign workflow recipes for Codex, Claude Code, and other MCP-capable external agents
Changed
pretorin campaignnow prepares runs for external execution by default when the optional builtin backend is unavailable, instead of failing item-by-item- CLI and MCP campaign adapters now share one request-normalization and validation path to reduce drift
- Optional built-in executor dependencies are now exposed as
pretorin[builtin-agent], withpretorin[agent]preserved as a compatibility alias
0.10.0 - 2026-03-28
Added
- Workflow state and analytics MCP tools:
get_workflow_state,get_analytics_summary,get_family_analytics,get_policy_analytics - Family operations MCP tools:
get_pending_families,get_family_bundle,trigger_family_review,get_family_review_results - Policy workflow MCP tools:
get_pending_policy_questions,get_policy_question_detail,answer_policy_question,get_policy_workflow_state,trigger_policy_generation,trigger_policy_review,get_policy_review_results - Scope workflow MCP tools:
get_pending_scope_questions,get_scope_question_detail,answer_scope_question,trigger_scope_generation,trigger_scope_review,get_scope_review_results - ExecutionScope for thread-safe parallel agent execution
0.9.7 - 2026-03-25
Fixed
- Aligned CLI control status validation with the live platform status enum set, including
partially_implemented - Aligned MCP control status validation with the live platform status enum set to match public API behavior
- Synced package version metadata and release notes so PyPI builds publish a consistent CLI version
Changed
- Updated CLI and MCP coverage tests to reflect the platform control status contract used by public control workflows
0.8.7 - 2026-03-23
Added
- MCP questionnaire tooling for scope and organization policy workflows:
patch_scope_qa,list_org_policies,get_org_policy_questionnaire, andpatch_org_policy_qa
Changed
- MCP documentation now reflects the full 29-tool surface, including existing batch evidence support and the new questionnaire tools
0.8.6 - 2026-03-23
Added
pretorin context show --quietfor a compact one-line context summary that works well in scripts and shell promptspretorin context show --checkto fail fast when the stored system/framework scope is missing, stale, or cannot be verified
Changed
context shownow caches and displays the last known system name so offline or stale context output stays human-friendly instead of falling back to a raw UUID
Fixed
context shownow validates stored context against the platform and clearly reports invalid or unverified scope instead of silently treating deleted systems as active
0.8.5 - 2026-03-23
Fixed
- Reset active system/framework context when logging into a different API endpoint or with a different API key, preventing stale localhost scope context from bleeding into prod usage
- Align the model API base URL with the configured platform public API endpoint during login, so prod logins no longer keep talking to a localhost model proxy
- Make
scope populate --json --applyandpolicy populate --json --applypersist questionnaire updates instead of exiting after preview output - Raise the Codex subprocess line buffer to tolerate larger policy questionnaire responses without stream parsing failures
0.8.0 - 2026-03-07
Added
- MCP
generate_control_artifactsfor read-only AI drafting of control narratives and evidence-gap assessments using the same Codex workflow as the CLI - Shared AI drafting workflow helper for structured MCP/CLI parity around generated compliance artifacts
Changed
- MCP system-scoped tools now resolve friendly system names the same way the CLI does, returning canonical system IDs in responses
- Codex Desktop MCP configuration can be pinned to the UV-managed Pretorin wrapper to avoid PATH drift to incompatible installs
0.7.0 - 2026-03-07
Fixed
- Made control implementation parsing tolerant of deployments that return
notes: null, preventing narrative and implementation read crashes on untouched controls - Added compatibility fallback for control note reads when the dedicated
/notesendpoint returns405 Method Not Allowed - Added compatibility fallback for evidence search on deployments that only expose system-scoped evidence routes
- Prevented
pretorin agent run --no-streamfrom crashing when model output includes literal[[PRETORIN_TODO]]blocks
Changed
- MCP and legacy agent evidence search tools now accept optional
system_idcontext and use the same compatibility search path as the CLI
0.6.1 - 2026-03-05
Fixed
- Added required MCP registry ownership marker (
mcp-name: io.github.pretorin-ai/pretorin) to PyPI README metadata so MCP registry publish validation succeeds
0.6.0 - 2026-03-05
Added
- Shared markdown quality validator for auditor-readable artifacts, including strict no-heading enforcement and rich-markdown requirements
- Dedicated tests for markdown quality guardrails, including explicit image rejection
- CLI/MCP/agent parity for reading notes via the dedicated control-notes endpoint
Changed
- Narrative and evidence update flows now enforce markdown quality checks before push/upsert
- Agent prompts and skill guidance now require auditor-ready markdown (lists/tables/code/links) and ban image markdown until platform upload support is available
- Source tagging normalized to
cliacross CLI/MCP/agent write paths
Removed
- Markdown image usage from narrative/evidence authoring contract (temporarily disabled pending platform-side attachment support)
0.5.4 - 2026-03-05
Added
pretorin narrative getto read current control narratives from the platformpretorin notes listandpretorin notes addfor explicit control-note managementpretorin evidence searchfor platform evidence visibilitypretorin evidence upsertfor find-or-create evidence with control/system linking- Shared compliance workflow helpers for:
- system resolution
- evidence dedupe/upsert
- canonical narrative TODO block rendering
- canonical gap-note rendering
- MCP
get_control_notestool for note read parity
Changed
create_evidenceMCP behavior now upserts by default (dedupe: true) and returns normalized upsert metadata (evidence_id,created,linked,match_basis)pretorin evidence pushnow uses find-or-create upsert logic (reused matches are reported separately)- Agent skill prompts now include explicit no-hallucination guidance, structured TODO placeholders, and gap note format requirements
- Legacy agent toolset now includes
add_control_note,link_evidence, andget_control_notes
Removed
- Automatic control status updates and monitoring-event side effects from CLI evidence push workflow
0.5.3 - 2026-03-02
Fixed
- CI lint failure from
ruff format --checkby formattingsrc/pretorin/agent/codex_agent.pyandsrc/pretorin/cli/auth.py - CLI model key precedence:
OPENAI_API_KEY->config.api_key->config.openai_api_key
0.5.2 - 2026-02-27
Fixed
- Rich markup error in login flow — unbalanced
[dim]tags causedMarkupErrorcrash - Evidence type mismatch — CLI used
documentationbut API expectspolicy_document,screenshot,configuration, etc. - Control ID casing — CMMC-style IDs like
AC.L1-3.1.1were incorrectly lowercased bynormalize_control_id monitoring pushnow checks active context before requiring--systemflagpretorin loginskips API key prompt when already authenticated (validates key against API)- Demo script:
--jsonflag position (pretorin --json context show, notpretorin context show --json) - Demo script:
pausereads from/dev/ttyso commands no longer consume stdin meant for prompts
Changed
- Default evidence type changed from
documentationtopolicy_documentacross CLI, MCP, and agent tools - Valid evidence types aligned with API:
screenshot,screen_recording,log_file,configuration,test_result,certificate,attestation,code_snippet,repository_link,policy_document,scan_result,interview_notes,other - Demo walkthrough adds prerequisites note, fedramp-moderate validation, and checkpoint pauses between sections
- Added
.pretorin/andevidence/to.gitignoreto prevent accidental credential commits
0.5.0 - 2026-02-27
Added
pretorin context list— List available systems and frameworks with compliance progresspretorin context set— Set active system/framework context (interactive or via--system/--frameworkflags)pretorin context show— Display current active context with live progress statspretorin context clear— Clear active system/framework contextpretorin evidence create— Create local evidence files with YAML frontmatterpretorin evidence list— List local evidence files with optional framework filterpretorin evidence push— Push local evidence to the platform with review flaggingpretorin narrative push— Push a narrative file to the platform for a controlpretorin monitoring push— Push monitoring events (security scans, config changes, access reviews)pretorin agent run— Run autonomous compliance tasks using the Codex agent runtimepretorin agent run --skill <name>— Run predefined skills (gap-analysis, narrative-generation, evidence-collection, security-review)pretorin agent doctor/install/version/skills— Agent runtime management commandspretorin agent mcp-list/mcp-add/mcp-remove— Manage MCP servers available to the agentpretorin review run— Review local code against framework controls with AI guidancepretorin review status— Check implementation status for a specific controlresolve_context()helper for resolving system/framework from flags > stored config > error- Local-only mode: commands work without platform access, saving artifacts locally
- 14 new MCP tools: system management, evidence CRUD, narrative push, monitoring events, control notes, control status, control implementation details
add_control_noteMCP tool — Add notes with suggestions for manual steps or systems to connectadd_control_noteadded to narrative-generation, evidence-collection, and security-review agent skillsControlContext,ScopeResponse,MonitoringEventCreate,EvidenceCreateclient models- Control ID normalization (zero-padding NIST IDs like ac-3 → ac-03)
- Codex agent runtime with isolated binary management under
~/.pretorin/bin/ - Interactive demo walkthrough script (
tools/demo-walkthrough.sh) - Beta messaging across CLI banner, login flow, MCP server instructions, and README
- MCP server
instructionsfield guides AI agents on beta status and system creation requirements
Changed
- Default platform API base URL changed to
/api/v1/publicfor public API routing - Client methods updated to match new public API path structure
list_evidence()andcreate_evidence()now scoped to system (not organization)update_control_status()changed from PATCH to POST with body
Removed
pretorin narrative generatecommand — usepretorin agent run --skill narrative-generationinsteadpretorin_generate_narrativeMCP tool — the CLI generates narratives locally, never via the platform
Security
- All MCP mutation handlers now validate required parameters (system_id, framework_id) before API calls
- Added
system_idtocreate_evidenceandlink_evidenceMCP tool schemas (was missing) - Client-side enum validation for evidence_type, severity, event_type, and control status
- Path traversal protection in evidence writer (sanitized framework_id and control_id in file paths)
- TOML injection prevention in Codex runtime config writer
- Connection error handling now shows the URL being contacted
0.2.0 - 2026-02-06
Added
--jsonflag for machine-readable output across all commands (for scripting and AI agents)pretorin frameworks family <framework> <family>command to get control family detailspretorin frameworks metadata <framework>command to get control metadata for a frameworkpretorin frameworks submit-artifact <file>command to submit compliance artifacts- Positional
FAMILY_IDargument oncontrolscommand (pretorin frameworks controls fedramp-low access-control) - Full AI Guidance content rendering on control detail view
.mcp.jsonfor Claude Code MCP auto-discovery- Usage examples in all command docstrings and error messages
Changed
- Control references (statement, guidance, objectives) now shown by default on
controlcommand --references/-rflag replaced by--brief/-bto skip references (old flag kept as hidden deprecated no-op)- Default controls limit changed from 50 to 0 (show all) to prevent truncated results
- Improved error messages with example command syntax
0.1.0 - 2025-02-03
Added
- Initial public release
- CLI commands for browsing compliance frameworks
pretorin frameworks list- List all frameworkspretorin frameworks get- Get framework detailspretorin frameworks families- List control familiespretorin frameworks controls- List controlspretorin frameworks control- Get control detailspretorin frameworks documents- Get document requirements
- Authentication commands
pretorin login- Authenticate with API keypretorin logout- Clear stored credentialspretorin whoami- Show authentication status
- Configuration management
pretorin config list- List all configurationpretorin config get- Get a config valuepretorin config set- Set a config valuepretorin config path- Show config file path
- MCP (Model Context Protocol) server for AI assistant integration
- 7 tools for accessing compliance data
- Resources for analysis guidance
- Setup instructions for Claude Desktop, Claude Code, Cursor, Codex CLI, and Windsurf
- Self-update functionality via
pretorin update - Version checking with PyPI update notifications
- Rich terminal output with branded styling
- Rome-bot ASCII mascot with expressive animations
- Docker support with multi-stage Dockerfile
- Docker Compose configuration for containerized testing
- GitHub Actions CI/CD workflows for testing and PyPI publishing
- Integration test suite for CLI commands and MCP tools
- Comprehensive MCP documentation in
docs/MCP.md
Supported Frameworks
- NIST SP 800-53 Rev 5
- NIST SP 800-171 Rev 2/3
- FedRAMP (Low, Moderate, High)
- CMMC Level 1, 2, and 3
- Additional frameworks available on the platform