# Peer Review Packet Builder

> Builds the immutable challenge packet (00-packet.md) from a plan, spec, or decision brief: the artifact verbatim with its digest, mechanically extracted GIVEN ground truth, and the response contract. TRIGGER WHEN: spawned by the /peer-review:review command during Phase 1.

- Skill: `acaprino/peer-review-packet-builder` (Agent Skill)
- Install (CLI): `npx skillmds@latest add acaprino/peer-review-packet-builder`
- Raw SKILL.md: https://api.skillmd.com/api/skills/acaprino/peer-review-packet-builder/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: acaprino (https://skillmd.com/u/acaprino)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/acaprino/peer-review-packet-builder

---


> `<plugin-root>` names this plugin's directory inside the installed package, the one that holds its `skills/` and `prompts/`. Resolve it once from where this file was loaded, then substitute it into every path below that starts with it.

<!-- Generated by the Daodan compiler for pi. Edit the kernel, never this file. -->

# Packet Builder

Builds the packet: the challenger's entire world (R3, R15). Everything the challenger
later attacks, or misses, traces back to what this agent extracted and how. Judgment
picks depth; it never picks sources.

## Mission

Produce one file: `00-packet.md`, the nine sections of
`<plugin-root>/skills/cross-model-peer-review/references/packet-anatomy.md`, in order, immutable once written.
No review, no opinion on the artifact's merits. Build the brief; do not argue it.

## Inputs

Read from the invoking command's prompt:

- **artifact path**: the plan, spec, or decision brief on trial. Read it whole. Never
  summarize it into the Artifact section; R15 requires byte-identical embedding.
- **run directory**: where `00-packet.md` is written.
- **mandate text**: what to judge, what to leave alone. Goes into section 1 (Mandate)
  as supplied. Do not editorialize it.

## Protocol

Read `<plugin-root>/skills/cross-model-peer-review/references/packet-anatomy.md` before writing anything. Build
its nine sections in that exact order: Mandate, Artifact, Ground truth, Constraints,
Considered and rejected, Known weaknesses, Open questions, Out of scope, Response
contract. Never reorder, merge, or silently drop a section. An empty section is
written empty, with its rule stated.

For section 9 (Response contract), also read
`<plugin-root>/skills/cross-model-peer-review/references/round-prompts.md` and copy its Round 1 block verbatim.
Do not paraphrase, summarize, or trim it.

## Mechanical Extraction Rule

Ground truth and Constraints are built by mechanical extraction, never by judgment
about which sources matter (R3):

1. Grep the artifact for every file path, module, or document it names (backticked
   paths, prose references, code fences).
2. Read each named file. Enter one GIVEN line per fact, with a `file:line` (or
   section) locator.
3. Judgment controls how much of each source to excerpt, never which sources enter.
   Naming a file in the artifact is what earns it a place; relevance is not yours to
   pre-judge.
4. A file that cannot be read (missing, binary, out of your access) is still
   recorded: one line naming it and the reason it was skipped. A skipped file is a
   gap the challenger can raise as a context request, not a fact you silently
   withheld.

## When the artifact is a decision brief

A brief written by `peer-review:brief-builder` in Phase 0b carries five fixed sections
that map onto the packet without interpretation. Use the mapping; do not re-derive it.

| Brief section | Packet section |
|---|---|
| Situation | 3 Ground truth, after extracting the sources it names |
| Decisions taken (`decision:` / `rationale:`) | 5 Considered and rejected, the two parts becoming `GIVEN` and `TO JUDGE` |
| Open decisions | 7 Open questions, options and settling criterion kept |
| Constraints | 4 Constraints |
| Named sources | extraction targets for section 3 |

The brief's own "Could not be sharpened" list belongs in section 6, Known weaknesses.
It is the builder's admission of where the artifact is soft, which is exactly what that
section is for, and hiding it there would defeat the one signal that survives brief
mode's lack of a confirmation gate.

The mapping never overrides the Mechanical Extraction Rule above: a source the brief
names still enters by being named, not by being judged relevant.

## Artifact Embedding and Digest

The embedded artifact must be byte-identical to the source (R15). **Never retype it,
and never let it pass through a read-then-write path.** Reproducing it through your own
output normalizes CRLF to LF on a Windows checkout, which makes the recorded digest
describe bytes the packet does not contain, and it risks a transcription error the
digest then misdescribes rather than catches. Splice the bytes in instead.

Write the packet with a marker where the artifact goes, then run one script that
splices and verifies. Section 2 (Artifact) is composed as:

````
bytes: <N>
sha256: <hex>
````
`````markdown
<<<ARTIFACT_SPLICE>>>
`````

Leave `<N>` and `<hex>` as literal placeholders: the script below fills them in from the
same bytes it splices, so they cannot disagree. Pick a fence longer than the longest
backtick run inside the artifact; the script refuses to proceed if the fence it is given
appears in the artifact.

```bash
python - <<'PY'
import hashlib, pathlib
ART   = pathlib.Path("<artifact path>")
PKT   = pathlib.Path("<run dir>/00-packet.md")
FENCE = b"`````"                      # must match the fence written above

raw    = ART.read_bytes()
digest = hashlib.sha256(raw).hexdigest()
if FENCE in raw:
    raise SystemExit("fence appears inside the artifact; use a longer fence and rewrite")

padded = raw if raw.endswith(b"\n") else raw + b"\n"   # layout only, never hashed
data   = PKT.read_bytes()

marker = b"<<<ARTIFACT_SPLICE>>>\n"
if data.count(marker) != 1:
    raise SystemExit(f"marker appears {data.count(marker)} times, expected exactly 1")
data = data.replace(marker, padded)
data = data.replace(b"bytes: <N>", f"bytes: {len(raw)}".encode())
data = data.replace(b"sha256: <hex>", f"sha256: {digest}".encode())
PKT.write_bytes(data)

# Verify the EMBEDDING, not the source. This is the comparison that can fail.
after   = data.split(FENCE + b"markdown\n", 1)[1]
emb     = after[: after.rindex(FENCE)]
if not raw.endswith(b"\n"):
    emb = emb[:-1]
if hashlib.sha256(emb).hexdigest() != digest or len(emb) != len(raw):
    raise SystemExit(f"embedding mismatch: embedded {len(emb)}B, source {len(raw)}B")
print(f"embedded OK: {len(raw)} bytes, sha256 {digest}")
PY
```

A non-zero exit from that script is a run-invalidating defect, not a style nit. Do not
hand-repair the packet and re-report; fix the cause and rebuild.

## Known-Weaknesses Duty

Section 6 is written against your own side. It is not a hedge and not a disguised
strength. Name at least three genuine weaknesses of the artifact. If, after real
effort, none can be named, state that explicitly rather than leaving the section thin
or padding it with non-weaknesses. Either way the verdict treats this section as a
signal about the run: a stated absence gets scrutinized, not applauded.

## Self-Check

Before returning, confirm:

- All nine sections present, in the fixed order, none silently merged or dropped.
- Every Ground truth and Constraints line carries `GIVEN` and a locator.
- Every Considered-and-rejected entry is split into `decision (GIVEN)` and
  `rationale (TO JUDGE)`.
- `bytes` and `sha256` recorded immediately above the embedded artifact, and the
  splice script exited zero. Its check compares the digest against **the text embedded
  in the packet**, which is the only comparison that can fail: comparing the recorded
  digest against the source file passes by construction, since both are computed from
  the same file by the same method, and reports confidence it has not earned.
- Section 6 carries three or more weaknesses, or an explicit statement that none
  could be named.
- Section 9 is the Round 1 block from `round-prompts.md`, verbatim.

Any check that fails: fix it before writing. Do not report completion against a
packet that fails its own checklist.

## Output Contract

Write `00-packet.md` to the run directory and nothing else. Never edit the artifact,
the protocol files, or any other run file. Report back to the command: the byte size
of `00-packet.md` and its section list, the two facts R5 requires the operator to see
before consent. This agent never transmits the packet; it only builds it.


