---
phase: 23-commune-signoff-project-root-head-sha-stamping
verified: 2026-05-19T00:00:00Z
status: passed
score: 4/4
overrides_applied: 0
---

# Phase 23: Commune & Signoff Project-Root + HEAD SHA Stamping — Verification Report

**Phase Goal:** Every commune and signoff payload records `project_root` and `HEAD` SHA so resumed agents can compute staleness and detect repo/working-tree changes since last activity.
**Verified:** 2026-05-19
**Status:** PASSED
**Re-verification:** No — initial verification

---

## Goal Achievement

### Observable Truths

| # | Truth | Status | Evidence |
|---|-------|--------|----------|
| 1 | Every commune payload includes `project_root` and `head_sha` (+ subject line) | VERIFIED | `compose_commune_event` (commune.rs:21), `compose_init_signoff_payload` (signoff.rs:22), `compose_echo_commune_payload` (echo_commune.rs:66), `compose_commune_payload` (wrapper/mod.rs:474), `process_file_drop` stamps both commune+signoff branches (mod.rs:1210). All call `stamp.event_attrs()` which emits machine/project and optionally branch/head_sha/head_subject inline. |
| 2 | Every amend-signoff context save includes the same fields | VERIFIED | `run_save` (context.rs:295), `context_save_result` (context.rs:804), `run_amend_signoff` (context.rs:729), `amend_signoff_result` (context.rs:839) — all call `crate::common::git::stamp()` and prepend `stamp.yaml_frontmatter()`. All four entry points confirmed. |
| 3 | On psyche-download/resume, fields surfaced so Self can compare stored head_sha vs current HEAD and detect drift | VERIFIED | `download_payload` (context.rs:433) parses file-head YAML frontmatter via `parse_yaml_frontmatter`, emits `<psyche-stamp{attrs}/>` when present, unconditionally emits `<current{attrs} commits_since="N" commits_unpulled="N"/>`, fires `SAME_PROJECT_DRIFT_DIRECTIVE` (locked AskUserQuestion HTML comment) on same-project drift when not suppressed. `suppress-drift` subcommand wired end-to-end (cli.rs:310, live/mod.rs:71, context.rs:872). |
| 4 | Commune/signoff still works when not in a git repo (fields gracefully omit / "not a repo") | VERIFIED | `stamp_at` (git.rs:72): `branch`/`head_sha`/`head_subject` are `Option<String>`, set to `None` on git failure/timeout. `event_attrs()` (git.rs:146-176) omits Optional fields entirely — no empty-string slots. `yaml_frontmatter()` (git.rs:185-199) same omission policy. D-11 contract enforced on all output surfaces. |

**Score:** 4/4 truths verified

---

### Required Artifacts

| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| `src/common/git.rs` | Stamp struct + stamp() + event_attrs + yaml_frontmatter + commits_since/unpulled + 500ms timeout | VERIFIED | 579 lines; all helpers present and wired; no module-level `#![allow(dead_code)]`; per-symbol allows dropped as callers landed across plans 02-04 |
| `src/common/mod.rs` | `pub(crate) mod git;` registration | VERIFIED | One-line declaration confirmed by Plan 01 verification gate |
| `src/live/commune.rs` | `compose_commune_event` + EVENT envelope, no legacy prose | VERIFIED | Lines 21-31; `COMMUNE (` absent from production code; `!out.contains("COMMUNE (")` test assertion present |
| `src/live/signoff.rs` | `compose_init_signoff_payload` with `stamp: &Stamp` second parameter | VERIFIED | Lines 22-39; stamp threaded through `run()` at line 54 |
| `src/live/context.rs` | 4-writer YAML frontmatter + parse_yaml_frontmatter + is_suppressed + SAME_PROJECT_DRIFT_DIRECTIVE + download_payload blocks + suppress_drift_result + run_suppress_drift | VERIFIED | All helpers present; download_payload wired at lines 451-533; SAME_PROJECT_DRIFT_DIRECTIVE const at line 248; suppress_drift_result at line 872 |
| `src/owl/echo_commune.rs` | `compose_echo_commune_payload` + `dispatch_commune_markers` with stamp; D-14 fallback | VERIFIED | Lines 66-79; D-14 `resolve_self_project_stamp` helper present |
| `src/live/wrapper/mod.rs` | `compose_commune_payload` stamped + `process_file_drop` threads stamp | VERIFIED | Lines 474-484 (composer); line 1210 (process_file_drop both branches) |
| `src/live/wrapper/orphan.rs` | Orphan INIT_SIGNOFF stamps via compose_init_signoff_payload | VERIFIED | Plan 02 SUMMARY confirms wired in Task 1 GREEN (ed36f19) |
| `src/cli.rs` | `LiveCommands::SuppressDrift { self_id, project }` | VERIFIED | Line 310 confirmed by grep |
| `src/live/mod.rs` | Dispatch arm for SuppressDrift | VERIFIED | Lines 71-72 confirmed by grep |
| `plugin/spt/skills/commune/SKILL.md` | Phase 23 v1.8 envelope shape section | VERIFIED | Lines 44-58; `type="commune"` example, D-11 no-repo example, cross-link to live skill |
| `plugin/spt/skills/signoff/SKILL.md` | Phase 23 v1.8 envelope shape section | VERIFIED | Lines 57-71; init_signoff with/without final commune, D-11 omission, cross-link |
| `plugin/spt/skills/live/SKILL.md` | Drift detection (Phase 23 v1.8) subsection | VERIFIED | Lines 223-258; verbatim SAME_PROJECT_DRIFT_DIRECTIVE quote, 3 option-to-action mappings, Peek NOT AVAILABLE warning, D-10 cross-project silence, suppress-drift invocation |

---

### Key Link Verification

| From | To | Via | Status | Details |
|------|----|-----|--------|---------|
| `commune.rs::run` | `git::stamp()` | direct call line 56 | WIRED | Per-fire, no caching (D-12) |
| `signoff.rs::run` | `git::stamp()` | direct call line 54 | WIRED | Per-fire |
| `echo_commune.rs::dispatch_commune_markers` | `resolve_self_project_stamp` | called in dispatch | WIRED | D-14 fallback chain present |
| `context.rs::run_save` | `stamp().yaml_frontmatter()` | lines 295-297 | WIRED | File-head YAML prepend |
| `context.rs::amend_signoff_result` | `stamp().yaml_frontmatter()` | lines 839-844 | WIRED | Per-section YAML prepend |
| `context.rs::download_payload` | `parse_yaml_frontmatter` | line 464 | WIRED | Reads stored stamp from file head |
| `context.rs::download_payload` | `<psyche-stamp/>` emission | line 469 | WIRED | `s.event_attrs()` on stored stamp |
| `context.rs::download_payload` | `<current/>` emission | lines 471-483 | WIRED | Live `git::stamp()` + `commits_since` + `commits_unpulled` |
| `context.rs::download_payload` | `SAME_PROJECT_DRIFT_DIRECTIVE` | line 497 | WIRED | Same-project drift condition (stored.project == current.project AND branch/sha/machine differ AND not suppressed) |
| `context.rs::suppress_drift_result` | `suppression_marker_path` | line 897 | WIRED | Locked `__` separator path; Plan 04 read-side uses same helper |
| `cli.rs::SuppressDrift` | `context::run_suppress_drift` | live/mod.rs:72 | WIRED | Full subcommand dispatch chain |

---

### Data-Flow Trace (Level 4)

| Artifact | Data Variable | Source | Produces Real Data | Status |
|----------|---------------|--------|-------------------|--------|
| `download_payload` | `stored: Option<Stamp>` | `parse_yaml_frontmatter(&ctx_path)` reading on-disk YAML written by `run_save`/`amend_signoff_result` | Yes — reads from actual context files on disk | FLOWING |
| `download_payload` | `current: Stamp` | `crate::common::git::stamp()` — live git subprocesses | Yes — 500ms-bounded git subprocess calls | FLOWING |
| `download_payload` | `commits_since` | `git::commits_since(sha)` → `git rev-list --count {sha}..HEAD` | Yes — real git subprocess | FLOWING |
| `download_payload` | `commits_unpulled` | `git::commits_unpulled()` → `git rev-list --count HEAD..@{upstream}` | Yes — returns 0 when no upstream (graceful) | FLOWING |
| `commune.rs::run` | `stamp: Stamp` | `git::stamp()` per fire | Yes — real git subprocess per fire, no cache | FLOWING |

---

### Behavioral Spot-Checks

| Behavior | Command | Result | Status |
|----------|---------|--------|--------|
| `src/common/git` module tests | `cargo test --lib common::git -- --test-threads=1` | 13/13 pass | PASS |
| `src/live/context` module tests | `cargo test --lib live::context -- --test-threads=1` | 60/60 pass, 1 ignored | PASS |
| Full lib suite | `cargo test --lib -- --test-threads=1` | 551/551 pass, 2 ignored | PASS |
| Release build | `cargo build --release` | Finished — 3 pre-existing dead_code warnings, zero errors | PASS |
| Legacy prose form gone | `grep` for `COMMUNE (` in production code | 0 production hits; only doc comments and test absence assertions | PASS |
| D-11 not-a-repo omission | `event_attrs()` and `yaml_frontmatter()` | Optional fields skipped via `if let Some(...)` arms | PASS |

---

### Probe Execution

No probe scripts (`scripts/*/tests/probe-*.sh`) declared or relevant for this phase.

---

### Requirements Coverage

| Requirement | Source Plan | Description | Status | Evidence |
|-------------|------------|-------------|--------|---------|
| PROJ-META-01..03 | Plan 01 | Stamp struct + machine/project derivation | SATISFIED | `src/common/git.rs` Stamp, hostname(), git_project_basename() |
| COMMIT-META-01 | Plan 01 | head_sha/branch/head_subject helpers + 500ms timeout | SATISFIED | `run_git_with_timeout`, `stamp_at` |
| COMMIT-META-02/03 | Plan 02 | EVENT envelope cutover + signoff stamping | SATISFIED | commune.rs, signoff.rs, echo_commune.rs, wrapper/mod.rs |
| ECHO-DELTA-01 | Plan 02 | echo_commune Self-project D-14 fallback | SATISFIED | `resolve_self_project_stamp` in echo_commune.rs |
| BACK-COMPAT-02 | Plan 02 | Wrapper parser ignores unknown attrs | SATISFIED | Additive attrs, case-insensitive type= match unchanged |
| YAML-META-01/02 | Plan 03 | YAML frontmatter on context-save + amend-signoff | SATISFIED | 4 writer entry points in context.rs |
| RESUME-DELTA-01..07 | Plan 04 | psyche-download stamp blocks + drift directive + suppression read | SATISFIED | download_payload, parse_yaml_frontmatter, is_suppressed, SAME_PROJECT_DRIFT_DIRECTIVE |
| BACK-COMPAT-01 | Plan 04 | Legacy files without frontmatter degrade gracefully | SATISFIED | parse_yaml_frontmatter returns None; `<current/>` still emits |
| RESUME-DELTA-05 | Plan 05 | suppress-drift write-side subcommand | SATISFIED | SuppressDrift variant, suppress_drift_result, run_suppress_drift |

---

### Anti-Patterns Found

| File | Line | Pattern | Severity | Impact |
|------|------|---------|----------|--------|
| `src/common/git.rs` | 67-70 | `pub(crate) fn stamp_at(...)` — `pub(crate)` variants retain allows for `_at` variants not yet consumed | Info | Intentional — no in-tree consumer yet; documented; Plan 04/05 explain this |
| ROADMAP.md | 408 | `- [ ] 23-06-PLAN.md` — checkbox unchecked despite plan being complete | Warning | ROADMAP housekeeping only; code and SKILL.md are confirmed shipped. git log shows 8c8a5b0 + 74e24ea. Not a code gap. |

No TBD/FIXME/XXX markers found in any Phase 23 modified files.

---

### Human Verification Required

None. All success criteria are mechanically verifiable via codebase inspection and test results. The trampoline-routing issue (Plans 03-05) correctly notes that `target/release/owl.exe` smoke tests are intercepted by the deployed binary during development; this is expected behavior and does not affect the correctness of the in-process lib tests.

---

### Gaps Summary

No gaps. All four success criteria are verified against the codebase.

**One cosmetic housekeeping item (not a gap):** ROADMAP.md line 408 still shows `[ ]` for plan 06. The commits and code are shipped (git log: 8c8a5b0, 74e24ea). The checkbox can be ticked in a follow-up commit along with the untracked PLAN.md/RESEARCH.md files that plan 06 SUMMARY noted as pre-existing untracked artifacts.

---

_Verified: 2026-05-19T00:00:00Z_
_Verifier: Claude (gsd-verifier)_
