Skip to content

feat(deliverables): git-first artifact write-path + verify endpoint#39

Merged
aimerdoux merged 2 commits into
mainfrom
feat/deliverable-git-writepath
Jun 2, 2026
Merged

feat(deliverables): git-first artifact write-path + verify endpoint#39
aimerdoux merged 2 commits into
mainfrom
feat/deliverable-git-writepath

Conversation

@aimerdoux

Copy link
Copy Markdown
Owner

Summary

Closes the highest-value gap from the OSS gap analysis: writeDeliverable() existed (task #46) but had zero callers and wrote a loose JSON envelope with no verifiability. An agent could "complete" an issue with a ledger row but no inspectable output.

This PR makes every deliverable a git commit in a per-company deliverables repo, and adds a verify step — turning "the fleet ran" into "here's the commit you can inspect."

Slice 1 — verifiable write-path

  • db: commit_sha + git_ref columns on deliverables (migration 0012_deliverable_git.sql + journal entry).
  • shared: Deliverable gains commitSha/gitRef; DeliverableStatus gains verified/failed (matches the cloud deliverable_ledger vocabulary); new deliverable_verified activity event.
  • mission-control/deliverables.ts: commitArtifact() lazily git inits the deliverables dir (pinned to main), commits the artifact, returns the SHA. writeDeliverable() calls it and persists commit_sha/git_ref. Best-effort — a git failure leaves commit_sha empty and the DB row is still written (the row stays the source of truth).
  • route: POST /api/mission-control/deliverable — board-auth producer endpoint recording an agent run's output as a committed artifact.

Slice 2 — verify

  • verifyDeliverable() resolves the recorded commit (git cat-file -e <sha>^{commit}) and re-hashes the on-disk file against contentHash; sets verified/failed, stamps reviewedAt, emits deliverable_verified.
  • route: POST /api/mission-control/deliverable/:id/verify.

Boundary preserved

The write-path is local only (local git + @wavex-os/db). The Liaison's existing mirror carries commit_sha up to Supabase deliverable_ledger.artifacts — the server never writes Supabase directly, honoring "the cloud never reaches the machine."

Tests

3 new + 3 existing, all green (packages/wavex-os-server/test/mission-control-deliverables.test.ts):

  • commit resolves via git cat-file and the file is in the commit tree
  • clean artifact → verified
  • tampered on-disk artifact → failed (hash mismatch)

Verification done locally

  • tsc --noEmit on db / shared / wavex-os-server: no new errors (only pre-existing pool-b-health.ts null-checks + unbuilt vendored sdk).
  • vitest run deliverables suite: 6/6 pass; migration 0012 applies clean in the in-memory PGlite harness.

Follow-up (Slice 3, separate PR)

Auto-producer reconciler that detects completed issues carrying a wavex-artifact block + the agent-side DELIVERABLE_EMIT skill (placed in liaison-ext, since standard-skills/** is frozen).

🤖 Generated with Claude Code

aimerdoux and others added 2 commits May 28, 2026 10:29
Closes the gap where writeDeliverable() existed but (a) had zero callers
and (b) wrote a loose JSON envelope with no verifiability. Now every
deliverable is committed to a per-company git repo, so "the fleet ran"
becomes "here is the commit you can inspect."

Slice 1 — verifiable write-path:
- db: add commit_sha + git_ref columns to deliverables (migration 0012).
- shared: Deliverable gains commitSha/gitRef; DeliverableStatus gains
  verified/failed (matches the cloud deliverable_ledger vocabulary);
  new deliverable_verified activity event.
- deliverables.ts: commitArtifact() lazily `git init`s the deliverables
  dir, commits the artifact file, returns the SHA. writeDeliverable()
  calls it and persists commit_sha/git_ref. Best-effort — a git failure
  leaves commit_sha empty and the DB row is still written.
- route: POST /api/mission-control/deliverable — board-auth producer
  endpoint that records an agent run's output as a committed artifact.

Slice 2 — verify:
- verifyDeliverable() resolves the recorded commit (git cat-file -e) AND
  re-hashes the on-disk file against contentHash; sets verified/failed,
  stamps reviewedAt, emits deliverable_verified.
- route: POST /api/mission-control/deliverable/:id/verify.

Tests: 3 new (commit resolves via git; clean → verified; tampered →
failed) alongside the 3 existing write/query tests — all 6 green.

Boundary preserved: the write-path is local only (local git + @wavex-os/db).
The Liaison's existing mirror carries commit_sha up to Supabase
deliverable_ledger.artifacts — the server never writes Supabase directly.

Follow-up (Slice 3, separate PR): auto-producer reconciler that detects
completed issues carrying a wavex-artifact block + the agent-side
DELIVERABLE_EMIT skill.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
commitSha is optional on the Deliverable shape (string | undefined);
execFileSync's args array requires string. The test asserts it matches
the hex regex just above, so `!` is safe. Fixes a tsc overload error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aimerdoux aimerdoux merged commit 7a8aa6d into main Jun 2, 2026
1 check passed
aimerdoux pushed a commit that referenced this pull request Jun 2, 2026
Slice 3 — makes the git-first write-path (PR #39) fire from completed
issues, so agents capture verifiable artifacts without a manual call.

- artifact-block.ts: parseArtifactBlock() extracts a fenced
  `wavex-artifact` block (kind/title/mime header + `---` + body) from
  issue text. Mirrors the wavex-contract block convention.
- reconcile-deliverables.ts:
  - reconcileDeliverables() — pure, testable: for each terminal-state
    issue carrying a block with no existing deliverable, calls
    writeDeliverable() (which git-commits the artifact). Idempotent;
    one deliverable per issue.
  - fetchCompletedIssuesForCompany() — defensive I/O glue: reads the
    paperclip-handoff, GETs the local Paperclip issues, flattens to
    ReconcileIssue[] (field-name fallbacks; comments appended so a
    block posted as a closing comment is still scanned). Any failure
    yields [] so a tick no-ops rather than throwing.
- route POST /api/mission-control/:companyId/reconcile-deliverables —
  board-auth trigger. Intended for the Liaison heartbeat or a cron;
  safe to call anytime.
- DELIVERABLE_EMIT.md (liaison-ext, non-frozen) — teaches agents to
  emit the block on completion. code_change/db_migration still go
  through the Git Engineer PR flow, not this block.

No always-on scheduler in this PR: the producer fetch hits the local
Paperclip issues API, which isn't verified against a live instance
here. The route makes it triggerable now; wiring it to the Liaison
heartbeat is a one-line follow-up once the issues API shape is
confirmed live.

Tests: 9 new (parse: 5, isTerminalState: 1, reconcile: 3 incl.
idempotency + git-commit assertion). All green alongside Slice 1+2's 6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aimerdoux added a commit that referenced this pull request Jun 2, 2026
…#41)

Slice 3 — makes the git-first write-path (PR #39) fire from completed
issues, so agents capture verifiable artifacts without a manual call.

- artifact-block.ts: parseArtifactBlock() extracts a fenced
  `wavex-artifact` block (kind/title/mime header + `---` + body) from
  issue text. Mirrors the wavex-contract block convention.
- reconcile-deliverables.ts:
  - reconcileDeliverables() — pure, testable: for each terminal-state
    issue carrying a block with no existing deliverable, calls
    writeDeliverable() (which git-commits the artifact). Idempotent;
    one deliverable per issue.
  - fetchCompletedIssuesForCompany() — defensive I/O glue: reads the
    paperclip-handoff, GETs the local Paperclip issues, flattens to
    ReconcileIssue[] (field-name fallbacks; comments appended so a
    block posted as a closing comment is still scanned). Any failure
    yields [] so a tick no-ops rather than throwing.
- route POST /api/mission-control/:companyId/reconcile-deliverables —
  board-auth trigger. Intended for the Liaison heartbeat or a cron;
  safe to call anytime.
- DELIVERABLE_EMIT.md (liaison-ext, non-frozen) — teaches agents to
  emit the block on completion. code_change/db_migration still go
  through the Git Engineer PR flow, not this block.

No always-on scheduler in this PR: the producer fetch hits the local
Paperclip issues API, which isn't verified against a live instance
here. The route makes it triggerable now; wiring it to the Liaison
heartbeat is a one-line follow-up once the issues API shape is
confirmed live.

Tests: 9 new (parse: 5, isTerminalState: 1, reconcile: 3 incl.
idempotency + git-commit assertion). All green alongside Slice 1+2's 6.

Co-authored-by: aimerdoux <aimerdoux94@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aimerdoux aimerdoux deleted the feat/deliverable-git-writepath branch June 2, 2026 16:19
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