---
name: finish-and-verify
description: Use for the last mile of a slice or task. Rerun verification, inspect the diff, persist evidence, optionally commit/push. The slice-done gate that prevents premature completion claims.
---

# Finish And Verify

## Purpose

The closing gate for a slice or task. Stops "looks green to me" from becoming "marked complete" without fresh verification, without consumer-path proof, and without recorded evidence.

Use this skill to:

- Rerun final verification (typecheck, tests, lint).
- Inspect the actual diff before declaring done.
- Persist evidence to the unit artefacts (`.sf/active/{unit-id}/`).
- Commit / push when the user asks.

This skill does NOT decide whether a slice is shippable in isolation — that's `validate-milestone` or `complete-slice`. This skill ensures the artefact is honest before those gates run.

## When to Run

- After `spec-first-tdd` reaches GREEN on the contract test.
- After a debugging fix from `systematic-debugging`.
- Before calling `complete_task` or `complete_slice`.
- Inside an autonomous iteration loop, between slices.

If used inside an autonomous iteration loop and the user goal is still in progress:

1. Verify the current slice.
2. Record evidence.
3. Refresh `.sf/active/{unit-id}/active-slice.md` if one exists.
4. **Return control to the loop. Do not stop just because the slice is green.**

## Self-Awareness — Why this skill exists

You are an LLM-driven agent, and you are bad at verification. This is documented and persistent:

- You read code and write "looks good" instead of running it.
- You see the first 80% — a polished diff, a test name that matches the contract — and feel inclined to declare done. The first 80% is the easy part. Your value is the last 20%.
- You trust your own self-reports. "Tests pass." Did *you* run them, just now, after the last edit?
- You hedge when uncertain instead of deciding. "Probably fine" is not a verification result.

Knowing this, your job in this skill is to catch yourself doing those things and do the opposite.

## Recognize Your Own Rationalizations

You will feel the urge to skip checks. These are the exact excuses you reach for — recognize them and invert each:

- "The code looks correct based on my reading." → Reading is not verification. Run it.
- "The implementer's tests already pass." → The implementer is also an LLM. Verify independently — re-run, and read what each test actually asserts.
- "This is probably fine." → Probably is not verified. Run it.
- "Let me start the server and check the code." → No. Start the server and hit the endpoint.
- "This would take too long to actually exercise." → Not your call. The unit is not done until exercised.
- "The diff is small, so the risk is small." → Small diffs ship the most subtle regressions. Run the same checks regardless of diff size.

If you catch yourself writing an explanation in place of a command — stop. Run the command, paste the output, then write the explanation.

## Slice Done Gate

Do not declare a slice done until **all** are true:

- [ ] Contract test is green — and you ran it now, not 5 minutes ago.
- [ ] Required component verification is green (`npm run typecheck:extensions`, `npm test`, lint clean for touched files).
- [ ] Consumer-path check is explicit: `rg` confirms a real caller still depends on the changed symbol.
- [ ] **At least one adversarial probe was run.** Pick whichever fits the change: boundary value (0, -1, empty, very long, unicode), idempotency (apply twice — duplicate? error? correct no-op?), concurrency (parallel callers on a create-if-not-exists path), orphan reference (input ID that doesn't exist). Document the result even when "handled correctly" — a green run with no probe is happy-path confirmation, not verification.
- [ ] Active-slice artefact (`.sf/active/{unit-id}/active-slice.md` or equivalent) is updated with current state.
- [ ] Falsifier from the plan was either checked or admitted as residual risk.
- [ ] No slice-local next step remains undocumented.

If any item fails: do not mark done. Either fix the gap or capture it as a follow-up unit.

## Final Verification Matrix

```bash
# State
git status --short
git diff --stat
git diff                                        # actually look at it

# Compile + check
npm run build:core
npm run typecheck:extensions

# Test
npm run test:unit                               # full unit suite
npm run test:integration                        # integration if relevant

# Lint (when configured)
npx eslint <touched-files>
```

For changes in `packages/<pkg>/`:

```bash
cd packages/<pkg> && npx tsc --noEmit
```

For native (Rust) changes:

```bash
npm run build:native
ldd rust-engine/npm/linux-x64-gnu/forge_engine.node | grep -E "not found" || echo "OK"
```

## Git Workflow

Stage only task-relevant files in a dirty worktree. Never `git add -A` blindly.

```bash
git add path/to/changed-file.ts path/to/changed-file.test.ts
git commit -m "type(scope): short description"
```

Commit message: Conventional Commits format (`feat:`, `fix:`, `refactor:`, etc.) — required by the commit-msg hook in this repo. Reference the unit/issue when relevant.

Push only on explicit user request:

```bash
git push origin HEAD
```

Never `--force` to a shared branch unless the user specifically asks.

## Evidence to Persist

Before declaring done, capture in `.sf/active/{unit-id}/`:

- The failing test that motivated the change (test name + commit SHA before fix).
- The passing test result (test name + commit SHA after fix).
- Lint result.
- Build result when relevant.
- The consumer path (one line: "called by `<file>:<symbol>`").
- The value at risk (one line: "if wrong, `<consequence>`").

For non-trivial slices:

```markdown
## Evidence Markers

- **Observed**: <facts from runtime/test output>
- **Inferred**: <intended contract these facts support>
- **Proposed**: <change applied>
- **Confidence**: <0.0–1.0> — <one-line reason>
- **Falsifier**: <observable condition that would prove this wrong>
- **Reflection**: <weakest assumption, next verification step>
```

For runtime/provider/transport changes, also capture explicit before/after repro evidence — traces alone are insufficient when boundary behaviour changed.

### Trace Format for Verification Evidence

Every claimed PASS in the slice artefact must be backed by a trace of this shape — paraphrase is not evidence:

```
### Check: <what was verified>
**Command run:** <exact command, copy-pasteable>
**Output observed:** <actual stdout/stderr — copy-paste, not paraphrase; truncate long output but keep the relevant part>
**Result: PASS** (or FAIL — with Expected vs Actual)
```

Rejected (do not use):

```
### Check: typecheck
**Result: PASS**
Evidence: I reviewed the touched files and the types look consistent.
```

(No command run. Reading types is not running tsc.)

A check without a `Command run` block is not a PASS — it's a skip.

## Rules

- Do not claim completion without fresh verification — even if you ran tests 5 minutes ago, run them again after the last edit.
- Do not claim deployment success from a `docker-compose up` or `npm run build` alone — verify a real consumer path executes.
- Stage only task-relevant files in a dirty worktree.
- Never bypass the commit-msg hook (`--no-verify`) without explicit user authorisation.
- Never `--force-push` to a shared branch without authorisation.
- If verification fails, do not mark done — either fix it or escalate via `systematic-debugging`.
