Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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-Client header while leaving unauthenticated probes and the existing User-Agent unchanged. 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_ID drift 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 objective commands 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 context now 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 deployment commands 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 update on 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 signed SHA256SUMS, which in turn binds the new RELEASE-TAG asset (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 to brew upgrade pretorin (brew owns the file), and macOS or other-architecture binaries keep manual guidance.
  • RELEASE-TAG release asset and an embedded-key release gate (#428). Every release now ships RELEASE-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_status and status://cli now return upgrade_requires_human_approval, upgrade_restart_required, and a route-specific upgrade_note alongside upgrade_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_workflow now supports compact validation-equivalent schemas and complete Markdown section slices; get_test_manifest supports exact rule_id filtering plus paginated summary mode; and cci show filters 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 /consent endpoint 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 / --json run 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 clear consent_required result (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 a 200 is an answer — a 404 (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_reason and 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_issues reads (#395). The MCP and built-in-agent tools now filter by status, page with limit/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> (or set_active_recipes in add mode) 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). --json now 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.txt page list, and docs changelog are accurate, and a cross-reference test guards internal links, anchors, and SUMMARY.md coverage against future rot.
  • Correctness and packaging fixes surfaced by the sweep. The legacy agent runner honors declared turn budgets, recipe validate flags unedited scaffold placeholders and rejects script names that cannot become MCP tool names, the PEP 561 py.typed marker ships so downstream consumers see types, and the pypdf and cryptography advisories 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-analysis now 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-create now 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-evaluate keeps 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 deprecated control-note-attestation recipe 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 say issues and issue_count rather 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 execute runs 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 are 0 for clean/submitted, 2 for detected inventory drift, and 1 for execution or submission errors.

Fixed

  • Abandoned plan drafts remain prunable (#369). pretorin plan prune now removes unactivated drafts older than the shared age threshold, measured from created_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_task now seeds a workflow-required mapping step and an immutable 800-character narrative completion criterion into every single-control Plan; activation preserves mapping immediately before evidence-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_evidence requires an expectation binding or explicit unbound_reason and 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 requires review_requested_by_user=true alongside trigger_review=true; explicit overrides re-read coverage after the write, return a visible warning, and require exact-generation analysis. ai_analysis is 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 dashboard with bounded posture, tier/provider, residual-risk heatmap, and expiry reporting from the organization-wide vendor dashboard endpoint. --horizon-days accepts 1–365 days and --json preserves the response body; 403 responses identify the required organization-scoped entitlement.

  • Vendor TPRM reporting dashboard — MCP tool (#321). Adds get_vendor_dashboard with 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_id UUID, and every campaign create write — each evidence batch item and control-issue creation — sends a derived idempotency_key ({run_id}:{item_id}:{artifact_type}:{revision}:{index}). A resumed or retried run reuses the same run_id, so the platform replays writes it already committed instead of duplicating them; a deliberate fresh campaign mints a new one. run_id is stored beside the checkpoint’s identity rather than inside it, so resume identity validation is unchanged. Submitting a new proposal over an item that already has receipts bumps its proposal_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 probes GET /capabilities once per run and records idempotency_support (supported / unsupported / unknown) in the checkpoint — an error response is unknown, never unsupported, 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_conflict is 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 recording issue_id: null on the issues endpoint, which returns the record under an issue envelope. 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 list now 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 the control_implementation_id and issue_id they take were never displayed. A single control’s listing prints the shared implementation id once in the header. New pretorin issues inbox lists 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. New pretorin issues update edits 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-get and action-get read one plan version (with its full approval lifecycle) or one action. plan-create/plan-update accept 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-set now 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 --status is validated against the server enum, and --note is required for the blocked and cancelled transitions the platform rejects without one.

  • get_system_issues, get_issue_plan, and get_issue_action MCP 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_issues filters by status, source, or one control with pagination, and normalizes through the same path as get_control_issues so 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 separate matched_total for everything the filter matched server-side. All three are registered in the control_issue_tracking capability, so search_platform_capabilities surfaces them.

  • Risk framing in local issue files. pretorin issues create accepts --title, --likelihood, --impact, and --risk-basis, and stores them in the file’s YAML frontmatter so pretorin issues push intakes 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-confirm records the risk determination (distinct from risk-add, which stays provisional — confirming supersedes any active acceptance, recomputes gate status, and can demote the control’s approval gate); accept and acceptance-revoke record and withdraw a formal risk acceptance; plan-approve, plan-reject, plan-opa-review, and plan-complete govern a submitted treatment plan; verify closes an Issue and void retires a finding that was never valid. The matching MCP tools are confirm_issue_risk_evaluation, accept_issue_risk, revoke_issue_risk_acceptance, approve_issue_plan, reject_issue_plan, review_issue_opa, complete_issue_plan, verify_issue, and void_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 to verification_pending, not closed), then verify it (which closes it). plan-complete and verify remain deliberately distinct steps. Void requires explicit --force/force=true confirmation 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-positive and --operational-requirement are 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_ids to an endpoint that takes a singular control_id, so the filter was accepted and silently ignored, and a family_id the platform now rejects outright with a 400 — which broke pretorin campaign controls --all-open-issues --issue-family and made --issue-controls a 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 resolve closed an Issue by sending is_resolved=true through the generic control-issue PATCH, which the platform rejects with issue_verification_required — so closure had never actually worked from the CLI, the resolve_control_issue MCP 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’s control_implementation_id from the control listing (which in the same call confirms the Issue exists under that control) and pre-flights lifecycle_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 and resolve’s closing behavior is a documented compatibility wrapper. --reopen and metadata-only updates keep using PATCH, which remains the supported path for both, and the client now refuses is_resolved=true outright so the dead path cannot be reintroduced. Campaign apply records a proposed closure as a skipped receipt 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 where GET already 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_blocking is now documented as the always-true compatibility flag it is: the canonical Issue domain has no non-blocking Issue, historical false rows 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 from pretorin issues list, while is_blocking, blocking_total, and non_blocking_total are retained on the wire for clients that read them (non_blocking_total is always 0). Above-target suggestions are described in their real home, ai_analysis.gaps_detail, where is_blocking genuinely can be false. verification_pending remains distinct from closed throughout.

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_incomplete details, 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). Repeated start_task calls no longer accumulate duplicate Plans. Before creating one, start_task looks for non-terminal Plans in the identical execution context — same workflow, same scope (system, framework, control, and any workflow-specific targets kept in scope.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 in resume_candidates using the same summary shape as list_recent_plans; a single candidate is adopted and its id returned as plan_id, while two or more leave the choice to the caller. The new top-level create_new_plan=true argument 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, and evaluator_results, and document the draft → active → completed/cancelled lifecycle.

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.txt manifests 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_narrative MCP 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_questionnaire gains an include_guidance=false projection for retrieving large questionnaires without static template guidance.

0.26.13 - 2026-07-21

Added

  • get_policy_narrative read tool for safe surgical policy edits (#312, monorepo #2282). Adds the MCP tool get_policy_narrative, the CLI command pretorin policy narrative, and the client method PretorianClient.get_policy_narrative, all reading GET /org-policies/{id}/sections — the read counterpart to update_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 was get_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|revoke to 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 systems command group (list/attach/detach) and pretorin vendor residual-acceptance sign mirror 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). attach takes one or more --system-id values; sign records 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 contact and pretorin vendor contract command 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 carry name, email, title, phone, is_primary (auto-demotes the prior primary), and notes. Contracts carry name, contract_type (contract/sla/dpa/order_form), date/renewal/notice/termination fields, and a linked document evidence item; the server-derived status and is_expired are rendered read-only and cannot be set. All contact/contract endpoints require the server-side vendor.pii scope (or an admin token).
  • Vendor Management Phase 3 core. New pretorin vendor lifecycle <vendor_id> <target_status> command and set_vendor_lifecycle MCP tool transition vendors between onboarding/active/inactive with a required audit --reason (≤500 chars); the endpoint requires the server-side vendor.pii scope (or an admin token). vendor list / list_vendors gain --include-inactive and --lifecycle-status filters, and vendor listings/details now surface lifecycle status and document-expiry flags (has_expired_document, has_expiring_document). vendor upload-doc / upload_vendor_document accept --expires-at and --refresh-cadence-days for document expiry and refresh reminders, and vendor list-docs now shows expires_at and is_expired. vendor assessment launch prints an actionable message when a vendor is inactive.

Changed

  • Backward-compatibility call-out: pretorin vendor list (and the list_vendors MCP tool) now omit inactive vendors by default. Pass --include-inactive (CLI) or include_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.txt manifests 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-baseline now captures each node’s OS from status.nodeInfo.osImage into os_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 k8s gains a --namespace-env option 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 to prod. 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_tier and tier_label metadata. Regression coverage confirms the additive response fields pass through the MCP and start_task surfaces 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_label and scope-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.txt manifests 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-capture for generic manual-review and attestation expectations when manual-attestation has 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). ScopeResponse now carries the platform’s additive template_id, template_label, and document_title fields, so the CLI and MCP get_scope passthrough can tell which document a system is scoping (SOC 2 System Description vs NIST SSP scope). pretorin scope show prints a Document: header line when the platform supplies a label, and the scope help text notes that the question set and section labels are framework-dependent. Purely additive — scope_narrative/scope_qa_responses stay 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_recipe without a control_id now opens a family context scoped to system_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 own control_id for 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_recipe friendly system-name regression coverage (#283). Added regression tests proving start_recipe accepts 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_evidence parity (#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, preserves metadata_key_count / control_mapping_count / truncation markers from compact responses, and exposes include_metadata (plus the MCP/agent include_full_detail alias) to opt into full per-result metadata and control mappings when needed. The CLI and tool wrappers also forward snippet_chars to 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-baseline now emits platform-valid asset_type values (container for workload controllers and endpoint for LoadBalancer Services), infers environment from labels or namespace defaults such as pretorin -> dev and pretorin-prod -> prod, and leaves unknown environments unset instead of guessing prod. 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_task MCP result size (#273). A single-control start_task response no longer overflows the MCP result token cap (it was ~75 KB and forced the host to spill to disk, breaking the documented “call start_task first” entrypoint). The compact capture plan now drops the top-level recipe_gaps array — a verbatim duplicate of the per-item recipe_gap — in favour of a recipe_gap_count (the per-item recipe_gap stays canonical); lifts the host ready_source_kinds / ready_alternative_recipe_ids lists (identical on every gap) to one top-level ready_alternatives object each gap points at; and drops the per-item reason when it is a verbatim copy of recipe_gap.reason. The routed/ambiguous start_task response also summarizes inspect_summary.org_policies to an org_policies_count (call list_org_policies for the full list), and the compact response_mode path 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 via check_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_count markers) 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-capture recipe 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 ranks ci_cd_platform and code_repository ahead 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_profile summary 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.probe strings now run through sh -c, so shell operators and environment expansion behave as users expect; explicit params.command argv 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_numbers is validated as a single line or range with clear guidance to use source_locator for 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_preflight now 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_manifest falls through to the platform’s recommended source kinds when no local manifest exists, and confirmed scope scale (cached_scale_tier) surfaces in pretorin context list, pretorin scope show, and system reads. pretorin preflight init seeds platform recommendations for the scope and restricts default bindings to them. Platform scope_incomplete refusals now stop start_task/get_control_context/check_sources with 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) and scope (structured usage intent, e.g. subscription/region) via pretorin preflight bind --constraint/--scope. Binding-derived scope becomes recipe param defaults on both surfaces — MCP start_recipe reports them as source_params, pretorin recipe run prints the applied defaults — with explicit caller params always winning. Scope never crosses cloud providers (an az-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 tools get_active_recipes (active set + candidates + coverage gaps + version drift) and set_active_recipes (replace/add/remove); new CLI pretorin recipe activate/deactivate/active, pretorin recipe list --active, and pretorin preflight provision [--apply]. list_recipes annotates each recipe with an active flag and accepts active_only. Once a scope is provisioned, start_recipe refuses recipes outside the active set (force=true for 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). New pretorin stig subcommands 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), and import <checklist-id> <file> [--format auto|ckl|cklb|xccdf] (push a review-axis .ckl/.cklb file, or route --format xccdf to 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. The openscap-baseline recipe 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_sources MCP 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. Use get_source_manifest and check_sources for source preflight.

Fixed

  • MCP result sizes on hot paths (#247). Multi-control start_task now returns a bounded per-control capture-plan summary (counts, statuses, a top_capture_hint per control — full per-expectation detail via check_sources), and RAG search_evidence requests are clamped to 10 results across MCP, CLI --json, and pretorin 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-chars parity with the MCP knobs, and the interactive table honors --limit unclamped.
  • 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. Default preflight init bindings no longer flip to permanently degraded the 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) or overwrite=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; the Content-Disposition basename sanitizer also strips Windows drive-relative prefixes (C:evil.bat); and import transport failures surface as PretorianClientError like every other client call. The openscap-baseline recipe accepts a profile param (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. replace mode 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 as deactivated. 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, and pretorin recipe activate with only unknown ids exits non-zero.
  • check_sources / capture-plan recipe_gap dead-ends (#248). A control whose ai_guidance source hints point at a source kind no recipe covers (e.g. enterprise-SaaS kinds like siem_log_platform) no longer returns a bare “no installed recipe can produce evidence” dead-end. recipe_gap now 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_error previously passed a dict detail straight through as the error text, so a structured 409 refusal (scope_incomplete, and the new per-framework controls_scope_not_approved gate) rendered as a stringified dict in error.message — e.g. the capture-plan control-context read showed {'code': ..., 'message': ...} instead of the human sentence. The client now extracts the refusal’s message as the error text and keeps the full payload (including code and scope_page) in error.details, so callers and the agent see the actual reason (“approve control scope for this framework on the platform…”) and can still branch on code. Like scope_incomplete, controls_scope_not_approved is a human/platform action the CLI cannot self-serve.
  • MCP hot-path response sizes (#221). start_task.suggested_capture_plan and check_sources now compact verbose per-expectation source_hints by default, returning source_hint_count plus a preferred_source_hint summary unless include_source_hints=true is requested. RAG search_evidence responses now replace body-sized fields such as artifact_content and matched_text with snippets and omitted-character counts by default; callers can opt into capped body content with snippet_only=false and max_body_chars.
  • Recipe-context evidence tally follow-up (#201). create_evidence now reconciles EvidenceUpsertResult.created with the platform’s operation_status, so platform idempotency responses such as reused / already_linked no longer bump evidence_count or append produced_evidence_ids after a stale client-side dedupe miss. The batch tally path is pinned to the confirmed platform contract: only per-item status: "created" counts as a produced row; generic success strings do not.
  • generate_inheritance_narrative sent no request body. The client posted only a framework_id query param and no JSON body, so the platform returned body: Field required and 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 --replace is 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 MCP list_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_preflight summaries before they can be persisted or returned. JSON probe output now surfaces a useful identity instead of a bare {, and pretorin preflight show displays details for unverified rows such as rejected workspace markers.
  • Typed CLI --param values. pretorin preflight bind --param key=value now coerces numeric/boolean values to JSON scalars, so --param timeout=60 is 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 open type + params; its only hard contract is “can I be verified?”. Built-in verifiers: workspace_path, cli_tool (gh/az/aws/kubectl auth probes), command (generic), manual/attested (user-asserted, never silently “connected”), plus probe-or-unverified for mcp/connected_api/pretorin_feature. The registry fails open — unknown types with a declared probe run it, otherwise report unverified.
    • 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.
    • preflight workflow + pretorin preflight CLI + MCP tools. The interactive workflow maps recommended kinds to resolver collections, verifies them, and reports the verdict. pretorin preflight show / verify / bind is the human surface; get_preflight / verify_preflight / update_preflight are the agent surface.
    • Recipe capabilities + executor grain. SourceRequirement gains an optional capabilities list. start_recipe now consults preflight and refuses to open a context when a required source kind is verified missing (overridable with force=true); unknown/unverified fails open, so planner and executor agree.

Changed

  • Source availability now reads the preflight verdict, not the platform registry. capture_plan, list_recipes, and check_sources decide availability from the local verdict. An absent/empty verdict reads as source_unknown (a soft “verify before capture”), and only a verified-missing kind reads as source_unavailable — the old empty-registry false-negative is gone. list_connected_sources remains 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:, and TODO: 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_responsibility MCP tool — sends a complete request body. The client previously sent only responsibility_mode, source_type, and vendor_provider_id, missing the control_id, framework_id, and source_control_id fields the platform’s CreateResponsibilityEdgeRequest requires and using the wrong key name for the vendor (vendor_provider_id instead of source_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, normalizes source_control_id (defaulting to the target control id for the common vendor-inheritance case where the source covers the same control concept), maps vendor_id to source_provider_id, and accepts an explicit source_system_id for org-system inheritance. The MCP tool schema exposes source_control_id and source_system_id as 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 in pretorin.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_reason validation in the evidence MCP handlers into a shared resolve_override_or_error helper; added unit coverage for the InSpec and OpenSCAP scanners (0% → ~95%/98%); refreshed uv.lock (no vulnerabilities, dropped the now-unused types-requests transitive); and applied ruff format to 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 the llms.txt manifests — 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=true flag 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 --force no 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-artifacts workflow + scope_artifacts intent verb. start_task routes scope-artifact intent to a dedicated workflow (distinct from the answer questionnaire loop) that walks each system-spec kind: produce → upload → link → attest.
    • Three system_spec MCP write toolslink_spec_snapshot, attest_spec_snapshot, attest_spec_inventory — wrapping the platform’s /spec/snapshots/* and /spec/inventory/attest endpoints. kind is free-form (validated against list_artifact_requirements) so the CLI can’t drift from the platform’s kind registry. All three are workflow-tier writes that thread plan_id / step_index and record PlanArtifacts (new kinds spec_snapshot_link, spec_attestation) into the plan’s produced_artifacts[] audit chain.
    • Plan completion gate all_required_spec_kinds_attested. A new typed AcceptanceCriterionKind whose evaluator refuses complete_plan until 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 new acceptance_criteria field on the workflow manifest, and start_task seeds them onto the plan at instantiation.
    • General-purpose HTML evidence composer (pretorin.evidence.html). A reusable sibling to the markdown composer: compose_html_document wraps 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_table renders 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-compose recipe — 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-mgmt classes 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-scrolling pt-figure, plus a wide param 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 helper pretorin.evidence.svg_layout (SvgCanvas + anchor + route_*) implements the layout moves — boxes, zone/cluster/boundary containers, orthogonal connectors with arrowheads, collision-aware labels, all emitting the pt-* 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_task validation errors are now path-qualified — fixes walkthrough Bug #15. When a calling MCP agent omitted a required field from inside entities (e.g. intent_verb or raw_prompt), the handler previously returned entities 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, added intent_verb at the top level (the wrong place), and looped through several retries before discovering the nesting requirement. The handler now parses ValidationError.errors() and emits one entities.<path>: <msg> line per error, plus a one-line reminder that all prompt-derived fields must live inside the entities wrapper. 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 in tests/test_mcp_engagement_handler.py (test_missing_intent_verb_error_is_path_qualified, test_missing_raw_prompt_error_is_path_qualified).
  • end_recipe accepts recipe_context_id for parity with sibling tools — fixes walkthrough Bug #16. update_narrative, add_control_issue, resolve_control_issue all accept the recipe-execution handle as recipe_context_id, but end_recipe was the lone exception that required context_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 canonical recipe_context_id; the legacy context_id parameter is still accepted with a deprecation warning logged through logger.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 teach recipe_context_id. Four regression tests added in tests/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 on pretorin-public-platform.
  • Pending-question routing dead-end (#208). start_task routed a completed scope to the dead-end scope-question workflow because the router ran bool() on the get_pending_*_questions dict (always truthy) instead of reading pending_count. Fixed for both the scope and policy paths, and the scope-artifact intent now has a real destination.
  • answer_scope_question / answer_policy_question doc mismatch (#209). The scope-q-answer / policy-q-answer recipes and the scope-question / policy-question workflows instructed the agent to pass a recipe_context_id the 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_snapshot sent evidence_id (server wants evidence_item_id); attest_snapshot / attest_inventory sent rationale instead of the required sufficiency envelope. Corrected to the platform contract.
  • MCP schema enum drift. The start_task intent_verb enum and the create_plan acceptance-criterion kind enum are now pinned by tests to their Python source-of-truth (the IntentVerb Literal / 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_diff now documents the platform-validated enums for asset_type / environment / data_classification (a wrong value 422s); the sufficiency.canonical_source_id field 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); and pretorin scope artifacts inventory scan no longer loses the [cloud-inventory] extra to Rich markup, so the SDK-missing hint correctly reads pip install 'pretorin[cloud-inventory]'.

Documentation

  • Rewrote docs/src/workflows/system-spec.md to 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-artifacts workflow 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 where end_recipe returned evidence_count: 6 after the agent’s 3 actual evidence creations and evidence_ids: [] despite those creations. Two bugs collapsed into one:

    • ContextStore.record_evidence_write was called inside _build_audit_metadata_for_write before 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 on EvidenceUpsertResult.created is True for the single-evidence path and on the batch result’s per-item status == "created" for the batch path. Dedupe reuses, link-only reuses, and errored items no longer move the count.
    • ExecutionContext.evidence_ids was an input-only field (evidence the caller passed to start_recipe for narrative-citing recipes), but RecipeResult.evidence_ids returned the same list, conflating “supplied” and “produced”. A new produced_evidence_ids: list[str] field carries the ids of new rows the recipe actually created, in creation order. The input evidence_ids field is preserved unchanged so existing narrative-recipe callers continue to work.
  • Updated record_evidence_write signature — now accepts an optional evidence_id keyword that, when supplied, also appends the id to ctx.produced_evidence_ids. The legacy id-less form (count-only bump) is preserved for tests.

  • Docstrings on ExecutionContext.evidence_count and the two evidence_ids fields 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 is created. Full pytest suite green: 3105 passed.

  • Plans Phase B3 — step_index=0 on campaign-workflow plans no longer short-circuits the B3 audit chain. resolve_plan_coordinates previously raised PlanStepError (“step_index 0 out of range; plan has 0 step(s)”) whenever a caller passed any step_index on a plan that didn’t pre-populate plan.steps — which is every campaign-workflow plan, because campaigns list their controls in scope.extra.control_filter rather than as explicit steps. The error short-circuited the handler before record_plan_artifact_safely could append to produced_artifacts[], silently breaking the B3 audit chain for every multi-control walkthrough in production. Discovered during the SOC 2 walkthrough on pretorin-public-platform: 13 successful MCP writes (status, link_evidence, create_evidence, update_narrative, resolve_control_issue) all carrying plan_id + step_index=0 produced zero produced_artifacts[] entries; the underlying record path was fine, the bounds check was wrong. The fix only enforces step_index < len(plan.steps) when the plan has at least one explicit step; for stepless plans (campaigns and anything similar), the write proceeds and step_index is dropped to None rather 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 in tests/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 the entities property 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 the entities object, with only active_system_id / active_framework_id / skip_inspect at 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 from entities alone.
    • start_recipe: the recipe_version property description now points callers at get_recipe(recipe_id).manifest.version (or the version field returned by list_recipes) and warns against hard-coded values that will break when the recipe registry advances.
    • create_evidence / create_evidence_batch: the source_locator property description now explains the platform-side audit-metadata contract (issue #701), the handler’s auto-derive-from-code_line_numbers fallback, and that non-code sources (policy excerpts, docs, vendor reports, dashboards) must pass an explicit locator like section 3.7 / page 4 paragraph 2, otherwise the platform rejects the write with Missing: 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 (completed or cancelled) whose terminal timestamp is older than --older-than-days (default 30). Active plans are NEVER pruned regardless of age. Defaults to interactive confirmation; --yes skips the prompt, --dry-run previews the action without touching disk, --include-corrupt opts the operator into deleting unparseable plan files (the default reports them only). The corresponding PlansStore.prune(*, older_than_days, include_corrupt, dry_run, now) API returns a typed PruneResult carrying 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_CRITERIA cap (32). The Plan model rejects any acceptance_criteria list longer than the cap via a @field_validator that fires at both create time and load time, with matching early-rejection guards in PlansStore.create and handle_create_plan so an over-cap input never reaches per-item Pydantic validation. The MCP create_plan inputSchema advertises maxItems: 32 so 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 force complete_plan to make a corresponding number of platform reads.
  • Plans Phase B4 polish — log-on-exception in the acceptance fetcher adapter. _PretorianClientAcceptanceFetcher.get_narrative and get_evidence_count_for_control previously swallowed every PretorianClient exception silently and returned the fail-safe value (None / 0). They now also emit a logger.warning(...) carrying sanitized metadata — exception type plus HTTP status code when the exception is a PretorianClientError — 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_index flow 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 optional plan_id + step_index parameters. Each handler runs a resolve_plan_coordinates preflight that validates the plan id shape, loads the plan, refuses non-active plans, and bounds-checks step_index. After a successful platform write, record_plan_artifact_safely appends a typed PlanArtifact (one of eight kinds: evidence, evidence_link, narrative, control_issue, control_status, monitoring_event, scope_qa, policy_qa) to the plan’s produced_artifacts[] list — the local audit chain a future auditor reads to trace every artifact this plan produced. plan_id / step_index are 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 via extra="ignore" until indexing-by-plan ships server-side.
  • PlanArtifact model + PlansStore.record_artifact() method. New typed model with kind enum, optional step_index (≥ 0), optional control_id, required artifact_locator (1-300 chars), recorded_at timestamp, and a JSON-serialisable extra payload capped at 2 KiB. record_artifact requires the plan to be active (terminal plans refuse to accept further artifacts so finalized audit chains stay finalized), honours expected_version for optimistic locking, but does not bump Plan.version itself — appending an artifact is runtime progress, not a structural edit (RFC Decision 2; same logic as update_plan_step status changes). The produced_artifacts list is capped at MAX_PRODUCED_ARTIFACTS = 500 per plan, enforced via a @field_validator at both create and load time plus a PlanArtifactLimitError raised from record_artifact — well above any realistic plan size while keeping the worst-case plan-file size well under MAX_PLAN_FILE_BYTES = 1 MiB.
  • MCP schemas advertise the new fields. Each of the 14 wired Tier-1 tool definitions in mcp/tools.py exposes plan_id (string) and step_index (integer, minimum 0) as optional properties so MCP-client agents discover the parameters via tool introspection. Neither field is in required; omitting them keeps pre-B3 call semantics (no plan attached, no audit-chain entry).
  • CLI render: pretorin plan show adds a Produced artifacts section listing each artifact’s kind, step pointer, control id, recorded timestamp, locator, and truncated extra blob; the full payload is preserved in --json mode. 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 notes and pretorin issues are 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 in src/pretorin/cli/_control_annotations.py — a frozen AnnotationKind descriptor (NOTE / ISSUE) parameterises the platform-client method names and display terminology, and issues.py / notes.py shrink 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.py from 17% to 100% line coverage with a new tests/test_cli_issues_coverage.py suite; applied ruff format to tests/evidence/test_audit_metadata.py; and verified the version is aligned across pyproject.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-adjacent CLI.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, the USER environment variable, and the llms.txt / llms-full.txt manifests — then rebuilt the committed mdBook output and confirmed no dead or unresolved internal references remain.
  • Backward compatible: PLAN_SCHEMA_VERSION stays at 1. Existing ~/.pretorin/plans/*.json files written before this version load cleanly with produced_artifacts=[] as the default. Pre-B3 callers that omit the new plan_id / step_index kwargs 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, the resolve_plan_coordinates helper, the _attach_plan_metadata client helper applied to each of the 14 write methods, and the CLI render of produced_artifacts. Full quality gate green: 3073 pytest, ruff/format/mypy strict, MCP smoke 20/20.

0.23.8 - 2026-06-18

Fixed

  • MCP start_task inspect-status system resolution (#191): inspect_status now 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-section System not found errors. 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 on complete_plan. The Plan model now carries a monotonic version: int counter (default 1) and an acceptance_criteria: list[AcceptanceCriterion] (default empty). All three mutation methods on PlansStore (update_step, complete, cancel) and their MCP handlers accept an optional expected_version for optimistic locking — mismatched versions return a structured version_conflict error with both expected and actual versions in the JSON body so the caller can reload and retry. complete_plan runs 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 structured acceptance_failed error carrying the full failed_criteria[] list so the agent fixes every gap in one shot. The plan stays active on a failed gate so the agent can address the gap and retry. Empty acceptance_criteria preserves pre-B4 behaviour (no gate, last-write-wins). A TOCTOU guard pins the plan version we evaluated against through the actual complete() 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_acceptance module with the per-kind evaluator functions and an orchestrator evaluate_plan_acceptance(plan, fetcher) that returns the structured failure list. Evaluators depend on a narrow PlanAcceptancePlatformFetcher protocol — the production adapter (_PretorianClientAcceptanceFetcher in the handler module) wraps PretorianClient with 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_plan advertises acceptance_criteria array on each step item; update_plan_step, complete_plan, and cancel_plan advertise expected_version (integer, min 1). pretorin plan show renders version next to the plan id and a dedicated Acceptance criteria section 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 list now 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 support owner_user_id and inherent_risk, and pretorin vendor history plus MCP get_vendor_history mirror the public /vendors/{id}/history endpoint.

Changed

  • Backward compatible: PLAN_SCHEMA_VERSION stays at 1. Existing ~/.pretorin/plans/*.json files written before this version load cleanly with the new defaults applied (version=1, acceptance_criteria=[]), and step-status changes via update_step deliberately do not bump version per 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 alias medium is accepted by CLI create/update, normalized to moderate, 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 against checksum_sha256; the file is not written and the command exits non-zero on mismatch), and latest --type <type> [--download] (newest validated artifact of a type; exits non-zero when none exists). Only generation_state=succeeded + validation_status=valid artifacts 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 tools list_oscal_artifacts / get_oscal_artifact.

0.23.5 - 2026-06-15

Added

  • Plans flow — Phase B2: typed PlanStep parameters. PlanStep now carries two new optional fields: recipe_version (string, max 50 chars, only valid when kind == "recipe") and params (free-form JSON-serialisable dict, capped at 8 KiB serialised via the new MAX_STEP_PARAMS_BYTES constant). A pydantic model validator rejects recipe_version on 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 MCP create_plan inputSchema advertises both new fields on each step item, and pretorin plan show renders them inline — recipe_version as a v<version> suffix on the step line, params truncated to 100 chars on a ↳ params: continuation line (the full payload is always available via --json / get_plan).

Changed

  • Backward compatible: PLAN_SCHEMA_VERSION stays at 1. Existing ~/.pretorin/plans/*.json files written before this version load cleanly with the new defaults applied (recipe_version=None, params={}), and update_plan_step preserves 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_error helper (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_recipe opened a recipe-execution row with no scope check, an agent could bypass the existing write guards by passing allow_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_override is 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 with pretorin context set moves 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.0 to rust-v0.137.0 with 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-pin branch 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_task instantiates a plan and returns plan_id. When the routing layer settles on a non-ambiguous, non-null selected_workflow, the engagement handler now persists a Plan record from the resolved scope and stamps the new EngagementSelection.plan_id field. Agents can drive subsequent execution from the plan via get_plan / update_plan_step / complete_plan. create_plan remains agent-callable for advanced cases per the resolved design decision. Backward compatible: every existing EngagementSelection field is preserved, agents that don’t read plan_id keep 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 during start_task are non-fatal: the routing decision still returns cleanly with plan_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>.json with 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 plan CLI surface. Operator-side commands pretorin 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.md documenting 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_plan stays agent-callable alongside start_task; plans are mutable with monotonic version bumps; complete_plan runs 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_id guard used by the MCP artifact and risk handlers into a shared helper; dead-code removal (unused YELLOW color constant, unreachable codex_bin_dir property, 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 new GET /api/v1/public/systems/{id}/risks/posture endpoint. 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 via POST /api/v1/public/systems/{id}/risks/{rid}/attest. The signed payload reuses the existing evidence attestation signer + key registry, so verifiers resolve trust uniformly. --type is validated client-side against residual_accepted | mitigation_approved | inherent_validated so 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-baseline recipe (and the AWS, Kubernetes, and IaC-workspace recipes) now distinguish “the scan broke” from “there are genuinely no assets”: failures are surfaced in an errors list instead of silently returning scanned: 0. pretorin scope artifacts inventory scan now 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-inventory dependency 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_REGION to scan a single region. Azure subscription is resolved from AZURE_SUBSCRIPTION_ID or the logged-in az default.

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 shared exit_with_error helper. 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 update no 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 of pretorin@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 update refreshes uv’s package index for latest installs: uv-managed no-argument updates now run uv 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 fresh 0.22.12 release first resolved only to 0.22.11.

0.22.12 - 2026-05-29

Fixed

  • pretorin update restores 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 unpinned pretorin@latest install 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 update through uv pip install --python ... --upgrade --refresh pretorin instead of python -m pip. The installer subprocess also preserves detected uv/pipx tool homes for custom tool directories.
  • pretorin update avoids local import shadowing: installer and verification subprocesses now run from the active venv root (or home directory fallback) and strip PYTHONPATH/PYTHONHOME, preventing untrusted working-directory files such as pip.py or pretorin.py from 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-markdown available for file/stdin reformatting.

0.22.10 - 2026-05-29

Added

  • Control issues workflow: Added the first-class pretorin issues CLI, matching MCP/agent issue tools, local issue writer/sync support, and issue-driven campaign targeting with issues-fix plus --all-open-issues selectors.

Changed

  • Legacy notes commands 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_implementation now reports the canonical narrative source, note writes require a dedicated control-note-attestation recipe 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 get and pretorin evidence attestation verify subcommands 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 through GET /api/v1/public/keys rather 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 matching get_evidence_attestation MCP tool lets external agents fetch the envelope (plus an optional lineage view) for any evidence record. New cryptography>=42.0.0 runtime dependency.

0.22.7 - 2026-05-26

Added

  • Scoped evidence RAG search (#148): search_evidence now 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, and system_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_note no longer 400’s Claude-based clients: the tool’s input schema declared a top-level allOf to express “resolution_note is required when is_resolved is true”. Claude’s API rejects anyOf/oneOf/allOf at the top level of tool input_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 update detects uv/pipx installs outside the default folders: the installer detector now reads uv’s uv-receipt.toml and pipx’s pipx_metadata.json from the running venv before falling back to path heuristics. This keeps custom uv/pipx tool installs from falling through to python -m pip, which fails in tool venvs that intentionally omit pip.
  • Update notices point at pretorin update: passive CLI/MCP status prompts no longer hardcode pip 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 update no 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.Z pin. 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 unpinned pretorin@latest form was unaffected because it uses uv’s live-resolve path. Now pretorin update dispatches uv tool install --force pretorin@latest directly and lets uv be the single source of truth for what “latest” means.
  • Explicit-version updates use --refresh: pretorin update X.Y.Z now passes --refresh to uv (and --no-cache-dir to pip/pipx) so the installer invalidates any cached index data before resolving. Same intent as the @latest path: avoid the dual-index-view race.

Removed

  • JSON-API pre-resolution + post-install verify dance: pretorin update no 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 to typer.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.tools declared optional parameters in properties without listing them in required. OpenAI’s strict-mode function-calling validator rejected the entire tools array before any model turn ('required' is required to be supplied and to be an array including every key in properties). Added _to_strict_schema which normalizes schemas at the SDK boundary: every property gets added to required, and optional properties become nullable unions (["string", "null"]). Applied in to_function_tool so 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 by chain, 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 show always reported empty (#133 follow-up): the CLI read the response under payload["assets"] but the platform returns asset rows under "items". Same bug caused inventory scan to misclassify every row as added (it diffed against an empty existing inventory). Both paths now read payload["items"].
  • artifacts toggle always 422’d (#133 follow-up): the client posted {"optional": ...} but the server’s PATCH schema is keyed on toggled_off. Renamed the wire field while keeping the user-facing --optional/--required flag unchanged. The artifacts list renderer now reads either toggled_off or legacy optional defensively.
  • Added two TestSystemSpecEndpoints regression 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 can artifacts list, inventory show [--as-of T], inventory upload <csv>, inventory scan <source>, and artifacts 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 accepts recipe_context_id but 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), and asset-inventory-iac-workspace (static parse of .tf / .tf.json / K8s YAML / CloudFormation files in the cwd — no cloud credentials required). All four ship as tier: 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_id is now forwarded on recipe-produced evidence writes, including batch evidence.
  • Narrative citations were rejected. Citations are now sent as evidence_citations so the platform can validate the supporting evidence.
  • pretorin update was 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_status now 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_plan now falls back from control context to get_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-capture is 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_requirements client/MCP surface and pretorin frameworks documents command. Evidence requirements are derived from AI guidance.

0.21.3 - 2026-05-19

Fixed

  • pretorin update works on uv tool and pipx installs: the update command now detects how pretorin was installed by inspecting sys.executable and dispatches to uv tool upgrade pretorin or pipx upgrade pretorin when appropriate. Previously it always shelled out to python -m pip install --upgrade, which fails with No module named pip on recent uv versions because tool venvs no longer ship pip. Pinned upgrades (pretorin update X.Y.Z) route to uv tool install --force / pipx install --force so 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_EVENT with event_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 exposes list_connected_sources and check_sources, start_task returns suggested_capture_plan, and list_recipes(system_id=...) filters to source-eligible recipes while failing open on older platform deployments.
  • Narrative recipe support (#118): start_recipe accepts evidence_ids, update_narrative requires a narrative-producing recipe context with cited evidence ids, and the built-in evidence-narrative-compose recipe provides the canonical narrative path.
  • Workspace capture floor recipe (#118): workspace-capture generalizes 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, and update_narrative now reject agent writes without recipe_context_id using a structured recipe_required error.

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 resolve accepts --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 see mcp__pretorin__check_context instead of mcp__pretorin__pretorin_check_context. Recipe-script tools follow the same rule (recipe_<id>__<script> instead of pretorin_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 initialize instructions 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’s instructions block, 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 (still isError=true) instead of plain-text errors. routing_hint.suggested_intent_verb tells the agent the exact start_task call to make. Backed by a new WorkflowRoutingError exception class.
    • Workflow schema bundling: get_workflow now bundles required_tool_schemas — the full MCP Tool definitions 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 successful start_task and on WorkflowRoutingError raises. Feeds the phase-4 trigger decision in the RFC. Opt out with PRETORIN_MCP_TELEMETRY_DISABLED=1.
    • pretorin mcp-smoke-test command: 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 description summaries plus standalone Markdown artifact_content, with source/capture context in audit_metadata (source_label, source_locator, source_excerpt, content_hash, capture_method, and related fields). Batch evidence follows the same per-item contract. Added pretorin evidence validate to compare fresh source-material hashes before re-verifying; drifted sources update the existing evidence artifact with a drift_note instead of silently calling mark-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-days flag and mark-current command (#108 PR B): pretorin evidence upsert accepts --cadence-days <int> to opt new evidence into a refresh cadence; the platform then computes expires_at server-side and includes the row in the daily freshness sweep. New pretorin evidence mark-current <id> subcommand re-affirms that evidence is still current — bumps expires_at by the cadence, transitions expired→valid, writes a re_verified lineage row, and auto-resolves any open evidence.expiring/evidence.expired monitoring events. EvidenceCreate carries the new refresh_cadence_days field. 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 upsert gains --coverage-start, --coverage-end, and --capture-query flags so callers can populate the new auditor sufficiency columns. The MCP create_evidence tool accepts the same arguments. EvidenceCreate and EvidenceBatchItemCreate now carry data_coverage_start_at, data_coverage_end_at, and capture_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 upsert and MCP evidence writes now serialize audit_metadata.captured_at using Pydantic JSON mode before handing payloads to httpx. Previously, recipe/agent-stamped evidence failed locally with TypeError: Object of type datetime is not JSON serializable before 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 reads active_system_id / active_framework_id from Config instead of PretorianClient (getattr(client, ...) was silently returning None because those attributes live on Config). Every scanner recipe (manual-attestation, inspec-baseline, openscap-baseline, cloud-aws-baseline, cloud-azure-baseline) was failing at fetch_test_manifest with System not found because ctx.system_id reached the script as None. As a side benefit, PRETORIN_SYSTEM_ID / PRETORIN_FRAMEWORK_ID env-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-answer and policy-q-answer recipe scripts imported redact_secrets from pretorin.evidence.redact, but the module only exports redact and RedactionResult (redact_secrets is a kwarg of redact(), not a symbol). Every invocation failed at import time with cannot import name 'redact_secrets', silently breaking the documented contract that the scope-question and policy-question workflows redact answers before submission. Switched both scripts to redact() + unpack the (str, RedactionResult) return shape, matching code-evidence-capture/scripts/redact_secrets.py.

Documentation

  • Customer-managed air-gapped install guide: new docs/src/getting-started/customer-managed-airgap.md walks 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 via PRETORIN_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. New pretorin risk command group: list, show, create, seed, update, refresh-summary, link add/link rm, and library 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 (requires framework_id + matching ControlImplementation rows), mitigation is recorded via update_risk (no separate /mitigate endpoint), and AI summary refresh is best-effort (check ai_summary_generated_at to confirm AI ran).

0.17.5 - 2026-05-06

Fixed

  • pretorin cci impl panel now surfaces the impl row id (the id field in the platform response) so agents can chain directly into evidence link-cci without re-querying. The previous render hid this UUID.
  • Panel header now displays the CCI human label (CCI-000007) by reading the platform’s cci_identifier field, instead of repeating the catalog UUID twice. The earlier code read a non-existent cci_uuid field 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 tool get_cci_implementation wrap the new platform GET /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-cci and pretorin evidence link-stig plus MCP tools link_evidence_to_cci_implementation and link_evidence_to_stig_rule_workflow. Both honor the platform’s override_system_mismatch + override_reason gate 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-control workflow playbook now clarify that the STIG-rule → CCI relationship is catalog-level (DISA-defined, immutable, synced during ingestion) — agents should reach for get_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=false opt-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_agents now performs filesystem assertions inside the Path.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.json revision-lifecycle endpoints. New commands under pretorin frameworks:
    • init-custom <id> — scaffold a minimal valid unified.json template.
    • 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 to unified.json.
    • upload-custom <path> [--publish] — POST a draft custom-framework revision; --publish immediately promotes the draft. Renders the platform’s structured validation_report on 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 _oscal blocks 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 structured validation_report is preserved through PretorianClientError.details on 400.
  • jsonschema>=4.0.0 added as a runtime dependency for local artifact validation.

Documentation

  • New page docs/src/frameworks/custom.md walking 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_task MCP 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_workflows and get_workflow MCP 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 deleted pretorin scan command.
    • scope-q-answer, policy-q-answer — questionnaire-answer redaction recipes for the new questionnaire workflows.
  • Recipe authoring surface: pretorin recipe list / show / new / validate / run CLI commands. Four loader paths with clear precedence: explicit > project > user > built-in. Scaffolder + validator. Per-script MCP tools auto-registered as recipe_<safe_id>__<script>.
  • Recipe execution context: start_recipe / end_recipe open a server-side context; every platform write inside the context auto-stamps producer_kind="recipe", the recipe id, and the recipe version on audit_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 at pretorin.evidence.audit_metadata are 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) attests match before falling through to freelance. The decision is recorded as a RecipeSelection on 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 pretorin skill v0.17.0: teaches the calling agent about engagement → workflow → recipe routing. New “Engagement (Routing)” section flags start_task as the FIRST call, “Workflow Playbooks” enumerates the four playbooks, “Recipes” enumerates the eight built-ins.
  • MCP server instructions field updated: explicit routing guidance — the calling agent must call start_task first 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 scan CLI command removed. All scanner functionality moved to recipes. Existing automation should migrate to pretorin recipe run <recipe-id> (e.g., pretorin recipe run inspec-baseline --param stig_id=RHEL_9_STIG) or invoke via MCP. The platform-side submit_test_results endpoint stays live; only the local CLI surface changed.
  • ScanOrchestrator removed. The manifest fetch + rule filter + result summary helpers were extracted into pretorin.scanners.manifest and shared across the five scanner recipes.

Removed

  • src/pretorin/cli/scan.py (296 lines) — the legacy pretorin scan typer app.
  • src/pretorin/scanners/orchestrator.py (281 lines) — the legacy multi-scanner dispatch loop.
  • The deprecated rejected_invalid_type campaign-apply telemetry counter (deprecated in 0.16.0).

0.16.3 - 2026-04-26

Fixed

  • CCI chain test fix: test_cci_chain_with_system_status now correctly mocks resolve_execution_context so CCI status rendering is exercised. No production code changes.

0.16.2 - 2026-04-21

Fixed

  • pretorin campaign controls --family case-insensitive resolution (#84): --family cc6 (or any casing/whitespace variant) now resolves to the canonical CC6 before hitting the backend’s case-sensitive list_controls(family_id=...). Unknown families raise a structured PretorianClientError whose message lists available families and points at pretorin frameworks families <framework-id>; MCP clients receive framework_id, requested_family_id, and available_families in details for programmatic recovery. Raw user input is preserved on the campaign checkpoint’s request.family_id field. Same resolver applied to the prepare_campaign MCP handler. --family help 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_type is 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 upsert require -t/--type. The error lists all 13 canonical values so users can self-correct.
    • create_evidence MCP tool schema lists evidence_type in required and removes the policy_document default.
    • EvidenceCreate and EvidenceBatchItemCreate pydantic models reject missing and non-canonical evidence_type values via a shared field_validator.
    • LocalEvidence dataclass requires evidence_type. Existing on-disk evidence files missing the frontmatter field will fail to load — add the field manually (canonical values are listed in pretorin.evidence.types.VALID_EVIDENCE_TYPES).
    • upsert_evidence() and build_narrative_todo_block() no longer default evidence_type / suggested_evidence_type to policy_document.

Added

  • Evidence provenance fields: CLI now sends code_file_path, code_line_numbers, code_snippet, code_repository, and code_commit_hash to 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 SourceVerificationPayload schema with proper source_type and source_role mapping. Sent alongside _provenance on 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_evidence MCP 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_role on SourceIdentity: 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_repository and code_commit_hash from the attested snapshot instead of separate subprocess calls.
  • Code provenance on local evidence: pretorin evidence create and push now support code_file_path, code_line_numbers, code_repository, code_commit_hash in markdown frontmatter.
  • pretorin.evidence.types module: canonical 13-type enum, AI-drift alias map (EVIDENCE_TYPE_ALIASES), and normalize_evidence_type(). The normalizer uses a static alias map plus difflib fuzzy matching (stdlib, zero-cost, deterministic, future-proof) before falling back to "other". Common AI near-misses like audit_loglog_file, plural test_resultstest_result, screenshootscreenshot, policy_docpolicy_document now normalize instead of causing HTTP 400s during campaign apply.
  • campaign.apply.control telemetry adds evidence_type_normalized (alias + fuzzy hits) and evidence_type_fallback (unknown → "other") counters. The legacy rejected_invalid_type counter is now always 0 (the normalizer no longer rejects) and is deprecated; it will be dropped in 0.17.0. Migrate dashboards to the new counters.
  • evidence_type.normalized structured log records (INFO for alias/fuzzy matches, WARNING for unknown → "other" fallback) so post-ship telemetry can size the drift map.

Changed

  • EvidenceCreate and EvidenceBatchItemCreate models now include 5 optional code provenance fields.
  • Campaign evidence batch construction now extracts code_file_path, code_line_numbers, code_snippet, and relevance_notes from AI recommendations (previously dropped).
  • AI generation prompt schema includes code provenance fields in evidence_recommendations.
  • upsert_evidence() accepts code_context parameter and creates enriched evidence (with provenance) as a new record rather than reusing a match that lacks provenance.
  • evidence upsert CLI command has new --code-file, --code-lines, --code-repo, --code-commit options.

Fixed

  • SOC2 campaign batches that previously failed partially because the AI emitted non-canonical evidence_type strings (report, procedure, contract, audit_log, plural test_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, MCP create_evidence/create_evidence_batch, agent tools, upsert_evidence workflow) can no longer silently tag missing-type evidence as policy_document and pollute the platform’s custom-policies page.

0.15.5 - 2026-04-20

Fixed

  • Campaign --apply runs no longer flood the evidence locker with AI-authored summaries typed as policy_document (issue #77). The pipeline now wires recommended_notes through to the platform as real gap notes, rejects evidence recommendations with missing or invalid evidence_type (turning them into synthesized gap notes), and emits a structured campaign.apply.control telemetry line for post-ship measurement.
  • Partial failures in the per-control notes write now raise PretorianClientError with 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_type is now required on EvidenceBatchItemCreate. The campaign batch write path no longer silently tags missing types as policy_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 empty evidence_recommendations list is a valid result — gaps belong in recommended_notes.
  • _WORKFLOW_GUARDRAILS merged 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 update now checks PyPI before running pip, skipping reinstall when already current
  • pretorin update verifies the installed version after pip runs, detecting silent failures in pipx/uv-managed environments
  • pretorin update no 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 --yes flag for non-interactive workflows
  • MCP tool delete_evidence for programmatic evidence deletion within system scope
  • API client method delete_evidence wired to the public DELETE /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 manifest command for viewing the resolved manifest and evaluating it against detected sources
  • Manifest loading from four layered sources: PRETORIN_SOURCE_MANIFEST env 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_status and missing_required_sources fields)
  • control_id threading through MCP resolve_execution_scope and 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_attestation now evaluates manifest requirements after the existing MISMATCH check
  • resolve_execution_context accepts an optional control_id for family-level manifest enforcement
  • build_write_provenance accepts an optional control_id and includes manifest evaluation in provenance metadata
  • TODOS.md added 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_override escape 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-serve now 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_campaign now reports apply: true after 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.02 to a different control when the exact control does not resolve in the active framework

Added

  • get_cli_status and the status://cli MCP resource expose local CLI version, update availability, and upgrade guidance to MCP hosts and agents

0.13.1 - 2026-04-07

Added

  • get_stig MCP tool for STIG benchmark detail
  • get_cci_chain MCP 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 stig CLI group: list, show, rules, applicable, infer
  • pretorin cci CLI group: list, show, chain
  • pretorin scan CLI 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, and get_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 campaign now 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], with pretorin[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, and patch_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 --quiet for a compact one-line context summary that works well in scripts and shell prompts
  • pretorin context show --check to fail fast when the stored system/framework scope is missing, stale, or cannot be verified

Changed

  • context show now 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 show now 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 --apply and policy populate --json --apply persist 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_artifacts for 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 /notes endpoint returns 405 Method Not Allowed
  • Added compatibility fallback for evidence search on deployments that only expose system-scoped evidence routes
  • Prevented pretorin agent run --no-stream from crashing when model output includes literal [[PRETORIN_TODO]] blocks

Changed

  • MCP and legacy agent evidence search tools now accept optional system_id context 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 cli across 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 get to read current control narratives from the platform
  • pretorin notes list and pretorin notes add for explicit control-note management
  • pretorin evidence search for platform evidence visibility
  • pretorin evidence upsert for 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_notes tool for note read parity

Changed

  • create_evidence MCP behavior now upserts by default (dedupe: true) and returns normalized upsert metadata (evidence_id, created, linked, match_basis)
  • pretorin evidence push now 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, and get_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 --check by formatting src/pretorin/agent/codex_agent.py and src/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 caused MarkupError crash
  • Evidence type mismatch — CLI used documentation but API expects policy_document, screenshot, configuration, etc.
  • Control ID casing — CMMC-style IDs like AC.L1-3.1.1 were incorrectly lowercased by normalize_control_id
  • monitoring push now checks active context before requiring --system flag
  • pretorin login skips API key prompt when already authenticated (validates key against API)
  • Demo script: --json flag position (pretorin --json context show, not pretorin context show --json)
  • Demo script: pause reads from /dev/tty so commands no longer consume stdin meant for prompts

Changed

  • Default evidence type changed from documentation to policy_document across 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/ and evidence/ to .gitignore to prevent accidental credential commits

0.5.0 - 2026-02-27

Added

  • pretorin context list — List available systems and frameworks with compliance progress
  • pretorin context set — Set active system/framework context (interactive or via --system/--framework flags)
  • pretorin context show — Display current active context with live progress stats
  • pretorin context clear — Clear active system/framework context
  • pretorin evidence create — Create local evidence files with YAML frontmatter
  • pretorin evidence list — List local evidence files with optional framework filter
  • pretorin evidence push — Push local evidence to the platform with review flagging
  • pretorin narrative push — Push a narrative file to the platform for a control
  • pretorin monitoring push — Push monitoring events (security scans, config changes, access reviews)
  • pretorin agent run — Run autonomous compliance tasks using the Codex agent runtime
  • pretorin agent run --skill <name> — Run predefined skills (gap-analysis, narrative-generation, evidence-collection, security-review)
  • pretorin agent doctor/install/version/skills — Agent runtime management commands
  • pretorin agent mcp-list/mcp-add/mcp-remove — Manage MCP servers available to the agent
  • pretorin review run — Review local code against framework controls with AI guidance
  • pretorin review status — Check implementation status for a specific control
  • resolve_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_note MCP tool — Add notes with suggestions for manual steps or systems to connect
  • add_control_note added to narrative-generation, evidence-collection, and security-review agent skills
  • ControlContext, ScopeResponse, MonitoringEventCreate, EvidenceCreate client 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 instructions field guides AI agents on beta status and system creation requirements

Changed

  • Default platform API base URL changed to /api/v1/public for public API routing
  • Client methods updated to match new public API path structure
  • list_evidence() and create_evidence() now scoped to system (not organization)
  • update_control_status() changed from PATCH to POST with body

Removed

  • pretorin narrative generate command — use pretorin agent run --skill narrative-generation instead
  • pretorin_generate_narrative MCP 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_id to create_evidence and link_evidence MCP 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

  • --json flag for machine-readable output across all commands (for scripting and AI agents)
  • pretorin frameworks family <framework> <family> command to get control family details
  • pretorin frameworks metadata <framework> command to get control metadata for a framework
  • pretorin frameworks submit-artifact <file> command to submit compliance artifacts
  • Positional FAMILY_ID argument on controls command (pretorin frameworks controls fedramp-low access-control)
  • Full AI Guidance content rendering on control detail view
  • .mcp.json for 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 control command
  • --references/-r flag replaced by --brief/-b to 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 frameworks
    • pretorin frameworks get - Get framework details
    • pretorin frameworks families - List control families
    • pretorin frameworks controls - List controls
    • pretorin frameworks control - Get control details
    • pretorin frameworks documents - Get document requirements
  • Authentication commands
    • pretorin login - Authenticate with API key
    • pretorin logout - Clear stored credentials
    • pretorin whoami - Show authentication status
  • Configuration management
    • pretorin config list - List all configuration
    • pretorin config get - Get a config value
    • pretorin config set - Set a config value
    • pretorin 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