Skip to content

feat(evidence): add versioned per-record carriers - #112

Merged
m0n0x41d merged 3 commits into
devfrom
fix/issue-100-evidence-carriers
Aug 11, 2026
Merged

m0n0x41d merged 3 commits into
devfrom
fix/issue-100-evidence-carriers

Conversation

@m0n0x41d

Copy link
Copy Markdown
Owner

What

  • writes one versioned Markdown carrier per EvidenceRecord under .haft/evidence
  • imports carriers through the evidence domain path with strict identity, parent, schema, timestamp, and presentation validation
  • adds schema 59 for causal/update fields and durable projection-debt backfill
  • reports projection debt in haft check and repairs it only after pulled carriers are imported
  • prepares the 9.1.0 changelog, release note, and release-workflow default

Why

Evidence attachments were SQLite-only, so git collaboration could not transfer them and concurrent attachments had no independent carrier. This implements the bound choice in dec-20260811-2e06aae9 without changing existing CLI or MCP request fields.

Root cause and failure semantics

The semantic EvidenceRecord and the git-facing representation had no explicit projection boundary. The new domain path keeps SQLite as the runtime projection, writes carriers atomically, records durable debt after post-commit publication failure, rejects missing or changed parents, and preserves divergent git and SQLite states for explicit reconciliation.

Compatibility and impact

  • existing evidence APIs remain compatible; carrier path, warning text, and check JSON are additive
  • schema 58 to 59 is snapshot-backed and startup-safe
  • legacy evidence rows are preserved and queued for backfill by haft sync
  • downgrade to 9.0.3 requires restoring the verified schema-58 snapshot

Checks

  • full non-desktop Go suite, excluding only the separately gated consolidated P13 runner
  • go vet ./...
  • focused race tests for artifact, CLI sync/MCP evidence, and schema migration paths
  • FPF integration verify, token gate, refresh packages, and P13 manifest structure
  • darwin-arm64 CLI build

Formal exact-SHA CI/full-race, installed-runtime P14, tag validation, and GitHub Release publication remain separate gates.

Fixes #100

@m0n0x41d
m0n0x41d marked this pull request as ready for review August 11, 2026 12:39

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e59a32ceed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/cli/check.go
Comment on lines +179 to +181
report.EvidenceCarrierProjectionDebt, err = store.ListEvidenceCarrierProjectionDebt(ctx)
if err != nil {
return report, fmt.Errorf("scan evidence carrier projection debt: %w", err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard check against pre-59 project ledgers

On an existing project whose local SQLite ledger is still at schema 58, runCheck opens the DB directly and does not go through the project-ledger readiness check, so this new unconditional query of evidence_carrier_projection_debt (created only by migration 59) fails with no such table before haft check can print its normal report or a migration/repair hint. Treat a missing debt table as an empty/diagnostic-unavailable inventory, or require the current schema before building the report.

Useful? React with 👍 / 👎.

Comment on lines +293 to +294
if evidenceFormalityBridge(formalityScale) != nil && item.FormalityBridge == nil {
return EvidenceCarrier{}, fmt.Errorf("evidence %s formality_bridge is required for scale %s", item.ID, formalityScale.ScaleID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject non-canonical formality bridges

When a synced carrier declares a legacy or unversioned formality_scale, this only checks that formality_bridge is non-nil; ImportEvidenceCarrier then stores that bridge and WLNK reads item.FormalityBridge.Loss, so a hand-edited git carrier can set an arbitrary bridge/loss and silently change downstream bridge-loss diagnostics while still passing validation. Compare the supplied bridge to evidenceFormalityBridge(formalityScale) (and reject extra bridges when the canonical bridge is nil) before importing.

Useful? React with 👍 / 👎.

Comment on lines +229 to +232
if !unchanged {
item := carrier.Evidence
if err := s.addEvidenceItemWithExec(ctx, tx, &item, carrier.ArtifactRef); err != nil {
return "", fmt.Errorf("import evidence %s: %w", carrier.Evidence.ID, err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reuse evidence binding validation on import

For a pulled carrier, this goes straight to the low-level insert path, bypassing the validation in AttachEvidence that rejects claim_refs on non-decision parents and resolves/validates them against a decision's structured claims. A hand-edited .haft/evidence/*.md can therefore sync claim bindings onto a Note or reference non-existent decision claims, leaving SQLite in a state the normal evidence API would never create; import should load the parent and run the same binding validation before inserting.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@m0n0x41d
m0n0x41d merged commit a706e68 into dev Aug 11, 2026
19 checks passed
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