Skip to content

Ship CLI proof receipts#114

Merged
Keesan12 merged 1 commit into
mainfrom
codex/public-proof-receipts-0.3.5
Jun 10, 2026
Merged

Ship CLI proof receipts#114
Keesan12 merged 1 commit into
mainfrom
codex/public-proof-receipts-0.3.5

Conversation

@Keesan12

@Keesan12 Keesan12 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • replaces the old rounded proof-card SVG with the locked dark CLI proof receipt layout
  • adds a real governed proof receipt PNG plus sanitized Markdown/JSON examples to public docs
  • bumps the root martin-loop package to 0.3.5 and documents the release
  • tightens proof-card tests and root pack guard for the current packed surface

Validation

  • pnpm --filter @martin/cli test -- proof-card.test.ts
  • pnpm --filter @martin/cli test -- operator-commands.test.ts -t "writes a shareable receipt bundle"
  • node --test scripts/tests/readme-public-surface.test.mjs
  • pnpm public:copy-scan
  • pnpm --filter @martin/cli lint
  • pnpm --filter @martin/cli build
  • pnpm public:git-surface
  • pnpm oss:validate
  • pnpm public:smoke
  • pnpm lint
  • pnpm test
  • pnpm build
  • pnpm release:validate-local
  • pnpm release:root:guard
  • pnpm release:validate:platforms

Release

After merge, tag v0.3.5 and let the root release workflow publish martin-loop@0.3.5 through GitHub Actions trusted publishing.

Summary by CodeRabbit

  • New Features

    • Proof receipts now render as terminal-style SVG cards with enhanced metadata (budget, cost, runtime, verification details)
    • Added CLI commands runs verify --latest and share --latest for generating shareable receipt bundles (JSON, Markdown, SVG)
    • Proof cards use semantic green/red color states with dark terminal styling
  • Documentation

    • Added comprehensive proof receipt guides, examples, and visual design constraints
  • Tests

    • Added visual regression tests for proof card terminal-style rendering
  • Chores

    • Bumped package version to 0.3.5

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Release 0.3.5 introduces comprehensive proof-receipt enhancements: the CLI gathers expanded run metrics (budget, verification steps, runtime, event timeline), the data model is extended with derived verdict and context fields, and the SVG renderer is rewritten for dark terminal-style visual presentation with metrics sections and event-rail visualization. Complete test coverage validates the new fields, visual constraints, and verdict states. Documentation guides users through receipt generation and specifies design constraints.

Changes

Proof Receipt 0.3.5 Release

Layer / File(s) Summary
Version bump and release governance
package.json, docs/release/VERSION-LEDGER.md, AGENTS.md, docs/release/OSS-0.3.5-RELEASE-NOTES.md, scripts/root-release-guard.mjs
Package version bumped to 0.3.5; release ledger updated with new dist-tag and next planned version; design lock added to AGENTS.md prohibiting proof-card restyling without approval; OSS release notes document new receipt rendering and missing-evidence visibility; build governance expanded to permit new documentation files in packaged surface.
Proof card input enrichment from CLI
packages/cli/src/index.ts
proofCardInputFromLoop computes remainingBudget, overspendRatio string, verificationStepCount from event history, runMode from task configuration, human-readable runtime label, and timelineEvents array from loop event sequence.
Proof card data model interfaces
packages/cli/src/proof-card.ts
MartinProofCardInput interface extended with optional metrics: remainingBudget, overspendRatio, verificationStepCount, runMode, runtime, timelineEvents; MartinProofCard output adds derived fields proofVerdict ("VERIFIED" | "HALTED" | "FAILED" | "EVIDENCE_BOUNDARY"), taskLabel, and timelineEvents; FIELD_LABELS map extended to label new receipt fields for consistent table and SVG rendering.
Proof card building and field population
packages/cli/src/proof-card.ts
buildMartinProofCard populates fields table with new optional metrics using sanitizeOptionalText; derives proofVerdict from completeness/status/lifecycle/verifier state and receipt integrity; computes taskLabel from objective keywords; normalizes timelineEvents array for event-rail display.
SVG proof receipt rendering rewrite
packages/cli/src/proof-card.ts
renderMartinProofCardSvg substantially rewritten: introduces new layout constants and terminal-receipt title; adds "METRICS" and "RUN CONTEXT" sections populated from expanded card fields; renders "EVENT RAIL" from timelineEvents with event-name compaction; applies verdictColor(card.proofVerdict) for semantic green/red accenting; includes new helper functions for field lookup, row rendering, event display, SVG styling, value normalization (normalizeCliValue, normalizeMoneyValue, normalizeBoundaryLine), verdict color selection, text sanitization, and task-label derivation.
Proof card testing
packages/cli/tests/proof-card.test.ts, packages/cli/tests/operator-commands.test.ts
Test fixture completeInput() updated to include all new metrics; "complete evidence" test expanded to assert proof receipt title and CLI verification command in SVG; new tests validate "locked terminal" visual language (monospaced layout, no gradients/rounded corners/typography changes), correct rendering of undefined fields as "not recorded" with EVIDENCE_BOUNDARY verdict, and color/semantic differences between verified and boundary states; share command test updated to expect MARTIN LOOP :: PROOF RECEIPT title in SVG.
User documentation and examples
README.md, docs/oss/AGENT-START-HERE.md, docs/oss/AGENT-RUN-RECEIPTS.md, docs/examples/proof-receipts/*
README adds "Proof Receipts" section describing receipt generation and updates version references to 0.3.5; AGENT-START-HERE documents post-run runs verify --latest and share --latest commands, expected bundle artifacts (run-receipt.json, run-receipt.md, proof-card.svg), and handling of missing evidence as boundaries; AGENT-RUN-RECEIPTS specifies proof-card visual constraints (terminal-style dark canvas, green/red semantic coloring, no restyling without approval) and links to live example; new example documents show complete JSON and Markdown receipt structure for a governed run.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Keesan12/martin-loop#105: Modifies docs/release/VERSION-LEDGER.md to track root package version alignment (related version ledger pattern).
  • Keesan12/martin-loop#97: Updates docs/oss/AGENT-RUN-RECEIPTS.md with share bundle documentation and receipt guidance (shares receipt documentation expansion).
  • Keesan12/martin-loop#87: Adds the martin share --latest command and proof-receipt bundle generation that this PR's enhanced proof-card SVG rendering supports (foundational share feature).

Poem

🐰 A rabbit hops with glee,
Receipt cards now set free!
Terminal dark, verdicts clear,
Budget lines without fear,
Events rail in sight,
Proof receipts burning bright!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Ship CLI proof receipts' directly and concisely captures the main change: implementing and releasing the new CLI proof receipt feature, which is the primary focus across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/public-proof-receipts-0.3.5

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request upgrades MartinLoop to version 0.3.5, introducing redesigned terminal-style CLI proof receipts and SVG proof cards. The changes add detailed metrics (such as remaining budget, overspend ratio, and verification steps), run context, and an event rail to the proof cards, while updating documentation and tests to reflect these visual and structural enhancements. A review comment identifies a potential runtime TypeError in packages/cli/src/index.ts when accessing payload properties without a truthiness check, and provides a code suggestion to resolve it.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/cli/src/index.ts
Comment on lines +3014 to +3016
: loop.events
.map((event) => event.payload)
.find((payload) => typeof payload["adapterId"] === "string" || typeof payload["model"] === "string");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If loop.events contains any event with an undefined or null payload, loop.events.map(event => event.payload) will include undefined or null in the resulting array. When .find() iterates over this array, it will pass undefined or null to the callback, causing a TypeError: Cannot read properties of undefined (reading 'adapterId') when attempting to access payload['adapterId']. Adding a truthiness check for payload prevents this potential runtime crash.

Suggested change
: loop.events
.map((event) => event.payload)
.find((payload) => typeof payload["adapterId"] === "string" || typeof payload["model"] === "string");
: loop.events
.map((event) => event.payload)
.find((payload) => payload && (typeof payload["adapterId"] === "string" || typeof payload["model"] === "string"));

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/proof-card.ts (1)

87-94: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Treat missing receipt integrity as an evidence boundary.

undefined currently counts as trustworthy, and the integrity row is omitted entirely, so any caller that forgets to populate receiptIntegrityState can still get completeEvidence = true and proofVerdict = "VERIFIED". defaultChallengeProofCardInput() currently does exactly that, which means the built-in demo receipt can advertise verified proof with unknown integrity.

Suggested fix
 export function buildMartinProofCard(input: MartinProofCardInput): MartinProofCard {
+  const receiptIntegrityState = input.receiptIntegrityState ?? "unsigned";
   const generatedAt = sanitizeText(input.generatedAt);
   const evidenceBoundaryNotes =
     typeof input.evidenceBoundaryNotes === "string"
       ? sanitizeText(input.evidenceBoundaryNotes)
       : input.evidenceBoundaryNotes.map((note) => sanitizeText(note)).join("; ");
@@
-    ...(input.receiptIntegrityState
-      ? [
-          {
-            label: FIELD_LABELS.receiptIntegrityState,
-            value: sanitizeText(input.receiptIntegrityState)
-          }
-        ]
-      : []),
+    {
+      label: FIELD_LABELS.receiptIntegrityState,
+      value: sanitizeText(receiptIntegrityState)
+    },
@@
-  const trustworthyReceipt =
-    input.receiptIntegrityState === undefined || input.receiptIntegrityState === "verified";
+  const trustworthyReceipt = receiptIntegrityState === "verified";
@@
     proofVerdict: deriveProofVerdict({
       completeEvidence,
       status: input.status,
       lifecycle: input.lifecycle,
       verifierStatus: input.verifierStatus,
-      receiptIntegrityState: input.receiptIntegrityState
+      receiptIntegrityState
     }),

Also applies to: 109-139

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/proof-card.ts` around lines 87 - 94, The
receiptIntegrityState must be treated as an evidence boundary instead of being
omitted when undefined: update the code that builds the proof card rows (the
conditional around input.receiptIntegrityState that currently pushes {label:
FIELD_LABELS.receiptIntegrityState, value:
sanitizeText(input.receiptIntegrityState)}) so that the integrity row is always
included; set its value to a safe sentinel like
sanitizeText(input.receiptIntegrityState ?? "UNKNOWN" or "MISSING") (and make
the same change in the other occurrence around lines 109-139), so callers that
omit receiptIntegrityState will get an explicit "UNKNOWN"/"MISSING" row rather
than silently appearing as verified.
🧹 Nitpick comments (2)
docs/release/VERSION-LEDGER.md (1)

7-8: ⚡ Quick win

Clarify temporal language in version ledger.

Lines 7-8 use "before the 0.3.5 proof receipt release publishes" which will become stale and confusing once this branch merges and 0.3.5 is released. Version ledgers typically describe current state or use conditional language. Consider either removing the "before" clause or updating these lines post-release to reflect the live state.

📝 Suggested alternative wording
-- live npm dist-tag `latest`: `0.3.4` before the `0.3.5` proof receipt release publishes
-- live public GitHub release: `v0.3.4` before the `v0.3.5` release workflow completes
+- live npm dist-tag `latest`: `0.3.5` (updated after proof receipt release)
+- live public GitHub release: `v0.3.5` (updated after release workflow completes)

Or simply:

-- live npm dist-tag `latest`: `0.3.4` before the `0.3.5` proof receipt release publishes
-- live public GitHub release: `v0.3.4` before the `v0.3.5` release workflow completes
+- live npm dist-tag `latest`: `0.3.5`
+- live public GitHub release: `v0.3.5`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/release/VERSION-LEDGER.md` around lines 7 - 8, Update the two lines that
read "live npm dist-tag `latest`: `0.3.4` before the `0.3.5` proof receipt
release publishes" and "live public GitHub release: `v0.3.4` before the `v0.3.5`
release workflow completes" to remove the temporal "before..." wording; either
state the current state explicitly (e.g., "live npm dist-tag `latest`: `0.3.4`"
and "live public GitHub release: `v0.3.4`") or use conditional phrasing (e.g.,
"live npm dist-tag `latest`: `0.3.4` (prior to publishing v0.3.5)" / "live
public GitHub release: `v0.3.4` (prior to v0.3.5 release)"), updating the lines
containing the exact phrases "live npm dist-tag `latest`" and "live public
GitHub release: `v0.3.4`".
docs/examples/proof-receipts/live-governed-run-receipt.json (1)

15-15: ⚡ Quick win

Clarify "runtime" field semantics.

The runtime field contains model/provider information ("claude / claude-sonnet-4-6 / agent-cli:claude") rather than execution duration, which could confuse users expecting time metrics. Consider renaming this field to provider, model, or execution_context, or adding a duration-based runtime field alongside model information.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/examples/proof-receipts/live-governed-run-receipt.json` at line 15, The
"runtime" JSON field currently holds model/provider info ("claude /
claude-sonnet-4-6 / agent-cli:claude") which is misleading; update the schema
and example by renaming the "runtime" key to a clearer identifier such as
"model" or "provider" (or add an additional "execution_context" key), and if you
need to record elapsed time also add a separate duration field (e.g.,
"runtime_ms" or "duration_ms"). Modify the JSON example to replace "runtime"
with the chosen name (or include both the new model/provider key and a numeric
duration key) and update any consumers/tests/docs that reference the "runtime"
key accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/examples/proof-receipts/live-governed-run-receipt.json`:
- Around line 1-17: Replace the mismatched fields to match the proof-card
schema: rename receiptIntegrity -> receiptIntegrityState, verificationSteps ->
verificationStepCount (use a number), rollback -> rollbackStatus, and verifier
-> verifierStatus; set receiptIntegrityState to one of the allowed values
("verified" | "unsigned" | "tamper_detected") (e.g., "verified" instead of
"signed"); update verifierStatus values to the schema's expected values; add the
missing proof-card fields present in the markdown example (Objective, Status,
Lifecycle, Halt reason, Evidence boundary, Run mode) with appropriate
schema-compliant keys and values, ensure types match the schema (e.g.,
verificationStepCount as an integer) and keep existing metadata like generatedAt
and budget fields unchanged.

In `@docs/examples/proof-receipts/live-governed-run-receipt.md`:
- Line 21: The "Run mode" table row uses "not recorded" but the JSON example
uses "not-recorded" for the rollback value; update the table cell (the Run mode
/ rollback entry) to use "not-recorded" to match the JSON example and maintain
consistent formatting across examples (refer to the rollback field and the Run
mode table row in the document).

In `@packages/cli/src/index.ts`:
- Around line 3007-3009: The computed metric named overspendRatio is actually
actualUsd/maxUsd (so values <1 indicate under budget); update the logic to
either (A) rename the variable to spendRatio (e.g., spendRatio =
loop.budget.maxUsd > 0 ? `${(loop.cost.actualUsd /
loop.budget.maxUsd).toFixed(2)}x` : "unknown" and use that where you mean
"budget utilization"), or (B) keep overspendRatio but only compute/emit it when
loop.cost.actualUsd > loop.budget.maxUsd (e.g., overspendRatio =
loop.cost.actualUsd > loop.budget.maxUsd ? `${(loop.cost.actualUsd /
loop.budget.maxUsd).toFixed(2)}x` : undefined/"0x"). Apply the same change for
the second occurrence using the same symbols (remainingBudget, overspendRatio,
loop.cost.actualUsd, loop.budget.maxUsd).

---

Outside diff comments:
In `@packages/cli/src/proof-card.ts`:
- Around line 87-94: The receiptIntegrityState must be treated as an evidence
boundary instead of being omitted when undefined: update the code that builds
the proof card rows (the conditional around input.receiptIntegrityState that
currently pushes {label: FIELD_LABELS.receiptIntegrityState, value:
sanitizeText(input.receiptIntegrityState)}) so that the integrity row is always
included; set its value to a safe sentinel like
sanitizeText(input.receiptIntegrityState ?? "UNKNOWN" or "MISSING") (and make
the same change in the other occurrence around lines 109-139), so callers that
omit receiptIntegrityState will get an explicit "UNKNOWN"/"MISSING" row rather
than silently appearing as verified.

---

Nitpick comments:
In `@docs/examples/proof-receipts/live-governed-run-receipt.json`:
- Line 15: The "runtime" JSON field currently holds model/provider info ("claude
/ claude-sonnet-4-6 / agent-cli:claude") which is misleading; update the schema
and example by renaming the "runtime" key to a clearer identifier such as
"model" or "provider" (or add an additional "execution_context" key), and if you
need to record elapsed time also add a separate duration field (e.g.,
"runtime_ms" or "duration_ms"). Modify the JSON example to replace "runtime"
with the chosen name (or include both the new model/provider key and a numeric
duration key) and update any consumers/tests/docs that reference the "runtime"
key accordingly.

In `@docs/release/VERSION-LEDGER.md`:
- Around line 7-8: Update the two lines that read "live npm dist-tag `latest`:
`0.3.4` before the `0.3.5` proof receipt release publishes" and "live public
GitHub release: `v0.3.4` before the `v0.3.5` release workflow completes" to
remove the temporal "before..." wording; either state the current state
explicitly (e.g., "live npm dist-tag `latest`: `0.3.4`" and "live public GitHub
release: `v0.3.4`") or use conditional phrasing (e.g., "live npm dist-tag
`latest`: `0.3.4` (prior to publishing v0.3.5)" / "live public GitHub release:
`v0.3.4` (prior to v0.3.5 release)"), updating the lines containing the exact
phrases "live npm dist-tag `latest`" and "live public GitHub release: `v0.3.4`".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 90b8b051-61d8-4ef6-883b-0f1d9ac4f750

📥 Commits

Reviewing files that changed from the base of the PR and between 8e06760 and 5ba41f1.

⛔ Files ignored due to path filters (1)
  • docs/assets/proof-receipt-live-governed.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • AGENTS.md
  • README.md
  • docs/examples/proof-receipts/live-governed-run-receipt.json
  • docs/examples/proof-receipts/live-governed-run-receipt.md
  • docs/oss/AGENT-RUN-RECEIPTS.md
  • docs/oss/AGENT-START-HERE.md
  • docs/release/OSS-0.3.5-RELEASE-NOTES.md
  • docs/release/VERSION-LEDGER.md
  • package.json
  • packages/cli/src/index.ts
  • packages/cli/src/proof-card.ts
  • packages/cli/tests/operator-commands.test.ts
  • packages/cli/tests/proof-card.test.ts
  • scripts/root-release-guard.mjs

Comment on lines +1 to +17
{
"title": "Martin Loop Proof Receipt",
"loopId": "loop_82emkgkf",
"proofVerdict": "EVIDENCE_BOUNDARY",
"evidenceLine": "Incomplete Martin proof: missing budget, rollback, or verifier evidence.",
"verifier": "passed",
"costSpend": "$0.51",
"budget": "$3.00",
"remainingBudget": "$2.49",
"overspendRatio": "0.17x",
"attempts": "1",
"rollback": "not-recorded",
"receiptIntegrity": "signed",
"verificationSteps": "1",
"runtime": "claude / claude-sonnet-4-6 / agent-cli:claude",
"generatedAt": "2026-06-10T20:01:03.635Z"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find the JSON serialization logic for proof receipts and verify field naming

# Search for JSON receipt generation/serialization
rg -nP --type=ts -C5 'run-receipt\.json|JSON\.stringify.*proof|toJSON.*receipt'

# Search for the mapping between interface fields and output JSON
ast-grep --pattern 'receiptIntegrity'

Repository: Keesan12/martin-loop

Length of output: 787


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find the MartinProofCardInput interface (or equivalent) and its field names
rg -n --type=ts 'interface\s+MartinProofCardInput|type\s+MartinProofCardInput|MartinProofCardInput\s*<' .

# 2) Find where the receipt JSON fields are defined/serialized
rg -n --type=ts 'function\s+buildShareBundle|buildShareBundle\(|shareBundle\.receipt|receipt:\s*' packages/cli/src

# 3) Find any usage of these specific field keys in codegen/rendering
rg -n --type=ts '"receiptIntegrityState"|"verificationStepCount"|"receiptIntegrity"|"verificationSteps"|"costSpend"|"remainingBudget"' packages

# 4) Find the MD example table that the JSON might be mirroring
fd -e md -a . | head -n 200
fd -e md . | rg -n 'proof-receipts|live-governed-run-receipt|Martin'

Repository: Keesan12/martin-loop

Length of output: 1314


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show MartinProofCardInput interface
echo "---- packages/cli/src/proof-card.ts (MartinProofCardInput) ----"
sed -n '1,220p' packages/cli/src/proof-card.ts | nl -ba | sed -n '1,220p'

# Show receipt construction path (buildShareBundle) around the receipt assignment
echo
echo "---- packages/cli/src/index.ts (buildShareBundle receipt) ----"
sed -n '3080,3245p' packages/cli/src/index.ts | nl -ba

# Show CliWorkflowReceipt type / receipt shape (workflow-state.ts)
echo
echo "---- packages/cli/src/workflow-state.ts (CliWorkflowReceipt) ----"
rg -n 'type\s+CliWorkflowReceipt|interface\s+CliWorkflowReceipt|export\s+type\s+CliWorkflowReceipt|export\s+interface\s+CliWorkflowReceipt' packages/cli/src/workflow-state.ts
sed -n '1,220p' packages/cli/src/workflow-state.ts | nl -ba | sed -n '1,220p'

# Locate the MD example file for proof receipts and show the relevant table/field names
echo
echo "---- Find proof receipt docs examples ----"
fd -a docs -e md | rg -n 'proof-receipts|live-governed-run-receipt|Martin Loop Proof Receipt|Martin proof receipt' || true

# Specifically print the MD file if present
mdfile="$(fd -a docs -e md -i | rg -n 'proof-receipts|live-governed-run-receipt' | head -n 1 | cut -d: -f1 || true)"
if [ -n "${mdfile:-}" ]; then
  echo
  echo "---- $mdfile (excerpt) ----"
  sed -n '1,220p' "$mdfile" | nl -ba
fi

# Finally: inspect the specific JSON file in question
echo
echo "---- docs/examples/proof-receipts/live-governed-run-receipt.json ----"
sed -n '1,120p' docs/examples/proof-receipts/live-governed-run-receipt.json | nl -ba

Repository: Keesan12/martin-loop

Length of output: 189


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- packages/cli/src/proof-card.ts (MartinProofCardInput) ----"
cat -n packages/cli/src/proof-card.ts | sed -n '1,240p'

echo
echo "---- packages/cli/src/index.ts (buildShareBundle receipt) ----"
cat -n packages/cli/src/index.ts | sed -n '3060,3225p'

echo
echo "---- packages/cli/src/workflow-state.ts (CliWorkflowReceipt) ----"
rg -n 'CliWorkflowReceipt' packages/cli/src/workflow-state.ts
echo
# show the definition region if present
start="$(rg -n 'CliWorkflowReceipt' packages/cli/src/workflow-state.ts | head -n 1 | cut -d: -f1 | awk '{print $1}')"
if [ -n "${start:-}" ]; then
  s=$((start-40))
  if [ $s -lt 1 ]; then s=1; fi
  cat -n packages/cli/src/workflow-state.ts | sed -n "${s},$((s+220))p"
fi

echo
echo "---- docs/examples/proof-receipts (find relevant MD/JSON) ----"
fd -a docs/examples/proof-receipts -e md -e json
echo
mdfile="$(fd -a docs -e md | rg -n 'proof-receipts|live-governed-run-receipt|Martin Loop Proof Receipt' | head -n 1 | cut -d: -f1 || true)"
if [ -n "${mdfile:-}" ]; then
  echo "---- $mdfile (excerpt) ----"
  cat -n "$mdfile" | sed -n '1,260p'
fi

echo
echo "---- docs/examples/proof-receipts/live-governed-run-receipt.json ----"
cat -n docs/examples/proof-receipts/live-governed-run-receipt.json | sed -n '1,140p'

Repository: Keesan12/martin-loop

Length of output: 28217


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find and print proofCardInputFromLoop (or similarly named function)
echo "---- Search for proofCardInputFromLoop ----"
rg -n --type=ts 'proofCardInputFromLoop' packages/cli/src

func_file="$(rg -n --type=ts 'proofCardInputFromLoop' packages/cli/src | head -n1 | cut -d: -f1 || true)"
if [ -n "${func_file:-}" ]; then
  echo "---- snippet around ${func_file} ----"
  # print a reasonable region around the first match line
  match_line="$(rg -n --type=ts 'proofCardInputFromLoop' packages/cli/src | head -n1 | cut -d: -f2)"
  start=$((match_line-80)); if [ $start -lt 1 ]; then start=1; fi
  end=$((match_line+120))
  sed -n "${start},${end}p" "$func_file" | cat -n
fi

# 2) Read the JSON example in question (with line numbers)
echo
echo "---- docs/examples/proof-receipts/live-governed-run-receipt.json ----"
cat -n docs/examples/proof-receipts/live-governed-run-receipt.json | sed -n '1,200p'

# 3) Find the corresponding Markdown file/table (if it exists)
echo
echo "---- Find docs markdown references to 'Martin Loop Proof Receipt' and 'live-governed-run-receipt' ----"
rg -n --type=md 'Martin Loop Proof Receipt|live-governed-run-receipt|proof-receipts' docs || true

# If any MD file exists under docs/examples/proof-receipts, list them
echo
echo "---- List docs/examples/proof-receipts directory (if present) ----"
ls -la docs/examples/proof-receipts 2>/dev/null || true

# Print all md files under that folder (small output only)
for f in $(ls docs/examples/proof-receipts 2>/dev/null | rg '\.md$' || true); do
  echo
  echo "---- docs/examples/proof-receipts/$f (excerpt) ----"
  cat -n "docs/examples/proof-receipts/$f" | sed -n '1,240p'
done

Repository: Keesan12/martin-loop

Length of output: 11988


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --type=ts '"verificationSteps"\s*:' . || true
rg -n --hidden --type=ts '"receiptIntegrity"\s*:' . || true
rg -n --hidden --type=ts '"verifier"\s*:' . || true
rg -n --hidden --type=ts '"rollback"\s*:' . || true
rg -n --hidden --type=ts 'verificationStepCount|receiptIntegrityState' packages/cli/src || true

# also check for a renderer that flattens MartinProofCard fields into JSON-like objects
rg -n --hidden --type=ts 'render.*Proof.*json|Proof.*json|toJSON.*receipt|share-receipt|run-receipt\.json' packages/cli/src || true

Repository: Keesan12/martin-loop

Length of output: 1985


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find the ReceiptIntegrityState definition/value set
rg -n --hidden --type=ts 'ReceiptIntegrityState' . | head -n 200

# 2) Find where CLI outputs JSON for proof cards (flattened vs structured)
rg -n --hidden --type=ts 'proofVerdict|EVIDENCE_BOUNDARY|verificationSteps|receiptIntegrity"\s*:|\"receiptIntegrity\"|\"verificationSteps\"' packages/cli/src || true

# 3) Locate any renderer that produces the flat keys seen in the docs example
rg -n --hidden --type=ts 'verifier"\s*:?|rollback"\s*:?|verificationSteps|receiptIntegrity' packages/cli/src || true

# 4) Find docs example generator references (if any)
rg -n --hidden --type=md 'live-governed-run-receipt' docs || true

Repository: Keesan12/martin-loop

Length of output: 3645


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Flattened key strings as they appear in docs example JSON
rg -n --hidden --type=ts '"receiptIntegrity"\s*:|receiptIntegrity"\s*\)|receiptIntegrity'\''|\"receiptIntegrity\"' packages/cli/src || true
rg -n --hidden --type=ts '"verificationSteps"\s*:|\"verificationSteps\"' packages/cli/src || true
rg -n --hidden --type=ts '"runtime"\s*:|\"runtime\"' packages/cli/src | head -n 50 || true
rg -n --hidden --type=ts '"rollback"\s*:|\"rollback\"' packages/cli/src || true
rg -n --hidden --type=ts '"verifier"\s*:|\"verifier\"' packages/cli/src || true

# Also search for docs file generator / mapping from card.fields -> flat object
rg -n --hidden --type=ts 'fields.*reduce|getFieldValue|card\.fields|buildMartinProofCard|Proof Receipt' packages/cli/src || true

Repository: Keesan12/martin-loop

Length of output: 1617


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Fixed-string searches for the flattened keys present in docs example JSON
rg -n --hidden -F '"receiptIntegrity"' packages/cli/src || true
rg -n --hidden -F '"verificationSteps"' packages/cli/src || true
rg -n --hidden -F '"rollback"' packages/cli/src || true
rg -n --hidden -F '"verifier"' packages/cli/src || true
rg -n --hidden -F '"runtime"' packages/cli/src || true

# Also search for outputting "Martin Loop Proof Receipt" JSON
rg -n --hidden -S 'Martin Loop Proof Receipt' packages/cli/src || true
rg -n --hidden -S 'run-receipt.json' packages/cli/src || true
rg -n --hidden -S 'receiptJson|receiptMarkdown|proofCardSvg' packages/cli/src || true

# Search for docs markdown generator that might produce flat receipt JSON
rg -n --hidden -S 'renderShareReceiptMarkdown|render.*Receipt' packages/cli/src || true

Repository: Keesan12/martin-loop

Length of output: 1645


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where proofVerdict / evidenceLine are used in JSON-ish outputs
rg -n --hidden --type=ts '"proofVerdict"' packages/cli/src || true
rg -n --hidden --type=ts '"evidenceLine"' packages/cli/src || true
rg -n --hidden --type=ts 'renderMartinProofCardMarkdown|renderMartinProofCardSvg' packages/cli/src || true

# Find CLI command handlers that return JSON for proofs/cards
rg -n --hidden --type=ts 'execute.*Command|command\.format|format === "json"|outputMode' packages/cli/src || true

# Specifically check for "runs verify" / "verify" command implementations
rg -n --hidden --type=ts 'runs verify|execute.*verify|verify\b' packages/cli/src || true

# Search docs generator or tests for snapshot of this JSON
rg -n --hidden --type=ts 'live-governed-run-receipt|run-receipt\.json|proof-receipts' packages/cli/tests packages/cli/src docs || true

Repository: Keesan12/martin-loop

Length of output: 11381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for flattened doc-example keys/values across repo
rg -n --hidden -S 'verificationSteps' . || true
rg -n --hidden -S 'receiptIntegrity' . || true
rg -n --hidden -S '"signed"' . || true

# See how the doc example JSON is referenced/produced
rg -n --hidden -S 'live-governed-run-receipt\.json' . || true
rg -n --hidden -S 'live-governed-run-receipt\.md' . || true

Repository: Keesan12/martin-loop

Length of output: 6023


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- docs/oss/AGENT-RUN-RECEIPTS.md (excerpt around receiptIntegrity / example schema) ----"
rg -n 'receiptIntegrity|verificationSteps|verificationStepCount|run-receipt\.json|live-governed-run-receipt\.json' docs/oss/AGENT-RUN-RECEIPTS.md
sed -n '1,120p' docs/oss/AGENT-RUN-RECEIPTS.md | cat -n
sed -n '120,220p' docs/oss/AGENT-RUN-RECEIPTS.md | cat -n

echo
echo "---- docs/examples/proof-receipts/live-governed-run-receipt.md (whole file) ----"
cat -n docs/examples/proof-receipts/live-governed-run-receipt.md

echo
echo "---- README.md (receipt example section) ----"
sed -n '90,140p' README.md | cat -n

Repository: Keesan12/martin-loop

Length of output: 10223


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show executeRunsVerifyCommand
echo "---- executeRunsVerifyCommand (packages/cli/src/index.ts) ----"
sed -n '1840,1925p' packages/cli/src/index.ts | cat -n

echo
echo "---- executeShareCommand around JSON output (packages/cli/src/index.ts) ----"
sed -n '3060,3188p' packages/cli/src/index.ts | cat -n

echo
echo "---- executeBadgeCommand around json formatting (packages/cli/src/index.ts) ----"
sed -n '3280,3360p' packages/cli/src/index.ts | cat -n

Repository: Keesan12/martin-loop

Length of output: 13288


Fix live-governed-run-receipt.json field names/value to match the proof-card schema

  • docs/examples/proof-receipts/live-governed-run-receipt.json uses receiptIntegrity, verificationSteps, rollback, and verifier, but the proof-card input schema uses receiptIntegrityState, verificationStepCount, rollbackStatus, and verifierStatus.
  • The example sets receiptIntegrity to "signed", but ReceiptIntegrityState is only "verified" | "unsigned" | "tamper_detected".
  • The JSON example omits fields that are present in docs/examples/proof-receipts/live-governed-run-receipt.md (Objective, Status, Lifecycle, Halt reason, Evidence boundary, Run mode), so the JSON doesn’t mirror the documented proof card.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/examples/proof-receipts/live-governed-run-receipt.json` around lines 1 -
17, Replace the mismatched fields to match the proof-card schema: rename
receiptIntegrity -> receiptIntegrityState, verificationSteps ->
verificationStepCount (use a number), rollback -> rollbackStatus, and verifier
-> verifierStatus; set receiptIntegrityState to one of the allowed values
("verified" | "unsigned" | "tamper_detected") (e.g., "verified" instead of
"signed"); update verifierStatus values to the schema's expected values; add the
missing proof-card fields present in the markdown example (Objective, Status,
Lifecycle, Halt reason, Evidence boundary, Run mode) with appropriate
schema-compliant keys and values, ensure types match the schema (e.g.,
verificationStepCount as an integer) and keep existing metadata like generatedAt
and budget fields unchanged.

| Remaining budget | $2.49 |
| Overspend ratio | 0.17x |
| Verification steps | 1 |
| Run mode | not recorded |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent value format with JSON example.

Line 21 shows "not recorded" (space-separated) while the JSON example uses "not-recorded" (hyphenated) for the rollback field. Ensure consistent formatting across example formats.

🔧 Proposed fix for consistency
-| Run mode | not recorded |
+| Run mode | not-recorded |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| Run mode | not recorded |
| Run mode | not-recorded |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/examples/proof-receipts/live-governed-run-receipt.md` at line 21, The
"Run mode" table row uses "not recorded" but the JSON example uses
"not-recorded" for the rollback value; update the table cell (the Run mode /
rollback entry) to use "not-recorded" to match the JSON example and maintain
consistent formatting across examples (refer to the rollback field and the Run
mode table row in the document).

Comment thread packages/cli/src/index.ts
Comment on lines +3007 to +3009
const remainingBudget = Math.max(0, loop.budget.maxUsd - loop.cost.actualUsd);
const overspendRatio =
loop.budget.maxUsd > 0 ? `${(loop.cost.actualUsd / loop.budget.maxUsd).toFixed(2)}x` : "unknown";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Rename or recompute the new "overspend ratio" metric.

This is actualUsd / maxUsd, so in-budget runs now emit values like 0.77x. The receipt later renders that under the "Overspend ratio" label, which reads as though the run exceeded budget when it did not. Either rename the field to budget utilization/spend ratio, or only emit an overspend metric once actualUsd > maxUsd.

Also applies to: 3059-3060

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/index.ts` around lines 3007 - 3009, The computed metric
named overspendRatio is actually actualUsd/maxUsd (so values <1 indicate under
budget); update the logic to either (A) rename the variable to spendRatio (e.g.,
spendRatio = loop.budget.maxUsd > 0 ? `${(loop.cost.actualUsd /
loop.budget.maxUsd).toFixed(2)}x` : "unknown" and use that where you mean
"budget utilization"), or (B) keep overspendRatio but only compute/emit it when
loop.cost.actualUsd > loop.budget.maxUsd (e.g., overspendRatio =
loop.cost.actualUsd > loop.budget.maxUsd ? `${(loop.cost.actualUsd /
loop.budget.maxUsd).toFixed(2)}x` : undefined/"0x"). Apply the same change for
the second occurrence using the same symbols (remainingBudget, overspendRatio,
loop.cost.actualUsd, loop.budget.maxUsd).

@Keesan12 Keesan12 merged commit 2c8f6d3 into main Jun 10, 2026
1 of 2 checks passed
@Keesan12 Keesan12 deleted the codex/public-proof-receipts-0.3.5 branch June 10, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant