Skip to content

feat(runs): record base SHA provenance - #166

Open
jungle-lethanh wants to merge 1 commit into
theam:mainfrom
jungle-lethanh:feat/base-sha-provenance
Open

feat(runs): record base SHA provenance#166
jungle-lethanh wants to merge 1 commit into
theam:mainfrom
jungle-lethanh:feat/base-sha-provenance

Conversation

@jungle-lethanh

@jungle-lethanh jungle-lethanh commented Aug 16, 2026

Copy link
Copy Markdown

This PR does not compare workspaceBaseSha with the live branch during plan acceptance and does not alter Gate 1 or /builder dispatch; it provides the durable input required for that follow-up behavior.

What changes

Records the Git base commit for repository-backed runs and deliveries.

  • Adds nullable runs.workspace_base_sha.
  • Adds nullable run_deliveries.base_sha.
  • Captures the workspace HEAD after checkpoint restoration and before agent execution.
  • Adds an authenticated runner endpoint for recording workspace provenance.
  • Makes workspace provenance immutable:
    • First write succeeds.
    • Identical retries succeed.
    • Conflicting retries return 409 workspace_base_mismatch.
  • Preserves the delivery base already calculated by shipGitChanges.
  • Adds optional github.base_sha receipt provenance.
  • Exposes workspaceBaseSha through the public Run API and generated SDK.

Workspace and delivery bases remain separate:

Field Meaning
workspaceBaseSha Commit presented to the agent
Delivery baseSha Base of the published change set
expectedHeadSha Published delivery head

For delivery receipts, github.base_sha uses the delivery base. Runs without a delivery fall back to the prepared workspace base.

Why

Facility records the resulting head commit, but not the commit from which the agent started.

A branch name such as main can remain unchanged while its commit advances. Without the original base SHA, Facility cannot reliably determine whether a run was based on the current tree, reconstruct the exact delivered range, or provide durable provenance in receipts.

The runner already calculates these commits during workspace preparation and delivery; this change persists them instead of discarding them.

This is additive and backward-compatible:

  • Existing database rows remain valid.
  • Old receipts remain valid because base_sha is optional.
  • No historical backfill is attempted.
  • Gate 1 UI and stale-base enforcement are intentionally outside this PR.

Refs #147.

Verification

Verified:

  • Workspace SHA validation and lowercase normalization
  • Authenticated first-write and idempotent replay behavior
  • Conflicting replay rejection
  • Resume over an advanced base records the restored workspace HEAD
  • Delivery base propagation and database persistence
  • Receipt fallback, legacy compatibility, and integrity hashing
  • Database migration
  • OpenAPI and generated SDK consistency
  • Relevant builds and typechecks
  • Complete runner package suite: 169 tests passed
  • SDK suite: 23 tests passed
  • Biome and git diff --check

pnpm verify is not marked as passing locally. WSL verification encountered timing-sensitive failures in unchanged runner process-deadline and assistant cleanup tests. The affected runner tests pass independently, and no provenance test failed.

  • pnpm verify passes locally
  • Behaviour verified beyond the focused suite
  • Generated API documentation is updated; no UI change

Persist the prepared workspace base and published delivery base in run records, deliveries, receipts, and the public API.

Refs theam#147
@UsamaIslam

Copy link
Copy Markdown

Nice catch on splitting workspace_base_sha from delivery base_sha — that's the right shape, since the two answer different questions (what the agent read vs. what got published). One thing I couldn't tell from the PR description: does anything compare workspace_base_sha against the live branch HEAD at plan-acceptance time (before /builder is dispatched), or does this land the data without yet wiring it into the Gate 1 approval UI? If it's just the former for now, might be worth a follow-up issue so "record" and "surface to the approver" don't silently get conflated as the same fix.

@jungle-lethanh

Copy link
Copy Markdown
Author

Good question. This PR only lands the durable provenance data.
It does not currently resolve the live branch HEAD or compare it with workspaceBaseSha during plan acceptance, and it does not change the Gate 1 UI or /builder dispatch behavior.
The intended follow-up would use the plan-producing run’s workspaceBaseSha as the recorded base, resolve the current target-branch HEAD at approval time, and surface the drift to the approver. Whether that should warn or block dispatch is a separate policy/UX decision.

I kept capture and persistence separate from Gate 1 behavior so the provenance contract can be reviewed independently. I used Refs #147 rather than closing the issue, and I’ll update the PR description to make this scope boundary more explicit. We can keep the Gate 1 work under #147 or track it in a focused follow-up issue, depending on maintainer preference.

@jungle-lethanh
jungle-lethanh marked this pull request as ready for review August 16, 2026 21:52

@adrian-lorenzo adrian-lorenzo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the solid contribution!

@jungle-lethanh

jungle-lethanh commented Aug 19, 2026

Copy link
Copy Markdown
Author

Thank you for the review and approval! I appreciate the opportunity to contribute.

Once the provenance PR lands, I’d be interested in taking the remaining Gate 1 slice.
My proposed first scope is to compare the architect run’s workspaceBaseSha with the live target-branch HEAD, then show an advisory at platform plan approval with the current SHA and the paths changed since planning. I would recheck at approval time and avoid automatically blocking dispatch in the first slice.

I would not infer overlap by parsing the plan Markdown; the UI would present deterministic changed-path evidence for the human decision.
Should this remain under #147, and would you prefer the first slice to cover only the platform approval UI, or also define behavior for GitHub /builder acceptance?

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.

3 participants