Skip to content
Back to skills

Stamp Protocol

ASecurity

Use when stamping a plan, prompt, or snapshot - Authored-against format, derivation commands, never-type rule.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
toolsrustgoshellbashgit

Works with

  • terminal

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add thrum-team/thrum-pro --skill stamp-protocol --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Stamp Protocol?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Stamp Protocol
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/thrum-team-stamp-protocol/badge)](https://www.skillsdirectory.com/skills/thrum-team-stamp-protocol)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: stamp-protocol
description: "Use when stamping a plan, prompt, or snapshot - Authored-against format, derivation commands, never-type rule."
---


# Authored-Against Stamp Protocol
This is the canonical source-of-truth for the Authored-against stamp: its format,
derivation commands, and the never-type rule. Consuming files point here instead of
restating the recipe. Do not run this as a command; it has no terminal action — other skills and commands load it by name.
(To find what currently points here: `grep -rn "thrum:stamp-protocol" claude-plugin/commands/ claude-plugin/skills/`
— a hand-listed consumer roster in this file would rot the moment a new emitter or
reader is added, so none is kept here.)

## Purpose

A date alone cannot tell a reader whether the tree moved since an artifact was
authored. The Authored-against stamp embeds the exact commit SHA the author was
looking at and the configured merge target at authoring time. A reader can later
run the stamped diff command to detect whether any cited file has changed —
converting a qualitative suspicion ("is this stale?") into a falsifiable check.

## Stamp format (emitted artifact — verbatim)

Place these two lines at the appropriate location in the artifact (immediately
after its own date/frontmatter for brainstorm/plan/prompt; immediately after the
`Last updated` line for State.md and project_state.md):

```text
**Authored-against:** `<sha>` target: `<merge_target>`

> ⚠️ Verify base before acting: `git diff <sha>..origin/<merge_target> -- <files cited>` -- non-empty ⇒ cited code moved. (Resolve `<merge_target>` through its remote-tracking ref, never a bare local branch name — a local branch of the same name can be stale or absent.)
```

Always resolve `<merge_target>` through its remote-tracking ref
(`origin/<merge_target>`), never a bare local branch name, in every recipe in
this file — a local branch of the same name can be stale (last fetched days
ago) or simply absent on the reader's machine, while `origin/<merge_target>`
is only ever what's actually on the remote. Fetch before running any of these
diffs if the remote-tracking ref might be stale.

## Derivation commands (run at authoring time)

```bash
# SHA of the current HEAD
git rev-parse HEAD

# Configured merge target -- resolve through .thrum/redirect when present.
# A worktree's .thrum/ holds only a `redirect` file (a single line: the
# absolute path to the MAIN REPO'S .thrum directory itself), not its own
# config.json -- reading .thrum/config.json directly from a worktree
# silently returns empty. Root repos have no redirect file, so CONFIG falls
# through to the direct path.
CONFIG=".thrum/config.json"
[ -f .thrum/redirect ] && CONFIG="$(cat .thrum/redirect)/config.json"
jq -r '.orchestration.merge_target' "$CONFIG"
```

The author must never type or remember either value by hand — both come from the
shell commands above, run at authoring time.

If either command returns empty or `null`, STOP and report — do NOT emit a stamp
with a null/empty field. An artifact with no stamp is honest; an artifact stamped
`null` is a lie the reader cannot detect (the string "null" still matches the
reader's regex, so it reads as a valid stamp instead of UNVERIFIABLE, and the
resulting `git diff <sha>..null` then errors).

Before emitting the stamp, also verify the derived `<sha>` actually resolves:

```bash
git cat-file -e <sha>
# or: git rev-parse --verify <sha>^{commit}
```

If this fails, STOP and report — do NOT emit a stamp citing an unresolvable SHA. This is the same failure class as the
null/empty check above (a stamp the reader cannot trust), catching a different way to get there: `git rev-parse HEAD`
itself can't produce a bad SHA, but a stamp isn't always freshly derived this way — it can be hand-typed, copied from a
stale source, or otherwise introduced without running the command above. Treat this resolve-check as a mandatory guard
regardless of how the SHA was obtained, not an optional sanity check.

## Format conventions

The stamp follows the same literal-match convention as the `THRUM-REVIEW` marker
(canonical form documented in `coordinator-running-brainstorm-cycles` skill
§ "Footer → commit → stamp"): fixed field order, case-sensitive, ASCII-only —
parseable with `grep -F` semantics without regex. The reader-side regex in
`verify-against-plan` anchors on this fixed format; do not reorder or recase any
field.

## Review-object binding (THRUM-REVIEW stamp — plan/prompt binding)

A review stamp's PRESENCE proves a review happened; it does not prove the
stamp still binds the artifact that was reviewed. An edit made after a
`Ready:Yes` verdict leaves a stamp that still reads `Ready:Yes` while
describing a document that no longer exists — the same class of staleness the
Authored-against stamp solves for the tree, applied here to the artifact
itself.

The `THRUM-REVIEW` stamp carries two extra keys per stage, binding it to the
exact git blob it reviewed and the exact source it was reviewed against:

| Stage | Self-binding key | Source-lock key |
| --- | --- | --- |
| `stage=plan` | `plan_obj` | `src_lock` |
| `stage=prompt` | `prompt_obj` | `plan_lock` |

### Derivation (strip-then-hash, run at stamping time)

```sh
# self-object blob: strip EVERY THRUM-REVIEW line, hash the remainder, filters OFF
obj=$(grep -v '^<!-- THRUM-REVIEW:' "$FILE" | git hash-object --no-filters --stdin)
# source-lock blob: the source file is not mutated by the stamp -> plain hash
lock=$(git hash-object --no-filters "$SOURCE_FILE")
```

- Strip set = every line matching `^<!-- THRUM-REVIEW:` (all cycles) — NOT
  `THRUM-GATE`/`THRUM-DEFER`. The stamp cannot bind a hash that includes
  itself, so its own lines are removed before hashing (chicken-and-egg).
- `--no-filters --stdin` bypasses gitattributes clean filters / autocrlf so
  the value emitted here and the value re-derived at read time agree
  byte-for-byte.
- Hash the **working-tree** file, not a committed blob — an uncommitted
  post-review edit must be caught before it is ever committed.
- For `stage=plan`: `$SOURCE_FILE` is the LOCKED brainstorm (plus design spec,
  if any); `src_lock` proves the plan was reviewed against the source that was
  current at review time.
- For `stage=prompt`: `$SOURCE_FILE` is the LOCKED plan; `plan_lock` proves the
  prompt was reviewed against the plan that was current at review time.
- When multiple cycles' `THRUM-REVIEW: stage=<S>` lines coexist, the
  **highest-cycle (last-appended)** line is the binding verdict; earlier
  lines are history, never re-checked. Stamps are only ever appended, never
  reordered, so append-order == cycle-order — select with `tail -1`, never a
  sort (`cycle=10` must beat `cycle=9`, which a lexical sort inverts).

### Null/unresolvable guard

Same failure class as the Authored-against stamp above: if either `obj` or
`lock` comes back empty or `null`, STOP and report — do NOT emit a stamp with
an empty/`null` binding key. A `THRUM-REVIEW` line with `plan_obj=` (or any of
the four binding keys) empty or literal `null` still matches a reader's regex
and reads as a valid binding — the value a reader would trust to prove binding
is exactly the value that never resolved.

### Extended stamp shape (fixed key order preserved)

```text
<!-- THRUM-REVIEW: stage=plan verdict=Ready:Yes cycle=<N> date=<YYYY-MM-DD> verify=<...> plan_obj=<blob> src_lock=<blob> [rev=... notes="..."] -->
<!-- THRUM-REVIEW: stage=prompt verdict=Ready:Yes cycle=<N> date=<YYYY-MM-DD> prompt_obj=<blob> plan_lock=<blob> -->
```

`plan_obj`/`src_lock` and `prompt_obj`/`plan_lock` are appended after the
stage's existing keys, in this order — keeping the fixed-key-order convention
this file already establishes for the Authored-against stamp above.

## Read-time provenance re-derivation

Both checks below are computable from the two fields the stamp already carries
(`<sha>` and `<merge_target>`) — no new stamped field is needed. A reader running
either check for the first time, or re-running it on an artifact read before,
must run them in this exact order; the second is undefined if the first fails
(short-circuit):

1. **SHA-resolves** — `git cat-file -e <sha>` (or
   `git rev-parse --verify <sha>^{commit}`). If this fails, the stamp cites a
   FABRICATED or mistyped SHA — flag RED immediately and do NOT attempt check 2.
   Merge-status has no defined answer for a SHA that does not exist.

2. **Merge-status** — only once check 1 has passed:
   `git merge-base --is-ancestor <sha> origin/<merge_target>`. If this succeeds
   (the SHA IS already an ancestor of the merge target) AND the artifact's own
   prose describes that SHA's work as still open ("in-progress", "awaiting a
   gate", "not yet merged", or similar), flag the claim STALE — the work
   described has already landed; whatever gate the artifact was waiting on
   already happened, or was never blocking to begin with.

This re-derivation must run EVERY TIME the artifact is read, not only once at
authoring time — the same diff-at-read discipline this file already establishes
for the base stamp (`git diff <sha>..origin/<merge_target>`). A check that only
ran once at write time cannot catch drift that accumulates afterward, as the
tree keeps moving.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.