Narrative & Evidence Workflow
This is the core workflow for updating control implementations on the platform. Follow this sequence for any control update.
Workflow Steps
1. Resolve the Target
Identify the system_id, control_id, and framework_id for your update. Set the active context:
pretorin context set --system "My Application" --framework fedramp-moderate
2. Read Current State
Before making changes, understand what’s already there:
# Get full control context (requirements + current implementation)
pretorin control context ac-02 --framework-id fedramp-moderate
# Via MCP: get_control_context
# Get current narrative
pretorin narrative get ac-02 fedramp-moderate
# Search existing evidence — filter-based (exact control + framework match)
pretorin evidence search --control-id ac-02 --framework-id fedramp-moderate
# Search existing evidence — RAG semantic query (finds reusable unattached
# and policy evidence the agent can attach instead of drafting fresh)
pretorin evidence search -q "account management approval workflow"
# Via MCP: search_evidence with a natural-language query
# List existing issues
pretorin issues list ac-02 fedramp-moderate
3. Collect Observable Facts
Search your codebase and connected systems for evidence. Only document what is directly observable — never assume or fabricate implementation details.
Treat existing Pretorin narratives, issues, and status fields as a starting point, not proof that a control gap exists. Before writing a narrative update or issue, inspect the relevant implementation in the workspace and connected systems. If those sources show stronger implementation than the current platform record, update the narrative to reflect the observed implementation and record any remaining evidence gap as an issue.
4. Map Evidence to Declared Expectations
Before composing the narrative, read the active tier from
get_control_context.scale_tier.tier and the expectation keys from
get_control_context.expectation_coverage. Search/reuse evidence first, create
only what is missing, and then classify every artifact considered for the
control:
link_evidence(evidence_id="ev-1", control_id="ac-02", expectation_key="exp-a")
link_evidence(evidence_id="ev-2", control_id="ac-02",
unbound_reason="Useful context, but it supports no declared expectation.")
Narrative citations and expectation mappings are separate. Citations ground
individual prose claims; only link_evidence with an expectation key changes
expectation coverage. unbound_reason is a platform write, not a local note:
it preserves the control link, clears any expectation binding the artifact
currently has, and records the reason in the platform audit chain. Never pass
it for an artifact that is correctly bound.
Call get_control_context again after linking and capture the active tier,
declared keys, covered, uncovered, and unbound_evidence_count. A
single-control Plan contains a required evidence-expectation-mapping step;
complete it with update_plan_step.evidence_mapping, recording bindings by key
and every intentionally unbound artifact/reason. The step cannot be skipped.
5. Draft Updates
Prepare three types of updates:
Narrative — How the control is implemented. Narratives describe observed implementation only; do not include gap lists, missing-information placeholders, or remediation backlog.
Evidence — Specific artifacts demonstrating implementation (config files, code, policies). Evidence describes the artifact and what it supports only. Its body starts directly with factual content and omits section headers or standalone bold labels because the SSP supplies headings.
Issues — Independently supported gaps against in-scope expectations. One expectation gets one Issue; manual follow-up, missing context, and evidence suggestions stay as workflow next actions:
Expectation key: ac-02.mfa-enforcement
Unmet expectation: Administrative accounts enforce MFA.
Observed gap: Administrative accounts do not enforce MFA.
Observation basis: idp/policy-export.json:42 sets admin_mfa_required to false.
Risk basis: Compromised administrator passwords can be used without a second factor.
Clearance condition: MFA is enforced for every administrative account.
Minimum evidence: IdP policy export; successful admin MFA challenge record.
6. Push Updates
# Push a single narrative file
pretorin narrative push-file ac-02 fedramp-moderate "My Application" narrative-ac02.md
# Upsert evidence (finds or creates, then links)
pretorin evidence upsert ac-02 fedramp-moderate \
--name "RBAC Configuration" \
--description "Role mapping in IdP" \
--artifact-content "**Evidence**\n\n- Role mapping is enforced in the IdP export." \
--type configuration
# Cadenced evidence with audit-sufficiency metadata
pretorin evidence upsert ac-02 fedramp-moderate \
--name "Quarterly Access Review" \
--description "Output of quarterly access review query" \
--artifact-content "**Evidence**\n\n- Quarterly access review query output is attached as Markdown." \
--type attestation \
--coverage-start 2026-01-01 --coverage-end 2026-03-31 \
--capture-query "SELECT user_id, last_login FROM users WHERE ..." \
--cadence-days 90
# Add issues
pretorin issues add ac-02 fedramp-moderate \
--content "Gap: Missing MFA evidence..."
# Start/reopen implementation authoring
pretorin control status ac-02 in_progress \
--framework-id fedramp-moderate
CLI and MCP callers may only set in_progress. Stage-for-approval, approval, and not-applicable decisions happen in the Pretorin UI by a human.
MCP narrative writes default to trigger_review=false, and normal agent work
must leave review disabled. Only when the user explicitly asks to review the
final stable narrative may the agent set both trigger_review=true and
review_requested_by_user=true. The tool re-reads coverage and returns a
visible warning when the mapping step is incomplete or expectations/evidence
remain uncovered/unbound. Verify that the returned reviewed generation equals
the target generation. Treat ai_analysis as explanatory read-only output:
never copy a review finding into add_control_issue; the platform reconciler
owns those Issues and exposes them through the issue reads. Create agent Issues
only from independently observed workspace/source gaps. This boundary prevents
stale or superseded analysis from creating duplicates. Source or recipe
availability gaps are preflight warnings, not control issues.
The final handoff must include the active tier, covered and uncovered
expectation keys, evidence ids bound to each key, intentionally unbound
artifacts/reasons, unbound_evidence_count, and whether review was not
requested, completed for the exact generation, or explicitly overridden with a
coverage warning.
Read-Only Draft Workflow
When you want AI drafts before any platform writes:
- Resolve scope (system, control, framework)
- Read current state (context, narrative, evidence, issues)
- Generate drafts via
pretorin agent run --skill narrative-generationor the MCPgenerate_control_artifactstool - Review the draft — clearly separate candidate narrative, evidence recommendations, and issue drafts
- Only push to the platform after explicit approval
Markdown Quality Rules
All narratives and evidence must pass markdown quality validation:
Narratives
- No section headers, including Markdown headings or standalone bold labels
- At least 1 structural element (code block, table, or list)
- No markdown images
Human-authored CLI narratives may use any valid structural element.
Agent-authored control narratives use a stronger, bounded profile: target
150–300 words, require at least 800 characters, never exceed 400 words, open with a short
implementation overview, include an
Expectation | Implemented behavior | Evidence table, and add concise
supported operating detail. A few bullets alone are rejected. Built-in
generation receives one focused repair attempt before failing explicitly.
Evidence
- No section headers, including Markdown, HTML, setext, or standalone bold labels
- At least 1 rich markdown element
- No markdown images
Continuous Compliance & Cadenced Evidence
Evidence created with --cadence-days carries a refresh cadence; the platform stores expires_at = created_at + cadence_days and emits evidence.expiring / evidence.expired monitoring events as the deadline approaches and passes.
To re-affirm that cadenced evidence is still current, prefer validate so the CLI compares the fresh source-material hash before marking current:
pretorin evidence validate <evidence_id>
# If unchanged, records re_verified; if changed, replaces the Markdown artifact
# with a drift note instead of silently marking stale evidence current.
This fails with HTTP 400 if the evidence has no cadence set. The --coverage-start / --coverage-end flags describe the period the evidence content covers (point-in-time if --coverage-end is omitted). The --capture-query flag records the query, filter, or command that produced the artifact — auditors use this for IPE (Information Produced by the Entity) reproducibility.
Linking Evidence to CCI Implementations
To attach evidence to a per-system CCI implementation row (rather than the control as a whole), use link-cci:
pretorin evidence link-cci <evidence_id> <cci_implementation_uuid>
The CCI implementation UUID comes from pretorin cci impl <cci_uuid>; the row must already exist on the platform. Add --override-system-mismatch --override-reason "<why>" to permit cross-system attachment.
Linking Evidence to Assessment Objectives
For CMMC and other objective-bearing catalogs, inspect the full objective and expectation posture before linking at leaf grain:
pretorin objective list --framework-id cmmc-l2 --control AC.L2-3.1.1 --open-only
pretorin objective show <objective_implementation_uuid>
pretorin objective link-evidence <objective_implementation_uuid> <evidence_id>
An objective evidence link does not itself prove a bound evidence expectation.
Reread objective show or control context and confirm that each expectation’s
explicit coverage—not its suggestions or the objective evidence count—matches
the intended posture. See Assessment Objectives.
Evidence Deduplication
pretorin evidence upsert and the MCP create_evidence tool use find-or-create logic by default (dedupe: true):
- Search for an exact match on (name + description + type + control + framework) within the active system scope
- If found, reuse the existing evidence item
- If not found, create a new one
- Ensure the evidence is linked to the specified control
The response indicates whether the evidence was created (new) or reused, along with the match_basis.