Output Schema
September 15, 2026 · View on GitHub
ripr emits stable JSON for tools, CI systems, editor integrations, and coding
agents.
Output streams by command family
The CLI has two intentional output conventions:
- The check-family commands (
check,diff,explain, andcontext) write their primary result to stdout.check,diff, andcontextcan emit machine-readable JSON;explainemits its human explanation. Warnings and diagnostics go to stderr, so scripts can capture stdout without filtering status text. - The gate-family commands write reviewed artifacts to the paths shown by their
help text and print human
Wrote ...status lines to stdout.gate evaluate,baseline diff, andzero statussupport their documented JSON/Markdown output paths;baseline createandbaseline updatesupport--outfor the JSON ledger, whilebaseline diffis the baseline subcommand that also supports--out-md.baseline create --dry-runis the explicit exception: it prints the candidate JSON to stdout without writing a file.
This split is deliberate: check-family output is a direct analysis result,
while gate-family output is a reviewed, file-backed policy/report artifact.
The gate evaluator can still return a non-zero status after writing its
artifacts when the decision is blocked or config_error; callers should
inspect both the exit status and the written JSON.
The ripr check --format json schema version is:
0.2
schema_version is a per-contract namespace, not a single product-wide number
(#2075): each output family versions independently. The command-to-version
map is:
| Output | Field | Current value |
|---|---|---|
ripr check --format json | schema_version | 0.2 |
ripr check --format sarif | version | 2.1.0 (standard SARIF envelope) |
ripr gate evaluate | schema_version | 0.1 |
ripr doctor --json | schema_version | 0.2 |
ripr agent packet | schema_version | 0.4 |
ripr agent receipt | schema_version | 0.5 |
ripr agent verify | schema_version | 0.3 |
ripr agent status | schema_version | 0.1 |
ripr agent review-summary | schema_version | 0.1 |
ripr receipt write/check | schema_version | 0.1 |
| badge JSON | schema_version | 0.8 |
ripr cache status --json | schema_version | 0.1 |
ripr swarm queue --json | schema_version | 0.2 |
Bump rules below apply per contract: a breaking change to one family bumps that family's version only.
JSON object key ordering
JSON object key order is not part of the semantic contract for ordinary
schema-bearing ripr output. The examples below use a stable, readable order,
but consumers must parse JSON objects by key rather than match raw strings,
prefixes, or byte offsets. This keeps declaration-order and map-backed
renderers interoperable.
This guidance does not relax byte-canonical artifact contracts. Inputs to
ripr agent verify and artifacts carrying a content_sha256 commitment are
validated as exact canonical bytes; consumers must preserve those bytes rather
than parse and re-render them before verification.
Individual renderers may emit object keys in different deterministic orders, including declaration order or map order. The exact order is an implementation detail, not a schema distinction, and this document deliberately does not specify which order a renderer must choose. The repository may retain byte-oriented golden snapshots as renderer regression tests, but those snapshots do not authorize downstream consumers to depend on their key order. Changing a renderer's ordering would be a separate output migration and is not implied by any schema version.
Schema changes that remove fields, rename fields, or change field meanings
should bump schema_version.
Repository config in ripr.toml does not add a new field to the check
schema. It can change the rendered mode and configured severity values,
because those fields already describe the effective analysis mode and reporting
policy for the current run. See Configuration.
SARIF output is governed by
RIPR-SPEC-0008. SARIF uses the
standard SARIF version: "2.1.0" envelope rather than schema_version: "0.1".
Adding SARIF or GitHub annotation detail must not remove or rename existing
JSON, badge, LSP, or context fields. Preview-card surface_scope values record
which public advisory surfaces are currently wired.
ripr check --format github emits GitHub Actions workflow-command text rather
than JSON. For Python preview findings, that message may append either an
eligible repair-card summary or a no-action/static-limit summary. For Perl
preview findings with strict fact-packet evidence, it may append a compact
perl_preview_card.v1 advisory summary with missing discriminator, suggested
assertion, suggested location, and verify command. GitHub annotation text does
not expose receipt commands, edit-boundary authority, or agent packets, and
remains advisory review context rather than verify, receipt, gate, badge, or
RIPR Zero authority.
ripr check --format human is the bounded default terminal surface. It prints
header and summary counts, then one Start here: triage block with a closed
state (top_gap, no_actionable_gap, preview_limited, static_limited, or
missing_scope), one selected finding digest when available, an omitted-finding
count, and pointers to --format human-full and --format json.
ripr check --format human-full (alias text-full) preserves the exhaustive
per-finding human report. These human text formats do not change
schema_version; the machine-readable contract remains --format json.
Repo-scoped formats such as repo-exposure-json, repo-exposure-md,
repo-sarif, and agent-seam-packets-json warn on stderr when paired with
--base or --diff, because those flags do not bound full-repo formats.
Check Output
ripr check --json emits:
The normative top-level contract is
schemas/ripr/check.schema.json. It pins
schema_version (0.2), tool, mode, root, summary, and findings.
The optional analysis_outcome block preserves producer-owned completeness;
the optional finding_alignment block is the typed canonical seam projection.
Unknown top-level fields are rejected by the verification contract. Nested
finding and seam details may grow additively within the pinned version.
{
"schema_version": "0.2",
"tool": "ripr",
"mode": "draft",
"root": ".",
"base": "origin/main",
"summary": {
"changed_rust_files": 1,
"probes": 1,
"findings": 1,
"exposed": 0,
"weakly_exposed": 1,
"reachable_unrevealed": 0,
"no_static_path": 0,
"infection_unknown": 0,
"propagation_unknown": 0,
"static_unknown": 0
},
"analysis_outcome": {
"analysis_complete": true,
"outcome": {
"schema_version": "0.1",
"kind": "complete_with_findings",
"identity": {
"base_revision": "origin/main",
"input_identity": "sha256:<diff-bytes>"
},
"counts": {
"changed_file_count": 1,
"changed_line_count": 2,
"candidate_line_count": 2,
"probe_count": 1,
"finding_count": 1
},
"limitations": [],
"claim_boundary": "Static analysis outcome only; no correctness, test-adequacy, runtime-execution, or merge-readiness claim."
}
},
"findings": []
}
analysis_outcome is emitted for diff and worktree analysis. Its
analysis_complete member is derived from outcome.kind; consumers must use
the typed outcome and its limitations[] rather than infer completeness from
findings or probes. For unsupported_input and
partial_with_limitations, zero findings is explicitly not a clean result.
When supported raw findings align to a canonical evidence item, ripr check --json also emits an additive finding_alignment section. The section is
omitted when no supported alignment item is present, so existing consumers can
continue to read findings directly. Raw findings remain unchanged and are
repeated only as supporting evidence for the canonical item.
When Rust diff-scoped analysis stops at a configured budget before probe
expansion, ripr check --json still exits non-zero, but it writes a limited
check artifact to stdout before reporting the error on stderr. This artifact
preserves the normal check envelope (schema_version, tool, mode, root,
summary, and findings) and adds:
analysis_scope.run_status: "diff_scope_oversized"analysis_scope.basis: "rust_diff_scope_budget"analysis_scope.downstream_consumable: falseanalysis_scope.limitation: "diff_scope_oversized"analysis_scope.repair_route: "analysis/diff-scope-budget"run_limitations[]with the same category, run status, repair route, and the budget diagnostic message
Consumers must not treat a limited diff_scope_oversized artifact as a clean
or complete analysis. The zero summary and empty findings array mean analysis
did not run far enough to classify probes, not that the diff has no findings.
{
"finding_alignment": {
"scope": "supported_classes",
"supported_evidence_classes": ["presentation_text", "config_or_policy_constant"],
"summary": {
"raw_signals": 2,
"canonical_items": 1,
"aligned_raw_findings": 2,
"unaligned_raw_findings": 0,
"raw_to_canonical_ratio": 2.0,
"duplicate_groups_total": 1,
"actionable_gaps": 0,
"already_observed": 0,
"internal_no_action": 0,
"static_limitations": 1,
"unknown": 0,
"calibrated_supported": 0,
"uncalibrated": 1,
"repair_route_coverage": 0,
"actionable_items_without_repair_route": 0,
"verify_command_coverage": 0,
"actionable_items_without_verify_command": 0,
"presentation_text_total": 1,
"presentation_text_user_visible": 0,
"presentation_text_observed": 0,
"presentation_text_unobserved": 0,
"presentation_text_internal_only": 0,
"presentation_text_visibility_unknown": 1,
"presentation_text_observer_unknown": 1,
"presentation_text_duplicate_groups": 1,
"presentation_text_actionable_snapshot": 0,
"presentation_text_actionable_output_repairs": 0,
"presentation_text_no_action": 0,
"presentation_text_static_limitations": 1,
"config_policy_constant_total": 0,
"config_policy_user_visible": 0,
"config_policy_observed": 0,
"config_policy_unobserved": 0,
"config_policy_internal_only": 0,
"config_policy_flow_unknown": 0,
"config_policy_observer_unknown": 0,
"config_policy_duplicate_groups": 0,
"config_policy_actionable_output_observer": 0,
"config_policy_actionable_behavior_discriminator": 0,
"config_policy_no_action": 0,
"config_policy_static_limitations": 0,
"config_policy_repair_route_coverage": 0,
"config_policy_verify_command_coverage": 0
},
"items": [
{
"canonical_gap_id": "presentation_text::APPLE_M3_AIR_DEVICE_LABELS_TEXT",
"canonical_item_kind": "limitation",
"evidence_class": "presentation_text",
"gap_state": "static_limitation",
"actionability": "inspect_visibility",
"raw_group_size": 2,
"group_reason": "declaration_and_literal_same_text_constant",
"primary_anchor": {
"file": "src/device_labels.rs",
"line": 46,
"kind": "exposed",
"source_id": "probe:src_device_labels_rs:46:decl",
"reason": "declaration_line_for_grouped_constant"
},
"raw_spans": [
{
"file": "src/device_labels.rs",
"start_line": 46,
"end_line": 46,
"kind": "exposed",
"source_id": "probe:src_device_labels_rs:46:decl"
},
{
"file": "src/device_labels.rs",
"start_line": 47,
"end_line": 47,
"kind": "static_unknown",
"source_id": "probe:src_device_labels_rs:47:literal"
}
],
"why": "Changed presentation text could not be traced to or away from a user-visible output sink.",
"recommended_repair": "Trace the string constant to a rendered output path or confirm it is internal-only.",
"repair_route": null,
"related_test": null,
"verify_command": "cargo xtask evidence-quality-scorecard",
"static_limitations": [
{
"category": "presentation_text_visibility_unknown",
"repair_route": "trace_string_constant_to_output_or_snapshot_test",
"user_actionability": "unknown_until_visibility_known"
}
],
"confidence": {
"basis": "fixture_backed",
"notes": [
"Visibility-unknown presentation text is benchmark-pinned; no user test debt is claimed without an output sink."
]
},
"raw_findings": [
{
"file": "src/device_labels.rs",
"line": 46,
"kind": "exposed",
"expression": "pub const APPLE_M3_AIR_DEVICE_LABELS_TEXT: &str =",
"probe_kind": "field_construction",
"source_id": "probe:src_device_labels_rs:46:decl",
"evidence_record_ref": "probe:src_device_labels_rs:46:decl"
},
{
"file": "src/device_labels.rs",
"line": 47,
"kind": "static_unknown",
"expression": "\"apple-m3-air-cpu-neon = M3 MacBook Air Apple CPU/NEON lane\";",
"probe_kind": "static_unknown",
"source_id": "probe:src_device_labels_rs:47:literal",
"evidence_record_ref": "probe:src_device_labels_rs:47:literal"
}
],
"presentation_text": {
"constant_name": "APPLE_M3_AIR_DEVICE_LABELS_TEXT",
"text_literal": "apple-m3-air-cpu-neon = M3 MacBook Air Apple CPU/NEON lane",
"visibility": "unknown",
"observer": "unknown",
"actionability": "static_limitation_visibility_unknown",
"source_kind": "const_decl",
"canonical_group_reason": "declaration_and_literal_same_text_constant",
"recommended_observer": "unknown",
"repair_kind": "inspect_visibility",
"target_test_type": "unknown",
"suggested_assertion": "Trace the constant to a supported output sink before adding or updating tests."
},
"config_policy": null
}
]
}
}
Field contract:
finding_alignment.scope- currentlysupported_classes; Lane 1 reports only evidence classes whose grouping behavior is fixture-backed.finding_alignment.supported_evidence_classes- evidence classes included in this projection. The current fixture-backed classes arepresentation_textandconfig_or_policy_constant.finding_alignment.summary.raw_signals- total raw findings emitted in the check output.finding_alignment.summary.canonical_items- supported canonical evidence items after alignment.finding_alignment.summary.aligned_raw_findingsandunaligned_raw_findings- how many raw findings were attached to supported canonical items versus left as ordinary raw findings.finding_alignment.summary.raw_to_canonical_ratio- raw signal count divided by supported canonical item count; this is diagnostic evidence, not a score.finding_alignment.summary.duplicate_groups_total- canonical items with more than one supporting raw finding.finding_alignment.summary.actionable_gaps,already_observed,internal_no_action,static_limitations, andunknown- Lane 1 evidence states. Policy states such as baseline, waiver, acknowledgement, suppression, or reintroduction remain outside this section.finding_alignment.summary.calibrated_supportedanduncalibrated- confidence-basis counts for canonical items. Current presentation-text items are fixture-backed static evidence unless a later checked runtime calibration class supplies calibrated support.finding_alignment.summary.repair_route_coverage- count of actionable canonical items that carry a concrete top-levelrepair_routewithrepair_kind,target_test_type, andsuggested_assertion.finding_alignment.summary.actionable_items_without_repair_route- count of actionable canonical items that are missing a concrete top-level repair route. Supported fixture-backed classes should keep this at zero; no-action and static-limitation items are not counted as missing user repair routes.finding_alignment.summary.verify_command_coverage- count of actionable canonical items that carry a concreteverify_command.finding_alignment.summary.actionable_items_without_verify_command- count of actionable canonical items missing a concrete verification route. Supported fixture-backed classes should keep this at zero; no-action and static-limitation items are not counted as missing user verification commands.finding_alignment.summary.presentation_text_*- presentation-text class counts for visibility, observer status, duplicate grouping, no-action states, static limitations, and output-observer repairs.finding_alignment.summary.config_policy_*- config/policy constant class counts for visibility, observer or discriminator status, duplicate grouping, no-action states, static limitations, output-observer repairs, behavior-discriminator repairs, repair-route coverage, and verify-command coverage. Config/policy repair-route coverage uses the same normalized top-level structuredrepair_routecontract as the overall summary; proserecommended_repairor class-local repair metadata alone does not count. Config/policy verify-command coverage uses the same concrete-command rule as the overall summary; empty,unknown, orverify_command_unknownvalues do not count as covered.finding_alignment.items[]- canonical evidence items. Downstream surfaces should prefer these items as the user-facing unit and show raw findings as supporting evidence.finding_alignment.items[].canonical_gap_id- stable class-scoped grouping key. For presentation text constants this is currentlypresentation_text::<CONSTANT_NAME>, so line movement does not change the identity.finding_alignment.items[].gap_state- one ofactionable,already_observed,internal_only,static_limitation, orunknown.finding_alignment.items[].actionability- class-scoped action label such asinspect_visibility,add_output_observer,already_observed, orno_action. Presentation text does not produce user repair work from text alone.finding_alignment.items[].primary_anchor- nullable preferred placement hint for downstream surfaces that need one inline location. Supported declaration-backed items point at the declaration or owner line and include the source ID plus a placement reason.finding_alignment.items[].raw_spans[]- source-span summary for every raw finding attached to the canonical item. These spans preserve line-local evidence for expansion/detail views; they do not become separate user actions.finding_alignment.items[].repair_route- nullable normalized repair route copied from class-specific evidence. It is required forgap_state = "actionable"in supported classes and isnullfor already-observed, internal-only, and static-limitation items.finding_alignment.items[].static_limitations[]- analyzer limitation categories and repair routes.presentation_text_visibility_unknownmeans RIPR could not safely trace the text to or away from a user-visible output sink.finding_alignment.items[].presentation_text- class-specific visibility, observer, actionability, source-kind, grouping reason, recommended observer, repair kind, target test type, and suggested assertion context. Implemented fixture-backed states include visibility unknown, user-visible unobserved help/report text, user-visible observed report text, and internal-only labels.finding_alignment.items[].config_policy- class-specific constant role, source-kind, visibility, observer/discriminator, actionability, repair kind, target test type, and suggested assertion context. Implemented fixture-backed states include internal-only policy metadata, visible unobserved report/config labels, observed schema labels, cross-file flow unknown limitations, and opaque lookup limitations.
Check Artifact
ripr check --write-artifact <path> writes a full-fidelity check artifact
(RIPR-SPEC-0140) for later ripr explain --from <path> /
ripr context --from <path> reuse. This is a separate envelope from
check --json: the findings JSON above is a one-way, lossy render
projection and is not a reuse source. The artifact is a local, disposable
derivative of one check run — it must never feed a support-tier row, gate,
badge, or proof route, and it is not portable between machines.
Envelope (schema_version = "ripr-check-artifact-v1"):
{
"schema_version": "ripr-check-artifact-v1",
"tool": "ripr",
"analyzer_version": "0.10.0",
"identity": {
"diff_source": { "diff_file": { "path": "/abs/path/to/example.diff" } },
"diff_bytes_hash": "fnv1a64:0123456789abcdef",
"root": "/abs/path/to/workspace",
"mode": "draft",
"enabled_languages": ["rust"],
"analysis_options": {
"include_unchanged_tests": true,
"perl_facts_path": null,
"perl_facts_content_hash": null
},
"config_identity_version": 1,
"config_identity_hash": "fnv1a64:fedcba9876543210"
},
"findings": [ /* complete Finding set, full fidelity */ ]
}
diff_sourceis{"diff_file": {"path": ...}}(a canonicalized--diffpath),{"base_head": {"base": ..., "head": "HEAD"}}, or{"worktree": {"base": ...}}(a--worktreerun;baseisnullwhen the producing run used dynamic default-base resolution). At reuse time the recorded source is re-resolved: a recorded--diffpath is re-read, a recorded base/head pair or worktree diff is re-resolved through git, and the bytes are re-hashed againstdiff_bytes_hash. A dirty or advanced worktree between write and reuse fails closed ondiff_bytes_hash.findingsserializes the completeFindingset with serde: uncappedrelated_tests(no 8-entry render cap), always-present probeowner, and no render-time severity projection.- The identity gate is fail-closed: any mismatch on
diff_bytes_hash,root,mode,enabled_languages,analysis_options.*,config_identity_version,config_identity_hash, oranalyzer_versionis a typed error naming every mismatched field. Scope flags passed alongside--from(--diff,--base) are assertions verified against the recording, never overrides. There is no silent recompute fallback. config_identity_hashcovers a closed, versioned allowlist of finding-affectingripr.tomlfields (oracles.*,typescript.resolve_tsconfig_paths,perl.*), canonically serialized with defaults materialized. Render-only knobs (severity display,reports.max_related_tests) are excluded and honored fresh at render time. Adding a finding-affecting config field requires extending the allowlist and bumpingconfig_identity_versionin the same PR.- Writes are atomic: uniquely named temp file in the destination directory, flush + fsync, rename; temp files are unlinked on failure; last writer wins on a repeated write to the same path.
Finding
The id field is content-addressed: probe:<sanitized_path>:<family>:<fp8>[.<n>] where <fp8> is the first 8 hex chars of SHA-256 over path\0family\0owner\0expression\0. This means a suppression tracks the code, not the line — the same expression moved to a new line keeps its id (suppression follows it), while changed code at a spot gets a new id (stale suppression invalidates). The line field in the probe object still gives locality for display.
A finding contains:
{
"id": "probe:src_lib.rs:predicate:bbaa2c25",
"classification": "weakly_exposed",
"severity": "warning",
"confidence": 0.92,
"probe": {
"id": "probe:src_lib.rs:predicate:bbaa2c25",
"family": "predicate",
"delta": "control",
"file": "src/lib.rs",
"line": 88,
"expression": "if amount >= discount_threshold {"
},
"ripr": {
"reach": {
"state": "yes",
"confidence": "medium",
"summary": "Related tests appear to reach price: premium_customer_gets_discount"
},
"infect": {
"state": "weak",
"confidence": "medium",
"summary": "Tests have literals, but no detected value matches changed boundary"
},
"propagate": {
"state": "yes",
"confidence": "medium",
"summary": "Changed behavior can propagate through a return boundary"
},
"observe": {
"state": "yes",
"confidence": "medium",
"summary": "A related test observes a value near the changed behavior"
},
"discriminate": {
"state": "weak",
"confidence": "high",
"summary": "Only weak or smoke oracle found"
}
},
"evidence_path": [
"reach yes: Related tests appear to reach price: premium_customer_gets_discount",
"propagation yes: Changed behavior appears to influence returned value: amount - discount",
"related test tests/pricing.rs:12 premium_customer_gets_discount uses strong exact value oracle: assert_eq!(total, 90)",
"observed function argument value amount = 100 at line 12",
"missing discriminator amount == discount_threshold: No related test call uses the boundary value"
],
"flow_sinks": [
{
"kind": "return_value",
"text": "amount - discount",
"line": 89
}
],
"evidence": [],
"missing": [],
"assertion_texts": {
"12": "assert_eq!(discounted_total(50, 100), 50);"
},
"activation": {
"observed_values": [
{
"line": 12,
"value": "amount = 50",
"context": "function_argument"
}
],
"missing_discriminators": [
{
"value": "amount == discount_threshold",
"reason": "No related test call uses amount equal to discount_threshold",
"flow_sink": {
"kind": "return_value",
"text": "amount - 10",
"line": 89
}
}
]
},
"observed_values": [
{
"line": 12,
"value": "amount = 50",
"context": "function_argument"
}
],
"missing_discriminators": [
{
"value": "amount == discount_threshold",
"reason": "No related test call uses amount equal to discount_threshold",
"flow_sink": {
"kind": "return_value",
"text": "amount - 10",
"line": 89
}
}
],
"related_tests_total": 1,
"related_tests": [
{
"name": "premium_customer_gets_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_strength": "strong",
"oracle_kind": "exact_value",
"oracle": "assert_eq!(total, 90)",
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
}
],
"stop_reasons": [],
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"recommended_next_step": "Add boundary tests with exact assertions.",
"suggested_next_action": "Add boundary tests with exact assertions.",
"language": "rust"
}
The evidence-first fields are additive in schema 0.2:
-
evidence_pathis an ordered, human-readable summary of reachability, infection, propagation, observation, discrimination, local flow, related test oracles, observed values, and missing discriminator evidence. -
identity.git_candidate_subject(additive, noschema_versionbump, #3278) appears in theanalysis_outcome.outcome.identityobject as a non-null object exactly when the run analyzed an immutable Git candidate (--candidate-tree); the key itself is always present, and ordinary runs leave itnull. It binds directly to the resolved producer state —subject_kind(tree_to_tree),base_treeandcandidate_treeobject IDs, anddiff_identity(SHA-256 of the derived base→candidate unified diff). A consumer compares the emittedcandidate_treewith its supplied OID without parsing prose; ordinary runs leave the fieldnull. -
assertion_texts(added in schema0.2) is a finding-level JSON object mapping line-number strings to assertion source text. Per-value objects inobserved_valuesno longer carry a redundanttextfield; downstream consumers recover the assertion source viafinding.assertion_texts[line.to_string()]. Known limitation: the map is keyed by line number only, so if two assertions in different source files share the same line number within one finding, only one text is retained in this map — differing texts are retained per-value via the optionalprovenancefield described below. This is a low-probability edge case; a future schema could use"file:line"composite keys. -
Per-value objects in
observed_valuescarry an optionalprovenancefield (additive, noschema_versionbump, #3295 follow-up). It carries the fact's retained source text whenever it differs from the shared assertion source for its line — the exact texts the line-keyedassertion_textsmap drops. That includes call-source text for plainfunction_argumentfacts and, for facts computed by the bounded value-transfer evaluator (#3295) or the helper-transfer chain (#3296), the full evaluation chain with bound inputs and chain depth (e.g.assert_eq!(…); | body = "fix" via strip_prefix -> map_or over label = "pre-fix" (chain depth 2)). Facts whose text is the plain assertion source stay deduped and omit the field, soassertion_textsremains the recovery path for them. -
flow_sinks,observed_values, andmissing_discriminatorspromote the nested activation evidence for consumers that want direct finding-level access. -
related_tests_total— number of related tests the analyzer matched for this finding (pre-cap, always the true count). Therelated_testsarray is capped atMAX_RELATED_TESTS_PER_FINDING_JSON(currently 8) to bound artifact size on real repos where a high-traffic owner can fan out to hundreds of related tests. This is an additive field (noschema_versionbump). The cap never affects classification, finding count, or theoracle_kind/oracle_strengthsummary — those use the full pre-cap vector. Mirrors therelated_tests_total+ cap pattern already inseams[].related_tests_totalfor therepo-exposure.jsonformat. -
related_tests[].relation_reason— (optional, additive, noschema_versionbump) the highest-priority static signal that caused this test to be included. Values:direct_owner_call,helper_owner_call,assertion_target_affinity,same_test_file,same_module,owner_named_test,import_path_affinity,fixture_owner_affinity,weak_token_substring. Consumers can filter or de-prioritize entries taggedweak_token_substring— these are attached via probe-token name matching and cover ~59–90% of unrelated tests in real repos. Membership is unchanged: all tests that were previously inrelated_testsremain; only the tagging is added. Absent on language adapters (Python, TypeScript) that do not yet compute reason;null/ omitted in that case. -
related_tests[].relation_confidence— (optional, additive) companion confidence level for therelation_reason. Values:high,medium,low,opaque.direct_owner_call→high;assertion_target_affinity,owner_named_test,same_test_file→medium;weak_token_substring,same_module,helper_owner_call→low; other static signals →opaque. -
oracle_kindandoracle_strengthsummarize the strongest related oracle currently visible to the finding. -
suggested_next_actionmirrorsrecommended_next_stepfor action-oriented integrations. -
changed_sink,observed_sink,oracle_alignment, andalignment_reasonare additive optional fields (RIPR-SPEC-0028) that surface the Python classifier's sink-alignment decision — why a strong oracle did or did not creditexposed. They are emitted only onlanguage == "python"findings and are absent on Rust and TypeScript findings; they do not bumpschema_version(still0.2).changed_sinkis the comma-joined significant tokens of the changed line;observed_sinkis the strongest related oracle's assertion text;alignment_reasonis a stable snake_case token. Theoracle_alignmentvalue is a controlled enum (ORACLE_ALIGNMENT_VALUES):direct— a strong oracle observes the changed owner by name.alias— a strong oracle observes an import alias of the owner.changed_sink_token— a strong oracle observes a changed-sink token from the changed line, but not the owner name.orthogonal— a strong oracle exists but observes a different sink than the change (the fail-closedweakly_exposedbranch);alignment_reasonisstrong_oracle_observes_different_sink.unknown— no strong oracle observed the changed sink (or a<module>owner with no usable token).
Example — an
exposedfinding aligned directly, and aweakly_exposedfinding whose strong oracle is orthogonal:{ "class": "exposed", "language": "python", "changed_sink": "amount, threshold", "observed_sink": "assert apply_discount(100, 100) == 90", "oracle_alignment": "direct", "alignment_reason": "strong_oracle_observes_owner_name" } { "class": "weakly_exposed", "language": "python", "changed_sink": "amount, threshold", "observed_sink": "assert run_retry(lambda: 'x') == 'x'", "oracle_alignment": "orthogonal", "alignment_reason": "strong_oracle_observes_different_sink" } -
source_currentnessis an additive per-finding field (#3280, parent #3212) that states which revision owns the finding's actionable source. It is always emitted and does not bumpschema_version(still0.2). The value is a controlled enum (SOURCE_CURRENTNESS_VALUES):candidate_current— the finding's source expression is present in the candidate (head-side) source at the recordedprobe.file/probe.line; the location is a candidate edit target. RIPR-SPEC-0152 routes every actionability surface through this field: badge gaps and unknowns, alignment items, gap records (authority projections only forcandidate_current), start-here triage, the LSP actionable profile, SARIF results, GitHub annotations, and PR severe-gap counts exclude non-current findings while denominators keep everything; TS/JS/Python findings now resolvecandidate_currentfrom their head-side probes and Perl stays the explicit unknown.base_deleted— the expression was removed on the candidate side. The retained evidence is base-side and the finding is not a candidate edit target;probe.linestill records the projected new-side coordinate in this slice, and consumer re-coordination of deleted-side evidence is the #3212 projection slice.moved_or_renamed— the same expression re-appears elsewhere in the candidate file, but the producer cannot prove the exact candidate identity of the source; not a candidate edit target.unresolved_subject— the producing surface does not resolve source currentness (preview-language findings today); the explicit unknown, and the backward-compatibility value when reading artifacts written before the field existed. For Rust diff findings the disposition is resolved from the diff evidence that seeded the probe; repo-mode findings arecandidate_currentby construction (they seed from the current tree). In this slice the field is informational for consumers: gate and actionability policy follow in the #3212 projection slice.
-
repair_placementis an additive optional object for preview-language findings that can statically name a bounded test location and command before full repair-card projection. It currently appears for direct weak Python findings with a concrete missing discriminator and a detected pytest or unittest related test. It carriessuggested_test_file,suggested_test_name, optionalsuggested_test_node_id,verify_command, andverify_command_confidence. -
python_repair_cardis an additive optional object for direct weak Python findings that already have a canonical gap, concrete missing discriminator, related-test evidence, placement, and verify command. It is intentionally Python-scoped so it does not collide with the existing GapRecordrepair_cardpacket contract. The v1 card carriescard_version,source,canonical_gap_id,language,language_status,authority_boundary,repair_action,changed_owner,changed_behavior,current_test_evidence,missing_discriminator,recommended_test_shape,suggested_assertion,suggested_location,verify,receipt,stop_conditions, andlimits.repair_action = "strengthen_existing_test"means the card and derived packet should strengthen the named weak related test instead of adding a redundant new test. In rawripr checkoutput,receipt.commandmay still benullbecause the renderer does not know where the caller will save before/after check snapshots. Raw check cards includereceipt.guidance, and pilot projections carry the same text asreceipt_guidance, so humans and agents can save the check JSON and runfirst-pr --check-outputorreports gap-ledger --check-output; that bridge can synthesize the concrete receipt route from the supplied check-output path. -
preview_actionabilityis an additive optional object for TypeScript and JavaScript preview findings. It projects the preview adapter's fail-closed actionability state as structured data while preserving the originalfindings[].evidencestrings for compatibility. It is not a repair packet and is not gate, badge, baseline, RIPR Zero, or agent-packet authority. Current fields areauthority_boundary("preview_advisory_only"),repair_packet_ready(boolean;falsefor most preview findings; flips totrueonly for TypeScript findings satisfying the RIPR-SPEC-0087 complete contract — see the flip condition below),gap_state,actionability_category,why_not_actionable,repair_route,missing_actionability_fields[],missing_graph_legs[], nullableunlock_condition,evidence_needed_to_promote, andraw_evidence_refs[].repair_packet_readyflip condition (RIPR-SPEC-0087 §PR7): a TypeScript finding flipsrepair_packet_ready: trueiff ALL of the following hold: (a)actionability_category == "incomplete_repair_packet"(G-A); (b)language_status == "preview"andlanguage ∈ {typescript, javascript}; (c)typescript_oracle_expectedis a concrete literal ANDtypescript_dynamic_assertion_unresolvedlimitation is absent (G-C); (d) related test is oracle-eligible (import-aware/owner-call, not heuristic-only) — guaranteed by G-A (G-D); (e) at least one named missing discriminator exists inmissing_discriminators(G-E); (f) noroute_cross_language_oracle_visibility_limitationortypescript_bun_bridge_verdictevidence present (G-F); AND the sharedvalidate_agent_gap_record_packetvalidator returnsOk(()). When flipped:actionability_categorybecomes"complete_repair_packet",gap_statebecomes"actionable",missing_actionability_fieldsbecomes[], andauthority_boundarystays"preview_advisory_only"(TypeScript remains preview). Onlyincomplete_repair_packetis eligible to flip; all other categories stay non-actionable.schema_versionis unchanged. When flipped, the actionability fields are rewritten to read as actionable (RIPR-SPEC-0088 §PR8) so they do not contradict the complete packet:repair_routenames the actual repair action (the suggested assertion shape or missing discriminator) rather than the blocked-case "only after ... available" text;evidence_needed_to_promoteis the empty string (nothing is needed); andwhy_not_actionablecarries the "why actionable" confirmation naming the resolved contract fields. The JSON keys are kept stable for schema compatibility; the human renderer relabels them towhy actionable/repair actionand omits the emptyevidence neededline for the actionable case. Raw evidence refs carry the original raw string plus parsedfile,line,kind,source_id, optionalowner, optional graphleg, and optional sourcesamplewhen present. -
TypeScript preview findings may include additive package-discovery evidence strings inside the existing
findings[].evidence[]array. These strings are produced by theanalysis/language/typescript/package.rsmanifest resolver (RIPR-SPEC-0085 PR 2 — package-root and workspace discovery). They are advisory and do not changerepair_packet_ready,preview_advisory_only, orlanguage_status. New evidence strings are:typescript_package_root: <path>— nearest ancestor directory that contains apackage.json(relative to the repo root). Absent when nopackage.jsonis found.typescript_workspace_root: <path>— nearest ancestor with apnpm-workspace.yamlor apackage.json"workspaces"field; falls back topackage_root. Absent whenpackage_rootis unresolved.typescript_framework_hint: <jest|vitest|bun|mocha|node_test|ava>— test framework detected frompackage.jsondeps/devDeps. Absent when no evidence-backed framework is found.typescript_test_runner: <jest|vitest|bun|mocha|node_test|ava>— dedicated evidence field for the detected test runner name. Always co-emitted withtypescript_framework_hintwhen a framework is detected. Absent when no framework is found (fail-closed). Detected fromdevDependencies,dependencies, andscripts.testvalue (script-name fallback handles composite scripts like"xo && npm run build && ava"). Additive: does not change any existing field. A later item uses this field to infer verify commands for runners not yet handled byverify_command_for_discovery(TS must-use roadmap item 3; RIPR-SPEC-0085).typescript_runner_hint: <bun|pnpm|yarn|npm>— package runner detected from lockfile presence orscripts.test. Absent when no evidence-backed runner is found.typescript_package_confidence: <high|medium|low|none>— how much manifest evidence backed the resolution.high= framework + runner,medium= one of the two,low= package found but neither resolved,none= nopackage.jsonfound at all.typescript_package_limitation: <kind>— named limitation when required evidence is absent. Current kinds:typescript_package_root_unresolved(nopackage.jsonfound; value is never fabricated from the file extension alone),typescript_framework_hint_unresolved,typescript_package_manager_unresolved(framework is known so a verify command IS available via the framework binary, but no lockfile evidence identified the package manager (npm/pnpm/yarn/bun); informational, not blocking; per RIPR-SPEC-0101),typescript_runner_hint_unresolved(no framework AND no lockfile/script runner evidence; no verify command can be derived; strong fail-closed case),typescript_test_runner_unresolved(neither framework nor runner could be resolved to a bounded verify command; emitted whenverify_command_for_discoveryreturnsNone; fail-closed per RIPR-SPEC-0085 §"Fail-closed"). Whentypescript_package_root_unresolvedis present, notypescript_package_rootline is emitted (fail-closed per RIPR-SPEC-0085).typescript_verify_command: <cmd>— evidence-backed verify command for the strongest related test, expressed relative topackage_root. Emitted only when at least one offramework_hintorrunner_hintis resolved. When emitted,typescript_preview_card.verify.commandreflects the same value. Command forms (RIPR-SPEC-0085 PR 3):jest <file>,vitest run <file>,bun test <file>,ava <file>,node --test <file>,npm test -- <file>,pnpm test -- <file>,yarn test <file>.typescript_limitation: <name>— ADDITIVE evidence line (RIPR-SPEC-0085 §PR4, named limitation taxonomy). Emitted only when a REAL detected TypeScript construct triggers the named limitation. No existing field is changed. Current emitted names and their real producers:typescript_mock_only_observer— fired byStaticLimitKind::MockedModule(a related test file usesjest.mock()/vi.mock()).typescript_import_graph_unresolved— fired byStaticLimitKind::MissingImportGraph(the changed line calls an imported symbol whose cross-module implementation is unavailable to the syntax adapter).typescript_snapshot_discriminator_unresolved— fired when an oracle-eligible related test assertion hasOracleKind::Snapshot(toMatchSnapshot/toMatchInlineSnapshot).typescript_custom_matcher_unresolved— fired when an oracle-eligible related test assertion hasOracleKind::UnknownAND a non-empty matcher name that is not in the recognised matcher set (real oxc-parsed AST evidence).typescript_dynamic_assertion_unresolved— fired (RIPR-SPEC-0085 §PR5) when an oracle-eligible related test assertion has a non-literal dynamic matcher argument (a variable, function call, or computed expression). The real producer isoracle.rs::extract_matcher_expected_value, which setshas_dynamic_matcher_arg = truewhen the argument is not a resolvable literal. The limitation explains that the expected discriminator value cannot be statically resolved.typescript_table_case_unresolved— fired when an oracle-eligibletest.each(...)/it.each(...)table case uses a row-derived dynamic matcher argument. The real producer uses table-call test extraction plushas_dynamic_matcher_arg = true; the limitation explains that syntax-only preview evidence cannot bind the row to a concrete expected value.typescript_oracle_helper_gated— fired when an oracle-eligible related test calls an assertion-shaped helper around the changed owner call but no direct supported assertion is extracted. The limitation explains that the adapter cannot inspect the helper body or prove its oracle semantics from the call site.typescript_target_unresolved— fired (RIPR-SPEC-0085 §PR6) when a test in a different package references the owner by call name but is excluded by the package-local ownership filter. The real producer isstatic_limit.rs::named_limitations_for_unresolved_ownership, which confirms the cross-package exclusion by comparing candidates with vs. without the package-local filter. Only emitted whenworkspace_rootisSome(i.e. in production, not in unit tests without a workspace root).
typescript_limitation_sample: <name> at <file>:<line>— additive; thefile:lineof the real AST evidence that triggered the named limitation.typescript_limitation_why: <name> — <why>— additive; human-readable reason why the finding is not actionable for this limitation.typescript_limitation_repair_route: <name> → <route>— additive; pointer to the analyzer backlog slice that would resolve this limitation.
TypeScript Limitation Leaderboard Report
ripr reports ts-limitations --check-output <check.json> writes advisory JSON
and Markdown reports to:
target/ripr/reports/typescript-limitations.json
target/ripr/reports/typescript-limitations.md
The command reads an existing ripr check --json artifact. It does not rerun
analysis, execute TypeScript tests, edit source, generate tests, call providers,
run mutation testing, publish comments, change gates, or contribute badge
authority.
JSON fields:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "typescript_limitation_leaderboard",
"status": "advisory",
"root": ".",
"generated_at": "unix_ms:1720000000000",
"inputs": {
"check_output": "target/ripr/reports/check.json"
},
"summary": {
"findings_total": 4,
"typescript_family_findings_total": 4,
"limitations_total": 12,
"distinct_limitations_total": 6,
"top_limitation_kind": "typescript_package_root_unresolved"
},
"limitations": [
{
"kind": "typescript_package_root_unresolved",
"count": 4,
"sources": ["typescript_package_limitation"],
"samples": [
{
"finding_id": "probe:src_dispatch.ts:typescript_preview:dd0f8848",
"language": "typescript",
"file": "src/dispatch.ts",
"line": 2
}
]
}
],
"warnings": [],
"limits": [
"Advisory TypeScript-family preview limitation counts only.",
"Counts come from explicit check JSON evidence; this report does not rerun analysis.",
"This report does not execute TypeScript tests, edit source, generate tests, call providers, change gates, or contribute badge authority."
]
}
statusisadvisorywhen the supplied check output parsed, even when no TypeScript-family limitation signals were found. It isblockedwhen the artifact is missing, unreadable, malformed, or lacks afindingsarray.limitations[].kindis counted once per finding per kind. Duplicate evidence lines in the same finding do not inflate counts.sources[]names where the limitation signal came from:typescript_limitation,typescript_package_limitation, orstatic_limit_kind. Staticmissing_import_graphandmocked_modulefindings are normalized to the corresponding TypeScript named limitation (typescript_import_graph_unresolvedortypescript_mock_only_observer) so the leaderboard groups equivalent signals together. Other TypeScript-familystatic_limit_kindvalues keep their existing static-limit vocabulary. This normalization is for report grouping only and does not change check JSON. It is not a support-tier, gate, badge, baseline, or RIPR Zero claim. Samples are bounded to three findings per limitation kind and are examples, not exhaustive proof.
TypeScript False-Actionable Audit Report
ripr reports ts-false-actionable --corpus fixtures/typescript-preview-false-actionable-audit/corpus.json writes
advisory JSON and Markdown reports to:
target/ripr/reports/typescript-false-actionable-audit.json
target/ripr/reports/typescript-false-actionable-audit.md
The command reads an existing TypeScript-family preview audit corpus. It does not rerun analysis, execute TypeScript tests, edit source, generate tests, call providers, run mutation testing, publish comments, change gates, contribute badge/baseline/RIPR Zero authority, or promote support tiers.
JSON fields:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "typescript_false_actionable_audit",
"status": "advisory",
"root": ".",
"generated_at": "unix_ms:1720000000000",
"inputs": {
"corpus": "fixtures/typescript-preview-false-actionable-audit/corpus.json"
},
"summary": {
"cases_total": 14,
"must_remain_non_actionable_total": 14,
"repair_packet_ready_true_total": 0,
"actionable_gap_state_total": 0,
"complete_packet_category_total": 0,
"false_actionable_total": 0,
"false_actionable_denominator": 14,
"false_actionable_rate": 0.0,
"preview_boundary_violation_total": 0
},
"disposition_counts": [
{ "value": "candidate_future_support", "count": 7 }
],
"risk_class_counts": [
{ "value": "mock interaction payload gap", "count": 1 }
],
"cases": [
{
"id": "mock_interaction_without_payload_proof",
"language": "typescript",
"risk_class": "mock interaction payload gap",
"evidence_kind": "mock_interaction",
"disposition": "candidate_future_support",
"gap_state": "advisory",
"actionability_category": "incomplete_repair_packet",
"repair_packet_ready": false,
"must_remain_non_actionable": true,
"authority_boundary": "preview_advisory_only",
"false_actionable": false,
"source_fixture": "fixtures/typescript_jest_vitest_assertion_facts",
"source_finding_id": "probe:src_checkout.ts:typescript_preview:mock"
}
],
"warnings": [],
"limits": [
"Advisory TypeScript-family preview audit metric only.",
"The false-actionable rate is computed from explicit audit corpus rows; this report does not rerun analysis or execute TypeScript tests.",
"This report does not edit source, generate tests, call providers, run mutation testing, change gates, contribute badge authority, or promote support tiers."
]
}
statusisadvisorywhen the supplied corpus parsed. It isblockedwhen the artifact is missing, unreadable, malformed, or not the expectedtypescript_preview_false_actionable_audit_corpusshape.summary.false_actionable_totalcounts audit rows markedmust_remain_non_actionablethat also setrepair_packet_ready = true,gap_state = "actionable", oractionability_category = "complete_repair_packet".summary.false_actionable_denominatoris the number ofmust_remain_non_actionablerows, not all TypeScript findings.- The report is an audit over explicit preview rows. It is not evidence that TypeScript support is usable alpha, gate eligible, badge eligible, baseline eligible, RIPR Zero eligible, or runtime adequate.
- Oracle metadata evidence lines (RIPR-SPEC-0085 §PR5). ADDITIVE: do not change
oracle_kind,oracle_strength,static_limit_kind, orrepair_packet_ready. Emitted from the strongest oracle-eligible assertion across all oracle-eligible related test candidates. Only ONE assertion's metadata is emitted per finding.typescript_oracle_observed: <expr>— additive; theexpect(<expr>)argument as source text, extracted from the oxc AST span. The actual value/expression being observed by the assertion.typescript_oracle_expected: <value>— additive; the matcher argument as source text, emitted ONLY when the argument is a concrete resolvable literal (string, number, boolean, null, or a safe all-literal object). NOT emitted for dynamic/non-literal arguments; those triggertypescript_dynamic_assertion_unresolvedinstead.typescript_oracle_confidence: <level>— additive; confidence derived fromoracle_strengthplus whether the expected value is a concrete literal. Values:high(Strong oracle + literal expected),medium(Strong oracle without literal, or Medium oracle),low(Weak or Smoke oracle),unknown(Unknown oracle kind).typescript_oracle_evidence_ref: <file>:<line>— additive;file:lineback to theexpect(...)call in the test file, pointing at the AST call site of the assertion.
typescript_preview_cardis an additive optional object for TypeScript and JavaScript preview findings that already have structuredpreview_actionability. It is an advisory card, not a repair packet. The v1 card carriescard_version,source,language,language_status,authority_boundary,owner, optionalowner_kind,probe_family,changed_behavior, optionalrelated_test,oracle_kind,oracle_strength, optionalbun_cross_language_grip, optionalmissing_discriminator,suggested_assertion_shape,static_limits, nullableverify.command,why_not_actionable,repair_route,repair_packet_ready, andlimits. The optionalbun_cross_language_gripobject carries one coherent configured Bun bridge profile selected from the related evidence (including Blob,copy_to_unshared, and Markdown resizable profiles). It carriesstate,rust_seam.file,rust_seam.owner,rust_seam.boundary,typescript_evidence.test_file,typescript_evidence.verdict,typescript_evidence.bridge_confidence,typescript_evidence.missing_discriminators[],limitation_category,repair_route,missing_graph_legs[], nullableunlock_condition,raw_evidence_refs[],action,suggested_test_file, optionalplacement, nestedproof_mode, nestedadvisory_packet,authority_boundary, andrepair_packet_ready. The nestedadvisory_packetis a preview task-shaping packet, not public repair-packet authority. When one finding has multiple configured Bun bridge profiles, the first profile remains inbun_cross_language_gripfor compatibility and the same object also carriesprofiles[], containing every full grip in deterministic producer order. Human, JSON, SARIF, and GitHub projections must retain every profile; consumers must not treat the first profile as an exhaustive summary. It carriespacket_version = "bun_cross_language_advisory_packet.v1",cross_language_state,rust_file,rust_owner,rust_boundary, nullablets_test_file,missing_discriminators[],suggested_shape,bridge_confidence,missing_graph_legs[], nestedproof_mode,next_action,authority_boundary,repair_packet_ready = false,public_repair_packet = false,must_not_change[],stop_condition, andraw_evidence_refs[]. The nestedproof_modeobject carriesmode,reason,authority_boundary = "preview_advisory_only",runtime_execution = false,mutation_execution = false,miri_execution = false, andproof_claim = false. Current modes areobservable_red_green,mutation_plus_miri,helper_gated,bridge_unknown, andstatic_limitation; these name an advisory proof strategy only and do not report that any runtime, mutation, Miri, or model proof was executed. The current configured Bun Blob route may nametest/js/web/fetch/blob.test.tsas advisory placement when shared/resizable boundary discriminators are missing on a configured bridge. Mention-only, partial external-oracle, bridge-unknown, and unresolved target cases stay atsuggested_test_file=not_applicable, emit noplacement, no verify or receipt command, no allowed edit surface, and no public repair packet until the full public packet fields exist. Configured bridge evidence is a creditedraw_evidence_refs[].leg = "binding_edge"; abridge_unknownlimitation must omit that credited binding raw ref and instead namebinding_or_ffi_edgeinmissing_graph_legs[]. It is not a generated test, source edit, runtime command, Rust-test placement, gate, badge, baseline, or repair packet.repair_packet_readyremainsfalsefor this preview slice, and nullableverify.commandmust not be interpreted as a delegated repair route.typescript_repair_packetis an additive optional object present only whentypescript_preview_card.repair_packet_ready == true(i.e., the full RIPR-SPEC-0087 contract is satisfied). It is an advisory repair-work packet projected via the shared renderer from the GapRecord computed bytypescript_gap_record_for. It carriesschema_version("0.3"),source("typescript_preview_projection"),gap_id,canonical_gap_id,language,language_status("preview"),authority_boundary("preview_advisory_only"), optionalfile, optionalline, optionalowner,verify_command, optionalreceipt_command,allowed_edit_surface[],forbidden_files[],must_not_change[], optionalassertion_shape, optionalrepair_kind, optionaltarget_test, and optionalmissing_discriminator. When absent, the human output contains a namedstatus: not actionablelimitation section instead. This field is RIPR-SPEC-0088 §2.2. It is not a gate, badge, or public repair authority; authority boundary remainspreview_advisory_only.perl_preview_cardis an additive optional object for Perl preview findings that already have strict fact-packet evidence, canonical gap identity, related-test evidence, missing discriminator evidence, verify-command evidence, receipt evidence, stop conditions, must-not-change constraints, and safe repo-relative raw evidence refs. It is a check JSON, human CLI, SARIF, GitHub annotation, and gap-ledger Markdown advisory card, not a public repair packet. Scope caveat (Campaign 31 #1379): the renderer is real production code, but in the current state it projects only from synthetic test findings — no production Perl source can produce a finding that carries this card, because the Perl adapter module is#[cfg(test)] mod perl;, the path router ignores.pm/.pl/.t/.psgi, and the upstreamperl-lsp ripr-factsexporter does not exist yet. Perl's support tier isscaffold, notpreview(see Support Tiers). The card lights up for real Perl source once Campaign 31 lands the production exporter + consumer bridge. The v1 card carriescard_version,source,language,language_status,authority_boundary,surface_scope,public_projection_ready,public_repair_packet,repair_packet_ready,agent_packet_ready,gate_candidate,badge_candidate,ripr_zero_candidate,packet_id,canonical_gap_id,gap_state,changed_owner,evidence_class,repair_route,current_test_evidence,missing_discriminator,target_test_shape,suggested_test_location,suggested_assertion,verify,receipt,confidence,raw_evidence_refs[],stop_if[],must_not_change[], andlimits. For this slice,surface_scope = "check_json_human_sarif_github_gap_ledger_markdown",public_repair_packet = false,repair_packet_ready = false,agent_packet_ready = false,gate_candidate = false,badge_candidate = false, andripr_zero_candidate = false.verify.commandis copied from fact evidence withverify.status = "fact_only_not_delegated".receipt.commandis alwaysnulleven though receipt evidence is required internally, andreceipt.status = "available_not_delegated". Perl preview cards are public check JSON, human CLI, diff-scoped SARIF, GitHub annotation, and gap-ledger Markdown advisory context only. Gap-ledger derivation may emit a PR-local previewGapRecordwithprojection_eligibility.markdown_advisory = trueso the Markdown ledger can show the changed owner, missing discriminator, suggested assertion, suggested test location, and fact-only verify command. That derived record must keepagent_packet,pr_comment,gate_candidate,ripr_zero_count, andripr_plus_countineligible and must not synthesize a receipt command. Perl preview cards do not project allowed edit surfaces, forbidden files, receipt argv, PR, CI, LSP, swarm routing, badge authority, gate authority, or RIPR Zero authority in this slice.ripr reports gap-ledger --check-output <check.json>can derive PR-local Python and TypeScriptGapRecordentries from findings that carrypython_repair_cardortypescript_repair_packet. Those records are advisory preview inputs forripr agent packet --gap-ledger ... --gap-id ... --json; they preserve the canonical preview-language gap ID, source anchor, suggested test location, verify command, stop conditions, and preview authority boundary without rerunning analysis or claiming before/after closure.canonical_gap_idis an additive optional stable identity for a language-qualified behavioral gap when the producer can name one without relying on line numbers alone. Python preview values usegap:python:<path>:<owner>:<behavior_kind>:<probe_kind>:<normalized_discriminator>. Static-limit findings may omit this field until a non-actionable gap-state projection exists.canonical_gap_group_sizeis the number of raw findings in the current report that share the samecanonical_gap_id, or omitted when no canonical gap identity is assigned.canonical_gapis an additive optional object that carries the identity parts used to derivecanonical_gap_id:id,language,file,owner,behavior_kind,probe_kind, andnormalized_discriminator.probe.owneris an additive optional stable owner identifier emitted when a preview-language adapter populated a changed owner. Python preview owners usepython:<path>::<owner>, for examplepython:src/pricing.py::calculate_discount. Module-level Python changes use<module>as the owner segment.languageis the per-finding source language reported by the language adapter that produced it (see RIPR-SPEC-0026). Values arerust,typescript,javascript,python, orperl. Omitted when no adapter populated it. Rust findings always carrylanguage: "rust"; preview adapters set the preview-language value when configured.language_statusis the per-finding adapter status. Values arestableorpreview. Omitted for Rust per RIPR-SPEC-0026; configured preview adapters setpreview.owner_kindis an additive optional per-finding syntactic owner discriminator. It is omitted when no preview adapter populated a bounded owner. Values arefunction,method,class_method,arrow_function,component, ormodule_function.static_limit_kindis an additive optional per-finding static limitation discriminator. It is omitted when no structured static limit is known. Values aredynamic_dispatch,metaprogramming,missing_import_graph,decorator_indirection,mocked_module,opaque_custom_assertion_helper,property_based_test,unresolved_pytest_fixture,unsupported_syntax,cross_language_oracle_visibility_unresolved,rust_transitive_reach_unresolved,rust_integration_public_api_path_unresolved, orrust_macro_reach_unresolved, orrust_macro_wrapped_test_call_unresolved, orrust_macro_wrapped_assertion_unresolved, orrust_value_propagation_unresolved.static_limitationis an additive optional per-finding object emitted only when a finding withstatic_limit_kindalso carries a complete structured limitation detail. Current Rust transitive-reach, integration public-API path, macro-reach, direct test macro-call, macro-wrapped assertion, and value-propagation limitations populate it from the same evidence lines rendered in human output. Fields arekind,last_established_edge,first_unresolved_edge,analyzer_route, andnon_claim. The object is absent for static limits that do not have all four detail fields; consumers should keep usingstatic_limit_kindas the limitation discriminator and treatstatic_limitationas richer detail when present.
preview_languages (top-level additive advisory, RIPR-SPEC-0082)
Added in schema 0.2 as an additive optional top-level array. Emitted whenever
preview-language files (TypeScript, JavaScript, or Python) are present in the
analyzed scope — regardless of whether the preview adapter is enabled in
ripr.toml. Absent for pure-Rust scopes. Does not bump schema_version.
Not-enabled (default) example — the #1111 case where a TypeScript change is run under the default Rust-only config and was therefore not analyzed:
"preview_languages": [
{
"language": "typescript",
"file_count": 1,
"sample_paths": ["src/utils.ts"],
"enabled": false,
"analyzed": false,
"category": "preview_language_advisory",
"why": "preview adapter not enabled; files detected but not analyzed; empty result is not Rust-grade clean; to enable add to ripr.toml: [languages] enabled = [\"rust\", \"typescript\"]"
}
]
Enabled example carries "enabled": true, "analyzed": true, and a
"why": "preview adapter; advisory; may be incomplete; empty result is not Rust-grade clean".
language— stable wire string; one oftypescript,javascript,pythonfile_count— number of files in scope routed to this adapter (real, never fabricated)sample_paths— up to three normalized (forward-slash) file pathsenabled— whether the preview adapter was enabled (ran) for this analysisanalyzed— whether the files were analyzed (mirrorsenabled)category— always"preview_language_advisory"for machine filteringwhy— advisory rationale string (case-specific)
An empty or absent preview_languages array means only stable (Rust) content
was in scope. A non-empty array is an honesty signal: either the listed
preview-language files were not analyzed at all (enabled == false) or were
analyzed under advisory preview support that may be incomplete
(enabled == true). In neither case is an empty result a Rust-grade clean
result.
test_harnesses (top-level additive advisory, #3532)
Added in schema 0.2 as an additive optional top-level array. Emitted only when
the repository registered test harnesses ([analysis.test_harnesses] in
ripr.toml) and the run's analysis carried harness facts. Absent for
repositories without registrations, so their output is byte-identical to the
pre-#3532 shape. Does not bump schema_version.
The LSP editor surface carries the same registered facts on its analysis
snapshot (harness_projections): registration identity, harness kind,
adapter generation, exact marker and target, provenance, established
subjects, and typed limitations.
The editor workspace status discloses a bounded summary of the same
facts: harness_registry.registrations[] with registration id,
harness kind, adapter, target, established subject count, and typed
limitation count per registration. The key is Null when the run
carried no harness facts and is absent from runs of repositories
without registrations. The snapshot carries them only from
complete runs whose diff scope included the registered target; limited
runs (git timeout, oversized diff) disclose the run-status limitation
instead and repopulate on the next full refresh. This is the
registered-facts subset — it never claims the harness subjects were
executed (#3605).
Example — one registered harness = false custom target with one exact trial
subject and one dynamic-name limitation:
"test_harnesses": [
{
"registration_id": "mimic-suite",
"harness_kind": "custom_harness",
"adapter": "libtest_mimic_v1",
"marker": "libtest_mimic",
"target": "tests/price_mimic.rs",
"provenance": "ripr.toml [analysis.test_harnesses]",
"subjects": [
{
"name": "alpha_parses",
"file": "tests/price_mimic.rs",
"start_line": 9,
"end_line": 9,
"selector": "named_unexecuted",
"claim": "named_invocation"
}
],
"limitations": [
{
"code": "dynamic_trial_name",
"file": "tests/price_mimic.rs",
"line": 17,
"detail": "trial name is not a simple string literal; generated names remain unresolved"
}
]
}
]
registration_id— the stable identifier from the registrationharness_kind—custom_harnessorregistered_attributeadapter— adapter generation, e.g.libtest_mimic_v1,exact_attribute_v1marker— the exact source marker the adapter matched (crate or attribute path)target— the exact registered target file (workspace-relative, forward-slashed)provenance— where the authority came from (registration channel)subjects[].name— stable subject identity (trial name or test fn name)subjects[].selector—named_unexecutedwhen a selector route is known; a known route is never a selector that ran — passive analysis never starts Cargo or a harnesssubjects[].claim—named_invocation(the invocation is one source-level subject; generated cases are not enumerated) ornamed_function(the function is one executable test).named_invocationis a syntactic claim bounded by the registered target: a named trial invocation exists in the registered target. It does not claim the harness registers or executes the trial — a constructor in dead construction (an unused helper, anif falsebranch, a collection never passed to the harness's run entry point) still carries the claim. Denominator admission for the subject is decided by the bounded reachability authority (#3636): a construction provably excluded from every resolved run argument keeps this claim but leaves the executable-test denominator and is named by aregistration_unreachablelimitation; a construction the resolver can neither connect nor exclude stays in the denominator under this claim with an aggregateregistration_reachability_unknowndisclosure. There is no per-subject reachability field: the unknown bucket is exactly the case where per-subject attribution is not established.limitations[]— typed shapes the registration saw but could not classify (dynamic_trial_name,dynamic_trial_registration,ambiguous_import,unanchored_trial_path,unresolved_marker_import,duplicate_subject,parse_unavailable). Cargo target metadata conflicts (#3608) usetarget_not_declared(the target matches no Cargo[[test]]target, declared or autodiscovered),harness_flag_conflict(the Cargo target still hasharness = true), andmanifest_unavailable(the owning manifest could not be read or parsed); each records that the registration grants no file-wide evidence role, demotion, or trial subjects and the target keeps its ordinary per-function classification. Reachability limitations (#3636) useregistration_unreachable(one per trial: the construction provably cannot reach the registered run entry point's argument — no supported run entry call exists in the target, or every run argument resolved completely and the trial is not in any of them — so the subject keeps its syntactic claim and fact but its executable-test fact does not join the denominator) andregistration_reachability_unknown(one aggregate disclosure per registration: the bounded resolver could not establish reachability for the named trials, so they remain in the denominator under the syntactic claim and the gap is disclosed here rather than per subject).
An absent test_harnesses array means the repository has no harness
registrations; it is never a claim that custom harnesses do not exist.
scope_disclosures (top-level additive advisory, RIPR-SPEC-0083)
Added as an additive optional top-level array. Emitted only when ripr check
was invoked with no analysis scope (no --diff, --base, or --mode
flag) and the result is empty. Absent when scope was explicitly provided (even
if the analyzed scope produced 0 findings). Does not bump schema_version.
No-scope example — the RIPR-SPEC-0083 case where bare ripr check analyzes
nothing yet prints empty:
"scope_disclosures": [
{
"scope_status": "no_scope_provided",
"category": "no_scope_disclosure",
"why": "no analysis scope provided; ripr check is diff-first; empty result does not mean changed behavior is covered; run ripr check --base origin/main or ripr check --root . --mode fast"
}
]
When scope was explicitly provided (--diff, --base, or --mode),
scope_disclosures is absent. A scope-provided empty result is honest and
requires no disclosure.
scope_status— always"no_scope_provided"for machine filteringcategory— always"no_scope_disclosure"for machine filteringwhy— advisory rationale string guiding the user to the correct invocation
unanalyzed_working_tree (top-level additive boolean, RIPR-SPEC-0112)
Added as an additive optional top-level boolean. Emitted (as true) only when
ALL of the following are true:
ripr check --base <rev>was invoked (i.e.--basewas explicit).--diff <file>was NOT also supplied.- The working tree has at least one uncommitted change to a tracked source
file, as reported by
git status --porcelain.
Absent (not emitted) when false. Does not bump schema_version.
This field closes the false-clean gap where ripr check --base HEAD with an
uncommitted .rs edit returns 0 probes and exit 0 — a result that is honest
for the committed diff but misleading if the user assumes it covers their
working-tree change. When unanalyzed_working_tree: true is present, the
result is NOT a clean pass for the uncommitted changes.
Example:
"unanalyzed_working_tree": true
The field is absent when the worktree is clean, when --diff <file> was used
instead of --base, when --worktree was used to include staged and unstaged
tracked edits in the analyzed diff, or when git status --porcelain cannot be
run (fail-closed: no fabricated disclosure).
suppression_policy and suppressed findings (top-level additive, #1441)
Emitted only when ripr check is invoked with --suppression-policy PATH.
Absent otherwise, so consumers without a policy see byte-identical output.
Does not bump schema_version.
The policy file uses the .ripr/suppressions.toml schema. exposure_gap
entries select findings either by exact finding_id (the existing selector)
or by a path glob over root-relative finding paths (** spans path
segments, * and ? stay within one segment), optionally narrowed by
static_class (which must then be one of the seven classification values).
Expired entries are not applied; expired and unmatched selectors surface as
warnings. A missing or malformed policy fails the run (fail-closed): the run
never silently emits unfiltered counts as if a policy had been applied.
Three surfaces change when the flag is present:
summary.suppressed_by_policy— count of suppressed findings. The per-classsummarybuckets (exposed…static_unknown) count unsuppressed findings only; buckets plussuppressed_by_policyadd back up tosummary.findings, which stays the total rendered count.findings[].suppressed/findings[].suppressed_by— suppressed findings stay fully rendered (visible, not hidden) and carry"suppressed": trueplus the selector (finding_idor path glob) that matched. The first matching entry in policy-file order names the selector.- top-level
suppression_policyobject —path(as supplied),suppressed(count), andwarnings(expired/unmatched selector strings).
Example:
"summary": {"findings": 2, "no_static_path": 1, "suppressed_by_policy": 1},
"findings": [
{"id": "probe:docs_gen_a", "suppressed": true, "suppressed_by": "docs/gen/**", ...},
{"id": "probe:src_lib", ...}
],
"suppression_policy": {
"path": "policy/ripr-suppressions.toml",
"suppressed": 1,
"warnings": []
}
Scope: the flag applies to the findings-based check formats (human,
human-full, json, github). Human output lists suppressed findings as compact
one-liners instead of detailed blocks; GitHub-format output skips
annotations for suppressed findings. SARIF keeps its existing
.ripr/suppressions.toml finding_id suppression channel, and badge/repo
formats keep their own suppression projections — ripr check rejects the
flag for those formats instead of silently ignoring it. Date-expiry
enforcement beyond expires (review-after deadlines, required-active
ledgers) belongs to the gate exception policy (#1442), not check
suppression.
Enums
classification values:
exposedweakly_exposedreachable_unrevealedno_static_pathinfection_unknownpropagation_unknownstatic_unknown
severity values:
infowarningnote
family values:
predicatereturn_valueerror_pathcall_deletionfield_constructionside_effectmatch_armstatic_unknown
delta values:
valuecontroleffectunknown
static_limit_kind values:
-
dynamic_dispatch -
metaprogramming -
missing_import_graph -
decorator_indirection -
mocked_module -
opaque_custom_assertion_helper -
property_based_test -
unresolved_pytest_fixture -
unsupported_syntax -
cross_language_oracle_visibility_unresolved— The changed Rust seam owner is FFI/binding-exposed; whether an external-language (e.g. TypeScript) test oracle discriminates this behavior is not statically known — verify the external oracle rather than adding a Rust test. -
rust_transitive_reach_unresolved— (RIPR-SPEC-0114, additive) A test appears to call public API that may transitively reach the changed Rust owner through a pub->pub(crate) helper chain or similar internal call graph, but ripr cannot fully resolve the path (macros, generics, trait dispatch, or depth>5 stop the walk). Classification staysno_static_path; this is a named limitation, not a coverage claim. -
rust_integration_public_api_path_unresolved-- (RIPR-SPEC-0118, additive) An integration test appears to call crate public API, or a test helper that calls crate public API, along a candidate path toward the changed Rust owner. RIPR cannot fully resolve that integration/public-API path, so classification staysno_static_path; this is a named limitation, not a reach, coverage, or oracle claim. -
rust_macro_reach_unresolved-- (RIPR-SPEC-0117, additive) A test appears to call a Rust entry point whose path toward the changed owner stops at a same-repo macro invocation. ripr does not expand macros, so classification staysno_static_path; this is a named limitation, not a coverage claim. -
rust_macro_wrapped_test_call_unresolved-- (RIPR-SPEC-0119, additive) A Rust test directly invokes a same-repo macro whose definition mentions the changed owner. ripr does not expand macros, so classification staysno_static_path; this is a named limitation, not a reach, coverage, or oracle claim. -
rust_macro_wrapped_assertion_unresolved-- (RIPR-SPEC-0120, additive) A Rust test reaches the changed owner, but its assertion-like custom macro is not classified as an oracle. Classification staysreachable_unrevealed; this is a named limitation, not an oracle, coverage, or repair-packet claim. -
rust_value_propagation_unresolved-- (RIPR-SPEC-0150, additive) A changed Rust value-producing binding reaches a same-owner equality predicate through a boundedmap_orshape that ripr cannot fully resolve. Classification staysstatic_unknown; this is a named limitation, not a propagation, coverage, or repair claim.
Reserved flow_sink values:
return_valueerror_variantstruct_fieldevent_callstate_writepersistencelog_messageconfig_changecall_effectmatch_armunknown
These labels are internal analysis terms in schema 0.1. The side-effect
families are additive refinements of the older generic call_effect sink:
event or outbound calls, state writes, persistence writes, log messages, and
configuration changes are named when syntax-first analysis can identify them,
while call_effect remains the fallback for other observable calls.
state values:
yesweaknounknownopaquenot_applicable
confidence values inside RIPR stages:
highmediumlowunknown
oracle_strength values:
strongmediumweaksmokenoneunknown
oracle_kind values:
exact_valueexact_error_variantguarded_result_matchwhole_object_equalitysnapshotrelational_checkbroad_errorsmoke_onlymock_expectationunknown
value_context values:
function_argumentassertion_argumentbuilder_methodtable_rowenum_variantreturn_valueunknown
stop_reason values:
max_depth_reachedexternal_crate_boundarydynamic_dispatch_unresolvedproc_macro_opaquefixture_opaquefeature_unknownasync_boundary_opaqueno_changed_rust_linemacro_reach_unresolvedinfection_evidence_unknownpropagation_evidence_unknownstatic_probe_unknown
Badge Output
Badge-native JSON is a separate output contract from ripr check --json.
It is consumed by CI artifacts, public Shields endpoint generation, and
badge policy tooling. The Shields projection is always exactly four fields;
the native shape carries the stable metadata consumers need to understand
scope and count basis.
Formats:
ripr check --format badge-json
ripr check --format badge-plus-json
ripr check --format repo-badge-json
ripr check --format repo-badge-plus-json
ripr check --format repo-badge-json --gap-ledger target/ripr/reports/gap-decision-ledger.json
Native schema 0.8:
{
"schema_version": "0.8",
"kind": "ripr",
"scope": "repo",
"basis": "canonical_actionable_gap",
"label": "ripr",
"message": "0 actionable",
"status": "pass",
"color": "brightgreen",
"analysis_complete": null,
"analysis_outcome": null,
"counts": {
"unsuppressed_exposure_gaps": 0,
"unsuppressed_test_efficiency_findings": 0,
"intentional_test_efficiency_findings": 0,
"suppressed_exposure_gaps": 0,
"suppressed_test_efficiency_findings": 0,
"unknowns": 0,
"unknowns_test_efficiency": 0,
"analyzed_findings": 0,
"analyzed_seams": 120,
"analyzed_gap_records": 0,
"analyzed_tests": 0
},
"reason_counts": {
"no_assertion_detected": 0,
"smoke_oracle_only": 0,
"relational_oracle": 0,
"broad_oracle": 0,
"assertion_may_not_match_detected_owner": 0,
"opaque_helper_or_fixture_boundary": 0,
"no_activation_literal_detected": 0,
"expected_value_computed_from_detected_owner_path": 0,
"duplicate_activation_and_oracle_shape": 0
},
"policy": {
"include_unknowns": false,
"fail_on_nonzero": false,
"test_intent_path": ".ripr/test_intent.toml",
"suppressions_path": ".ripr/suppressions.toml"
},
"warnings": [],
"preview_skipped": [],
"public_projection": {
"state": "zero_actionable",
"message": "0 actionable",
"run_status": "full",
"generated_at": "2026-06-20T00:00:00Z",
"actionable_count": 0,
"limited_reason": null,
"stale_age_secs": 0,
"source_report": "target/ripr/reports/repo-ripr-badge.json"
}
}
Field contract:
schema_version— currently"0.8".0.2addedscope;0.3addsbasisandcounts.analyzed_seams;0.4addsbasis = "gap_decision_ledger"andcounts.analyzed_gap_records;0.5addsbasis = "canonical_actionable_gap"for public repair-item projection;0.6addspreview_skipped;0.7adds thepublic_projectionobject (RIPR-SPEC-0066) on repo-scoped public badges;0.8addsanalysis_completeand typedanalysis_outcomeon diff-scoped badges. Repo-scoped badges emit both fields asnullbecause they do not have a diff completeness denominator.kind—"ripr"or"ripr_plus".scope—"diff"for PR/diff artifacts,"repo"for public repo baseline artifacts.basis—"finding_exposure"for legacy Finding/ExposureClass count artifacts,"canonical_actionable_gap"for public repo repair-item badge projection,"seam_native"for internal RepoSeam/SeamGripClass inventory artifacts, or"gap_decision_ledger"when repo badge formats are explicitly rendered from supplied GapRecord projection targets. Diff-scoped badge formats currently usefinding_exposure; repo-scoped public badge formats usecanonical_actionable_gapunless--gap-ledgeris supplied.message— the headline rendered as a string for Shields compatibility. Diff-scoped and internal badges render the bare count (for example"5"). Repo-scoped public badges render the closed RIPR-SPEC-0066 vocabulary ("0 actionable","<n> actionable","limited","stale", or"unknown"), combined with thelabelto read asripr: <n> actionable. It is a count or a named state, never a denominator or coverage fraction.counts.unsuppressed_exposure_gaps— diff scope: unsuppressedweakly_exposed,reachable_unrevealed, andno_static_pathFindings; repo public scope: unresolved actionable canonical repair items; seam-native inventory scope: configured-visible headline-eligible seam classes.counts.unknowns— diff scope: static unknown Finding classes; seam-native inventory scope: configured-visibleopaqueseams. Canonical-actionable public badge projection does not count unknown-only or limitation-only states in the headline.counts.analyzed_findings— number of Findings considered by the finding-exposure basis;0for canonical-actionable and seam-native repo badges.counts.analyzed_seams— number of classified seams considered by the canonical-actionable or seam-native repo basis;0for finding-exposure diff badges.counts.analyzed_gap_records— number of GapRecord entries considered by the gap-decision-ledger basis, or canonical repair groups considered by the canonical-actionable basis;0for finding-exposure and seam-native badges.warnings— advisory suppressions/config warnings that remain visible in native JSON. The Shields projection never includes warnings.preview_skipped— (v0.6) array of preview-language adapter names detected in the diff but not enabled; a non-empty list means the result is not a clean Rust-grade result. Always present as an array (possibly empty).analysis_complete— (v0.8) nullable Boolean derived from the typed diff-scopedanalysis_outcome;falsemeans the badge is not a clean result even when its finding count is zero, whilenullmeans the badge is repo-scoped or otherwise has no diff outcome.analysis_outcome— (v0.8) nullable typedAnalysisOutcomeDTO for diff-scoped badges. It preserves the producer outcome kind, counts, limitations, recovery routes, and semantic input identity. An incomplete outcome downgrades a pass/green diff badge to warning/yellow and names the outcome kind inmessage; an existing failure remains a failure.public_projection— (v0.7) present only on repo-scoped public badges (canonical_actionable_gaporgap_decision_ledgerbasis). The RIPR-SPEC-0066 projection of the badge into one closed public state plus the required sidecar fields. Absent on diff-scoped and internal badges. When present, the nativemessage/status/colorare projected from it. Fields:state— one ofzero_actionable,actionable,limited,stale,unknown. Selected with fail-closed precedence (unknown > stale > limited > count); a degraded input never resolves toward the cleaner-looking state.message— the Shields message for the state (label-agnostic, e.g.0 actionable,limited).run_status— Lane-1 completeness state of the source run (fullor a namedlimited_*value).generated_at— RFC3339 UTC timestamp the badge was generated, ornull.actionable_count— unresolved canonical actionable gap count; present only for the count states (zero_actionable/actionable),nullalongside any degraded state.limited_reason— thelimitation_category(and repair route) for alimitedstate;nullotherwise.stale_age_secs— age of the artifact relative to its source at evaluation time, in seconds;nullwhengenerated_atis unknown.source_report— repo-relative path the badge was projected from, ornull.
Shields projection:
{
"schemaVersion": 1,
"label": "ripr",
"message": "0",
"color": "brightgreen"
}
The Shields projection drops native-only fields including schema_version,
kind, scope, basis, status, counts, reason_counts, policy, and
warnings.
Badge-Basis Audit Report
cargo xtask badge-basis writes an advisory audit report at:
target/ripr/reports/badge-basis.json
target/ripr/reports/badge-basis.md
This report decomposes committed public endpoint values and proves whether the
public badge basis matches RIPR-SPEC-0056. It does not edit badges/*.json.
Required JSON shape:
{
"schema_version": "0.1",
"status": "pass",
"mode": "advisory",
"current_public_endpoints": [
{
"path": "badges/ripr.json",
"label": "ripr",
"message": "179",
"color": "orange"
}
],
"current_repo_badges": [
{
"kind": "ripr",
"scope": "repo",
"basis": "canonical_actionable_gap",
"message": "179",
"counts": {}
}
],
"seam_native": {
"status": "pass",
"source": "ripr check --root . --format repo-exposure-md",
"counts_by_class": {}
},
"test_efficiency": {
"status": "pass",
"source": "target/ripr/reports/test-efficiency.json",
"counts_by_class": {}
},
"canonical_actionable_gap": {
"status": "available",
"source": "repo-badge-artifacts",
"ripr_count": 179,
"ripr_plus_count": 179
},
"supporting_signals": {
"raw_alignment_signals": { "status": "not_in_current_badge_generator" },
"canonical_evidence_items": { "status": "not_in_current_badge_generator" },
"static_limitations": { "status": "available" },
"suppressed_or_intentional_items": { "status": "available_from_badge_counts" },
"no_action_items": { "status": "requires_gap_decision_ledger" }
},
"recommended_public_projection": {
"basis": "canonical_actionable_gap",
"rule": "README/store badges should count unresolved actionable static repair gaps using canonical_actionable_gap; ripr+ adds only items projected into the same repair, verify, and receipt model; seam-native inventory stays supporting/internal."
},
"warnings": [],
"non_claims": []
}
Field contract:
current_public_endpointsmirrors committed Shields endpoint JSON.current_repo_badgesrecords the native badge basis used to derive public counts.canonical_actionable_gaprecords the public repair projection counts: the unresolved actionable static repair gaps used for README/store badge headlines.seam_nativerecords internal inventory status and per-class counts when collected with--include-seam-classes.test_efficiencyrecords class counts but does not move the publicripr+headline unless those items are projected into the repair / verify / receipt model.supporting_signalsnames supporting or excluded evidence rather than silently dropping it.recommended_public_projection.basismust becanonical_actionable_gapfor public repair badges, andrecommended_public_projection.rulemust keep seam-native inventory supporting/internal rather than a public headline counter.
SARIF Output
Campaign 5B SARIF formats:
ripr check --format sarif
ripr check --format repo-sarif
sarif is the diff-scoped Finding SARIF surface. repo-sarif is the
repo-scoped classified seam SARIF surface. Both use SARIF 2.1.0:
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "ripr",
"rules": []
}
},
"results": []
}
]
}
Rule IDs are stable public integration strings.
Finding rule IDs:
ripr.finding.exposedripr.finding.weakly_exposedripr.finding.reachable_unrevealedripr.finding.no_static_pathripr.finding.infection_unknownripr.finding.propagation_unknownripr.finding.static_unknown
Seam rule IDs:
ripr.seam.strongly_grippedripr.seam.weakly_grippedripr.seam.ungrippedripr.seam.reachable_unrevealedripr.seam.activation_unknownripr.seam.propagation_unknownripr.seam.observation_unknownripr.seam.discrimination_unknownripr.seam.opaqueripr.seam.intentionalripr.seam.suppressed
Configured severity maps into SARIF as:
ripr.toml severity | SARIF result behavior |
|---|---|
warning | emit level: "warning" |
info | emit level: "note" |
note | emit level: "note" |
off | omit the result |
SARIF v1 does not emit level: "error". CI blocking is a separate opt-in
policy decision, not a property of the static SARIF renderer.
Diff-scoped SARIF also carries additive run-level properties when the
producer supplies an AnalysisOutcome: run_status is "complete" or
"incomplete", analysis_complete is the derived Boolean, and
analysis_outcome is the typed DTO. These properties keep an empty results
array from being misread as a clean analysis. Repo-scoped seam SARIF retains
its existing limitation properties and does not invent a diff outcome.
Every result carries:
ruleId;level;- a primary physical location when file and line are known;
partialFingerprints.riprFingerprintV1;properties.kind(findingorseam);- stable IDs (
finding_id,probe_id, orseam_id) when available; - class metadata (
classification,probe_family,grip_class, orseam_kind) when available. - diff-scoped preview-language Finding results may also carry additive
properties.language,properties.language_status,properties.owner_kind,properties.static_limit_kind,properties.preview_actionability, andproperties.typescript_preview_card. Thepreview_actionabilityand TypeScript preview-card shapes matchripr check --format jsonand remain advisory preview context, not SARIF policy decisions or repair packets. - Direct weak Python preview Findings with an eligible
python_repair_cardinripr check --format jsonalso carry additiveproperties.python_repair_cardin diff-scoped SARIF. The nested card keeps the same preview/advisory boundary, canonical gap ID, missing discriminator, suggested location, verify command, receipt status/guidance, stop conditions, and limits. This is code-scanning context only; it does not make SARIF a repair executor, receipt authority, or gate. - Python preview Findings that are not repair-card eligible because they are
already observed, have no safe related-test route, are heuristic-only, or hit
a static limit carry additive
properties.python_no_actionin diff-scoped SARIF. The nested object marksrepair_packet_ready = false,repair_card_present = false,no_action_kind, null verify/receipt commands, stop conditions, and thepreview_advisory_onlyauthority boundary. Ordinary no-action states userepairability = "no_action"withnot_applicable_no_actionverify/receipt status. Static limits userepairability = "analyzer_limitation", include the typedstatic_limit_kind, and usenot_applicable_static_limitstatus. This is fail-closed review context only; it must not be treated as an agent packet or closure receipt. - Perl preview cards with strict fact-packet evidence also carry additive
properties.perl_preview_cardin diff-scoped SARIF. The nested card matches theripr check --format jsonshape, keeps receipt commands null and edit boundaries hidden, and remains code-scanning context only. It does not make SARIF a repair executor, receipt authority, gate, badge input, or RIPR Zero authority.
Suppressed exposure-gap Findings remain visible with SARIF suppression metadata
when their configured severity is visible. Results whose configured severity is
off are omitted. See RIPR-SPEC-0008 for the full suppression and baseline
policy contract.
cargo xtask sarif-policy compares current SARIF against an optional baseline
and writes:
target/ripr/reports/sarif-policy.json
target/ripr/reports/sarif-policy.md
The JSON report is repo automation output with schema version "0.1":
{
"schema_version": "0.1",
"tool": "ripr",
"status": "new_results",
"mode": "baseline-check",
"threshold": "warning",
"current": {
"path": "target/ripr/reports/ripr-seams.sarif.json",
"results_total": 12,
"compared_results": 3
},
"baseline": {
"path": ".ripr/sarif-baseline.json",
"missing": false,
"results_total": 10,
"compared_results": 2
},
"new_results_total": 1,
"new_results": [
{
"rule_id": "ripr.seam.weakly_gripped",
"level": "warning",
"fingerprint": "ripr.seam.weakly_gripped|abc123|src/lib.rs|42",
"uri": "src/lib.rs",
"line": 42,
"message": "weakly_gripped seam grip for predicate_boundary"
}
]
}
Policy reports are advisory unless --mode fail-on-new-warning is used.
Context Packet
ripr context --json emits compact test intent for agents:
{
"version": "1.0",
"tool": "ripr",
"probe": {
"id": "probe:src_lib.rs:predicate:bbaa2c25",
"family": "predicate",
"delta": "control",
"file": "src/lib.rs",
"line": 88,
"changed_expression": "if amount >= discount_threshold {"
},
"ripr": {
"reach": "yes",
"infect": "weak",
"propagate": "yes",
"observe": "yes",
"discriminate": "weak"
},
"related_tests": [],
"observed_values": [],
"missing_discriminators": [],
"witness": {
"kind": "static_discriminator_gap",
"probe_family": "predicate",
"changed_expression": "amount >= discount_threshold",
"before": "amount > discount_threshold",
"after": "amount >= discount_threshold",
"expected_sink": "return_value",
"missing_discriminators": [
{
"value": "amount == discount_threshold",
"reason": "the current tests do not distinguish the equality boundary"
}
],
"fix_site": {
"file": "tests/pricing.rs",
"line": 42,
"test_name": "discount_at_threshold",
"current_oracle": "assert!(result.is_some())",
"oracle_kind": "smoke_only",
"oracle_strength": "weak",
"oracle_location": { "file": "tests/pricing.rs", "line": 44 }
},
"suggested_assertion": null,
"explain_command": "ripr explain --root . probe:src_lib.rs:predicate:bbaa2c25",
"confidence": { "value": 0.75, "basis": "static_only" },
"limitations": [
{
"kind": "suggested_assertion_unavailable",
"detail": "No producer-owned symbol-resolved assertion template is available."
}
]
},
"missing": [],
"stop_reasons": [],
"recommended_next_step": "Add below, equal, and above threshold tests."
}
The context packet is intentionally smaller than check output. It is optimized
for coding agents and editor commands. witness is additive and is omitted
when an exposed finding has no unresolved discriminator. It contains only
producer-owned facts: fix_site and oracle_location are absent when the
producer cannot identify them, and suggested_assertion remains null until
the producer supplies a symbol-resolved assertion template. limitations[]
names unavailable evidence; renderers must not infer it from paths, lines,
classes, or prose. source_currentness (RIPR-SPEC-0152) mirrors the finding's
disposition: agent consumers must not treat a base_deleted,
moved_or_renamed, or unresolved_subject packet as a candidate edit
target.
Repo Seam Inventory
ripr check --root . --format repo-seams-json emits the repo seam inventory
introduced by RIPR-SPEC-0005. The artifact lands at
target/ripr/reports/repo-seams.json when generated via
cargo xtask repo-seam-inventory.
{
"schema_version": "0.1",
"scope": "repo",
"seams": [
{
"seam_id": "f3c9e4d21a0b7c88",
"kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"owner": "src/pricing.rs::discounted_total",
"expression": "amount >= discount_threshold",
"required_discriminator": {
"kind": "boundary_value",
"description": "amount >= discount_threshold"
},
"expected_sink": {
"kind": "return_value"
}
}
]
}
Field contract:
schema_version— currently"0.1". Bumping requires updating this section, the renderer (crates/ripr/src/output/repo_seams.rs), and any downstream consumers in lockstep.scope— always"repo"for this artifact. Distinguishes the repo seam inventory from diff-scoped findings.seam_id— 16-char lowercase hex. FNV-1a 64-bit hash offile | owner | kind | byte_offset(null-byte separators). Stable across runs and file walk reorderings.kind— one ofpredicate_boundary,error_variant,return_value,field_construction,side_effect,match_arm,call_presence. The spec also reservesvalidation_branchfor a future detection PR.file— repo-root-relative Unix-separator path (no leading./).line— 1-based start line for human display only. Not part of the seam ID hash;byte_offsetis the canonical position field internally.owner— fully-qualified module/symbol path of the enclosing function. Backslashes from native paths are normalized to forward slashes before hashing. Test functions (e.g.,#[test] fninside#[cfg(test)] mod tests) are excluded.expression— verbatim source-code text at the seam origin. Surfaced for human review; not part of the seam ID hash.required_discriminator.kind—boundary_value,error_variant,return_value,field_value,effect,match_arm_taken, orcall_site.required_discriminator.description— human-readable summary of what a test must observe to grip the seam.expected_sink.kind—return_value,output_field,error_channel, orside_effect. The spec'sunknownsink will return when an undetermined kind is detected.
The repo seam inventory v1 captures every probeable production syntax shape
and does not yet classify test grip. When the repository root is analyzed,
repository automation and fixture data (xtask/, top-level fixtures/) are
excluded so repo-scoped public signals represent the published ripr package
surface; passing an individual fixture workspace as --root still analyzes
that fixture normally. analysis/repo-ripr-classification-v1 adds
SeamGripClass and the headline-eligibility table per RIPR-SPEC-0005.
Static output continues to forbid runtime-mutation outcome words.
The Markdown sibling (repo-seams.md, generated alongside the JSON) is
human-readable but follows the same contract for kind, owner, and
expected_sink strings.
Repo Exposure Report
ripr check --root . --format repo-exposure-json emits the classified seam
inventory introduced by analysis/repo-ripr-classification-v1. The artifact
lands at target/ripr/reports/repo-exposure.json when generated via
cargo xtask repo-exposure-report.
The full repo-exposure-json artifact is evidence-heavy by design: each seam
can carry related tests, observed values, missing discriminator records, and the
Lane 1 evidence_record projection. Large repositories should use
repo-exposure-summary-json for ordinary metrics, badge, planning, or CI
summary workflows, and reserve the full artifact for explicit deep inspection.
Every producer-generated repo-exposure-json snapshot also carries an
additive top-level artifact envelope before it is suitable for
ripr agent verify:
{
"kind": "repo_exposure",
"schema_version": "1",
"canonicalization": "raw_json_placeholder_v1",
"producer": {"tool": "ripr", "version": "0.10.0"},
"repository": {"root": "<workspace-root>", "head": "<40-hex-sha>"},
"analysis": {
"format": "repo-exposure-json",
"mode": "draft",
"base_revision": null,
"input_identity": "input:v3:fnv1a64:<16-hex-fingerprint>",
"command": "ripr check --format repo-exposure-json",
"profile": "draft",
"worktree": "clean"
},
"snapshot_identity": "snapshot:input:v3:fnv1a64:<16-hex-fingerprint>;revision:<full-head-sha>",
"content_sha256": "sha256:<64-hex-digest>"
}
content_sha256 commits the exact JSON bytes after replacing its one value
with the fixed zero-digest placeholder. This is an integrity/currentness
commitment, not a signature or runtime proof. repository.head and
analysis.worktree are unavailable when the producer cannot resolve Git;
such an artifact is disclosed but is not accepted by agent verify.
analysis.input_identity is the portable semantic/configuration identity of
the analysis input. It carries an explicit algorithm version and digest shape
(input:v3:fnv1a64:<16 lowercase hex>) and covers the identity version,
mode, profile (this producer binds profile to mode and states both), base
semantics, analysis format, manifest and lockfile content identities, the
repo-exposure producer-consumed configuration boundary (the three
oracle-strength fields oracles.snapshot_strength,
oracles.mock_expectation_strength, and oracles.broad_error_strength — the
Rust-only seam inventory consumes nothing else from ripr.toml), and the
analyzer version — never
the concrete checkout root or any host-specific path spelling. Cargo manifest
and lockfile CRLF line endings are normalized to LF for this portable identity;
standalone CR is preserved. Two equivalent
checkouts of the same commit under different temporary roots therefore share
one input identity, while repository.root stays the concrete
checkout-instance evidence: agent verify validates the declared root with
exact canonical-path equality, so an artifact produced in one root is still
rejected at another. The snapshot identity
(snapshot:<input_identity>;revision:<head>) binds that portable input
identity to the concrete repository head, so two clean artifacts from
different commits have distinct snapshot identities even when their input
identity is unchanged. Only the current input:v3: identity version with the
exact fnv1a64:<16 lowercase hex> digest shape validates as current
evidence; a wrong version is rejected as an unsupported input identity
version and a wrong digest shape as a malformed input identity digest. agent verify
and agent receipt compare the stable producer/version, base, mode, and
profile fields separately, and reject unchanged identities when the declared
repository commits differ. analysis.command and analysis.profile state the
producer operation used.
Repo Exposure Summary JSON
ripr check --root . --format repo-exposure-summary-json emits a bounded
aggregate view over the same classified seam inventory. It does not include the
full seams[] array, per-seam evidence_record, related_tests,
observed_values, or missing_discriminators payloads.
{
"schema_version": "0.1",
"format": "repo-exposure-summary-json",
"tool": "ripr",
"ripr_version": "0.8.0",
"scope": "repo",
"basis": "canonical_actionable_gap",
"metadata": {
"root": ".",
"base": "origin/main",
"head": "HEAD",
"mode": "draft"
},
"metrics": {
"raw_seams": 135812,
"headline_eligible_seams": 120408,
"canonical_gap_records": 2722,
"raw_actionable_seam_records": 46406,
"unsuppressed_exposure_gaps": 2722,
"suppressed_exposure_gaps": 0,
"grip_class": {
"strongly_gripped": 15404,
"weakly_gripped": 1800,
"ungripped": 0,
"reachable_unrevealed": 2,
"activation_unknown": 118606,
"propagation_unknown": 0,
"observation_unknown": 0,
"discrimination_unknown": 0,
"opaque": 0,
"intentional": 0,
"suppressed": 0
}
},
"reason_breakdown": {
"actionability": {
"add_focused_test": 200,
"extend_related_test": 2100,
"upgrade_assertion": 422
},
"gap_state": {
"actionable": 46406,
"already_observed": 15404,
"static_limitation": 0
},
"seam_kind": {
"predicate_boundary": 1200,
"return_value": 900,
"field_construction": 622
},
"grip_class": {
"strongly_gripped": 15404,
"weakly_gripped": 1800,
"ungripped": 0,
"reachable_unrevealed": 2,
"activation_unknown": 118606,
"propagation_unknown": 0,
"observation_unknown": 0,
"discrimination_unknown": 0,
"opaque": 0,
"intentional": 0,
"suppressed": 0
}
},
"limits": {
"top_files_limit": 25,
"top_files_total": 130,
"top_files_truncated": true
},
"top_files": [
{
"file": "src/pricing.rs",
"raw_seams": 480,
"headline_eligible_seams": 220,
"canonical_gap_records": 30,
"unsuppressed_exposure_gaps": 30,
"suppressed_exposure_gaps": 0,
"reason_breakdown": {
"actionability": {
"extend_related_test": 20,
"upgrade_assertion": 10
},
"grip_class": {
"strongly_gripped": 260,
"weakly_gripped": 20,
"activation_unknown": 200
}
}
}
]
}
Field contract:
schema_version- currently"0.1"for the bounded summary shape.format- always"repo-exposure-summary-json".scope- always"repo".basis- always"canonical_actionable_gap"; the headline metric is the unique canonical actionable gap count, not raw seam inventory.metadata.root,metadata.base,metadata.head, andmetadata.mode- command context for the analyzed root.headrecords the selected head ref asHEAD; this format does not resolve a commit hash.metrics.raw_seams- number of classified seam records inspected.metrics.headline_eligible_seams- raw seam records whosegrip_classis headline-eligible.metrics.canonical_gap_records- unique canonical gap identities assigned to headline-eligible seam records.metrics.raw_actionable_seam_records- raw seam records whose canonical item is actionable and carries a repair route, verify command, and receipt command.metrics.unsuppressed_exposure_gaps- unique actionable canonical gap count. This is the summary counterpart of the public repo badge basis.metrics.suppressed_exposure_gaps- raw seam records classified assuppressed.metrics.grip_class- all 11SeamGripClasscount buckets.reason_breakdown.actionability- unique actionable canonical gap counts by canonical item actionability, such asadd_focused_test,extend_related_test, andupgrade_assertion.reason_breakdown.gap_state- raw canonical item counts by state, such asactionable,already_observed,internal_only,static_limitation, andunknown.reason_breakdown.seam_kind- unique actionable canonical gap counts by seam kind.reason_breakdown.grip_class- same all-bucket class counts asmetrics.grip_class, repeated for consumers that read breakdowns only.limits.top_files_limit- maximum number oftop_files[]rows returned. The current limit is 25.limits.top_files_totalandlimits.top_files_truncated- total file rows before truncation and whether the emitted list is capped.top_files[]- bounded file summaries sorted by actionable canonical gap count, then headline-eligible raw seams, raw seams, and file path. File-levelunsuppressed_exposure_gapscounts unique actionable canonical gap IDs within that file.
The summary format is additive. It does not replace repo-exposure-json, which
remains the full per-seam evidence artifact for deep debugging and downstream
consumers that require complete evidence records.
cargo xtask repo-exposure-summary-report wraps this format with a local
timeout. The timeout is controlled by RIPR_REPO_EXPOSURE_SUMMARY_TIMEOUT_MS
(default: 240000). If the command times out, exits before a complete summary, or
cannot start, it writes a warning artifact to the same
target/ripr/reports/repo-exposure-summary.json path with:
basis: "limited_runtime_status"run_statussuch aslimited_timeout,limited_runner_failure, orlimited_incomplete_inputruntime_status.downstream_consumable: false- an empty
metricsobject and emptytop_filesarray run_limitations[]with command, timeout, duration, exit code, and stderr/stdout excerpts
Consumers must not treat limited artifacts as canonical actionable counts.
{
"schema_version": "0.3",
"scope": "repo",
"metrics": {
"seams_total": 9355,
"headline_eligible": 6114,
"strongly_gripped": 3241,
"weakly_gripped": 1756,
"ungripped": 0,
"reachable_unrevealed": 2,
"activation_unknown": 4356,
"propagation_unknown": 0,
"observation_unknown": 0,
"discrimination_unknown": 0,
"opaque": 0,
"intentional": 0,
"suppressed": 0
},
"seams": [
{
"seam_id": "f3c9e4d21a0b7c88",
"kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"owner": "src/pricing.rs::discounted_total",
"expression": "amount >= discount_threshold",
"grip_class": "weakly_gripped",
"headline_eligible": true,
"evidence": {
"reach": "yes",
"activate": "yes",
"propagate": "yes",
"observe": "yes",
"discriminate": "weak"
},
"related_tests_total": 47,
"related_tests": [
{
"name": "below_threshold_has_no_discount",
"file": "tests/pricing_tests.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"evidence_summary": "exact value assertion",
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
}
],
"observed_values": ["50", "10000"],
"missing_discriminators": [
{
"value": "input that hits the boundary: amount >= discount_threshold",
"reason": "predicate uses an equality-bearing operator; tests should exercise the boundary case"
},
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate"
}
],
"evidence_record": {
"schema_version": "0.1",
"seam_id": "f3c9e4d21a0b7c88",
"canonical_gap_id": "gap:67fc764ba37d77bd",
"canonical_gap_group_size": 1,
"canonical_gap_reason": "same owner, seam kind, flow sink, missing discriminator, and assertion shape",
"raw_findings": [
{
"file": "src/pricing.rs",
"line": 88,
"kind": "weakly_gripped",
"expression": "amount >= discount_threshold",
"probe_kind": "predicate_boundary",
"source_id": "f3c9e4d21a0b7c88",
"evidence_record_ref": "f3c9e4d21a0b7c88"
}
],
"canonical_item": {
"canonical_gap_id": "gap:67fc764ba37d77bd",
"raw_group_size": 1,
"canonical_item_kind": "gap",
"evidence_class": "predicate_boundary",
"gap_state": "actionable",
"actionability": "extend_related_test",
"group_reason": "same owner, seam kind, flow sink, missing discriminator, and assertion shape",
"primary_anchor": {
"file": "src/pricing.rs",
"line": 88,
"kind": "weakly_gripped",
"source_id": "f3c9e4d21a0b7c88",
"reason": "canonical_group_primary_raw_finding"
},
"raw_spans": [
{
"file": "src/pricing.rs",
"start_line": 88,
"end_line": 88,
"kind": "weakly_gripped",
"source_id": "f3c9e4d21a0b7c88"
}
],
"why": "extend the nearest related test with the missing discriminator",
"recommended_repair": "Add or strengthen `assert_eq!(discounted_total(/* boundary input where amount >= discount_threshold */), /* expected */)` for `input that hits the boundary: amount >= discount_threshold` in `tests/pricing_tests.rs` as `discounted_total_boundary_discriminator`.",
"repair_route": {
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"suggested_assertion": "assert_eq!(discounted_total(/* boundary input where amount >= discount_threshold */), /* expected */)"
},
"related_test": {
"name": "below_threshold_has_no_discount",
"file": "tests/pricing_tests.rs",
"line": 12,
"reason": "direct_owner_call"
},
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json",
"confidence": {
"basis": "static_only",
"notes": ["no imported runtime calibration data"]
}
},
"owner": "src/pricing.rs::discounted_total",
"location": {
"file": "src/pricing.rs",
"line": 88
},
"seam_kind": "predicate_boundary",
"grip_class": "weakly_gripped",
"headline_eligible": true,
"evidence_path": {
"reach": {
"state": "yes",
"confidence": "medium",
"summary": "owner is reached"
},
"activate": {
"state": "yes",
"confidence": "medium",
"summary": "boundary values were observed"
},
"propagate": {
"state": "yes",
"confidence": "medium",
"summary": "changed value flows to return value"
},
"observe": {
"state": "yes",
"confidence": "medium",
"summary": "related test observes returned value"
},
"discriminate": {
"state": "weak",
"confidence": "medium",
"summary": "equality discriminator is missing"
}
},
"assertion_texts": {
"12": "discounted_total(50, 100)"
},
"observed_values": [
{
"value": "50",
"line": 12,
"context": "function_argument"
}
],
"missing_discriminators": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate",
"flow_sink": null
}
],
"related_tests_total": 47,
"related_tests": [
{
"name": "below_threshold_has_no_discount",
"file": "tests/pricing_tests.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"evidence_summary": "exact value assertion",
"oracle_semantics": {
"observes": "the exact value or value pattern asserted by the test",
"missing": "no obvious value-shape discriminator gap under static scope",
"upgrade_suggestion": null
},
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
}
],
"recommendation": {
"action": "write_targeted_test",
"reason": "extend the nearest related test with the missing discriminator",
"recommended_test": {
"name": "discounted_total_boundary_discriminator",
"file": "tests/pricing_tests.rs",
"reason": "place the new targeted test next to the nearest strong related test"
},
"nearest_test_to_imitate": {
"name": "below_threshold_has_no_discount",
"file": "tests/pricing_tests.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"evidence_summary": "exact value assertion",
"oracle_semantics": {
"observes": "the exact value or value pattern asserted by the test",
"missing": "no obvious value-shape discriminator gap under static scope",
"upgrade_suggestion": null
},
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
},
"candidate_values": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate"
}
],
"assertion_shape": {
"kind": "exact_return_value",
"example": "assert_eq!(actual, expected)"
},
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json"
},
"actionability": {
"class": "actionable_related_test_extension",
"reason": "extend the nearest related test with the missing discriminator",
"has_concrete_guidance": true,
"signals": {
"missing_discriminator": true,
"candidate_value": true,
"assertion_shape": true,
"related_test": true,
"recommended_test_target": true,
"verification_command": true
}
},
"calibration": {
"availability": "not_imported",
"confidence": "unknown",
"agreement": "no_runtime_data"
},
"static_limitations": [],
"presentation_text": null
}
}
]
}
Field contract:
schema_version— currently"0.3". Bumping requires updating this section, the renderer (crates/ripr/src/output/repo_exposure.rs), and any downstream consumers in lockstep.0.1→0.2: per-related-test entries gainedrelation_reasonandrelation_confidencefields (analysis/related-test-precision-v1).0.2->0.3: seams gained the additiveevidence_recordprojection (RIPR-SPEC-0021) while preserving existing top-level seam fields.relation_reasonis an additive string enum within0.3;helper_owner_callextends the existing relation taxonomy without changing the field shape.scope— always"repo".run_status— always present; one of"complete"or"seam_limit_applied"."complete"means the run analyzed all seams."seam_limit_applied"meansRIPR_REPO_EXPOSURE_SEAM_LIMITtruncated the inventory. Consumers must readrun_statusbefore treating counts as complete-repo totals. Added as an additive field within schema version0.3per RIPR-SPEC-0074.limitations[]— present when repo exposure has a named run limitation or guidance disclosure. Consumers must branch oncategory.category: "repo_seam_limit_applied"appears whenrun_statusis"seam_limit_applied". It carriesseams_analyzed,seams_total,limit_source,control, andrepair_route.limit_sourceis"default"when the cap came from the built-in default (DEFAULT_REPO_EXPOSURE_SEAM_LIMIT = 10_000) and"configured"whenRIPR_REPO_EXPOSURE_SEAM_LIMITwas explicitly set in the environment.category: "typescript_diff_first"appears when a TS/JS-predominant workspace has TS/JS files, no Rust files, and zero classified seams.run_statusremains"complete"because the Rust repo-exposure scan completed. It carriests_file_count,repair_route, and the optional nestedtypescript_readinessobject.typescript_readiness.sourceis"repo_exposure_typescript_readiness.v1".typescript_readiness.authority_boundaryis"preview_advisory_only".typescript_readiness.analysis_modelis"diff_first".typescript_readiness.source_file_countis the count of TS/JS files not detected as tests.typescript_readiness.test_file_countis the count of detected TS/JS test files.typescript_readiness.package_root_countis the count of distinct package roots resolved from detected TS/JS files.typescript_readiness.package_confidenceisnone,low,medium, orhigh; it is the highest package discovery confidence across detected TS/JS files.typescript_readiness.runner_statusisno_tests_detected,resolved,partial, orunresolved.typescript_readiness.verify_command_countis the number of detected test files with a concrete verify command.typescript_readiness.top_blockeris the top missing readiness signal, ornull.typescript_readiness.non_claims[]states that the card does not emit full-repo TypeScript seams, run TypeScript tests, or create gate/badge authority.
metrics— totals plus a per-SeamGripClasscount bucket. Keys mirrorSeamGripClass::as_str(). The renderer emits all 11 buckets even when zero so consumers can plot stable bar charts.metrics.headline_eligible— count of seams whosegrip_classsatisfiesSeamGripClass::is_headline_eligible()per RIPR-SPEC-0005.seams[].grip_class— one of the 11SeamGripClassstrings:strongly_gripped,weakly_gripped,ungripped,reachable_unrevealed,activation_unknown,propagation_unknown,observation_unknown,discrimination_unknown,opaque,intentional,suppressed.seams[].evidence— per-stageStageStatestrings:yes,weak,no,unknown,opaque,not_applicable.seams[].related_tests_total— number of related tests the analyzer matched. Therelated_testsarray is capped for artifact size; seeMAX_RELATED_TESTS_PER_SEAM_JSONin the renderer (currently 8). The total field always carries the unbounded count.seams[].related_tests[].relation_reason— single highest-priority reason this test is related to the seam. One of:direct_owner_call,helper_owner_call,assertion_target_affinity,same_test_file,same_module,owner_named_test,import_path_affinity,fixture_owner_affinity. Detection lives incrates/ripr/src/analysis/test_grip_evidence.rs.helper_owner_callis limited to a one-hop helper or wrapper that directly calls the owner. Supported shapes are same-file helpers, test-local helpers, explicitly qualified test-support helpers, and unambiguous same-package production wrappers. The helper either carries the specific owner token in its name or is a direct delegating wrapper whose supported owner calls all target one specific owner name. Generic owner names, skipped-owner wrappers, mixed-owner wrappers, ambiguous production wrapper names, local test-helper shadows, and two-hop wrapper chains remain non-activating static limitations.seams[].related_tests[].relation_confidence—high,medium,low, oropaque. Mapping from reason:direct_owner_call,helper_owner_call→high;assertion_target_affinity,same_test_file,same_module,owner_named_test, andimport_path_affinity→medium;fixture_owner_affinity→low. Independent oforacle_strength: alowrelation can still carry a strong oracle.- The
related_testsarray is ranked by(confidence, reason_priority, oracle_strength, activation_overlap, file, name, line)so the highest-confidence tests appear first, then the nearest strong imitation target wins within otherwise equivalent relationships.activation_overlapis a static tie-breaker from already observed call values, such as a predicate-boundary equality call.related_tests_totalis unaffected by ranking. seams[].observed_values— statically resolved scalar values seen in owner-call arguments across related tests. In addition to direct literals, Rust predicate boundaries may carry exact values from source-ordered direct field assignments whose right-hand side is a same-file literal constant or that constant plus/minus a bounded integer offset. The write must be an unconditional function-body statement with no intervening explicit mutable borrow before the owner call. Other bare identifiers, helper-derived values, conditional writes, invalidated values, and ambiguous field writes are intentionally excluded.seams[].missing_discriminators— per-rule hypothesis strings (e.g., the equality-boundary case for predicate seams). Empty when no rule fires.seams[].evidence_record- additive Lane 1 evidence spine for the seam. It is schema versioned independently from repo exposure and currently usesschema_version: "0.1".seams[].evidence_record.canonical_gap_id- generated canonical behavioral gap identity for headline-eligible gap classes, ornullfor strong, opaque, intentional, and suppressed seams. Line numbers remain locators, not durable canonical identity.seams[].evidence_record.canonical_gap_group_size- number of raw seams in this repo-exposure snapshot that share the same canonical gap identity, ornullwhen no canonical gap identity is assigned.seams[].evidence_record.canonical_gap_reason- grouping reason for the canonical identity, ornullwhen no canonical gap identity is assigned.seams[].evidence_record.raw_findings- supporting raw analyzer signals that contributed to this record. The current seam-native projection emits one raw finding per seam; later class-specific grouping may attach multiple raw findings to one canonical item.seams[].evidence_record.canonical_item- additive finding-alignment projection withgap_state, class-scopedactionability,why,recommended_repair, nullable structuredrepair_route,related_test,verify_command, nullablereceipt_command,confidence, raw group size, nullableprimary_anchor, andraw_spans. Actionable canonical items carryrepair_route.repair_kind,target_test_type, andsuggested_assertion; no-action, observed, limitation, and unknown items keeprepair_route: null. Actionable items also carry a safe agent receipt command when the canonical repair/verify loop is available, so public-projection readiness can be assessed from canonical evidence rather than raw findings. Downstream surfaces should render this canonical item before treating raw findings as separate work.seams[].evidence_record.canonical_item.command_specs- additive typed descriptions for the canonicalverify_commandandreceipt_commandwhen RIPR owns those routes. Each spec carries ordered argv, policies, expected writes, and an authority boundary. A verify command that writes through shell redirection is markedexecution_mode: "shell_required"; receipt--outis represented as direct argv. These descriptions are not execution permission, and arbitrary preview test commands remain legacy advisory text until their producer supplies an executable boundary.seams[].evidence_record.canonical_item.primary_anchor- preferred placement hint for downstream surfaces when the canonical item has a safe source location. It isnullonly when RIPR cannot safely name a placement.seams[].evidence_record.canonical_item.raw_spans[]- source-span summary for every raw finding contributing to the canonical item. These spans are supporting evidence, not independent user-facing actions.seams[].evidence_record.canonical_item.static_limitations[]- canonical item-local copy of named analyzer limitations for static-limitation and unknown states. Downstream canonical-item consumers may use these category and repair-route rows to explain why an item is not actionable, but must not treat them as user test debt.field_assignment_value_unresolvedroutes toanalysis/field-assignment-value-resolutionwhen a direct Rust field write is present but its value is outside the safe literal/constant-offset subset.seams[].evidence_record.evidence_path- typed reach, activate, propagate, observe, and discriminate stages. Each stage carriesstate,confidence, andsummary.seams[].evidence_record.observed_values,missing_discriminators, andrelated_tests- structured copies of existing seam evidence, including related-test relation fields. The nestedrelated_testsarray is capped like the top-level array and keepsrelated_tests_total.seams[].evidence_record.related_tests[].oracle_semantics- structured oracle-shape explanation withobserves,missing, and nullableupgrade_suggestion. Weak, broad, smoke-only, and unknown oracle shapes name the behavior they observe, the discriminator they fail to observe, and the assertion upgrade RIPR recommends for this seam kind. The upgrade suggestion is strength-gated (#3731): astrongoracle already discriminates, so itsupgrade_suggestionisnull; medium-or-below keeps the recommendation.seams[].evidence_record.recommendation- bounded test-intent guidance derived from existing evidence: recommended test target, nearest test to imitate, candidate values, assertion shape, and verification command when the seam has concrete guidance.seams[].evidence_record.actionability- advisory classification plus boolean signals showing which pieces of guidance are present. It does not change gate or baseline policy.seams[].evidence_record.calibration- placeholder static/runtime confidence context.no_runtime_datameans no imported runtime calibration was supplied; it does not imply runtime confirmation.seams[].evidence_record.static_limitations- unknown or opaque static evidence stages that should be treated as analyzer limitations rather than focused-test instructions. Each entry carries the originalstage,state, andreasonplus a normalizedcategoryandrepair_routeso Lane 1 can group analyzer limits without treating them as user test gaps. Predicate boundaries whose activation operand is local, member-access, iterator-derived, or computed use categoryactivation_boundary_input_unresolved. Iterator-derived operands route toanalysis/iterator-boundary-operand-resolution; member-access operands route toanalysis/local-member-boundary-operand-resolution; local or computed operands route toanalysis/local-computed-boundary-operand-resolution. They must not emit exact boundary candidate values or public repair packets.seams[].evidence_record.presentation_text- reserved presentation-text evidence-class projection. It isnulluntil a fixture-backed presentation text slice classifies visibility, observer shape, and output actionability.
The fixture contract corpus at
fixtures/boundary_gap/expected/evidence-record-contract/corpus.json pins
representative evidence_record v0.1 records for predicate boundaries, exact
error variants, strong exact-value evidence, broad error assertions, field and
whole-object oracles, snapshot evidence, side-effect observers, opaque static
limitations, generated canonical gap identity, and the current
no_runtime_data calibration placeholder. Unit and repo-exposure tests pin the
additive raw_findings, canonical_item, and presentation_text alignment
fields before later presentation-text grouping changes. cargo xtask check-fixture-contracts
validates the required case matrix and field shape; cargo xtask check-output-contracts validates the evidence_record schema version in code,
docs, and the corpus.
The Markdown sibling (repo-exposure.md) prints a metrics table plus
the top headline-eligible seams (capped at 50). Both formats are
generated together by cargo xtask repo-exposure-report.
This report shows static test-grip evidence for repo seams. Runtime
confirmation via cargo-mutants is a separate calibration step
(calibration/cargo-mutants-v1). Static-language constraints from
RIPR-SPEC-0005 still apply: the report never uses runtime-mutation
outcome words.
Evidence Health Report
ripr evidence-health --root . summarizes Lane 1 analyzer evidence health
without changing analyzer behavior. The same report lands at
target/ripr/reports/evidence-health.json and
target/ripr/reports/evidence-health.md when generated through
cargo xtask evidence-health.
The xtask facade bounds both the preflight cargo build -p ripr phase and the
live ripr evidence-health subprocess with RIPR_EVIDENCE_HEALTH_TIMEOUT_MS
(default 4 minutes). If either phase times out, exits before a complete report
is available, or the xtask runner cannot start, capture, poll, or read the
child process, xtask discards stale or partial outputs and writes warning JSON
and Markdown with status = "warn", phase context such as
evidence_health_build or evidence_health_generation, and a named
evidence_health_timeout, evidence_health_incomplete, or
evidence_health_runner_error run_limitations[] entry. Runner/capture errors
use inputs.generation.status = "runner_error" and the limitation category
evidence_health_runner_error. The default is intentionally below common
5-minute validation shells so pathological live runs can write bounded warning
artifacts instead of being killed before evidence-health.json / .md exist.
while pathological runs still produce bounded diagnostics before abnormal
termination can drop the artifact. During
generation, xtask enables repo-exposure latency tracing so timeout artifacts can
include analyzer phase breadcrumbs when available. Limited artifacts expose those
breadcrumbs as bounded latency_trace_events_total and latency_trace_tail
fields on both inputs.generation and run_limitations[], so operators can see
which repo-exposure phase was active without scraping stderr. That limited
artifact is diagnostic only; it does not claim user test debt from missing health
counts.
{
"schema_version": "0.2",
"tool": "ripr",
"scope": "repo",
"status": "advisory",
"inputs": {
"root": ".",
"mutation_calibration": "target/ripr/reports/mutation-calibration.json"
},
"metrics": {
"seams_total": 9355,
"headline_eligible_total": 6114,
"weakly_gripped_total": 1756,
"ungripped_total": 0,
"grip_class_counts": {
"strongly_gripped": 3241,
"weakly_gripped": 1756,
"ungripped": 0,
"reachable_unrevealed": 2,
"activation_unknown": 4356,
"propagation_unknown": 0,
"observation_unknown": 0,
"discrimination_unknown": 0,
"opaque": 0,
"intentional": 0,
"suppressed": 0
},
"stage_state_counts": {
"reach": {
"yes": 4999,
"weak": 0,
"no": 0,
"unknown": 4356,
"opaque": 0,
"not_applicable": 0
}
},
"unknown_stage_counts": {
"reach": 4356,
"activate": 4356,
"propagate": 0,
"observe": 0,
"discriminate": 0
},
"unknown_stop_reason_counts": {
"activation_unknown": 4356,
"propagation_unknown": 0,
"observation_unknown": 0,
"discrimination_unknown": 0,
"opaque": 0
},
"missing_discriminators_total": 1756,
"seams_with_missing_discriminators": 1756,
"missing_discriminator_counts": [
{"label": "amount == threshold", "count": 4}
],
"observed_values_total": 740,
"seams_with_observed_values": 310,
"observed_value_context_counts": {
"function_argument": 600,
"assertion_argument": 40,
"builder_method": 30,
"table_row": 50,
"enum_variant": 12,
"return_value": 8,
"unknown": 0
},
"related_tests_total": 2200,
"seams_with_related_tests": 1720,
"related_test_confidence_counts": {
"high": 910,
"medium": 1060,
"low": 220,
"opaque": 10
},
"oracle_strength_counts": {
"strong": 800,
"medium": 410,
"weak": 600,
"smoke": 300,
"none": 80,
"unknown": 10
},
"oracle_kind_counts": {
"exact_value": 700,
"exact_error_variant": 60,
"whole_object_equality": 40,
"snapshot": 120,
"relational_check": 180,
"broad_error": 250,
"smoke_only": 300,
"mock_expectation": 40,
"unknown": 10
},
"opaque_oracle_count": 10
},
"evidence_quality": {
"canonical_gap_groups_total": 4800,
"duplicate_looking_groups_total": 240,
"largest_canonical_groups": [
{
"canonical_gap_id": "gap:37d49d135d41fb52",
"count": 18,
"reported_group_size": 18,
"owner": "crates/ripr/src/output/first_useful_action.rs::selected_from_editor_context",
"seam_kind": "call_presence",
"flow_sink": "n/a",
"missing_discriminator": "n/a",
"assertion_shape": "n/a",
"example_seam_id": "f013a5a5798ec6c5",
"example_file": "crates/ripr/src/output/first_useful_action.rs"
}
],
"actionability_class_counts": {
"actionable_related_test_extension": 1200,
"static_limitation": 3600
},
"static_limitation_stage_counts": {
"activate": 3600
},
"static_limitation_reason_counts": [
{
"label": "No concrete activation values observed for seam `Vec::new()`",
"count": 255
}
],
"static_limitation_category_counts": {
"activation_value_unresolved": 255
},
"calibration_availability_counts": {
"not_imported": 9355
},
"movement_availability": {
"records_with_seam_id": 9355,
"records_with_canonical_gap_id": 6114,
"records_with_complete_evidence_path": 9355,
"records_with_recommendation": 9355,
"records_with_verify_command": 1756
},
"top_evidence_quality_risks": [
{
"kind": "static_limitations",
"count": 3600,
"summary": "Evidence records still contain static limitations."
}
]
},
"calibration": {
"status": "loaded",
"source": "target/ripr/reports/mutation-calibration.json",
"matched_total": 18,
"static_without_runtime_total": 120,
"runtime_without_static_total": 2,
"ambiguous_file_line_total": 1,
"unmatched_runtime_total": 2
},
"top_static_limitations": [
{
"kind": "missing_discriminator",
"count": 1756,
"summary": "At least one discriminator remains missing for the seam.",
"example_seam_id": "f3c9e4d21a0b7c88"
}
]
}
Field contract:
schema_version- currently"0.2".0.2changes free-formmissing_discriminator_countsandstatic_limitation_reason_countsfrom JSON objects to{label, count}rows so downstream consumers do not treat analyzer evidence strings as stable field names.scope- always"repo".status-"advisory"for complete analyzer-health reports and"warn"for bounded xtask fallback artifacts. This report is an analyzer-health view, not a gate decision.inputs.root- the analyzed workspace root as supplied to the command.inputs.mutation_calibration- optional imported calibration report path;nullwhen not provided.inputs.generation- present on bounded xtask fallback artifacts. It recordsphase(evidence_health_buildorevidence_health_generation), bounded command,status(fail,timeout,pass_incomplete, orrunner_error), timeout/duration, exit code when available, output byte counts, optionalfailure_reason, bounded stdout/stderr excerpts,latency_trace_events_total, andlatency_trace_tailrepo-exposure phase diagnostics when available. Completeripr evidence-healthreports omit this wrapper field and keep the normal analyzer-health payload, so the current contract does not emit an"ok"generation status.metrics.grip_class_counts- allSeamGripClassbuckets, including zero counts.metrics.stage_state_counts- per-stageStageStatebuckets forreach,activate,propagate,observe, anddiscriminate.metrics.unknown_stage_counts- unknown or opaque counts by evidence stage.metrics.unknown_stop_reason_counts- counts of unknown/opaqueSeamGripClassbuckets. This is intentionally repo-seam terminology; diff finding stop-reason strings are not reinterpreted here.metrics.missing_discriminator_counts- aggregate{label, count}rows for missing discriminator value text. It is row-shaped because the labels are analyzer evidence strings and can collide in case-insensitive JSON consumers.metrics.observed_value_context_counts- aggregate counts keyed byValueContext::as_str().metrics.related_test_confidence_counts-high,medium,low, andopaquerelated-test confidence buckets.metrics.oracle_strength_countsandmetrics.oracle_kind_counts- aggregate oracle evidence observed on related tests.evidence_quality- audit-style fields derived fromseams[].evidence_recordand canonical gap identity, without changing classifications or policy.evidence_quality.canonical_gap_groups_total- number of distinct canonical gap IDs among headline-eligible evidence records.evidence_quality.duplicate_looking_groups_total- number of canonical gap groups with more than one raw seam.evidence_quality.largest_canonical_groups- top canonical gap groups by raw seam count, capped to 10 rows, including the canonical ID, reported group size, owner, seam kind, flow sink, discriminator, assertion shape, and example seam/file.evidence_quality.actionability_class_counts- counts keyed byevidence_record.actionability.class.evidence_quality.static_limitation_stage_countsandstatic_limitation_reason_counts- distributions fromevidence_record.static_limitations. Reason counts are{label, count}rows because reasons are free-form evidence strings.evidence_quality.static_limitation_category_counts- normalized limitation categories such asactivation_value_unresolved,activation_owner_call_absent,activation_owner_call_absent_call_presence_target_affinity,activation_owner_call_absent_assertion_target_affinity,activation_owner_call_absent_affinity_only,activation_owner_call_absent_same_file_only,activation_owner_call_unresolved,constructor_field_owner_ambiguous,opaque_helper_call,cross_file_constant_unresolved,dynamic_dispatch,unsupported_mock_shape,snapshot_field_unknown, andside_effect_sink_unknown.activation_owner_call_absentroutes toanalysis/owner-call-absence-triage; it means static analysis found related context but no direct owner call, so it remains a named limitation rather than user-facing test repair debt. When the related-test evidence has no direct or helper owner-call relation, the category is split intoactivation_owner_call_absent_call_presence_target_affinityrouted toanalysis/call-presence-target-affinity-owner-call-tracingfor call-presence target-token affinity,activation_owner_call_absent_assertion_target_affinityrouted toanalysis/assertion-target-affinity-owner-call-tracing; return-value assertion-target owner-call absence may route more narrowly toanalysis/assertion-target-return-value-owner-call-tracingwhile remaining non-actionable,activation_owner_call_absent_affinity_onlyrouted toanalysis/related-test-affinity-owner-call-tracing, oractivation_owner_call_absent_same_file_onlyrouted toanalysis/same-file-owner-call-tracingwhen same-file context is the primary non-owner-call relation. Call-presence target-affinity, related-test-affinity, and same-file owner-call absence backlog packets may further splitlimitation_subrouteby expression shape, such as receiver-method, associated-call, or function-call missing-owner-call routes, so analyzer work can distinguish local receiver method evidence from free-function call tracing without making the item actionable.constructor_field_owner_ambiguousroutes toanalysis/constructor-field-observation; it means an exact-field observer exists but a same-name same-crate caller maps to multiple possible owners. The seam remains a static limitation rather than selecting an owner or presenting the field observer as actionable closure evidence.evidence_quality.calibration_availability_counts- counts keyed byevidence_record.calibration.availability. These are placeholder coverage labels from the static record and do not imply runtime execution.evidence_quality.movement_availability- counts of records carrying seam IDs, canonical gap IDs, complete evidence paths, recommendations, and verify commands for movement-aware downstream reports.evidence_quality.top_evidence_quality_risks- largest advisory risk buckets for follow-up Lane 1 work. They are measurements, not gate decisions.calibration- availability counts from an already-produced mutation calibration report when one is supplied. The evidence-health command does not run mutation testing, infer thresholds, or change static classification.top_static_limitations- the largest static evidence gaps by count, capped to 10 rows and carrying one example seam ID for inspection.run_limitations- present on bounded xtask fallback artifacts. Timeout, incomplete, and runner-error rows nameevidence_health_timeout,evidence_health_incomplete, orevidence_health_runner_error, theevidence_health_buildorevidence_health_generationphase, timeout/duration/output byte diagnostics, bounded stdout/stderr excerpts, optionalfailure_reason, boundedlatency_trace_events_totalandlatency_trace_tailrepo-exposure phase diagnostics when available, and a repair route for inspecting runtime, stdout/stderr, or increasingRIPR_EVIDENCE_HEALTH_TIMEOUT_MSon slower machines. If the child exits successfully but the expected JSON/Markdown artifacts are missing or incomplete, the fallback usesinputs.generation.status = "pass_incomplete"and overwrites stale prior artifacts. If the build or generation runner cannot start, capture, poll, or read the child process, the fallback usesinputs.generation.status = "runner_error",run_limitations[].category = "evidence_health_runner_error", and still overwrites stale prior artifacts.
The Markdown sibling prints the same summary, grip-class, top missing discriminator, oracle-strength, related-test confidence, evidence-quality, largest canonical group, actionability, static limitation distribution, evidence-record calibration coverage, calibration, top evidence-quality risk, and top limitation sections for humans. High-cardinality missing-discriminator and static-limitation reason details remain complete in JSON and are capped in Markdown. Static-language constraints still apply: runtime-specific labels stay confined to the optional imported calibration availability section.
Lane 1 Runtime Status
Lane 1 repair-control reports keep the existing advisory status field and add
a separate run_status field for completeness:
full
limited_timeout
limited_runner_failure
limited_large_cache_skip
limited_incomplete_input
limited_sampled_input
limited_stale_input
Reports that emit this contract also include runtime_status:
{
"run_status": "limited_timeout",
"runtime_status": {
"state": "limited_timeout",
"phase": "repo_exposure_generation",
"duration_ms": 120000,
"limit_ms": 120000,
"input_kind": "repo-exposure-json",
"input_path": null,
"limitation_category": "lane1_repo_exposure_timeout",
"repair_route": "inspect repo-exposure latency trace",
"downstream_consumable": false
}
}
run_status = "full" means the report did not observe a completeness-affecting
runtime limitation. Limited states must name the phase, duration or limit when
available, an input kind or path, a limitation category, a repair route, and
whether downstream consumers may safely use the counts. status = "advisory"
still means the artifact does not change gate policy or public badge semantics.
Downstream surfaces must read run_status before treating Lane 1 counts as
complete.
Lane 1 Evidence Quality Audit
cargo xtask lane1-evidence-audit writes a repo-local audit over generated
ripr check --mode instant --format repo-exposure-json
seams[].evidence_record data:
target/ripr/reports/lane1-evidence-audit.json
target/ripr/reports/lane1-evidence-audit.md
target/ripr/reports/actionable-gaps.json
target/ripr/reports/actionable-gaps.md
cargo xtask evidence-quality-audit is an alias. The report is advisory and
does not change analyzer behavior, gate policy, PR/CI projection, editor UX, or
runtime execution.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "lane1-evidence-audit",
"scope": "repo",
"status": "advisory",
"run_status": "full",
"runtime_status": {
"state": "full",
"phase": null,
"duration_ms": null,
"limit_ms": null,
"input_kind": null,
"input_path": null,
"limitation_category": null,
"repair_route": null,
"downstream_consumable": true
},
"inputs": {
"root": ".",
"source": "repo-exposure-json",
"repo_exposure_mode": "instant",
"repo_exposure_schema_version": "0.3",
"repo_exposure_generation": {
"command": "target/debug/ripr check --root . --mode instant --format repo-exposure-json",
"timeout_ms": 120000,
"status": "pass",
"failure_reason": null,
"duration_ms": 42000,
"exit_code": 0,
"stdout_bytes": 1048576,
"stderr_bytes": 4096,
"latency_trace_events_total": 18,
"latency_trace_tail": [
{
"phase": "evidence_for_seams_progress",
"status": "processed_5000_of_38124",
"duration_ms": 41000
}
]
}
},
"run_limitations": [],
"summary": {
"seams_total": 9355,
"raw_headline_gaps": 6114,
"evidence_records_total": 9355,
"evidence_records_missing": 0,
"canonical_gap_groups_total": 4800,
"duplicate_looking_groups_total": 240,
"headline_without_canonical_gap_id": 12,
"missing_discriminators_total": 1756,
"static_limitations_total": 4356,
"related_tests_total": 2200,
"seams_without_related_tests": 310,
"low_or_opaque_top_related_tests": 48,
"calibrated_records": 0,
"uncalibrated_records": 9355
},
"finding_alignment": {
"source": "evidence_record.canonical_item",
"summary": {
"raw_findings": 9355,
"raw_signals": 9355,
"canonical_items": 9355,
"aligned_raw_findings": 9355,
"unaligned_raw_findings": 0,
"raw_to_canonical_ratio": 1.0,
"duplicate_groups_total": 0,
"actionable_gaps": 1756,
"already_observed": 3200,
"internal_no_action": 20,
"static_limitations": 4356,
"unknown": 23,
"calibrated_supported": 0,
"uncalibrated": 9355,
"presentation_text_total": 0,
"presentation_text_visibility_unknown": 0,
"finding_alignment_raw_signals_total": 9355,
"finding_alignment_canonical_items_total": 9355,
"finding_alignment_actionable_items_total": 1756,
"finding_alignment_static_limitation_total": 4356
},
"coverage": {
"alignment_coverage_by_class": [
{
"evidence_class": "predicate_boundary",
"raw_findings": 4200,
"canonical_items": 3900,
"aligned_raw_findings": 4100,
"unaligned_raw_findings": 100,
"actionable_items": 900,
"already_observed_items": 1700,
"internal_no_action_items": 20,
"static_limitation_items": 1200,
"unknown_items": 80
}
],
"unaligned_raw_findings_by_class": {
"config_or_policy_constant": 12
},
"top_unaligned_examples": [
{
"evidence_class": "config_or_policy_constant",
"file": "src/policy.rs",
"line": 10,
"kind": "static_unknown",
"expression": "pub const POLICY_LABEL: &str = \"internal\";",
"reason": "missing canonical_item"
}
],
"same_line_duplicate_groups": [
{
"file": "src/policy.rs",
"line": 10,
"raw_findings": 2,
"evidence_classes": ["config_or_policy_constant"],
"kinds": ["exposed", "static_unknown"],
"example_expression": "pub const POLICY_LABEL: &str ="
}
],
"static_unknown_without_named_limitation": 0,
"canonical_items_without_repair_route": 0,
"canonical_items_without_verify_command": 120
},
"actionable_gap_top_lists": {
"top_actionable_gap_classes": [
{"label": "predicate_boundary", "count": 900}
],
"top_actionable_files": [
{"label": "src/pricing.rs", "count": 42}
],
"top_repair_kinds": [
{"label": "add_boundary_assertion", "count": 810}
],
"top_missing_discriminator_kinds": [
{"label": "return_value", "count": 720}
],
"top_static_limitation_reasons": [
{"label": "opaque helper value", "count": 1200}
],
"top_verify_command_unknowns": [
{"label": "predicate_boundary", "count": 120}
],
"top_repair_route_unknowns": []
},
"actionable_gap_packets": [
{
"canonical_gap_id": "gap:abc",
"evidence_class": "predicate_boundary",
"gap_state": "actionable",
"actionability": "extend_related_test",
"source_file": "src/pricing.rs",
"primary_anchor": {"file": "src/pricing.rs", "line": 42},
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(price(/* boundary input where amount == threshold */), expected)",
"repair_route": {
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(price(/* boundary input where amount == threshold */), expected)"
},
"target_test_shape": "boundary_discriminator: assert_eq!(price(/* boundary input where amount == threshold */), expected)",
"recommended_repair": "Add or strengthen `assert_eq!(price(/* boundary input where amount == threshold */), expected)` for `input that hits the boundary: amount == threshold` in `tests/pricing.rs` as `price_boundary_discriminator`.",
"why": "Related tests reach the seam but miss equality at the threshold.",
"related_test_or_observer": {
"file": "tests/pricing.rs",
"name": "below_threshold_has_no_discount",
"line": 10
},
"candidate_value_or_observer": "input that hits the boundary: amount == threshold",
"verify_command": "cargo xtask evidence-quality-scorecard",
"repair_route_source": "canonical_item.repair_route",
"verify_command_source": "canonical_item.verify_command",
"receipt_command": null,
"receipt_command_or_path": null,
"receipt_source": "missing",
"public_projection_eligible": false,
"projection_exclusion_reasons": ["missing_receipt_command"],
"raw_evidence_refs": [
{"file": "src/pricing.rs", "line": 42, "kind": "weakly_exposed"}
],
"raw_findings": [
{"file": "src/pricing.rs", "line": 42, "kind": "weakly_exposed"}
],
"raw_findings_supporting_only": true,
"static_limitations": [],
"confidence": {"basis": "static_only"},
"confidence_basis": "static_only",
"must_not_change": [
"Do not infer actionability from raw static class."
],
"allowed_edit_surface": [
"tests/pricing.rs"
]
}
],
"actionable_gap_packet_public_projection": {
"scope": "emitted_actionable_gap_packets",
"public_projection_eligible_packets": 0,
"public_projection_excluded_packets": 1,
"projection_exclusion_reasons": [
{"label": "missing_receipt_command", "count": 1}
]
},
"runtime_confidence_by_class": [
{
"evidence_class": "predicate_boundary",
"canonical_items": 900,
"calibrated_supported": 0,
"fixture_backed": 0,
"static_only": 900,
"unknown_confidence": 0,
"uncalibrated": 900,
"actionable_items": 120,
"static_limitation_items": 40
}
]
},
"canonical_gap_groups": {
"total": 4800,
"largest": [
{
"key": "canonical:gap:abc",
"canonical_gap_id": "gap:abc",
"count": 8,
"reported_group_size": 8,
"owner": "pricing::discount",
"seam_kind": "predicate_boundary",
"flow_sink": "return_value",
"missing_discriminator": "amount == threshold",
"assertion_shape": "exact_value",
"example_seam_id": "f3c9e4d21a0b7c88",
"example_file": "src/pricing.rs"
}
]
},
"duplicate_looking_groups": [],
"missing_discriminator_classes": {
"by_reason": [
{"label": "boundary value not observed", "count": 900}
],
"by_flow_sink": {
"return_value": 870
},
"by_value": [
{"label": "amount == threshold", "count": 4}
]
},
"static_limitations": {
"by_reason": [
{"label": "static evidence is opaque or unknown for this seam", "count": 1200}
],
"by_stage": {
"activate": 800
},
"by_category": {
"activation_static_unknown": 800
},
"repair_routes": {
"analysis/static-limitation-taxonomy": 800
}
},
"oracle_semantics_distribution": {
"by_semantics": [
{
"label": "observes=exact return value; missing=boundary equality; upgrade=add equality boundary",
"count": 42
}
],
"oracle_kind_counts": {
"exact_value": 700
},
"oracle_strength_counts": {
"strong": 800
}
},
"related_test_ranking": {
"all_confidence_counts": {
"high": 910,
"medium": 1060,
"low": 220,
"opaque": 10
},
"top_confidence_counts": {
"high": 600,
"medium": 900,
"low": 40,
"opaque": 8
},
"top_relation_reason_counts": {
"direct_owner_call": 600
},
"seams_without_related_tests": 310,
"low_or_opaque_top_related_tests": 48
},
"movement_availability": {
"records_with_seam_id": 9355,
"records_with_canonical_gap_id": 4800,
"records_with_complete_evidence_path": 9355,
"records_with_recommendation": 9355,
"records_with_verify_command": 1756
},
"calibration_availability": {
"availability_counts": {
"not_imported": 9355
},
"confidence_counts": {
"unknown": 9355
},
"agreement_counts": {
"no_runtime_data": 9355
},
"calibrated_records": 0,
"uncalibrated_records": 9355,
"runtime_confidence_by_class": [
{
"evidence_class": "predicate_boundary",
"canonical_items": 900,
"calibrated_supported": 0,
"fixture_backed": 0,
"static_only": 900,
"unknown_confidence": 0,
"uncalibrated": 900,
"actionable_items": 42,
"static_limitation_items": 0
}
]
},
"evidence_record_field_health": [
{
"field": "canonical_gap_id",
"present": 4800,
"missing": 0,
"null": 4555,
"empty": 0
}
],
"top_files_by_unresolved_evidence_debt": [
{
"file": "src/pricing.rs",
"debt_score": 42,
"headline_gaps": 10,
"missing_discriminators": 10,
"static_limitations": 5,
"unknown_stage_records": 12,
"no_related_tests": 3,
"low_or_opaque_top_related_tests": 2,
"missing_evidence_records": 0
}
]
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".report- always"lane1-evidence-audit".scope- always"repo".status- always"advisory".run_status- Lane 1 completeness state. Values arefull,limited_timeout,limited_runner_failure,limited_large_cache_skip,limited_incomplete_input,limited_sampled_input, orlimited_stale_input.runtime_status- structured completeness context matchingrun_status. Limited states name the phase, input kind or path, limitation category, repair route, timing fields when available, anddownstream_consumable.inputs.root- analyzed root for the generated repo exposure snapshot.inputs.source- always"repo-exposure-json".inputs.repo_exposure_mode- currently"instant"; this keeps the repo-local audit bounded while preserving the existing repo-exposureevidence_recordcontract.inputs.repo_exposure_generation.latency_trace_tail- includes the preservedrepo_exposure_seam_limittrace row when the default sampled repo-exposure input path is used.cargo xtask lane1-evidence-auditsamples 5,000 seams by default via the internalRIPR_REPO_EXPOSURE_SEAM_LIMIThandoff; operators can setRIPR_LANE1_EVIDENCE_AUDIT_SAMPLE_SEAMS=0for an unsampled full-repo attempt, or a positive integer to change the sample size.inputs.repo_exposure_schema_version- schema version read from the generated repo exposure JSON, ornullif absent.inputs.repo_exposure_generation- bounded diagnostics for the live repo-exposure subprocess, including timeout, status, nullablefailure_reason, duration, output byte counts, and the last captured latency trace events. These diagnostics explain long or pathological audit input generation without changing classifications, gate policy, or score semantics.run_limitations- bounded report-level limitations. A timed-out repo-exposure subprocess produces a warning audit artifact only when the captured repo-exposure JSON is missing or incomplete. If the captured file is complete and contains a top-levelseamsarray, the audit consumes it and recordsinputs.repo_exposure_generation.status = "timeout_complete"instead of claiming a timeout-limited zero-debt artifact. A true timeout limitation includes alane1_repo_exposure_timeoutrow, phase/input context, timeout/duration diagnostics, the latency trace tail, and a repair route. A subprocess that exits before writing complete repo-exposure JSON, including a nominally successful exit with an empty or malformed output file, produceslane1_repo_exposure_incompletewith the same bounded diagnostics. Counts in such limited artifacts are not complete repo truth and downstream reports must surface the limitation instead of treating zeros as absence of gaps. A runner or capture failure before repo exposure can be started or read produceslane1_repo_exposure_runner_errorwithfailure_reason, command, timeout, duration, phase/input context, and a repair route. If the existingtarget/ripr/cachefootprint exceeds the Lane 1 cache budget before repo-exposure generation starts, the audit writeslane1_repo_exposure_large_cache_preflight_skipwithrun_status = "limited_large_cache_skip",downstream_consumable = false, and a repair route throughcargo xtask cache reportandcargo xtask cache gc --dry-run. Current repo seam cache writes entries larger thanRIPR_REPO_SEAM_CACHE_LIMITas bounded shard files undertarget/ripr/cache. Older audit artifacts or older cache-store implementations may still reportlane1_repo_exposure_cache_store_skipped_large_entrywhen the live repo-exposure run emitted complete evidence but skipped a full classified seam cache store. That compatibility limitation carries structuredobserved_seamsandcache_limitfields in addition to the compatibilityinputstring, and its repair route namescargo xtask cache reportplusRIPR_REPO_SEAM_CACHE_LIMITconfiguration when a machine has enough disk/time budget for larger cache shard writes. The default sampled repo-exposure path recordslimited_sampled_inputwithlane1_repo_exposure_sampledand input such asrepo-exposure-json:limit_5000_of_39685; sampled counts are useful work-queue evidence, not full-repo debt totals. Run-limitation rows also carryrun_status,input_kind,input_path,limit_ms, anddownstream_consumableso consumers do not need to infer completeness from category strings. Namedrun_limitations[]entries also contribute tosummary.static_limitations_totalandstatic_limitations.by_category, so a limited audit cannot look like a clean zero-limitation run in headline summaries.summary.raw_headline_gaps- count of seams that are headline-eligible in the record or top-level repo exposure row.finding_alignment.source- source used for audit-local alignment counts; currentlyevidence_record.canonical_item.finding_alignment.summary.raw_signalsandfinding_alignment.summary.finding_alignment_raw_signals_total- raw finding/supporting-signal count derived from each evidence record'sraw_findings[]orcanonical_item.raw_group_size.finding_alignment.summary.canonical_itemsandfinding_alignment.summary.finding_alignment_canonical_items_total- count of evidence records carrying a canonical item.finding_alignment.summary.actionable_gaps,already_observed,internal_no_action,static_limitations,unknown,calibrated_supported, anduncalibrated- audit-local rollups ofcanonical_item.canonical_item_kind,gap_state,actionability, andconfidence.basis.finding_alignment.summary.presentation_text_*- presentation-text class-specific counts when those canonical items are present. These remain zero when the instant repo-exposure artifact has no presentation-text canonical items.finding_alignment.coverage.alignment_coverage_by_class- per-class raw finding, canonical item, state, and aligned/unaligned counts. The grain isevidence_class, usingcanonical_item.evidence_classwhen available and a conservative seam/raw-finding fallback otherwise. Rows also carrystatic_limitation_categoriesandstatic_limitation_repair_routesmaps so static-dominated classes keep their named analyzer limitation and repair route instead of collapsing to a genericstatic_unknownbucket.finding_alignment.coverage.unaligned_raw_findings_by_class- raw finding counts by class for evidence records that do not carrycanonical_item.finding_alignment.coverage.top_unaligned_examples- bounded examples of raw findings that did not align to a canonical item, for fixture-first follow-up selection. Each example includesevidence_class,file,line,kind,expression, andreasonso the next fixture can be selected from typed raw-finding context instead of Markdown prose.finding_alignment.coverage.same_line_duplicate_groups- bounded raw finding groups sharing one file and line so maintainers can spot remaining duplicate user-action risks. Each group includesfile,line,raw_findings,evidence_classes,kinds, andexample_expression.finding_alignment.coverage.evidence_class_work_queue- ranked evidence classes that still need Lane 1 work, derived from alignment coverage rows. Rows includework_score,dominant_signal, raw/canonical/actionable/ limitation/unknown/unaligned/duplicate counts, dominant static limitation category/count/repair route when present, andnext_repair. When static limitations dominate a class,next_repairis the dominant named limitation repair route. This is the audit-local "choose the next class from live output" queue.finding_alignment.coverage.static_unknown_without_named_limitation- count of static-unknown or limitation-shaped canonical items without a named static limitation category plus repair route. Genericstatic_unknownorunknowncategories do not satisfy the named-limitation requirement.finding_alignment.coverage.canonical_items_without_repair_routeandcanonical_items_without_verify_command- coverage counts for canonical items missing repair or verification guidance.finding_alignment.actionable_gap_top_lists- bounded top counts derived from canonical items, not raw findings. Each row is{label, count}sorted by descending count and then label. The section reports actionable gap classes, files, repair kinds, missing discriminator kinds, static limitation reasons on actionable gap records, verify-command unknowns by class, and repair-route unknowns by class so maintainers can choose the next fixture-backed repair slice from live evidence.finding_alignment.actionable_gap_packets- bounded top actionable canonical gap packets derived fromevidence_record.canonical_item. Packets are agent-safe work items: they carry stablecanonical_gap_ididentity, evidence class, repair kind,target_test_shape, related test or observer, verification command, receipt command, raw evidence references as supporting evidence, confidence basis, conservativemust_not_changeboundaries, andallowed_edit_surface[]file bounds. Derived edit surfaces must resolve to existing workspace files before public projection or swarm-ready ranking; a guessed or missing file is reported asmissing_allowed_edit_surface. Packets do not create user work from raw static class alone. A broad repo-exposure snapshot comparison verify command is not enough for swarm-ready routing unless RIPR can derive a narrowercargo test -p <package> <test-filter>command from a typedrelated_test_or_observerfile/name pair.seam_id,finding_id, and synthetic packet IDs can help internal diagnostics, but they do not satisfy public repair packet identity; missing canonical identity is reported asmissing_canonical_gap_id.raw_evidence_refs[]entries are structured evidence anchors. For public projection and swarm planning, at least one entry must carry an anchor field (file,path, orsource_file) and an identity field (kind,source_id,evidence_record_ref, orcanonical_gap_id). Empty objects, strings, counts, or other placeholders are treated asmissing_raw_evidence_refs.finding_alignment.actionable_gap_packet_public_projection- packet-level badge-readiness diagnostics for the emitted packet set. It counts public-projection eligible packets, excluded packets, and stableprojection_exclusion_reasonsrows such asnot_actionable_gap_state,missing_canonical_gap_id,missing_receipt_command,missing_repair_kind,missing_target_test_shape,missing_related_test_or_observer,missing_confidence,missing_must_not_change,missing_allowed_edit_surface,missing_raw_evidence_refs,unbounded_verify_command, andstatic_limitation_present. This is advisory report evidence only and does not change public badge endpoint semantics. Swarm planning treats explicit packet-field projection exclusions such asnot_actionable_gap_state,missing_repair_kind,missing_repair_route,missing_verify_command,unbounded_verify_command,missing_receipt_command,missing_must_not_change,missing_raw_evidence_refs,missing_related_test_or_observer, ormissing_confidenceas field-level blocked states even if stale actionability text, stale route text, stale command, boundary text, placeholder evidence, stale related target text, or stale confidence text is still present in the packet artifact.static_limitation_presentprojection exclusions are routed throughblocked_by_static_limitationeven when an older packet artifact also carries stale actionable-looking repair fields.finding_alignment.runtime_confidence_by_class- runtime confidence coverage rows at the canonical evidence-class grain. Each row reports canonical item count, calibrated-supported, fixture-backed, static-only, unknown-confidence, uncalibrated, actionable, and static-limitation counts so maintainers can see which classes still need runtime support before badge-readiness work.canonical_gap_groups.total- number of distinct canonical gap IDs among headline records.canonical_gap_groups.largest- top canonical groups by observed count, capped for review.duplicate_looking_groups- canonical or fallback groups with observed count greater than one, or a reported group size greater than one.missing_discriminator_classes- complete{label, count}rows by reason and value plus count maps by flow sink.static_limitations- complete{label, count}rows by limitation reason plus count maps by evidence stage, normalized category, and suggested repair route.oracle_semantics_distribution- complete{label, count}rows for rendered related-test oracle semantics plus oracle kind and strength counts. Free-form text counts are not object keys because discriminator, limitation, and oracle text can differ only by case, and Windows/PowerShell JSON consumers treat object keys case-insensitively.related_test_ranking- confidence and relation-reason counts for all rendered related tests and for the top related test per seam.movement_availability- counts of records carrying the identity and recommendation fields needed by before/after evidence movement.calibration_availability- counts of imported calibration placeholder fields fromevidence_record;runtime_confidence_by_classbreaks canonical items down bycanonical_item.evidence_class, confidence basis, actionability, and limitation state so badge-readiness work can see which classes remain static-only or unknown. This report does not import or execute calibration itself.evidence_record_field_health- per-field present, missing, null, and empty counts for keyevidence_recordcontract fields.top_files_by_unresolved_evidence_debt- top files by an audit-local debt score that combines headline gaps, missing discriminators, static limitations, unknown stages, no related tests, low/opaque top related tests, and missing evidence records.
The Markdown sibling prints the same audit areas in bounded tables. JSON keeps the complete count maps.
Actionable Gap Packets
cargo xtask lane1-evidence-audit also writes a bounded packet projection for
humans and agents:
target/ripr/reports/actionable-gaps.json
target/ripr/reports/actionable-gaps.md
The packet artifact is advisory and derives from the Lane 1 audit's
evidence_record.canonical_item projection. It does not change public badge
semantics, PR/CI rendering, gate policy, provider calls, generated tests, or
mutation execution.
The Markdown sibling includes a Runtime Status table with the same
completeness fields as JSON so human readers can see whether packet counts are
full or limited before acting on them.
static_limitation_backlog carries the same named limitation categories and
analyzer repair routes from the source Lane 1 audit so downstream swarm
surfaces can explain why no packet is safely actionable without turning those
limitations into user repair work.
For top_categories[], repair_route is the dominant route from the
route-grained backlog packets for that category when packet evidence exists;
otherwise it uses the category fallback route.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "actionable-gaps",
"scope": "repo",
"status": "advisory",
"run_status": "full",
"runtime_status": {
"state": "full",
"phase": null,
"duration_ms": null,
"limit_ms": null,
"input_kind": null,
"input_path": null,
"limitation_category": null,
"repair_route": null,
"downstream_consumable": true
},
"source_report": "target/ripr/reports/lane1-evidence-audit.json",
"source": "evidence_record.canonical_item",
"packet_limit": 25,
"summary": {
"raw_signals": 47515,
"canonical_items": 38445,
"actionable_gaps": 162,
"already_observed": 12006,
"internal_no_action": 0,
"static_limitations": 26277,
"packets_emitted": 25,
"public_projection_eligible_packets": 25,
"public_projection_excluded_packets": 0,
"projection_exclusion_reasons": [],
"raw_to_canonical_ratio": 1.24,
"repair_route_unknowns": 0,
"verify_command_unknowns": 0
},
"run_limitations": [],
"static_limitation_backlog": {
"source": "lane1-evidence-audit.static_limitations",
"top_categories": [
{
"category": "activation_boundary_input_unresolved",
"count": 297,
"repair_route": "analysis/local-computed-boundary-operand-resolution"
}
],
"top_subroutes": [
{
"category": "activation_owner_call_absent_call_presence_target_affinity",
"subroute": "bare_alias_unsupported",
"count": 12,
"repair_route": "analysis/call-presence-target-affinity-owner-call-tracing"
}
],
"top_repair_routes": [
{
"repair_route": "analysis/local-computed-boundary-operand-resolution",
"count": 297
}
],
"limitation_backlog_packets": [
{
"packet_id": "limitation:activation_boundary_input_unresolved:analysis-local-computed-boundary-operand-resolution",
"limitation_category": "activation_boundary_input_unresolved",
"limitation_subroute": "activation_boundary_input_unresolved",
"repair_route": "analysis/local-computed-boundary-operand-resolution",
"signal_count": 297,
"sample_canonical_gap_ids": ["gap:idx-offset-local"],
"sample_sources": [
{
"canonical_gap_id": "gap:idx-offset-local",
"evidence_class": "predicate_boundary",
"source_file": "src/window.rs",
"line": 44,
"expression": "idx >= offset",
"limitation_reason": "local/computed operand cannot be mapped to a safe test input"
}
],
"dominant_evidence_class": "predicate_boundary",
"why_not_actionable": "activation inputs cannot yet be mapped to a safe concrete test value",
"unlock_condition": "implement `analysis/local-computed-boundary-operand-resolution` so local, member-access, iterator, or computed operands can be resolved before candidate values are recommended",
"non_claims": [
"not a public repair packet",
"not swarm-ready work",
"do not edit tests from this backlog item alone",
"do not invent exact candidate values",
"do not invent exact boundary candidate values"
]
}
]
},
"packets": [
{
"canonical_gap_id": "gap:abc",
"evidence_class": "predicate_boundary",
"gap_state": "actionable",
"actionability": "extend_related_test",
"source_file": "src/pricing.rs",
"primary_anchor": {"file": "src/pricing.rs", "line": 42},
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(price(/* boundary input where amount == threshold */), expected)",
"repair_route": {
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(price(/* boundary input where amount == threshold */), expected)"
},
"recommended_repair": "Add or strengthen `assert_eq!(price(/* boundary input where amount == threshold */), expected)` for `input that hits the boundary: amount == threshold` in `tests/pricing.rs` as `price_boundary_discriminator`.",
"why": "Related tests reach the seam but miss equality at the threshold.",
"related_test_or_observer": {
"file": "tests/pricing.rs",
"name": "below_threshold_has_no_discount",
"line": 10
},
"candidate_value_or_observer": "input that hits the boundary: amount == threshold",
"missing_discriminators": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate"
}
],
"verify_command": "cargo xtask evidence-quality-scorecard",
"repair_route_source": "canonical_item.repair_route",
"verify_command_source": "canonical_item.verify_command",
"receipt_command_or_path": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id probe:src_pricing_rs:42:predicate_boundary --json --out target/ripr/reports/agent-receipt.json",
"receipt_source": "canonical_item.receipt_command",
"public_projection_eligible": true,
"projection_exclusion_reasons": [],
"raw_findings": [
{"file": "src/pricing.rs", "line": 42, "kind": "weakly_exposed"}
],
"raw_findings_supporting_only": true,
"static_limitations": [],
"confidence_basis": "static_only",
"must_not_change": [
"Do not infer actionability from raw static class."
],
"allowed_edit_surface": [
"tests/pricing.rs"
]
}
],
"must_not_infer": [
"raw findings are supporting evidence, not user work",
"do not infer actionability from raw static class",
"do not treat named static limitations as user test debt",
"do not claim mutation execution or runtime proof from this packet"
]
}
The packet grain is one canonical actionable item. raw_findings[] is included
only to preserve supporting evidence and line context; downstream consumers must
not fan it back out into separate user-facing work.
missing_discriminators[] carries the exact unresolved discriminator facts from
the evidence record so agents do not have to infer the boundary or assertion
target from a broader candidate-value hint.
public_projection_eligible is an audit-only badge-readiness decision for the
emitted packet. It is true only when the packet has public-projection
prerequisites such as gap_state = "actionable", canonical repair and verify
fields plus a receipt command or path; otherwise the stable
projection_exclusion_reasons[] values explain why an otherwise useful agent
packet is not yet a public badge item. This does not change committed badge
endpoint semantics.
Canonical evidence-record items carry additive command_specs.verify and
command_specs.receipt CommandSpec objects when RIPR owns those routes.
GapRecord-derived gap-ledger and agent-packet queue projections carry those
objects only when the producer supplied them; legacy display strings are never
parsed back into machine authority. A legacy string-only GapRecord remains
readable, but its typed command collections are omitted until a producer-owned
spec is available. LSP gap-artifact validation accepts the object form and
compatibility array form, but rejects non-object command_specs containers,
malformed specs, and role-mismatched specs before projection.
This producer-owned projection boundary is distinct from the explicit
agent verify-execute surface below. GapRecord packet rendering does not
reconstruct typed routes from compatibility display strings; a consumer that
requires direct execution must apply its own execution-route consistency and
provenance checks before running a command.
RIPR Swarm Plan
cargo xtask ripr-swarm plan --top <n> ranks existing actionable canonical gap
packets for a bounded, dry-run repair loop:
target/ripr/reports/swarm-plan.json
target/ripr/reports/swarm-plan.md
The command reads target/ripr/reports/actionable-gaps.json by default, or the
path supplied by --actionable-gaps. It is report-only. It does not edit files,
run tests, call providers, generate tests, create receipts, run mutation
testing, change PR/CI rendering, change editor/LSP behavior, change gates, or
change public badges.
blocked_state_examples[] is not top-limit truncated; it gives readiness one
sample packet per blocked packet class where the plan has source data.
For compatibility with current actionable-gap packets, input may carry either
receipt_command_or_path or receipt_command. The swarm plan normalizes the
ranked packet output to receipt_command. A packet is not swarm-ready unless it
also carries a structured repair_route object and a typed workspace-relative
repair target in related_test_or_observer or candidate_value_or_observer.
If the actionable-gaps input is missing or malformed, the command still writes
a bounded blocked report with the input path, input state, and limitation text.
It does not silently drop the plan or infer work from stale Markdown.
The Markdown sibling includes a Runtime Status table with the same
completeness fields as JSON before listing plan inputs.
static_limitation_backlog is copied from the actionable-gap source audit so
operators can see which named analyzer limitations are blocking routeable
packets. It is backlog routing evidence only; it must not be counted as
repair-ready packet work.
static_limitation_backlog.limitation_backlog_packets[] turns top limitation
routes into analyzer work packets with sample IDs, source file, optional line,
expression, limitation reason, dominant evidence class, unlock condition, and
non-claims. limitation_subroute names the more specific analyzer bucket when a
category is still too broad, such as target-affinity owner-call cases that are
blocked by unsupported alias or ambiguity shapes. Packet identity is route- and
subroute-grained: the same limitation category can emit separate backlog packets
for separate analyzer repair routes or named subroutes. These packets are not
public repair packets and must not enter the swarm-ready queue.
The summary.static_limitation_packets count is limited to public repair
packets that carry static limitations. summary.static_limitation_backlog_packets
and summary.static_limitation_backlog_signals summarize the separate analyzer
backlog so consumers can route analyzer work even when no public repair packets
are emitted.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "swarm-plan",
"scope": "repo",
"status": "advisory",
"input": {
"actionable_gaps": "target/ripr/reports/actionable-gaps.json",
"state": "read",
"limitation": null
},
"source": "actionable-gaps.packets",
"source_summary": {
"raw_signals": 47515,
"canonical_items": 38445,
"actionable_gaps": 162,
"packets_emitted": 25
},
"static_limitation_backlog": {
"source": "lane1-evidence-audit.static_limitations",
"top_categories": [
{
"category": "activation_value_unresolved",
"count": 141,
"repair_route": "analysis/value-resolution-audit-fixes"
}
],
"top_subroutes": [
{
"category": "activation_value_unresolved",
"subroute": "activation_value_unresolved",
"count": 141,
"repair_route": "analysis/value-resolution-audit-fixes"
}
],
"top_repair_routes": [
{
"repair_route": "analysis/value-resolution-audit-fixes",
"count": 141
}
]
},
"top_limit": 10,
"summary": {
"packets_total": 25,
"swarm_ready_packets": 10,
"blocked_packets": 15,
"blocked_by_missing_context_packets": 12,
"blocked_by_static_limitation_packets": 2,
"blocked_by_public_projection_exclusion_packets": 0,
"blocked_by_operator_judgment_packets": 1,
"public_projection_excluded_packets": 0,
"missing_canonical_gap_id": 0,
"missing_verify_command": 0,
"missing_receipt_command": 0,
"missing_repair_kind": 0,
"missing_repair_route": 0,
"missing_target_test_shape": 0,
"missing_must_not_change": 0,
"missing_allowed_edit_surface": 0,
"missing_confidence": 0,
"missing_raw_evidence_refs": 0,
"missing_related_test_or_observer": 3,
"related_context_missing": 3,
"static_limitation_packets": 2,
"static_limitation_backlog_packets": 6,
"static_limitation_backlog_signals": 141,
"high_confidence_packets": 4
},
"blocked_state_examples": [
{
"state": "missing_canonical_gap_id",
"example_packet_id": "packet:missing-canonical-gap-id",
"example_canonical_gap_id": "packet-fallback-seam-id",
"example_repair_kind": "add_boundary_assertion",
"example_missing_context": ["canonical_gap_id"],
"example_projection_exclusion_reasons": ["missing_canonical_gap_id"],
"example_blocked_reasons": ["missing_canonical_gap_id"]
},
{
"state": "missing_target_test_shape",
"example_packet_id": "packet:missing-target-test-shape",
"example_canonical_gap_id": "gap:missing-target-test-shape",
"example_repair_kind": "add_boundary_assertion",
"example_missing_context": ["target_test_shape"],
"example_projection_exclusion_reasons": [],
"example_blocked_reasons": ["missing_target_test_shape"]
},
{
"state": "missing_allowed_edit_surface",
"example_packet_id": "packet:missing-edit-surface",
"example_canonical_gap_id": "gap:missing-edit-surface",
"example_repair_kind": "add_boundary_assertion",
"example_missing_context": ["allowed_edit_surface"],
"example_projection_exclusion_reasons": [],
"example_blocked_reasons": ["missing_context"]
}
],
"top_ready_packets": [
{
"packet_id": "gap:abc",
"canonical_gap_id": "gap:abc",
"evidence_class": "predicate_boundary",
"source_file": "src/pricing.rs",
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(price(/* boundary */), expected)",
"confidence_basis": "fixture_backed",
"swarm_state": "queued",
"score": 110,
"expected_canonical_gap_delta": 1,
"readiness_reasons": [
"repair_route_present",
"verify_command_present",
"receipt_command_present",
"related_test_or_observer_present",
"must_not_change_present",
"allowed_edit_surface_present",
"public_projection_eligible",
"no_static_limitation",
"confidence_basis_fixture_backed"
],
"blocked_reasons": [],
"missing_context": [],
"verify_command": "cargo xtask evidence-quality-scorecard",
"receipt_command": "cargo xtask receipts check",
"allowed_edit_surface": ["tests/pricing.rs"],
"allowed_edit_surface_count": 1,
"related_test_or_observer_available": true,
"must_not_change": ["production behavior"],
"must_not_change_count": 1,
"raw_findings_count": 2,
"raw_findings_supporting_only": true,
"static_limitations_count": 0,
"public_projection_eligible": true,
"projection_exclusion_reasons": []
}
],
"top_blocked_packets": [],
"top_missing_verify_or_receipt": [],
"must_not_infer": [
"do not consume raw findings as swarm work",
"do not rank static limitations as repair-ready",
"do not rank static-only predicate-boundary packets as swarm-ready without stronger evidence",
"do not rank packets without receipt_command as swarm-ready",
"do not rank packets without verify_command as high confidence",
"do not edit files, call providers, generate tests, run mutation testing, or create receipts from this plan"
]
}
swarm_state = queued means the packet is ready for a bounded dry-run repair
attempt. Queued packets require a structured repair_route object, a typed
workspace-relative related_test_or_observer or candidate_value_or_observer
target, and an allowed_edit_surface[] entry that resolves to an existing
workspace file. Candidate prose, repair_route_source hints, and top-level
repair-shape strings remain supporting context only; they do not authorize file
edits or swarm-ready ranking by themselves. Packets missing required typed
context use blocked_by_missing_context. Packets with static limitations use
blocked_by_static_limitation. Packets excluded from the public actionable
projection use blocked_by_public_projection_exclusion; a non-empty
projection_exclusion_reasons[] array is blocking even if a stale producer also
sets public_projection_eligible = true. Static-only
predicate-boundary assertion packets use blocked_by_operator_judgment; they
remain visible but are not default
swarm-ready until upstream evidence is fixture-backed, calibrated, or explicitly
operator-selected. Ranking is advisory and never redefines actionability; it
starts from the canonical packet state already emitted by Lane 1.
projection_exclusion_reasons[] includes unbounded_verify_command when the
packet's only verify route is a broad ripr agent verify repo-exposure snapshot
comparison. Those commands require separately generating before/after
repo-exposure artifacts and are not a bounded proof command for agent-safe
repair delegation. swarm-plan treats this as a verify-command field blocker
and also applies this exclusion when reading older artifacts that predate the
reason, so legacy packets do not remain swarm-ready solely because they carry
the old broad verify command.
summary.public_projection_exclusion_reasons[] is a stable reason-count
breakdown for packets routed through blocked_by_public_projection_exclusion.
Readiness preserves the same rows so operators can inspect the dominant
projection policy reason instead of treating all public-projection exclusions as
one generic blocked bucket.
RIPR Swarm Attempt Dry Run
cargo xtask ripr-swarm attempt --packet <id> --dry-run reads
target/ripr/reports/actionable-gaps.json by default, or the path supplied by
--actionable-gaps, and prints bounded packet context to stdout. The packet id
can be a packet_id, canonical_gap_id, or compatible unprefixed canonical
identifier. The command does not edit files, run tests, call providers,
generate tests, create receipts, run mutation testing, merge code, or change
public badge semantics.
The dry-run output includes:
copy-ready operator packet
task
allowed files
do-not-change boundaries
repair target
verify command
receipt command
stop conditions
required return format
canonical_gap_id
evidence_class
source_file
swarm_state
confidence_basis
repair_kind
repair_route
target_test_type
assertion_or_observer_shape
related_test_or_observer
expected_evidence_movement
verify_command
receipt_command_or_path
must_not_change boundaries
raw_findings_count
static_limitations_count
queued packets show the expected canonical-gap delta if receipt-backed
evidence movement resolves or improves the item. Blocked packets remain visible
with their blocked_by_missing_context or blocked_by_static_limitation state
or blocked_by_public_projection_exclusion or blocked_by_operator_judgment
state and are not promoted to repair-ready work.
Actionable Gap Outcomes
cargo xtask actionable-gap-outcomes joins actionable-gap packets with optional
agent receipt and targeted-test outcome artifacts:
target/ripr/reports/actionable-gap-outcomes.json
target/ripr/reports/actionable-gap-outcomes.md
The report is advisory. It does not run repairs, generate tests, execute mutation testing, change PR/CI rendering, or change public badge semantics.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "actionable-gap-outcomes",
"scope": "repo",
"status": "advisory",
"source": "actionable-gaps plus optional receipt and targeted-test outcome artifacts",
"inputs": {
"actionable_gaps": "target/ripr/reports/actionable-gaps.json",
"agent_receipt": "target/ripr/reports/agent-receipt.json",
"targeted_test_outcome": "target/ripr/reports/targeted-test-outcome.json"
},
"summary": {
"packets_total": 25,
"outcomes_total": 25,
"not_attempted": 22,
"attempted_no_receipt": 0,
"receipt_present": 0,
"evidence_improved": 1,
"evidence_unchanged": 1,
"evidence_regressed": 0,
"resolved": 1,
"unknown": 0,
"receipts_present": 1,
"receipts_missing_after_input": 24,
"orphaned_receipts": 1
},
"movement_front": {
"current_actionable_count": 25,
"receipt_linked_actionable_delta": -1,
"resolved": 1,
"improved": 1,
"unchanged_after_attempt": 1,
"missing_receipts": 24,
"orphaned_receipts": 1,
"top_blocked_reason": "missing_receipts"
},
"outcomes": [
{
"canonical_gap_id": "gap:abc",
"evidence_class": "predicate_boundary",
"repair_kind": "add_boundary_assertion",
"source_file": "src/pricing.rs",
"verify_command": "ripr agent verify --root . --before before.json --after after.json --json",
"verify_result": "pass",
"receipt_command": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id abc --json --out target/ripr/reports/agent-receipt.json",
"receipt_command_or_path": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id abc --json --out target/ripr/reports/agent-receipt.json",
"receipt_state": "receipt_movement_improved",
"outcome_state": "evidence_improved",
"timestamp": "unix_ms:1778240100000",
"attempt_instance": "timestamp:unix_ms:1778240100000",
"seam_id": "abc",
"before": "weakly_gripped",
"after": "strongly_gripped",
"movement_source": "agent_receipt",
"movement_direction": "improved",
"evidence_delta": [
"missing discriminator no longer reported: threshold equality"
],
"reason": "Matched agent receipt artifact."
}
],
"orphaned_receipts": [
{
"receipt_id": "receipt:old-gap",
"seam_id": "old-gap",
"source_file": "src/old.rs",
"line": 7,
"movement_direction": "improved",
"reason": "Receipt artifact did not match any current actionable canonical gap packet."
}
],
"must_not_infer": [
"outcome reports join existing artifacts; they do not execute repairs",
"raw findings remain supporting evidence, not user work",
"targeted-test outcomes are static evidence movement, not mutation proof",
"missing receipts do not imply a repair failed",
"orphaned receipts do not create new actionable gaps"
]
}
outcome_state uses the bounded Lane 1 lifecycle states
not_attempted, attempted_no_receipt, receipt_present,
evidence_improved, evidence_unchanged, evidence_regressed, resolved,
and unknown. Raw findings do not determine outcome state; the join is based
on canonical packet identity, seam identity, or the packet primary anchor.
timestamp and attempt_instance carry stable attempt identity when an
outcome is backed by a matching receipt or targeted-test outcome. The attempt
instance prefers a receipt/targeted timestamp when available, then the matched
receipt artifact path, then the targeted-test outcome artifact path; missing
identity remains null for not-attempted packets.
Targeted-test outcome movement without a matching receipt is classified as
attempted_no_receipt; its movement fields remain visible for debugging, but it
does not count as evidence_improved, evidence_unchanged,
evidence_regressed, or resolved until receipt evidence is joined.
receipt_command is the normalized command for downstream consumers;
receipt_command_or_path remains as compatibility for older packet artifacts.
verify_result is optional typed evidence copied from matching receipt or
targeted-test outcome artifacts. Missing values remain null; RIPR must not
infer a passing result from a present verify_command.
receipt_state uses the canonical receipt lifecycle vocabulary:
receipt_missing, receipt_found, receipt_stale,
receipt_gap_mismatch, receipt_movement_improved,
receipt_movement_unchanged, or receipt_not_applicable.
movement_front is the first-screen outcome summary. It reports the current
actionable packet count, receipt-linked actionable delta, resolved/improved
movement, unchanged attempts, missing/orphaned receipts, and the top follow-up
blocker. The delta is receipt-linked static movement only: it is not mutation
confirmation, runtime adequacy, policy eligibility, gate passage, or merge
readiness.
orphaned_receipts[] preserves receipt artifacts that do not match any current
packet so attempt history remains visible without creating new actionable gaps.
RIPR Swarm Attempt Ledger
cargo xtask ripr-swarm attempt-ledger joins the swarm plan,
actionable-gap outcome report, optional real repair attempts, and prior ledger
into durable attempt history:
target/ripr/reports/swarm-attempt-ledger.json
target/ripr/reports/swarm-attempt-ledger.md
The command reads target/ripr/reports/swarm-plan.json,
target/ripr/reports/actionable-gap-outcomes.json, any existing
target/ripr/reports/swarm-attempt-ledger.json, and
fixtures/real-repair-attempts/corpus.json by default. The real-repair-attempts
input is advisory dogfood evidence; it is imported as attempt history and route
quality, not as a new public repair packet. The command preserves prior durable
attempt entries by attempt_id, drops stale synthetic not_attempted
placeholders when their packet is no longer present in the current swarm plan,
adds the current outcome join, imports real dogfood attempts, and highlights the
latest attempt per canonical_gap_id. It does not execute repairs, edit files,
run tests, create receipts, call providers, run mutation testing, change PR/CI
rendering, change editor/LSP behavior, change gates, or change public badges.
The Markdown sibling includes a Runtime Status table with the same
completeness fields as JSON before listing ledger inputs. attempted_no_receipt
entries may carry missing_receipt_reason so receipt reliability failures remain
actionable operator evidence instead of only route-quality counts.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "swarm-attempt-ledger",
"scope": "repo",
"status": "advisory",
"run_status": "full",
"runtime_status": {
"state": "full",
"phase": null,
"duration_ms": null,
"limit_ms": null,
"input_kind": null,
"input_path": null,
"limitation_category": null,
"repair_route": null,
"downstream_consumable": true
},
"generated_at": "unix_ms:1778240100000",
"inputs": {
"swarm_plan": {
"path": "target/ripr/reports/swarm-plan.json",
"state": "read",
"limitation": null
},
"actionable_gap_outcomes": {
"path": "target/ripr/reports/actionable-gap-outcomes.json",
"state": "read",
"limitation": null
},
"prior_ledger": {
"path": "target/ripr/reports/swarm-attempt-ledger.json",
"state": "read",
"limitation": null
},
"real_repair_attempts": {
"path": "fixtures/real-repair-attempts/corpus.json",
"state": "read",
"limitation": null
}
},
"summary": {
"attempts_total": 4,
"canonical_gaps_total": 3,
"not_attempted": 1,
"attempted_no_receipt": 0,
"receipt_present": 0,
"missing_verify_result": 0,
"evidence_improved": 2,
"evidence_unchanged": 1,
"expected_unchanged": 0,
"evidence_regressed": 0,
"resolved": 0,
"unknown": 0,
"orphaned_receipts": 1
},
"attempt_history_summary": {
"attempts_total": 5,
"durable_attempts_total": 4,
"canonical_gaps_total": 3,
"not_attempted": 1,
"attempted_no_receipt": 1,
"receipt_present": 0,
"missing_verify_result": 0,
"evidence_improved": 2,
"evidence_unchanged": 1,
"expected_unchanged": 0,
"evidence_regressed": 0,
"resolved": 0,
"unknown": 0
},
"repair_route_quality": [
{
"language": null,
"repair_kind": "add_boundary_assertion",
"repair_kind_attempted": 2,
"repair_kind_improved": 1,
"repair_kind_unchanged": 1,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 1,
"repair_kind_dominant_failure_reason": "unchanged",
"repair_kind_success_rate": 0.5,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": []
}
],
"language_repair_route_quality": [
{
"language": "typescript",
"repair_kind": "sharpen_static_limitation_route",
"repair_kind_attempted": 1,
"repair_kind_improved": 1,
"repair_kind_unchanged": 0,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 0,
"repair_kind_dominant_failure_reason": null,
"repair_kind_success_rate": 1.0,
"sample_packet_ids": ["packet-ts-route-001"],
"sample_attempt_ids": ["attempt-ts-route-001"],
"sample_canonical_gap_ids": ["gap:ts-route"],
"sample_missing_receipt_reasons": []
}
],
"historical_repair_route_quality": [
{
"language": null,
"repair_kind": "add_boundary_assertion",
"repair_kind_attempted": 3,
"repair_kind_improved": 2,
"repair_kind_unchanged": 1,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 1,
"repair_kind_dominant_failure_reason": "unchanged",
"repair_kind_success_rate": 0.667,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": []
}
],
"historical_language_repair_route_quality": [
{
"language": "typescript",
"repair_kind": "sharpen_static_limitation_route",
"repair_kind_attempted": 2,
"repair_kind_improved": 2,
"repair_kind_unchanged": 0,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 0,
"repair_kind_dominant_failure_reason": null,
"repair_kind_success_rate": 1.0,
"sample_packet_ids": ["packet-ts-route-001"],
"sample_attempt_ids": ["attempt-ts-route-001"],
"sample_canonical_gap_ids": ["gap:ts-route"],
"sample_missing_receipt_reasons": []
}
],
"top_failing_repair_routes": [
{
"language": null,
"repair_kind": "add_boundary_assertion",
"repair_kind_attempted": 2,
"repair_kind_improved": 1,
"repair_kind_unchanged": 1,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 1,
"repair_kind_dominant_failure_reason": "unchanged",
"repair_kind_success_rate": 0.5,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": []
}
],
"top_historical_failing_repair_routes": [
{
"language": null,
"repair_kind": "add_boundary_assertion",
"repair_kind_attempted": 3,
"repair_kind_improved": 2,
"repair_kind_unchanged": 1,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 1,
"repair_kind_dominant_failure_reason": "unchanged",
"repair_kind_success_rate": 0.667,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": []
}
],
"repair_route_quality_backlog": [
{
"packet_id": "route-quality:add-boundary-assertion:unchanged",
"repair_kind": "add_boundary_assertion",
"improvement_route": "analysis/repair-route-guidance/add-boundary-assertion",
"failure_count": 1,
"dominant_failure_reason": "unchanged",
"dominant_failure_count": 1,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": [],
"why_action_required": "`add_boundary_assertion` produced unchanged evidence; refine target shape, assertion guidance, or evidence expectations before increasing packet volume",
"unlock_condition": "update `add_boundary_assertion` guidance so a future attempt can produce evidence_improved or resolved instead of evidence_unchanged",
"non_claims": [
"not a public repair packet",
"not swarm-ready work",
"do not retry this repair kind from this backlog item alone",
"do not promote or downgrade actionability from route-quality evidence alone",
"do not change badge or gate semantics from route-quality evidence alone"
]
}
],
"top_missing_evidence_fields": [
{
"label": "receipt_command",
"count": 1,
"sample_packet_ids": ["packet-boundary-001"],
"sample_canonical_gap_ids": ["gap:abc"],
"sample_repair_kinds": ["add_boundary_assertion"]
}
],
"attempts": [
{
"packet_id": "packet-boundary-001",
"canonical_gap_id": "gap:abc",
"attempt_id": "attempt:gap-abc:evidence-improved:receipt-movement-improved:agent-receipt:abc:timestamp-unix-ms-1778240100000",
"evidence_class": "predicate_boundary",
"source_file": "src/pricing.rs",
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(discounted_total(threshold), expected)",
"actor_kind": "agent",
"receipt_path": "target/ripr/reports/agent-receipt.json",
"verify_command": "cargo test -p ripr boundary_gap",
"verify_result": "pass",
"receipt_command": "cargo xtask receipts write --packet packet-boundary-001",
"missing_receipt_reason": null,
"before_gap_state": "weakly_gripped",
"after_gap_state": "strongly_gripped",
"outcome": "evidence_improved",
"timestamp": "unix_ms:1778240100000",
"receipt_state": "receipt_movement_improved",
"movement_source": "agent_receipt",
"route_quality_expectation": null,
"reason": "Matched agent receipt artifact."
}
],
"latest_attempts": [
{
"packet_id": "packet-boundary-001",
"canonical_gap_id": "gap:abc",
"attempt_id": "attempt:gap-abc:evidence-improved:receipt-movement-improved:agent-receipt:abc:timestamp-unix-ms-1778240100000",
"evidence_class": "predicate_boundary",
"source_file": "src/pricing.rs",
"repair_kind": "add_boundary_assertion",
"target_test_type": "boundary_discriminator",
"assertion_shape": "assert_eq!(discounted_total(threshold), expected)",
"actor_kind": "agent",
"receipt_path": "target/ripr/reports/agent-receipt.json",
"verify_command": "cargo test -p ripr boundary_gap",
"verify_result": "pass",
"receipt_command": "cargo xtask receipts write --packet packet-boundary-001",
"missing_receipt_reason": null,
"before_gap_state": "weakly_gripped",
"after_gap_state": "strongly_gripped",
"outcome": "evidence_improved",
"timestamp": "unix_ms:1778240100000",
"receipt_state": "receipt_movement_improved",
"movement_source": "agent_receipt",
"route_quality_expectation": null,
"reason": "Matched agent receipt artifact."
}
],
"orphaned_receipts": [
{
"receipt_id": "receipt:old-gap",
"seam_id": "old-gap",
"reason": "Receipt artifact did not match any current actionable canonical gap packet."
}
],
"must_not_infer": [
"attempt ledgers preserve existing artifact joins; they do not execute repairs",
"not_attempted means no matching attempt artifact was supplied, not that repair failed",
"receipt_present without movement is not evidence improvement",
"orphaned receipts do not create new actionable gaps",
"repair-route quality is grouped from latest attempts by repair_kind; it is not a ranking gate",
"ledger counts do not change public badge semantics or CI gate mode"
]
}
attempts[] is durable history plus current-plan queue placeholders.
latest_attempts[] is the current routing view, one entry per canonical gap,
and is the source readiness uses for
attempt/improved/unchanged/regressed/resolved counts. The ledger preserves
current top_ready_packets[] as synthetic not_attempted queue placeholders
until a receipt or outcome row replaces them. It preserves
attempted_no_receipt, receipt_present, evidence_improved,
evidence_unchanged, evidence_regressed, resolved, and unknown outcomes.
summary is the latest-projection state used for current routing, except
summary.attempts_total, which reports the durable row count for operator
visibility. attempt_history_summary counts full durable attempts[] history
before latest-attempt collapse and is the place to inspect prior unchanged,
no-receipt, regressed, or expected-unchanged outcomes that were superseded by a
newer current attempt.
It preserves prior not_attempted rows only when they remain tied to the current
swarm plan or carry durable receipt/verification evidence; stale synthetic
not_attempted placeholders are dropped so retired packets do not create
route-quality or missing-field noise. Missing outcome inputs make the ledger
limited_incomplete_input; readable-but-limited outcome inputs keep their
limited runtime_status instead of becoming a clean full ledger. Missing
swarm-plan input is consumable but explicitly limited because packet ids may be
less complete.
verify_result is preserved when supplied by outcome or prior-ledger rows.
Attempted rows with no verify_result contribute to
summary.missing_verify_result and to top_missing_evidence_fields[] as
verify_result.
route_quality_expectation = "expected_unchanged_negative_capability" keeps an
evidence_unchanged attempt visible while marking the unchanged result as the
expected trust-boundary outcome. When such an attempt is the latest row for its
canonical gap, it increments summary.expected_unchanged and
repair_kind_expected_unchanged; it does not contribute to
repair_kind_failure_count, top failing repair routes, or route-quality backlog
packets. If a newer improved or resolved attempt supersedes it, the expected
unchanged row remains in durable attempts[] history but no longer affects
latest-route quality counts. It still contributes to
attempt_history_summary.expected_unchanged.
Generated attempt_id values include a stable attempt-instance suffix when the
outcome carries one, preferring explicit outcome attempt_instance, then
outcome timestamp, then receipt artifact path, then targeted-test-outcome
artifact path. This keeps repeated same-state attempts visible without creating
a new history row from a plain ledger rerun over the same artifacts.
repair_route_quality[] is grouped from latest attempts by repair_kind and
reports attempted, improved, unchanged, regressed, resolved, no-receipt,
receipt-only, missing-verify-result, expected-unchanged, unknown, and
success-rate counts.
Rows include language = null because they are repo-level repair-kind rollups.
language_repair_route_quality[] is the additive language-scoped projection
grouped by language and repair_kind for attempts that carry a known language
field. It lets TypeScript/JavaScript preview route outcomes be measured without
promoting preview evidence into public repair packets, badge inputs, or gates.
historical_repair_route_quality[] and
historical_language_repair_route_quality[] use the same row shape over the
durable full attempt history instead of the latest-attempt projection. They keep
older unchanged, regressed, and no-receipt attempts visible after a later
follow-up improves or resolves the same canonical gap. They are audit evidence;
current routing still comes from latest-attempt repair_route_quality[].
top_failing_repair_routes[] is the subset with unexpected unchanged,
regressed, no-receipt, missing-verify-result, or unknown outcomes,
ordered for analyzer-improvement routing. Repair-route quality rows include
sample packet IDs, attempt IDs, and canonical gap IDs for representative attempted rows when
available, so successful and failing route metrics both remain inspectable.
top_failing_repair_routes[] and repair_route_quality_backlog[] still derive
their routing from failing attempts and preserve the concrete failed-attempt
sample in both next_actions[].attempt_id and the reason text when available.
repair_route_quality_backlog[] converts
top failing repair routes into analyzer/report backlog packets with stable
packet IDs, improvement routes, unlock conditions, samples, and non-claims; the
rows are not public repair packets, are not swarm-ready work, and do not promote
or downgrade actionability by themselves.
top_historical_failing_repair_routes[] applies the same failing-route ordering
to durable history. It is for route-learning audits and must not be used as the
current next action when the latest-attempt projection has already improved or
resolved the route.
When sample_missing_receipt_reasons[] shows that no-receipt attempts timed
out before receipt capture, readiness routes that sample to the bounded
verify-route improve_repair_route_quality action instead of generic
collect_missing_attempt_receipts. Ordinary missing receipts still route to
receipt collection.
top_missing_evidence_fields[]
counts missing route/verify/receipt fields that prevent route-quality analysis
and includes sample packet IDs, canonical gap IDs, and repair kinds when the
row is derived from attempts. Legacy label/count-only rows remain readable and
default sample arrays to empty.
repair_kind_failure_count is the sum of unexpected unchanged, regressed,
no-receipt, missing-verify-result, and unknown latest attempts. Expected
unchanged negative-capability rows remain counted in repair_kind_unchanged
and repair_kind_expected_unchanged, but are excluded from failure routing.
repair_kind_dominant_failure_reason is the highest-count failing bucket, with
deterministic tie preference for regressed, missing-verify-result, unchanged,
no-receipt, then unknown.
The Markdown attempt-ledger and readiness repair-route quality tables include
both fields so human readers see the same failure explanation as JSON
consumers.
RIPR Swarm Readiness
cargo xtask ripr-swarm readiness rolls up the existing swarm plan,
actionable-gap outcomes, and swarm attempt ledger into a repo-level
repair-coordination readiness report:
target/ripr/reports/swarm-readiness.json
target/ripr/reports/swarm-readiness.md
The command reads target/ripr/reports/swarm-plan.json and
target/ripr/reports/actionable-gap-outcomes.json and
target/ripr/reports/swarm-attempt-ledger.json by default, or the paths
provided by --swarm-plan, --actionable-gap-outcomes, and
--attempt-ledger. It is report-only. It does not execute repairs, edit files,
run tests, call providers, generate tests, create receipts, run mutation
testing, change PR/CI rendering, change editor/LSP behavior, change gates, or
change public badges.
If swarm-plan.json is missing or malformed, the report is blocked with a
bounded input limitation. If actionable-gap-outcomes.json or
swarm-attempt-ledger.json is missing, the report records the limitation and
routes the operator to regenerate the missing artifact; missing outcomes or
ledger inputs do not imply failed attempts. They do make readiness
non-consumable for downstream attempt/outcome claims until the missing artifact
is regenerated.
Swarm plan, attempt-ledger, and readiness reports include run_status and
runtime_status. Readiness also includes readiness_state, a coarse
user-facing class with one of full, limited, stale, or blocked.
readiness_state is additive: consumers that need the exact runtime limitation
should continue reading run_status and runtime_status. Readiness preserves
limited swarm-plan, actionable-gap
outcome, and attempt-ledger inputs, and reports missing or malformed required
plan input as limited_incomplete_input instead of turning absent packets into a
clean zero-ready state. Missing outcomes or attempt ledger inputs also report
limited_incomplete_input with downstream_consumable = false because the
repair queue can still be inspected, but attempt history and outcome quality are
incomplete. If outcomes are present while the attempt ledger is missing,
readiness may display those outcome counts as advisory context, but the report
remains non-consumable until durable attempt history is available.
The Markdown input table mirrors the JSON inputs object and includes swarm
plan, actionable-gap outcomes, and attempt-ledger rows. The Markdown sibling
also includes a Runtime Status table with the same completeness fields as JSON
before listing those inputs.
Readiness recomputes attempt/outcome summary counts, repair-route quality, and
missing-evidence-field counts from durable attempt-ledger attempts[] when
present, and otherwise forwards attempt-ledger summary,
repair_route_quality[], top_failing_repair_routes[], and
top_missing_evidence_fields[] so the next operator action can distinguish
"try the next packet" from "fix the noisy repair route first." These fields are
advisory quality signals and do not change badge, LSP, PR, or CI gate
semantics.
Readiness forwards static_limitation_backlog from swarm-plan so thin
surfaces can show the leading analyzer repair routes when no packet is safely
actionable. This field is advisory limitation backlog, not a public actionable
count and not a CI gate predicate.
Readiness summary counts keep the same split as the plan summary:
static_limitation_packets counts public repair packets blocked by static
limitations, while static_limitation_backlog_packets and
static_limitation_backlog_signals describe the separate analyzer backlog.
top_limitation_routes[] is a readiness-level projection of those analyzer
routes with sample packet context, sample category/subroute, sample canonical
gap IDs, sample source locations, why_not_actionable, unlock conditions, and
non-claims so operators can inspect the backlog without treating it as repair
work. It is intentionally separate from repair_route_quality[], which is
based only on latest repair attempts.
The backlog packet set is bounded, but it preserves representative samples for
each packet-backed top repair route in addition to the highest-volume subroutes
so low-count routes do not collapse to unknown sample context. Report-only
runtime diagnostics remain in runtime_status and run_limitations, not in
the packet-backed route projection.
For older or external backlog packets that omit presentation-only route fields,
readiness fills standard non-claims, fallback non-actionability text, fallback
unlock conditions, and explicit unknown evidence class values rather than
dropping the route or making it look repair-ready.
attempt_history_summary preserves durable attempt-ledger history before
readiness collapses to latest attempts for current routing counts. Use it to
inspect prior unchanged, no-receipt, regressed, or expected-unchanged outcomes
without treating those superseded rows as current route-quality failures.
top_next_action is a single-object projection of next_actions[0] for
thin downstream surfaces that need one canonical next route without
reinterpreting the full advisory queue. When that action routes static
limitation backlog, its reason preserves the sample subroute and
why_not_actionable text so thin surfaces can explain why the route is
analyzer work rather than a repair packet.
When all required inputs are readable but a non-consumable limited runtime state
is preserved from one input, readiness emits
resolve_limited_runtime_status before packet or route-quality actions so
downstream surfaces do not treat limited zero counts as work-ready truth.
For known runtime limitation categories, that action includes the command that
regenerates or inspects the limiting input, for example
cargo xtask lane1-evidence-audit for sampled, timed-out, runner-failed, or
incomplete repo-exposure generation and cache report/GC commands for large cache
limits.
Readiness also includes cross_language_oracle_route_quality, a SPEC-0062
preview-only summary over the checked Bun Blob cross-language oracle graph
corpus. This section counts complete advisory witnesses, missing discriminator
limitations, mention-only limitations, unknown bridge limitations, and public
packet exclusions while keeping all rows repair_packet_ready = false. It is
operator route-quality evidence only; it does not create repair packets, verify
commands, receipt commands, source edits, generated tests, gates, badges, or
support-tier claims.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "swarm-readiness",
"scope": "repo",
"status": "advisory",
"readiness_state": "full",
"run_status": "full",
"runtime_status": {
"state": "full",
"phase": null,
"duration_ms": null,
"limit_ms": null,
"input_kind": null,
"input_path": null,
"limitation_category": null,
"repair_route": null,
"downstream_consumable": true
},
"inputs": {
"swarm_plan": {
"path": "target/ripr/reports/swarm-plan.json",
"state": "read",
"limitation": null
},
"actionable_gap_outcomes": {
"path": "target/ripr/reports/actionable-gap-outcomes.json",
"state": "read",
"limitation": null
},
"attempt_ledger": {
"path": "target/ripr/reports/swarm-attempt-ledger.json",
"state": "read",
"limitation": null
}
},
"summary": {
"actionable_gaps_total": 162,
"public_projection_eligible_packets": 25,
"swarm_ready_packets": 10,
"blocked_packets": 15,
"blocked_by_missing_context_packets": 12,
"blocked_by_static_limitation_packets": 2,
"blocked_by_public_projection_exclusion_packets": 0,
"blocked_by_operator_judgment_packets": 1,
"public_projection_excluded_packets": 0,
"missing_canonical_gap_id": 0,
"missing_verify_command": 0,
"missing_verify_result": 0,
"missing_receipt_command": 0,
"missing_repair_kind": 0,
"missing_target_test_shape": 0,
"static_limitation_packets": 2,
"static_limitation_backlog_packets": 6,
"static_limitation_backlog_signals": 141,
"high_confidence_packets": 4,
"attempted_packets": 3,
"attempted_no_receipt_packets": 0,
"receipt_present_packets": 0,
"improved_packets": 2,
"unchanged_packets": 1,
"expected_unchanged_packets": 0,
"regressed_packets": 0,
"resolved_packets": 1,
"orphaned_receipts": 0
},
"attempt_history_summary": {
"attempts_total": 6,
"durable_attempts_total": 5,
"canonical_gaps_total": 4,
"not_attempted": 1,
"attempted_no_receipt": 1,
"receipt_present": 0,
"missing_verify_result": 0,
"evidence_improved": 2,
"evidence_unchanged": 2,
"expected_unchanged": 1,
"evidence_regressed": 0,
"resolved": 1,
"unknown": 0
},
"static_limitation_backlog": {
"source": "lane1-evidence-audit.static_limitations",
"top_categories": [
{
"category": "activation_value_unresolved",
"count": 141,
"repair_route": "analysis/value-resolution-audit-fixes"
}
],
"top_repair_routes": [
{
"repair_route": "analysis/value-resolution-audit-fixes",
"count": 141
}
]
},
"top_limitation_routes": [
{
"repair_route": "analysis/value-resolution-audit-fixes",
"signal_count": 141,
"sample_packet_id": "limitation:activation-value-unresolved:value-resolution-audit-fixes",
"sample_limitation_category": "activation_value_unresolved",
"sample_limitation_subroute": "activation_value_unresolved",
"sample_canonical_gap_ids": ["gap:value-resolution"],
"sample_sources": [
{
"canonical_gap_id": "gap:value-resolution",
"evidence_class": "predicate_boundary",
"source_file": "crates/ripr/src/analysis/value_resolution.rs",
"line": 88,
"expression": "idx >= offset",
"limitation_reason": "activation value cannot be safely mapped to a test input"
}
],
"dominant_evidence_class": "predicate_boundary",
"why_not_actionable": "activation value cannot be safely mapped to a test input",
"unlock_condition": "implement analyzer value-resolution before public repair packets are emitted",
"non_claims": [
"not a public repair packet",
"not swarm-ready work",
"do not edit tests from this backlog item alone",
"do not invent exact candidate values"
]
}
],
"blocked_state_routes": [
{
"state": "blocked_by_missing_context",
"count": 12,
"reason": "required packet context is missing before the packet can be safely delegated",
"next_action_kind": "inspect_blocked_missing_context",
"repair_route": "cargo xtask lane1-evidence-audit",
"example_packet_id": "packet:missing-context",
"example_canonical_gap_id": "gap:missing-context",
"example_repair_kind": "add_boundary_assertion",
"example_receipt_path": null
},
{
"state": "blocked_by_static_limitation",
"count": 2,
"reason": "a named static limitation prevents a safe bounded repair route",
"next_action_kind": "route_static_limitations",
"repair_route": "cargo xtask lane1-evidence-audit",
"example_packet_id": "packet:static-limit",
"example_canonical_gap_id": "gap:static-limit",
"example_repair_kind": "add_boundary_assertion",
"example_receipt_path": null
},
{
"state": "blocked_by_operator_judgment",
"count": 1,
"reason": "typed context exists, but default swarm routing still requires operator judgment",
"next_action_kind": "route_operator_judgment_packets",
"repair_route": "cargo xtask ripr-swarm plan --top 10",
"example_packet_id": "packet:manual",
"example_canonical_gap_id": "gap:manual",
"example_repair_kind": "add_boundary_assertion",
"example_receipt_path": null
}
],
"repair_route_quality": [
{
"language": null,
"repair_kind": "add_boundary_assertion",
"repair_kind_attempted": 2,
"repair_kind_improved": 1,
"repair_kind_unchanged": 1,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 1,
"repair_kind_dominant_failure_reason": "unchanged",
"repair_kind_success_rate": 0.5,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": []
}
],
"language_repair_route_quality": [
{
"language": "typescript",
"repair_kind": "sharpen_static_limitation_route",
"repair_kind_attempted": 1,
"repair_kind_improved": 1,
"repair_kind_unchanged": 0,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 0,
"repair_kind_dominant_failure_reason": null,
"repair_kind_success_rate": 1.0,
"sample_packet_ids": [],
"sample_attempt_ids": [],
"sample_canonical_gap_ids": [],
"sample_missing_receipt_reasons": []
}
],
"cross_language_oracle_route_quality": {
"status": "pass",
"source_path": "fixtures/cross-language-oracle-graph-corpus/corpus.json",
"cases_total": 9,
"passing_cases": 9,
"failing_cases": 0,
"cross_language_oracle_graph_complete_advisory_witnesses": 3,
"cross_language_oracle_graph_missing_discriminator_limitations": 1,
"cross_language_oracle_graph_missing_external_oracle_limitations": 1,
"cross_language_oracle_graph_bridge_unknown_limitations": 1,
"cross_language_oracle_graph_mention_only_limitations": 1,
"cross_language_oracle_graph_panic_boundary_limitations": 1,
"cross_language_oracle_graph_public_packet_exclusions": 9,
"repair_packet_ready_cases": 0,
"authority_boundary": "preview_advisory_only",
"non_claims": [
"not a public repair packet",
"not badge or gate input",
"not runtime Bun execution",
"not generated tests",
"not source edits",
"not full cross-language proof",
"not support-tier promotion"
],
"rows": [
{
"case_id": "bun_blob_bridge_unknown_limitation",
"expected_state": "bridge_unknown",
"observed_state": "bridge_unknown",
"status": "pass",
"missing_discriminators": [],
"missing_graph_legs": ["binding_or_ffi_edge"],
"authority_boundary": "preview_advisory_only",
"repair_packet_ready": false,
"unlock_condition": "Name a configured or generated binding edge from the TypeScript Blob surface to Blob::from_js_without_defer_gc."
},
{
"case_id": "bun_blob_missing_external_oracle_limitation",
"expected_state": "rust_ungripped_ts_missing_external_oracle",
"observed_state": "rust_ungripped_ts_missing_external_oracle",
"status": "pass",
"missing_discriminators": [],
"missing_graph_legs": ["external_oracle:stable_byte_copy"],
"authority_boundary": "preview_advisory_only",
"repair_packet_ready": false,
"unlock_condition": "Connect the partial Blob observer evidence to a stable byte oracle before crediting the Rust seam or suggesting placement."
}
]
},
"top_failing_repair_routes": [
{
"language": null,
"repair_kind": "add_boundary_assertion",
"repair_kind_attempted": 2,
"repair_kind_improved": 1,
"repair_kind_unchanged": 1,
"repair_kind_regressed": 0,
"repair_kind_resolved": 0,
"repair_kind_attempted_no_receipt": 0,
"repair_kind_receipt_present": 0,
"repair_kind_missing_verify_result": 0,
"repair_kind_expected_unchanged": 0,
"repair_kind_unknown": 0,
"repair_kind_failure_count": 1,
"repair_kind_dominant_failure_reason": "unchanged",
"repair_kind_success_rate": 0.5,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"]
}
],
"repair_route_quality_backlog": [
{
"packet_id": "route-quality:add-boundary-assertion:unchanged",
"repair_kind": "add_boundary_assertion",
"improvement_route": "analysis/repair-route-guidance/add-boundary-assertion",
"failure_count": 1,
"dominant_failure_reason": "unchanged",
"dominant_failure_count": 1,
"sample_packet_ids": ["packet-boundary-002"],
"sample_attempt_ids": ["attempt-boundary-002"],
"sample_canonical_gap_ids": ["gap:def"],
"sample_missing_receipt_reasons": [],
"why_action_required": "`add_boundary_assertion` produced unchanged evidence; refine target shape, assertion guidance, or evidence expectations before increasing packet volume",
"unlock_condition": "update `add_boundary_assertion` guidance so a future attempt can produce evidence_improved or resolved instead of evidence_unchanged",
"non_claims": [
"not a public repair packet",
"not swarm-ready work",
"do not retry this repair kind from this backlog item alone",
"do not promote or downgrade actionability from route-quality evidence alone",
"do not change badge or gate semantics from route-quality evidence alone"
]
}
],
"top_missing_evidence_fields": [
{
"label": "receipt_command",
"count": 1,
"sample_packet_ids": ["packet-boundary-001"],
"sample_canonical_gap_ids": ["gap:abc"],
"sample_repair_kinds": ["add_boundary_assertion"]
}
],
"top_next_action": {
"kind": "improve_repair_route_quality",
"packet_id": "route-quality:add-boundary-assertion:unchanged",
"attempt_id": "attempt-boundary-002",
"canonical_gap_id": null,
"evidence_class": null,
"repair_kind": "add_boundary_assertion",
"command": "cargo xtask ripr-swarm readiness",
"reason": "`add_boundary_assertion` has 1 failing latest attempt(s); dominant reason `unchanged` appears 1 time(s); route backlog packet `route-quality:add-boundary-assertion:unchanged` through `analysis/repair-route-guidance/add-boundary-assertion` before increasing packet volume; sample failed packet `packet-boundary-002` attempt `attempt-boundary-002`"
},
"next_actions": [
{
"kind": "improve_repair_route_quality",
"packet_id": "route-quality:add-boundary-assertion:unchanged",
"attempt_id": "attempt-boundary-002",
"canonical_gap_id": null,
"evidence_class": null,
"repair_kind": "add_boundary_assertion",
"command": "cargo xtask ripr-swarm readiness",
"reason": "`add_boundary_assertion` has 1 failing latest attempt(s); dominant reason `unchanged` appears 1 time(s); route backlog packet `route-quality:add-boundary-assertion:unchanged` through `analysis/repair-route-guidance/add-boundary-assertion` before increasing packet volume; sample failed packet `packet-boundary-002` attempt `attempt-boundary-002`"
},
{
"kind": "inspect_unchanged_attempts",
"packet_id": null,
"attempt_id": null,
"canonical_gap_id": null,
"evidence_class": null,
"repair_kind": null,
"command": "cargo xtask ripr-swarm attempt-ledger",
"reason": "1 attempted packet(s) left evidence unchanged; refine the repair route before retrying"
},
{
"kind": "route_static_limitations",
"packet_id": null,
"canonical_gap_id": null,
"evidence_class": null,
"repair_kind": null,
"command": "cargo xtask lane1-evidence-audit",
"reason": "2 packet(s) are blocked by static limitations; route them to the Lane 1 analyzer backlog, not repair execution"
},
{
"kind": "route_operator_judgment_packets",
"packet_id": "gap:static-only-boundary",
"canonical_gap_id": "gap:static-only-boundary",
"evidence_class": "predicate_boundary",
"repair_kind": "add_boundary_assertion",
"command": "cargo xtask ripr-swarm plan --top 10",
"reason": "1 top blocked packet(s) require operator judgment; improve upstream evidence confidence or choose a manual repair outside the default swarm-ready queue"
},
{
"kind": "attempt_ready_packet",
"packet_id": "packet-boundary-001",
"canonical_gap_id": "gap:boundary",
"evidence_class": "predicate_boundary",
"repair_kind": "add_boundary_assertion",
"command": "cargo xtask ripr-swarm attempt --packet packet-boundary-001 --dry-run",
"reason": "packet is queued with repair, verify, receipt, and no static limitation"
}
],
"must_not_infer": [
"readiness reports summarize existing swarm artifacts; they do not execute repairs",
"raw findings remain supporting evidence, not swarm work",
"missing outcome artifacts mean no outcome join is available, not that attempts failed",
"repair-route quality is an analyzer improvement signal, not a public badge basis",
"top_next_action is a projection of next_actions[0], not a separate ranking source",
"readiness counts do not change public badge semantics",
"static limitations and blocked packets are not repair-ready work"
]
}
The readiness report is the management dashboard for repair coordination. It
summarizes whether actionable packets have enough typed context to be
swarm-ready, whether attempts have been recorded, and whether receipt-backed
outcomes improved, stayed unchanged, regressed, or resolved. It does not make
badge-readiness claims by itself. next_actions is a bounded advisory queue
derived from the same plan and outcome artifacts. It can point operators to a
ready dry-run packet, missing verify/receipt source fields, orphaned receipts,
unchanged or regressed attempts, static-limitation backlog work, or
operator-judgment packets that are visible but not default swarm-ready. It does
not execute the action or consume raw findings as work. Route-quality next
actions may carry attempt_id to point at the concrete failed receipt sample
behind the analyzer/report backlog route. top_next_action is
the first item in that queue, duplicated as a stable object for badge, LSP, PR,
CI, or other thin surfaces that should not implement their own ranking rules.
blocked_state_routes[] gives every reported blocked packet or attempt state a
count, reason, next action kind, repair route, and example packet/canonical gap
identity when source artifacts provide one, so no blocked class is visible only
through raw packet JSON. It includes coarse states such as
blocked_by_missing_context, field-level blockers such as
missing_canonical_gap_id, missing_repair_kind, missing_target_test_shape, missing_allowed_edit_surface,
missing_confidence, missing_raw_evidence_refs, and
missing_related_test_or_observer, and outcome blockers such as orphan_receipt,
unchanged_attempt, and
regressed_attempt. For blocked_by_static_limitation, readiness prefers the
top static-limitation backlog route and sample packet when available, so the
blocked route names the analyzer repair lane instead of a generic report rerun.
Evidence Quality Scorecard
cargo xtask evidence-quality-scorecard writes a repo-local Lane 1 scorecard
over existing evidence-quality artifacts:
target/ripr/reports/evidence-quality-scorecard.json
target/ripr/reports/evidence-quality-scorecard.md
The command reads target/ripr/reports/lane1-evidence-audit.json, regenerating
the audit first only when that required input is absent. It also reads
target/ripr/reports/evidence-health.json and the previous scorecard artifact
when they are already available. The report is advisory and does not change
analyzer behavior, gate policy, PR/CI projection, editor output, source files,
generated tests, provider calls, or runtime execution.
The Markdown sibling includes a Runtime Status table with the same
completeness fields as JSON before listing scorecard summary metrics.
If the scorecard cannot regenerate a missing Lane 1 audit, it still writes a
bounded diagnostic scorecard instead of silently dropping the report. That
limited scorecard carries unknowns[].kind = "evidence_quality_scorecard_audit_regeneration_failed" and an audit
run_limitations[] entry with the same category. Counts in that artifact are
diagnostic only and must not be treated as complete repo truth or user test
debt.
Scorecard JSON includes run_status and runtime_status. It preserves a
limited current audit or limited evidence-health input instead of converting
partial counts into a clean scorecard headline. A completed audit that only
skipped a large cache store reports limited_large_cache_skip with
downstream_consumable = true; an audit skipped before generation because
the existing cache footprint exceeded the Lane 1 budget reports
limited_large_cache_skip with downstream_consumable = false; timeout,
runner failure, sampled, incomplete, or audit-regeneration states are not
complete repo truth.
When a Lane 1 audit carries named run_limitations[], the scorecard treats the
matching static_limitations.by_category rows as static limitations even if an
older or partial audit summary did not increment summary.static_limitations_total.
This keeps limited artifacts visible in the headline static-limitation count
instead of presenting a misleading zero.
The scorecard also includes cross_language_oracle_route_quality, the same
SPEC-0062 preview-only route-quality summary emitted by swarm readiness. It is
included so evidence-quality readers can see whether the checked Bun Blob
cross-language corpus is credited, missing a discriminator, mention-only, bridge
unknown, or excluded from public repair packets without running a separate
analyzer path. It remains advisory and does not change gate, badge, baseline,
repair-packet, generated-test, source-edit, provider, runtime, or support-tier
authority.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "evidence-quality-scorecard",
"generated_at": "unix_ms:1778620000000",
"run_status": "full",
"runtime_status": {
"state": "full",
"phase": null,
"duration_ms": null,
"limit_ms": null,
"input_kind": null,
"input_path": null,
"limitation_category": null,
"repair_route": null,
"downstream_consumable": true
},
"scope": {
"kind": "repo",
"root": "."
},
"inputs": {
"lane1_evidence_audit": {
"path": "target/ripr/reports/lane1-evidence-audit.json",
"status": "loaded",
"schema_version": "0.1",
"sha256": "0123456789abcdef",
"note": "required Lane 1 evidence-quality audit input"
},
"evidence_health": {
"path": "target/ripr/reports/evidence-health.json",
"status": "missing",
"schema_version": null,
"sha256": null,
"note": "optional durable evidence-health audit fields"
}
},
"headline": {
"primary_metric": "finding_alignment_actionable_unresolved_canonical_gaps",
"primary_count": 0,
"counting_model": "actionable_canonical_gaps",
"raw_signals": 2,
"canonical_items": 1,
"already_observed": 0,
"internal_no_action": 0,
"static_limitations": 4356,
"unknown": 0,
"raw_to_canonical_ratio": 2.0,
"note": "Raw findings are diagnostic; actionable canonical gaps are the user-facing repair count."
},
"summary": {
"raw_headline_gaps": 6114,
"canonical_gap_groups_total": 4800,
"duplicate_looking_groups_total": 240,
"missing_discriminators_total": 1756,
"static_limitations_total": 4356,
"related_tests_total": 2200,
"low_or_opaque_top_related_tests": 48,
"calibrated_records": 0,
"uncalibrated_records": 9355,
"evidence_records_total": 9355,
"evidence_records_missing": 0,
"top_repair_count": 5,
"recent_delta_available": false,
"finding_alignment_raw_findings_total": 2,
"finding_alignment_raw_signals_total": 2,
"finding_alignment_canonical_items_total": 1,
"finding_alignment_aligned_raw_findings_total": 2,
"finding_alignment_unaligned_raw_findings_total": 0,
"finding_alignment_raw_to_canonical_ratio": 2.0,
"finding_alignment_duplicate_groups_total": 1,
"finding_alignment_actionable_items_total": 0,
"finding_alignment_actionable_unresolved_canonical_gaps": 0,
"finding_alignment_already_observed_total": 0,
"finding_alignment_internal_only_total": 0,
"finding_alignment_internal_no_action_total": 0,
"finding_alignment_static_limitation_total": 1,
"finding_alignment_unknown_total": 0,
"finding_alignment_calibrated_supported_total": 0,
"finding_alignment_uncalibrated_total": 1,
"finding_alignment_visibility_unknown_total": 1,
"finding_alignment_presentation_text_actionable_total": 0,
"finding_alignment_static_unknown_without_named_limitation": 0,
"finding_alignment_canonical_items_without_repair_route": 0,
"finding_alignment_canonical_items_without_verify_command": 0,
"finding_alignment_actionable_gap_packet_public_projection_eligible_packets": 25,
"finding_alignment_actionable_gap_packet_public_projection_excluded_packets": 0,
"presentation_text_total": 1,
"presentation_text_user_visible": 0,
"presentation_text_observed": 0,
"presentation_text_unobserved": 0,
"presentation_text_internal_only": 0,
"presentation_text_visibility_unknown": 1,
"presentation_text_observer_unknown": 1,
"presentation_text_duplicate_groups": 1,
"presentation_text_actionable_snapshot": 0,
"presentation_text_no_action": 0,
"presentation_text_static_limitations": 1
},
"maturity_by_class": [
{
"class": "related_test_ranking",
"status": "static_only",
"proof_source": "RIPR-SPEC-0029, Lane 1 audit related-test confidence distribution",
"known_limits": "Top related-test choices include low-confidence or opaque rankings.",
"recommended_next_repair": "analysis/related-test-ranking-audit-fixes"
}
],
"canonical_gap_groups": {
"total": 4800,
"largest": []
},
"duplicate_looking_groups": [],
"static_limitation_categories": {
"by_reason": [],
"by_stage": {},
"by_category": {},
"repair_routes": {}
},
"missing_discriminator_classes": {
"by_reason": [],
"by_flow_sink": {},
"by_value": []
},
"related_test_confidence": {
"all_confidence_counts": {},
"top_confidence_counts": {}
},
"oracle_semantics_distribution": {
"by_semantics": [],
"oracle_kind_counts": {},
"oracle_strength_counts": {}
},
"movement_availability": {
"records_with_canonical_gap_id": 4800
},
"calibration_coverage": {
"availability_counts": {
"not_imported": 9355
},
"confidence_counts": {
"unknown": 9355
},
"agreement_counts": {
"no_runtime_data": 9355
},
"calibrated_records": 0,
"uncalibrated_records": 9355,
"runtime_scope": "uncalibrated",
"by_evidence_class": [
{
"evidence_class": "predicate_boundary",
"canonical_items": 900,
"calibrated_supported": 0,
"fixture_backed": 0,
"static_only": 900,
"unknown_confidence": 0,
"uncalibrated": 900,
"actionable_items": 42,
"static_limitation_items": 0
}
]
},
"actionable_gap_top_lists": {
"top_actionable_gap_classes": [
{"label": "predicate_boundary", "count": 900}
],
"top_actionable_files": [
{"label": "src/pricing.rs", "count": 42}
],
"top_repair_kinds": [
{"label": "add_boundary_assertion", "count": 810}
],
"top_missing_discriminator_kinds": [
{"label": "return_value", "count": 720}
],
"top_static_limitation_reasons": [
{"label": "opaque helper value", "count": 1200}
],
"top_verify_command_unknowns": [
{"label": "predicate_boundary", "count": 120}
],
"top_repair_route_unknowns": []
},
"actionable_gap_packet_public_projection": {
"scope": "emitted_actionable_gap_packets",
"public_projection_eligible_packets": 25,
"public_projection_excluded_packets": 0,
"projection_exclusion_reasons": []
},
"cross_language_oracle_route_quality": {
"status": "pass",
"source_path": "fixtures/cross-language-oracle-graph-corpus/corpus.json",
"cases_total": 9,
"passing_cases": 9,
"failing_cases": 0,
"cross_language_oracle_graph_complete_advisory_witnesses": 3,
"cross_language_oracle_graph_missing_discriminator_limitations": 1,
"cross_language_oracle_graph_missing_external_oracle_limitations": 1,
"cross_language_oracle_graph_bridge_unknown_limitations": 1,
"cross_language_oracle_graph_mention_only_limitations": 1,
"cross_language_oracle_graph_panic_boundary_limitations": 1,
"cross_language_oracle_graph_public_packet_exclusions": 9,
"repair_packet_ready_cases": 0,
"authority_boundary": "preview_advisory_only",
"rows": [
{
"case_id": "bun_blob_missing_resizable_oracle_limitation",
"expected_state": "rust_ungripped_ts_missing_discriminator",
"observed_state": "rust_ungripped_ts_missing_discriminator",
"status": "pass",
"missing_discriminators": ["resizable_array_buffer"],
"missing_graph_legs": [
"boundary_discriminator:resizable_array_buffer"
],
"repair_packet_ready": false,
"unlock_condition": "Prove a TypeScript Blob observer for a resizable ArrayBuffer on the configured bridge before placement or actionability is suggested."
},
{
"case_id": "bun_blob_missing_external_oracle_limitation",
"expected_state": "rust_ungripped_ts_missing_external_oracle",
"observed_state": "rust_ungripped_ts_missing_external_oracle",
"status": "pass",
"missing_discriminators": [],
"missing_graph_legs": [
"external_oracle:stable_byte_copy"
],
"repair_packet_ready": false,
"unlock_condition": "Connect the partial Blob observer evidence to a stable byte oracle before crediting the Rust seam or suggesting placement."
}
]
},
"recommended_repairs": [
{
"slice": "analysis/related-test-ranking-audit-fixes",
"priority": 100,
"evidence_class": "related_test_ranking",
"risk_kind": "low_or_opaque_top_related_tests",
"signal_count": 48,
"why": "Top related-test choices include low-confidence or opaque evidence.",
"expected_impact": "Improve first-useful-action task quality and agent packet reliability without changing gate behavior."
}
],
"recent_audit_deltas": {
"available": false,
"source": null,
"reason": "no previous scorecard artifact was available",
"deltas": []
},
"unknowns": [
{
"kind": "recent_delta_unavailable",
"summary": "No previous scorecard artifact was available for before/after delta reporting.",
"next_repair": "report/evidence-quality-trend"
}
]
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".report- always"evidence-quality-scorecard".generated_at- generation timestamp inunix_ms:<millis>form.scope.kind- always"repo".inputs.*- input artifact identity with path, load status, optional schema version, optional SHA-256, and a short note. Missing optional artifacts are reported instead of treated as failures.headline- additive scorecard lead numbers for the finding-alignment counting model plus the audit-wide static-limitation headline.primary_metricisfinding_alignment_actionable_unresolved_canonical_gaps,primary_countis the actionable canonical gap count, and raw signals remain diagnostic context alongside canonical item, already-observed, no-action, unknown, and raw-to-canonical counts.static_limitationsmirrors the scorecard summary's audit-widestatic_limitations_total, including named run limitations that are carried into the static-limitation taxonomy. This does not redefine public badges or gate policy.summary- headline scorecard counts copied from the current Lane 1 audit plus scorecard-local repair, delta availability, finding-alignment, and presentation-text counts. Finding-alignment counts preserve raw signals, canonical item totals, raw-to-canonical ratio, evidence states, confidence basis, and class-scoped presentation-text actionability without redefining RIPR scores.maturity_by_class- class-scoped maturity rows. Status values arefixture_backed,static_only,imported_runtime_calibrated, oruncalibrated; these are scorecard maturity labels, not RIPR exposure classifications.canonical_gap_groups,duplicate_looking_groups,static_limitation_categories,missing_discriminator_classes,related_test_confidence,oracle_semantics_distribution, andmovement_availability- current audit sections carried forward so the scorecard remains traceable tolane1-evidence-audit.json. Static limitation categories and repair routes are advisory Lane 1 analyzer-work buckets; they are not user-actionable test-gap labels.calibration_coverage- class-scoped calibration availability fromevidence_record.calibration;by_evidence_classcarries the audit's runtime-confidence rows for canonical items so maintainers can see calibrated support, fixture-backed static confidence, static-only evidence, unknown confidence, actionable items, and limitation items by class. It does not run mutation testing.actionable_gap_top_lists- the audit-derivedfinding_alignment.actionable_gap_top_listssection carried forward for the scorecard. It shows the dominant actionable classes, files, repair kinds, missing discriminator kinds, static limitation reasons on actionable gap records, and guidance-unknown classes so the scorecard explains the shape of user work before any badge or downstream rendering change.actionable_gap_packet_public_projection- the audit-derivedfinding_alignment.actionable_gap_packet_public_projectionreadiness section carried forward for scorecard and trend use. It counts emitted actionable-gap packets that are internally ready for future public projection and lists exclusion reasons such as missing receipt paths. This is advisory badge-readiness evidence only; it does not switch public badges or PR/CI rendering.cross_language_oracle_route_quality- the checked SPEC-0062 Bun Blob route summary. It reports complete advisory witnesses, missing discriminator limitations, mention-only limitations, unknown bridge limitations, public packet exclusions, row-level missing graph legs, unlock conditions, andrepair_packet_ready=false. It is preview/advisory evidence only and does not create public repair packets, verify commands, receipt commands, source edits, generated tests, runtime execution, gates, badges, baselines, RIPR Zero, or support-tier claims.evidence_class_work_queue- the audit-derivedfinding_alignment.coverage.evidence_class_work_queuesection carried forward so the scorecard names the next evidence classes to burn down from live output rather than static roadmap guesses. Static-dominated rows retain the dominant named limitation category and repair route, matching the audit queue.recommended_repairs- bounded Lane 1 repair slices. The scorecard promotes the audit-derivedevidence_class_work_queuerows first so the next repair class comes from live evidence-class counts rather than static roadmap guesses; remaining generic risks are ordered by product risk priority and signal count. These are advisory next steps, not policy decisions.recent_audit_deltas- before/after summary deltas when a previous scorecard artifact is available; otherwise an explicit unavailable reason.unknowns- unavailable inputs and evidence-quality unknowns that should stay visible until a fixture, analyzer, or calibration slice addresses them. A scorecard generated after failed missing-audit regeneration includesevidence_quality_scorecard_audit_regeneration_failedand the genericlane1_evidence_audit_limitedunknown so downstream consumers can explain the bounded diagnostic state. Non-completeness audit limitations, such as skipped full-cache storage after a complete repo-exposure run, remain visible on the audit artifact but do not mark scorecard counts as partial.
The Markdown sibling prints bounded sections for summary, finding-alignment and presentation-text quality, actionable canonical gap top lists, actionable-gap packet public-projection readiness, evidence-class work queue, maturity by class, top evidence-quality risks, recommended repairs, duplicate/canonical group signals, static limitations, missing discriminators, related-test and oracle distributions, movement and calibration coverage, recent deltas, and unknowns.
Evidence Quality Trend
cargo xtask evidence-quality-trend writes a repo-local Lane 1 trend report
over existing scorecard or audit snapshots:
target/ripr/reports/evidence-quality-trend.json
target/ripr/reports/evidence-quality-trend.md
By default the command reads the current
target/ripr/reports/evidence-quality-scorecard.json, regenerating the
scorecard first only when that required input is absent. It compares against
target/ripr/reports/evidence-quality-scorecard.previous.json or
target/ripr/reports/lane1-evidence-audit.previous.json when one exists.
Operators may also pass --current <path> and --previous <path>. Missing
history is reported explicitly as unknown; the command does not change
analyzer behavior, gate policy, PR/CI projection, editor output, source files,
generated tests, provider calls, score definitions, or runtime execution.
The Markdown sibling includes a Runtime Status table with the same
completeness fields as JSON before listing trend movement.
If an explicit --previous <path> artifact is missing or malformed, the command
still writes bounded trend JSON/Markdown with summary.status = "unknown",
inputs.previous_artifact.status = "missing" or "malformed", and the named
evidence_quality_trend_previous_artifact_unavailable unknown instead of
exiting before producing trend evidence. Metric rows may still carry current
values, but movement and badge-readiness deltas remain unknown.
Trend JSON includes run_status and runtime_status. A limited current
scorecard preserves its runtime state, including limited_sampled_input or
limited_incomplete_input; an explicit missing or malformed previous artifact
also produces a limited trend state. Missing implicit history remains an
unknown trend, not a gate or badge claim.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "evidence-quality-trend",
"generated_at": "unix_ms:1778620000000",
"run_status": "full",
"runtime_status": {
"state": "full",
"phase": null,
"duration_ms": null,
"limit_ms": null,
"input_kind": null,
"input_path": null,
"limitation_category": null,
"repair_route": null,
"downstream_consumable": true
},
"scope": {
"kind": "repo",
"root": "."
},
"inputs": {
"current_scorecard": {
"path": "target/ripr/reports/evidence-quality-scorecard.json",
"status": "loaded",
"schema_version": "0.1",
"sha256": "0123456789abcdef",
"note": "current evidence-quality scorecard"
},
"previous_artifact": {
"path": "target/ripr/reports/evidence-quality-scorecard.previous.json",
"status": "missing",
"schema_version": null,
"sha256": null,
"note": "optional previous scorecard or audit snapshot unavailable; movement is diagnostic only"
}
},
"summary": {
"status": "unknown",
"compared_metrics": 0,
"improved_metrics": 0,
"regressed_metrics": 0,
"unchanged_metrics": 0,
"unknown_metrics": 27,
"no_history": true
},
"movement_front": {
"current_actionable_count": 926,
"actionable_delta_since_prior_refresh": null,
"resolved": null,
"improved": null,
"unchanged_after_attempt": null,
"missing_receipts": null,
"orphaned_receipts": null,
"top_blocked_reason": "trend_history_unavailable",
"receipt_linked_movement_source": "unavailable_in_evidence_quality_trend",
"next_receipt_linked_command": "cargo xtask actionable-gap-outcomes"
},
"metric_trends": [
{
"metric": "finding_alignment_actionable_unresolved_canonical_gaps",
"label": "Actionable canonical gaps",
"before": null,
"after": 926,
"delta": null,
"direction": "unknown",
"interpretation": "No comparable previous value was available."
}
],
"static_limitation_category_trends": [],
"runtime_confidence_static_only_class_trends": [
{
"metric": "runtime_confidence_static_only_class:call_presence",
"label": "call_presence",
"before": null,
"after": 2567,
"delta": null,
"direction": "unknown",
"interpretation": "No comparable previous value was available."
}
],
"unknowns": [
{
"kind": "trend_history_unavailable",
"summary": "No previous scorecard or audit snapshot was available, so the report cannot claim improvement or regression.",
"next_repair": "report/evidence-quality-trend"
},
{
"kind": "evidence_quality_trend_previous_artifact_unavailable",
"summary": "Evidence-quality trend could not load the requested previous artifact. No movement or badge-readiness delta claim is made from this limited trend.",
"next_repair": "report/evidence-quality-trend"
}
]
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".report- always"evidence-quality-trend".inputs.current_scorecard- current scorecard artifact identity. The command creates the default scorecard first if it is missing.inputs.previous_artifact- optional previous scorecard or audit snapshot. Missing history is an explicit unknown, not a failure. Missing or malformed explicit previous paths are bounded unavailable-input states.summary.status-improvement,regression,mixed,unchanged, orunknown.movement_front- the first-screen movement panel. Inevidence-quality-trend,current_actionable_countandactionable_delta_since_prior_refreshcome from the scorecard trend forfinding_alignment_actionable_unresolved_canonical_gaps. Receipt-linkedresolved,improved,unchanged_after_attempt,missing_receipts, andorphaned_receiptsarenullbecause this report does not read receipt artifacts; operators should runcargo xtask actionable-gap-outcomesfor receipt-linked movement. This field does not imply runtime adequacy, mutation proof, policy eligibility, gate passage, or merge readiness.metric_trends[]- comparable Lane 1 evidence-quality metrics with nullablebefore,after, anddeltavalues plus a direction. Lower counts are better for debt and uncertainty metrics; higher counts are better for calibrated records, calibrated-supported canonical items, already-observed items, and internal no-action items. The first trend row is the actionable canonical gap count, matching the scorecard headline and keeping raw findings diagnostic rather than user work. Finding-alignment and presentation-text metrics also track raw-to-canonical quality, duplicate groups, actionability, static limitations, visibility unknowns, no-action/observed outcomes, and actionable-gap packet public-projection readiness. If the current scorecard carries limited input unknowns such aslane1_evidence_audit_limited,evidence_health_limited, orevidence_quality_scorecard_audit_regeneration_failed, metric rows remain present for diagnostics but their direction isunknownanddeltais null.static_limitation_category_trends[]- bounded category-level deltas for normalized static limitation classes. Current limited scorecards also force these category trend directions tounknown.runtime_confidence_static_only_class_trends[]- bounded evidence-class deltas derived fromcalibration_coverage.by_evidence_class[].static_only. Rows make the top static-only canonical evidence classes visible so runtime confidence work can pick calibrated fixture expansion targets. They remain advisory trend evidence and do not imply mutation execution or gate authority. Current limited scorecards also force these class trend directions tounknown.unknowns[]- missing history or missing current metric fields that must stay visible until later audit or scorecard inputs exist. Acurrent_scorecard_limitedunknown means the current scorecard is itself a bounded diagnostic artifact, so the trend must not claim improvement or regression from its counts. Missing or malformed explicit previous artifacts are reported asevidence_quality_trend_previous_artifact_unavailable.
The Markdown sibling starts with a movement front section, then prints bounded sections for summary, metric trends, static limitation category trends, runtime confidence static-only class trends, and unknowns.
Repo Exposure Latency Report
cargo xtask repo-exposure-latency-report writes a maintainer diagnostic
report to:
target/ripr/reports/repo-exposure-latency.json
target/ripr/reports/repo-exposure-latency.md
This report is intentionally separate from repo-exposure.json and
repo-exposure.md. It can time-box the repo-exposure command path and capture
phase timing without changing analyzer classifications or public report
schemas.
{
"schema_version": "0.1",
"tool": "ripr",
"report": "repo-exposure-latency",
"status": "warn",
"timeout_ms": 30000,
"binary": "target/debug/ripr.exe",
"runs": [
{
"format": "repo-exposure-json",
"status": "timeout",
"duration_ms": 30082,
"exit_code": 1,
"stdout_bytes": 0,
"stderr_bytes": 152,
"trace": [
{
"phase": "collect_workspace_state",
"status": "ok",
"duration_ms": 15
},
{
"phase": "cache_load",
"status": "miss",
"duration_ms": 0
},
{
"phase": "file_fact_cache",
"status": "hits_134_misses_0_corrupt_0_store_errors_0",
"duration_ms": 328
}
]
}
]
}
Field contract:
schema_version- currently"0.1"for the diagnostic report.status-passwhen every attempted format completes successfully,warnwhen a format times out or a later format is skipped after timeout, andfailwhen a format exits unsuccessfully before timeout.timeout_ms- timeout budget per repo-exposure format. Override withRIPR_REPO_EXPOSURE_LATENCY_TIMEOUT_MS.runs[].format-repo-exposure-jsonorrepo-exposure-md.runs[].status-pass,fail,timeout, orskipped_after_json_timeout.runs[].trace- analyzer trace lines captured from stderr whenRIPR_REPO_EXPOSURE_LATENCY_TRACE=1is set by the xtask command. Phases currently includecollect_workspace_state,cache_load,file_fact_cache,apply_oracle_policy,inventory_seams,evidence_for_seams,classify_seams,cold_compute,cache_store, andtotal; cache load statuses includehit,miss, andcorrupt_ignored. Thefile_fact_cachestatus is a compact counter label such ashits_134_misses_0_corrupt_0_store_errors_0; it describes parser/file-fact cache reuse only, not rendered output caching.
Targeted-Test Outcome Report
ripr outcome --before <snapshot-json> --after <snapshot-json> compares two
static RIPR snapshots and prints Markdown by default. The snapshots can be
repo-exposure JSON with seams[] or check-output JSON with findings[] that
carry canonical gap IDs. Use --format json for the machine-readable shape, or
--out <path> to write the rendered receipt to disk.
ripr outcome --before before.json --after after.json
ripr outcome --before before.json --after after.json --format json
ripr outcome --before before.json --after after.json --out target/ripr/outcome/targeted-test-outcome.md
The report is an advisory receipt for the targeted-test loop. It does not run
analysis, mutation testing, SARIF policy, or badge generation; it only compares
the two supplied static artifacts. Repo-exposure seams are matched by
seam_id; check-output findings are matched by canonical_gap_id, which lets
Python repair cards and TypeScript repair packets produce before/after receipts
without language-specific receipt commands.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "advisory",
"inputs": {
"before": "target/ripr/before.json",
"after": "target/ripr/after.json"
},
"before": {
"seams_total": 15,
"strongly_gripped": 3,
"weakly_gripped": 9,
"ungripped": 3
},
"after": {
"seams_total": 15,
"strongly_gripped": 5,
"weakly_gripped": 7,
"ungripped": 3
},
"summary": {
"moved": 2,
"unchanged": 12,
"regressed": 0,
"new": 0,
"removed": 1,
"gap_movement": {
"closed": 2,
"opened": 0,
"strengthened": 0,
"weakened": 0,
"unchanged": 12,
"new": 0,
"removed": 1,
"changed": 0
}
},
"moved": [
{
"seam_id": "67fc764ba37d77bd",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"before": "weakly_gripped",
"after": "strongly_gripped",
"direction": "improved",
"gap_movement": "closed",
"evidence_delta": [
"grip class moved from weakly_gripped to strongly_gripped",
"discriminate evidence moved from missing to yes",
"missing discriminator no longer reported: discount_threshold (equality boundary)",
"stronger related oracle visible: weak -> strong"
],
"evidence_source": "evidence_record",
"reach_delta": null,
"activate_delta": null,
"propagate_delta": null,
"observe_delta": null,
"discriminate_delta": {
"before_state": "missing",
"after_state": "yes",
"before_confidence": "high",
"after_confidence": "high",
"before_summary": "equality boundary not asserted",
"after_summary": "equality boundary asserted"
},
"observed_values_added": ["discount_threshold"],
"observed_values_removed": [],
"missing_discriminators_resolved": [
"discount_threshold (equality boundary)"
],
"missing_discriminators_reopened": [],
"oracle_strength_delta": "weak -> strong",
"related_test_delta": 1,
"no_movement_reason": null
}
],
"unchanged": [],
"regressed": [],
"new": [],
"removed": [],
"review_receipt": {
"gap_movement": {
"closed": 2,
"opened": 0,
"strengthened": 0,
"weakened": 0,
"unchanged": 12,
"new": 0,
"removed": 1,
"changed": 0
},
"what_changed": [
"Compared before snapshot target/ripr/before.json with after snapshot target/ripr/after.json.",
"Static seam movement: 2 moved, 12 unchanged, 0 regressed, 0 new, 1 removed."
],
"ripr_flagged_before": [
"weakly_gripped before predicate_boundary at src/pricing.rs:88."
],
"focused_proof_added": [
"predicate_boundary at src/pricing.rs:88 shows static evidence movement for focused proof outside RIPR: missing discriminator no longer reported: discount_threshold (equality boundary); new observed value: discount_threshold."
],
"movement_after_verification": [
"2 improved, 0 changed without ranking higher, 0 regressed, 12 unchanged.",
"Gap movement: 2 closed, 0 opened, 0 strengthened, 0 weakened, 12 unchanged, 0 new, 1 removed, 0 changed.",
"predicate_boundary at src/pricing.rs:88 moved weakly_gripped -> strongly_gripped (improved)."
],
"remaining_weak_or_unknown": [
"predicate_boundary remains weakly_gripped at src/checkout.rs:41."
],
"reviewer_should_inspect": [
"Open the compared artifacts: target/ripr/before.json and target/ripr/after.json.",
"Inspect the focused test or output proof corresponding to each listed evidence delta.",
"Review remaining weak, unknown, new, or regressed seams before treating the repair loop as complete."
],
"reviewer_may_believe": [
"RIPR compared only the listed static snapshots: target/ripr/before.json and target/ripr/after.json.",
"The listed focused-proof signals are static evidence visible after a test or output proof changed outside RIPR.",
"The movement and remaining-weak sections define the static claim boundary for this receipt."
],
"reviewer_should_not_believe": [
"Runtime mutation result.",
"Coverage adequacy.",
"General correctness.",
"Merge approval.",
"That RIPR edited source or generated tests."
]
}
}
For check-output snapshots, seam_id is the canonical gap ID. A Python or
TypeScript preview gap that moves from weakly_exposed to exposed is rendered as
weakly_gripped -> strongly_gripped with gap_movement = "closed". This is
still static/advisory evidence: verify success and a closed gap movement are
receipt signals, not runtime mutation proof or correctness proof.
The Python first-PR fixture pins this path with before/after check-output
snapshots and expected closed, unchanged, opened, strengthened, and weakened
receipts at
fixtures/first_successful_pr/python-preview-gap/inputs/reports/before-check.json,
fixtures/first_successful_pr/python-preview-gap/inputs/reports/after-check.json,
fixtures/first_successful_pr/python-preview-gap/inputs/reports/no-path-check.json,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/closed.json,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/closed.md,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/unchanged.json,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/unchanged.md,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/opened.json,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/opened.md,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/strengthened.json,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/strengthened.md,
fixtures/first_successful_pr/python-preview-gap/expected/outcome/weakened.json,
and
fixtures/first_successful_pr/python-preview-gap/expected/outcome/weakened.md.
The TypeScript preview packet receipt path is pinned by
fixtures/first_successful_pr/typescript-preview-gap/inputs/reports/before-check.json,
fixtures/first_successful_pr/typescript-preview-gap/inputs/reports/after-check.json,
fixtures/first_successful_pr/typescript-preview-gap/expected/outcome/closed.json,
and
fixtures/first_successful_pr/typescript-preview-gap/expected/outcome/closed.md.
The non-boundary return-value receipt path is pinned by
fixtures/first_successful_pr/python-return-gap/inputs/reports/before-check.json,
fixtures/first_successful_pr/python-return-gap/inputs/reports/after-check.json,
fixtures/first_successful_pr/python-return-gap/expected/outcome/closed.json,
and
fixtures/first_successful_pr/python-return-gap/expected/outcome/closed.md.
The exception-path receipt path is pinned by
fixtures/first_successful_pr/python-exception-gap/inputs/reports/before-check.json,
fixtures/first_successful_pr/python-exception-gap/inputs/reports/after-check.json,
fixtures/first_successful_pr/python-exception-gap/expected/outcome/closed.json,
and
fixtures/first_successful_pr/python-exception-gap/expected/outcome/closed.md.
The field/object receipt path is pinned by
fixtures/first_successful_pr/python-field-gap/inputs/reports/before-check.json,
fixtures/first_successful_pr/python-field-gap/inputs/reports/after-check.json,
fixtures/first_successful_pr/python-field-gap/expected/outcome/closed.json,
and
fixtures/first_successful_pr/python-field-gap/expected/outcome/closed.md.
The output/log receipt path is pinned by
fixtures/first_successful_pr/python-output-gap/inputs/reports/before-check.json,
fixtures/first_successful_pr/python-output-gap/inputs/reports/after-check.json,
fixtures/first_successful_pr/python-output-gap/expected/outcome/closed.json,
and
fixtures/first_successful_pr/python-output-gap/expected/outcome/closed.md.
Field contract:
schema_version— currently"0.1".status— always"advisory"; this report is a receipt, not a CI policy.inputs.before/inputs.after— normalized paths to the compared static evidence snapshots. Supported snapshots arerepo-exposure-jsonartifacts withseams[]or check-output JSON artifacts withfindings[].before/after— grip-class counts computed from the supplied seams. The report emitsseams_totalplus every knownSeamGripClassbucket, even when a bucket is zero.summary— movement bucket counts.movedmeans the seam matched byseam_idchanged grip class without ranking lower;regressedmeans the after class ranked lower than the before class;unchangedmeans the class stayed the same;newandremovedcover seam IDs present in only one input.summary.gap_movement- comparable canonical gap movement counts derived from each matched row'sgap_movement:closed,opened,strengthenedfor row-levelimproved,weakenedfor row-levelregressed,unchanged, andchanged.newandremovedare one-sided identity counts. These counts are receipt signals for static evidence movement; they are not mutation proof or correctness proof.review_receipt.remaining_weak_or_unknownincludes unchanged, regressed, and improved-but-still-attention-needed rows. A strengthened row is not treated as closed unless the after snapshot no longer needs review attention.moved[]/unchanged[]/regressed[]— matched seams with before/after grip classes, a direction string, and evidence-delta hints. Whenseams[].evidence_recordis present, the comparison prefers that shared evidence spine; otherwise it falls back to legacy repo-exposure seam fields.evidence_delta[]— advisory hints such as missing discriminators no longer reported, new observed values, or stronger related oracles. These hints are based on the rendered static artifact and do not claim runtime confirmation.evidence_source—evidence_record,legacy_fields, or a mixed transition label when before and after snapshots differ in available evidence source.reach_delta,activate_delta,propagate_delta,observe_delta, anddiscriminate_delta—nullwhen the stage is unchanged or unavailable, or an object with before/after state, confidence, and summary copied from the evidence record.observed_values_added/observed_values_removed— value-level activation evidence movement derived from the evidence record when available.missing_discriminators_resolved/missing_discriminators_reopened— discriminator-level movement derived from the evidence record when available.oracle_strength_delta—nullwhen unchanged, otherwise a compactbefore -> afterstatic oracle-strength movement label.related_test_delta— count movement for related-test evidence.no_movement_reason— explicit static reason for unchanged seams with no rendered evidence movement.new[]/removed[]— seam identity and grip class for seam IDs present in only one input.review_receipt— an additive reviewer packet derived from the same before/after movement data. It answers what changed, what RIPR flagged before the focused repair attempt, which static proof signals moved, what still remains weak or unknown, which bounded static claims reviewers may make, and what reviewers should inspect or avoid inferring. It does not add gate authority or runtime evidence beyond the compared snapshots.
The Markdown surface prints the same summary plus a "Gap Movement" table, highlights moved, unchanged, regressed, new, and removed seams for human review, and includes a "Review Receipt" section with the same reviewer-native fields. Unchanged seams can still carry evidence-delta hints, such as a new observed value, so reviewers can see when a targeted test improved rendered evidence without changing the grip class.
Agent Verify
ripr agent verify --root <workspace> --before <snapshot-json> --after <snapshot-json> --json compares two saved static snapshots
under the workspace root and emits a compact agent-focused JSON summary. It
reuses the targeted-test outcome comparison engine, but names the buckets for
the active agent loop:
ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json
The command does not run analysis, mutation testing, SARIF policy, badge
generation, LSP refresh, or cache warm-up. It only compares the supplied static
artifacts after validating they resolve under --root and carry the
producer-owned repo-exposure identity envelope. Missing, unsupported,
root-mismatched, revision-invalid, or content-tampered artifacts fail before
movement is calculated. This is static artifact integrity/currentness
validation; it does not execute tests or runtime mutation testing.
JSON shape:
{
"schema_version": "0.3",
"tool": "ripr",
"status": "advisory",
"inputs": {
"before": "target/ripr/workflow/before.repo-exposure.json",
"after": "target/ripr/workflow/after.repo-exposure.json",
"before_content_sha256": "sha256:<64-hex-digest>",
"after_content_sha256": "sha256:<64-hex-digest>"
},
"artifact_currentness": "historical_before_current_after",
"summary": {
"improved": 1,
"changed": 0,
"regressed": 0,
"unchanged": 0,
"new": 0,
"resolved": 0,
"gap_movement": {
"closed": 1,
"opened": 0,
"strengthened": 0,
"weakened": 0,
"unchanged": 0,
"new": 0,
"removed": 0,
"changed": 0
}
},
"changed_seams": [
{
"seam_id": "67fc764ba37d77bd",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"before": "weakly_gripped",
"after": "strongly_gripped",
"change": "improved",
"gap_movement": "closed",
"evidence_delta": [
"grip class moved from weakly_gripped to strongly_gripped",
"missing discriminator no longer reported: discount_threshold (equality boundary)"
],
"evidence_source": "evidence_record",
"reach_delta": null,
"activate_delta": null,
"propagate_delta": null,
"observe_delta": null,
"discriminate_delta": {
"before_state": "missing",
"after_state": "yes",
"before_confidence": "high",
"after_confidence": "high",
"before_summary": "equality boundary not asserted",
"after_summary": "equality boundary asserted"
},
"observed_values_added": ["discount_threshold"],
"observed_values_removed": [],
"missing_discriminators_resolved": [
"discount_threshold (equality boundary)"
],
"missing_discriminators_reopened": [],
"oracle_strength_delta": "weak -> strong",
"related_test_delta": 1,
"no_movement_reason": null
}
],
"unchanged_seams": [],
"new_gaps": [],
"resolved_gaps": []
}
Field contract:
schema_version- currently"0.3". Version0.2added the artifact content-commitment binding (inputs.before_content_sha256/inputs.after_content_sha256) so a verify result is bound to the exact artifact bytes it compared. Version0.3(#3027) corrects the pair-levelartifact_currentnessvalue domain — a closed-vocabulary correction that removes the old catch-alldirty_worktreepair token — so consumers dispatching on 0.2 values must re-verify;agent receiptfails closed on any other schema version and never migrates a 0.2 document.status- always"advisory"; this is an agent verification hint, not a CI policy.inputs.before/inputs.after- the compared snapshot paths.inputs.before_content_sha256/inputs.after_content_sha256- the validatedartifact.content_sha256commitments of the compared artifacts. This is the replay binding: a consumer that revalidates the artifacts can detect any byte change after verify, including one invisible to the movement render.artifact_currentness- the pair's repository identity disclosure, one of:current,historical_noncurrent,historical_before_current_after,current_before_historical_after,dirty_before,dirty_after, ordirty_both. A dirty side names the side (dirty_before,dirty_after, ordirty_both).historical_before_current_afteris the expected before/after transaction shape — the repository moved past the before artifact while the after artifact is bound to the current HEAD — and is a revision-movement disclosure, not a cleanliness certificate: a historical side is classified by head mismatch alone, and the worktree state remembered at production time does not participate in that classification, so a historical artifact produced on a dirty worktree still renders ahistorical_*pair token (#3229).current_before_historical_afteris a reachable accepted outcome when the checked-out HEAD is the before artifact's revision and the after artifact is bound to a descendant revision. A fully current pair (both artifacts current at the same clean revision) fails the movement gate before any output is rendered, socurrentcloses the vocabulary without being a reachable successful verify outcome. The field does not claim that tests ran or that the static gap is correct.summary.improved- matched seams whose afterSeamGripClassranks higher than before.summary.changed- matched seams whose class changed without ranking higher or lower.summary.regressed- matched seams whose after class ranks lower than before.summary.unchanged- matched seams whose class stayed the same.summary.new- seam IDs present only in the after snapshot.summary.resolved- seam IDs absent from the after snapshot. This is advisory; it can mean a gap was fixed, or that the seam disappeared because the code changed.summary.gap_movement- the same additive static gap-movement summary used byripr outcome, so agent receipts can read closed/opened/strengthened/ weakened/unchanged/new/removed/changed counts without scanning every row.changed_seams[]- improved, same-rank changed, and regressed matched seams.unchanged_seams[]- matched seams whose class stayed the same. These can still carryevidence_deltahints when rendered evidence improved without changing class.changed_seams[]/unchanged_seams[]carry the same additive evidence-record movement fields asripr outcome: stage deltas, observed-value movement, missing-discriminator movement, oracle strength movement, related-test count movement,gap_movement, andno_movement_reason.new_gaps[]/resolved_gaps[]- seam identity and static class for seam IDs present in only one snapshot.
Agent Verify Execute
ripr agent verify-execute --root <workspace> --packet <packet-json> --result-json <result-json> --authorize --json is the only explicit process
execution surface in the agent loop. It accepts one schema 0.4 producer
envelope containing exactly one packet, and executes only the direct,
no-network, no-write ripr agent verify route. The current ripr executable is
used; shell text is never interpreted.
The packet's typed command_specs.verify is an array, and it must equal
exactly what RIPR derives from that packet's own verification_commands. The
headline verify_command must resolve to the same route. Exactly one of the
reproduced routes must be executable; zero and more-than-one are both refused
rather than guessed.
How route authority is established
Authority is layered, because packet self-consistency alone is not provenance — every field of a packet is caller-supplied.
- Consistency. The typed specs must be reproducible from the packet's own display commands, and the headline must resolve to the same route. This buys one property: the command a reviewer reads is the command that runs. On its own it proves nothing about origin — a caller who coherently rewrites every copy of the route would pass this layer.
- Provenance. The route's
--beforeand--afterinputs must each pass the repo-exposure provenance contract: canonical shape,riprproducer identity, the exactripr check --format repo-exposure-jsonproducer command, a repository root equal to the selected root, a full-SHA HEAD, and a recomputed content commitment. Their base revisions must agree. RIPR then recomputes the canonical verify route over those validated artifacts and requires the packet's route to equal it.
The packet therefore chooses which validated producer artifacts to compare; it
never authors the command. A coherently rewritten packet naming anything that is
not a provenance-valid producer artifact is refused with
verification_rejected_policy and no process starts.
The operation requires --authorize, bounds process lifetime and stdout/stderr
separately, refuses to overwrite an existing result, and checks repository HEAD
and worktree state before and after execution. --before and --after inputs
must resolve under --root, and their content digests are committed alongside
the result.
Every successfully parsed execution attempt — including authorization and
execution refusals — emits one typed JSON terminal result on stdout with a
disposition field. Usage errors (a missing --packet, --result-json, or
--json, or a malformed --cancel-after-ms) remain plain usage errors on
stderr and produce no disposition. The exit status distinguishes only whether
RIPR
committed a bounded observation: 0 when it did (including
verification_executed_fail, which is a successful observation of a failing
command), nonzero when it could not. Dispositions are
verification_executed_pass, verification_executed_fail,
verification_command_not_found, verification_rejected_policy,
verification_wrong_root, verification_timed_out,
verification_cancelled, verification_output_limited,
verification_repository_changed, and verification_result_write_failed.
ripr agent verify-execute --root . --packet target/ripr/workflow/packet.json --result-json target/ripr/workflow/verification-execution.json --authorize --json
Environment posture
EnvironmentPolicy::Clean means no ambient application or credential variables
reach the child — not an empty environment block. The verify route invokes
git, so a literally empty environment strips PATH and makes a passing
observation unreachable on every real repository. Only a fixed platform floor
crosses the boundary (PATH, Windows SystemRoot/SystemDrive/windir/
COMSPEC/PATHEXT/TEMP/TMP, and HOME/TMPDIR/LANG/LC_ALL). The
floor is disclosed by name in the response preflight.environment_floor;
values are never emitted. Tokens and cloud credentials are dropped.
Because HOME is in the floor, host global Git configuration can influence the
child's Git behavior. "Clean" here means no ambient credential or application
variables — not behavioural independence from host Git configuration. Disabling
global and system Git configuration for the child is a possible future
tightening, not a current guarantee.
Declared limitations
- Descendant containment. Only the owned child is terminated. The workspace
forbids
unsafe_codeand the dependency policy admits neitherlibcnorwindows-sys, so no process-group or job-object substrate is available. The authority boundary compensates structurally: the only executable route is one leafripr agent verifyinvocation, which spawns no long-lived descendants. The posture is disclosed asdescendant_containmentin the response. verification_executed_fail,verification_timed_out, andverification_command_not_foundare mapped and unit-tested but are not reachable end-to-end today. The only executable route isripr agent verifyover two provenance-valid artifacts, and that command always exits 0 well inside its 120s timeout. Reaching these states needs a fallible typed route (for example acargo testroute) in the command catalog, which this surface deliberately does not add.--cancel-after-msis the deterministic bounded-termination path that is reachable.verification_command_not_foundcovers failure to start the resolved ripr executable, not aPATHlookup, because the route is executed via the current executable rather than by program name.
This is process evidence only. It does not compare static before/after movement, issue a repair receipt, prove mutation adequacy or correctness, or grant gate or merge authority. Packet rejection, wrong-root paths, policy rejection, and result-write failures are fail-closed and do not produce a receipt.
Agent Receipt
ripr agent receipt --root <workspace> --verify-json <agent-verify-json> --seam-id <id> --json narrows a saved ripr agent verify artifact to one
seam and adds optional handoff metadata for review:
ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id 67fc764ba37d77bd --json
ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id 67fc764ba37d77bd --test discounted_total_boundary_discriminator --command "cargo test discounted_total_boundary_discriminator" --json --out target/ripr/reports/agent-receipt.json
The command does not run analysis, mutation testing, SARIF policy, badge
generation, LSP refresh, or cache warm-up. It reads the supplied agent verify
JSON after validating that path resolves under --root, then reads and hashes
the inputs.before and inputs.after snapshot artifacts named by the verify
JSON after validating those paths also resolve under --root.
JSON shape:
{
"schema_version": "0.4",
"tool": "ripr",
"status": "advisory",
"analysis_outcome_status": "complete",
"analysis_outcome_error": null,
"analysis_outcome": {
"analysis_complete": true,
"outcome": {
"schema_version": "0.1",
"kind": "complete_no_findings",
"identity": {},
"counts": {},
"limitations": [],
"claim_boundary": "Static analysis outcome only; no correctness, test-adequacy, runtime-execution, or merge-readiness claim."
},
"semantic_digest": "sha256:..."
},
"inputs": {
"agent_verify_json": "target/ripr/workflow/agent-verify.json",
"before": "target/ripr/workflow/before.repo-exposure.json",
"after": "target/ripr/workflow/after.repo-exposure.json"
},
"provenance": {
"ripr_version": "0.8.0",
"repo_root": ".",
"config_fingerprint": "fnv1a64:4c94a2f6cfaa5c21",
"command_template_version": "0.1",
"generated_at": "unix_ms:1778179200000",
"workflow_artifact": null,
"before_artifact": {
"path": "target/ripr/workflow/before.repo-exposure.json",
"sha256": "sha256:..."
},
"after_artifact": {
"path": "target/ripr/workflow/after.repo-exposure.json",
"sha256": "sha256:..."
},
"verify_artifact": {
"path": "target/ripr/workflow/agent-verify.json",
"sha256": "sha256:..."
},
"seam_id": "67fc764ba37d77bd",
"before_class": "weakly_gripped",
"after_class": "strongly_gripped",
"movement": "improved",
"limits": {
"static_artifact_relationship": true,
"runtime_mutation_execution": false,
"runtime_adequacy_claim": false
}
},
"seam": {
"seam_id": "67fc764ba37d77bd",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"before": "weakly_gripped",
"after": "strongly_gripped",
"grip_class": null,
"change": "improved",
"evidence_delta": [
"missing discriminator no longer reported: discount_threshold (equality boundary)"
]
},
"test_changed": "discounted_total_boundary_discriminator",
"verification": {
"commands_run": ["cargo test discounted_total_boundary_discriminator"]
},
"summary": {
"receipt_state": "receipt_movement_improved",
"remaining_gap": "No remaining static gap is named by this receipt; inspect the current seam packet if review needs final assertion detail.",
"next_recommendation": "Keep the focused test and attach this receipt with the agent verify JSON.",
"next_action": {
"kind": "improved",
"summary": "Static grip improved.",
"recommended_action": "Keep the focused test and include this receipt in review.",
"safe_to_merge": false
}
}
}
Field contract:
schema_version- currently"0.4". Version0.2added receipt provenance fields; version0.3added structured next-action guidance; version0.4adds the producer-owned analysis-outcome envelope while preserving the selected-seam and handoff fields from0.1.status-"advisory"only when the producer outcome is complete;"incomplete"when the producer outcome is incomplete or unavailable; and"invalid"when the producer artifact is malformed, stale, or identity mismatched. This is a handoff receipt, not a CI policy.analysis_outcome_status- the producer evidence state:complete,incomplete,missing, orinvalid. It is copied from the canonicaltarget/ripr/workflow/analysis-outcome.jsonartifact and is never inferred from static movement, finding counts, or receipt presence.analysis_outcome_error- a diagnostic formissingorinvalidproducer evidence; it isnullwhen the typed outcome is present.analysis_outcome- the validated producer-owned typed outcome, including its derived completeness, limitations, recovery routes, input identity, and semantic digest. It isnullwhen producer evidence is unavailable or invalid; the receipt never fabricates a replacement outcome.inputs.agent_verify_json- the verify JSON path supplied to the command.inputs.before/inputs.after- snapshot paths copied from the verify JSON.provenance- identity for the static artifacts behind the receipt. It is produced without rerunning analysis after the referenced artifacts are revalidated and the supplied verify JSON is compared with canonical movement recomputed from those artifacts.provenance.ripr_version- theriprbinary version that rendered the receipt.provenance.repo_root- the--rootargument normalized to forward slashes for reporting.provenance.config_fingerprint- stable fingerprint ofripr.tomlwhen that file exists under the root, ornullwhen no config file is present. The receipt reads the file text only; it does not rerun analysis.provenance.command_template_version- version of the internal agent-loop command templates that produced the workflow command strings.provenance.generated_at- local render timestamp asunix_ms:<millis>.provenance.workflow_artifact- reserved workflow manifest artifact identity when a future receipt command is tied to a specific manifest. It is currentlynull.provenance.before_artifact/provenance.after_artifact/provenance.verify_artifact- path and SHA-256 hash for the static before, after, and verify artifacts used by the receipt.provenance.seam_id- selected seam identity copied from the receipt seam.provenance.before_class/provenance.after_class- static grip classes before and after for matched seams. For one-sided gaps, the absent side isnull.provenance.movement- selected verify movement bucket such asimproved,changed,regressed,unchanged,new, orresolved.provenance.limits- explicit static boundary flags. Receipts prove only the relationship between static before/after artifacts; they do not run mutation testing or claim runtime adequacy.- The receipt reads and validates the canonical producer artifact but does not rerun diff analysis. A complete zero-finding producer outcome remains complete; partial, unsupported, missing, malformed, stale, or identity- mismatched producer evidence remains visibly non-clean.
- Receipt issuance rejects hand-authored or altered verify JSON before this
envelope is rendered; the input must be exact canonical output from
ripr agent verifyfor the bound artifacts. seam- the selected seam fromchanged_seams,unchanged_seams,new_gaps, orresolved_gaps.seam.before/seam.after- before/after grip class for matched seams, ornullfor one-sided new/resolved gaps.seam.grip_class- one-sided grip class forneworresolvedgaps, ornullfor matched seams.test_changed- optional focused test name supplied by the caller.verification.commands_run- optional commands supplied by the caller. The receipt records them; it does not run them.summary.remaining_gap/summary.next_recommendation- static advisory guidance derived from the verify bucket. It does not claim runtime confirmation.summary.receipt_state- canonical receipt lifecycle state for the selected receipt. It is one ofreceipt_missing,receipt_found,receipt_stale,receipt_gap_mismatch,receipt_movement_improved,receipt_movement_unchanged, orreceipt_not_applicable.summary.next_action- structured static guidance for agents and reviewers.kindisimproved,changed,regressed,unchanged,new_gap,resolved, orunknown;summaryis a short static movement statement;recommended_actionis the bounded next step; andsafe_to_mergeis alwaysfalsebecause the static receipt is review evidence, not a merge policy.
Assurance axes (design contract)
The current agent verify and agent receipt surfaces are static-only
compatibility commands. Their verify_command, commands_run, and
verify_result fields record routes or caller-supplied context; they do not
prove that a command executed. Receipt presence does not imply test execution,
runtime mutation confirmation, adequacy, correctness, or merge authority.
RIPR-SPEC-0135 and
schemas/ripr/repair-assurance.schema.json reserve the versioned
RepairAssuranceV1 envelope. It keeps these axes independent:
static_movement_evaluatedwith an explicit movement result;verification_command_available,verification_executed_pass,verification_executed_fail,verification_not_run,verification_unavailable, orverification_cancelled_or_timed_out;receipt_issued,receipt_rejected, orreceipt_not_requested; andruntime_mutation_confirmation_externalonly for externally supplied runtime evidence.
This is a design-only contract in the current release. No packet, receipt request, or editor action automatically executes a command. A future execution slice must bind the typed command, working root, repository revision, process disposition, bounded output commitments, and currentness before emitting an executed state. A static-only receipt must remain visibly lower assurance.
PR Test Guidance
RIPR-SPEC-0012 defines the pinned contract for the
ripr review-comments report that projects existing seam evidence into
advisory pull-request guidance:
ripr review-comments \
--root . \
--base <sha> \
--head <sha> \
--out target/ripr/review/comments.json
ripr review-comments \
--root . \
--base <sha> \
--head <sha> \
--gap-ledger target/ripr/reports/gap-decision-ledger.json \
--out target/ripr/review/comments.json
The command is a pure renderer. The default path joins existing static seam
evidence with the changed-line diff, but it reports a scoped review input
instead of full-repo truth: changed production files plus bounded immediate
caller files. The JSON and Markdown carry analysis_scope.run_status = "limited_diff_scope" and the review_comments_diff_scope_only limitation
route so large-repo users can see the narrowed basis. When --gap-ledger is
supplied, the JSON and Markdown carry analysis_scope.run_status = "artifact_scope" and the review_comments_gap_ledger_artifact_scope_only
limitation route so users can see that RIPR consumed a supplied ledger artifact
rather than rerunning diff or full-repo analysis. The command renders
changed-line repair cards only from explicit GapRecord entries with
projection_eligibility.pr_comment.eligible = true, PR-local scope, a stable
anchor, a dedupe fingerprint, a repair route, and verification commands. It
does not post to GitHub, run mutation testing, refresh LSP state, edit source
files, or generate tests. CI can use the JSON to write a job summary and emit
check annotations by default. Inline PR review comments require a custom
explicit opt-in publisher.
Producer-backed output may also include a top-level review_input object.
It is the compact renderer projection, not the complete analysis inventory.
Its ripr.review_input.v1 envelope binds projected findings to the producer
through root, base/head/tree, canonical-diff identity, producer check digest,
mode, completeness, producer outcome, and finding-count/limit fields. A truncated projection
must disclose its selection policy and projected count; consumers validate the
digest and exact subject before rendering.
The nested run_receipt uses schema 0.2. A receipt with status = complete
and last_completed_phase = artifact_io must contain at least one
phase_evidence record and no missing artifacts. Timeout, partial, and
malformed producer states remain non-green even when rendered comment arrays
are empty.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "advisory",
"root": ".",
"base": "origin/main",
"head": "HEAD",
"mode": "draft",
"inputs": {
"gap_ledger": "target/ripr/reports/gap-decision-ledger.json"
},
"analysis_scope": {
"scope": "gap_ledger_artifact",
"run_status": "artifact_scope",
"basis": "supplied_gap_decision_ledger",
"changed_files": ["src/pricing.rs"],
"changed_lines": 1,
"changed_owner_functions": 0,
"changed_production_files": ["src/pricing.rs"],
"immediate_caller_files": [],
"scoped_production_files": ["src/pricing.rs"],
"total_rust_files": null,
"total_production_files": null,
"production_files_considered": 1,
"classified_seams_considered": 1,
"downstream_consumable": true,
"limitation": "review_comments_gap_ledger_artifact_scope_only",
"repair_route": "reports/gap-decision-ledger"
},
"limits": {
"max_inline_comments": 3,
"max_summary_items": 10
},
"summary": {
"comments": 2,
"summary_only": 1,
"suppressed": 1,
"unchanged_tests": true
},
"comments": [
{
"id": "ripr-review-67fc764ba37d77bd",
"seam_id": "67fc764ba37d77bd",
"canonical_gap_id": "gap:67fc764ba37d77bd",
"dedupe_key": "ripr:67fc764ba37d77bd:src/pricing.rs:88",
"placement": {
"path": "src/pricing.rs",
"line": 88,
"side": "RIGHT",
"mode": "exact_seam_line"
},
"kind": "predicate_boundary",
"grip_class": "weakly_gripped",
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"severity": "warning",
"source_location": {
"file": "src/pricing.rs",
"limitation": null,
"line": 88,
"repair_route": null,
"span": null,
"status": "resolved"
},
"reason": "Related tests reach and observe the owner but miss the equality boundary.",
"missing_discriminator": "amount == discount_threshold",
"suggested_test": {
"intent": "Add an equality-boundary test.",
"candidate_values": ["amount == discount_threshold"],
"assertion_shape": "Assert the returned discount behavior directly.",
"assertion_kind": "exact_value",
"recommended_file": "tests/pricing.rs",
"recommended_name": "discounted_total_boundary",
"near_test": "applies_discount_above_threshold",
"related_test": {
"name": "applies_discount_above_threshold",
"file": "tests/pricing.rs",
"line": 18
}
},
"llm_guidance": {
"prompt": "Write one focused Rust test for the missing equality boundary. Place it near tests/pricing.rs::applies_discount_above_threshold. Do not change production code. Preserve existing fixture style. Verify with ripr agent verify.",
"command": "ripr agent brief --root . --seam-id 67fc764ba37d77bd --json > target/ripr/workflow/agent-brief.json",
"verify_command": "ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json"
},
"repair_card": {
"gap_kind": "MissingBoundaryAssertion",
"changed_behavior": "amount == discount_threshold",
"why_this_matters": "Changed behavior `amount == discount_threshold` has a repairable MissingBoundaryAssertion gap.",
"repair": "Assert the returned discount behavior directly.",
"evidence_ids": ["evidence:pricing-threshold-reached"],
"verification_commands": ["cargo xtask fixtures boundary_gap"],
"verify_command": "cargo xtask fixtures boundary_gap",
"source_artifact": "target/ripr/reports/gap-decision-ledger.json",
"authority_boundary": "gate_decision_artifact_only"
}
}
],
"summary_only": [],
"suppressed": [],
"warnings": [],
"limits_note": "Advisory static evidence only; no automatic edits, generated tests, runtime mutation execution, or CI blocking."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".status- always"advisory"; this report is review guidance, not a CI policy.root,base,head, andmode- the workspace root, compared revisions, and RIPR analysis mode used to render the report.inputs.gap_ledger- optional explicit gap decision ledger used for repair-card projection. It is present only when--gap-ledgeris supplied.analysis_scope- scoped-input metadata for the renderer path. The default diff renderer emitsscope = "diff_scoped_changed_files",run_status = "limited_diff_scope", changed files, changed owner count, changed production files, immediate caller files, total production-file counts, the classified seam count considered, and thereview_comments_diff_scope_onlylimitation route. This makes the report useful on large repos without representing the scoped review as full-repo evidence. Gap-ledger rendering emitsscope = "gap_ledger_artifact"andrun_status = "artifact_scope"withbasis = "supplied_gap_decision_ledger", ledger anchor files, the supplied GapRecord count inclassified_seams_considered, and thereview_comments_gap_ledger_artifact_scope_onlylimitation route. That path does not rerun diff or full-repo analysis; its authority is the supplied ledger artifact.limits.max_inline_comments- default cap for changed-line annotations.limits.max_summary_items- default cap for total recommendations.summary.comments- count of guidance items with safe changed-line placement.summary.summary_only- count of recommendations without safe changed-line placement.summary.suppressed- count hidden by configured severity, suppression, caps, or missing guidance.summary.unchanged_tests-truewhen selected recommendations did not have a nearby test change in the pull request.comments[]- line-placeable advisory recommendations. These are the only items eligible for check annotations or inline review comments.comments[].id- stable report-local ID derived from the seam when possible.comments[].seam_id- static seam identifier from the existing exposure or agent packet evidence.comments[].canonical_gap_id- required, nullable stable behavioral-gap identity. Working-set cards project it from the canonical analysis domain; gap-ledger cards preserveGapRecord.canonical_gap_id. The renderer never derives it from file, line, expression, or related-test navigation.nullnames the absence of an eligible domain identity rather than a fallback.comments[].dedupe_key- stable key based on seam ID, path, and seam line.comments[].placement- GitHub-compatible changed-line placement. Items without safe placement belong insummary_only[].comments[].placement.mode-"exact_seam_line","owner_function_changed_line", or"same_file_changed_line". The renderer must prefer summary-only guidance over misleading line placement.comments[].kind- seam kind from the existing static evidence.comments[].grip_class- seam grip class from the existing static evidence.comments[].severity- configured report severity for the recommendation.comments[].source_location- canonical source coordinate for the seam or gap record rendered next to the seam ID in Markdown. When resolution is not available,statusis"source_location_unresolved",fileandlinerender as unknown,limitationis"source_location_unresolved", andrepair_routeis"analysis/source-location-resolution".comments[].reason- short static-evidence explanation for why a focused test would be useful.comments[].missing_discriminator- missing value, branch, variant, or observation when available.comments[].suggested_test- bounded test intent, candidate values, assertion shape, recommended test file, and related test to imitate when available.assertion_guidanceis the typed projection of the same producer-owned contract used by agent packets: onlystate: "concrete"carries an example;requires_observer_setup,fix_site_only,verification_only,unresolved, andstalecarryexample: nulland their bounded reason/recovery fields.comments[].suggested_test.related_test- structured navigational object{name, file, line}for the nearest strong related test (RIPR-SPEC-0068), ornullwhen no strong related test resolves. The flatrecommended_file,recommended_name, andnear_teststrings are retained alongside it; this object adds a directly navigablefile:linewhen the related-test location is resolved. On the gap-ledger card pathfileandlinemay benullwhen the supplied repair route names only the related test.comments[].llm_guidance- bounded handoff command and prompt for one focused test. It is not a request for free-form diff review.comments[].repair_card- optional GapRecord-backed repair card. When present, inline publish planning should use this field for the human/LLM comment body instead of raw static classes. It carries gap kind, changed behavior when available, why the gap matters, the bounded repair route, evidence IDs, verification commands, source artifact, and authority boundary.comments[].oracle_kind/comments[].oracle_strength- card-level oracle facts (RIPR-SPEC-0068) projecting the representative related test's oracle (the nearest strong related test, else the top-ranked related test). When no related test observes the seam they degrade honestly tooracle_kind = "unknown"/oracle_strength = "none", never a fabricated observer. These project the same oracle facts agent briefs and seam packets already carry; the review card computes no oracle of its own. Working-set path.oracle_kindis one of"exact_value","exact_error_variant","whole_object_equality","snapshot","relational_check","broad_error","smoke_only","mock_expectation","unknown";oracle_strengthis one of"strong","medium","weak","smoke","none","unknown". Enforced byspec0068_card_carries_oracle_kind_and_strength.comments[].gap_state- canonical actionability state per RIPR-SPEC-0061. Present on every card (working-set and gap-ledger paths). Values:"actionable","static_limitation","already_observed","internal_only", or"unknown". This replaces the previous implicit classification fromgrip_classalone for consumer code; always prefergap_statefor routing decisions. Enforced by reject-list testspec0068_every_card_carries_gap_state.comments[].receipt_command- copyableripr agent receiptcommand. Present whengap_state == "actionable". This completes the actionable-card contract:verify_command(inllm_guidance) plusreceipt_commandtogether form the proof-closure handoff. Enforced by reject-list testspec0068_actionable_card_carries_verify_and_receipt_commands.comments[].why_not_actionable- human-readable sentence from the firstEvidenceRecordStaticLimitation.reason. Present whengap_state == "static_limitation". Consumers should show this alongsidelimitationandlimitation_routewhen explaining why no repair is offered.comments[].non_claims- advisory-only boundary declarations. Present whengap_state == "static_limitation". Always carriesauthority_boundary: "advisory_static_evidence_only". Thelanguage_statusfield classifies the evidence tier ("advisory","preview_advisory", etc.).comments[].canonical_gap_id- stable gap identity from the gap-ledger. Present on gap-ledger path cards when available. Deferred on the working-set path (noCanonicalGapIdentityis threaded through the working-set renderer today; planned for a future slice).summary_only[]- same recommendation shape withoutplacement. These rows still carrysource_locationfor navigable Markdown and JSON parity. CI should show these in the Markdown/job summary but must not invent a changed-line annotation for them.summary_only[].summary_reason- closed-vocabulary token explaining why the card is in the summary rather than the inline set. Valid tokens:inline_comment_cap_reached,no_safe_changed_line_placement,navigation_only_cross_language_target,nearby_test_changed,summary_cap,missing_verification_command. Free-text values are forbidden per RIPR-SPEC-0068; adding a new token requires amending the spec.suppressed[]- bounded records for recommendations hidden by caps or nearby test changes.warnings[]- structured selection warnings from the agent brief selection path. Each warning has a closed-vocabularykind, a non-emptymessage, and an optionalpath.limits_note- static-evidence boundary text for downstream summaries.
Default CI projection runs ripr review-comments on pull requests, writes
summary items to the job summary, and emits check annotations only for changed
lines. Inline PR review comments remain opt-in through RIPR_COMMENT_MODE; the
generated workflow can emit a publish plan or publish safe same-repository
changed-line comments only when explicitly configured, capped, and deduped. See
PR review guidance for the command, generated CI
behavior, placement-safe review flow, and inline-comment boundary.
PR Inline Comment Publish Plan
RIPR-SPEC-0025 defines the optional inline comment publisher contract. The first surface is a read-only publish plan over existing PR guidance:
target/ripr/review/comment-publish-plan.json
target/ripr/review/comment-publish-plan.md
The plan consumes target/ripr/review/comments.json, optional existing RIPR
comment metadata, explicit comment mode, and permission context. The producer
does not post comments, call GitHub, rerun analysis, edit source files,
generate tests, run mutation testing, or change gate authority. Generated CI
keeps inline comments disabled by default, writes the plan in opt-in plan or
inline mode, and publishes only safe create/update operations in explicit
inline mode.
Producer:
ripr pr-comments plan \
--pr-guidance target/ripr/review/comments.json \
--existing-comments target/ripr/review/existing-comments.json \
--mode plan \
--out target/ripr/review/comment-publish-plan.json \
--out-md target/ripr/review/comment-publish-plan.md
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "pr_inline_comment_publish_plan",
"status": "advisory",
"root": ".",
"generated_at": "2026-05-10T12:00:00Z",
"mode": "plan",
"inputs": {
"pr_guidance": "target/ripr/review/comments.json",
"existing_comments": "target/ripr/review/existing-comments.json",
"pull_request": 123,
"event_name": "pull_request",
"head_repo": "EffortlessMetrics/ripr",
"base_repo": "EffortlessMetrics/ripr"
},
"limits": {
"max_inline_comments": 3,
"advisory": true,
"comments_default": "off"
},
"summary": {
"guidance_comments": 4,
"summary_only": 1,
"suppressed": 1,
"publishable": 3,
"planned_create": 2,
"planned_update": 1,
"planned_keep": 0,
"planned_delete": 0,
"skipped": 2,
"blocked": 0,
"safe_to_publish": false
},
"operations": [
{
"operation": "create",
"safe_to_publish": false,
"dry_run": true,
"source_collection": "comments",
"source_id": "ripr-review-67fc764ba37d77bd",
"dedupe_key": "ripr:67fc764ba37d77bd:src/pricing.rs:88",
"placement": {
"path": "src/pricing.rs",
"line": 88,
"side": "RIGHT",
"mode": "exact_seam_line"
},
"body": "RIPR advisory: static evidence says this seam misses `amount == discount_threshold`. Add one focused boundary assertion and verify with `ripr agent verify`.",
"existing_comment_id": null,
"skip_reason": null,
"blocked_reason": null
}
],
"skipped": [
{
"source_collection": "summary_only",
"source_id": "ripr-review-summary-1",
"dedupe_key": "ripr:summary:67fc764ba37d77bd",
"skip_reason": "summary_only",
"message": "Summary-only guidance is visible in comments.md but is not eligible for inline publishing."
}
],
"blocked": [],
"warnings": [],
"limits_note": "Advisory inline-comment publish plan only; default workflows do not post comments, summary-only guidance is never published inline, and gate decisions remain separate."
}
Field contract:
schema_versionis0.1until the plan shape changes.kindis alwayspr_inline_comment_publish_plan.statusisadvisory; this report is not gate authority.modeisoff,plan, orinline; generated CI defaults tooff.inputs.pr_guidancerecords the explicitreview-commentssource.inputs.existing_commentsrecords optional existing-comment metadata when supplied.inputs.event_name,inputs.head_repo, andinputs.base_repopreserve the permission context used for plan decisions.limits.max_inline_commentsdefaults to three.limits.comments_defaultisoff.summary.guidance_comments,summary.summary_only, andsummary.suppressedmirror the input collections when available.summary.publishablecounts onlycomments[]items eligible under placement, cap, permission, and dedupe rules.summary.safe_to_publishistrueonly when mode isinlineand every planned publishing operation satisfies the permission boundary.operations[]records publishable operations sourced fromcomments[]and stale existing-comment cleanup candidates.operations[].operationiscreate,update,keep, ordelete.operations[].source_collectionmust becommentsfor publishable operations.operations[].dedupe_keyis required forcreate,update,keep, anddelete.operations[].placementis copied from the sourcecomments[]item; the plan must not invent placement.operations[].bodypreserves advisory static-evidence language and must not claim runtime mutation results.skipped[]records capped, summary-only, suppressed, disabled, and already-current items.skip_reasonismode_off,summary_only,suppressed,inline_comment_cap_reached,unchanged_tests,not_publishable, oralready_current.blocked[]records hard safety blockers such as missing permissions, untrusted forks, missing PR context, unsafe events, missing dedupe keys, or malformed inputs.blocked_reasonismissing_pr_guidance,malformed_pr_guidance,missing_pull_request,missing_token,missing_write_permission,fork_untrusted,unsafe_event,missing_dedupe_key,missing_changed_line_placement,unsupported_mode, orunknown.warnings[]records malformed optional inputs, stale existing comments, unsupported optional metadata, and other non-authoritative context.limits_notepreserves the default-off, advisory, no-summary-only-inline, and separate-gate-authority boundaries.
Existing-comment metadata may be supplied to plan upsert behavior:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "pr_inline_comment_existing_comments",
"comments": [
{
"comment_id": 987654321,
"dedupe_key": "ripr:67fc764ba37d77bd:src/pricing.rs:88",
"path": "src/pricing.rs",
"line": 88,
"side": "RIGHT",
"body_hash": "sha256:...",
"outdated": false
}
]
}
Generated CI may upload and summarize the publish plan only when explicit
configuration requests plan or inline mode. The default remains job summary,
check annotations, and uploaded artifacts without durable PR comments.
Bun UB TypeScript Calibration Report
The Bun UB TypeScript calibration report is a repo-local operator receipt for
the preview Bun Blob / ArrayBuffer stable-byte corpus. It summarizes whether
the calibrated cases are TS-discriminated, missing shared/resizable
discriminators, mention-only rather than observed, or blocked by an unknown
bridge. It is advisory preview evidence only.
The repo-local report command is:
cargo xtask bun-ub-calibration \
--corpus fixtures/typescript-bun-ub-calibration/corpus.json \
--out target/ripr/reports/bun-ub-calibration.json \
--out-md target/ripr/reports/bun-ub-calibration.md
With defaults, cargo xtask bun-ub-calibration writes:
target/ripr/reports/bun-ub-calibration.json
target/ripr/reports/bun-ub-calibration.md
JSON shape:
{
"schema_version": "0.1",
"report": "bun-ub-calibration",
"status": "pass",
"source_path": "fixtures/typescript-bun-ub-calibration/corpus.json",
"authority_boundary": "preview_advisory_only",
"summary": {
"cases_total": 7,
"passing_cases": 7,
"failing_cases": 0,
"ts_discriminated_cases": 1,
"ts_missing_resizable_cases": 1,
"ts_missing_shared_cases": 1,
"ts_missing_shared_and_resizable_cases": 1,
"ts_missing_external_oracle_cases": 1,
"ts_mention_not_observer_cases": 1,
"bridge_unknown_cases": 1,
"missing_discriminator_cases": 3,
"public_packet_exclusions": 7,
"repair_packet_ready_cases": 0
},
"operator_question": "This Rust/FFI seam changed. Do Bun's TypeScript integration tests discriminate the boundary that would catch the stable-byte bug?",
"calibration_boundary": "Bun UB TypeScript calibration is preview/advisory only...",
"non_claims": [
"no provider calls",
"no source edits",
"no generated tests",
"no runtime Bun execution",
"no mutation execution",
"no default gates",
"no public badge contribution",
"no baseline authority",
"no RIPR Zero authority",
"no support-tier promotion",
"no public repair packet",
"no full cross-language proof"
],
"rows": [
{
"case_id": "bun_blob_resizable_missing",
"source": "#31648-stripped-resizable",
"expected_state": "ts_missing_resizable",
"observed_state": "ts_missing_resizable",
"status": "pass",
"rust_seam": {
"file": "src/jsc/Blob.rs",
"owner": "Blob::from_js_without_defer_gc",
"boundary": "array_buffer.shared || array_buffer.resizable"
},
"typescript_evidence": {
"test_file": "test/js/web/fetch/blob.test.ts",
"entrypoints": ["new Blob", "blob.arrayBuffer"],
"shared_array_buffer": true,
"resizable_array_buffer": false,
"view_backed_blob_input": true,
"stable_byte_copy_oracle": true,
"max_byte_length_mention_only": false
},
"bridge_confidence": "configured_hint",
"expected_action": "route_cross_language_oracle_visibility_limitation",
"expected_missing_discriminators": ["resizable_array_buffer"],
"missing_discriminators": ["resizable_array_buffer"],
"missing_graph_legs": ["boundary_discriminator:resizable_array_buffer"],
"suggested_test_file": "test/js/web/fetch/blob.test.ts",
"suggested_shape": "add or inspect a resizable ArrayBuffer Blob stable-byte discriminator in the configured TypeScript observer file; keep repair_packet_ready=false until verify, receipt, and edit-surface evidence exists",
"authority_boundary": "preview_advisory_only",
"repair_packet_ready": false,
"non_claims": ["runtime Bun execution", "generated tests"],
"reason": "Missing the resizable ArrayBuffer discriminator in the manifest calibration case.",
"errors": []
}
]
}
status is pass only when every row matches its expected state and no row is
repair_packet_ready. bridge_unknown rows name binding_or_ffi_edge in
missing_graph_legs[]; mention-only rows name
external_blob_or_stable_byte_observer. The report does not run Bun, tsc,
tsserver, mutation, providers, generated tests, source edits, gates, badges,
baselines, RIPR Zero, or support-tier promotion.
Bun UB Preview Summary Report
The Bun UB preview summary is a compact operator surface built from existing Bun UB calibration, cross-language oracle graph, and dogfood receipt data. It summarizes route counts, named static limitations, public packet exclusions, and receipt state without creating public repair packets.
The repo-local report command is:
cargo xtask bun-ub-preview-summary \
--calibration-corpus fixtures/typescript-bun-ub-calibration/corpus.json \
--graph-corpus fixtures/cross-language-oracle-graph-corpus/corpus.json \
--dogfood-corpus fixtures/bun-ub-cross-language-dogfood/corpus.json \
--out target/ripr/reports/bun-ub-preview-summary.json \
--out-md target/ripr/reports/bun-ub-preview-summary.md
With defaults, cargo xtask bun-ub-preview-summary writes:
target/ripr/reports/bun-ub-preview-summary.json
target/ripr/reports/bun-ub-preview-summary.md
JSON shape:
{
"schema_version": "0.1",
"report": "bun-ub-preview-summary",
"status": "pass",
"authority": "preview_advisory_only",
"authority_boundary": "preview_advisory_only",
"repair_packet_ready": false,
"source_paths": {
"calibration": "fixtures/typescript-bun-ub-calibration/corpus.json",
"cross_language_oracle_graph": "fixtures/cross-language-oracle-graph-corpus/corpus.json",
"dogfood": "fixtures/bun-ub-cross-language-dogfood/corpus.json"
},
"summary": {
"calibration_cases_total": 7,
"route_quality_cases_total": 9,
"dogfood_receipts_total": 4,
"route_state_counts": {
"rust_ungripped_ts_discriminated": 3,
"rust_ungripped_ts_missing_discriminator": 1,
"bridge_unknown": 1,
"ts_mention_not_observer": 1
},
"dogfood_state_counts": {
"rust_ungripped_ts_discriminated": 1,
"rust_ungripped_ts_missing_discriminator": 1,
"ts_mention_not_observer": 1,
"public_reachable_panic_boundary_unrevealed": 1
},
"named_static_limitations": [
{
"category": "cross_language_oracle_visibility_unresolved",
"count": 4,
"repair_routes": ["analysis/cross-language-oracle-visibility"],
"sample_case_ids": ["bun_blob_bridge_unknown_limitation"]
}
],
"public_packet_exclusions": 20,
"repair_packet_ready_cases": 0
},
"calibrated_routes": [
{
"route_label": "bun_blob_missing_resizable_oracle_limitation",
"profile": "bun_blob_array_buffer",
"case_id": "bun_blob_missing_resizable_oracle_limitation",
"state": "rust_ungripped_ts_missing_discriminator",
"gap_state": "static_limitation",
"limitation_category": "cross_language_oracle_visibility_unresolved",
"repair_route": "analysis/cross-language-oracle-visibility",
"suggested_test_file": "test/js/web/fetch/blob.test.ts",
"missing_discriminators": ["resizable_array_buffer"],
"missing_graph_legs": ["boundary_discriminator:resizable_array_buffer"],
"public_projection_eligible": false,
"repair_packet_ready": false,
"authority_boundary": "preview_advisory_only",
"unlock_condition": "prove the external oracle path and keep typed placement evidence"
}
],
"dogfood_receipts": [
{
"case_id": "bun_blob_missing_resizable_receipt",
"source_case": "bun_blob_resizable_missing",
"route_quality_case": "bun_blob_missing_resizable_oracle_limitation",
"state": "rust_ungripped_ts_missing_discriminator",
"receipt_state": "closed",
"operator_action": "add_resizable_blob_discriminator",
"proof_mode": "preview_manifest_receipt",
"suggested_test_file": "test/js/web/fetch/blob.test.ts",
"repair_packet_ready": false,
"authority_boundary": "preview_advisory_only",
"errors": []
}
],
"non_claims": [
"preview/advisory only",
"no public repair packet",
"no runtime Bun execution",
"no TypeScript execution",
"no mutation execution",
"no provider calls",
"no generated tests",
"no source edits",
"no gates or badges",
"no support-tier promotion",
"no full cross-language proof"
],
"errors": []
}
Markdown shape:
# Bun UB Preview Summary
Status: `pass`
authority = preview_advisory_only
repair_packet_ready: false
## Source Paths
## Summary
## State Counts
## Named Static Limitations
## Calibrated Routes
## Dogfood Receipts
## Non-Claims
status is pass only when the source calibration and route-quality reports
pass, dogfood receipts validate, every source keeps
authority_boundary = preview_advisory_only, and
repair_packet_ready_cases = 0. This report does not run Bun, tsc,
tsserver, Jest, Vitest, Miri, mutation, providers, generated tests, source
edits, gates, badges, baselines, RIPR Zero, support-tier promotion, or
ripr check --profile. It is not a TypeScript/JavaScript stability claim, a
full Bun binding graph, a runtime UB proof, or a public repair packet source.
Configured Bridge Inventory Report
The configured bridge inventory is a report-only Bun cross-language profile inventory built from the existing cross-language oracle graph corpus. It makes current configured bridges and manifest-only future surfaces visible without adding analyzer behavior or a full Bun binding graph.
The repo-local report command is:
cargo xtask configured-bridge-inventory \
--graph-corpus fixtures/cross-language-oracle-graph-corpus/corpus.json \
--out target/ripr/reports/configured-bridge-inventory.json \
--out-md target/ripr/reports/configured-bridge-inventory.md
With defaults, cargo xtask configured-bridge-inventory writes:
target/ripr/reports/configured-bridge-inventory.json
target/ripr/reports/configured-bridge-inventory.md
JSON shape:
{
"schema_version": "0.1",
"report": "configured-bridge-inventory",
"status": "pass",
"authority": "preview_advisory_only",
"authority_boundary": "preview_advisory_only",
"repair_packet_ready": false,
"source_path": "fixtures/cross-language-oracle-graph-corpus/corpus.json",
"summary": {
"configured_bridge_profiles": 3,
"bridge_unknown_profiles": 1,
"future_or_missing_surfaces": 2,
"named_static_limitation_profiles": 1,
"repair_packet_ready_cases": 0,
"s3_surfaces_backed_by_corpus": false
},
"configured_bridges": [
{
"profile": "bun_blob_array_buffer",
"label": "Blob ArrayBuffer",
"surface_state": "configured",
"rust_file": "src/jsc/Blob.rs",
"rust_owner": "Blob::from_js_without_defer_gc",
"bridge_kind": "configured_bridge",
"bridge_confidence": "configured_hint",
"external_surface": "test/js/web/fetch/blob.test.ts",
"source_cases": ["bun_blob_complete_ts_discriminated_advisory"],
"missing_graph_legs": [],
"inventory_action": "inventory_only",
"repair_packet_ready": false,
"public_projection_eligible": false,
"authority_boundary": "preview_advisory_only"
}
],
"bridge_unknown": [
{
"profile": "bun_blob_array_buffer",
"label": "Blob ArrayBuffer",
"surface_state": "bridge_unknown",
"missing_graph_legs": ["binding_or_ffi_edge"],
"inventory_action": "inventory_only",
"repair_packet_ready": false
}
],
"future_or_missing_surfaces": [
{
"profile": "bun_write_helper_gated",
"label": "Bun.write sink",
"surface_state": "manifest_only",
"missing_graph_legs": [
"helper:bun_write_fixture_helper",
"binding_or_ffi_edge:bun_write_sink",
"external_oracle:stable_byte_write"
],
"inventory_action": "inventory_only",
"repair_packet_ready": false
}
],
"named_static_limitations": [],
"non_claims": [
"preview/advisory only",
"report-only bridge inventory",
"no inferred reachability",
"no full Bun binding graph",
"no public repair packet",
"no placement from missing inventory rows",
"no runtime Bun execution",
"no TypeScript execution",
"no mutation execution",
"no provider calls",
"no generated tests",
"no source edits",
"no gates or badges",
"no support-tier promotion"
],
"errors": []
}
Markdown shape:
# Configured Bridge Inventory
Status: `pass`
authority = preview_advisory_only
repair_packet_ready: false
## Summary
## Configured Bridges
## Bridge Unknown
## Future Or Missing Surfaces
## Named Static Limitations
## Non-Claims
status is pass only when required configured bridge profiles and
manifest-only future surfaces are present in the corpus and no row claims a
repair packet. Missing inventory entries are inventory_only; they do not
become repair tasks or TypeScript placement suggestions.
Recommendation Calibration Report
RIPR-SPEC-0013 defines the recommendation calibration report contract. The report measures whether existing PR guidance was useful, correctly placed, properly suppressed or capped, aimed at the expected test target, and correlated with later static evidence movement.
The repo-local report command is:
cargo xtask recommendation-calibration \
--root . \
--pr-guidance target/ripr/review/comments.json \
--calibration-expectations fixtures/boundary_gap/expected/recommendation-calibration/expectations.json \
--outcome-receipts fixtures/boundary_gap/expected/recommendation-calibration/outcome-receipts \
--agent-receipt target/ripr/reports/agent-receipt.json \
--targeted-test-outcome target/ripr/outcome/targeted-test-outcome.json \
--out target/ripr/reports/recommendation-calibration.json
The report writes:
target/ripr/reports/recommendation-calibration.json
target/ripr/reports/recommendation-calibration.md
See Recommendation calibration for the operator workflow and metric interpretation guide.
This is an advisory calibration surface. It does not call LLM providers, edit source files, generate tests, run mutation testing, post comments, or make CI blocking by default.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "advisory",
"root": ".",
"inputs": {
"pr_guidance": ["target/ripr/review/comments.json"],
"agent_receipt": "target/ripr/reports/agent-receipt.json",
"targeted_test_outcome": "target/ripr/outcome/targeted-test-outcome.json",
"calibration_expectations": "fixtures/boundary_gap/expected/recommendation-calibration/expectations.json",
"outcome_receipts": [
"fixtures/boundary_gap/expected/recommendation-calibration/outcome-receipts/useful.json"
]
},
"summary": {
"recommendations_evaluated": 4,
"top_recommendation_outcome": "useful",
"useful": 2,
"noisy": 1,
"false_annotations": 1,
"summary_only_correct": 1,
"suppressed_correctly": 1,
"target_file_correct": 2,
"static_improved": 1,
"static_unchanged": 1,
"static_regressed": 0,
"unknown": 1
},
"latency": {
"guidance_generated_unix_ms": 1778240000000,
"annotation_emitted_unix_ms": 1778240001200,
"outcome_recorded_unix_ms": 1778240100000,
"annotation_latency_ms": 1200,
"outcome_latency_ms": 100000
},
"recommendations": [
{
"id": "ripr-review-67fc764ba37d77bd",
"seam_id": "67fc764ba37d77bd",
"rank": 1,
"source": "comments",
"source_artifact": "target/ripr/review/comments.json",
"source_case": "useful_exact_line_boundary",
"placement": {
"path": "src/pricing.rs",
"line": 88,
"mode": "exact_seam_line",
"quality": "correct"
},
"grip_class": "weakly_gripped",
"severity": "warning",
"missing_discriminator": "amount == discount_threshold",
"suggested_test": {
"recommended_file": "tests/pricing.rs",
"near_test": "applies_discount_above_threshold",
"target_quality": "correct",
"expected_file": "tests/pricing.rs"
},
"calibration": {
"outcome": "useful",
"source": "outcome_receipt:fixture",
"reason": "expected equality-boundary recommendation on the changed seam"
},
"static_movement": {
"state": "improved",
"source": "outcome_receipt",
"before_class": null,
"after_class": null
}
}
],
"suppressed": [
{
"id": "ripr-review-capped-1",
"seam_id": "67fc764ba37d77bd",
"source_artifact": "target/ripr/review/comments.json",
"source_case": "configured_off_boundary",
"reason": "cap_reached",
"quality": "suppressed_correctly",
"calibration": {
"outcome": "suppressed_correctly",
"source": "fixture_expectation",
"reason": "expected cap suppression"
}
}
],
"warnings": [],
"limits_note": "Advisory recommendation-quality evidence only; no telemetry, generated tests, source edits, runtime execution, or CI blocking."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".status-advisorywhen at least one recommendation can be evaluated andincompletewhen required inputs are missing. Malformed required inputs return an actionable command error instead of a successful report.root- workspace root used to resolve artifact paths.inputs- paths and receipt lists considered by the report. Missing optional inputs should be visible asnull, empty arrays, or warnings.summary.recommendations_evaluated- count of visible and suppressed recommendations considered.summary.top_recommendation_outcome- outcome label for the highest-ranked recommendation, orunknown.summary.useful,summary.noisy,summary.false_annotations,summary.summary_only_correct,summary.suppressed_correctly,summary.target_file_correct,summary.static_improved,summary.static_unchanged,summary.static_regressed, andsummary.unknown- aggregate quality and static-movement counts.latency.*_unix_ms- optional timestamps from artifacts or CI-provided metadata. Values arenullwhen timestamps are unavailable.latency.annotation_latency_ms- elapsed time from guidance generation to annotation emission when both timestamps are available.latency.outcome_latency_ms- elapsed time from guidance generation to the first matching outcome or receipt timestamp when available.recommendations[]- calibrated records for visible PR guidance items.recommendations[].rank- ranking from the source guidance.recommendations[].placement.quality-correct,wrong_line,summary_only_expected,not_placeable, orunknown.summary_only_expectedis a placement-quality value only; the matching review-quality outcome remainssummary_only_correct.recommendations[].suggested_test.target_quality-correct,wrong_target,not_applicable, orunknown.recommendations[].calibration.outcome-useful,noisy,wrong_line,already_covered,wrong_target,summary_only_correct,suppressed_correctly, orunknown.recommendations[].calibration.source-fixture_expectationoroutcome_receipt:<source>.recommendations[].static_movement.state-improved,unchanged,regressed,resolved,new_gap,missing_after_snapshot, orunknown.suppressed[]- recommendations hidden by caps, suppression, configured-off severity, generated/migration exclusion, or nearby-test change.suppressed[].reason- stable reason code:cap_reached,suppression,severity_off,nearby_test_changed,generated_or_migration, orunknown.suppressed[].quality-suppressed_correctly,over_suppressed, orunknown.warnings[]- missing inputs, unsupported expectation fields, stale artifacts, or latency values that could not be derived.limits_note- advisory boundary text for summaries and generated CI.
Calibrated Gate Decision
RIPR-SPEC-0014 defines the optional calibrated gate policy contract. The gate decision report is read-only policy over existing repo exposure, PR guidance, GapRecord decisions, SARIF policy, labels, receipts, recommendation calibration, and optional imported mutation calibration artifacts.
The evaluator is:
ripr gate evaluate \
--root . \
--repo-exposure target/ripr/reports/repo-exposure.json \
--pr-guidance target/ripr/review/comments.json \
--gap-ledger target/ripr/reports/gap-decision-ledger.json \
--sarif-policy target/ripr/reports/sarif-policy.json \
--labels-json target/ci/labels.json \
--agent-verify target/ripr/workflow/agent-verify.json \
--agent-receipt target/ripr/reports/agent-receipt.json \
--recommendation-calibration target/ripr/reports/recommendation-calibration.json \
--mutation-calibration target/ripr/reports/mutation-calibration.json \
--mode visible-only \
--out target/ripr/reports/gate-decision.json \
--out-md target/ripr/reports/gate-decision.md
The report writes:
target/ripr/reports/gate-decision.json
target/ripr/reports/gate-decision.md
This is an optional policy surface. Generated workflows remain advisory and
non-blocking by default. When --gap-ledger is supplied, gate candidates come
from explicit GapRecord projection_eligibility.gate_candidate records that
satisfy the safe gate predicate; PR guidance remains the legacy/fallback input.
The evaluator writes JSON and Markdown before returning a non-zero exit for
blocked or config_error decisions. It must not post comments, edit source
files, generate tests, run mutation testing, upload SARIF, mutate GitHub state,
or hide acknowledged decisions.
Generated CI runs this evaluator only when RIPR_GATE_MODE is explicitly set.
The default generated workflow leaves RIPR_GATE_MODE empty, captures pull
request labels to target/ci/labels.json, and uploads any gate-decision files
with the regular RIPR artifact packet. When gate-decision.json and
RIPR_GATE_BASELINE are available, generated CI also runs
ripr baseline diff as a non-blocking movement report and uploads
baseline-debt-delta.{json,md} with the same artifact packet. The job summary
renders an at-a-glance projection of mode, status, decision counts, labels,
waiver, baseline, calibration, blocking reason, debt movement counts, and
artifact paths before appending the full Markdown decision report.
visible-only remains advisory; blocking modes are opt-in.
The CLI also prints a stderr warning when ripr gate evaluate omits --mode
and stderr is non-interactive: the default is visible-only, which records
advisory evidence and never blocks. This warning is not part of the JSON or
Markdown report contract; an explicit --mode visible-only suppresses it.
See Calibrated gate policy for the operating model, rollout path, waiver behavior, and static/runtime vocabulary boundary.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "acknowledged",
"mode": "acknowledgeable",
"root": ".",
"inputs": {
"repo_exposure": "target/ripr/reports/repo-exposure.json",
"pr_guidance": "target/ripr/review/comments.json",
"gap_ledger": "target/ripr/reports/gap-decision-ledger.json",
"sarif_policy": "target/ripr/reports/sarif-policy.json",
"labels_json": "target/ci/labels.json",
"labels": ["ripr-waive"],
"agent_verify": "target/ripr/workflow/agent-verify.json",
"agent_receipt": "target/ripr/reports/agent-receipt.json",
"recommendation_calibration": "target/ripr/reports/recommendation-calibration.json",
"mutation_calibration": null,
"baseline": null
},
"policy": {
"mode": "acknowledgeable",
"threshold": "high_confidence_new_gap",
"acknowledgement_labels": ["ripr-waive"],
"default_workflow_posture": "advisory"
},
"summary": {
"evaluated": 2,
"blocking": 0,
"acknowledged": 1,
"advisory": 1,
"suppressed": 0,
"not_applicable": 0,
"unknown_confidence": 0
},
"decisions": [
{
"id": "ripr-gate-67fc764ba37d77bd",
"source": "pr_guidance",
"decision": "acknowledged",
"gate_reason": "policy-eligible gap acknowledged by ripr-waive",
"seam_id": "67fc764ba37d77bd",
"source_id": "ripr-review-67fc764ba37d77bd",
"gap_state": "actionable",
"static_class": "weakly_gripped",
"severity": "warning",
"placement": {
"path": "src/pricing.rs",
"line": 88
},
"policy": {
"mode": "acknowledgeable",
"threshold": "high_confidence_new_gap",
"acknowledgement_label": "ripr-waive",
"baseline_identity": null
},
"repair_route": {
"canonical_gap_id": "gap:pricing:threshold",
"seam_id": "67fc764ba37d77bd",
"classification": "weakly_gripped",
"changed_owner": "pricing::discounted_total",
"changed_behavior": "amount >= discount_threshold",
"missing_discriminator": "amount == discount_threshold",
"repair_target": {
"kind": "related_test",
"name": "discounted_total_boundary",
"file": "tests/pricing.rs",
"line": 12
},
"test_intent": "Exercise the production caller at the equality boundary and assert the returned discount.",
"verify_command": "cargo test -p pricing discounted_total_boundary",
"receipt_command": "ripr receipt write --gap gap:pricing:threshold",
"inspection_command": "ripr agent brief --root . --seam-id 67fc764ba37d77bd --json",
"authority_boundary": "static_ripr_evidence_only",
"limitation": null
},
"evidence": {
"missing_discriminator": "amount == discount_threshold",
"assertion_shape": "Assert the returned discount behavior directly.",
"candidate_values": ["amount == discount_threshold"],
"recommended_test": "tests/pricing.rs::discounted_total_boundary",
"nearby_test_changed": false,
"suppressed": false,
"configured_off": false,
"recommendation_calibration": {
"available": true,
"outcome": "useful",
"confidence_effect": "supports_static_gap"
},
"mutation_calibration": {
"available": false,
"confidence_effect": "not_used"
}
}
}
],
"warnings": [],
"limits_note": "Optional policy over static RIPR evidence; advisory by default; runtime mutation calibration is used only when supplied."
}
Field contract:
schema_version- currently"0.1".status- one ofpass,advisory,acknowledged,blocked, orconfig_error.mode- one ofvisible-only,acknowledgeable,baseline-check, orcalibrated-gate.inputs- normalized paths and labels used by the evaluator. Optional inputs should appear asnullor produce a warning when they are absent.inputs.gap_ledger- optional explicit gap decision ledger input. When supplied, gate candidates come from GapRecord gate-candidate projection targets instead of raw PR guidance candidates.policy.mode- effective gate mode after config and CLI precedence.policy.threshold- initiallyhigh_confidence_new_gap.policy.acknowledgement_labels- configured labels that can turn a blocking candidate into a visible acknowledged decision.policy.default_workflow_posture- must remainadvisoryfor generated workflows unless a later explicit configuration changes it.summary.evaluated- candidate count considered after parsing inputs.summary.blocking- count of candidate decisions that make the gate fail.summary.acknowledged- count of candidate decisions made non-failing by an acknowledgement label.summary.advisory- count of visible non-blocking decisions.summary.suppressed- count of suppressed or configured-hidden candidates preserved in the gate report.summary.not_applicable- count of parsed records that are outside the configured policy scope.summary.unknown_confidence- count of candidates that could not satisfy high-confidence requirements.decisions[].source- source artifact family such aspr_guidance,gap_decision_ledger,repo_exposure,sarif_policy, oragent_receipt.decisions[].gap_idanddecisions[].gap_kind- optional GapRecord identity and repair-problem kind copied when the decision came from a gap ledger.decisions[].canonical_gap_id- optional semantic Lane 1 gap identity copied from the source candidate when supplied directly, throughidentity.canonical_gap_id, or throughevidence_record.canonical_gap_id. The field is omitted when unavailable.decisions[].decision- one ofblocking,acknowledged,advisory,suppressed, ornot_applicable.decisions[].gate_reason- short policy explanation for human summaries.decisions[].gap_state- producer-owned gap state, ornullwhen the source cannot supply it.decisions[].static_class- source static class copied without rewriting seam-grip classes into finding classes.decisions[].severity- configured severity from the source surface.decisions[].policy- mode, threshold, acknowledgement, and baseline facts that affected the candidate.decisions[].policy.baseline_identity- identity used for baseline comparison. Matching preferscanonical_gap_idbefore legacy seam, source, ID, dedupe-key, and path/line/static-class fallback identities.decisions[].baseline_match_kind- optional disclosure recorded when the baseline match happened only through the legacy path/line/static-class fallback identity. The sole allowed value is"legacy_path_line_class". The field is omitted for canonical identity matches and for baseline-new candidates, so their rendered decisions stay byte-identical. During the compatibility window a fallback-only match still suppresses blocking but also produces a report-level warning naming the candidate and the matched legacy identity.decisions[].evidence- static evidence and optional calibration confidence effects used for the candidate.decisions[].repair_route- uniform failure-time route object, present on every decision. It carries nullable producer-owned fields forcanonical_gap_id,seam_id,classification,changed_owner,changed_behavior,missing_discriminator, taggedrepair_target,test_intent,verify_command,receipt_command, and exact producer-ownedinspection_command. A changed owner is not assumed to be a production caller, generic evidence-vector position is not treated as seam identity, and path/line is not manufactured into an exact inspection selector. Theauthority_boundaryisstatic_ripr_evidence_only.decisions[].repair_route.limitation-nullonly when the route is complete. Otherwise it has kindincomplete_repair_route, a closed list of missing fields, and a bounded detail. A candidate that would otherwise be policy-eligible fails closed to advisory visibility when this limitation is present; no renderer invents a fallback identity, location, test, or command.gate-decision.md- human projection consumed directly by generated GitHub step summaries. Blocking, acknowledged, and advisory decisions expand the same structured route into gap/seam identity, gap state, classification, changed owner/behavior, missing discriminator, tagged target, test intent, verify/receipt/inspection commands, and the static authority boundary. Incomplete routes print their named limitation and missing fields without a fabricated inspection command; suppressed and not-applicable decisions do not present an actionable route.decisions[].evidence.repair_routeandverification_commands- optional GapRecord repair route and verification commands. These fields are present when the gate decision is driven by a repairable gap ledger record.warnings[]- missing optional inputs, unsupported labels, ambiguous calibration, baseline limitations, or schema limitations.limits_note- static/runtime and advisory-default boundary text.new_unsuppressed- canonical downstream-thresholding receipt (see below).
new_unsuppressed receipt field
Added by RIPR-SPEC-0111. Additive — does not bump schema_version.
"new_unsuppressed": { "basis": "diff", "count": 3, "reason": null }
Consumers may threshold on .new_unsuppressed.count (e.g.
max_new_unsuppressed=0). The field is a stable filter over the gate's own
decisions[] — reproducible by any reader of the same receipt.
Honest definition. count is the number of decisions d in decisions[]
where ALL of the following hold:
d.static_class ∈ {"weakly_gripped","ungripped","reachable_unrevealed","weakly_exposed"}(policy-eligible class).d.decision ∈ {"blocking","advisory"}— suppressed, acknowledged, and not_applicable candidates are EXCLUDED (they are handled or ineligible).d.repair_route.limitation == null. An advisory decision withincomplete_repair_routeis visible but is not policy-eligible debt for a downstream threshold.- If
basis == "baseline": additionallyd.is_baseline_newis true. Ifbasis == "diff": all candidates in 1+2+3 count (diff scope equals "new").
CRITICAL: count INCLUDES policy-eligible advisory decisions. It is NOT
equal to summary.blocking. In visible-only mode every eligible candidate is
advisory (blocking=0) but count is the advisory candidate count. An external
thresholder applies its own policy; ripr reports the complete-route candidate
count regardless of its own blocking/advisory label.
basis values.
basis | Meaning |
|---|---|
"diff" | Diff-scoped run. All surviving candidates are new by definition. |
"baseline" | Baseline-aware run (baseline-check or calibrated-gate). Only is_baseline_new=true candidates count. |
null | FAIL CLOSED: config_errors is non-empty — analysis did not run. |
Fail-closed rule. When config_errors is non-empty, basis=null,
count=0, and reason discloses the first config error. count=0 with
basis=null must NEVER be read as "clean/pass" — the reason field is
the mandatory disclosure.
exception_policy ledger section (top-level additive, #1442)
Emitted only when ripr gate evaluate is invoked with
--exception-policy PATH. Absent otherwise, so existing gate-decision
consumers and goldens see byte-identical output. Does not bump
schema_version. inputs.exception_policy carries the supplied path when
the flag is present.
The ledger is a quality-gate-exceptions TOML file: a dated, auditable list
of named temporary burndown exceptions. Header fields: schema_version = 1,
policy = "quality-gate-exceptions", optional owner, status
(default "active"), updated, and due_review = "warn" | "fail"
(default "fail", fail-closed). An optional [requirements] required_active
list names exception ids that MUST be active. Each [[exception]] requires
id, kind, scope, owner, reason, final_target, evidence,
removal_criteria, and YYYY-MM-DD created, review_after, and expires
dates; issue is optional metadata. Unknown keys, blank required fields,
malformed dates, and duplicate ids are load errors.
Enforcement, evaluated against today's UTC date; ripr owns these semantics while the consumer owns only the ledger content:
expires < today→quality_exception_expired(blocking).- otherwise
review_after <= today→quality_exception_review_due(blocking underdue_review = "fail"; a gate warning under"warn"). - a
required_activeid with no active exception →quality_exception_required_missing(blocking). An expired required exception raises both violations; both stay visible. - ledger
status = "final"→ every still-active exception isquality_exception_final_active(blocking): final enforcement means zero active exceptions remain.
Any blocking violation makes the top-level gate status "blocked" (non-zero
exit). A missing or malformed ledger is a config_error, never a silently
ignored input — the gate must not report pass while believing a policy was
applied.
"exception_policy": {
"path": "policy/quality-gate-exceptions.toml",
"ledger_status": "active",
"ledger_owner": "EffortlessMetrics",
"due_review": "fail",
"active_count": 1,
"active": [
{"id": "ripr-total-burndown", "kind": "temporary_burndown",
"scope": "ripr_plus_total", "owner": "proof-lane",
"reason": "Existing repo-wide gaps predate the transition gate.",
"review_after": "2026-06-28", "expires": "2026-09-30"}
],
"violations": [
{"kind": "quality_exception_review_due",
"exception_id": "ripr-total-burndown",
"detail": "exception `ripr-total-burndown` passed its review_after date 2026-06-28 (today 2026-07-05); re-review it and move review_after forward",
"blocking": true}
]
}
The Markdown report renders a matching ## Exception Policy section with the
ledger path, status, active entries, and violations (BLOCKING vs warning).
These are gate policy states, not static exposure claims: violation kinds are
quality_exception_* terms and never rewrite finding classifications.
Markdown should fit in a job summary. It should name the top-level decision, mode, counts, blocking or acknowledged seams, repair action, and limits. It must not hide acknowledged decisions. If the evaluator returns a blocking exit code, the Markdown still needs enough evidence for the next agent or reviewer to resolve the state.
Gate Baseline Ledger
ripr baseline create writes the first executable Campaign 17 baseline ledger.
It turns an existing gate-decision JSON report into a stable historical-debt
baseline that can be reviewed, checked in, diffed against current evidence, and
shrink-only refreshed after resolved debt is reviewed.
Command:
ripr baseline create \
--from target/ripr/reports/gate-decision.json \
--out .ripr/gate-baseline.json
Options:
--from- required gate-decision JSON fromripr gate evaluate.--out- baseline path. Defaults to.ripr/gate-baseline.json.--dry-run- print the baseline JSON without writing.--force- overwrite an existing baseline path.
The command includes advisory, acknowledged, and blocking gate decisions.
It skips suppressed, configured-off, not_applicable, and malformed
decisions. The command refuses to overwrite an existing baseline unless
--force is supplied. It does not run analysis, change gate policy, edit
source, generate tests, run mutation testing, or make CI blocking by default.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "gate_baseline",
"created_at": "unix_ms:1778277000000",
"source_report": "target/ripr/reports/gate-decision.json",
"mode": "baseline-check",
"reviewed": false,
"summary": {
"entries": 1,
"included": 1,
"skipped": {
"suppressed": 0,
"not_applicable": 0,
"malformed": 0,
"other": 0
}
},
"entries": [
{
"identity": {
"canonical_gap_id": "pricing::discount::threshold_equality",
"seam_id": "67fc764ba37d77bd",
"source_id": "ripr-review-67fc764ba37d77bd",
"id": "ripr-gate-67fc764ba37d77bd",
"dedupe_key": null,
"fallback": "src/pricing.rs:88:weakly_gripped"
},
"path": "src/pricing.rs",
"line": 88,
"static_class": "weakly_gripped",
"decision": "advisory",
"severity": "warning",
"source": "pr_guidance",
"gate_reason": "visible-only mode records evidence without blocking",
"evidence": {
"missing_discriminator": "amount == discount_threshold",
"assertion_shape": "Assert returned discount behavior directly.",
"recommended_test": "tests/pricing.rs::applies_discount_above_threshold"
},
"review": {
"reviewed": false,
"owner": null,
"reason": "initial adoption baseline",
"created_at": "unix_ms:1778277000000",
"review_after": null,
"source": "target/ripr/reports/gate-decision.json"
}
}
],
"warnings": [],
"limits_note": "Reviewed baseline debt ledger over static RIPR gate evidence; baselines are not suppressions and do not change gate policy by themselves."
}
The gate evaluator accepts this entries[] ledger shape in addition to the
older lightweight decisions[] baseline fixture shape, so newly created
baselines can be used by ripr gate evaluate --baseline.
The entries[].review object is additive review metadata for later RIPR Zero
reporting. New ledgers include owner, created_at, review_after, and
source fields alongside the original reviewed and reason fields. Older
Campaign 17 ledgers that only contain reviewed and reason, or no entry
review object at all, remain valid inputs for baseline diff and shrink-only
update.
Gate Baseline Update
ripr baseline update --remove-resolved refreshes a reviewed baseline ledger in
shrink-only mode. It removes reviewed baseline entries that are absent from the
current gate-decision evidence and never adopts new current debt.
Command:
ripr baseline update \
--baseline .ripr/gate-baseline.json \
--current target/ripr/reports/gate-decision.json \
--remove-resolved \
--out .ripr/gate-baseline.json
Options:
--baseline- reviewed baseline ledger to refresh.--current- current gate-decision JSON fromripr gate evaluate.--remove-resolved- required shrink-only mode.--out- updated baseline path. Defaults to--baseline.
The update command hard-fails if either input is missing or unsupported. It preserves malformed entries without stable identity and ambiguous matches for manual review. New current gate decisions are counted as ignored and are not inserted into the baseline. Generated CI must not use this command to rewrite checked-in baselines automatically.
The output is the same kind = "gate_baseline" ledger with updated entries
and summary counts plus an additive update receipt:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "gate_baseline",
"summary": {
"entries": 40,
"included": 39,
"skipped": {
"malformed": 1
}
},
"entries": [],
"update": {
"remove_resolved": true,
"current_gate_decision": "target/ripr/reports/gate-decision.json",
"removed_resolved": 7,
"ignored_new_current": 2
},
"warnings": [
"preserved malformed baseline entry without stable identity during shrink-only update"
],
"limits_note": "Shrink-only baseline refresh over static RIPR gate evidence; update removes resolved reviewed debt and never adopts new current debt."
}
Baseline Debt Delta Report
RIPR-SPEC-0016 defines the baseline debt delta report. The report compares an explicit reviewed baseline ledger with current gate-decision evidence so teams can see existing, resolved, new, acknowledged, suppressed, stale, invalid, and missing-input behavioral-grip debt without making the report a gate.
Command:
ripr baseline diff \
--baseline .ripr/gate-baseline.json \
--current target/ripr/reports/gate-decision.json \
--out target/ripr/reports/baseline-debt-delta.json \
--out-md target/ripr/reports/baseline-debt-delta.md
The report writes:
target/ripr/reports/baseline-debt-delta.json
target/ripr/reports/baseline-debt-delta.md
This report is advisory movement evidence. ripr gate evaluate remains the
pass/fail authority for configured gate modes. Generated CI uploads and
summarizes the delta report when RIPR_GATE_BASELINE is set and
gate-decision.json exists, but the report itself must not fail CI, rewrite a
baseline, post comments, edit source, generate tests, rerun analysis, or run
mutation testing.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "baseline_debt_delta",
"status": "advisory",
"root": ".",
"inputs": {
"baseline": ".ripr/gate-baseline.json",
"current_gate_decision": "target/ripr/reports/gate-decision.json",
"pr_guidance": null,
"agent_receipt": null
},
"baseline": {
"path": ".ripr/gate-baseline.json",
"schema_version": "0.1",
"entries": 47,
"valid": 46,
"stale": 1,
"invalid": 0
},
"delta": {
"still_present": 40,
"resolved": 7,
"new_policy_eligible": 2,
"acknowledged": 1,
"suppressed": 0,
"stale_baseline_entry": 1,
"invalid_baseline_entry": 0,
"missing_current_input": 0
},
"items": [
{
"bucket": "new_policy_eligible",
"identity": {
"canonical_gap_id": "pricing::discount::threshold_equality",
"seam_id": "67fc764ba37d77bd",
"source_id": "ripr-review-67fc764ba37d77bd",
"id": "ripr-gate-67fc764ba37d77bd",
"dedupe_key": null,
"fallback": "src/pricing.rs:88:weakly_gripped",
"matched_by": "canonical_gap_id"
},
"path": "src/pricing.rs",
"line": 88,
"static_class": "weakly_gripped",
"decision": "blocking",
"reason": "Current policy-eligible gap is not present in the reviewed baseline.",
"missing_discriminator": "amount == discount_threshold",
"suggested_test": {
"recommended_test": "tests/pricing.rs::applies_discount_above_threshold",
"assertion_shape": "Assert returned discount behavior directly."
},
"repair": {
"action": "add_focused_test_or_acknowledge",
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json"
},
"review": null
}
],
"warnings": [],
"limits_note": "Advisory baseline debt movement over static RIPR gate evidence; pass/fail remains owned by ripr gate evaluate."
}
Field contract:
schema_version- currently"0.1".status- currentlyadvisory. The report does not returnblocked; blocking belongs to the gate evaluator.inputs.baseline- explicit baseline ledger path. Missing or unreadable required baseline input produces a repair-oriented warning and amissing_current_inputitem instead of treating the baseline as resolved.inputs.current_gate_decision- current gate-decision JSON path.inputs.pr_guidance,inputs.agent_receipt, and other optional inputs - used only to enrich repair context when supplied.baseline.entries- parsed baseline entry count.baseline.valid,baseline.stale, andbaseline.invalid- baseline record health counts after current comparison.delta.still_present- baseline identities present in current evidence.delta.resolved- baseline identities absent from current evidence.delta.new_policy_eligible- current policy-eligible identities absent from the baseline.delta.acknowledged- current visible findings acknowledged by label or policy.delta.suppressed- current findings hidden by suppression or configured-off severity while remaining visible in the delta report.delta.stale_baseline_entry- baseline records that parse but cannot join cleanly because the identity is ambiguous, obsolete, or incompatible.delta.invalid_baseline_entry- malformed baseline records or records missing required identity fields.delta.missing_current_input- records whose movement cannot be classified because required current artifacts are missing or unreadable.items[].bucket- one primary bucket from thedeltaobject.items[].identity- stable identity fields. Matching order iscanonical_gap_id,seam_id,source_id,id,dedupe_key, then normalized path, line, and static class fallback.canonical_gap_idmay be supplied directly, throughidentity.canonical_gap_id, or throughevidence_record.canonical_gap_id; when absent it remainsnullfor backward-compatible ledgers.items[].identity.matched_by- the identity selector that joined baseline and current records.items[].repair- focused repair context from the current gate decision and built-in baseline debt movement actions.items[].review- optional reviewed baseline metadata copied from the baseline ledger when the item is baseline-derived. It preservesreviewed,owner,reason,created_at,review_after, andsourcewhen present. Current-only items usenull; older Campaign 17 entries with onlyreviewedandreasonremain valid and render missing metadata fields asnull.warnings[]- malformed baseline entries, ambiguous matches, fallback matches, missing optional inputs, or unsupported schema versions.limits_note- advisory boundary text for generated CI summaries.
Markdown should fit in a generated CI job summary. It should include the baseline path, status, bucket counts, top new policy-eligible gaps, top resolved baseline entries, warnings, and the advisory boundary. It must distinguish baseline debt from suppressions and acknowledged current findings from hidden success.
RIPR Zero Status Report
RIPR-SPEC-0017 defines the RIPR Zero status report. ripr zero status joins
existing baseline ledgers, baseline debt deltas, gate decisions, PR guidance,
gap decision ledgers, and optional calibration or receipt artifacts so teams
can see repo-level movement toward RIPR 0 without changing analyzer identity,
gate policy, or advisory defaults.
Command:
ripr zero status \
--baseline .ripr/gate-baseline.json \
--delta target/ripr/reports/baseline-debt-delta.json \
--gap-ledger target/ripr/reports/gap-decision-ledger.json \
--gate target/ripr/reports/gate-decision.json \
--pr-guidance target/ripr/review/comments.json \
--recommendation-calibration target/ripr/reports/recommendation-calibration.json \
--out target/ripr/reports/ripr-zero-status.json \
--out-md target/ripr/reports/ripr-zero-status.md
The report writes:
target/ripr/reports/ripr-zero-status.json
target/ripr/reports/ripr-zero-status.md
This report is advisory progress evidence. ripr gate evaluate remains the
pass/fail authority for configured gate modes. Generated CI uploads and
summarizes ripr-zero-status.{json,md} when baseline-debt-delta.json exists,
but the report itself must not fail CI, rewrite baselines, post comments, edit
source, generate tests, rerun analysis, call an LLM, or run mutation testing.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "ripr_zero_status",
"status": "advisory",
"root": ".",
"generated_at": "2026-05-08T00:00:00Z",
"inputs": {
"baseline": ".ripr/gate-baseline.json",
"baseline_debt_delta": "target/ripr/reports/baseline-debt-delta.json",
"gap_decision_ledger": "target/ripr/reports/gap-decision-ledger.json",
"gate_decision": "target/ripr/reports/gate-decision.json",
"pr_guidance": "target/ripr/review/comments.json",
"recommendation_calibration": null,
"previous_status": null
},
"ripr_zero": {
"state": "not_yet",
"target_source": "gap_decision_ledger",
"visible_unresolved": 43,
"new_policy_eligible": 1,
"blocking_candidates": 0,
"acknowledged": 1,
"suppressed": 0,
"limits_note": "RIPR 0 means no visible unresolved behavioral test-grip gaps under configured scope and policy; it is not a coverage or runtime adequacy claim."
},
"baseline": {
"path": ".ripr/gate-baseline.json",
"entries": 47,
"still_present": 40,
"resolved": 7,
"age_days": 31,
"metadata": {
"current": 38,
"stale": 4,
"missing_metadata": 5,
"unknown": 0
}
},
"debt_delta": {
"still_present": 40,
"resolved": 7,
"new": 2,
"new_policy_eligible": 1,
"acknowledged": 1,
"suppressed": 0,
"stale": 4,
"invalid": 0,
"missing_input": 0
},
"trend": {
"source": "not_available",
"window": null,
"visible_unresolved_delta": null,
"resolved_delta": null,
"new_policy_eligible_delta": null
},
"top_debt_areas": [
{
"rank": 1,
"area": "src/pricing.rs",
"visible_unresolved": 8,
"new_policy_eligible": 1,
"stale_baseline_entries": 2,
"top_static_class": "weakly_gripped"
}
],
"repair_routes": [
{
"rank": 1,
"source": "baseline_debt_delta",
"gap_id": null,
"canonical_gap_id": null,
"seam_id": "67fc764ba37d77bd",
"path": "src/pricing.rs",
"line": 88,
"missing_discriminator": "amount == discount_threshold",
"suggested_test": "Add an equality-boundary assertion.",
"related_test": "tests/pricing.rs::applies_discount_above_threshold",
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json",
"agent_command": "ripr agent start --root . --seam-id 67fc764ba37d77bd --out target/ripr/workflow",
"static_limitations": []
}
],
"warnings": [
"5 baseline entries are missing review metadata"
],
"limits_note": "Read-only advisory RIPR Zero status over existing static RIPR artifacts; gate-decision remains the pass/fail authority."
}
Field contract:
schema_version- currently"0.1".status-advisoryfor complete reports andincompletewhen required inputs are missing or unsupported.ripr_zero.state- one ofachieved,not_yet, orunknown.ripr_zero.target_source-gap_decision_ledgerwhen explicit GapRecord RIPR Zero targets were supplied, otherwisebaseline_debt_delta.ripr_zero.visible_unresolved- visible unresolved behavioral test-grip gaps under the supplied baseline and gate scope, or explicitprojection_eligibility.ripr_zero_countGapRecord targets when a gap ledger is supplied.ripr_zero.new_policy_eligible- current policy-eligible gaps that are not covered by the reviewed baseline.ripr_zero.blocking_candidates- current gate candidates that would block under the configured gate mode. The status report surfaces this count but does not make the blocking decision.ripr_zero.acknowledged- visible current findings acknowledged by label or policy.ripr_zero.suppressed- current findings hidden by suppression or configured-off severity while remaining visible in the status report.baseline.metadata.current,stale,missing_metadata, andunknown- baseline review metadata health counts. Missing metadata must not hide the entry.debt_delta.*- baseline movement buckets copied from the baseline debt delta report so summaries can show old debt, new debt, resolved debt, acknowledgements, suppressions, stale entries, invalid entries, and missing inputs without reinterpreting gate policy.trend.source-previous_status,ledger, ornot_available.top_debt_areas[]- capped groups by stable repo-relative path or configured area name. Grouping is a reporting surface, not an analyzer identity rewrite.repair_routes[]- capped focused repair candidates copied from existing PR guidance, gate decisions, baseline debt delta, agent packets, or receipts. When a baseline debt delta item suppliesevidence_record, RIPR Zero status prefers the record's location, grip class, missing discriminator, related test, assertion shape, verification command, and static limitations while preserving legacy top-level fields as fallback. The report must not invent missing commands or generated tests.warnings[]- stale baseline metadata, missing inputs, unsupported schemas, ambiguous identities, and trend gaps.limits_note- advisory boundary text for generated CI summaries.
Markdown should fit in a generated CI job summary. It should show RIPR 0 state, visible unresolved gaps, existing baseline gaps still present, resolved baseline gaps, new policy-eligible gaps, acknowledged gaps, suppressed gaps, stale metadata, the top repair route, warnings, and the advisory boundary. It must say that RIPR 0 is not perfect tests, 100 percent coverage, or runtime mutation adequacy.
Policy Readiness Report
RIPR-SPEC-0029 defines the policy readiness report. ripr policy readiness
joins explicit existing policy artifacts so maintainers can see the strictest
safe policy posture for the current repository without executing a gate or
changing any policy decision.
Command:
ripr policy readiness \
--gate-decision target/ripr/reports/gate-decision.json \
--baseline-delta target/ripr/reports/baseline-debt-delta.json \
--recommendation-calibration target/ripr/reports/recommendation-calibration.json \
--mutation-calibration target/ripr/reports/mutation-calibration.json \
--waiver-aging target/ripr/reports/waiver-aging.json \
--suppression-health target/ripr/reports/suppression-health.json \
--out target/ripr/reports/policy-readiness.json \
--out-md target/ripr/reports/policy-readiness.md
The report writes:
target/ripr/reports/policy-readiness.json
target/ripr/reports/policy-readiness.md
This report is advisory readiness evidence. ripr gate evaluate remains the
only pass/fail authority when an explicit gate mode is configured. The command
does not run analysis, mutate baselines or suppressions, post comments, edit
source, generate tests, run mutation testing, change gate policy, or make CI
blocking.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "policy_readiness",
"status": "ready_for_baseline_check",
"recommended_mode": "baseline-check",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"inputs": {
"gate_decision": "target/ripr/reports/gate-decision.json",
"baseline_delta": "target/ripr/reports/baseline-debt-delta.json",
"recommendation_calibration": null,
"mutation_calibration": null,
"waiver_aging": null,
"suppression_health": null,
"repo_config": null,
"previous_readiness": null
},
"summary": {
"blocking_ready": true,
"visible_only_ready": true,
"acknowledgeable_ready": false,
"baseline_check_ready": true,
"calibrated_gate_ready": false,
"preview_candidates": 1,
"preview_candidates_gate_eligible": 0,
"warnings": 0,
"unknowns": 6
},
"blocking_readiness": {
"state": "healthy",
"evidence": [
"gate_status=advisory",
"current_gate_mode=visible-only",
"blocking_candidates=0"
],
"warnings": [],
"next_action": "Keep generated CI advisory unless RIPR_GATE_MODE is explicitly configured."
},
"baseline_health": {
"state": "healthy",
"evidence": ["new_policy_eligible=0", "auto_adopt_new=false"],
"warnings": [],
"next_action": "Use baseline-check only with the reviewed baseline path supplied."
},
"waiver_health": {
"state": "missing",
"evidence": [],
"warnings": [],
"next_action": "Add waiver-aging input before requiring acknowledgement."
},
"suppression_health": {
"state": "missing",
"evidence": [],
"warnings": [],
"next_action": "Add suppression-health input before tightening policy."
},
"calibration_health": {
"state": "not_ready",
"evidence": [],
"warnings": [],
"next_action": "Collect same-class recommendation calibration before calibrated-gate."
},
"preview_evidence_boundary": {
"state": "healthy",
"preview_languages": ["typescript"],
"preview_findings_visible": 1,
"preview_findings_acknowledgeable": 1,
"preview_findings_suppressible": 1,
"preview_findings_baseline_advisory": 1,
"preview_findings_gate_eligible": 0,
"preview_findings_ripr_zero_blocking": 0,
"preview_findings_calibrated_confidence": 0,
"missing_language_status": 0,
"static_limits_seen": 1,
"static_limits_required": true,
"promotion_policy": null,
"warnings": [],
"next_action": "Keep preview evidence advisory until an explicit promotion policy exists."
},
"unknowns": [
{
"kind": "missing_input",
"message": "recommendation_calibration input not supplied.",
"source_artifact": null
},
{
"kind": "missing_input",
"message": "mutation_calibration input not supplied.",
"source_artifact": null
},
{
"kind": "missing_input",
"message": "waiver_aging input not supplied.",
"source_artifact": null
},
{
"kind": "missing_input",
"message": "suppression_health input not supplied.",
"source_artifact": null
},
{
"kind": "missing_input",
"message": "repo_config input not supplied.",
"source_artifact": null
},
{
"kind": "missing_input",
"message": "previous_readiness input not supplied.",
"source_artifact": null
}
],
"warnings": [],
"next_policy_action": "Enable baseline-check for stable Rust evidence only; keep preview evidence advisory.",
"limits_note": "Read-only advisory readiness over explicit artifacts; gate-decision remains the only pass/fail authority when configured.",
"preview_limits_note": "Preview-language evidence is visible and advisory by default; it is not gate-eligible, RIPR Zero blocking debt, or calibrated confidence without explicit promotion."
}
Field contract:
status- one ofadvisory_only,ready_for_visible_only,ready_for_acknowledgeable,ready_for_baseline_check,ready_for_calibrated_gate, orconfig_error.recommended_mode-advisory-only,visible-only,acknowledgeable,baseline-check, orcalibrated-gate. Values other thanadvisory-onlymatch gate mode strings.inputs- supplied artifact paths, ornullwhen omitted.summary.*_ready- boolean projection of which policy modes currently have enough readable input evidence.blocking_readiness,baseline_health,waiver_health,suppression_health, andcalibration_health- independent health axes withstate, evidence facts, warnings, and a next action.suppression_health.evidence[]- includes the suppliedsuppression_health_status, suppression count, missing owner/reason counts, stale count, overbroad scope count, unknown selector count, preview label gap count, warning count, and config-error count.warningorconfig_errorstatus prevents acknowledgeable readiness.preview_evidence_boundary- RIPR-SPEC-0030 projection. Preview findings remain visible while default gate eligibility, RIPR Zero blocking, and calibrated-confidence counts remain zero until explicit promotion. Missing preview labels keep the readiness recommendation advisory until repaired.unknowns[]- missing recommended or optional inputs. Missing inputs are not treated as passing evidence.warnings[]- malformed supplied inputs, preview metadata gaps, or policy readiness limitations.limits_noteandpreview_limits_note- advisory, pass/fail, and preview policy boundary text.
Markdown should fit in a job summary. It should show the status, recommended mode, each health axis, preview zero-count boundary, unknowns, warnings, next policy action, and limits. It must not claim runtime mutation outcomes or make the report a gate.
Policy Operations Report
RIPR-SPEC-0039 defines the policy operations report. ripr policy operations
composes explicit policy artifacts into one read-only operator
packet that names the current safe ceiling, next safe action, safe and blocked
promotion modes, blockers, action lists, warnings, unknowns, and input health.
Command:
ripr policy operations \
--policy-readiness target/ripr/reports/policy-readiness.json \
--waiver-aging target/ripr/reports/waiver-aging.json \
--suppression-health target/ripr/reports/suppression-health.json \
--baseline-delta target/ripr/reports/baseline-debt-delta.json \
--gate-decision target/ripr/reports/gate-decision.json \
--recommendation-calibration target/ripr/reports/recommendation-calibration.json \
--mutation-calibration target/ripr/reports/mutation-calibration.json \
--out target/ripr/reports/policy-operations.json \
--out-md target/ripr/reports/policy-operations.md
The report writes:
target/ripr/reports/policy-operations.json
target/ripr/reports/policy-operations.md
This report is advisory policy operations evidence. It does not execute a gate, mutate config, baselines, suppressions, workflows, branch protection, generated CI defaults, or source files, promote preview-language evidence, run analysis, generate tests, call providers, post comments, or run mutation testing.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "policy_operations",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"current_policy_ceiling": "ready_for_acknowledgeable",
"recommended_next_action": "Run shrink-only baseline review and remove resolved entries.",
"safe_to_promote_to": [
{
"mode": "visible-only",
"allowed_now": true,
"reason": "Policy readiness and supplied inputs allow visible-only advisory display.",
"source_artifacts": [
"target/ripr/reports/policy-readiness.json",
"target/ripr/reports/gate-decision.json"
]
},
{
"mode": "acknowledgeable",
"allowed_now": true,
"reason": "Waivers are visible PR-time acknowledgements and suppression health is readable.",
"source_artifacts": [
"target/ripr/reports/policy-readiness.json",
"target/ripr/reports/waiver-aging.json",
"target/ripr/reports/suppression-health.json"
]
}
],
"not_safe_to_promote_to": [
{
"mode": "baseline-check",
"allowed_now": false,
"reason": "Current policy ceiling ready_for_acknowledgeable does not allow baseline-check. Baseline contains 1 stale entries.",
"blockers": [
"current_ceiling_below_baseline_check",
"baseline_stale_entries"
],
"source_artifacts": [
"target/ripr/reports/baseline-debt-delta.json"
]
}
],
"promotion_blockers": [
{
"kind": "baseline_stale_entries",
"severity": "warning",
"message": "Baseline contains 1 stale entries.",
"target_modes": ["baseline-check", "calibrated-gate"],
"source_artifact": "target/ripr/reports/baseline-debt-delta.json",
"repair_action": "Run shrink-only baseline review and remove resolved entries."
}
],
"baseline_actions": [
"Review stale baseline entries.",
"Use shrink-only refresh for resolved debt."
],
"waiver_actions": [
"Review repeated PR-time acknowledgements before requiring acknowledgement.",
"Keep waivers visible and do not convert them to suppressions automatically."
],
"suppression_actions": [
"Keep durable suppressions visible with owner, reason, scope, and review metadata."
],
"calibration_actions": [
"Collect same-class recommendation calibration before calibrated-gate.",
"Optional mutation calibration was not supplied; keep runtime confirmation separate from static evidence."
],
"preview_boundary_actions": [
"Keep typescript preview evidence visible/advisory and excluded from gate eligibility, RIPR Zero blocking debt, and calibrated confidence."
],
"warnings": [
{
"kind": "missing_optional_input",
"message": "No mutation calibration input was supplied.",
"source_artifact": null
}
],
"unknowns": [
{
"kind": "preview_boundary_not_supplied",
"message": "Preview boundary details came only from policy readiness when available.",
"source_artifact": "target/ripr/reports/policy-readiness.json"
}
],
"input_artifacts": [
{
"kind": "policy_readiness",
"path": "target/ripr/reports/policy-readiness.json",
"status": "read"
},
{
"kind": "preview_boundary",
"path": null,
"status": "omitted"
}
],
"limits_note": "Read-only advisory policy operations report over explicit existing artifacts. Promotion requires separate manual review and configuration changes; this report never mutates config, baselines, suppressions, workflows, CI defaults, or preview-language eligibility."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".kind- always"policy_operations".current_policy_ceiling- copied or derived from policy readiness. Supported values areadvisory_only,ready_for_visible_only,ready_for_acknowledgeable,ready_for_baseline_check,ready_for_calibrated_gate,not_ready, andconfig_error.recommended_next_action- the first repair or operator action needed before stricter policy review.safe_to_promote_to[]- target modes currently allowed by the ceiling and readable dependent inputs.not_safe_to_promote_to[]- target modes blocked by ceiling, baseline, waiver, suppression, calibration, preview-boundary, or input health.promotion_blockers[]- normalized blocker records with severity, target modes, source artifact, and repair action.baseline_actions[],waiver_actions[],suppression_actions[],calibration_actions[], andpreview_boundary_actions[]- operator actions grouped by policy surface.warnings[]- malformed supplied inputs or optional evidence gaps.unknowns[]- missing or unknowable context that limits confidence.input_artifacts[]- one record for every operations input. Status values areread,omitted,missing,malformed, andnot_applicable.limits_note- static advisory boundary and no-mutation policy text.
Markdown should fit in a job summary. It should show current ceiling, next safe action, can-promote and cannot-promote sections, top blockers, grouped actions, warnings, unknowns, input artifact status, and limits. It must not make a gate decision or promote preview-language evidence.
Policy History Report
RIPR-SPEC-0041 defines the policy history report. ripr policy history reads a
current policy-operations.json report plus an optional append-only history
JSONL input and writes a read-only advisory trend packet. The report shows
whether readiness, waiver pressure, suppression health, baseline movement,
preview-boundary state, and calibration health improved, regressed, stayed
unchanged, or are unknown.
Command:
ripr policy history \
--current target/ripr/reports/policy-operations.json \
--history .ripr/policy-history.jsonl \
--commit HEAD \
--pr-number 123 \
--out target/ripr/reports/policy-history.json \
--out-md target/ripr/reports/policy-history.md
The report writes:
target/ripr/reports/policy-history.json
target/ripr/reports/policy-history.md
This report is advisory policy trend evidence. It does not append to
.ripr/policy-history.jsonl, execute gates, collect telemetry, mutate config,
baselines, suppressions, workflows, branch protection, generated CI defaults,
or source files, promote preview-language evidence, run analysis, generate
tests, call providers, post comments, or run mutation testing.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "policy_history",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"current": {
"commit": "HEAD",
"pr_number": "123",
"generated_at": "unix_ms:1778277000000",
"recommended_mode": "acknowledgeable",
"current_policy_ceiling": "ready_for_acknowledgeable",
"baseline_health": "warning",
"waiver_health": "advisory",
"suppression_health": "healthy",
"calibration_health": "not_ready",
"preview_boundary_state": "healthy",
"new_policy_eligible_count": 1,
"waiver_count": 2,
"stale_suppression_count": 0,
"baseline_still_present": 4,
"baseline_resolved": 1
},
"history_summary": {
"entries": 3,
"oldest_generated_at": "unix_ms:1778190600000",
"newest_generated_at": "unix_ms:1778277000000",
"readiness_improved": true,
"waiver_pressure_increased": false,
"suppression_health_regressed": false,
"baseline_shrank": true,
"preview_remained_advisory": true,
"calibration_changed_ceiling": false
},
"trend": {
"ceiling": {
"previous": "ready_for_visible_only",
"current": "ready_for_acknowledgeable",
"direction": "improved"
},
"waiver_count": {
"previous": 3,
"current": 2,
"direction": "improved"
},
"stale_suppression_count": {
"previous": 0,
"current": 0,
"direction": "unchanged"
},
"baseline_still_present": {
"previous": 5,
"current": 4,
"direction": "improved"
},
"baseline_resolved": {
"previous": 0,
"current": 1,
"direction": "improved"
},
"preview_boundary_state": {
"previous": "healthy",
"current": "healthy",
"direction": "unchanged"
},
"calibration_health": {
"previous": "not_ready",
"current": "not_ready",
"direction": "unchanged"
}
},
"example_append_record": {
"commit": "HEAD",
"pr_number": "123",
"generated_at": "unix_ms:1778277000000",
"current_policy_ceiling": "ready_for_acknowledgeable",
"recommended_mode": "acknowledgeable"
},
"warnings": [],
"unknowns": [
{
"kind": "history_not_supplied",
"message": "No policy history JSONL was supplied; trend is limited to the current snapshot.",
"source_artifact": null
}
],
"input_artifacts": [
{
"kind": "policy_operations",
"path": "target/ripr/reports/policy-operations.json",
"status": "read"
},
{
"kind": "policy_history_jsonl",
"path": ".ripr/policy-history.jsonl",
"status": "missing"
}
],
"limits_note": "Read-only advisory policy history report. It reads explicit history inputs and never appends, mutates policy, or changes gate authority."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".kind- always"policy_history".current- normalized snapshot derived frompolicy-operations.jsonplus optional commit and PR metadata.current.recommended_mode- derived from the highest safe promotion mode or current policy operations ceiling.current.current_policy_ceiling- copied from policy operations.current.*_healthfields - normalized policy surface states derived from operations actions, blockers, and input artifacts.current.new_policy_eligible_count,waiver_count,stale_suppression_count,baseline_still_present, andbaseline_resolved- current movement counters when available, otherwise zero with an unknown.history_summary.entries- count of prior plus current snapshots included in the trend.history_summary.readiness_improved- true only when the current ceiling ranks higher than the previous comparable snapshot.history_summary.waiver_pressure_increased- true when waiver count rises.history_summary.suppression_health_regressed- true when stale or malformed suppression signals rise.history_summary.baseline_shrank- true when still-present baseline debt falls or resolved baseline debt rises without adopt-new behavior.history_summary.preview_remained_advisory- true only when preview evidence stayed non-gating across comparable snapshots.history_summary.calibration_changed_ceiling- true when calibration health improvement is the reason the ceiling changed.trend.*.direction-improved,regressed,unchanged, orunknown.example_append_record- the current snapshot in appendable JSONL shape. It is advisory output only and must not be written automatically.warnings[]- malformed supplied history lines, malformed current input, or unsupported historical shapes.unknowns[]- missing optional history, commit, PR number, or unavailable metric fields.input_artifacts[]- per-input status. Status values areread,omitted,missing,malformed, andnot_applicable.limits_note- read-only/no-telemetry/no-mutation/no-gate boundary.
Markdown should fit in generated CI summaries and report packets. It should show the current ceiling, recommended mode, history entry count, trend summary, current snapshot counters, input artifact status, an optional manual append record, warnings, unknowns, and limits. It must not append history automatically, make a gate decision, or promote preview-language evidence.
Policy Promotion Packet
RIPR-SPEC-0042 defines the policy promotion packet. ripr policy promote
reads a current policy-operations.json report plus optional
policy-history.json and writes a read-only manual-review packet for one target
mode.
Command:
ripr policy promote \
--to baseline-check \
--operations target/ripr/reports/policy-operations.json \
--history target/ripr/reports/policy-history.json \
--out target/ripr/reports/policy-promotion-baseline-check.json \
--out-md target/ripr/reports/policy-promotion-baseline-check.md
The report writes:
target/ripr/reports/policy-promotion-visible-only.json
target/ripr/reports/policy-promotion-visible-only.md
target/ripr/reports/policy-promotion-acknowledgeable.json
target/ripr/reports/policy-promotion-acknowledgeable.md
target/ripr/reports/policy-promotion-baseline-check.json
target/ripr/reports/policy-promotion-baseline-check.md
target/ripr/reports/policy-promotion-calibrated-gate.json
target/ripr/reports/policy-promotion-calibrated-gate.md
This report is advisory policy review evidence. It does not mutate ripr.toml,
baselines, suppressions, workflows, branch protection, generated CI defaults,
source files, history ledgers, or preview-language eligibility. It does not
execute gates, post comments, run analysis, generate tests, call providers, run
mutation testing, or make CI blocking by default.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "policy_promotion_packet",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"target_mode": "baseline-check",
"allowed_now": false,
"why_or_why_not": "Baseline contains stale entries and suppression health has warnings.",
"required_repairs": [
"Run shrink-only baseline review and remove resolved entries.",
"Repair suppression-health warnings before tightening policy."
],
"required_receipts": [
"policy-operations.json showing baseline-check in safe_to_promote_to",
"policy-history.json showing baseline debt is not being normalized",
"baseline-debt-delta.json showing reviewed shrink-only movement",
"suppression-health.json showing durable exception metadata is healthy"
],
"rollback_path": [
"Revert the manual gate-mode config change.",
"Return to visible-only or acknowledgeable policy mode.",
"Keep policy operations and history artifacts for audit."
],
"example_config_change": {
"file": "ripr.toml",
"change": "Set the reviewed policy gate mode to baseline-check.",
"manual_only": true
},
"input_artifacts": [
{
"kind": "policy_operations",
"path": "target/ripr/reports/policy-operations.json",
"status": "read"
},
{
"kind": "policy_history",
"path": "target/ripr/reports/policy-history.json",
"status": "read"
}
],
"warnings": [],
"unknowns": [],
"non_goals": [
"No automatic config mutation.",
"No automatic baseline adoption.",
"No suppression creation.",
"No default CI blocking.",
"No preview-language promotion."
],
"limits_note": "Read-only advisory promotion packet. It supports manual review only and never mutates policy configuration or gate authority."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".kind- always"policy_promotion_packet".target_mode- one ofvisible-only,acknowledgeable,baseline-check, orcalibrated-gate.allowed_now- true only when policy operations lists the target insafe_to_promote_to.why_or_why_not- explanation from the operations safe/not-safe entry and blockers.required_repairs[]- blocker repair actions required before manual promotion review.required_receipts[]- artifacts reviewers should inspect before accepting a manual config change.rollback_path[]- explicit steps to return to a less strict posture.example_config_change- manual review guidance only. The command must not write this change.input_artifacts[]- per-input status.warnings[]- malformed supplied inputs, unsupported history shape, or target-mode limitations.unknowns[]- missing optional history or unavailable supporting context.non_goals[]- hard boundaries repeated in the packet.limits_note- read-only/manual-review/no-mutation boundary.
Markdown should fit in generated CI summaries and report packets. It should show the target mode, allowed status, why/why not explanation, required repairs, required receipts, rollback path, manual-only config example, input artifact status, warnings, unknowns, non-goals, and limits. It must not mutate policy configuration or promote preview-language evidence.
Preview Evidence Promotion Packet
RIPR-SPEC-0044 defines the preview evidence promotion packet. The
ripr policy preview-promote command writes a read-only advisory packet for a
preview language and evidence class. The default result is blocked:
allowed_now = false with reason preview promotion evidence not supplied.
The maintainer-facing proof checklist is
Preview promotion criteria.
Command:
ripr policy preview-promote \
--language typescript \
--class boundary_gap \
--evidence target/ripr/reports/preview-promotion-evidence.json \
--out target/ripr/reports/preview-promotion-typescript-boundary-gap.json \
--out-md target/ripr/reports/preview-promotion-typescript-boundary-gap.md
The report writes:
target/ripr/reports/preview-promotion-<language>-<class>.json
target/ripr/reports/preview-promotion-<language>-<class>.md
This report is advisory policy review evidence. It does not mutate ripr.toml,
baselines, suppressions, workflows, branch protection, generated CI defaults,
source files, history ledgers, gate configuration, RIPR Zero membership,
calibrated confidence, or preview-language eligibility. It does not execute
gates, post comments, run analysis, generate tests, call providers, run
mutation testing, or make CI blocking by default.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "preview_evidence_promotion_packet",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"language": "typescript",
"language_status": "preview",
"candidate_class": "boundary_gap",
"target_status": "policy_eligible",
"allowed_now": false,
"reason": "preview promotion evidence not supplied",
"required_evidence": [
{
"kind": "fixture_corpus_coverage",
"required": true,
"description": "Representative fixtures cover the candidate class and known static limits."
},
{
"kind": "static_limit_exclusions",
"required": true,
"description": "Known static parser, language-adapter, and static-limit taxonomy limits are covered, excluded, or labeled."
},
{
"kind": "false_positive_review",
"required": true,
"description": "Maintainer-reviewed false-positive sample is documented for this language and class."
},
{
"kind": "recommendation_calibration",
"required": true,
"description": "Same-class recommendation calibration supports policy eligibility."
},
{
"kind": "dogfood_receipts",
"required": true,
"description": "External-style dogfood receipts exercise the candidate language and class through the start-here repair loop."
},
{
"kind": "related_test_accuracy_review",
"required": true,
"description": "Maintainer-reviewed related-test samples show the candidate language does not route repair packets to wrong tests."
},
{
"kind": "false_repair_packet_review",
"required": true,
"description": "Maintainer-reviewed sample confirms preview repair packets do not overstate or invent safe repairs."
},
{
"kind": "surface_consistency_review",
"required": true,
"description": "Editor, CLI, generated CI, PR evidence, receipts, and docs show the same preview/advisory boundary."
},
{
"kind": "policy_signoff",
"required": true,
"description": "Policy owner explicitly signs off that the narrow language/class may be reviewed for stronger status."
},
{
"kind": "mutation_calibration",
"required": false,
"description": "Optional runtime calibration exists for this language and class without being inferred from Rust."
},
{
"kind": "baseline_behavior",
"required": true,
"description": "Baseline handling keeps preview debt visible and does not auto-adopt new preview findings."
},
{
"kind": "waiver_suppression_behavior",
"required": true,
"description": "Waivers and suppressions preserve owner, reason, scope, and preview status."
},
{
"kind": "rollback_path",
"required": true,
"description": "Manual rollback to advisory preview status is documented."
},
{
"kind": "generated_ci_posture",
"required": true,
"description": "Generated CI remains advisory and non-blocking unless a later explicit gate mode is configured."
}
],
"supplied_evidence": [],
"missing_evidence": [
"fixture_corpus_coverage",
"static_limit_exclusions",
"false_positive_review",
"recommendation_calibration",
"dogfood_receipts",
"related_test_accuracy_review",
"false_repair_packet_review",
"surface_consistency_review",
"policy_signoff",
"baseline_behavior",
"waiver_suppression_behavior",
"rollback_path",
"generated_ci_posture"
],
"required_repairs": [
"Supply explicit preview promotion evidence before policy eligibility review."
],
"required_receipts": [
"preview-promotion-typescript-boundary-gap.json",
"preview-boundary report showing advisory language status",
"fixture corpus coverage receipt for TypeScript boundary_gap",
"static-limit exclusions receipt for TypeScript boundary_gap",
"false-positive review receipt for TypeScript boundary_gap",
"recommendation-calibration receipt for TypeScript boundary_gap",
"dogfood receipt for TypeScript boundary_gap",
"related-test accuracy review receipt for TypeScript boundary_gap",
"false repair packet review receipt for TypeScript boundary_gap",
"surface consistency receipt for TypeScript boundary_gap",
"policy signoff receipt for TypeScript boundary_gap",
"baseline behavior receipt for TypeScript boundary_gap",
"waiver/suppression behavior receipt for TypeScript boundary_gap",
"rollback path receipt for TypeScript boundary_gap",
"generated CI posture receipt for TypeScript boundary_gap"
],
"rollback_path": [
"Keep TypeScript boundary_gap evidence advisory.",
"Remove any manual preview promotion config if one was reviewed later.",
"Regenerate policy operations and preview promotion packets after rollback."
],
"generated_ci_posture": {
"may_upload_artifact": true,
"may_summarize_artifact": true,
"may_fail_check": false,
"may_post_comment": false,
"may_mutate_config": false
},
"input_artifacts": [],
"warnings": [],
"unknowns": [],
"non_goals": [
"No actual promotion.",
"No gate eligibility change.",
"No RIPR Zero inclusion.",
"No calibrated confidence.",
"No CI blocking."
],
"limits_note": "Read-only advisory preview promotion packet. Preview evidence remains visible and non-gating until a later explicit promotion policy is reviewed."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".kind- always"preview_evidence_promotion_packet".language- requested preview language.language_status- current status, initially"preview".candidate_class- requested evidence class.target_status- requested future policy status. The packet may describe it but must not apply it.allowed_now- false unless every required evidence item is supplied and a later implementation explicitly recognizes those receipts.reason- concise explanation for the decision.required_evidence[]- full evidence checklist for preview promotion.supplied_evidence[]- evidence receipts accepted by the packet.missing_evidence[]- required evidence still absent.required_repairs[]- concrete work before a maintainer can review promotion.required_receipts[]- artifacts reviewers should inspect before promotion.rollback_path[]- explicit return path to advisory preview status.generated_ci_posture- advisory CI permissions and hard denials.input_artifacts[]- optional explicit evidence input status.warnings[]- malformed supplied inputs or target-language limitations.unknowns[]- unavailable context that must stay visible.non_goals[]- hard boundaries repeated in the packet.limits_note- read-only/manual-review/no-promotion boundary.
Markdown should fit in generated CI summaries and report packets. It should show language, class, current status, target status, allowed status, reason, supplied and missing evidence, required repairs, required receipts, rollback path, generated CI posture, input artifact status, warnings, unknowns, non-goals, and limits. It must not promote preview evidence or mutate policy.
Suppression Health Report
ripr policy suppression-health summarizes the durable suppression manifest
without applying suppressions or changing policy. It exists so teams can audit
whether durable exceptions have enough metadata before stricter policy modes
depend on them.
Command:
ripr policy suppression-health \
--root . \
--manifest .ripr/suppressions.toml \
--out target/ripr/reports/suppression-health.json \
--out-md target/ripr/reports/suppression-health.md
The report writes:
target/ripr/reports/suppression-health.json
target/ripr/reports/suppression-health.md
This report is advisory policy evidence. It does not run analysis, mutate baselines or suppressions, post comments, edit source, generate tests, run mutation testing, change gate policy, or make CI blocking.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "suppression_health",
"status": "warning",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"inputs": {
"manifest": ".ripr/suppressions.toml"
},
"summary": {
"suppressions": 2,
"healthy": 1,
"missing_owner": 0,
"missing_reason": 0,
"missing_scope": 1,
"missing_created_at": 0,
"missing_last_seen": 0,
"missing_review_by_or_expires": 0,
"missing_expected_visibility": 0,
"missing_static_class": 0,
"stale": 0,
"overbroad_scope": 1,
"unknown_selector": 0,
"preview_without_preview_label": 1,
"warnings": 3,
"config_errors": 0
},
"records": [
{
"identity": "probe:src/pricing.rs:88:predicate",
"kind": "exposure_gap",
"owner": "billing",
"reason": "accepted durable policy exception",
"scope": "seam:pricing::threshold",
"created_at": "2026-01-01",
"last_seen": "2026-05-01",
"expires": null,
"review_by": "2026-12-01",
"expected_visibility": "suppressed_visible",
"static_class": "weakly_exposed",
"language": "rust",
"language_status": null,
"health": "healthy",
"still_visible": true,
"source": ".ripr/suppressions.toml:4",
"findings": []
}
],
"findings": [
{
"kind": "preview_without_preview_label",
"severity": "warning",
"message": "preview-language suppression is missing language_status = \"preview\"",
"source": ".ripr/suppressions.toml:18"
}
],
"warnings": [],
"limits_note": "Read-only advisory suppression-health report over the durable suppression manifest; suppressions remain visible and the report never creates, deletes, applies, or gates on suppressions."
}
Field contract:
static_classis required forexposure_gaprecords because it identifies the exposure class covered by the durable exception. It is not applicable totest_efficiencyrecords, which select a test and optional path instead.status-no_suppressionswhen the manifest is missing or empty,healthywhen all parsed records have complete policy metadata,warningwhen valid records need review, orconfig_errorwhen the manifest is malformed.summary.missing_ownerandsummary.missing_reason- parser-level structural errors. Owner and reason remain required for every durable suppression.summary.stale- entries whoseexpiresorreview_bydate is before the report date.summary.overbroad_scope- entries whose scope is explicitly broad, or test-efficiency suppressions that omitpath.summary.unknown_selector- unsupported kinds, missing required selectors, blank selectors, or duplicate selectors.summary.preview_without_preview_label- preview-language suppressions that omitlanguage_status = "preview".records[].still_visible- alwaystrue; suppression health never hides suppressed findings.findings[]- normalized findings withkind,severity,message, and optional source.limits_note- advisory/read-only boundary text.
Markdown should fit in a job summary. It should show the status, each durable suppression identity, owner, review date, findings, and the advisory boundary.
Waiver Aging Report
ripr policy waiver-aging summarizes visible PR-time waivers from the current
PR evidence ledger and optional prior ledger history. It exists so repeated
waiver remains a visible signal for repair or explicit policy review without
becoming a failure, a suppression, or a hidden exception.
Command:
ripr policy waiver-aging \
--ledger target/ripr/reports/pr-evidence-ledger.json \
--history .ripr/pr-evidence-ledger.jsonl \
--out target/ripr/reports/waiver-aging.json \
--out-md target/ripr/reports/waiver-aging.md
The report writes:
target/ripr/reports/waiver-aging.json
target/ripr/reports/waiver-aging.md
This report is advisory policy evidence. It does not run analysis, mutate baselines or suppressions, post comments, edit source, generate tests, run mutation testing, change gate policy, or make CI blocking.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "waiver_aging",
"status": "advisory",
"root": ".",
"generated_at": "unix_ms:1778277000000",
"inputs": {
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"history": ".ripr/pr-evidence-ledger.jsonl"
},
"summary": {
"waiver_count": 3,
"identity_count": 1,
"repeated_seam_count": 1,
"repeated_file_count": 1,
"max_age_prs": 3,
"max_age_days": 40,
"focused_test_candidates": 1,
"durable_suppression_candidates": 1,
"warnings": 0
},
"records": [
{
"identity": "pricing::discount::threshold_equality",
"canonical_gap_id": "pricing::discount::threshold_equality",
"seam_id": "67fc764ba37d77bd",
"file": "src/pricing.rs",
"owner": null,
"waiver_count": 3,
"first_seen": "pr#123",
"last_seen": "pr#125",
"age_prs": 3,
"age_days": 40,
"same_seam_waived_repeatedly": true,
"same_file_waived_repeatedly": true,
"candidate_for_focused_test": true,
"candidate_for_durable_suppression": true,
"reasons": ["accepted for this PR"],
"labels": ["ripr-waive"],
"still_visible": true,
"source_records": [
".ripr/pr-evidence-ledger.jsonl:1",
".ripr/pr-evidence-ledger.jsonl:2",
"target/ripr/reports/pr-evidence-ledger.json"
]
}
],
"warnings": [],
"limits_note": "Read-only advisory waiver-aging report over existing PR evidence ledgers; repeated waiver is a signal, not a failure or durable suppression."
}
Field contract:
status-advisory,no_waivers,incomplete, orconfig_error.inputs- supplied current PR ledger and JSONL history paths, ornullwhen omitted.summary.waiver_count- visible waiver observations across supplied ledgers.summary.identity_count- distinct canonical gap, seam, or waiver identities.summary.repeated_*- repeated-waiver signals. These are not failures.records[].identity- canonical gap id when available, else seam id, decision id, or a source-local fallback.records[].fileandrecords[].owner- copied from source ledgers when available; missing values staynull.records[].candidate_for_focused_test- advisory signal for repeated or aged waiver that should usually become a focused test.records[].candidate_for_durable_suppression- advisory signal for policy review only; it does not create or imply a suppression.records[].still_visible- waivers remain visible acknowledgements.warnings[]- malformed supplied inputs, invalid JSONL lines, or missing optional history.limits_note- advisory boundary text.
Markdown should fit in a job summary. It should show waiver identities, counts, age, candidate signals, warnings, and the policy boundary that repeated waiver is a visible signal rather than pass/fail authority.
PR Evidence Ledger
RIPR-SPEC-0018 defines the PR evidence ledger. ripr pr-ledger record records
per-PR behavioral grip movement from existing RIPR artifacts so teams can track
new policy-eligible gaps, resolved baseline debt, visible acknowledgements,
suppressions, repair receipts, and optional coverage/grip frontier signals
without changing analyzer identity, gate policy, or advisory defaults.
Command:
ripr pr-ledger record \
--pr-number 123 \
--head <sha> \
--base <sha> \
--gate target/ripr/reports/gate-decision.json \
--baseline-delta target/ripr/reports/baseline-debt-delta.json \
--zero-status target/ripr/reports/ripr-zero-status.json \
--pr-guidance target/ripr/review/comments.json \
--gap-ledger target/ripr/reports/gap-decision-ledger.json \
--recommendation-calibration target/ripr/reports/recommendation-calibration.json \
--agent-receipt target/ripr/reports/agent-receipt.json \
--coverage target/ripr/reports/coverage-summary.json \
--history .ripr/pr-evidence-ledger.jsonl \
--out target/ripr/reports/pr-evidence-ledger.json \
--out-md target/ripr/reports/pr-evidence-ledger.md
The report writes:
target/ripr/reports/pr-evidence-ledger.json
target/ripr/reports/pr-evidence-ledger.md
This report is advisory history. ripr gate evaluate remains the pass/fail
authority for configured gate modes. Generated GitHub CI runs
ripr pr-ledger record on pull requests when target/ripr/review/comments.json
exists, adds optional gate, baseline delta, RIPR Zero, recommendation
calibration, agent receipt, coverage, label, and history inputs when present,
and may add a gap decision ledger input when an explicit ledger artifact exists.
It uploads pr-evidence-ledger.{json,md} with the normal report packet and
appends a PR movement card to the job summary. The report itself must not fail
CI, rewrite baselines, post comments, edit source, generate tests, rerun
analysis, call an LLM, or run mutation testing.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "pr_evidence_ledger",
"status": "advisory",
"root": ".",
"generated_at": "2026-05-09T00:00:00Z",
"pr": {
"number": 123,
"base": "53ea9a205f569a5ca636ba0a7451c6aca8b5ad2e",
"head": "984d5222a058fbceecfb9b230baef65c47c52820",
"labels": ["ripr-waive"]
},
"inputs": {
"gate_decision": "target/ripr/reports/gate-decision.json",
"baseline_debt_delta": "target/ripr/reports/baseline-debt-delta.json",
"ripr_zero_status": "target/ripr/reports/ripr-zero-status.json",
"pr_guidance": "target/ripr/review/comments.json",
"gap_decision_ledger": "target/ripr/reports/gap-decision-ledger.json",
"recommendation_calibration": "target/ripr/reports/recommendation-calibration.json",
"agent_receipt": "target/ripr/reports/agent-receipt.json",
"coverage": "target/ripr/reports/coverage-summary.json",
"history": ".ripr/pr-evidence-ledger.jsonl"
},
"movement": {
"new_policy_eligible": 1,
"baseline_still_present": 40,
"baseline_resolved": 3,
"acknowledged": 1,
"suppressed": 0,
"blocking_candidates": 0,
"visible_unresolved": 41,
"ripr_zero_state": "not_yet"
},
"gate": {
"mode": "baseline-check",
"decision": "acknowledged",
"pass_fail_authority": "ripr gate evaluate",
"acknowledgement_label": "ripr-waive"
},
"waivers": [
{
"label": "ripr-waive",
"canonical_gap_id": "pricing::discount::threshold_equality",
"decision_id": "ripr-gate-67fc764ba37d77bd",
"seam_id": "67fc764ba37d77bd",
"age_prs": 1,
"age_days": 0,
"reason": "accepted for this PR",
"still_visible": true
}
],
"suppressions": [
{
"canonical_gap_id": "pricing::discount::threshold_equality",
"decision_id": "ripr-gate-suppressed",
"seam_id": "suppressed",
"source": ".ripr/suppressions.toml",
"owner": "test-platform",
"reason": "accepted durable policy exception",
"still_visible": true
}
],
"repair_receipts": [
{
"source": "agent_receipt",
"canonical_gap_id": "pricing::discount::threshold_equality",
"seam_id": "67fc764ba37d77bd",
"receipt_state": "receipt_movement_improved",
"static_movement": {
"state": "improved",
"source": "agent_receipt",
"artifact": "target/ripr/reports/agent-receipt.json"
},
"focused_test": "tests/pricing.rs::threshold_exact_boundary",
"receipt": "target/ripr/reports/agent-receipt.json"
}
],
"coverage_grip_frontier": {
"status": "available",
"coverage_delta_percent": 0.0,
"ripr_visible_unresolved_delta": -3,
"interpretation": "behavioral grip improved without line-coverage movement",
"quadrants": {
"covered_with_ripr_gap": 2,
"covered_without_ripr_gap": 12,
"uncovered_with_ripr_gap": 1,
"uncovered_without_ripr_gap": 0
}
},
"top_repair_route": {
"source": "gap_decision_ledger",
"gap_id": "gap:pr:pricing:threshold-boundary",
"canonical_gap_id": "pricing::discount::threshold_equality",
"seam_id": "67fc764ba37d77bd",
"path": "src/pricing.rs",
"line": 88,
"missing_discriminator": "amount == discount_threshold",
"suggested_test": "Add an equality-boundary assertion.",
"related_test": "tests/pricing.rs::applies_discount_above_threshold",
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json",
"agent_command": "ripr agent start --root . --seam-id 67fc764ba37d77bd --out target/ripr/workflow"
},
"history": {
"source": ".ripr/pr-evidence-ledger.jsonl",
"records": 42,
"waiver_age_max_days": 14,
"baseline_resolved_total": 45,
"new_policy_eligible_total": 3,
"trend": "improving"
},
"warnings": [
"coverage input is optional and does not determine pass/fail"
],
"limits_note": "Read-only advisory PR evidence ledger over existing static RIPR artifacts; gate-decision remains the pass/fail authority."
}
Field contract:
schema_version- currently"0.1".status-advisoryfor complete reports andincompletewhen PR identity or all evidence sources are missing.movement.*- copied or derived from existing gate, baseline delta, and RIPR Zero status artifacts. The ledger must not recompute analyzer semantics.gate.pass_fail_authority- namesripr gate evaluatewhenever a gate decision is present.waivers[]- PR-time visible acknowledgement records. Waivers do not hide findings and do not become suppressions.waivers[].canonical_gap_idis copied from source artifacts when available and remainsnullotherwise.suppressions[]- durable policy exceptions. Suppressions are not waivers and are not baseline debt.suppressions[].canonical_gap_idis copied from gate or baseline-delta evidence when available.repair_receipts[]- supplied outcome or agent receipt evidence.repair_receipts[].receipt_statecarries the canonical receipt lifecycle label:receipt_missing,receipt_found,receipt_stale,receipt_gap_mismatch,receipt_movement_improved,receipt_movement_unchanged, orreceipt_not_applicable.repair_receipts[].static_movementuses the same object shape as review guidance outcome receipts, includingstate,source, andartifact; the ledger must not infer receipt success from a missing artifact.repair_receipts[].canonical_gap_idis copied from receipts or recommendation provenance when supplied.coverage_grip_frontier.status-available,not_available, orunsupported.coverage_grip_frontier.*- keeps coverage movement separate from RIPR evidence movement. Coverage movement is execution evidence, not test adequacy.top_repair_route- copied from an explicit gap decision ledger when it supplies a repairable, stable Rust, PR-local gap record with a verification command. If no such gap record is present, the ledger falls back to existing PR guidance, RIPR Zero status, gate decision, agent packet, or receipt artifacts. Missing fields arenullplus warnings, not invented.top_repair_route.gap_idandtop_repair_route.canonical_gap_idare copied from the selected source artifact when available.history.*- present only when prior ledger history or previous ledger summary is supplied.warnings[]- missing inputs, unavailable coverage, unsupported schemas, ambiguous identities, and trend gaps.limits_note- advisory boundary text for generated CI summaries.
Markdown should fit in a generated CI job summary. It should show new policy-eligible gaps, existing baseline gaps still present, baseline gaps resolved, acknowledged gaps, suppressed gaps, blocking candidates, visible unresolved gaps, the top focused test to add, receipt paths, coverage/grip frontier status, and the advisory boundary. It must say that the PR evidence ledger is advisory history and that gate decisions remain the pass/fail authority.
See PR evidence ledger workflow for how teams read ledger records as waiver aging, baseline burn-down, repair receipts, coverage/grip frontier signals, and movement toward RIPR 0.
Coverage / Grip Frontier Report
ripr coverage-grip frontier writes an advisory report that keeps execution
coverage movement and static RIPR behavioral grip movement as separate axes. It
can consume a coverage summary plus any existing PR evidence ledger, baseline
debt delta, or RIPR Zero status report.
Command:
ripr coverage-grip frontier \
--coverage target/ripr/reports/coverage-summary.json \
--ledger target/ripr/reports/pr-evidence-ledger.json \
--baseline-delta target/ripr/reports/baseline-debt-delta.json \
--zero-status target/ripr/reports/ripr-zero-status.json \
--out target/ripr/reports/coverage-grip-frontier.json \
--out-md target/ripr/reports/coverage-grip-frontier.md
The report writes:
target/ripr/reports/coverage-grip-frontier.json
target/ripr/reports/coverage-grip-frontier.md
Coverage is optional. Without coverage input, the report still preserves RIPR
movement and marks the coverage axis not_available. The report must not
treat coverage as test adequacy, run mutation testing, change gate policy, post
comments, edit source, generate tests, call an LLM, or make CI blocking by
default.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "coverage_grip_frontier",
"status": "advisory",
"root": ".",
"generated_at": "2026-05-09T00:00:00Z",
"inputs": {
"coverage": "target/ripr/reports/coverage-summary.json",
"pr_evidence_ledger": "target/ripr/reports/pr-evidence-ledger.json",
"baseline_debt_delta": "target/ripr/reports/baseline-debt-delta.json",
"ripr_zero_status": "target/ripr/reports/ripr-zero-status.json"
},
"coverage": {
"status": "available",
"delta_percent": "0.0",
"source": "target/ripr/reports/coverage-summary.json"
},
"ripr": {
"source": "pr_evidence_ledger",
"new_policy_eligible": 1,
"baseline_resolved": 3,
"baseline_still_present": 2,
"acknowledged": 1,
"suppressed": 0,
"blocking_candidates": 0,
"visible_unresolved": 4,
"visible_unresolved_delta": -3
},
"quadrants": {
"covered_with_ripr_gap": 4,
"covered_without_ripr_gap": 20,
"uncovered_with_ripr_gap": 2,
"uncovered_without_ripr_gap": 8
},
"interpretation": "behavioral grip improved without line-coverage movement",
"warnings": [],
"limits_note": "Coverage is execution evidence; RIPR is static behavioral grip evidence. This report is advisory and does not claim test adequacy or runtime mutation outcomes."
}
Markdown shape:
# RIPR Coverage / Grip Frontier
Status: advisory
Coverage axis:
- Status: available
- Delta percent: 0.0
RIPR axis:
- Source: pr_evidence_ledger
- New policy-eligible gaps: 1
- Baseline gaps resolved: 3
- Visible unresolved gaps: 4
- Visible unresolved delta: -3
Interpretation:
- behavioral grip improved without line-coverage movement
The report may use these coverage inputs when present:
coverage_delta_percent;coverage.delta_percent;summary.coverage_delta_percent;ripr_visible_unresolved_delta;ripr.visible_unresolved_delta;quadrants.covered_with_ripr_gap;quadrants.covered_without_ripr_gap;quadrants.uncovered_with_ripr_gap;quadrants.uncovered_without_ripr_gap.
Test-Oracle Assistant Loop
RIPR-SPEC-0019 defines the end-to-end test-oracle assistant loop. ripr assistant-loop proof writes an advisory proof report that joins existing PR
guidance, editor or agent handoff packets, before/after static evidence,
receipts, PR evidence ledgers, and optional gate or coverage/grip frontier
reports without changing analyzer identity, recommendation ranking, gate
policy, editor behavior, or CI defaults.
When an input artifact supplies the shared Lane 1 evidence_record, the proof
report prefers that record for selected seam identity, owner/location, grip
class, missing discriminator, assertion shape, related test, static limits, and
before/after movement classes. Legacy PR guidance, agent packet, receipt, and
repo-exposure fields remain fallback for older artifacts.
Command shape:
ripr assistant-loop proof \
--pr-guidance target/ripr/review/comments.json \
--agent-packet target/ripr/workflow/agent-brief.json \
--before target/ripr/pilot/repo-exposure.json \
--after target/ripr/pilot/after.repo-exposure.json \
--receipt target/ripr/reports/agent-receipt.json \
--ledger target/ripr/reports/pr-evidence-ledger.json \
--coverage-frontier target/ripr/reports/coverage-grip-frontier.json \
--gate-decision target/ripr/reports/gate-decision.json \
--out target/ripr/reports/test-oracle-assistant-proof.json \
--out-md target/ripr/reports/test-oracle-assistant-proof.md
The report writes:
target/ripr/reports/test-oracle-assistant-proof.json
target/ripr/reports/test-oracle-assistant-proof.md
Generated GitHub CI writes the same artifacts when the required PR guidance, editor/agent brief, before/after static evidence, agent receipt, and PR evidence ledger inputs already exist. The generated workflow treats the report as advisory summary/artifact content only; it does not make the proof report a pass/fail authority, post comments, mutate the baseline, rerun hidden analysis, or print a placeholder when the required inputs are missing.
The report is advisory and read-only. It must not fail CI, post comments, edit source, generate tests, call an LLM provider, run mutation testing, or claim runtime confirmation from static evidence.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "test_oracle_assistant_loop",
"status": "advisory",
"root": ".",
"inputs": {
"pr_guidance": "target/ripr/review/comments.json",
"agent_packet": "target/ripr/workflow/agent-brief.json",
"before": "target/ripr/pilot/repo-exposure.json",
"after": "target/ripr/pilot/after.repo-exposure.json",
"receipt": "target/ripr/reports/agent-receipt.json",
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"coverage_frontier": "target/ripr/reports/coverage-grip-frontier.json"
},
"seam": {
"seam_id": "67fc764ba37d77bd",
"canonical_gap_id": null,
"owner": "pricing::discounted_total",
"seam_kind": "predicate_boundary",
"path": "src/pricing.rs",
"line": 88,
"grip_class": "weakly_gripped",
"missing_discriminator": "amount == discount_threshold",
"evidence_source": "evidence_record",
"static_limitations": []
},
"recommendation": {
"source": "evidence_record",
"placement": "changed_line",
"summary_only_reason": null,
"suggested_test": "Add an equality-boundary assertion.",
"related_test": "tests/pricing.rs::applies_discount_above_threshold",
"assertion_shape": "assert_eq!(discounted_total(100, 100), 90)",
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json"
},
"handoff": {
"source": "agent_packet",
"artifact": "target/ripr/workflow/agent-brief.json",
"agent_command": "ripr agent start --root . --seam-id 67fc764ba37d77bd --out target/ripr/workflow",
"external_provider": false
},
"evidence_movement": {
"state": "improved",
"before_class": "weakly_gripped",
"after_class": "strongly_gripped",
"source": "agent_receipt",
"artifact": "target/ripr/reports/agent-receipt.json"
},
"ci_projection": {
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"coverage_frontier": "target/ripr/reports/coverage-grip-frontier.json",
"gate_decision": null,
"pass_fail_authority": "gate decision when explicitly configured"
},
"warnings": [],
"limits": {
"advisory": true,
"source_edits": false,
"generated_tests": false,
"external_service": false,
"runtime_mutation_execution": false,
"ci_blocking_default": false
}
}
Field contract:
statusisadvisoryfor complete proof records andincompletewhen the selected seam or required before/after evidence is missing.inputs.*records explicit input paths. Missing optional inputs arenull; missing or invalid supplied inputs produce a warning.seam.*is copied from existing RIPR evidence or guidance. Whenevidence_recordis present in the agent packet or matching repo-exposure seam,seam.evidence_sourceisevidence_record, and the proof prefers the record's seam identity, canonical gap ID, owner, location, grip class, missing discriminator, and static limits. Otherwiseseam.evidence_sourceislegacy_fields. The report must not recompute analyzer identity.recommendation.placementischanged_line,summary_only, orunknown. Summary-only guidance must remain visible.recommendation.assertion_shape,recommendation.related_test, andrecommendation.verify_commandpreferevidence_record.recommendationfields when available and otherwise use the legacy agent packet or PR guidance fields.handoff.external_provideris alwaysfalse; RIPR emits packets but does not call a provider.evidence_movement.stateisimproved,resolved,unchanged,regressed, orunknown. It is static RIPR movement, not runtime mutation confirmation. Without a receipt, before/after class comparison prefers the matching repo-exposureevidence_record.grip_classand falls back to legacy seamgrip_class.ci_projection.pass_fail_authoritykeeps proof records separate from optional gate decisions.limits.*preserves the no-edit, no-generated-test, no-provider-call, no-runtime-mutation-execution, and advisory-default boundaries.
Markdown should fit in a PR summary, generated CI job summary, or dogfood receipt. It should show the selected seam, missing discriminator, suggested focused test, related test, verify command, before/after static movement, receipt path, ledger path, optional coverage/grip frontier path, assertion shape, owner, and static limits.
See Test-oracle assistant proof report for how reviewers, maintainers, and coding agents should read the report, warnings, optional CI projection, and advisory limits.
First Useful Action Report
RIPR-SPEC-0020 defines the first useful action report. ripr first-action
writes an advisory JSON and Markdown report that compresses existing
editor, PR guidance, gap decision ledger, PR evidence ledger, baseline,
assistant proof, receipt, optional gate, optional coverage/grip, and staleness
evidence into one next test action or one fallback reason. The report is
read-only and must not rerun hidden analysis, edit source, generate tests, call
a provider, run mutation testing, invent policy, or change default CI blocking.
See First useful action workflow for how developers, reviewers, and coding agents read the report, act on the selected action, verify static movement, emit receipts, and interpret fallback states.
The producer lives in crates/ripr/src/output/first_useful_action.rs; the
fixture corpus under fixtures/boundary_gap/expected/first-useful-action/
pins every bounded status plus expected JSON and Markdown routes.
Command shape:
ripr first-action \
--root . \
--pr-guidance target/ripr/review/comments.json \
--assistant-proof target/ripr/reports/test-oracle-assistant-proof.json \
--gap-ledger target/ripr/reports/gap-decision-ledger.json \
--ledger target/ripr/reports/pr-evidence-ledger.json \
--baseline-delta target/ripr/reports/baseline-debt-delta.json \
--receipt target/ripr/reports/agent-receipt.json \
--gate-decision target/ripr/reports/gate-decision.json \
--coverage-frontier target/ripr/reports/coverage-grip-frontier.json \
--editor-context target/ripr/workflow/evidence-context.json \
--out target/ripr/reports/first-useful-action.json \
--out-md target/ripr/reports/first-useful-action.md
The report writes:
target/ripr/reports/first-useful-action.json
target/ripr/reports/first-useful-action.md
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "first_useful_action",
"status": "actionable",
"audience": "developer",
"action_kind": "write_focused_test",
"root": ".",
"generated_at": "2026-05-09T12:00:00Z",
"inputs": {
"pr_guidance": "target/ripr/review/comments.json",
"assistant_proof": "target/ripr/reports/test-oracle-assistant-proof.json",
"gap_ledger": "target/ripr/reports/gap-decision-ledger.json",
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"baseline_delta": "target/ripr/reports/baseline-debt-delta.json",
"receipt": "target/ripr/reports/agent-receipt.json",
"gate_decision": "target/ripr/reports/gate-decision.json",
"coverage_frontier": "target/ripr/reports/coverage-grip-frontier.json",
"editor_context": "target/ripr/workflow/evidence-context.json"
},
"selected": {
"source": "assistant_proof",
"source_artifact": "target/ripr/reports/test-oracle-assistant-proof.json",
"seam_id": "67fc764ba37d77bd",
"seam_kind": "predicate_boundary",
"path": "src/pricing.rs",
"line": 88,
"classification": "weakly_exposed",
"missing_discriminator": "amount == discount_threshold",
"gap_id": "gap:pr:pricing:threshold-boundary",
"canonical_gap_id": "gap:rust:pricing:discount:threshold-boundary",
"repair_route": "AddBoundaryAssertion"
},
"title": "Add equality-boundary discriminator test",
"why": "Changed predicate boundary is weakly exposed and lacks an equality-boundary discriminator.",
"why_first": [
"The seam is PR-local.",
"The assistant proof report links guidance, handoff, before/after evidence, and receipt inputs.",
"No waiver, acknowledgement, or suppression applies."
],
"target": {
"file": "tests/pricing.rs",
"related_test": "below_threshold_has_no_discount",
"suggested_test_name": "discounted_total_boundary_discriminator",
"suggested_assertion": "Assert the exact returned discount at the equality boundary."
},
"commands": {
"context_packet": "ripr agent packet --root . --seam-id 67fc764ba37d77bd --json",
"after_snapshot": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/after.repo-exposure.json",
"verify": "ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json",
"receipt": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id 67fc764ba37d77bd --json"
},
"evidence": {
"pr_guidance": "target/ripr/review/comments.json",
"assistant_proof": "target/ripr/reports/test-oracle-assistant-proof.json",
"gap_ledger": "target/ripr/reports/gap-decision-ledger.json",
"receipt": "target/ripr/reports/agent-receipt.json",
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"static_movement": "unknown"
},
"fallback": null,
"warnings": [],
"limits": [
"Static evidence only.",
"Does not prove runtime adequacy.",
"Does not run mutation testing.",
"Does not edit source or generate tests.",
"Does not make CI blocking by default."
]
}
Field contract:
schema_versionis0.1until the report shape changes.kindis alwaysfirst_useful_action.statusis one ofactionable,stale,missing_required_artifact,baseline_only,acknowledged,waived,suppressed,no_actionable_seam,already_improved, orunchanged_after_attempt.action_kindis one ofwrite_focused_test,refresh_evidence,generate_missing_artifact,acknowledge_baseline,inspect_proof_report,revise_focused_test, orno_action.audienceisdeveloper,reviewer, oragent.inputs.*records explicit input paths. Missing optional inputs arenullor omitted for additive unsupplied fields; missing or invalid supplied inputs produce warnings and an appropriate fallback status.selected.*is copied from existing RIPR artifacts. The report must not mint a new seam identity or rerank findings with a provider.selected.gap_id,selected.canonical_gap_id, andselected.repair_routeare present when an explicit gap decision ledger drives the first action.why_firstrecords deterministic routing reasons. It must not be an opaque score.target.*records the recommended test file, related test, suggested test name, and assertion shape when supplied by existing artifacts.commands.*records copyable commands from existing command templates or supplied artifacts. Missing commands becomenulland warnings.evidence.*records supporting artifact paths and static movement when supplied. Static movement is not runtime mutation confirmation.fallbackrecords the reason for non-actionable statuses and the next safe command when available.limitspreserves static-evidence, no-edit, no-generated-test, no-provider-call, no-runtime-mutation-execution, and advisory-default boundaries.
Markdown should fit in a PR summary, generated CI job summary, or editor status detail. It should show status, audience, action kind, top action, deterministic why-first reasons, target file, related test, suggested test name, verification command, receipt command, supporting artifact paths, warnings, fallback reason when present, and static limits.
Generated CI runs ripr first-action only when one or more explicit upstream
RIPR artifacts already exist, uploads first-useful-action.{json,md} with the
normal report packet, and appends a compact at-a-glance summary. The projection
is advisory: ripr gate evaluate remains the only configured pass/fail
authority, and the first-action report must not edit source, generate tests,
call a provider, run mutation testing, rerun hidden analysis, or change default
blocking.
The VS Code extension may also read an existing
target/ripr/reports/first-useful-action.json and project the selected action
through the status bar and ripr: Show Status. That editor projection is not a
schema producer: it does not run ripr first-action, add diagnostics, edit
source, generate tests, call providers, run mutation testing, or make gate
decisions.
Assistant Loop Health Report
RIPR-SPEC-0022 defines the assistant-loop-health report contract.
ripr assistant-loop health reads one or more explicit
test-oracle-assistant-proof.json paths and writes advisory JSON and Markdown
that summarize proof completeness, missing inputs, static movement, warnings,
and bounded repair queues. The report is read-only and must not rerun hidden
analysis, inspect source to infer missing fields, edit source, generate tests,
call providers, run mutation testing, change recommendation ranking, change gate
policy, or change default CI blocking.
Command shape:
ripr assistant-loop health \
--proof target/ripr/reports/test-oracle-assistant-proof.json \
--out target/ripr/reports/assistant-loop-health.json \
--out-md target/ripr/reports/assistant-loop-health.md
The report writes:
target/ripr/reports/assistant-loop-health.json
target/ripr/reports/assistant-loop-health.md
Fixture corpus:
fixtures/boundary_gap/expected/assistant-loop-health/
The corpus pins complete-improved, partial-missing-optional, missing-required-input, unchanged, regressed, warning-heavy, and multi-proof health reports plus representative proof inputs for producer tests.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "assistant_loop_health",
"status": "advisory",
"root": ".",
"generated_at": "2026-05-09T12:00:00Z",
"inputs": {
"proofs": [
"target/ripr/reports/test-oracle-assistant-proof.json"
]
},
"summary": {
"proofs": 1,
"complete": 0,
"partial": 1,
"missing_required_input": 0,
"missing_optional_input": 1,
"improved": 1,
"unchanged": 0,
"regressed": 0,
"unknown_movement": 0,
"warnings": 2,
"repair_queue": 1
},
"proofs": [
{
"id": "proof-67fc764ba37d77bd",
"source_artifact": "target/ripr/reports/test-oracle-assistant-proof.json",
"proof_state": "partial",
"movement_state": "improved",
"seam": {
"seam_id": "67fc764ba37d77bd",
"seam_kind": "predicate_boundary",
"path": "src/pricing.rs",
"line": 88,
"grip_class": "weakly_gripped",
"missing_discriminator": "amount == discount_threshold"
},
"recommendation": {
"placement": "changed_line",
"related_test": "tests/pricing.rs::applies_discount_above_threshold",
"suggested_test": "Add an equality-boundary assertion.",
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json"
},
"handoff": {
"artifact": "target/ripr/workflow/agent-brief.json",
"agent_command": "ripr agent start --root . --seam-id 67fc764ba37d77bd --out target/ripr/workflow"
},
"receipt": {
"artifact": null,
"status": "missing"
},
"movement": {
"before_class": "weakly_gripped",
"after_class": "strongly_gripped",
"source": "agent_receipt"
},
"optional_context": {
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"gate_decision": null,
"coverage_frontier": "target/ripr/reports/coverage-grip-frontier.json",
"first_useful_action": "target/ripr/reports/first-useful-action.json"
},
"warnings": [
{
"kind": "missing_optional_input",
"message": "No gate decision input was supplied.",
"source_artifact": null
},
{
"kind": "missing_receipt",
"message": "No receipt was supplied for the repair attempt.",
"source_artifact": "target/ripr/reports/test-oracle-assistant-proof.json"
}
]
}
],
"warning_summary": [
{
"kind": "missing_optional_input",
"count": 1,
"examples": [
"No gate decision input was supplied."
]
},
{
"kind": "missing_receipt",
"count": 1,
"examples": [
"No receipt was supplied for the repair attempt."
]
}
],
"repair_queue": [
{
"repair_kind": "rerun_verify_and_receipt",
"source_artifact": "target/ripr/reports/test-oracle-assistant-proof.json",
"seam_id": "67fc764ba37d77bd",
"path": "src/pricing.rs",
"line": 88,
"reason": "Proof packet is missing an agent receipt.",
"next_command": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id 67fc764ba37d77bd --json",
"expected_result": "Attach a receipt so reviewers can inspect static before/after movement."
}
],
"limits": [
"Static RIPR evidence only.",
"Does not provide runtime confirmation.",
"Does not run mutation testing.",
"Does not call providers.",
"Does not edit source or generate tests.",
"Does not change default CI blocking.",
"Gate evaluator remains pass/fail authority."
]
}
Field contract:
schema_versionis0.1until the report shape changes.kindis alwaysassistant_loop_health.statusisadvisorywhen at least one proof path was read and summarized, orincompletewhen no proof path could be read.inputs.proofsrecords explicit proof paths in deterministic order.summary.*counts proof states, movement buckets, warnings, and repair queue entries. Counts are derived from report items; they are not an opaque score.proofs[].proof_stateiscomplete,partial, ormissing_required_input.proofs[].movement_stateisimproved,unchanged,regressed, orunknown. A source proof movement ofresolvedis counted asimproved.proofs[].seam,recommendation,handoff,receipt, andmovementfields are copied from existing proof artifacts when present. The health report must not mint seam identities or rerank recommendations.optional_context.*records optional artifact paths when the proof names them. Missing optional paths arenulland may also appear as warnings.warnings[].kindis one ofmissing_required_input,missing_optional_input,stale_input,malformed_input,incompatible_schema,summary_only_guidance,unchanged_movement,regressed_movement,missing_receipt,missing_handoff,unknown_movement,static_limit, orother.repair_queue[].repair_kindis one ofregenerate_proof,regenerate_missing_artifact,rerun_verify_and_receipt,refresh_before_after_evidence,inspect_unchanged_attempt,inspect_regression,inspect_summary_only_guidance,attach_receipt, orno_repair.limitspreserves static-evidence, no-edit, no-generated-test, no-provider-call, no-runtime-mutation-execution, and advisory-default boundaries.
Markdown should fit in a generated CI job summary or reviewer handoff. It
should show status, complete/partial/missing proof counts, movement counts, top
warning kinds, bounded repair queue entries that include repair_kind, and
advisory limits. For example, a repair row should begin with
rerun_verify_and_receipt before the file and reason. If no proof input can be
read, Markdown should show Status: incomplete and put the repair instruction
before empty counts.
Generated CI runs ripr assistant-loop health only when proof artifacts exist,
uploads assistant-loop-health.{json,md} with the normal report packet, and
appends a compact summary. The projection is advisory: ripr gate evaluate
remains the only configured pass/fail authority.
See Assistant loop health workflow for how maintainers and coding agents read complete versus partial proof packets, missing-input repairs, unchanged movement, generated-CI summaries, and advisory limits.
PR Review Front Panel Report
RIPR-SPEC-0023 defines the PR review front-panel report contract. The
ripr pr-review front-panel producer reads explicit existing RIPR artifacts and
writes advisory JSON and Markdown that summarize the PR's top test-oracle issue,
policy state, baseline movement, repair route, receipt state, optional
calibration, optional coverage/grip context, and artifact groups. The report is
read-only and does not rerun hidden analysis, inspect source to infer missing
fields, edit source, generate tests, call providers, run mutation testing,
change recommendation ranking, change gate policy, publish inline comments, or
change default CI blocking.
Command shape:
ripr pr-review front-panel \
--root . \
--pr-guidance target/ripr/review/comments.json \
--first-action target/ripr/reports/first-useful-action.json \
--assistant-proof target/ripr/reports/test-oracle-assistant-proof.json \
--assistant-health target/ripr/reports/assistant-loop-health.json \
--ledger target/ripr/reports/pr-evidence-ledger.json \
--baseline-delta target/ripr/reports/baseline-debt-delta.json \
--zero-status target/ripr/reports/ripr-zero-status.json \
--gate-decision target/ripr/reports/gate-decision.json \
--recommendation-calibration target/ripr/reports/recommendation-calibration.json \
--mutation-calibration target/ripr/reports/mutation-calibration.json \
--coverage-frontier target/ripr/reports/coverage-grip-frontier.json \
--receipt target/ripr/reports/agent-receipt.json \
--out target/ripr/reports/pr-review-front-panel.json \
--out-md target/ripr/reports/pr-review-front-panel.md
The report writes:
target/ripr/reports/pr-review-front-panel.json
target/ripr/reports/pr-review-front-panel.md
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "pr_review_front_panel",
"status": "advisory",
"root": ".",
"generated_at": "2026-05-09T12:00:00Z",
"inputs": {
"pr_guidance": "target/ripr/review/comments.json",
"first_action": "target/ripr/reports/first-useful-action.json",
"assistant_proof": "target/ripr/reports/test-oracle-assistant-proof.json",
"assistant_health": "target/ripr/reports/assistant-loop-health.json",
"ledger": "target/ripr/reports/pr-evidence-ledger.json",
"baseline_delta": "target/ripr/reports/baseline-debt-delta.json",
"zero_status": "target/ripr/reports/ripr-zero-status.json",
"gate_decision": "target/ripr/reports/gate-decision.json",
"recommendation_calibration": "target/ripr/reports/recommendation-calibration.json",
"mutation_calibration": null,
"coverage_frontier": "target/ripr/reports/coverage-grip-frontier.json",
"receipt": "target/ripr/reports/agent-receipt.json"
},
"summary": {
"status": "advisory",
"headline": "Add equality-boundary discriminator test.",
"top_issue_state": "actionable",
"policy_state": "new_policy_eligible",
"placement": "changed_line",
"movement_state": "unknown",
"coverage_grip_state": "not_available",
"blocking_candidates": 0,
"acknowledged": 0,
"suppressed": 0,
"new_policy_eligible": 1,
"baseline_still_present": 42,
"baseline_resolved": 3
},
"top_issue": {
"source": "first_useful_action",
"source_artifact": "target/ripr/reports/first-useful-action.json",
"seam_id": "67fc764ba37d77bd",
"canonical_gap_id": "gap-67fc764ba37d77bd",
"path": "src/pricing.rs",
"line": 88,
"classification": "weakly_exposed",
"current_evidence_strength": "Static evidence found related test context, but the current check is weak because the discriminator is missing.",
"missing_discriminator": "amount == discount_threshold",
"focused_proof_intent": "Add an equality-boundary assertion.",
"related_test": "tests/pricing.rs::applies_discount_above_threshold",
"suggested_test": "Add an equality-boundary assertion.",
"verify_command": "ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json",
"receipt_command": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id 67fc764ba37d77bd --json",
"static_evidence_boundary": "static advisory evidence only; not runtime proof, coverage adequacy, mutation confirmation, gate approval, or merge approval.",
"agent_command": "ripr agent start --root . --seam-id 67fc764ba37d77bd --out target/ripr/workflow",
"receipt": {
"artifact": "target/ripr/reports/agent-receipt.json",
"status": "present"
}
},
"movement": {
"state": "unknown",
"before_class": null,
"after_class": null,
"source_artifact": null
},
"debt_delta": {
"new_policy_eligible": 1,
"baseline_still_present": 42,
"baseline_resolved": 3,
"acknowledged": 0,
"waived": 0,
"suppressed": 0,
"blocking_candidates": 0
},
"policy": {
"mode": "visible-only",
"decision": "advisory",
"authority_artifact": "target/ripr/reports/gate-decision.json",
"acknowledgement_label": "ripr-waive"
},
"calibration": {
"recommendation": "unknown",
"mutation": "not_available",
"source_artifacts": [
"target/ripr/reports/recommendation-calibration.json"
]
},
"coverage_grip": {
"state": "not_available",
"coverage_delta": null,
"grip_delta": null,
"source_artifact": "target/ripr/reports/coverage-grip-frontier.json"
},
"artifacts": [
{
"group": "start_here",
"label": "PR review front panel",
"path": "target/ripr/reports/pr-review-front-panel.md",
"available": true,
"required": true
},
{
"group": "repair",
"label": "Assistant proof",
"path": "target/ripr/reports/test-oracle-assistant-proof.md",
"available": true,
"required": false
},
{
"group": "policy",
"label": "Gate decision",
"path": "target/ripr/reports/gate-decision.md",
"available": true,
"required": false
}
],
"warnings": [],
"limits": [
"Static RIPR evidence only.",
"Does not provide runtime confirmation.",
"Does not run mutation testing.",
"Does not call providers.",
"Does not edit source or generate tests.",
"Does not publish inline comments.",
"Does not change default CI blocking.",
"Gate evaluator remains pass/fail authority."
]
}
Field contract:
schema_versionremains0.1; additive top-issue projection fields preserve existing consumers and carry the same first-screen vocabulary used byfirst-pr.kindis alwayspr_review_front_panel.statusisadvisory,pass,acknowledged,blocked,config_error, orincomplete.summary.top_issue_stateisactionable,summary_only,baseline_only,already_improved,unchanged_after_attempt,no_actionable_seam,missing_required_input, orstale_input.summary.policy_stateisnone,new_policy_eligible,baseline,acknowledged,waived,suppressed,blocking, orconfig_error.summary.placementischanged_line,summary_only, ornot_available.summary.movement_stateisimproved,resolved,unchanged,regressed,unknown, ornot_available.summary.coverage_grip_stateisnot_available,flat_coverage_grip_improved,coverage_and_grip_improved,coverage_improved_grip_unchanged,coverage_regressed, orunknown.inputs.*records explicit input paths. Missing optional paths arenull; missing recommended paths produce warnings or fallback states.summary.*carries first-screen counts and states derived from supplied artifacts. It must not be an opaque score.top_issue.*is copied from existing RIPR artifacts. The front panel must not mint seam identities, rerank recommendations with a model, or infer missing source facts from code.top_issue.current_evidence_strength,top_issue.missing_discriminator,top_issue.focused_proof_intent,top_issue.verify_command,top_issue.receipt_command, andtop_issue.static_evidence_boundaryare the typed one-screen repair vocabulary. They mirror the CLI first screen when the supplied artifacts carry the field. Forfirst_useful_actioninputs, current evidence strength must come fromselected.current_evidence_strength. Legacy PR guidance, gate, baseline, and assistant-health inputs may normalize existing typed class/status fields, but must not infer the value from Markdown prose or code inspection.movement.*preserves before/after static movement when supplied. It is not runtime mutation confirmation.debt_delta.*carries PR-local movement from baseline, RIPR Zero, gate, or ledger inputs when available.policy.authority_artifactrecords the gate decision path when supplied. Gate decision remains the only configured pass/fail authority.calibration.*andcoverage_grip.*are advisory context. They must not become adequacy or blocking claims.artifacts[].groupisstart_here,repair,evidence,policy,calibration, orgenerated_ci.artifacts[]groups known artifacts by reviewer use. Missing artifacts stay visible withavailable = false.warnings[].kindis one ofmissing_required_input,missing_optional_input,stale_input,malformed_input,incompatible_schema,summary_only_guidance,missing_receipt,missing_handoff,missing_gate_decision,missing_calibration,static_limit,config_error, orother.limitspreserves static-evidence, no-edit, no-generated-test, no-provider-call, no-runtime-mutation-execution, no-inline-comment, and advisory-default boundaries.
Markdown should fit in a generated GitHub job summary. It should show status, top issue, current evidence strength, missing discriminator, focused proof intent, suggested focused test, related test, baseline and PR movement, policy state, repair commands, receipt command/state, artifact groups, and advisory limits. For fallback states, Markdown should put the safe next step before lower-priority detail. For example, missing required inputs should say to regenerate the missing PR guidance or first-useful-action artifact before acting on the panel.
Generated CI runs the producer only when configured input artifacts exist,
uploads pr-review-front-panel.{json,md} with the normal report packet, and
appends the Markdown plus compact at-a-glance fields to the job summary. The
projection is advisory: ripr gate evaluate remains the only configured
pass/fail authority. See
PR review front panel workflow for the
reviewer, developer, maintainer, and coding-agent workflow over the generated
panel.
Report Packet Index
RIPR-SPEC-0024 defines the report packet index contract. The index is the
reviewer front door for the uploaded ripr-reports packet. It groups explicit
existing artifacts by reviewer use, identifies the recommended start-here
artifact, preserves missing or warning surfaces, and names commands that
regenerate missing expected artifacts when the command is known.
The report is advisory and read-only. It does not rerun hidden analysis, inspect
source to infer missing fields, edit source, generate tests, call providers, run
mutation testing, change recommendation ranking, change gate policy, publish
inline comments, or change default CI blocking. gate-decision.{json,md}
remains the only configured pass/fail authority.
Command shape:
ripr reports index \
--root . \
--reports-dir target/ripr/reports \
--review-dir target/ripr/review \
--receipts-dir target/ripr/receipts \
--workflow-dir target/ripr/workflow \
--agent-dir target/ripr/agent \
--pilot-dir target/ripr/pilot \
--ci-dir target/ci \
--out target/ripr/reports/index.json \
--out-md target/ripr/reports/index.md
Repo-local automation may keep cargo xtask reports index as a wrapper.
Generated GitHub CI uses the public ripr reports index command when indexed
artifacts exist and projects the resulting index into the advisory summary.
The report writes:
target/ripr/reports/index.json
target/ripr/reports/index.md
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "report_packet_index",
"status": "warn",
"root": ".",
"generated_at": "2026-05-10T12:00:00Z",
"inputs": {
"reports_dir": "target/ripr/reports",
"review_dir": "target/ripr/review",
"receipts_dir": "target/ripr/receipts",
"workflow_dir": "target/ripr/workflow",
"agent_dir": "target/ripr/agent",
"pilot_dir": "target/ripr/pilot",
"ci_dir": "target/ci"
},
"summary": {
"entries": 18,
"available": 14,
"missing_expected": 4,
"warnings": 3,
"failures": 0,
"start_here": "target/ripr/reports/start-here.md",
"gate_authority": "target/ripr/reports/gate-decision.md",
"advisory": true
},
"groups": [
{
"group": "start_here",
"label": "Start here",
"summary": "Reviewer-first PR story.",
"entries": [
{
"id": "first_pr_start_here",
"label": "First PR start here",
"kind": "markdown",
"path": "target/ripr/reports/start-here.md",
"json_path": "target/ripr/reports/start-here.json",
"status": "available",
"available": true,
"required": true,
"authority": false,
"description": "Canonical first-screen repair packet.",
"next_command": null
},
{
"id": "pr_review_front_panel",
"label": "PR review front panel",
"kind": "markdown",
"path": "target/ripr/reports/pr-review-front-panel.md",
"json_path": "target/ripr/reports/pr-review-front-panel.json",
"status": "available",
"available": true,
"required": true,
"authority": false,
"description": "First-screen PR review story.",
"next_command": null
}
]
}
],
"repo_ops_packets": [
{
"id": "gh_pr_status",
"label": "PR merge readiness",
"status": "warn",
"next_command": "cargo xtask gh-pr-status --pr <number>",
"description": "Summarizes one PR's merge state, checks, reviews, and safe next action.",
"artifacts": [
{
"path": "target/ripr/reports/gh-pr-status.md",
"status": "warn",
"available": true
},
{
"path": "target/ripr/reports/gh-pr-status.json",
"status": "warn",
"available": true
}
]
}
],
"lane1_readiness": {
"status": "warn",
"missing_artifacts": 2,
"warning_artifacts": 0,
"failing_artifacts": 0,
"packets": [
{
"id": "lane1_evidence_audit",
"label": "Lane 1 evidence audit",
"status": "missing",
"next_command": "cargo xtask lane1-evidence-audit",
"description": "Produces raw-to-canonical/actionability counts and actionable-gap packet inputs.",
"artifacts": [
{
"path": "target/ripr/reports/lane1-evidence-audit.json",
"status": "missing",
"available": false
},
{
"path": "target/ripr/reports/lane1-evidence-audit.md",
"status": "missing",
"available": false
}
]
}
]
},
"missing_expected": [
{
"id": "assistant_loop_health",
"label": "Assistant loop health",
"group": "repair_agent_handoff",
"path": "target/ripr/reports/assistant-loop-health.md",
"required": false,
"reason": "input_not_available",
"next_command": "ripr assistant-loop health --proof target/ripr/reports/test-oracle-assistant-proof.json --out target/ripr/reports/assistant-loop-health.json --out-md target/ripr/reports/assistant-loop-health.md"
}
],
"warnings": [
{
"kind": "missing_expected",
"message": "Assistant loop health was not generated because no proof input was present.",
"source_artifact": null
}
],
"limits": [
"Advisory report-packet index only.",
"Does not rerun analysis.",
"Does not edit source or generate tests.",
"Does not call providers.",
"Does not run mutation testing.",
"Does not publish inline comments.",
"Does not change default CI blocking.",
"Gate decision remains pass/fail authority when configured."
]
}
Field contract:
schema_versionis0.1until the report shape changes.kindis alwaysreport_packet_index.statusispass,warn,fail, orincomplete. This is packet-health context only, not gate authority.inputs.*records explicit directories and paths that the producer was allowed to inspect.summary.start_herenames the first artifact to show reviewers. Preferpr-review-front-panel.mdwhen available.summary.gate_authorityrecordsgate-decision.mdwhen supplied. The index itself never becomes gate authority.groups[].groupisstart_here,pr_review_story,repair_agent_handoff,evidence_movement,policy_gates,calibration,validation_receipts,sarif_badges, orlocal_context.groups[].entries[]records artifact id, label, kind, path, optional JSON sibling, status, availability, requiredness, authority, description, and next command.repo_ops_packets[]is the repo-local operating packet index used bycargo xtask reports index. It records command mutability, the repo cockpit, worktree doctor, PR-ready, PR triage, per-PR merge readiness, generated-clean, badge diff policy, command catalog coverage, critic, receipts, suggested-fixes, andcheck-prartifacts with status, known output paths, and regeneration commands. It is advisory front-door metadata only and never becomes gate authority.lane1_readinessis the Lane 1 evidence packet index used bycargo xtask reports index. It records whether evidence-health, Lane 1 evidence-audit/actionable-gap, evidence-quality scorecard, evidence-quality trend, and badge-basis packets are present and healthy. Missing, warning, or failing Lane 1 readiness artifacts add advisory next commands, but do not create gate authority, badge authority, runtime mutation proof, or coverage adequacy claims.
Report packet index field contract:
entries[].statusisavailable,missing,pass,warn,fail,actionable,blocked,acknowledged,suppressed,stale,incomplete,unreadable, ornot_applicable.lane1_readiness.statusispresent,warn, orfail.lane1_readiness.missing_artifacts,lane1_readiness.warning_artifacts, andlane1_readiness.failing_artifactsare counts over the packet artifacts.lane1_readiness.packets[]uses the same packet shape asrepo_ops_packets[]: id, label, status, next command, description, and artifact availability.missing_expected[].reasonisnot_generated,input_not_available,configured_off,missing_required_input,stale_upstream, orunknown.missing_expected[]keeps absent expected surfaces visible with a bounded reason and, when known, a command to regenerate the missing surface.warnings[]carries malformed, stale, unreadable, missing-input, and incomplete packet context without converting it to waiver, suppression, improvement, runtime confirmation, or pass/fail authority.limitspreserves read-only, explicit-input, no-source-edit, no-generated-test, no-provider-call, no-runtime-mutation-execution, no-inline-comment, and advisory-default boundaries.
target/ripr/reports/pr-triage.json is the open-board hygiene packet emitted by
cargo xtask pr-triage-report:
{
"schema_version": "0.1",
"mode": "advisory",
"status": "warn",
"open_prs": [],
"queue_disposition": [
{
"pr_number": 819,
"disposition": "needs_owner_decision",
"reason": "duplicate or stale work needs canonical owner selection",
"recommended_action": "Choose the canonical branch, refresh the stale draft, or close superseded variants."
}
],
"findings": [],
"recommended_actions": []
}
Field contract:
queue_disposition[].dispositionis advisory. It may bemerge_candidate,needs_rebase,needs_review,close_duplicate,superseded,needs_fresh_validation,needs_owner_decision, ordo_not_touch_wrong_lane.queue_disposition[]never closes, updates, merges, comments on, or mutates PRs. It translates triage findings into operator next-action vocabulary.findings[]remains the detailed evidence;recommended_actions[]keeps the grouped repair guidance for agents and maintainers.
target/ripr/reports/pr-ready.json is the local PR readiness cockpit emitted by
cargo xtask pr-ready:
{
"schema_version": "0.1",
"mode": "advisory",
"status": "actionable",
"next_action": "review the attention items, then run cargo xtask check-pr for full gate receipts",
"steps": [
{
"id": "worktree_doctor",
"command": "cargo xtask worktree doctor",
"status": "pass",
"required": true,
"report": "target/ripr/reports/worktree-doctor.md",
"summary": "completed"
}
],
"safe_repairs": ["run cargo xtask fix-pr"],
"generated_only": ["target/ripr/**"],
"judgment_required": ["golden blessing"],
"next_commands": ["cargo xtask check-pr"]
}
Field contract:
statusispass,actionable, orfail.failmeans a required local hygiene step failed;actionablemeans a non-blocking packet needs attention.steps[].requiredrecords whether a failed step makespr-readyexit nonzero.safe_repairs[]lists deterministic repair paths; it must not include badge value edits, golden blessing, baselines, suppressions, dependency exceptions, schema version changes, or policy authority changes.
target/ripr/reports/cockpit.json is the repo-level maintainer cockpit emitted
by cargo xtask cockpit:
{
"schema_version": "0.1",
"mode": "advisory",
"status": "actionable",
"next_action": "review the action queue, then run cargo xtask pr-ready or cargo xtask check-pr for the active PR",
"action_queue": ["review stale, duplicate, behind, policy-sensitive, or generated-artifact PRs"],
"steps": [
{
"id": "pr_triage",
"command": "cargo xtask pr-triage-report",
"status": "needs_attention",
"required": false,
"report": "target/ripr/reports/pr-triage.md",
"summary": "report status: warn; see target/ripr/reports/pr-triage.md"
}
],
"safe_repairs": ["run cargo xtask fix-pr"],
"generated_only": ["target/ripr/**"],
"judgment_required": ["branch protection"],
"next_commands": ["cargo xtask pr-ready", "cargo xtask check-pr"]
}
Field contract:
statusispass,actionable, orfail.failmeans a required repo-ops rail failed;actionablemeans the cockpit found advisory queue, source-of-truth, generated-evidence, or command-catalog attention items.action_queue[]is the maintainer-facing next-work queue derived from the composed repo-ops packet statuses. It is advisory and must not close PRs, update branches, edit badges, or mutate policy.steps[]records each composed repo-ops command, whether it is required for cockpit success, and the report path to inspect.safe_repairs[],generated_only[], andjudgment_required[]preserve the generated-evidence discipline boundary: deterministic cleanup is allowed, while badge refreshes, goldens, suppressions, baselines, dependency exceptions, branch protection, and policy authority remain human decisions.
Markdown should fit in a generated GitHub job summary and uploaded report
packet. It should show status, start-here artifact, gate authority, packet
summary counts, grouped artifact links, missing expected artifacts with next
commands, and advisory limits. When no useful packet map can be rendered,
Markdown should show Status: incomplete and put the regeneration instruction
before empty groups.
Generated GitHub CI may run the index producer after individual report
producers and before artifact upload, upload index.{json,md} with the normal
ripr-reports artifact, and append a compact index section to the job summary.
The projection is advisory. Missing optional index entries must not fail CI
unless the explicit gate decision already failed or reported config_error.
See Report packet index workflow for
reviewer, maintainer, developer, and coding-agent use of the generated packet
map.
First PR Start Here Packet
ripr first-pr writes the first successful PR front-door packet from explicit
existing RIPR artifacts. cargo xtask first-pr remains a repo-local wrapper
over the same public command. The packet selects one top repairable PR-local
stable Rust gap or preview Python/TypeScript gap when the gap decision ledger
supplies one, or emits a bounded no-action or blocked recovery state. It does not rerun
hidden analysis, edit source, generate tests, call providers, run mutation
testing, change gate policy, or change CI blocking.
Command shape:
ripr first-pr \
--root . \
--base origin/main \
--head HEAD \
--check-output target/ripr/reports/check.json \
--gap-ledger target/ripr/reports/gap-decision-ledger.json \
--first-action target/ripr/reports/first-useful-action.json \
--review-comments target/ripr/review/comments.json \
--agent-packet target/ripr/agent/gap-packet.md \
--gate-decision target/ripr/reports/gate-decision.json \
--receipts-dir target/ripr/receipts \
--out-dir target/ripr/reports
The command writes:
target/ripr/reports/start-here.json
target/ripr/reports/start-here.md
When --check-output is supplied, ripr first-pr treats the saved check JSON
as an explicit input artifact and materializes
target/ripr/reports/gap-decision-ledger.{json,md} before selecting the
start-here repair. This is the direct preview-language path for actionable
python_repair_card records and typescript_repair_packet records that
already came from ripr check; it does not rerun hidden analysis, run tests,
import preview-language code, generate tests, or change gate authority.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "first_pr_start_here",
"status": "blocked",
"posture": "advisory",
"root": ".",
"selected": {
"state": "stale_artifact",
"output_state": "stale_evidence",
"message": "The gap decision ledger is stale; refresh the first-run evidence before assigning repair work.",
"next_command": "ripr reports gap-ledger --repo-exposure target/ripr/reports/repo-exposure.json --out target/ripr/reports/gap-decision-ledger.json --out-md target/ripr/reports/gap-decision-ledger.md"
},
"preflight": {
"status": "needs_attention",
"mode": "write",
"root": ".",
"base": "origin/main",
"head": "HEAD",
"next_command": "git fetch origin main; then rerun `ripr first-pr --root . --base origin/main --head HEAD`.",
"checks": [
{
"id": "git_base",
"label": "Git base",
"status": "needs_attention",
"message": "Could not resolve `origin/main` to a commit.",
"path": null,
"next_command": "git fetch origin main; then rerun `ripr first-pr --root . --base origin/main --head HEAD`."
}
]
},
"commands": {
"regenerate_gap_ledger": "ripr reports gap-ledger --repo-exposure target/ripr/reports/repo-exposure.json --out target/ripr/reports/gap-decision-ledger.json --out-md target/ripr/reports/gap-decision-ledger.md",
"next": "ripr reports gap-ledger --repo-exposure target/ripr/reports/repo-exposure.json --out target/ripr/reports/gap-decision-ledger.json --out-md target/ripr/reports/gap-decision-ledger.md"
},
"artifacts": [
{
"id": "gap_ledger",
"label": "Gap decision ledger",
"path": "target/ripr/reports/gap-decision-ledger.json",
"status": "present",
"regeneration_command": "ripr reports gap-ledger --repo-exposure target/ripr/reports/repo-exposure.json --out target/ripr/reports/gap-decision-ledger.json --out-md target/ripr/reports/gap-decision-ledger.md"
}
],
"authority": {
"status": "advisory",
"gate_decision": "target/ripr/reports/gate-decision.json",
"boundary": "Pass/fail authority remains with explicit gate-decision artifacts when configured; this first-run packet does not gate."
},
"warnings": [
"The gap decision ledger is stale; refresh the first-run evidence before assigning repair work."
],
"limits": [
"Composes explicit RIPR artifacts only.",
"Does not run hidden analysis.",
"Does not edit source or generate tests.",
"Does not run mutation testing.",
"Does not change CI blocking or gate policy."
]
}
Field contract:
schema_versionis0.1until the packet shape changes.kindis alwaysfirst_pr_start_here.statusisactionable,blocked, orno_action. It is reviewer context only, not gate authority.postureis alwaysadvisory.selected.stateistop_gapfor a selected repairable gap,missing_artifact,malformed_artifact,stale_artifact,wrong_root(including selected-root preflight failures),blocked_artifact, ortimeoutfor blocked recovery states, andempty_difforno_actionfor no-action states.selected.output_stateis the canonical no-output/fail-closed state for machine consumers. It distinguishesactionable_gap,clean,no_actionable_gap,missing_artifacts,stale_evidence,wrong_root,language_disabled,adapter_unavailable,preview_disabled,preview_limited,malformed_artifact,timeout_partial,server_unavailable,unsupported_schema,unsafe_path, andunsafe_commandwhere the packet has that data.top_gaprequiresstatus = "actionable".selected.canonical_gap_idandselected.gap_ididentify the repair unit when a top gap is selected. Generated CI and report indexes should prefer the canonical gap id when present.selected.languageandselected.language_statuskeep stable Rust evidence distinct from preview Python and TypeScript evidence when a top gap is selected. Preview top gaps useselected.output_state = "preview_limited"and remain advisory repair routing, not support-tier promotion.selected.current_evidence_strength,selected.missing_discriminator, andselected.focused_proof_intentprovide the one-screen recommendation contract. They are derived from typed gap kind and repair-route fields; consumers must not infer them from Markdown prose.selected.whyexplains why the selected gap matters in reviewer language. It is supporting explanation for the same typed repair unit, not a separate authority source.selected.static_evidence_boundaryrepeats the static/advisory non-claim boundary in the selected top-gap object so one-screen consumers do not need to infer it from Markdown or higher-level packet authority text.selected.repair.route,selected.repair.target_file,selected.repair.related_test, andselected.repair.suggested_assertiondescribe the bounded repair route when present.selected.static_limit_kindandselected.static_limit_detailare optional; surfaces must show them before suggested action language when they are present.selected.verify_command,selected.receipt_command,selected.receipt_path,selected.receipt_command_source, andselected.receipt_stateare the static movement proof path. When the source gap ledger omits a receipt command,ripr first-prmay provide a deterministicripr outcomecommand under the configured receipts directory. A missing receipt is not failure, merge approval, mutation proof, or runtime adequacy.selected.receipt_stateuses the canonical receipt lifecycle vocabulary:receipt_missing,receipt_found,receipt_stale,receipt_gap_mismatch,receipt_movement_improved,receipt_movement_unchanged, orreceipt_not_applicable.missing_artifact,malformed_artifact,stale_artifact,wrong_root,blocked_artifact, andtimeoutrequirestatus = "blocked"and a bounded next command when one is known.blocked_artifactmay also represent setup preflight failures such as a missing git worktree, missing base ref, missing head ref, or invalid diff range.empty_diffandno_actionrequirestatus = "no_action"and must not produce a repair interruption.preflightis present for the publicripr first-prcommand path. It records read-only front-door checks for root, Git worktree, base/head refs, diff presence, supported project marker,ripr.tomldefaulting, output directory, and write/check mode. Supported project markers currently mean a Cargo workspace, Python preview project root, or TypeScript preview project root. Preflight does not create analyzer facts and does not become gate authority.inputs.check_outputis present only when--check-outputwas supplied. In that mode, the start-here packet can include acheck_outputartifact and thegap_ledgerartifact is the ledger materialized from that saved check JSON rather than from repo-exposure evidence.preflight.statusisreadywhen the command can proceed without setup attention, orneeds_attentionwhen a setup check has a recovery/no-action note. Aneeds_attentionpreflight can still accompany an explicit artifact-backed packet; typed artifact states still decide repair selection.preflight.checks[].statusis one ofok,needs_attention,no_action,defaulted, orwill_create. Checks withnext_commandprovide the next safe setup or recovery command; they must not imply mutation, coverage, runtime proof, merge approval, or gate pass/fail.commands.regenerate_gap_ledgeris always present so missing, stale, wrong-root, malformed, and timeout states can point to a known refresh path.artifacts[]records artifact id, label, path,presentormissingstatus, and optional regeneration command.authority.boundarypreserves the gate boundary. This packet never becomes pass/fail authority.warnings[]carries blocked-state context without converting it to waiver, suppression, improvement, clean, or gate-passing state.limitspreserves explicit-input, no-source-edit, no-generated-test, no-provider-call, no-runtime-mutation-execution, and advisory-default boundaries.
Markdown should fit in a PR summary, local handoff, or generated CI summary. It
should show the selected top gap, no-action state, or blocked recovery state
first. For a top gap, the first screen must include changed behavior, why it
matters, current evidence strength, missing discriminator, focused proof intent,
verify command, receipt command or path, and the static advisory boundary
before deeper artifact links.
empty_diff must render as a no-action state, not a blocked repair.
Review Guidance Outcome Receipt
Review guidance outcome receipts are optional repo-local inputs to the recommendation calibration report. They record reviewer, fixture, agent, or CI artifact feedback for one PR guidance item without sending telemetry, calling an external service, editing source, generating tests, running mutation testing, or changing CI blocking behavior.
Receipt files may live anywhere a repo chooses. The boundary-gap calibration corpus pins examples under:
fixtures/boundary_gap/expected/recommendation-calibration/outcome-receipts/
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "review_guidance_outcome_receipt",
"status": "advisory",
"spec": "RIPR-SPEC-0013",
"receipt_id": "review-outcome-useful-exact-line-boundary",
"case_id": "useful_exact_line_boundary",
"root": ".",
"guidance": {
"artifact": "fixtures/boundary_gap/expected/pr-guidance/exact-line/comments.json",
"collection": "comments",
"id": "ripr-review-8f7fa8644fd12280",
"seam_id": "8f7fa8644fd12280",
"dedupe_key": "ripr:8f7fa8644fd12280:src/pricing.rs:88"
},
"outcome": {
"label": "useful",
"source": "fixture",
"reason": "The recommendation points at the changed seam line and names the expected boundary discriminator and test target."
},
"placement": {
"path": "src/pricing.rs",
"line": 88,
"mode": "exact_seam_line",
"quality": "correct"
},
"suggested_test": {
"target_quality": "correct",
"expected_file": "tests/pricing.rs",
"actual_file": "tests/pricing.rs",
"near_test": "applies_discount_above_threshold"
},
"suppression": {
"reason": null,
"quality": "not_applicable"
},
"static_movement": {
"state": "improved",
"source": "targeted_test_outcome",
"artifact": "fixtures/boundary_gap/calibration/targeted-test-outcome.json"
},
"latency": {
"guidance_generated_unix_ms": null,
"outcome_recorded_unix_ms": null,
"outcome_latency_ms": null
},
"limits": {
"telemetry": false,
"external_service": false,
"source_edits": false,
"generated_tests": false,
"runtime_mutation_execution": false,
"ci_blocking": false
},
"limits_note": "Advisory review-guidance outcome receipt only; no telemetry, generated tests, source edits, mutation execution, or CI blocking."
}
Field contract:
schema_version- currently"0.1".tool- always"ripr".kind- alwaysreview_guidance_outcome_receipt.status-advisory; receipts are feedback artifacts, not policy gates.spec-RIPR-SPEC-0013.receipt_id- stable local identifier for this receipt.case_id- optional calibration-corpus case identifier when the receipt came from a fixture expectation.root- workspace root used to resolve artifact paths.guidance- the source PR guidance artifact, collection, item id,seam_id, and dedupe key when available.outcome.label- one ofuseful,noisy,wrong_line,already_covered,wrong_target,summary_only_correct,suppressed_correctly, orunknown.outcome.source- local source class such asfixture,reviewer,agent,ci_artifact, orunknown.outcome.reason- concise local rationale for the outcome label.placement.quality-correct,wrong_line,summary_only_expected,not_placeable, orunknown.suggested_test.target_quality-correct,wrong_target,not_applicable, orunknown.suppression.reason-cap_reached,suppression,severity_off,nearby_test_changed,generated_or_migration,none, orunknown.suppression.quality-suppressed_correctly,over_suppressed,not_applicable, orunknown.static_movement.state-improved,unchanged,regressed,resolved,new_gap,missing_after_snapshot, orunknown.latency.*- optional timestamps and elapsed time. Values arenullwhen not available.limits- explicit false values for telemetry, external services, source edits, generated tests, runtime mutation execution, and CI blocking.limits_note- static/advisory boundary text for downstream summaries.
Agent Status
ripr agent status --root <workspace> reads already-written agent-loop
artifacts and reports which step is missing next. Markdown is the default for
human review packets; add --json for the machine-readable contract:
ripr agent status --root .
ripr agent status --root . --json
The command does not run analysis, mutation testing, SARIF policy, badge generation, LSP refresh, or cache warm-up. It only inspects fixed artifact paths under the supplied workspace root:
target/ripr/workflow/before.repo-exposure.json
target/ripr/workflow/after.repo-exposure.json
target/ripr/workflow/agent-brief.json
target/ripr/workflow/agent-packet.json
target/ripr/workflow/agent-verify.json
target/ripr/reports/agent-receipt.json
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "incomplete",
"root": ".",
"seam": {
"seam_id": "67fc764ba37d77bd",
"source": "agent_receipt"
},
"artifacts": [
{
"name": "before_snapshot",
"label": "before snapshot",
"path": "target/ripr/workflow/before.repo-exposure.json",
"required": true,
"state": "present",
"bytes": 12000,
"modified_unix_ms": 1778179200000
}
],
"missing_commands": [
{
"step": "agent_packet",
"artifact": "target/ripr/workflow/agent-packet.json",
"reason": "agent packet artifact is missing",
"command": "ripr agent packet --root . --seam-id 67fc764ba37d77bd --json > target/ripr/workflow/agent-packet.json"
}
],
"next_command": {
"step": "agent_packet",
"artifact": "target/ripr/workflow/agent-packet.json",
"reason": "agent packet artifact is missing",
"command": "ripr agent packet --root . --seam-id 67fc764ba37d77bd --json > target/ripr/workflow/agent-packet.json"
},
"warnings": []
}
Field contract:
schema_version- currently"0.1".status-"complete"when every required artifact is present and there are no warnings;"warning"when every artifact is present but a stale-looking condition exists;"incomplete"when any required artifact is missing.root- the--rootargument normalized to forward slashes for reporting.seam- recovered seam identity when available. The current recovery order is receipt, verify, packet, then brief. It isnullwhen no existing artifact names a seam.artifacts[]- one entry for each required fixed artifact.bytesandmodified_unix_msarenullwhen the artifact is missing or the filesystem does not expose the timestamp.missing_commands[]- one command for each missing artifact in workflow order: before snapshot, packet, brief, after snapshot, verify, receipt. If no seam can be recovered, packet, brief, and receipt commands use<seam-id>.next_command- the first entry frommissing_commands, ornullwhen no required artifact is missing.warnings[]- stale-looking or unreadable-artifact hints. Timestamp warnings are emitted whenagent verifyis older than a before/after snapshot oragent receiptis older thanagent verify. Hash mismatch warnings remain a later reviewer-summary/status enhancement now that receipt provenance records artifact SHA-256 values.
Markdown output contains the same status, recovered seam, artifact table, next
command, warnings, and static-only limits. Generated CI writes it to
target/ripr/workflow/agent-status.md next to
target/ripr/workflow/agent-status.json.
Agent Review Summary
ripr agent review-summary --root <workspace> reads already-written agent-loop
artifacts and emits a compact Markdown packet for PR review. Add --json for
the machine-readable contract:
ripr agent review-summary --root .
ripr agent review-summary --root . --json
The command does not run analysis, mutation testing, SARIF policy, badge generation, LSP refresh, cache warm-up, source edits, or test generation. It joins only existing artifacts:
ripr agent statuscomputed from the current artifact tree;target/ripr/workflow/workflow.jsonwhen present;target/ripr/reports/agent-receipt.json;target/ripr/reports/operator-cockpit.jsonwhen present;target/ripr/reports/repo-exposure.jsonwhen present;target/ripr/reports/lsp-cockpit.jsonwhen present;target/ripr/workflow/analysis-outcome.json, the required producer-backed diff completeness envelope emitted by the generated agent workflow;- local file presence for CI-published work-loop artifacts.
The JSON schema is version 0.1:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "ready",
"root": ".",
"target_seam": {
"seam_id": "67fc764ba37d77bd",
"source": "agent_receipt",
"file": "src/lib.rs",
"line": 42,
"seam_kind": "predicate_boundary"
},
"static_movement": {
"state": "improved",
"before_class": "weakly_gripped",
"after_class": "strongly_gripped",
"grip_class": "strongly_gripped",
"evidence_artifact": "target/ripr/reports/agent-receipt.json",
"verify_artifact": "target/ripr/workflow/agent-verify.json",
"summary": "Static movement is improved (weakly_gripped -> strongly_gripped).",
"next_action": {
"kind": "improved",
"summary": "Static grip improved.",
"recommended_action": "Keep the focused test and include this receipt in review."
}
},
"analysis_outcome": {
"analysis_complete": true,
"outcome": {
"schema_version": "0.1",
"kind": "complete_no_findings",
"identity": {},
"counts": {},
"limitations": [],
"claim_boundary": "Static analysis outcome only; no correctness, test-adequacy, runtime-execution, or merge-readiness claim."
}
},
"next_command": null,
"surfaces": [
{
"name": "agent_status",
"label": "Agent status",
"path": "target/ripr/workflow/agent-status.json",
"state": "computed",
"status": "complete",
"required": true,
"summary": "6 required artifacts present, 0 missing, 0 warnings."
}
],
"ci_artifacts": [
{
"name": "agent_status",
"path": "target/ripr/workflow/agent-status.json",
"state": "present"
},
{
"name": "agent_status_markdown",
"path": "target/ripr/workflow/agent-status.md",
"state": "present"
},
{
"name": "agent_review_summary",
"path": "target/ripr/workflow/agent-review-summary.json",
"state": "missing"
},
{
"name": "agent_review_summary_markdown",
"path": "target/ripr/workflow/agent-review-summary.md",
"state": "missing"
}
],
"reviewer_summary": {
"headline": "Review packet is ready for seam 67fc764ba37d77bd.",
"what_changed": "Static movement is improved (weakly_gripped -> strongly_gripped).",
"evidence": "Review target/ripr/reports/agent-receipt.json with target/ripr/workflow/agent-verify.json.",
"remaining": "Keep the focused test and include this receipt in review.",
"reviewer_should_inspect": [
"target/ripr/reports/agent-receipt.json",
"target/ripr/workflow/agent-verify.json"
]
},
"limits": {
"static_artifact_relationship": true,
"runtime_mutation_execution": false,
"automatic_edits": false,
"generated_tests": false
}
}
Field notes:
statusisreadywhen a receipt is present, the required loop artifacts do not report warnings, and the producer-backedanalysis_outcomeis present and complete;warningwhen a receipt exists but optional local artifact state looks stale or malformed;incompletewhen the receipt or typed producer outcome is missing, invalid, or incomplete.target_seamis recovered from receipt first, then workflow, then agent status.static_movementis copied from the receipt and remains a static before/after artifact relationship.analysis_outcomeis copied from the producer's typed check envelope. Itsanalysis_completevalue is derived from the closed outcome kind; it is not inferred from receipt movement, packet-budget state, or empty findings.surfaces[]reports each joined surface ascomputed,present,missing,optional_missing,invalid, orinvalid_json.ci_artifacts[]is local file presence for artifacts that generated CI can upload later; it does not query GitHub Actions.reviewer_summaryis intentionally compact enough for PR comments and LLM context windows.
The Markdown output contains the same target seam, movement, evidence artifact, next command when one is missing, reviewer inspection list, and static limits.
Agent Workflow Manifest
ripr agent start --root <workspace> --seam-id <id> --out <dir> writes a
source-edit-free workflow packet for one visible seam:
ripr agent start --root . --seam-id 67fc764ba37d77bd --out target/ripr/workflow
Outputs:
target/ripr/workflow/workflow.json
target/ripr/workflow/commands.md
target/ripr/workflow/agent-brief.json
The command selects the requested seam with the same policy as
ripr agent brief --seam-id, writes a focused brief, then renders a workflow
manifest that names artifact paths and shared command templates for the static
before snapshot, agent packet, agent brief, after snapshot, verify, and
receipt steps. It does not edit source files, generate tests, call LLM APIs,
run mutation testing, refresh LSP state, or configure CI blocking.
The generated command list also captures the diff-scoped producer outcome at
target/ripr/workflow/analysis-outcome.json; this is a required input to the
review-summary projection and is distinct from repo-exposure snapshots.
When a step has a producer-owned typed route, its command object also carries
a command_spec — the versioned, direct-execution-safe form (#1617) whose
command_id, role, argv, policies, and expected writes bind machine
execution; the command string remains the human display. Steps without a
typed route are legacy-string-only: copyable, but never advertised as
direct-executable.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "ready",
"command_shell": "bash",
"root": ".",
"mode": "draft",
"out_dir": "target/ripr/workflow",
"seam": {
"seam_id": "67fc764ba37d77bd",
"file": "src/pricing.rs",
"line": 88,
"seam_kind": "predicate_boundary",
"grip_class": "weakly_gripped",
"why": "caller requested seam_id 67fc764ba37d77bd",
"missing_discriminator": "amount == discount_threshold",
"assertion_shape": "assert_eq!(...)",
"recommended_test_file": "tests/pricing.rs",
"recommended_test_name": "discount_threshold_equality_boundary_is_asserted",
"related_test_to_imitate": "applies_discount_above_threshold"
},
"outputs": {
"workflow_manifest": "target/ripr/workflow/workflow.json",
"commands_markdown": "target/ripr/workflow/commands.md",
"agent_brief": "target/ripr/workflow/agent-brief.json"
},
"artifacts": [
{
"name": "before_snapshot",
"label": "before snapshot",
"path": "target/ripr/workflow/before.repo-exposure.json",
"required": true,
"state": "missing"
}
],
"commands": [
{
"step": "before_snapshot",
"artifact": "target/ripr/workflow/before.repo-exposure.json",
"purpose": "Capture static seam evidence before editing tests.",
"command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/before.repo-exposure.json"
},
{
"step": "agent_packet",
"artifact": "target/ripr/workflow/agent-packet.json",
"purpose": "Expand the selected seam into a bounded agent packet.",
"command": "ripr agent packet --root . --seam-id 67fc764ba37d77bd --json > target/ripr/workflow/agent-packet.json",
"command_spec": {
"schema_version": "1",
"command_id": "ripr:agent:packet",
"role": "regeneration",
"execution_mode": "shell_required",
"program": "ripr",
"args": ["agent", "packet", "--root", ".", "--seam-id", "67fc764ba37d77bd", "--json"],
"working_directory": ".",
"environment": "clean",
"stdin": "null",
"timeout_ms": 120000,
"cancellation": "allowed",
"network": "forbidden",
"expected_result_parser": "declared_json",
"expected_exit_codes": [0],
"expected_writes": ["target/ripr/workflow/agent-packet.json"],
"cost_class": "unknown",
"platforms": ["linux", "macos", "windows"],
"human_display": "ripr agent packet --root . --seam-id 67fc764ba37d77bd --json > target/ripr/workflow/agent-packet.json",
"authority_boundary": "regeneration_route_only"
}
}
],
"missing_inputs": [
{
"step": "before_snapshot",
"artifact": "target/ripr/workflow/before.repo-exposure.json",
"purpose": "Capture static seam evidence before editing tests.",
"command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/before.repo-exposure.json"
}
],
"next_command": {
"step": "before_snapshot",
"artifact": "target/ripr/workflow/before.repo-exposure.json",
"purpose": "Capture static seam evidence before editing tests.",
"command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/before.repo-exposure.json"
},
"boundaries": {
"source_edits": false,
"generated_tests": false,
"runtime_mutation_execution": false,
"llm_api_calls": false,
"ci_blocking": false
}
}
Field contract:
schema_version- currently"0.1".status- currently"ready"when the manifest was written.command_shell- currently"bash". Everycommandstring in this manifest is a bash command line: arguments are quoted with POSIX single quotes and output redirection uses>. Consumers on Windows must run them through Git Bash; cmd.exe treats'as a literal character and PowerShell rejects the'\''escape. WSL bash is not equivalent, because paths in this manifest keep their Windows drive-letter prefix, which WSL resolves as a relative path.commands.mdstates the same boundary in prose above its first command block. No shell-neutral argv form is emitted for this schema version.root,mode, andout_dir- the selected workspace root, effective analysis mode, and workflow output directory.seam- the selected seam fields copied from the generated agent brief.outputs- the three files written byagent start.artifacts[]- required downstream workflow inputs and outputs, markedpresentormissingat manifest creation time.commands[]- deterministic command templates for regenerating the workflow, capturing snapshots, rendering packet and brief artifacts, comparing before/after evidence, and writing a receipt.missing_inputs[]- the commands whose artifacts are currently missing.next_command- the first missing-input command, ornullwhen all downstream artifacts are present.boundaries- explicit false-valued guardrails for source edits, generated tests, runtime mutation execution, LLM API calls, and CI blocking.
Release Readiness Report
cargo xtask release-readiness --version <version> writes a Campaign 10
release-surface report to:
target/ripr/reports/release-readiness.json
target/ripr/reports/release-readiness.md
The report checks repo artifacts and safe local commands for the 0.4
first-hour loop. It packages and extracts the local crate, installs the binary
from that extracted package, verifies the installed binary differs from the
workspace build, and exercises ripr doctor against an external fixture. It
then verifies the public command surface, runs the boundary-gap ripr pilot, ripr outcome, and
ripr agent verify snapshots, writes a focused ripr agent receipt, refreshes
repo-exposure latency and LSP cockpit reports, checks the advisory GitHub
workflow dry-run, and confirms VSIX and known-limit docs. It does not run
mutation testing, enable CI blocking, change analyzer classifications, or
expand LSP behavior.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"report": "release-readiness",
"version": "0.8.0",
"status": "warn",
"checks": [
{
"id": "installed-command-surface",
"status": "pass",
"required": true,
"command": "target/ripr/release-readiness/install/bin/ripr --help",
"summary": "installed binary exposes the public release-loop commands",
"artifacts": [
"target/ripr/release-readiness/install/bin/ripr"
],
"details": []
},
{
"id": "publish-dry-run",
"status": "not_run",
"required": false,
"command": "cargo publish -p ripr --dry-run",
"summary": "requested release version does not match the crate version yet",
"artifacts": [],
"details": [
"requested version: 0.4.0; crates/ripr version: 0.3.1"
]
}
],
"next_commands": [
"cargo publish -p ripr --dry-run"
]
}
Field contract:
schema_version- currently"0.1".status-passwhen all checks pass,warnwhen any check iswarnornot_runand no required check failed, andfailwhen a required check failed.version- requested release version from--version.checks[].id- stable check identifier such aspackage-list,publish-dry-run,package-install,installed-command-surface,pilot-boundary-fixture,outcome-boundary-fixture,agent-verify-boundary-fixture,agent-receipt-boundary-fixture,repo-exposure-latency,lsp-cockpit,github-workflow-defaults,vsix-packaging-path, orknown-limits-docs.checks[].status-pass,warn,fail, ornot_run.checks[].required-truefor checks that must pass in the normal local readiness run. Release-only package and publish dry-run checks can benot_runand non-required until the version bump and clean release-prep tree make them safe to execute.checks[].command- command or dry-run surface that produced the signal.checks[].summary- short human-readable status.checks[].artifacts- generated or inspected artifacts for the check.checks[].details- optional bounded command output, missing fields, or skip reasons.next_commands[]- follow-up commands for non-passing checks, or the release-readiness command itself when everything passed.
The Markdown sibling prints the same check table, per-check details, artifacts, and next commands for release review.
Historical Release Control Lens Report
cargo xtask release-control --input <captured-snapshot.json> replays a
captured historical 0.11 release-control snapshot. cargo xtask release-control --live collects current origin/main, open PRs, and #2379 through bounded
read-only adapters. Both paths write:
target/ripr/reports/release-control.json
target/ripr/reports/release-control.md
The JSON report has schema version 0.1 and the following stable top-level
shape:
{
"report": "release-control",
"schema_version": "0.1",
"status": "ready | reconcile_required",
"captured_at": "...",
"source": {
"mode": "captured | live",
"freshness": "current",
"main_sha": "...",
"authority_issue": 2379,
"authority_state": "open",
"authority_main_sha": "...",
"portfolio_state": "complete | unknown",
"open_prs_complete": true,
"active_claims_complete": true,
"worktree_inventory_complete": true,
"worktree_count": 1,
"graph_digest": "..."
},
"reconciliation_reasons": [],
"prs": [
{
"number": 2528,
"title": "...",
"is_draft": false,
"head_sha": "...",
"base_ref": "main",
"linked_issue_refs": [2528],
"release_disposition": "release_required",
"disposition_reason": "...",
"merge_eligible": true
}
],
"next_action": "...",
"authority_boundary": "temporary_release_lens_only",
"must_not_claim": [
"candidate qualification",
"package readiness",
"merge approval",
"release publication"
]
}
Allowed release_disposition values are release_required,
release_optional_pending_decision, hold_post_release, and
blocked_on_named_authority. A complete current snapshot can mark only
non-draft release_required rows as merge_eligible; any stale, missing, or
contradictory source input clears eligibility for every row. The live collector
does not claim portfolio or active-claim completeness from its bounded inputs;
its report remains reconcile_required until those authorities are supplied.
The Markdown report is derived from the same normalized DTO and is advisory
only. This report never closes issues, merges PRs, selects or qualifies a
candidate, or publishes release artifacts.
The open-PR inventory is informational and must not be used as a candidate
readiness gate. Candidate readiness is a separate, cut-relative decision over
selected claims, candidate-only exclusions, the reviewed denominator through
historical development cut C, and a reproducible historical candidate tree.
Those fields are retained for audit only; the active 0.11.0 publication
candidate is the exact transaction-boundary live swarm head recorded in
docs/release-candidates/0.11.0-live-head-selection.json. The candidate control
artifact must report candidate_required_claims_pending and the associated
landed, excluded, deferred, unresolved-defect, denominator, cut, and immutable
candidate-reference state. An open_release_pr_count, if displayed, is
context only.
The release-control JSON carries this candidate-relative state separately from PR rows:
{
"candidate_state": {
"status": "scope_pending | scope_closed | hard_cut_eligible | candidate_materialized | qualification_eligible",
"selected_candidate_claims": 0,
"candidate_required_claims_pending": 0,
"candidate_claims_landed": 0,
"candidate_claims_excluded": 0,
"candidate_claims_deferred": 0,
"candidate_defects_unresolved": 0,
"denominator_decisions_remaining": 0,
"denominator_decisions_remaining_through_selected_cut": 0,
"candidate_cut_selected": false,
"candidate_ref_created": false,
"projection_reproducible": false,
"candidate_tree_present": false,
"candidate_tree_parent_matches_cut": false,
"exclusion_digests_match": false,
"preservation_digests_match": false,
"manifest_matches_candidate_tree": false,
"qualification_instruments_available": false,
"reasons": []
}
}
denominator_decisions_remaining is retained for schema-0.1 wire compatibility
and counts decisions through the fixed provisional review cutoff. The additive
denominator_decisions_remaining_through_selected_cut field is null until a
development cut is selected; once selected, it must be zero before hard-cut
eligibility. Neither field counts the repository-wide open board. A state
earlier than qualification_eligible is not a qualification claim; the state
names the next missing boundary.
Release Denominator Ledger Report
release-denominator writes a deterministic supplemental denominator report
from a captured release_denominator_snapshot. The JSON report has this
stable top-level shape:
{
"report": "release-denominator",
"schema_version": "0.1",
"captured_at": "...",
"status": "ready | reconcile_required",
"source": {},
"candidate_selection": null,
"counts_by_disposition": {},
"counts_by_tree_state": {},
"records": [],
"range_digest": "sha256:...",
"candidate_tree_digest": "sha256:...",
"record_set_digest": "sha256:...",
"reconciliation_reasons": [],
"next_action": "...",
"authority_boundary": "supplemental_denominator_only",
"must_not_claim": ["candidate qualification", "merge approval", "release publication", "source integration"]
}
The validator preserves the ordered first-parent range and requires one
reviewed record per range commit. Missing, duplicate, out-of-range, wrongly
ordered, wrong-tree, stale-live, and unresolved-final-decision cases produce
reconcile_required; no report status qualifies or publishes a candidate.
Each record may retain typed reference authority in references[]:
{
"kind": "merge_pr | issue | pull_request | reviewed_manual_mapping",
"number": 2788,
"source": "associated_pull_request | closing_reference | body_reference | explicit_review",
"evidence_url": "https://github.com/...",
"github_identity": null,
"observed_for_commit_sha": "...",
"reviewed": true,
"limitation": ""
}
Exactly one of evidence_url or github_identity is required. The legacy
pr_refs and issue_refs fields are compatibility projections and cannot
establish final denominator authority by themselves. Final ledgers reject
unreviewed references and legacy-only projections.
source.github_repository pins the GitHub repository whose retained authority
may be imported; captures from another repository are rejected.
source.provisional_review_cutoff_sha optionally pins the fixed review cutoff
used by #2832 and extended through the selected development cut by #2825. Each record may also carry claim_refs[],
reference_capture_status (not_captured, captured,
no_linked_authority, ambiguous, or unavailable), and
reference_capture_limitation. candidate_tree_state_pending is the
fail-closed state for a row whose candidate-tree effect has not been
adjudicated; it is only valid with operator_decision_required. The optional
candidate_selection object is the #2766/#2871 selected-claim authority, not a
claim inferred from numeric issue or PR references.
The checked provisional fixture also retains the #2832 and #2825 adjudication
batch receipts in each reviewed record's review_refs[], and its
candidate-tree commit list is the ordered projection of reviewed
candidate_tree_state values. Unreviewed rows after a pinned cutoff remain
pending and do not enter that projection; once adjudicated through the
selected cut, each row carries its reviewed tree state into the projection.
Operator Cockpit Report
cargo xtask operator-cockpit joins existing repo-local report artifacts into
one next-action cockpit:
target/ripr/reports/operator-cockpit.json
target/ripr/reports/operator-cockpit.md
The command reads current artifacts under target/ripr/reports/; it does not
rerun analysis, generate tests, mutate source files, or change static
classifications. Missing inputs are reported with the command that should
generate them. cargo xtask operator-cockpit-report remains an alias for
existing repo automation.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "warn",
"inputs": [
{
"name": "repo exposure",
"path": "target/ripr/reports/repo-exposure.json",
"state": "present",
"status": "present",
"command": "cargo xtask repo-exposure-report",
"required": true,
"summary": "2 seams; 1 weakly_gripped, 0 ungripped, 0 reachable_unrevealed."
},
{
"name": "LSP cockpit",
"path": "target/ripr/reports/lsp-cockpit.json",
"state": "present",
"status": "pass",
"command": "cargo xtask lsp-cockpit-report",
"required": true,
"summary": "1 fixture reports; 0 uncovered contributed commands."
},
{
"name": "before snapshot",
"path": "target/ripr/pilot/repo-exposure.json",
"state": "present",
"status": "present",
"command": "ripr pilot --out target/ripr/pilot",
"required": true,
"summary": "2 seams; 1 weakly_gripped, 0 ungripped, 0 reachable_unrevealed."
},
{
"name": "after snapshot",
"path": "target/ripr/pilot/after.repo-exposure.json",
"state": "present",
"status": "present",
"command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/pilot/after.repo-exposure.json",
"required": true,
"summary": "2 seams; 0 weakly_gripped, 0 ungripped, 0 reachable_unrevealed."
},
{
"name": "agent verify",
"path": "target/ripr/agent/agent-verify.json",
"state": "present",
"status": "advisory",
"command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json > target/ripr/agent/agent-verify.json",
"required": true,
"summary": "1 improved, 0 changed, 0 regressed, 1 unchanged seams."
},
{
"name": "agent receipt",
"path": "target/ripr/agent/agent-receipt.json",
"state": "present",
"status": "advisory",
"command": "ripr agent receipt --root . --verify-json target/ripr/agent/agent-verify.json --seam-id <seam-id> --json --out target/ripr/agent/agent-receipt.json",
"required": true,
"summary": "Receipt for seam 67fc764ba37d77bd: improved; before weakly_gripped, after strongly_gripped. No remaining static gap is named by this receipt."
},
{
"name": "SARIF policy",
"path": "target/ripr/reports/sarif-policy.json",
"state": "missing",
"status": "missing",
"command": "cargo xtask sarif-policy --current target/ripr/workflow/current.repo-sarif.json",
"required": true,
"summary": "Report has not been generated yet."
},
{
"name": "badge status",
"path": "target/ripr/reports/repo-ripr-badge.json",
"state": "present",
"status": "present",
"command": "cargo xtask repo-badge-artifacts",
"required": true,
"summary": "Badge headline status is available."
},
{
"name": "targeted-test outcome",
"path": "target/ripr/reports/targeted-test-outcome.json",
"state": "missing",
"status": "missing",
"command": "ripr outcome --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --format json --out target/ripr/reports/targeted-test-outcome.json",
"required": true,
"summary": "Report has not been generated yet."
},
{
"name": "actionable gap outcomes",
"path": "target/ripr/reports/actionable-gap-outcomes.json",
"state": "missing",
"status": "missing",
"command": "cargo xtask actionable-gap-outcomes",
"required": true,
"summary": "Actionable packet outcome join has not been generated yet."
},
{
"name": "mutation calibration",
"path": "target/ripr/reports/mutation-calibration.json",
"state": "optional_missing",
"status": "optional",
"command": "cargo xtask mutation-calibration . --mutants-json target/mutants/outcomes.json --repo-exposure-json target/ripr/reports/repo-exposure.json",
"required": false,
"summary": "Optional calibration report has not been generated."
}
],
"top_weak_seams": [
{
"seam_id": "67fc764ba37d77bd",
"seam_kind": "predicate_boundary",
"file": "src/lib.rs",
"line": 42,
"owner": "src/lib.rs::discounted_total",
"expression": "amount >= discount_threshold",
"grip_class": "weakly_gripped",
"why_it_matters": "observed values do not include the equality-boundary case for this predicate",
"suggested_next_targeted_test": "Add a focused predicate_boundary test for `src/lib.rs::discounted_total` that exercises `discount_threshold (equality boundary)` and asserts the observable result.",
"best_related_test": {
"name": "below_threshold_has_no_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_strength": "strong"
}
}
],
"surface_alignment": [
{
"surface": "LSP cockpit",
"state": "present",
"status": "pass",
"agreement": "editor_contract_green",
"signal": "1 LSP fixture reports; 0 uncovered contributed VS Code commands.",
"command": "cargo xtask lsp-cockpit-report"
},
{
"surface": "agent verify",
"state": "present",
"status": "advisory",
"agreement": "agent_verify_counts_available",
"signal": "1 improved, 0 changed, 0 regressed, 1 unchanged seams.",
"command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json > target/ripr/agent/agent-verify.json"
},
{
"surface": "agent receipt",
"state": "present",
"status": "advisory",
"agreement": "agent_receipt_available",
"signal": "Receipt for seam 67fc764ba37d77bd: improved; before weakly_gripped, after strongly_gripped. No remaining static gap is named by this receipt.",
"command": "ripr agent receipt --root . --verify-json target/ripr/agent/agent-verify.json --seam-id <seam-id> --json --out target/ripr/agent/agent-receipt.json"
}
],
"next_commands": [
{
"command": "ripr pilot --out target/ripr/pilot",
"reason": "Open the top actionable seam packet and write one focused targeted test."
}
]
}
Field contract:
schema_version- currently"0.1".- top-level
status-"pass"when all required inputs are present and no top weak seams require operator attention;"warn"when required inputs are missing, stale/unreadable, LSP cockpit status needs review, or actionable weak seams are visible. inputs[]- report inventory for repo exposure, LSP cockpit, before snapshot, after snapshot, agent verify, agent receipt, SARIF policy, badge status, targeted-test outcome, and optional mutation calibration.stateispresent,missing,optional_missing,unreadable, orinvalid_json.inputs[].required-truefor reports expected in the normal operator cockpit loop andfalsefor optional mutation calibration.inputs[].status- when an artifact is present, this is copied from the artifact's top-levelstatusfield. If the source JSON has nostatus, the cockpit uses"present". Missing required inputs use"missing"; missing optional inputs use"optional"; unreadable or invalid JSON inputs use"warn". Source-specific values such as"pass","warn","new_results", and"advisory_missing_baseline"are preserved.top_weak_seams[]- up to five headline-eligible repo exposure seams with operator-attention classes:weakly_gripped,ungripped,reachable_unrevealed,activation_unknown,propagation_unknown,observation_unknown, ordiscrimination_unknown.surface_alignment[]- per-surface status and anagreementstring that states whether LSP, before/after snapshots, agent verify, agent receipt, SARIF, badge, targeted outcome, and calibration artifacts are available and aligned with the operator loop.next_commands[]- ordered commands to generate missing reports, inspect the top seam packet, capture the after snapshot, run agent verify, write an agent receipt, and write the before/after targeted-test receipt.
The Markdown sibling prints:
Top Weak Seams, with each seam's ID, class, file, line, kind, why it matters, suggested next targeted test, and best related test when present.Surface Alignment, a table withSurface,State,Status,Agreement, andSignalcolumns for LSP, before/after snapshots, agent verify, agent receipt, SARIF, badge, targeted outcome, and calibration surfaces.Inputs, a table withReport,Required,State, andPathcolumns for every input artifact.Next Commands, an ordered list of commands to refresh missing reports, inspect the top seam packet, capture the after snapshot, run agent verify, write the agent receipt, and write the before/after targeted-test receipt.
Agent Seam Packets
ripr check --root . --format agent-seam-packets-json emits per-seam
agent work orders for every headline-eligible classified seam. The
artifact lands at target/ripr/reports/agent-seam-packets.json when
generated via cargo xtask agent-seam-packets.
ripr agent packet --root . --seam-id <id> --json emits the same
agent-seam-packets-json envelope filtered to one visible seam. It does not
dump the full repo packet set. Missing seam IDs, non-actionable seam classes,
and seams whose configured severity is off return an actionable error.
ripr agent packet --root . --gap-ledger <path> --gap-id <id> --json emits
the same packet envelope from one explicit GapRecord, matched by gap_id or
canonical_gap_id. This mode does not rerun analysis and does not infer
projectability from raw classifications. The selected record must have
projection_eligibility.agent_packet.eligible = true, a repair_route,
verification_commands, and a bounded edit surface from repair_route.target_file
or a path-like repair_route.related_test fallback. Records that are already observed, waived,
suppressed, preview-gating ineligible, or otherwise not agent-packet eligible
return an actionable error instead of a repair packet.
When the gap ledger was derived from check JSON, actionable Python
python_repair_card findings become preview-language GapRecords with
policy_state = "new", repairability = "repairable", gate and RIPR-zero
projection ineligible, and agent_packet projection eligible. If the raw
repair card does not carry receipt.command, the check-output ledger bridge
synthesizes a deterministic command that compares the supplied before check
JSON with target/ripr/reports/after-check.json and writes a gap-scoped receipt
under target/ripr/receipts/. This keeps Python packets delegable without
claiming runtime proof or gate authority.
ripr swarm queue --language python --top 10 reads
target/ripr/reports/gap-decision-ledger.json by default and emits a
GapRecord-backed queue of bounded agent-packet work. The queue does not rerun
analysis and only includes records that can already render through
ripr agent packet --gap-ledger ... --gap-id ... --json. Static limitations,
already-observed/no-action records, records without verify commands, and
records without allowed_edit_surface are counted in exclusion_reasons
instead of entering packets[]. --top is applied after the live-current
filtering: packets[] contains only assignable candidates —
queue_state = "queued" with staleness_status = "current" — selected in
upstream ledger order, so a stale or not_evaluated record never consumes a
bounded packet slot. Non-assignable candidates stay visible in a bounded,
command-free blocked_review[] projection that carries identity, typed
queue/currentness state, reason, conflict group, and refresh_commands only.
The summary keeps the honest denominators for every truncation:
queue_total counts validated candidates, assignable_total counts the
live-current assignable frontier, returned counts rendered packets,
unreturned_assignable_total counts assignable candidates --top left
unrendered, and stale_total / not_evaluated_total count blocked
candidates, with blocked_review_total and blocked_review_returned
reporting the full and rendered review projections.
The queue envelope is:
{
"schema_version": "0.1",
"tool": "ripr",
"report": "swarm-queue",
"scope": "repo",
"source": "gap_decision_ledger",
"status": "advisory",
"inputs": {
"root": ".",
"gap_ledger": "target/ripr/reports/gap-decision-ledger.json",
"language": "python",
"top": 10
},
"summary": {
"records_total": 3,
"language_records_total": 3,
"queue_total": 2,
"returned": 2,
"stale_total": 0,
"excluded_records_total": 1,
"conflict_groups_total": 1,
"current_total": 2,
"not_evaluated_total": 0,
"assignable_total": 2,
"returned_assignable_total": 2,
"unreturned_assignable_total": 0,
"blocked_total": 0,
"blocked_review_total": 0,
"blocked_review_returned": 0
},
"conflict_groups": [
{
"conflict_group": "file:tests/test_pricing.py",
"size": 2,
"gap_ids": ["gap:python:pricing-boundary", "gap:python:pricing-return"]
}
],
"exclusion_reasons": [
{
"reason": "is not agent-packet eligible: already_observed",
"count": 1
}
],
"packets": [
{
"priority": 1,
"queue_state": "queued",
"staleness_status": "current",
"staleness_reason": "producer-validated repo-exposure source matches the selected canonical root, exact clean HEAD, snapshot identity, content commitment, and persisted GapRecords",
"gap_id": "gap:python:pricing-boundary",
"canonical_gap_id": "gap:python:src/pricing.py:calculate_discount:predicate_boundary:predicate:amount>=threshold",
"language": "python",
"language_status": "preview",
"repair_kind": "StrengthenExistingTest",
"task": "strengthen_targeted_test",
"changed_owner": "calculate_discount",
"missing_discriminator": "amount == threshold",
"discriminator_guidance": {
"state": "present",
"text": "amount == threshold",
"basis": "activation_evidence_fact",
"reason": null,
"recovery": null,
"static_limit_kind": null
},
"suggested_test_file": "tests/test_pricing.py",
"suggested_test_name": "test_calculate_discount_smoke",
"verify_command": "pytest tests/test_pricing.py::test_calculate_discount_smoke",
"conflict_group": "file:tests/test_pricing.py",
"conflict_group_size": 2,
"allowed_edit_surface": ["tests/test_pricing.py"],
"allowed_files": ["tests/test_pricing.py"],
"forbidden_files": ["src/pricing.py"],
"assignment": {
"eligible": true,
"reason": "producer-validated live-current packet"
},
"packet_command_args": [
"ripr",
"agent",
"packet",
"--root",
".",
"--gap-ledger",
"target/ripr/reports/gap-decision-ledger.json",
"--gap-id",
"gap:python:pricing-boundary",
"--json"
]
}
],
"blocked_review": [
{
"source_index": 2,
"gap_id": "gap:python:pricing-stale",
"canonical_gap_id": "gap:python:src/pricing.py:calculate_discount:predicate_boundary:stale",
"language": "python",
"queue_state": "blocked_stale",
"staleness_status": "stale",
"staleness_reason": "repo-exposure source input identity no longer matches the current producer configuration; regenerate the source and ledger before assignment",
"conflict_group": "file:tests/test_pricing.py",
"assignment": {
"eligible": false,
"reason": "repo-exposure source input identity no longer matches the current producer configuration; regenerate the source and ledger before assignment"
},
"refresh_commands": [
"ripr agent check-repo-exposure --root . --repo-exposure target/ripr/reports/repo-exposure.json --mode draft",
"ripr reports gap-ledger --repo-exposure target/ripr/reports/repo-exposure.json --root . --out target/ripr/reports/gap-decision-ledger.json"
]
}
]
}
source_currentness is the live producer-backed authority for a packet source.
It contains status, queue_state, reason, refresh_commands,
source_kind, and source_path. A packet is assignable only when
source_currentness.status = "current" and queue_state = "queued"; the
rendered packet mirrors these values as staleness_status, queue_state, and
staleness_reason. current requires a canonical repo-exposure artifact with
matching repository root, exact clean HEAD, producer input identity, content
commitment, and GapRecords. The input identity is recomputed from the current
producer-consumed configuration, including an untracked ripr.toml; a changed
or invalid relevant configuration therefore fails closed as stale or
not_evaluated.
staleness_status = "not_evaluated" is a stop-and-refresh state, not freshness
proof. Stale or mismatched sources use queue_state = "blocked_stale", while
unresolved identities and invalid source artifacts use
queue_state = "blocked_not_evaluated"; each retains a
staleness_reason, and schedulers must refresh instead of assigning them. Any
non-assignable candidate that reaches live-currentness rendering is projected
into blocked_review[] with its bounded shell-escaped refresh_commands;
malformed ledgers and missing or mismatched roots follow the error and
blocker-envelope paths instead, without the projection; the review projection never carries
packet_command_args, verify or receipt commands, command_specs, suggested
tests, or edit-surface authority. summary.stale_total counts stale blocked
candidates and summary.not_evaluated_total counts unevaluated blocked
candidates; blocked_review_total always reports the full blocked
denominator even when the projection is bounded by --top.
conflict_group_size > 1 means another queued packet targets the same edit
surface, so schedulers should avoid assigning those packets in parallel.
If the gap decision ledger omits top-level root provenance, or declares a
root that clearly differs from the selected --root, ripr swarm queue
fails closed with status = "blocked", blocker.kind = "missing_root" or
blocker.kind = "wrong_root", and packets = []. The blocked queue preserves
inputs.gap_ledger_root, inputs.gap_ledger_generated_at, and
language-scoped blocked counts so schedulers can stop instead of assigning
stale, rootless, or wrong-workspace packets. Regenerate the gap decision ledger
for the selected root before rerunning the queue.
ripr swarm ingest --result target/ripr/workflow/agent-result.json reads one
external agent result artifact and emits an advisory classification. It does not
trust an agent success claim, rerun the verify command, write receipts, call
providers, generate tests, or inspect source code. Missing verify evidence is
classified as uncertain, and edits to packet forbidden_files are classified
as edited_forbidden_file before any reported verify or receipt success.
attempt_outcome uses the shared repair-loop outcome vocabulary so downstream
ledgers can distinguish attempted_no_receipt, receipt_present,
evidence_improved, evidence_unchanged, evidence_regressed, resolved,
and unknown without reinterpreting raw agent output.
The Python preview first-PR fixture pins this path with
fixtures/first_successful_pr/python-preview-gap/inputs/agent-results/closed.json
and
fixtures/first_successful_pr/python-preview-gap/expected/swarm-ingest/closed.json.
The ingest envelope is:
{
"schema_version": "0.1",
"tool": "ripr",
"report": "swarm-ingest",
"scope": "agent_result",
"source": "external_agent_result",
"status": "advisory",
"attempt_outcome": "unknown",
"inputs": {
"result": "target/ripr/workflow/agent-result.json"
},
"classification": {
"state": "edited_forbidden_file",
"outcome": "unknown",
"reason": "Agent result reports edits to files forbidden by the packet.",
"gap_id": "gap:python:pricing-boundary",
"canonical_gap_id": "gap:python:src/pricing.py:calculate_discount:predicate_boundary:predicate:amount>=threshold"
},
"evidence": {
"agent_status": "completed",
"stop_reason": null,
"staleness_status": "not_evaluated",
"edited_files": ["tests/test_pricing.py", "app/pricing.py"],
"allowed_files": ["tests/test_pricing.py"],
"forbidden_files": ["app/pricing.py"],
"edited_forbidden_files": ["app/pricing.py"],
"verify": {
"present": true,
"status": "passed",
"exit_code": 0,
"passed": true,
"failed": false
},
"receipt": {
"present": true,
"path": "target/ripr/receipts/gap-python-pricing-boundary.targeted-test-outcome.json",
"movement": "resolved"
}
},
"safety": {
"forbidden_edit_flagged": true,
"requires_human_review": true,
"trusted_success": false
},
"next_action": {
"kind": "edited_forbidden_file",
"summary": "Reject or manually review the attempt before using any test repair."
},
"must_not_infer": [
"do not trust agent-reported success without verify evidence",
"do not treat missing verify output as closed",
"do not ignore forbidden production-code edits",
"do not run providers, generate tests, run mutation testing, or claim runtime proof from ingest"
]
}
classification.state is one of closed, partially_improved,
verify_failed, edited_forbidden_file, stopped_by_agent, stale_packet,
or uncertain. Closure requires both passing verify evidence and recognized
receipt movement such as resolved or closed; passing verify with only
improved movement is partially_improved. classification.outcome and the
top-level attempt_outcome are one of attempted_no_receipt,
receipt_present, evidence_improved, evidence_unchanged,
evidence_regressed, resolved, or unknown. Ingest keeps
status: "advisory" even when attempt_outcome = "resolved" because it
classifies an external result artifact; it does not run verification or write
the receipt.
classification.reason carries a machine-readable string for every outcome.
For unknown outcomes it is always one of the following closed set of
ingest_reason values:
reason value | When emitted |
|---|---|
forbidden_edit | Agent edited a file on the packet's forbidden_files list; all movement claims are discarded. |
missing_verify | Verify evidence is absent, failed, or inconclusive; classifier cannot reach any improvement outcome. |
movement_without_snapshot_provenance | Receipt claims a movement (improved/unchanged/regressed/resolved) but the receipt provenance block is missing a non-empty before_artifact.sha256 or after_artifact.sha256. Classifier fails closed per RIPR-SPEC-0073 outcome-resolution rule 5. |
stale_packet | The input packet's staleness_status is stale; evidence from a stale packet is unreliable and no movement claim is accepted. |
For non-unknown outcomes (e.g. resolved, evidence_improved) the reason
is a human-readable sentence describing the classification; those sentences are
not part of the closed ingest_reason vocabulary and may change without a
schema bump.
evidence.receipt.provenance carries:
before_sha256— thebefore_artifact.sha256from the receipt provenance block, ornullif absent.after_sha256— theafter_artifact.sha256from the receipt provenance block, ornullif absent.snapshot_provenance_present—trueonly when bothbefore_sha256andafter_sha256are non-empty. A movement claim is accepted only when this istrue.
{
"schema_version": "0.3",
"scope": "repo",
"packets_total": 12565,
"packets": [
{
"task": "write_targeted_test",
"seam_id": "f3c9e4d21a0b7c88",
"owner": "src/pricing.rs::discounted_total",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"changed_expression": "amount >= discount_threshold",
"current_grip": "weakly_gripped",
"headline_eligible": true,
"recommended_test": {
"name": "discounted_total_boundary_discriminator",
"file": "tests/pricing.rs",
"reason": "place the new targeted test next to the nearest strong related test"
},
"suggested_test_command": "cargo test discounted_total_boundary_discriminator",
"suggested_test_command_status": "runnable_after_the_suggested_test_exists",
"nearest_strong_test_to_imitate": {
"name": "below_threshold_has_no_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"relation_reason": "direct_owner_call",
"relation_confidence": "high",
"reason": "nearest strong related test by ranked evidence"
},
"evidence": {
"reach": "yes",
"activate": "yes",
"propagate": "yes",
"observe": "yes",
"discriminate": "weak"
},
"observed_values": ["50", "10000"],
"missing_discriminators": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate"
}
],
"candidate_values": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate"
}
],
"missing_oracle_shape": "exact returned value assertion at the equality boundary",
"assertion_shape": {
"kind": "exact_return_value",
"example": "assert_eq!(discounted_total(/* discount_threshold (equality boundary) */), /* expected */)"
},
"related_existing_tests": [
{
"name": "below_threshold_has_no_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"evidence_summary": "exact value assertion",
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
}
],
"patterns_to_imitate": [
{
"name": "below_threshold_has_no_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"relation_reason": "direct_owner_call",
"relation_confidence": "high",
"reason": "strong exact_value oracle with high relation"
}
],
"patterns_to_avoid": [
{
"pattern": "adding another test with only already-observed values",
"reason": "candidate values should include the missing discriminator"
}
],
"suggested_assertions": [
"assert_eq!(discounted_total(/* discount_threshold (equality boundary) */), /* expected */)"
],
"confidence": "high",
"evidence_record": {
"schema_version": "0.1",
"seam_id": "f3c9e4d21a0b7c88",
"canonical_gap_id": "gap:67fc764ba37d77bd",
"canonical_gap_group_size": 1,
"canonical_gap_reason": "same owner, seam kind, flow sink, missing discriminator, and assertion shape",
"owner": "src/pricing.rs::discounted_total",
"location": {
"file": "src/pricing.rs",
"line": 88
},
"seam_kind": "predicate_boundary",
"grip_class": "weakly_gripped",
"headline_eligible": true,
"evidence_path": {
"reach": {
"state": "yes",
"confidence": "high",
"summary": "related test calls owner"
},
"activate": {
"state": "yes",
"confidence": "high",
"summary": "related test supplies boundary-adjacent values"
},
"propagate": {
"state": "yes",
"confidence": "medium",
"summary": "predicate flows to return value"
},
"observe": {
"state": "yes",
"confidence": "medium",
"summary": "related test asserts returned value"
},
"discriminate": {
"state": "weak",
"confidence": "high",
"summary": "equality boundary is not observed"
}
},
"assertion_texts": {
"12": "discounted_total(50, 100)"
},
"observed_values": [
{
"value": "50",
"line": 12,
"context": "function_argument"
}
],
"missing_discriminators": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate",
"flow_sink": null
}
],
"related_tests_total": 1,
"related_tests": [
{
"name": "below_threshold_has_no_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"evidence_summary": "exact value assertion",
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
}
],
"recommendation": {
"action": "write_targeted_test",
"reason": "extend the nearest related test with the missing discriminator",
"recommended_test": {
"name": "discounted_total_boundary_discriminator",
"file": "tests/pricing.rs",
"reason": "place the new targeted test next to the nearest strong related test"
},
"nearest_test_to_imitate": null,
"candidate_values": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case for this predicate"
}
],
"assertion_shape": {
"kind": "exact_return_value",
"example": "assert_eq!(discounted_total(/* discount_threshold (equality boundary) */), /* expected */)"
},
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json"
},
"actionability": {
"class": "actionable_related_test_extension",
"reason": "extend the nearest related test with the missing discriminator",
"has_concrete_guidance": true,
"signals": {
"missing_discriminator": true,
"candidate_value": true,
"assertion_shape": true,
"related_test": true,
"recommended_test_target": true,
"verification_command": true
}
},
"calibration": {
"availability": "not_imported",
"confidence": "unknown",
"agreement": "no_runtime_data"
},
"static_limitations": []
},
"runtime_confirmation": "optional cargo-mutants confirmation; ripr reports static evidence only",
"static_evidence_boundary": "static advisory evidence only; not runtime proof, coverage adequacy, mutation confirmation, gate approval, or merge approval."
}
],
"next": {
"before_snapshot_command": "mkdir -p target/ripr/workflow target/ripr/reports && ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/before.repo-exposure.json",
"after_snapshot_command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/after.repo-exposure.json",
"verify_after_edit": "ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json > target/ripr/workflow/agent-verify.json",
"receipt_after_verify": "ripr agent receipt --root . --verify-json target/ripr/workflow/agent-verify.json --seam-id f3c9e4d21a0b7c88 --json --out target/ripr/reports/agent-receipt.json"
}
}
Field contract:
schema_version— currently"0.4". Distinct from the repo-exposure report's"0.2"because the packet is a separate contract aimed at coding agents rather than reviewers. Bumping requires updating this section, the renderer (crates/ripr/src/output/agent_seam_packets.rs), and any downstream consumers in lockstep.0.2→0.3:related_existing_tests[]entries gainedrelation_reasonandrelation_confidencefields, and the array is now ranked highest-confidence first (analysis/related-test-precision-v1);context/agent-seam-packets-v2addedrecommended_test,nearest_strong_test_to_imitate,candidate_values,assertion_shape,patterns_to_imitate,patterns_to_avoid, and packetconfidencewithout changing the version again because the in-flight0.3contract had not yet closed.0.4adds the producer-ownedanalysis_outcome_statusandanalysis_outcomeenvelope so packet consumers cannot mistake seam-budget completion for diff-analysis completeness. Reason and confidence vocabularies are documented in therepo-exposure.jsonfield contract above.scope— always"repo", including the one-seamripr agent packetexpansion. The one-seam command is a filtered view of the repo packet contract, not a second packet schema.analysis_outcome_status— the producer outcome projection state. It is"complete"or"incomplete"when a typed diff outcome is present,"missing"or"invalid"when a required producer artifact cannot be trusted, and"not_applicable"for repo-only or gap-ledger packets that do not have a diff denominator. This field is independent ofrun_status, which only describes the agent packet seam budget.analysis_outcome_error— optional bounded diagnostic formissingorinvalidproducer evidence. It is never converted into a clean packet.analysis_outcome—nullfornot_applicable,missing, orinvalid; otherwise an envelope containinganalysis_complete, the exact typed produceroutcome(including kind, limitations, recovery routes, and input identity), and itssemantic_digest. Packet consumers copy this envelope; they do not rerun diff analysis or infer completeness from packet counts.source- optional. Present as"gap_decision_ledger"when the packet was rendered from explicitGapRecordinput rather than live seam analysis.inputs.gap_ledger- optional. Present with gap-ledger packet mode so reviewers and agents can trace the packet back to the artifact that owned projection eligibility.packets_total— number of actionable packets emitted. Equals the count of headline-eligible seams plus opaque seams (which emitinspect_static_limitation). Strongly-gripped, intentional, and suppressed seams produce no packet.packets[].task—"write_targeted_test"for headline-eligible seams;"inspect_static_limitation"for opaque seams. Future versions may add tasks like"strengthen_oracle"or"add_match_arm_observer". Gap-ledger packet mode also uses"write_targeted_test"for repairable assertion routes,"strengthen_targeted_test"for Python preview routes that strengthen an existing weak related test,"inspect_static_limitation"for explicit inspection routes, and"add_output_golden"forMissingOutputContractrecords whose repair route isAddOutputGolden. A discriminator-dependent GapRecord route with no producer-owned discriminator is downgraded to"inspect_static_limitation".packets[].gap_id,packets[].canonical_gap_id,packets[].gap_kind,packets[].language,packets[].language_status,packets[].policy_state,packets[].gap_state,packets[].repairability- optional GapRecord identity and policy fields. Present only whensource = "gap_decision_ledger".packets[].current_evidence_strength- optional GapRecord first-screen evidence summary in the form<evidence_class> / <gap_state>. Present only whensource = "gap_decision_ledger"and mirrored in the copyable packet so agent work orders carry the same current-evidence vocabulary asfirst-pr.packets[].allowed_edit_surface- GapRecord safety scope in gap-ledger packet mode. It is the route target file when supplied, or a path-likerelated_testfallback for older artifacts. If no bounded edit surface is available, packet rendering fails closed instead of emitting delegable work.packets[].allowed_filesandpackets[].forbidden_files- compatibility GapRecord safety scope in gap-ledger packet mode.allowed_filesmirrorsallowed_edit_surface.forbidden_filesis the source anchor file when it differs from the allowed file. Python preview packets use this to bound agents to the suggested test file and keep production Python files read-only.packets[].must_not_change- GapRecord safety boundaries in gap-ledger packet mode. The list mirrors the copyable packet's do-not-do section so JSON consumers and agent handoffs receive the same edit and authority limits.packets[].conflict_group- optional gap-ledger packet grouping key used by swarm schedulers to avoid parallel edits to the same target file. It isfile:<allowed_edit_surface>when an edit surface exists and otherwise falls back to the selected gap ID.packets[].receipt_commandandpackets[].receipt_status- receipt projection in gap-ledger packet mode. Rendering fails closed when an agent-packet-eligible GapRecord lacksreceipt_command; emitted packets usereceipt_status: "available". This prevents delegable repair work without a receipt route.packets[].static_evidence_boundary- optional static/advisory non-claim string. Gap-ledger packet mode uses the same boundary text asfirst-prso coding agents do not infer runtime mutation proof, coverage adequacy, gate approval, or merge approval from a repair packet.packets[].anchor- optional GapRecord anchor withfile,line,owner, anddedupe_fingerprintwhen supplied by the ledger.packets[].repair_route- optional full GapRecord repair route. Present for gap-ledger packet mode and mirrors the source ledger instead of reconstructing repair intent from rendered prose.repair_routemay includemissing_discriminatorwhen the source record can name the exact missing proof separately from the suggested assertion shape.packets[].missing_discriminator- nullable legacy first-screen missing proof copied only from producer-ownedrepair_route.missing_discriminator.assertion_shapeandchanged_behaviorare never relabelled as this field.packets[].discriminator_guidance- typed additive availability authority withstate(present,not_produced,not_applicable,static_limitation, orstale), nullabletext,basis,reason,recovery, andstatic_limit_kind. When the state is notpresent, the packet must not promote a discriminator-dependent route to a targeted-test repair; the copyable Markdown and repair card carry the same state.packets[].verification_commandsandpackets[].verify_command- optional GapRecord verification commands.verify_commandis the first command and is provided for existing single-command consumers.packets[].stop_conditions- optional agent stop conditions. Gap-ledger packet mode uses the route'sstop_conditionswhen supplied and otherwise adds bounded operational stop conditions so agents know when to stop instead of inventing a fix.packets[].repair_card- optional GapRecord-backed repair card carrying repair text, route, source artifact, verification commands, and the current evidence strength, receipt status, static evidence boundary, and authority boundary. It is the same repair vocabulary used by PR comment projection.packets[].llm_guidance.copyable_packet- optional GapRecord-backed pasteable repair packet for coding agents. It carriestask,context,repair,verification,receipt,stop_conditions,do_not_do,authority_boundary, static evidence boundary context, and a Markdown sibling with the same sections. It is additive and derives only from the selectedGapRecord; it does not rerun analysis, edit source, generate tests, call providers, change gate authority, or infer repairability from prose.packets[].current_grip— one of theSeamGripClassstrings the packet is emitted for (weakly_gripped,ungripped,reachable_unrevealed, the four*_unknownclasses, oropaque).packets[].headline_eligible— boolean.truefor the headline-eligible classes,falseforopaque. Lets agents prioritize without re-deriving the headline mapping.packets[].recommended_test— suggested test placement.nameis a deterministic snake-case test name derived from the seam owner and kind.fileuses the nearest strong related test when present, falls back to the highest-confidence related test, and otherwise infers a conventionaltests/*_tests.rspath from the production seam file.reasonexplains that choice.packets[].suggested_test_command— an advisory Cargo test-name filter for the recommended test. It is emitted only forwrite_targeted_testpackets and is not expected to select a test until the agent writes the named test.packets[].suggested_test_command_status— the explicit valuerunnable_after_the_suggested_test_exists; this prevents consumers from presenting the proposed filter as an already-executed proof command.packets[].nearest_strong_test_to_imitate— first ranked related test withoracle_strength: "strong", ornullwhen no strong related test is visible. This is an imitation target, not a requirement to clone that test.packets[].evidence— per-stageStageStatestrings.packets[].observed_values— literal scalars seen in owner-call arguments across related tests.packets[].missing_discriminators— array of{value, reason}records mirroring the analyzer'sMissingDiscriminatorFactshape. For predicate-boundary seams, includes a fallback entry naming the equality boundary even when no analyzer hypothesis fired.packets[].candidate_values— array of{value, reason}records naming input values or trigger shapes the new test should exercise. It is seeded frommissing_discriminators; if no missing discriminator exists, it falls back to the seam's required discriminator.packets[].missing_oracle_shape— guidance string keyed bySeamKindandExpectedSink. Examples:predicate_boundary→ "exact returned value assertion at the equality boundary"error_variant→ "exact error-variant assertion (matches! / assert_matches!)"side_effect→ "mock expectation, event/state observer, or persistence assertion (...)"
packets[].assertion_shape— the typed assertion-guidance projection.stateis one ofconcrete,requires_observer_setup,fix_site_only,verification_only,unresolved, orstale. Onlyconcretemay carrykind,basis, orexample; every other state carriesexample: nulland names itsreasonplus any boundedrecovery. Observer-required states nameobserver_kindand never emit a comment-shaped assertion.packets[].related_existing_tests— capped atMAX_RELATED_TESTS_PER_PACKET(currently 8). Carries test name, file, line, oracle kind, oracle strength, and a shortevidence_summarydescribing the oracle shape (e.g., "exact value assertion", "is_err / broad-error assertion").packets[].patterns_to_imitate— ranked related tests with strong or medium oracle strength. Each entry carries the same test identity and oracle/relation fields asnearest_strong_test_to_imitate, plus a reason.packets[].patterns_to_avoid— advisory patterns that would keep the packet low-discriminator, such as copying broad/smoke-only related tests or adding another test with only already-observed values. Each entry has{pattern, reason}.packets[].suggested_assertions— best-effort assertion templates the agent fills in, emitted only forassertion_shape.state == concrete. Placeholders are intentional; ripr never invents expected values. Example for predicate boundary:"assert_eq!(discounted_total(/* discount_threshold (equality boundary) */), /* expected */)".packets[].confidence—high,medium,low, orunknownconfidence in the packet recommendation. It is derived from related test ranking and visible missing-discriminator evidence.packets[].evidence_record- additive Lane 1 evidence spine for the selected seam, using the same schema version0.1documented under repo exposure. Agent packets keep their existing top-level work-order fields for compatibility, while this nested record gives downstream consumers the shared identity, evidence path, recommendation, actionability, calibration placeholder, and static limitations without reassembling them.packets[].runtime_confirmation— boilerplate string reminding the agent thatripris preflight static evidence and runtime mutation confirmation (e.g.,cargo-mutants) is a separate calibration step.packets[].static_evidence_boundary- typed non-claim boundary for coding agents and editor surfaces. Consumers should copy this field rather than infer runtime, coverage, correctness, gate, or merge claims from prose.next— optional repair-loop commands emitted when the envelope contains at least one actionable targeted-test packet.before_snapshot_commandfirst creates the workflow and report directories, then captures the initial static evidence;after_snapshot_commandcaptures the static evidence after the edit;verify_after_editwrites the verify artifact consumed by the receipt command.receipt_after_verifyis a seam-scoped command for a one-seam packet and isnullfor a repo-wide envelope containing multiple seams. These commands are advisory handoff instructions and do not execute a test, approve a patch, or authorize a merge.
The packet is the agent's work order: it names the seam, the missing discriminator, the oracle shape, and either a producer-backed assertion template or an explicit non-concrete recovery state — but never generates the test itself. Composition with a coding agent closes the loop.
Agent Working-Set Brief
ripr agent brief --json is an agent-active routing surface governed by
RIPR-SPEC-0010. It emits a
small working-set summary that selects the top seams relevant to the files,
lines, diff, base ref, or explicit seam ID an agent is touching.
Command forms:
ripr agent brief --root . --diff change.diff --json
ripr agent brief --root . --base main --json
ripr agent brief --root . --files src/pricing.rs --json
ripr agent brief --root . --seam-id f3c9e4d21a0b7c88 --json
The JSON shape uses schema 0.1:
{
"schema_version": "0.1",
"tool": "ripr",
"scope": "working_set",
"root": ".",
"mode": "draft",
"config": {
"state": "loaded",
"path": "ripr.toml",
"fingerprint": "fnv1a64:4c94a2f6cfaa5c21"
},
"working_set": {
"source": "diff",
"files": ["src/pricing.rs"],
"changed_lines": [
{
"file": "src/pricing.rs",
"line": 88
}
],
"base": "main",
"diff": "change.diff",
"seam_id": null
},
"limits": {
"requested": 3,
"returned": 1,
"default": 3,
"hard_cap": 10
},
"top_seams": [
{
"seam_id": "f3c9e4d21a0b7c88",
"owner": "src/pricing.rs::discounted_total",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"expression": "amount >= discount_threshold",
"grip_class": "weakly_gripped",
"severity": "warning",
"headline_eligible": true,
"why_now": {
"reason": "changed_line_intersects_seam",
"confidence": "high",
"evidence": "changed line 88 intersects the seam origin"
},
"evidence": {
"reach": "yes",
"activate": "yes",
"propagate": "yes",
"observe": "yes",
"discriminate": "weak"
},
"recommended_test": {
"name": "discounted_total_boundary_discriminator",
"file": "tests/pricing.rs",
"reason": "place the new targeted test next to the nearest strong related test"
},
"nearest_strong_test_to_imitate": {
"name": "below_threshold_has_no_discount",
"file": "tests/pricing.rs",
"line": 12,
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"relation_reason": "direct_owner_call",
"relation_confidence": "high"
},
"candidate_values": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case"
}
],
"missing_discriminators": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case"
}
],
"assertion_shape": {
"kind": "exact_return_value",
"example": "assert_eq!(discounted_total(/* discount_threshold (equality boundary) */), /* expected */)"
},
"packet_ref": {
"format": "agent-seam-packets-json",
"seam_id": "f3c9e4d21a0b7c88"
},
"verification": {
"before_snapshot_command": "mkdir -p target/ripr/workflow target/ripr/reports && ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/before.repo-exposure.json",
"after_snapshot_command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/after.repo-exposure.json",
"verify_command": "ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json",
"suggested_test_command": "cargo test discounted_total_boundary_discriminator"
}
}
],
"next": {
"inspect_packet": "ripr check --root . --mode draft --format agent-seam-packets-json > target/ripr/workflow/agent-seam-packets.json",
"verify_after_edit": "ripr agent verify --root . --before target/ripr/workflow/before.repo-exposure.json --after target/ripr/workflow/after.repo-exposure.json --json"
},
"warnings": []
}
Field contract:
scope— always"working_set".working_set.source—"diff","base","files", or"seam_id".limits.default— always3.limits.hard_cap— always10.top_seams[]— ranked seam summaries, intentionally smaller than full agent seam packets.top_seams[].why_now.reason— one ofchanged_line_intersects_seam,changed_owner_function,changed_test_for_related_seam,changed_assertion_near_related_test,same_file_seam,explicit_seam_id, orrepo_actionable_fallback.top_seams[].packet_ref— pointer to the full agent seam packet.top_seams[].verification— before/after static evidence commands and an optional focused test command.
Static examples use abbreviated JSON fragments to show routing behavior.
Diff-scoped touched seam:
{
"working_set": {
"source": "diff",
"files": ["src/pricing.rs"],
"changed_lines": [{ "file": "src/pricing.rs", "line": 88 }],
"diff": "change.diff"
},
"limits": { "requested": 3, "returned": 1, "default": 3, "hard_cap": 10 },
"top_seams": [
{
"seam_id": "f3c9e4d21a0b7c88",
"file": "src/pricing.rs",
"line": 88,
"grip_class": "weakly_gripped",
"why_now": {
"reason": "changed_line_intersects_seam",
"confidence": "high"
},
"missing_discriminators": [
{ "value": "discount_threshold (equality boundary)" }
],
"packet_ref": {
"format": "agent-seam-packets-json",
"seam_id": "f3c9e4d21a0b7c88"
},
"verification": {
"after_snapshot_command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/workflow/after.repo-exposure.json"
}
}
],
"warnings": []
}
File-scoped capped brief:
{
"working_set": {
"source": "files",
"files": ["src/pricing.rs"],
"changed_lines": []
},
"limits": { "requested": 3, "returned": 3, "default": 3, "hard_cap": 10 },
"top_seams": [
{
"seam_id": "f3c9e4d21a0b7c88",
"why_now": { "reason": "same_file_seam", "confidence": "medium" }
},
{
"seam_id": "a4c733e1d9ef0220",
"why_now": { "reason": "same_file_seam", "confidence": "medium" }
},
{
"seam_id": "c2f1b5d0a8ee9b41",
"why_now": { "reason": "same_file_seam", "confidence": "medium" }
}
],
"warnings": ["7 additional visible seams were omitted by the brief cap"]
}
Seam-ID lookup:
{
"working_set": {
"source": "seam_id",
"files": ["src/pricing.rs"],
"seam_id": "f3c9e4d21a0b7c88"
},
"limits": { "requested": 1, "returned": 1, "default": 3, "hard_cap": 10 },
"top_seams": [
{
"seam_id": "f3c9e4d21a0b7c88",
"why_now": { "reason": "explicit_seam_id", "confidence": "high" },
"packet_ref": {
"format": "agent-seam-packets-json",
"seam_id": "f3c9e4d21a0b7c88"
}
}
],
"warnings": []
}
Configured-off or suppressed seams:
{
"working_set": {
"source": "files",
"files": ["src/pricing.rs"],
"changed_lines": []
},
"limits": { "requested": 3, "returned": 0, "default": 3, "hard_cap": 10 },
"top_seams": [],
"warnings": [
"1 matching seam was hidden because configured severity is off",
"1 matching seam was hidden by a reasoned suppression"
]
}
The working-set brief must not write files, generate tests, change cache or LSP refresh behavior, or emit runtime mutation claims.
Pilot Summary
ripr pilot writes a first-run operator packet under target/ripr/pilot/ by
default. It reuses the repo-exposure and agent seam packet renderers, then adds
a small summary that ranks the next actionable seams. When Python preview is
enabled, the pilot also projects the top diff-scoped Python repair card from the
existing check path as advisory first-use guidance.
Pilot files:
target/ripr/pilot/repo-exposure.json
target/ripr/pilot/repo-exposure.md
target/ripr/pilot/agent-seam-packets.json
target/ripr/pilot/pilot-summary.json
target/ripr/pilot/pilot-summary.md
pilot-summary.json uses schema 0.2:
{
"schema_version": "0.2",
"tool": "ripr",
"scope": "repo",
"status": "complete",
"root": ".",
"mode": "draft",
"config": {
"state": "missing",
"path": null
},
"outputs": {
"repo_exposure_json": "target/ripr/pilot/repo-exposure.json",
"repo_exposure_md": "target/ripr/pilot/repo-exposure.md",
"agent_seam_packets_json": "target/ripr/pilot/agent-seam-packets.json",
"pilot_summary_json": "target/ripr/pilot/pilot-summary.json",
"pilot_summary_md": "target/ripr/pilot/pilot-summary.md"
},
"max_seams": 5,
"timeout_ms": 30000,
"outputs_written": [
"repo_exposure_json",
"repo_exposure_md",
"agent_seam_packets_json",
"pilot_summary_json",
"pilot_summary_md"
],
"actionable_seams_total": 1,
"top_actionable_seams": [
{
"seam_id": "67fc764ba37d77bd",
"file": "src/lib.rs",
"line": 2,
"kind": "predicate_boundary",
"owner": "src/lib.rs::discounted_total",
"grip_class": "weakly_gripped",
"why": "missing discriminator: discount_threshold (equality boundary)",
"missing_discriminator": {
"value": "discount_threshold (equality boundary)",
"reason": "observed values do not include the equality-boundary case"
},
"related_test_present": true,
"suggested_assertion_present": true,
"targeted_test_brief": "Target seam:\n- src/lib.rs:2\n..."
}
],
"python_first_use": null,
"next": {
"inspect_packet": "target/ripr/pilot/agent-seam-packets.json",
"after_snapshot_command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/pilot/after.repo-exposure.json",
"outcome_command": "ripr outcome --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json"
}
}
For Python preview roots with a diff-scoped repair card, python_first_use
is populated:
{
"status": "ready",
"language": "python",
"language_status": "preview",
"authority_boundary": "preview_advisory_only",
"findings_total": 1,
"repair_cards_total": 1,
"limitation_count": 0,
"analysis_error": null,
"supported_features": [
"project_detection",
"diff_owner_mapping",
"pytest_oracle_facts",
"unittest_oracle_facts",
"repair_cards"
],
"deferred_features": [
"outcome_receipts",
"runtime_mutation_execution",
"gate_authority",
"generated_tests"
],
"top_repair_card": {
"card_version": "python_repair_card.v1",
"canonical_gap_id": "gap:python:src/pricing.py:calculate_discount:predicate_boundary:predicate:amount>=threshold",
"language": "python",
"language_status": "preview",
"authority_boundary": "preview_advisory_only",
"repair_action": "strengthen_existing_test",
"changed_owner": "calculate_discount",
"missing_discriminator": "amount == threshold",
"suggested_test_file": "tests/test_pricing.py",
"suggested_test_name": "test_calculate_discount_smoke",
"verify_command": "pytest tests/test_pricing.py::test_calculate_discount_smoke",
"receipt_command": null,
"receipt_status": "unavailable_until_python_gap_ledger",
"receipt_guidance": "Save this `ripr check --format json` report, then run `ripr first-pr --check-output <check.json>` or `ripr reports gap-ledger --check-output <check.json>` to materialize a gap ledger with a concrete receipt command.",
"stop_conditions": [
"Stop if imports, fixtures, or test setup cannot call the changed owner.",
"Stop if the expected value for the missing discriminator is ambiguous.",
"Stop if adding the test appears to require a production-code edit."
],
"limits": [
"Syntax-first Python preview evidence only.",
"No source edits, generated tests, mutation execution, provider calls, or gate authority.",
"Verify success alone is not a gap-closure receipt."
]
}
}
If analysis exceeds the pilot budget, pilot-summary.json is still written with
status: "partial" and no ranked seams:
{
"schema_version": "0.2",
"tool": "ripr",
"scope": "repo",
"status": "partial",
"reason": "timeout",
"timeout_ms": 30000,
"completed_phases": [],
"root": ".",
"mode": "draft",
"config": {
"state": "missing",
"path": null
},
"outputs": {
"repo_exposure_json": "target/ripr/pilot/repo-exposure.json",
"repo_exposure_md": "target/ripr/pilot/repo-exposure.md",
"agent_seam_packets_json": "target/ripr/pilot/agent-seam-packets.json",
"pilot_summary_json": "target/ripr/pilot/pilot-summary.json",
"pilot_summary_md": "target/ripr/pilot/pilot-summary.md"
},
"outputs_written": [
"pilot_summary_json",
"pilot_summary_md"
],
"max_seams": 5,
"actionable_seams_total": null,
"top_actionable_seams": [],
"next": {
"retry_command": "ripr pilot --root . --out target/ripr/pilot --mode draft --max-seams 5 --timeout-ms 120000"
}
}
Field contract:
schema_version— currently"0.2".scope— always"repo".status—"complete"when repo exposure and agent seam packet artifacts were written, or"partial"when the command stopped at a diagnostic summary.reason— present for partial summaries; currently"timeout".timeout_ms— explicit pilot analysis budget. The default is30000.completed_phases— present for partial summaries. It is empty until pilot owns more detailed phase instrumentation.root— analyzed workspace root as supplied toripr pilot.mode— effective analysis mode after explicit CLI flags and repo config are applied.config.state—"loaded"whenripr.tomlwas loaded, otherwise"missing". Missing config is healthy and means built-in conservative defaults were used.outputs— paths to the generated pilot packet files.outputs_written— names of output files actually written. Partial timeout summaries write onlypilot_summary_jsonandpilot_summary_md.max_seams— cap requested by--max-seams.actionable_seams_total— number of seams considered actionable by the pilot ranking policy, ornullfor partial summaries where analysis did not finish.top_actionable_seams[]— ranked seams using class orderweakly_gripped,ungripped,reachable_unrevealed, unknown-stage classes, thenopaque, with evidence tie-breakers for missing discriminator, related test, suggested assertion, and stable location.top_actionable_seams[].targeted_test_brief— human-readable work order derived from the same fields as the agent seam packet. Placeholders are intentional; RIPR does not invent expected values.python_first_use—nullwhen Python preview first-use projection was not collected for this pilot run. When present, it reports the Python preview status (ready,no_python_findings,no_repair_cards, oranalysis_unavailable), counts, supported and deferred features, and the toppython_repair_cardusing the same advisory card fields emitted byripr check --json.next— advisory follow-up commands. Complete summaries include the publicripr outcomebefore/after receipt command. Partial summaries include a retry command with a larger explicit timeout.
The Markdown sibling prints the same summary, puts the top recommendation first, and includes the inspected seam, why it matters, the focused test to write, the top seam's targeted test brief, and the before/after commands for complete runs. It remains advisory. On timeout, the Markdown sibling records the partial state and the retry command instead of pretending the packet is complete.
LSP Seam Diagnostics
The LSP server publishes a Diagnostic for every actionable
ClassifiedSeam alongside the existing diff-scoped Finding diagnostics
under the built-in saved-workspace default. Clients or repo policy can pass
seamDiagnostics: false to disable seam diagnostics for a session.
Diff-scoped discriminator witness
Diff-scoped finding diagnostics may carry the same versioned producer witness
as ripr context --json. The witness is placed in diagnostic data.witness
and the copy-context action forwards it unchanged. Hover, context packets,
and diagnostic data therefore share one typed fact set:
{
"data": {
"schema_version": "0.1",
"explain_command": "ripr explain --root . probe:pricing:88:error_path",
"witness": {
"kind": "static_discriminator_gap",
"probe_family": "error_path",
"changed_expression": "map_error(result)",
"before": "Err(PricingError::Other)",
"after": "Err(PricingError::Boundary)",
"expected_sink": "error_variant",
"missing_discriminators": [
{
"value": "PricingError::Boundary",
"reason": "the broad error oracle does not distinguish the variant"
}
],
"fix_site": {
"file": "tests/pricing.rs",
"line": 10,
"test_name": "rejects_boundary",
"current_oracle": "assert!(result.is_err())",
"oracle_kind": "broad_error",
"oracle_strength": "weak",
"oracle_location": { "file": "tests/pricing.rs", "line": 12 }
},
"suggested_assertion": null,
"explain_command": "ripr explain --root . probe:pricing:88:error_path",
"confidence": { "value": 0.75, "basis": "static_only" },
"limitations": [
{
"kind": "suggested_assertion_unavailable",
"detail": "No producer-owned symbol-resolved assertion template is available."
}
]
}
}
}
The witness is projection-only. It does not create a repair route or authorize
an edit. Missing or ambiguous producer evidence is represented by null, an
omitted optional field, or a named limitations[] entry. In particular, a
renderer must never synthesize an assertion, choose a test from path or line
proximity, or turn a generic oracle into an exact discriminator. The related
information location points to the exact oracle source line only when the
producer supplied a matching assertion fact; otherwise it points to the
producer's test target. The human-facing related-information message uses the
explicit Fix site: role so clients do not confuse it with the changed code.
Diagnostic shape:
{
"range": { "start": { "line": 87, "character": 0 }, "end": { "line": 87, "character": 28 } },
"severity": 2, // 1=Error, 2=Warning, 3=Information, 4=Hint
"code": "ripr-seam-weakly-gripped",
"source": "ripr",
"message": "Weakly gripped behavioral seam (predicate_boundary): amount >= discount_threshold",
"data": {
"schema_version": "0.1",
"seam_id": "f3c9e4d21a0b7c88",
"seam_kind": "predicate_boundary",
"grip_class": "weakly_gripped",
"headline_eligible": true,
"owner": "src/pricing.rs::discounted_total",
"expected_sink": "return_value",
"evidence": {
"reach": "yes",
"activate": "yes",
"propagate": "yes",
"observe": "yes",
"discriminate": "weak"
}
}
}
When target/ripr/reports/gap-decision-ledger.json exists, the LSP server also
publishes advisory diagnostics for records whose
projection_eligibility.lsp_diagnostic.eligible flag is true and whose anchor
contains a local file and line. These diagnostics are sourced from the explicit
GapRecord; they do not infer projectability from raw findings and do not make
gate or badge decisions.
GapRecord diagnostic shape:
{
"range": { "start": { "line": 41, "character": 0 }, "end": { "line": 41, "character": 120 } },
"severity": 2,
"code": "ripr-gap-MissingBoundaryAssertion",
"source": "ripr",
"message": "ripr gap: MissingBoundaryAssertion; repair route: AddBoundaryAssertion; changed behavior: amount >= threshold; suggested check: assert_eq!(...)",
"data": {
"schema_version": "0.1",
"source": "gap_decision_ledger",
"gap_ledger": "target/ripr/reports/gap-decision-ledger.json",
"gap_id": "gap:pr:pricing:threshold-boundary",
"canonical_gap_id": "gap:rust:pricing:threshold-boundary",
"gap_kind": "MissingBoundaryAssertion",
"language": "rust",
"language_status": "stable",
"scope": "pr_local",
"evidence_class": "boundary_assertion",
"gap_state": "actionable",
"policy_state": "new",
"repairability": "repairable",
"repair_route": { "route_kind": "AddBoundaryAssertion" },
"anchor": {
"file": "src/pricing.rs",
"line": 42,
"owner": "pricing::discounted_total",
"dedupe_fingerprint": "gap:rust:pricing:threshold-boundary"
},
"evidence_ids": ["evidence:pricing:threshold-boundary"],
"verification_commands": ["cargo xtask fixtures boundary_gap"],
"command_specs": { // abbreviated CommandSpec fields for the shape example; full fields are required
"verify": { "command_id": "ripr:agent:verify", "role": "verify", "execution_mode": "direct" },
"receipt": { "command_id": "ripr:agent:receipt", "role": "receipt", "execution_mode": "direct" }
}
}
}
Validated gap diagnostics can drive bounded repair actions such as Inspect gap: copy repair packet, Verify after test: copy verify command, and Review result: copy receipt command when the current artifact supplies safe payloads.
The repair-packet action calls ripr.collectContext with gap_id and
gap_ledger. The command returns the same GapRecord-backed agent packet
produced by ripr agent packet --gap-ledger ... --gap-id ...; it does not
rerun analysis, edit source, generate tests, call a provider, run mutation
testing, or parse the diagnostic message. Stale, missing, disabled, or
unvalidated gap artifacts fail closed to refresh-only actions.
The command_specs objects in the diagnostic example are abbreviated to show
the projection shape; real emitted objects carry the complete CommandSpec
fields described above. When present, data.command_specs.verify and .receipt are producer-owned
CommandSpec objects. The first_repair_packet and gap_repair_packet code
action payloads carry the same validated objects for machine-facing clients;
legacy display command fields remain for human and compatibility consumers.
The action projection never reconstructs typed argv from a display string and
does not execute either route.
Per-class severity:
SeamGripClass | Severity | Diagnostic? |
|---|---|---|
weakly_gripped | Warning | yes |
ungripped | Warning | yes |
reachable_unrevealed | Warning | yes |
activation_unknown | Information | yes |
propagation_unknown | Information | yes |
observation_unknown | Information | yes |
discrimination_unknown | Information | yes |
opaque | Information | yes |
strongly_gripped | — | no |
intentional | — | no |
suppressed | — | no |
Diagnostic codes are stable: ripr-seam-{class} with _ replaced by
- in the class name. Editors can filter or theme by code without
parsing severity. The data field carries seam_id so seam-evidence
hover (lsp/seam-evidence-hover-v1) can look up the same record from
inventory_classified_seams_at.
Seam evidence hover renders from that same ClassifiedSeam record, not from
diagnostic message text. For actionable seams it includes the grip class,
RIPR evidence path, observed values, missing discriminator, related test
location, suggested test shape, packet and brief handoff command strings,
verify and receipt command strings, static evidence limits, and per-kind next
step when those fields are available. The hover does not run mutation testing,
edit source, generate tests, or claim runtime adequacy.
The diagnostic range is currently a full-line placeholder: seams
do not yet carry a column, so the range spans (line, 0) →
(line, MAX_DIAGNOSTIC_RANGE_WIDTH). Editors render this as a
single-line squiggle that always covers the seam regardless of
indentation. A future PR can derive the real column from the source
file via the (now reserved) _root parameter on
diagnostic_for_classified_seam.
Seam diagnostics also drive editor code actions:
Inspect Test Gap - Copy Contextcallsripr.collectContextwithseam_idand copies the selected agent seam packet JSON.Write targeted test: copy briefcopies a plain-language work order derived from the same seam packet guidance.Agent handoff: copy packet commandandAgent handoff: copy brief commandcopy the selected seam's agent packet and brief commands.Verify after test: copy after-snapshot commandandVerify after test: copy verify commandcopy the static after-snapshot and verify commands.Review result: copy receipt commandcopies the selected seam's receipt command.Write targeted test: copy suggested assertionappears only when the agent seam packet assertion shape contains a concrete assertion example.Write targeted test: open best related testappears only when ranked related-test evidence has a visible file/line.Refresh Analysis - Saved Workspace Checkremains available for every request.
Validated GapRecord diagnostics use the same code-action surface for
repair-routing records. Python preview GapRecords accept bounded pytest ...
and python -m unittest ... verification commands, expose verify and receipt
copy actions when those commands are safe, expose Agent handoff: copy Python packet to copy the same GapRecord-backed agent packet as ripr agent packet --gap-ledger ... --gap-id ..., expose Copy Python repair card to copy a
current validated GapRecord repair-card brief for safe target-file routes through
ripr.copyTargetedTestBrief, can open repair_route.target_file when
related_test is a bare test name, and expose Write Python test: copy pytest skeleton for pytest-backed repairs. The Python agent-packet action appears
only for current validated Python GapRecord diagnostics with
gap_state = "actionable", repairability = "repairable", safe gap-ledger and
repair-route paths, and safe verify plus receipt commands. The copied repair
card includes the current-GapRecord freshness cue, changed owner, changed
behavior, current weak test evidence, missing discriminator, suggested
assertion and location, verify and receipt commands when safe, stop conditions,
and static preview limits. The copied skeleton is a fail-fast work order with
the canonical gap, missing discriminator, suggested file, verify command, stop
conditions, and a NotImplementedError placeholder; it does not edit files or
silently create a passing test.
These actions do not edit files, generate tests, or add CodeLens
surface. The pre-4B Finding/AnalysisSnapshot hover and context
actions continue to work for diff-scoped diagnostics; seam diagnostics
live alongside them.
Seam diagnostics can also drive executeCommand ripr.collectEvidenceContext.
The command accepts a seam_id argument and returns one bounded editor handoff
packet derived from the latest saved-workspace ClassifiedSeam plus the shared
agent-loop command templates. It does not run analysis, edit source, generate
tests, call an LLM provider, or run mutation testing. Unknown seams return no
packet.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"root": ".",
"mode": "draft",
"seam_id": "67fc764ba37d77bd",
"file": "src/pricing.rs",
"range": {
"start": 88,
"end": 88
},
"class": "weakly_gripped",
"seam_kind": "predicate_boundary",
"owner": "pricing::discounted_total",
"expression": "amount >= discount_threshold",
"required_discriminator": "boundary_value",
"expected_sink": "return_value",
"evidence_path": {
"reach": "present",
"activate": "present",
"propagate": "present",
"observe": "present",
"discriminate": "weak"
},
"evidence_summaries": {
"reach": "related test calls owner",
"activate": "test reaches branch",
"propagate": "return value sink",
"observe": "exact assertion",
"discriminate": "boundary value missing"
},
"missing_discriminator": "discount_threshold (equality boundary)",
"missing_discriminators": [
{
"value": "discount_threshold (equality boundary)",
"reason": "observed values skip equality boundary"
}
],
"related_test": "tests/pricing.rs::below_threshold_has_no_discount",
"related_test_location": {
"file": "tests/pricing.rs",
"line": 12,
"test_name": "below_threshold_has_no_discount",
"oracle_kind": "exact_value",
"oracle_strength": "strong"
},
"suggested_assertion": "assert_eq!(...)",
"suggested_test": {
"file": "tests/pricing.rs",
"name": "discounted_total_boundary_value",
"candidate_value": "discount_threshold (equality boundary)",
"assertion_shape": "Assert the exact returned value."
},
"agent_packet_command": "ripr agent packet --root . --seam-id 67fc764ba37d77bd --json > target/ripr/agent/agent-packet.json",
"agent_brief_command": "ripr agent brief --root . --seam-id 67fc764ba37d77bd --json > target/ripr/agent/agent-brief.json",
"after_snapshot_command": "ripr check --root . --mode draft --format repo-exposure-json > target/ripr/pilot/after.repo-exposure.json",
"verify_command": "ripr agent verify --root . --before target/ripr/pilot/repo-exposure.json --after target/ripr/pilot/after.repo-exposure.json --json > target/ripr/agent/agent-verify.json",
"receipt_command": "ripr agent receipt --root . --verify-json target/ripr/agent/agent-verify.json --seam-id 67fc764ba37d77bd --json --out target/ripr/agent/agent-receipt.json",
"limits_note": "Static evidence only; no runtime mutation execution."
}
Dogfood Report
cargo xtask dogfood writes:
target/ripr/reports/dogfood.json
target/ripr/reports/dogfood.md
target/ripr/dogfood/<fixture>/check.json
target/ripr/dogfood/<fixture>/human.txt
target/ripr/dogfood/gate-adoption/<case>/gate-decision.json
target/ripr/dogfood/gate-adoption/<case>/gate-decision.md
fixtures/boundary_gap/expected/gate-adoption/<case>/gate-decision.json
fixtures/boundary_gap/expected/gate-adoption/<case>/gate-decision.md
fixtures/boundary_gap/expected/first-useful-action/<case>/first-useful-action.json
fixtures/boundary_gap/expected/first-useful-action/<case>/first-useful-action.md
fixtures/first_successful_pr/<case>/expected/start-here.json
fixtures/first_successful_pr/<case>/expected/start-here.md
fixtures/boundary_gap/expected/pr-review-front-panel/<case>/pr-review-front-panel.json
fixtures/boundary_gap/expected/pr-review-front-panel/<case>/pr-review-front-panel.md
fixtures/boundary_gap/expected/report-packet-index/<case>/index.json
fixtures/boundary_gap/expected/report-packet-index/<case>/index.md
fixtures/finding-alignment-dogfood/corpus.json
fixtures/surface-projection-alignment/corpus.json
fixtures/real-repair-attempts/corpus.json
fixtures/python-real-repo-evals/corpus.json
fixtures/typescript-preview-repair-loop/corpus.json
fixtures/typescript-preview-false-actionable-audit/corpus.json
fixtures/user-surface-projection-alignment/corpus.json
fixtures/bun-ub-cross-language-dogfood/corpus.json
The report is advisory. It runs ripr check --mode fast against stable fixture
diffs and runs ripr gate evaluate against checked boundary-gap PR guidance
and calibration evidence for the explicit gate adoption modes. It also checks
repo-local first useful action receipts for the documented first-action routes.
It records first successful PR receipts and first-run adoption counters for the
checked start-here.{json,md} corpus.
It checks repo-local PR review front-panel receipts for the documented Campaign
24 reviewer routes. It checks repo-local report-packet index receipts for the
documented Campaign 25 packet-index routes. It records
default_ci_blocking: false; generated CI still leaves RIPR_GATE_MODE unset
unless the repository configures it. It also validates the generated GitHub
workflow cockpit receipt for Start here guidance, known regeneration
commands, artifact upload, advisory default posture, and gate-authority
boundaries. The generated adoption receipts are compared with
fixtures/boundary_gap/expected/gate-adoption/. The checked first-action
receipts are read from fixtures/boundary_gap/expected/first-useful-action/.
The checked first successful PR receipts are read from
fixtures/first_successful_pr/.
The checked front-panel receipts are read from
fixtures/boundary_gap/expected/pr-review-front-panel/. The checked
report-packet index receipts are read from
fixtures/boundary_gap/expected/report-packet-index/. The checked finding
alignment receipts are read from fixtures/finding-alignment-dogfood/ and
record real RIPR PR examples where raw findings remain supporting evidence,
canonical items are the countable unit, canonical gap identities and raw
finding summaries are explicit, actionable items have repair and verification
routes, static limitations name analyzer repair routes, and runtime-confidence
static-only class examples stay calibration work rather than user test debt.
The checked surface-projection alignment receipts are read from
fixtures/surface-projection-alignment/ and pin receipt-backed canonical gaps
plus static-limitation backlog routes across swarm-attempt-ledger and
swarm-readiness so canonical_gap_id, packet_id, repair_kind, verify
command, receipt command/state when present, outcome, limitation route, and
top_next_action stay aligned while badge, LSP, PR, and CI remain advisory
consumers instead of independent ranking or gate authorities.
The checked real repair attempt receipts are read from
fixtures/real-repair-attempts/ and record several repo-local Lane 1 repair
attempts, including improved/resolved movement and unchanged or missing-receipt
non-success cases, so failed or incomplete attempts remain visible instead of
being hidden from the repair queue.
The checked Python real-repo eval receipts are read from
fixtures/python-real-repo-evals/ and record the top Python repair card,
bounded agent packet, ranked top-3 repair-card findings, verify command,
before/after receipt movement, false-positive notes, and unsupported limitation
kinds. The report derives python_repair_routing_quality from those receipts,
including top-1 actionable usefulness, top-3 actionable precision over captured
ranked repair-card findings, verify-command validity, agent-packet boundary
validity, concrete-discriminator and test-location coverage,
false-actionable and crash rates, receipt closure rate, and unsupported
limitation distribution. Eval cases with fewer than three ranked repair-card
findings must include an explicit limit reason.
The checked TypeScript-family preview repair-loop receipts are read from
fixtures/typescript-preview-repair-loop/ and preserve advisory preview
boundaries for useful TypeScript/JavaScript routes, weak-oracle downgrades,
static limitations, skipped incomplete-packet cases, checked complete-packet
receipts, and packet-ready counts.
The checked TypeScript false-actionable audit rows are read from
fixtures/typescript-preview-false-actionable-audit/; dogfood projects
typescript_false_actionable_audit.summary.false_actionable_rate from rows
that must remain non-actionable and also reports packet-ready, actionable
gap-state, complete-packet category, and preview-boundary violation rates. This
section is advisory and does not create repair packets, gates, badge inputs,
baselines, RIPR Zero input, generated tests, source edits, provider calls,
mutation testing, or support-tier promotion.
The checked Bun UB cross-language witness receipts are read from
fixtures/bun-ub-cross-language-dogfood/ and record the calibrated
#31648-shaped known-good, stripped-resizable, maxByteLength mention-only,
bridge-unknown, configured copy_to_unshared, configured MarkdownObject, node:fs
scalar write manifest-only, Bun.write helper-gated, and FFI panic-boundary
operator cases. The bun_ub_cross_language_witnesses JSON section includes
default_ci_blocking: false, preview_authority: "advisory", summary counts,
including bridge_unknown and named_static_limitation, case ids, source
calibration or profile cases, route-quality cases, Rust seam fields, observed
state, missing discriminators or graph legs, suggested TypeScript test file,
manual verdict, operator action, bridge and placement verdicts, proof mode, raw
evidence refs, non-claims, and repair_packet_ready: false.
The checked user-surface projection receipts are read from
fixtures/user-surface-projection-alignment/ and prove badge, LSP, PR comment,
and CI projection examples share the same canonical gap, packet or limitation
backlog identity, repair kind, verify command, receipt command, and top next
action while remaining advisory and never treating raw finding totals as
headline product truth.
The calibrated-gate dogfood case expects a non-zero evaluator exit only for the
explicit blocking mode and treats that as healthy when the written decision
report has the expected blocked status and count.
JSON shape:
{
"schema_version": "0.1",
"status": "pass",
"advisory": true,
"runs": [
{
"name": "boundary_gap",
"root": "fixtures/boundary_gap/input",
"diff": "fixtures/boundary_gap/diff.patch",
"actual_dir": "target/ripr/dogfood/boundary_gap",
"duration_ms": 123,
"findings": 1,
"stop_reason_mentions": 1,
"class_counts": {
"exposed": 0,
"weakly_exposed": 1,
"reachable_unrevealed": 0,
"no_static_path": 0,
"infection_unknown": 0,
"propagation_unknown": 0,
"static_unknown": 0
},
"errors": []
}
],
"first_useful_action": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/boundary_gap/expected/first-useful-action",
"cases": [
{
"name": "actionable",
"expected_dir": "fixtures/boundary_gap/expected/first-useful-action/actionable",
"json_path": "fixtures/boundary_gap/expected/first-useful-action/actionable/first-useful-action.json",
"markdown_path": "fixtures/boundary_gap/expected/first-useful-action/actionable/first-useful-action.md",
"status": "actionable",
"action_kind": "write_focused_test",
"audience": "developer",
"selected": true,
"static_movement": "unknown",
"expected_status": "actionable",
"expected_action_kind": "write_focused_test",
"expected_audience": "developer",
"expected_selected": true,
"expected_static_movement": "unknown",
"errors": []
}
]
},
"first_successful_pr": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/first_successful_pr",
"metrics": {
"first_run_packets_total": 5,
"first_run_top_gap_selected_total": 3,
"first_run_no_action_total": 1,
"first_run_blocked_total": 1,
"first_run_missing_artifact_total": 0,
"first_run_stale_artifact_total": 0,
"first_run_wrong_root_total": 0,
"first_run_malformed_artifact_total": 0,
"first_run_timeout_total": 0
},
"cases": [
{
"name": "boundary-gap",
"expected_dir": "fixtures/first_successful_pr/boundary-gap/expected",
"json_path": "fixtures/first_successful_pr/boundary-gap/expected/start-here.json",
"markdown_path": "fixtures/first_successful_pr/boundary-gap/expected/start-here.md",
"status": "actionable",
"state": "top_gap",
"top_gap_kind": "MissingBoundaryAssertion",
"verify_command": "cargo xtask fixtures boundary_gap",
"next_command": null,
"expected_status": "actionable",
"expected_state": "top_gap",
"description": "A repairable Rust boundary gap becomes the top first-run repair.",
"errors": []
},
{
"name": "python-preview-gap",
"expected_dir": "fixtures/first_successful_pr/python-preview-gap/expected",
"json_path": "fixtures/first_successful_pr/python-preview-gap/expected/start-here.json",
"markdown_path": "fixtures/first_successful_pr/python-preview-gap/expected/start-here.md",
"status": "actionable",
"state": "top_gap",
"output_state": "preview_limited",
"top_gap_kind": "MissingBoundaryAssertion",
"verify_command": "pytest tests/test_pricing.py::test_calculate_discount_threshold_boundary",
"next_command": null,
"expected_status": "actionable",
"expected_state": "top_gap",
"description": "A repairable Python preview gap becomes a preview-limited first-run repair.",
"errors": []
}
]
},
"pr_review_front_panel": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/boundary_gap/expected/pr-review-front-panel",
"cases": [
{
"name": "actionable",
"json_path": "fixtures/boundary_gap/expected/pr-review-front-panel/actionable/pr-review-front-panel.json",
"markdown_path": "fixtures/boundary_gap/expected/pr-review-front-panel/actionable/pr-review-front-panel.md",
"status": "advisory",
"top_issue_state": "actionable",
"policy_state": "new_policy_eligible",
"placement": "changed_line",
"movement_state": "unknown",
"coverage_grip_state": "not_available",
"new_policy_eligible": 1,
"baseline_resolved": 0,
"blocking_candidates": 0,
"warnings": 0,
"expected_status": "advisory",
"expected_top_issue_state": "actionable",
"expected_policy_state": "new_policy_eligible",
"expected_placement": "changed_line",
"expected_movement_state": "unknown",
"expected_coverage_grip_state": "not_available",
"expected_new_policy_eligible": 1,
"expected_baseline_resolved": 0,
"expected_blocking_candidates": 0,
"expected_warnings": 0,
"reason": "The front panel should show the top focused-test action first when a PR-local seam is line-placeable.",
"errors": []
}
]
},
"report_packet_index": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/boundary_gap/expected/report-packet-index",
"cases": [
{
"name": "complete_packet",
"actual_dir": "fixtures/boundary_gap/expected/report-packet-index/complete-packet",
"json_path": "fixtures/boundary_gap/expected/report-packet-index/complete-packet/index.json",
"markdown_path": "fixtures/boundary_gap/expected/report-packet-index/complete-packet/index.md",
"expected_report": "fixtures/boundary_gap/expected/report-packet-index/complete-packet/index.json",
"expected_markdown": "fixtures/boundary_gap/expected/report-packet-index/complete-packet/index.md",
"status": "pass",
"missing_expected": 0,
"warnings": 0,
"failures": 0,
"start_here_available": true,
"gate_authority_present": true,
"groups": [
"start_here",
"pr_review_story",
"repair_agent_handoff",
"evidence_movement",
"policy_gates",
"calibration",
"validation_receipts",
"sarif_badges"
],
"expected_status": "pass",
"expected_missing_expected": 0,
"expected_warnings": 0,
"expected_failures": 0,
"expected_start_here_available": true,
"expected_gate_authority_present": true,
"expected_required_groups": [
"start_here",
"pr_review_story",
"repair_agent_handoff",
"evidence_movement",
"policy_gates",
"calibration",
"validation_receipts",
"sarif_badges"
],
"reason": "A complete packet should tell reviewers to start at the PR front panel while preserving gate-decision authority.",
"errors": []
}
]
},
"generated_ci_cockpit": {
"default_ci_blocking": false,
"default_inline_comments": "off",
"language_grouping": "deferred",
"cases": [
{
"name": "generated-pr-ci-review-workflow",
"command": "cargo run --quiet -p ripr -- init --ci github --dry-run",
"duration_ms": 123,
"start_here": true,
"repair_commands": 4,
"expected_repair_commands": 4,
"gate_authority_boundary": true,
"default_advisory": true,
"artifact_upload": true,
"language_grouping_status": "deferred",
"errors": []
}
]
},
"finding_alignment": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/finding-alignment-dogfood",
"cases": [
{
"name": "config_policy_rendered_label_unobserved",
"source_pr": "EffortlessMetrics/ripr#1016",
"canonical_gap_id": "gap:config_policy_rendered_label_unobserved",
"evidence_class": "config_or_policy_constant",
"raw_findings_total": 2,
"canonical_items_total": 1,
"raw_finding_summary": "A rendered policy-label declaration and literal align into one canonical output-observer item.",
"gap_state": "actionable",
"actionability": "add_output_observer",
"user_outcome": "actionable_gap",
"repair_kind": "output_observer",
"target_test_type": "report_render_or_golden",
"verify_command": "cargo xtask evidence-quality-scorecard",
"static_limitation_category": null,
"static_limitation_repair_route": null,
"raw_findings_supporting_only": true,
"recommended_repair": "Add or update a report-render, config-output, snapshot, or golden observer for the rendered policy label.",
"before_after_context": "Before structured repair-route checks, prose or class-local metadata could look sufficient; after the burn-down this actionable item requires a concrete repair and verify command.",
"must_not_claim": [
"Do not count declaration and literal findings as separate user actions.",
"Do not infer actionability from raw static class.",
"Do not recommend mutation testing before output-observer work."
],
"reason": "A rendered config or policy label with no supported observer should become one actionable output-observer item.",
"errors": []
}
]
},
"surface_projection_alignment": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/surface-projection-alignment",
"cases": [
{
"name": "receipt_improved_top_next_action_alignment",
"canonical_gap_id": "gap:boundary-discriminator-004",
"packet_id": "boundary-discriminator-004",
"repair_kind": "add_boundary_assertion",
"verify_command": "cargo test -p ripr-swarm boundary_discriminator_004",
"receipt_command": "cargo xtask receipts write --packet boundary-discriminator-004 --canonical-gap gap:boundary-discriminator-004",
"receipt_state": "receipt_movement_improved",
"outcome": "evidence_improved",
"readiness_status": "advisory",
"top_next_action_kind": "attempt_ready_packet",
"top_next_action_command": "cargo xtask ripr-swarm attempt --packet boundary-discriminator-004 --dry-run",
"attempted_packets": 1,
"improved_packets": 1,
"advisory_consumers": ["badge", "lsp", "pr_comment", "ci"],
"reason": "single receipt-backed canonical gap projection alignment",
"errors": []
}
]
},
"real_repair_attempts": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/real-repair-attempts",
"summary": {
"attempted": 5,
"improved": 2,
"unchanged": 1,
"regressed": 0,
"resolved": 1,
"attempted_no_receipt": 1
},
"cases": [
{
"name": "repair_route_quality_metrics_improved",
"source_ref": "EffortlessMetrics/ripr-swarm#415",
"canonical_gap_id": "gap:repair-route-quality-metrics-missing",
"packet_id": "repair-route-quality-metrics-001",
"repair_kind": "add_repair_route_quality_metrics",
"target_test_or_observer_shape": "readiness and attempt-ledger report assertions over repair_kind attempted/improved/unchanged/regressed counts",
"verify_command": "cargo xtask check-pr",
"verify_result": "pass",
"receipt_command": "cargo xtask ripr-swarm readiness",
"receipt_path": "target/ripr/reports/swarm-readiness.json",
"receipt_state": "receipt_movement_improved",
"actor_kind": "codex",
"before_gap_state": "actionable",
"after_gap_state": "actionable",
"outcome": "evidence_improved",
"attempted_repair": "Added repair-route quality rollups and top failing/missing evidence route fields to attempt-ledger/readiness outputs.",
"evidence_movement": "Readiness can now show repair_kind success-rate evidence instead of only packet counts.",
"operator_note": "The route-quality attempt improved analyzer-backlog signal without changing badge, LSP, PR, or CI authority.",
"must_not_change": ["public badge semantics", "CI gate defaults", "autonomous repair behavior"],
"raw_evidence_refs": ["metrics/capabilities.toml:ripr_swarm_repair_loop"],
"missing_receipt_reason": null,
"reason": "A real merged repair-loop PR converted attempt outcomes into route-quality evidence.",
"errors": []
}
]
},
"python_real_repo_evals": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/python-real-repo-evals",
"summary": {
"cases": 7,
"closed": 7,
"usable": 7
},
"cases": [
{
"name": "decorated_route_status_pytest_receipt",
"repo_shape": "decorated_route_pytest",
"canonical_gap_id": "gap:python:app/checkout.py:checkout:field_value:field_construction:response.status_code=422",
"repair_card_present": true,
"agent_packet_present": true,
"agent_packet_task": "Strengthen the existing decorated-route pytest test with response.status_code == 422.",
"agent_packet_command": "ripr agent packet --root target/ripr/python-real-repo-evals/decorated-route-receipt --gap-ledger gap-ledger.json --gap-id gap:python:app/checkout.py:checkout:field_value:field_construction:response.status_code=422 --json",
"agent_packet_allowed_files": ["tests/test_checkout.py"],
"agent_packet_forbidden_files": ["app/checkout.py"],
"agent_packet_stop_if": ["import cannot be resolved", "expected status code is ambiguous", "production code edit appears necessary"],
"missing_discriminator": "response.status_code == 422",
"suggested_test_file": "tests/test_checkout.py",
"verify_command": "pytest tests/test_checkout.py::test_expired_coupon_response_smoke",
"verify_result": "pass",
"receipt_result": "pass",
"gap_movement": "closed",
"unsupported_limitations": ["dynamic_route_registration"],
"ranked_top_3_findings": [
{
"rank": 1,
"canonical_gap_id": "gap:python:app/checkout.py:checkout:field_value:field_construction:response.status_code=422",
"repair_card_present": true,
"usability": "usable",
"missing_discriminator": "response.status_code == 422",
"suggested_test_file": "tests/test_checkout.py",
"verify_command": "pytest tests/test_checkout.py::test_expired_coupon_response_smoke",
"false_positive_notes": "none observed",
"reason": "Rank 1 repair card matched the closed Python receipt."
}
],
"ranked_top_3_limit_reason": "Focused eval emitted one Python repair card; no rank 2 or rank 3 repairable Python finding was present.",
"errors": []
}
]
},
"python_repair_routing_quality": {
"default_ci_blocking": false,
"input": "fixtures/python-real-repo-evals/corpus.json",
"quality_gate": {
"status": "pass",
"reason": "All checked top Python repair cards are usable, verifiable, placed, and receipt-backed without observed false actionability"
},
"summary": {
"cases": 7,
"top_1_actionable_precision": {
"status": "pass",
"count": 7,
"checked": 7
},
"top_3_actionable_precision": {
"status": "pass",
"count": 7,
"checked": 7
},
"verify_command_validity": {
"status": "pass",
"count": 7,
"checked": 7
},
"agent_packet_boundary_validity": {
"status": "pass",
"count": 7,
"checked": 7
},
"concrete_discriminator_rate": {
"status": "pass",
"count": 7,
"checked": 7
},
"related_test_location_rate": {
"status": "pass",
"count": 7,
"checked": 7
},
"receipt_closure_rate": {
"status": "pass",
"count": 7,
"checked": 7
},
"false_actionable_rate": {
"status": "pass",
"count": 0,
"checked": 7
},
"crash_rate": {
"status": "pass",
"count": 0,
"checked": 7
},
"ranked_top_3_cases_with_capture": {
"status": "pass",
"count": 7,
"checked": 7
}
},
"unsupported_limitation_distribution": [
{
"kind": "dynamic_route_registration",
"cases": 1
}
]
},
"user_surface_projection_alignment": {
"default_ci_blocking": false,
"receipt_dir": "fixtures/user-surface-projection-alignment",
"cases": [
{
"name": "badge_actionable_count_from_canonical_state",
"surface": "badge",
"artifact": "badge-basis",
"headline": "ripr: 8 actionable",
"run_status": "full",
"projection_basis": "canonical_actionable_gap",
"canonical_gap_id": "gap:boundary-discriminator-004",
"packet_id": "boundary-discriminator-004",
"repair_kind": "add_boundary_assertion",
"top_next_action_kind": "attempt_ready_packet",
"verify_command": "cargo test -p ripr-swarm boundary_discriminator_004",
"receipt_command": "cargo xtask receipts write --packet boundary-discriminator-004 --canonical-gap gap:boundary-discriminator-004",
"actionable_count": 8,
"raw_findings_total": 312,
"consumes_canonical_state": true,
"reinterprets_raw_findings": false,
"raw_findings_headline": false,
"advisory": true,
"blocking_default": false,
"limited_state_visible": true,
"stale_state_visible": true,
"reason": "Badge projection should show unresolved actionable canonical gaps or limited/stale, never raw finding volume.",
"errors": []
}
]
},
"gate_adoption": {
"default_ci_blocking": false,
"receipt_dir": "target/ripr/dogfood/gate-adoption",
"cases": [
{
"name": "visible-only-advisory",
"mode": "visible-only",
"actual_dir": "target/ripr/dogfood/gate-adoption/visible-only-advisory",
"json_path": "target/ripr/dogfood/gate-adoption/visible-only-advisory/gate-decision.json",
"markdown_path": "target/ripr/dogfood/gate-adoption/visible-only-advisory/gate-decision.md",
"duration_ms": 123,
"status": "advisory",
"blocking": 0,
"acknowledged": 0,
"advisory": 1,
"expected_status": "advisory",
"expected_blocking": 0,
"expected_acknowledged": 0,
"expected_advisory": 1,
"exit_success": true,
"expected_exit_success": true,
"errors": []
}
]
}
}
The checked first-action receipt cases are:
| Case | Expected status | Purpose |
|---|---|---|
actionable | actionable | Records the focused-test action for a PR-local weak seam. |
baseline-only | baseline_only | Keeps historical baseline debt visible without turning it into PR-local test work. |
stale | stale | Requires evidence refresh before selecting a focused action. |
missing-required-artifact | missing_required_artifact | Routes agents to generate the missing assistant proof input. |
unchanged-after-attempt | unchanged_after_attempt | Routes back to revising the focused test when static movement is unchanged. |
no-actionable-seam | no_actionable_seam | Records the clean advisory state instead of silence. |
The checked PR review front-panel receipt cases are:
| Case | Expected top issue state | Purpose |
|---|---|---|
actionable | actionable | Shows the focused-test repair route for a PR-local weak seam. |
acknowledged | actionable | Keeps ripr-waive visible as acknowledgement, not hidden success. |
suppressed | baseline_only | Keeps durable suppression policy visible in PR review. |
baseline_resolved | already_improved | Shows reviewed baseline debt resolved by the PR. |
blocked | actionable | Shows a configured gate block while preserving the repair route and gate authority. |
missing_proof | missing_required_input | Routes reviewers to regenerate the missing assistant proof artifact. |
advisory_only | no_actionable_seam | Records a no-action advisory state instead of silence. |
coverage_flat_grip_improved | already_improved | Shows static grip improvement while coverage stays flat. |
The checked report-packet index receipt cases are:
| Case | Expected status | Purpose |
|---|---|---|
complete_packet | pass | Shows the complete reviewer-first packet, including start-here and gate-authority links. |
sparse_advisory | warn | Keeps sparse adoption advisory while showing missing optional surfaces. |
missing_front_panel | warn | Makes a missing first-screen front panel visible instead of forcing artifact archaeology. |
blocked_gate | fail | Preserves a configured blocked gate state while naming gate decision as authority. |
missing_assistant_proof | warn | Routes users to regenerate missing assistant proof instead of hiding the gap. |
missing_receipts | warn | Shows missing validation receipts and their regeneration commands. |
coverage_grip_present | pass | Keeps coverage/grip context findable as calibration context, not runtime confirmation. |
The checked generated-CI cockpit receipt cases are:
| Case | Expected result | Purpose |
|---|---|---|
generated-pr-ci-review-workflow | pass | Validates the generated workflow summary starts with Start here, includes known regeneration commands for missing cockpit surfaces, uploads report artifacts, stays advisory by default, and keeps gate-decision authority separate. |
The checked adoption cases are:
| Case | Expected status | Purpose |
|---|---|---|
visible-only-advisory | advisory | Records policy evidence without blocking. |
acknowledged-waiver | acknowledged | Shows ripr-waive as a visible acknowledgement. |
baseline-check-existing | advisory | Shows a baseline-known identity as visible and non-blocking. |
baseline-check-new-gap | blocked | Shows a new policy-eligible identity blocking in explicit baseline-check mode. |
calibrated-high-confidence-new-gap | blocked | Shows explicit calibrated-gate behavior for a new supported candidate. |
missing-baseline-config | config_error | Shows missing required baseline input as a repair-oriented configuration error. |
LSP Cockpit Report
cargo xtask lsp-cockpit-report writes:
target/ripr/reports/lsp-cockpit.json
target/ripr/reports/lsp-cockpit.md
The report is an advisory dogfood artifact for the editor loop. It reads the
committed LSP fixture expectations, plus the VS Code e2e smoke test file, and
summarizes the editor surface without opening VS Code.
For seam fixtures, status downgrades from pass when the editor-agent loop
command actions for packet, brief, after-snapshot, verify, or receipt are
missing from the pinned action payloads.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"status": "pass",
"fixtures": [
{
"fixture": "boundary_gap",
"diagnostics_path": "fixtures/boundary_gap/expected/lsp-diagnostics.json",
"code_actions_path": "fixtures/boundary_gap/expected/lsp-code-actions.json",
"diagnostics": {
"total": 1,
"seams": 1,
"findings": 0,
"seam_ids": ["67fc764ba37d77bd"],
"grip_classes": ["weakly_gripped"]
},
"actions": {
"titles": [
"Inspect Test Gap - Copy Context",
"Write targeted test: copy brief",
"Agent handoff: copy packet command",
"Agent handoff: copy brief command",
"Verify after test: copy after-snapshot command",
"Verify after test: copy verify command",
"Review result: copy receipt command",
"Write targeted test: copy suggested assertion",
"Write targeted test: open best related test",
"Refresh Analysis - Saved Workspace Check"
],
"commands": [
"ripr.copyContext",
"ripr.copyTargetedTestBrief",
"ripr.copyAgentPacketCommand",
"ripr.copyAgentBriefCommand",
"ripr.copyAfterSnapshotCommand",
"ripr.copyAgentVerifyCommand",
"ripr.copyAgentReceiptCommand",
"ripr.copySuggestedAssertion",
"ripr.openRelatedTest",
"ripr.refresh"
],
"argument_fields": [
"after_snapshot",
"agent_brief_json",
"agent_packet_json",
"agent_receipt_json",
"agent_verify_json",
"assertion",
"before_snapshot",
"brief",
"command",
"diagnostic_range",
"label",
"line",
"mode",
"owner",
"root",
"seam_file",
"seam_id",
"seam_kind",
"severity",
"target_artifact",
"test_name",
"uri"
]
},
"context": {
"seam_packet_available": true,
"targeted_test_brief_available": true,
"agent_packet_command_available": true,
"agent_brief_command_available": true,
"after_snapshot_command_available": true,
"agent_verify_command_available": true,
"agent_receipt_command_available": true,
"assertion_available": true,
"related_test_available": true,
"refresh_available": true
}
}
],
"vscode_e2e": {
"test_file": "editors/vscode/test/suite/extension.test.ts",
"contributed_commands": [
"ripr.copyAfterSnapshotCommand",
"ripr.copyAgentBriefCommand",
"ripr.copyAgentPacketCommand",
"ripr.copyAgentReceiptCommand",
"ripr.copyAgentVerifyCommand",
"ripr.copyContext",
"ripr.copySuggestedAssertion",
"ripr.copyTargetedTestBrief",
"ripr.openRelatedTest",
"ripr.openSettings",
"ripr.restartServer",
"ripr.showOutput",
"ripr.showStatus"
],
"covered_commands": [
"ripr.collectContext",
"ripr.copyAfterSnapshotCommand",
"ripr.copyAgentBriefCommand",
"ripr.copyAgentPacketCommand",
"ripr.copyAgentReceiptCommand",
"ripr.copyAgentVerifyCommand",
"ripr.copyContext",
"ripr.copySuggestedAssertion",
"ripr.copyTargetedTestBrief",
"ripr.openRelatedTest",
"ripr.openSettings",
"ripr.restartServer",
"ripr.showOutput",
"ripr.showStatus"
],
"covered_contributed_commands": [
"ripr.copyAfterSnapshotCommand",
"ripr.copyAgentBriefCommand",
"ripr.copyAgentPacketCommand",
"ripr.copyAgentReceiptCommand",
"ripr.copyAgentVerifyCommand",
"ripr.copyContext",
"ripr.copySuggestedAssertion",
"ripr.copyTargetedTestBrief",
"ripr.openRelatedTest",
"ripr.openSettings",
"ripr.restartServer",
"ripr.showOutput",
"ripr.showStatus"
],
"uncovered_contributed_commands": []
}
}
status is pass when at least one fixture pins LSP diagnostics/actions and
all contributed VS Code commands are represented in the e2e command coverage
scan. It is warn when no LSP fixture expectations are present or a contributed
command is not represented in the e2e command scan. The report is not a schema
for LSP protocol messages; those remain pinned by fixture expectations and LSP
unit tests.
Gap Decision Ledger
ripr reports gap-ledger --records <path> renders a read-only advisory ledger
from explicit GapRecord input. The input may be a records array,
gap_records array, raw record array, or the fixtures/gap-decision-ledger
corpus shape where each case contains expected_gap_record.
ripr reports gap-ledger --repo-exposure <path> derives conservative
repo-scoped Rust GapRecord entries from existing
seams[].evidence_record.canonical_item data in a repo-exposure report. This
does not rerun analysis or make PR-local gate/comment claims; derived records
are repo-scoped projection inputs for reports, badges, LSP diagnostics, and
agent packets when the evidence record already supplies a repair route and
verification command.
ripr reports gap-ledger --check-output <path> derives PR-local records from
an existing check JSON finding_alignment.items[] section, actionable Python
findings[].python_repair_card objects, and complete TypeScript
findings[].typescript_repair_packet objects. Supported visible output text
without a checked observer becomes MissingOutputContract with
repair_route.route_kind = "AddOutputGolden" and
verification_commands = ["cargo xtask goldens check"]. Actionable Python
repair cards and complete TypeScript repair packets become preview-language
records with bounded test edit surfaces, verify commands, and a synthesized
ripr outcome command that compares the supplied before check JSON with
target/ripr/reports/after-check.json.
Python static-limit findings with static_limit_kind become report-only
StaticLimitation records with repairability = "analyzer_limitation" and no
agent-packet projection. Visibility-unknown presentation text and Python static
limits remain limitations and do not become generic static_unknown repair
instructions.
The command writes JSON to target/ripr/reports/gap-decision-ledger.json and
Markdown to target/ripr/reports/gap-decision-ledger.md by default. It does
not rerun analysis, infer analyzer truth, publish comments, edit source,
generate tests, call providers, run mutation testing, change gate policy, or
make CI blocking by default.
Each supplied GapRecord may carry seam_id when the producer owns a typed
canonical seam identity. Generic ordered evidence_ids, file/line placement,
display text, and owner names are not seam-ID fallbacks. A repair route may
also carry the producer-owned inspection_command; it is distinct from the
verification and receipt commands and is never synthesized by the gate. A
legacy record that omits either field remains readable but its normalized gate
route is explicitly incomplete_repair_route. Multiple records for one
canonical gap that contain duplicate, conflicting, or mixed seam identities
fail closed as a named ledger input configuration error.
Gap-ledger PR review cards likewise project only GapRecord.seam_id; a row
without it is suppressed with missing_seam_identity rather than using
gap_id as a seam substitute.
Typed command specifications (additive command_specs): records may carry
command_specs.verify, command_specs.receipt, and
command_specs.regeneration CommandSpec collections. Every collection
accepts a single object or an array (null reads as empty); each spec must
pass CommandSpec validation and carry the collection's role, so a verify
spec inside command_specs.regeneration is a named input error, not a silent
re-slot. Regeneration collections cover the canonical report-regeneration
routes only:
ripr check --root R --mode M --format repo-exposure-json > OUT- recovered asshell_required(the redirect is shell semantics) withOUTas the expected write and argv stopping before the redirect;Mmust come from the CLI mode vocabulary (instant,draft,fast,deep,ready).ripr reports gap-ledger --repo-exposure E --out O --out-md M,ripr reports gap-ledger --check-output C --root R --out O --out-md M, and the shorter single-output forms ending at--out O- recovered asdirectwithOand the CLI default Markdown output (target/ripr/reports/gap-decision-ledger.md, applied independently of--out) as the expected writes; forms without any output flag fail closed.ripr pr-review front-panel ...andripr reports index ...- loop-template routes: their closed flag set in any order, no repeats, and the route's mandatory flags present; front-panel additionally requires at least one explicit artifact input (--pr-guidance,--first-action,--assistant-proof,--assistant-health,--ledger,--baseline-delta,--zero-status,--gate-decision,--recommendation-calibration,--mutation-calibration,--coverage-frontier, or--receipt), matching the CLI.
Legacy string-only regeneration_commands for these routes gain their typed
specs at read time on every parse path (ledger build and persisted-ledger
loaders, LSP included); records already carrying typed regeneration specs are
never double-appended. Displays that deviate from a route's exact shape -
reordered flags, unknown or missing flags, extra tokens, compound && shell
lines, or traversing/absolute output paths - stay legacy strings and gain no
typed spec.
JSON shape:
{
"schema_version": "0.1",
"tool": "ripr",
"kind": "gap_decision_ledger",
"status": "advisory",
"root": ".",
"generated_at": "unix_ms:1778710000000",
"inputs": {
"source_kind": "records",
"records": "fixtures/gap-decision-ledger/corpus.json"
},
"summary": {
"records_total": 18,
"repairable_total": 9,
"static_limitation_total": 1,
"no_action_total": 5,
"missing_artifact_total": 1,
"projection_pr_comment_eligible": 5,
"projection_gate_candidate": 1,
"projection_agent_packet_eligible": 10,
"ripr_zero_target_count": 1,
"ripr_plus_target_count": 2,
"preview_ineligible_total": 1,
"receipt_improved_total": 1,
"receipt_unchanged_after_attempt_total": 1,
"missing_output_contract_total": 1
},
"records": [
{
"gap_id": "gap:pr:pricing:threshold-boundary",
"canonical_gap_id": "gap:rust:pricing:discount:threshold-boundary",
"kind": "MissingBoundaryAssertion",
"language": "rust",
"language_status": "stable",
"scope": "pr_local",
"evidence_class": "predicate_boundary",
"gap_state": "actionable",
"policy_state": "new",
"repairability": "repairable",
"repair_route": {
"route_kind": "AddBoundaryAssertion",
"target_file": "tests/pricing.rs",
"assertion_shape": "assert_eq!(discount(100, 100), 90)"
},
"anchor": {
"file": "src/pricing.rs",
"line": 42,
"owner": "pricing::discount",
"dedupe_fingerprint": "gap:rust:pricing:discount:threshold-boundary"
},
"evidence_ids": [
"evidence:pricing-threshold-reached"
],
"projection_eligibility": {
"pr_comment": {
"eligible": true,
"reason": "stable_anchor_and_repair_route"
},
"gate_candidate": {
"eligible": true,
"reason": "safe_gate_predicate_satisfied"
}
},
"verification_commands": [
"cargo xtask fixtures boundary_gap"
],
"safe_gate_predicate": {
"policy_target_enabled": true,
"suppressed": false,
"waived": false,
"acknowledged_only": false,
"baseline_known": false,
"preview_language": false,
"static_unknown_only": false
},
"receipt": {
"state": "missing_receipt",
"movement": "missing_receipt"
},
"authority_boundary": "gate_decision_artifact_only"
}
],
"warnings": [],
"limits": [
"Advisory static gap decisions only.",
"Gate-decision artifacts remain the only configured pass/fail authority."
]
}
status is advisory when records parse cleanly, advisory_with_warnings
when records are present but violate projection-safety checks, and blocked
when no records can be read. The summary counts are projection inputs only;
they are not gate authority.
Mutation Calibration Reports
ripr calibrate cargo-mutants --mutants-json <path> --repo-exposure-json <repo-exposure-json>
joins an existing repo exposure report with imported cargo-mutants JSON/output
and prints Markdown by default:
ripr calibrate cargo-mutants \
--mutants-json target/mutants/outcomes.json \
--repo-exposure-json target/ripr/pilot/after.repo-exposure.json
Use --format json for the JSON shape below, and --out <path> to write the
rendered report to a file. Repo-local automation can still write
target/ripr/reports/mutation-calibration.{json,md} through
cargo xtask mutation-calibration.
<path> may point directly at a JSON file or at a cargo-mutants output
directory. When given a directory, the command reads and combines
outcomes.json and mutants.json when both are present, preserving runtime
outcomes and generated mutant locations for matching.
This is an advisory runtime calibration report, not a static finding surface.
Runtime outcome labels come from the supplied mutation output and are kept under
the runtime side of each match. Static reports continue using the audit
vocabulary (test grip, missing discriminator, static evidence, runtime confirmation).
JSON shape:
{
"schema_version": "0.1",
"scope": "repo",
"status": "advisory",
"metrics": {
"static_seams_total": 120,
"mutants_total": 8,
"matched_total": 6,
"ambiguous_file_line_total": 1,
"unmatched_mutants_total": 1,
"static_without_runtime_total": 113,
"runtime_outcome_counts": {
"caught": 5,
"timeout": 3
},
"join_method_counts": {
"seam_id": 4,
"file_line": 2
}
},
"agreement": {
"static_gap_and_runtime_signal": 18,
"static_gap_without_runtime_signal": 4,
"runtime_signal_without_static_gap": 3,
"static_clean_and_runtime_clean": 41,
"runtime_inconclusive": 2
},
"precision_notes": [
"runtime gap signals are imported runtime labels such as missed, survived, not_caught, or uncaught"
],
"missed_runtime_signals": [
{
"runtime": {
"mutant_id": "m9",
"seam_id": "f3c9e4d21a0b7c88",
"file": "src/pricing.rs",
"line": 88,
"mutation_operator": "replace >= with >",
"runtime_outcome": "missed",
"duration": "123",
"test_command": "cargo test pricing"
},
"static": {
"seam_id": "f3c9e4d21a0b7c88",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"seam_grip_class": "strongly_gripped",
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"observed_values": ["50", "10000"],
"missing_discriminators": []
},
"confidence_label": "contradicts_static_clean",
"reason": "runtime gap signal joined to a static-clean seam"
}
],
"static_only_findings": [
{
"static": {
"seam_id": "a1b2c3d4e5f60718",
"seam_kind": "return_value",
"file": "src/pricing.rs",
"line": 90,
"seam_grip_class": "weakly_gripped",
"oracle_kind": "smoke",
"oracle_strength": "smoke",
"observed_values": [],
"missing_discriminators": ["exact returned value assertion"]
},
"confidence_label": "contradicts_static_gap",
"reason": "static gap seam matched runtime data without a runtime gap signal"
}
],
"matches": [
{
"join_method": "seam_id",
"static": {
"seam_id": "f3c9e4d21a0b7c88",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"seam_grip_class": "weakly_gripped",
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"observed_values": ["50", "10000"],
"missing_discriminators": ["amount == discount_threshold (equality boundary)"]
},
"runtime": {
"mutant_id": "m1",
"seam_id": "f3c9e4d21a0b7c88",
"file": "src/pricing.rs",
"line": 88,
"mutation_operator": "replace >= with >",
"runtime_outcome": "caught",
"duration": "123",
"test_command": "cargo test pricing"
},
"confidence_label": "contradicts_static_gap"
}
],
"ambiguous_file_line_matches": [
{
"runtime": {
"mutant_id": "m7",
"seam_id": null,
"file": "src/pricing.rs",
"line": 88,
"mutation_operator": "replace >= with >",
"runtime_outcome": "caught",
"duration": "99",
"test_command": "cargo test pricing"
},
"confidence_label": "ambiguous_runtime_join",
"candidates": [
{
"seam_id": "f3c9e4d21a0b7c88",
"seam_kind": "predicate_boundary",
"file": "src/pricing.rs",
"line": 88,
"seam_grip_class": "weakly_gripped",
"oracle_kind": "exact_value",
"oracle_strength": "strong",
"observed_values": ["50", "10000"],
"missing_discriminators": [
"amount == discount_threshold (equality boundary)"
]
},
{
"seam_id": "a1b2c3d4e5f60718",
"seam_kind": "return_value",
"file": "src/pricing.rs",
"line": 88,
"seam_grip_class": "ungripped",
"oracle_kind": "unknown",
"oracle_strength": "unknown",
"observed_values": [],
"missing_discriminators": []
}
]
}
],
"unmatched_mutants": [],
"static_without_runtime_sample": []
}
Field contract:
schema_version— currently"0.1".status— always"advisory"; this report does not block CI by default.metrics.static_seams_total— count of seams imported fromrepo-exposure.json.metrics.mutants_total— count of runtime mutation records imported from the supplied JSON.metrics.matched_total— runtime records joined to a static seam.metrics.ambiguous_file_line_total— runtime records whose normalized file/line matched multiple static seams and were therefore not assigned to a single seam.metrics.unmatched_mutants_total— runtime records that could not be joined byseam_idor file/line.metrics.static_without_runtime_total— static seams with no definitive or ambiguous runtime record in this import.metrics.runtime_outcome_counts— counts keyed by normalized runtime outcome label from the imported data.metrics.join_method_counts— counts forseam_idandfile_linejoins.agreement.static_gap_and_runtime_signal— static gap seams that also have at least one matched runtime gap signal in this import.agreement.static_gap_without_runtime_signal— static gap seams with no matched runtime gap signal in this import. This includes seams with only runtime-clean labels, only runtime-inconclusive labels, or no matched runtime record.agreement.runtime_signal_without_static_gap— runtime gap signals joined to static-clean seams, plus unmatched runtime gap signals.agreement.static_clean_and_runtime_clean— static-clean seams with matched runtime-clean labels and no matched runtime gap signal.agreement.runtime_inconclusive— matched or ambiguous runtime records whose imported labels are neither runtime gap signals nor runtime-clean signals.precision_notes[]— short notes explaining the report's advisory agreement mapping. The report treats imported labels such asmissed,survived,not_caught, anduncaughtas runtime gap signals, and labels such ascaughtandtimeoutas runtime-clean signals.missed_runtime_signals[]— capped sample of runtime gap signals that did not correspond to a static gap.staticisnullwhen the runtime record did not join to a seam.missed_runtime_signals[].confidence_label—contradicts_static_cleanwhen a runtime gap signal joined to a static-clean seam, orruntime_only_signalwhen a runtime gap signal did not join to any static seam. This is advisory calibration context only and does not create a static gap.static_only_findings[]— capped sample of static gap seams without a matched runtime gap signal.static_only_findings[].confidence_label—contradicts_static_gapwhen a static gap joined only to runtime-clean labels, orno_runtime_datawhen no usable runtime signal was available for the static gap in this import.matches[].join_method—seam_idwhen the runtime record carries a matching seam/probe ID; otherwisefile_linewhen normalized path and line match.matches[].static— static seam evidence copied fromrepo-exposure.json: seam identity, class, strongest visible oracle kind/strength, observed values, and missing discriminators.matches[].runtime— imported runtime mutation record: mutation ID when available, seam/probe ID when available, location, operator, outcome, duration, and test command.matches[].confidence_label— per-match static/runtime confidence label:supports_static_gap,contradicts_static_gap,supports_static_clean,contradicts_static_clean, orno_runtime_data. Runtime-inconclusive labels map tono_runtime_databecause they provide no usable support or contradiction for the static claim.ambiguous_file_line_matches[]— runtime records that matched multiple static seams by normalized file/line. These records are intentionally not assigned tomatches[]without a stronger seam/probe ID.ambiguous_file_line_matches[].confidence_label— alwaysambiguous_runtime_join; ambiguous joins do not raise or lower confidence for any candidate seam.unmatched_mutants[]— runtime records that did not match a static seam.static_without_runtime_sample[]— capped sample of static seams with no definitive or ambiguous runtime data in this import. Usestatic_without_runtime_totalfor the full count.
No-Panic Allowlist Proposal Reports
cargo xtask check-no-panic-family --propose writes review-only migration
artifacts:
target/ripr/reports/no-panic-allowlist-proposals.md
target/ripr/reports/no-panic-allowlist-proposals.toml
These reports are policy-maintenance aids, not product JSON contracts. They are
generated from current panic-family findings and the canonical
policy/no-panic-allowlist.toml ledger. They may propose semantic selectors
for legacy line/column entries, current semantic entries, or narrower selectors
for ambiguous entries, but they never rewrite the allowlist.
The Markdown report records each candidate's current finding, confidence,
whether it replaces a v0.1 entry, old coordinates when available, new
last_seen values, preserved reason text, suggested selector, and review
warnings. The TOML report uses schema 0.3 with status = "proposal" and is a
copy aid only; reviewers must supply real ids, owners, expiries, and rationale
before adopting any proposal.
Canonical PR Delta Artifact
cargo xtask ripr-pr writes target/ripr/pr/canonical-delta.json after it
materializes one canonical repo-exposure snapshot for each requested revision.
The artifact is producer-owned and versioned independently from the check and
repo-exposure schemas.
The top-level contract is:
{
"schema_version": "0.1",
"base": {"revision": "<rev>", "status": "complete", "available": true},
"head": {"revision": "<rev>", "status": "complete", "available": true},
"coverage": {
"base_items": 1,
"head_items": 1,
"matched_items": 1,
"ambiguous_items": 0,
"unknown_items": 0,
"complete": true,
"low_coverage_disclosed": false
},
"summary": {"attribution_counts": {"changed_surface_existing": 1}},
"limitations": [],
"deltas": []
}
Each deltas[] entry is the serialized CanonicalDelta from
ripr::domain, with base/head locations, seam ids, and a match_kind of
exact, rename_or_move, head_only, base_only, or ambiguous. The typed
attribution vocabulary is closed. Only canonical owner, behavior identity,
discriminator identity, evidence state, and oracle state establish a match;
line proximity never establishes causality. Missing or ambiguous snapshots
produce comparison_unknown. low_coverage_disclosed: true is informational
and must not be interpreted as a complete causal comparison.
Causal projection parity
The same producer-owned CanonicalDelta fields are projected unchanged into
gate decisions, baseline-debt-delta items, review-comment JSON, LSP diagnostic
data, agent seam packets, gap-record packets, and agent briefs when the
canonical PR delta artifact is available. Consumers match only by the exact
canonical_gap_id; they do not derive attribution from paths, line numbers,
classes, or prose. The projected fields are delta_attribution, base_state,
head_state, attribution_basis, and comparison_confidence.
Root-aware envelopes may also include causal_comparison, which discloses the
artifact coverage counts, complete, and low_coverage_disclosed. A missing
artifact leaves the optional projection absent. A malformed or unsupported
artifact is reported as unavailable and never converted into a causal result.
In particular, comparison_unknown and incomplete coverage remain visible but
cannot be promoted by a renderer into PR-caused debt.
Canonical PR Check Artifact
cargo xtask ripr-pr also preserves the parsed producer output at
target/ripr/pr/check.json. This is the canonical typed analysis envelope for
downstream PR projections; it is not the derived PR-evidence summary packet.
The artifact retains the producer's schema_version, tool, mode, root,
base, summary, findings, and analysis_outcome fields. A new PR-evidence
run removes a stale copy before invoking the producer, so a failed or timed-out
run cannot leave a previous passing outcome for generated CI to consume.
Pull-request workflows pass this artifact to ripr-review-comments --check-output target/ripr/pr/check.json for both rendering and contract
validation. Missing or malformed output remains an unavailable/error state;
generated CI does not infer a complete result from the derived
target/ripr/pr/repo-exposure.json packet.
PR Evidence Summary
cargo xtask ripr-pr-summary writes two sibling files after the legacy
pr-summary.md:
target/ripr/reports/pr-evidence-summary.json
target/ripr/reports/pr-evidence-summary.md
The JSON file carries a versioned, machine-readable evidence summary
derived from the other report artifacts already present in
target/ripr/reports/. Failure to load any artifact is fail-closed:
the affected field is set to "not_available" or null.
Pass --baseline <before.json> (a previous pr-evidence-summary.json)
to unlock delta counts. Without a baseline, delta fields are null
with an explanatory gap_delta_note (honest-baseline rule: never fake
zeros).
JSON shape (schema version 0.1):
{
"schema_version": "0.1",
"kind": "pr_evidence_summary",
"tool": "ripr",
"run_status": "diff_complete_full_repo_limited",
"analysis_complete": null,
"analysis_outcome": null,
"changed_surfaces": 3,
"gaps": {
"total_actionable": 2,
"total_static_limitation": 1,
"new_actionable": null,
"resolved": null,
"regressed": null,
"gap_delta_note": "no baseline snapshot provided; pass --baseline <before.json> for delta counts"
},
"limitations": [
{
"category": "repo_seam_limit_applied",
"repair_route": "Set RIPR_REPO_EXPOSURE_SEAM_LIMIT=0 to analyze all seams."
}
],
"missing_receipts": 2,
"receipt_status": {
"receipts_present": 1,
"missing_receipts": 2,
"orphan_receipts": "not_available",
"stale_receipts": "not_available",
"gap_mismatch_receipts": "not_available",
"verify_failed_receipts": "not_available"
},
"top_repair": {
"canonical_gap_id": "gap:src/lib.rs:error_path:c1a03250",
"language": "rust",
"repair_kind": "AddTest",
"target": "src/lib.rs",
"verify_command": "cargo test -p ripr error_path",
"receipt_command": "cargo xtask receipts",
"receipt_state": "receipt_missing"
},
"top_limitation": {
"category": "repo_seam_limit_applied",
"repair_route": "Set RIPR_REPO_EXPOSURE_SEAM_LIMIT=0 to analyze all seams.",
"why_not_actionable": "Seam inventory was capped; not all seams were analyzed in this run."
},
"local_reproduction_commands": [
"ripr check --base origin/main",
"ripr first-pr --root . --base origin/main --head HEAD",
"cargo test -p ripr error_path"
]
}
When top_repair is absent, top_repair_state appears in its place
and top_repair is null. When limitations is empty, top_limitation
is omitted entirely. When delta fields are computed (baseline supplied),
gap_delta_note is absent.
Field sources:
| Field | Source artifact | Path |
|---|---|---|
run_status | diff-report | run_status; unknown when diff evidence is missing, because repo-exposure status cannot establish diff-analysis completeness |
analysis_complete | diff-report | analysis_outcome.analysis_complete; null when the typed envelope is absent. A false value forces summary run_status to incomplete. |
analysis_outcome | diff-report | analysis_outcome; preserves typed kind, limitations, and recovery routes without reconstructing them from empty findings. |
changed_surfaces | diff-report | summary.changed_files |
gaps.total_actionable | gap-decision-ledger | summary.repairable_total |
gaps.total_static_limitation | gap-decision-ledger | summary.static_limitation_total |
gaps.* delta fields | computed from --baseline | before/after gaps.total_actionable |
limitations[] | repo-exposure | limitations[] |
missing_receipts | gap-decision-ledger | summary.repairable_total - receipt_improved_total |
receipt_status.receipts_present | gap-decision-ledger | summary.receipt_improved_total + summary.receipt_unchanged_after_attempt_total |
receipt_status.missing_receipts | gap-decision-ledger | mirrors top-level missing_receipts |
receipt_status.orphan_receipts | not yet derivable | "not_available" until receipts/ dir sweep added to ledger |
receipt_status.stale_receipts | not yet derivable | "not_available" until the real staleness signal (swarm_ingest.staleness_status) is wired into the gap-ledger build |
receipt_status.gap_mismatch_receipts | not yet derivable | "not_available" until each receipt's own canonical_gap_id is read and compared |
receipt_status.verify_failed_receipts | attempt-ledger attempts[].verify_result ∈ {"fail","failed","error"} | "not_available" when swarm-attempt-ledger.json is absent; integer count (incl. 0) when present (RIPR-SPEC-0057, PR7 of #1123) |
top_repair | start-here | selected (when state == "top_gap") |
top_repair_state | start-here | selected.state (when not "top_gap") |
top_limitation | first entry in limitations[] | derived |
local_reproduction_commands | diff-report + start-here | base/head + selected.verify_command |
The receipt_status object is additive — existing consumers reading missing_receipts
at the top level continue to work unchanged (schema_version stays "0.1"; additive
fields do not require a version bump per the stability rules above).
verify_failed_receipts is now derivable (PR7 of #1123): when
target/ripr/reports/swarm-attempt-ledger.json is present, it is counted
from attempts[].verify_result ∈ {"fail", "failed", "error"}, which flows
from the real swarm_ingest verify pipeline (verify.status/exit_code).
When the artifact is absent the field stays "not_available" (honest-absent
rule: absence is not zero). A 0 is now honest because a failed entry would
have been counted (validated by
verify_failed_receipts_nonzero_when_attempt_ledger_has_real_failure).
The three remaining "not_available" fields (orphan_receipts,
stale_receipts, gap_mismatch_receipts) honestly signal "this signal is
not yet computed" rather than claiming zero: emitting 0 would falsely assert
we checked and found none. The staleness signal lives in swarm_ingest
(staleness_status), which the gap-decision-ledger build path does not consume;
until a real producer is wired in, surfacing a 0 would be a fabricated count
that no real condition can produce (see #1130 adversarial review).
Spec: docs/specs/RIPR-SPEC-0075-pr-evidence-summary.md.
Targeted rerun output
ripr rerun --changed-test <path>[::<test_node>] [--before <path>] --json and
ripr rerun --gap <canonical-gap-id> --gap-ledger <path> [--before <path>] --json emit the
targeted-rerun receipt shape:
{
"schema_version": "ripr-targeted-rerun-v1",
"state": "current_state_only",
"selector": {
"kind": "changed_test",
"changed_test": "tests/pricing.rs::discounted_total_case",
"selected_test_count": 1,
"direct_call_names": ["discounted_total"]
},
"cache": {
"schema_version": "0.1",
"reuse_state": "reused_file_facts",
"file_fact_status": "hits_2_misses_0_corrupt_0_store_errors_0",
"hits": 2,
"misses": 0,
"corrupt_ignored": 0,
"stores": 0,
"store_errors": 0,
"recomputation_reasons": ["selected_test_scope_recomputed"],
"invalidation_status": "not_available",
"input_fingerprint": {
"schema_version": "0.3",
"analyzer_version": "0.10.0",
"workspace_root_hash": "…",
"files_content_hash": "…",
"cfg_features_hash": "…",
"config_hash": "…",
"test_intent_hash": "…",
"suppressions_hash": "…",
"workspace_manifests_hash": "…",
"lockfile_hash": "…",
"toolchain_hash": "…",
"seam_limit_key": "limit_10000",
"selector_ledger_hash": "not_applicable",
"graph_provenance": {
"package_graph_status": "complete",
"package_graph_hash": "…",
"package_graph_detail": null,
"feature_graph_status": "complete",
"feature_graph_hash": "…",
"feature_graph_detail": null,
"external_dependency_graph_status": "unavailable",
"external_dependency_graph_detail": "external dependency metadata is not resolved; no network access was used",
"path_dependency_graph": {
"status": "complete",
"detail": null,
"edge_count": 2,
"connected_edge_count": 2,
"adjacency": {
"crates/app/Cargo.toml": {
"forward": ["crates/shared/Cargo.toml"],
"reverse": []
},
"crates/shared/Cargo.toml": {
"forward": [],
"reverse": ["crates/app/Cargo.toml"]
}
}
}
}
}
},
"seams": [
{
"canonical_gap_id": "gap:4b5fdc1a2a157b0d",
"seam_id": "67fc764ba37d77bd",
"file": "src/lib.rs",
"line": 2,
"owner": "src/lib.rs::discounted_total",
"static_class": "weakly_gripped",
"repair_route_readiness": {
"state": "ready",
"seam_id": "67fc764ba37d77bd",
"canonical_gap_id": "gap:4b5fdc1a2a157b0d",
"required_evidence": [
"producer-owned missing discriminator fact: amount >= discount_threshold",
"safe test target"
],
"present_evidence": [
"producer-owned missing discriminator fact: amount >= discount_threshold",
"safe test target"
],
"missing_evidence": [],
"target_selection": {
"proposed": {
"kind": "integration",
"file": "tests/example.rs",
"owner": "pricing::discounted_total",
"provenance": "producer_owned"
}
},
"test_target": null,
"proposed_oracle": "ExactValue",
"current_oracle": null,
"authority_boundary": "analysis/producer-owned-repair-route-readiness"
},
"related_tests": [],
"missing_discriminators": []
}
],
"authority_boundary": "static evidence only; no before snapshot was supplied, so gap movement is not inferred"
}
For a changed-test selector, selector.kind is changed_test. changed_test
names the repository-relative parsed test file and may append
::<test_node> to select one test function within that file. An unknown or
ambiguous node is a named limitation. Without a node, all parsed tests in the
file participate. The report returns only seams owned by uniquely resolved
functions directly called from the selected test scope.
For a gap selector, selector.kind is canonical_gap, with
canonical_gap_id and gap_ledger. RIPR resolves every existing ledger record
with that domain-supplied canonical ID: one canonical gap may legitimately have
several seam records. matched_record_count names that group and
recomputed_scope_count names its stable-deduplicated file/owner scopes.
RIPR recomputes each scope, returns only current seams carrying the requested
canonical ID, and deduplicates them by seam_id.
The optional route stable-deduplicates existing verify_commands across the
matching records. It emits a singular receipt_command only when exactly one
distinct non-empty command exists; otherwise that field is explicit JSON
null. Multiple commands keep the rerun evidence and emit
route.receipt_command_conflict rather than choosing one arbitrarily. Neither
command is manufactured.
When the matching ledger records carry producer-owned typed command_specs,
the route also carries verify_command_specs (a JSON array of full
CommandSpec objects) beside the legacy verify_commands strings, and
receipt_command_spec (a single CommandSpec object) beside
receipt_command. The typed specs are deduplicated by their semantic digest
(sha256 over the serialized spec), so distinct invocations that reuse one
command id all survive in first-occurrence order. receipt_command_spec is
present only when the legacy string side also agrees on exactly one receipt
route: records without command_specs keep the route legacy-string-only, and
a conflicting legacy receipt set emits receipt_command_conflict and omits
the typed receipt instead of keeping a machine route across the conflict.
The rendered Markdown names each typed route with its execution mode, for
example Verify (typed, direct): ....
Anchorless or no-longer-current records appear in scope_limitations with their
matching-record index and do not hide other current scopes. The overall result
is limited only when no current scope resolves. Missing, root-mismatched, or
otherwise unresolved selectors emit state: "limited", an empty seams array,
and a named limitation such as canonical_gap_unresolved or
stale_gap_ledger. They never fall back to an unrelated workspace scan.
Both selectors reuse valid file facts but recompute the selected evidence. A
canonical_gap_id is domain-supplied and nullable; it is never derived from a
file, line, expression, or test navigation. Without --before, the command
reports state: "current_state_only", does not infer movement, and does not
discover an ambient report as before state.
With one explicit compatible prior targeted-rerun or repo-exposure snapshot, it adds:
"movement": {
"state": "closed | improved | unchanged | regressed",
"before": "target/ripr/previous-rerun.json",
"before_seam_count": 1,
"matched_seam_count": 1
}
The report state is the same closed-vocabulary movement value. Every current
selected seam_id must exist in the explicit before artifact. A missing,
malformed, unsupported, or non-overlapping before artifact returns
state: "limited" with before_artifact_unavailable or
before_artifact_incompatible; it never guesses movement. This remains static
evidence only and does not execute tests or mutations. Test-node, detailed
invalidation-reason, full-pipeline parity, and benchmark receipt surfaces remain
specified by RIPR-SPEC-0123.
cache.schema_version names the file-fact cache codec contract and
cache.reuse_state is one of reused_file_facts, mixed_file_fact_reuse,
recomputed_file_facts, or not_run. recomputation_reasons names the
selected scope, observed corrupt-entry/store-error fallbacks, and owned
content invalidations that caused this command to rebuild facts.
invalidation_status: "file_content_changed" is emitted only when a prior
same-path file-fact envelope is found under a different content key.
Every targeted receipt also carries cache.input_fingerprint, an owned hash
summary for the analyzer/cache schema, analyzer version, workspace root, Rust
file set, RIPR_CFG_FEATURES when supplied, RIPR config, test intent,
suppressions, workspace manifests, lockfile, toolchain selector, and seam
limit. For a --gap selector it also fingerprints the explicit ledger bytes;
changed ledger content is named input_changed:selector_ledger_hash. For a
changed-test selector the field is not_applicable. When an explicit
--before receipt carries the same fingerprint shape, changed components are
added to cache.recomputation_reasons as input_changed:<field> and the
receipt uses invalidation_status: "workspace_input_changed". This comparison
is never inferred from an ambient cache or report. Cold runs and before
artifacts without fingerprints remain not_available; a miss remains an
observed cache result, not a fabricated claim about which workspace input
changed.
input_fingerprint.graph_provenance records local package/member and feature
facts with complete, limited, or unavailable statuses. External
dependency metadata is explicitly unavailable because targeted rerun does not
use network or ambient Cargo metadata. Graph changes are named as
input_changed:package_graph_provenance or
input_changed:feature_graph_provenance or
input_changed:external_dependency_graph_provenance; parity fails closed when
required local graph provenance is unavailable.
input_fingerprint.graph_provenance.path_dependency_graph discloses the
forward/reverse path-dependency adjacency built in memory from the
path-dependency edges captured from local Cargo manifests (#2969). status
is complete, limited, or unavailable: limited means edge capture
reported limitations, so the adjacency covers a partial edge inventory;
complete with an empty adjacency means no path dependencies were declared
in the scanned manifests, not an omitted analysis; unavailable means no
manifest was found. edge_count names the captured edges and
connected_edge_count the subset carrying a resolved repo-relative identity;
edges without one (absolute paths, unresolved workspace inheritance, invalid
declarations) never participate, and the remainder is named in detail.
adjacency maps every participating repo-relative manifest to sorted
forward (the manifests it declares path dependencies on) and reverse
(the manifests that declare a path dependency on it) neighbor lists; crates
with no path-dependency edges are absent because they are isolated from the
path-dependency graph. The adjacency is derived without network access or
filesystem walking of dependencies; external dependency status stays
unavailable. The section is disclosure only in this slice: it does not yet
contribute to input_changed naming or parity input mismatches, because
workspace scope expansion does not consume the graph yet (#2970). Before
artifacts written before this section existed deserialize with an empty
default whose empty status is never read as a recorded graph fact.
Pass --check-parity to request an explicit full-inventory comparison. The
optional parity object reports matched only when the targeted and expected
full selector-scoped seam sets are identical and every shared seam has the
same canonical gap ID, seam ID, static class, file, owner, related-test
evidence, and missing-discriminator evidence. It records
missing_from_targeted, unexpected_in_targeted, and differing details;
a difference changes the overall report to limited with
full_pipeline_parity_mismatch; it is never rendered as a successful targeted
result. parity.mismatches[] retains a unified actionable view of those
differences rather than an unexplained count. This also includes
parity.input_mismatches[] when the targeted and full pipeline
workspace fingerprints differ; that condition is named
full_pipeline_parity_input_mismatch and fails closed.
Targeted seam entries carry repair_route_readiness unchanged from the
analysis authority. It records the readiness state, canonical identity,
required/present/missing evidence, target selection (existing, explicit
proposed, or missing), current/proposed oracle, and authority boundary; the
rerun renderer does not reconstruct those facts. A ready route must carry an
existing or explicit proposed target. already_gripped and policy_excluded
are terminal non-repair states; unresolved producer facts are
static_limitation.
diagnostic is opt-in because it intentionally runs the broad pipeline and is
not an interactive default. If the full inventory is capped, the report
instead uses full_pipeline_parity_incomplete because an absent seam may
simply lie outside the analyzed prefix.
Each targeted seam carries the producer-owned related_tests and
missing_discriminators arrays used by the parity comparison. These are static
evidence summaries; they do not claim runtime mutation behavior, correctness,
coverage adequacy, or complete test quality. Verify and receipt commands remain
the explicit route supplied by the selected ledger records; the rerun does not
manufacture commands from seam placement.
For a --gap receipt, the ledger may carry an explicit nullable seam_id
beside its behavioral canonical_gap_id. RIPR uses that typed producer-owned
identity only to retain the selected source seam when it becomes strongly
gripped and no longer produces a current canonical gap. Generic evidence_ids
remain generic references and are never interpreted by position as seam IDs.
When static evidence changes between incomparable same-rank classes, movement
is limited with movement_indeterminate rather than being mislabeled as an
incompatible before artifact.
Targeted rerun benchmark receipt
cargo xtask targeted-rerun-benchmark --root <path> --changed-test <path>
writes target/ripr/reports/targeted-rerun-benchmark.{json,md}. The JSON
schema is ripr-targeted-rerun-benchmark-v1 and records the named root,
changed-test selector, revision, analyzer version, runner class, sample count,
exact command templates, cold full/cold targeted/warm targeted timing series,
an explicit file-fact cache-reset invalidation series, and a separate parity
result. The report is scoped to the named repository, revision, configuration,
and runner; it does not claim universal latency, runtime mutation behavior,
correctness, coverage adequacy, or complete broader-input invalidation.
status: "pass" requires matched parity, successful samples, warm targeted
p50 no greater than 30 seconds, and a cold-full-to-warm-targeted p50 speedup of
at least 5x. Otherwise the receipt remains inconclusive and preserves the
measured values.
Python Eval Sweep Accepted Receipt
cargo xtask eval-sweep report --candidate <receipt.json> --accept
(RIPR-SPEC-0086, after the candidate passes the exact eval-sweep check
validation) writes the accepted receipt to
<state-dir>/receipts/<receipt-sha256>.json, content-addressed over the exact
written bytes. The envelope has schema_version: "0.1", the kind
python_eval_sweep_accepted_receipt, the spec and support tier, the
command-contract version, and the retained candidate binding (candidate kind
and schema version, candidate receipt sha256, manifest sha256).
Every count is emitted as {numerator, denominator} with the denominator its
contract defines — selection over the manifest subject denominator, top-level
counts and outcomes and distribution buckets over the selected rows, health
tallies over the selected rows they tally, and the runtime count over the
analyzed (run) rows. There are no bare rates and no denominator-free numbers.
Blocks: counts, outcomes, runtime_envelope (a reliable envelope, or a
typed unavailable with its reason), stability (compared and stable counts
with per-subject mismatch reasons), distributions (classification,
alignment, and a named disclosure in place of a limitation taxonomy that no
schema-0.3 row produces), health (detection and corpus-selection tallies
including the unrecorded share), per-subject rows with identity, evidence
digests, and recorded dispositions, identities (the currentness-bound
identity projection), incomplete_disclosures (copied from the candidate),
non_claims, and claim_boundary.
Non-claims are embedded in the artifact itself: no judged accuracy
(robustness and distribution metrics are informational and never become judged
accuracy), no repair-correctness claim, no support-tier change, no
outcome-flip claim, no coverage claim beyond the retained eight-subject
denominator, and no durable currentness claim — currentness is established
only by eval-sweep report --check-currentness at consumption time. Accepted
bytes reach their final path through a staged atomic write (staging file,
flush, rename). A file under a digest address whose bytes do not hash to that
address is not a valid prior artifact: re-acceptance republishes the
digest-named bytes (repair). The Markdown copy is named by the receipt's
digest rather than a digest of its own bytes, so it is not self-verifying: an
existing copy with different bytes is a typed refusal, never a silent repair.
Python Eval Sweep Current Pointer
Acceptance also writes <state-dir>/current.json with schema_version: "0.1"
and the kind python_eval_sweep_current_pointer. The pointer is identity-only:
the accepted receipt's digest and portable filename, the command-contract
version, an optional bounded as_of disclosure string, the manifest digest,
the RIPR toolchain identity block (source sha, binary digest, features, build
profile), and per-subject bound identities (accepted-row digest, tree digest,
input digest, config input and profile). It carries no totals, no rates, and
no per-subject outcomes.
as_of is a disclosure, never an identity: editing it can never repair
staleness, and --check-currentness requires it, when present, to be a
non-empty bounded string but never compares its value. Currentness is a
mechanical recomputation over digest, binding, and vocabulary comparisons with
the verdicts current, stale, unverifiable, or not_run (no pointer;
never a pass); only stale exits nonzero. The pointer is replaced by atomic
staged write, so a reader sees either the old or the new pointer, never a
partial one.
Stability Rules
Output contract values are registered in policy/output_contracts.txt.
Run:
cargo xtask check-output-contracts
Additive fields are allowed within the same schema version.
Do not remove fields, rename fields, or change enum meanings without bumping the schema version.
Do not emit mutation-runtime terms such as killed or survived in static JSON.
Historical 0.11 candidate execution-scope report
cargo xtask release-scope --input <scope.json> writes:
target/ripr/reports/release-scope.json
target/ripr/reports/release-scope.md
The JSON envelope has schema_version: "0.1", kind: "release-scope", a
status of ready or reconcile_required, the captured decision, verified
source commit/path observations, a historical candidate_tree_delta, boolean checks,
reconciliation_reasons, and explicit authority_boundary and
must_not_claim fields. candidate_tree_delta.candidate_tree_constructed is
always false: this historical report verifies a candidate-only disposition but does not
construct, mutate, merge, qualify, or publish a candidate tree. Markdown is a
projection of the same normalized report and cannot strengthen a
reconcile_required result.
Source-promotion resolved-tree validation receipt
cargo xtask source-promotion validate-resolved-tree writes a deterministic,
source-trusted preconstruction receipt with schema
ripr.source_promotion_resolved_tree_validation.v1.
The top-level status is one of:
rejected— the reviewed tree is ineligible for direct-J construction;validated— every required source-governed command passed for the exact bound source parent, frozen swarm parent, reviewed tree, and sidecars.
Each required command records one state:
failed— the governed command executed and failed;not_run— execution stopped before the command and the receipt carries the reason;passed— the governed command executed successfully;unavailable— the command or its retained evidence could not be produced.
Receipt paths carry an explicit role rather than ambient authority:
os_temp_disposable_checkout— the reviewed tree was materialized in an operating-system temporary checkout and no authoritative ref points to it;source_checkout_regular_file— the bound sidecar is a non-symlink regular file beneath the exact source checkout.
This receipt proves only the named source-governed repository contracts for one exact reviewed tree. It does not construct J, qualify later product or editor surfaces, move source or swarm authority, or authorize release publication.
Source-promotion network-policy resolution receipt
cargo xtask source-promotion resolve-network-policy writes the typed
ripr.source_promotion_network_policy_resolution.v1 receipt for one exact
source/W7 preview tree. It binds the accepted P0 receipt and artifact digests,
both parent policy blobs, explicit reviewer decisions, the complete live
production-pattern inventory, the one-path policy tree delta, and a run of the
source-owned production network-policy checker.
The stable receipt names a companion
ripr.source_promotion_network_policy_checker_execution.v1 attestation. The
attestation binds the stable receipt SHA-256 to the exact checker executable,
Rust toolchain, isolated build controls, and execution-output digests. Its bytes
are environment-specific and therefore do not participate in the stable
resolution-receipt or manifest-fragment digest.
The companion ripr.source_promotion_resolution_manifest_fragment.v1 object
describes only the integrated policy/network_allowlist.txt path and binds its
resolved blob and subject tree. Its published sidecar additionally binds the
resolution receipt bytes by SHA-256 so the fragment cannot stand alone as
authority.
The receipt proves semantic network-policy resolution for the frozen parent pair. It does not create the complete resolution manifest, construct or qualify the eventual join, move a ref, or authorize release or publication.
Source-promotion control packets
The source-owned controller writes indexed JSON/Markdown packets using
ripr.source_promotion_control_packet.v1. Its typed receipts are
ripr.source_promotion_trusted_builder.v1,
ripr.source_promotion_resolved_tree_admission.v1,
ripr.source_promotion_exact_join_construction.v1, and
ripr.source_promotion_candidate_ref_publication.v1. Admission consumes the
producer-bound ripr.source_promotion_integration_index.v1 schema; construction
consumes the terminal ripr.source_promotion_tree_qualification.v1 schema.
Admission and construction final snapshots reread every indexed packet member
and typed integration receipt. Matching index-file digests alone do not make
changed member bytes current. Construction performs the complete final live
snapshot immediately before its sole commit-tree attempt.
Controller status values are built, admitted, constructed, published,
reserved_before_side_effects, and rejected. published means
machine-readable guarded-push status reported an actual update of the exact
target ref, the exact join was observed there, and every bound post-push
authority remained current. Publication additionally uses
published_but_invalidated when the exact remote candidate ref moved but a
bound input invalidated afterward or the post-push local candidate-ref
observation was unavailable, and publication_state_unknown when a push was
attempted but its final remote state could not be observed or the exact join
was observed without a machine-readable actual target-update attribution. An
exit-zero up-to-date/no-op push is not publication attribution.
Neither status grants merge or release authority.
Publication receipts report push_process_succeeded independently from
target_ref_updated; an exit-zero up-to-date/no-op push records true and false
respectively and cannot produce published. Exit-zero malformed or unparseable
porcelain records true and null, respectively, and likewise cannot produce
published. atomic_push and
expected_state_guard_passed report the guarded operation independently from
the final status: both are true for an attributed target update, null after an
attempt without attribution, and false when no push was attempted. A later
divergent remote observation may therefore produce rejected while retaining
true values for those operation facts.
Every receipt exposes numeric commit_tree_attempts, local_ref_attempts,
remote_push_attempts, and merge_command_attempts. Admission and all
pre-mutation rejection paths require zero forbidden attempts. This controller
never emits a merge command, so merge_command_attempts remains zero.
Before any construction or publication side effect, the controller exclusively
creates the requested packet directory and syncs control-attempt.json with
status reserved_before_side_effects. A complete packet indexes that journal
and writes packet-index.json last. The journal's deterministic
reconciliation_context binds the protected refs, expected ref state, and
maximum per-operation attempt counters plus the admitted or constructed
commit/tree and packet identities. A reserved directory without the index is
an incomplete attempt with unknown final Git/remote state, not a rejection or
success receipt, and must be reconciled before retry. This is a
process-interruption ordering contract, not a portable power-loss durability
claim for directory entries. Outputs equal to or beneath either Git
administration directory, a consumed packet, or an indexed-receipt sidecar
directory reject before any output path is created. This applies to rejection
packets emitted for malformed commands as well as successful parses, and path
comparison resolves filesystem aliases before testing containment.
Qualification requires exactly these ordered lane names:
editor_package_linux;editor_package_windows;rust_product;source_governance;source_survivors;trusted_product_journeys;untrusted_workspace_contract;w7_product.
Construction and publication accept only refs/heads/main as source-main
authority. Candidate-ref publication binds both source remote URLs to the exact
source repository, rereads local and remote source/W7 refs and the full indexed
construction packet before and after mutation, uses an exact expected-state
lease, requires machine-readable proof that the push actually updated the
exact target plus every post-push authority bit for published, and reconciles
the remote after every push attempt. A rejected
remote push, including one whose final remote observation already equals the
constructed join, attempts to restore only the local candidate ref behind an
exact-state guard; the controller never rolls a remote ref back. An observed
join without an actual target-update status remains unattributed and produces
publication_state_unknown, including after an exit-zero up-to-date/no-op
push.
An unavailable final remote observation immediately rolls back only the local
candidate ref behind an exact-state guard, then records every mandatory
post-push authority reread before returning publication_state_unknown;
remote state remains unknown and is never rolled back.
Source-promotion admission workflow packet
cargo xtask source-promotion run-admission-workflow writes a normalized
runner-owned disposition with schema
ripr.source_promotion_admission_workflow.v1. The complete directory is
indexed by packet-index.json using packet schema
ripr.source_promotion_admission_workflow_packet.v1; the human projection is
workflow-disposition.md.
Before producer execution, the workflow writes one exact
ripr.source_promotion_admission_request.v1 request and captures the SHA-256
of those bytes. The producer compares every requested identity and locator to
its CLI inputs before materialization, embeds the request at
evidence/requested-identity.json, and binds its digest into the disposition.
Downloaded and final verification require the original request bytes and
pre-producer digest; a packet cannot replace its request and authorize itself.
The disposition status is one of:
admitted— every exact input, source-trusted producer, required command, final reread, packet member, and mode-specific attempt invariant passed; orrejected— the packet records a terminal non-green disposition and the available reason/evidence.
The closed execution_profile values are live, positive_synthetic, and
j5_negative. Synthetic packets include a deterministic fixture_identity;
live packets bind every external sidecar to its producer repository, immutable
commit/ref, regular-file path/mode, and SHA-256. The closed operation modes are
admit_only and constructor_dry_run.
reviewed_tree_carrier_sha names the exact source-repository commit that
materializes reviewed_tree_sha; live execution requires its ordered parents
to equal source_parent_sha and w7_peeled_sha.
Synthetic profiles require reviewed_tree_carrier_sha to be not_required
and make no live carrier-materialization claim.
controller_packets.*.path names the stable location beneath the uploaded
packet, and packet-index.json recursively binds the controller receipts and
all materialized locator evidence beneath evidence/. Final verification
rejects missing, extra, corrupt, symlinked, or summary-inconsistent members.
For admitted packets it also replays the indexed validation, trusted-builder,
integration, admission, qualification, and construction receipt contracts and
derives the normalized attempt summary from those receipt bytes. Rebinding
outer indexes or summary digests cannot make semantically invalid nested
evidence admissible.
An admitted constructor final packet requires a valid indexed construction
receipt. A rejected final packet may report that receipt unavailable while
still indexing all partial construction bytes; an absent output directory does
not create placeholder evidence.
trusted_checker_identity has the closed form
source-owned-xtask@<40-character-workflow-source-SHA> and must name the same
commit as workflow_source_sha. It binds source ownership while the workflow's
internally produced trusted-builder evidence binds toolchain, lockfile,
isolated external build, and executable digest.
The normalized mutation-attempt fields are:
constructor_commit_tree_attempts;local_ref_attempts;remote_push_attempts;merge_command_attempts; andrelease_or_publication_attempts.
admit_only requires all five values to be zero. constructor_dry_run permits
at most one constructor commit-tree attempt after terminal admission, in an
isolated synthetic repository, and requires the other four values to remain
zero. Neither mode grants ref, publication, merge, qualification, or release
authority.
If a rejected constructor invocation produced no parseable construction
receipt, its constructor, local-ref, remote-push, and merge-command attempt
counts are null (unknown), not zero. Publication reachability remains a
separately proven zero because the closed harness has no publication command.
After the immutable admission packet is independently enforced,
cargo xtask source-promotion finalize-admission-workflow writes the separate
final packet for admit-only normalization or the guarded constructor dry-run.
cargo xtask source-promotion verify-admission-workflow --packet <dir> --requested-identity <file> --requested-identity-sha256 <digest> rereads the
index, nested receipt semantics, packet bytes, and original request authority
independently. cargo xtask source-promotion enforce-admission-workflow --packet <dir> --expected-status admitted fails for
rejected, missing, malformed, unsupported, not_run, unavailable, non-zero
producer exit, stale identity, failed reread, or packet/conclusion
disagreement. The immutable admission packet uploads first, is downloaded to a
fresh runner-owned path, verified, and enforced before constructor dry-run is
reachable. The available final normalized packet uploads separately, so a
terminal-red state still retains all evidence produced before the stop.