Skip to content
Back to skills

Sd Port Fidelity

ASecurity

Cross-project port fidelity policy for specwright. A port reproduces a donor implementation inside a host repo; the donor's form is the specification, and every departure from it is a citable decision rather than a preference. Authored into port specs by `sd-spec-architect` and enforced against the changeset by `sd-reviewer`. Read the section matching your role. The core rule and the deviation allowlist apply to everyone. ---

  • 8 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 2, 2026
ai-agentsgoshellbashexpressgit

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add developzoneio/specwright --skill sd-port-fidelity --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sd Port Fidelity?

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

Security grade badge for Sd Port Fidelity
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/developzoneio-sd-port-fidelity/badge)](https://www.skillsdirectory.com/skills/developzoneio-sd-port-fidelity)

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
# sd-port-fidelity

Cross-project port fidelity policy for specwright. A port reproduces a donor implementation inside
a host repo; the donor's form is the specification, and every departure from it is a citable
decision rather than a preference. Authored into port specs by `sd-spec-architect` and enforced
against the changeset by `sd-reviewer`.

Read the section matching your role. The core rule and the deviation allowlist apply to everyone.

---

## The core rule

**Mirror the donor structurally. Every departure is a row in the deviation table, or it is a
defect.**

Structural mirror means the host reproduces, as far as the target permits: the donor's file
layout, member set, member order, symbol names, local variable names, step order within each
member, attribute order, and log message text. Judgement is not the mechanism here. A departure
carrying a deviation row is legal; a departure carrying none is a defect; and nobody is asked to
decide which of the two a given hunk is.

---

## Deviation allowlist

Exactly four groups force a departure. Each requires its own citation - a row citing nothing is
invalid, and the hunk it claims to cover is unjustified.

| Group | Forced by | Citation required |
|---|---|---|
| 1 | Compiler, namespace, or assembly conflict | the conflicting identifier |
| 2 | Host constitution | the constitution section, `§N.M` |
| 3 | Host precedent | `file:line` in the host |
| 4 | Behavior parity fix on an agreed donor defect | the parity criterion it satisfies |

Anything outside these four reverts to the donor form. "Cleaner", "more idiomatic to me", and "the
host does it differently somewhere" are not groups.

---

## Anti-simplification rules

These bind the implementer through the task blocks the architect writes, not by the implementer
loading this file: `sd-spec-architect` puts each applicable rule into the port task's `Acceptance`
and cites the donor `file:line` in `Pattern refs` (see **sd-atomic-task-format**).

- **No unrequested simplification.** Shorter is not better. Collapsing branches, merging members,
  or replacing a loop with a library call is a departure and needs a row.
- **No gratuitous rename.** Donor identifier names carry over even where host style would differ.
  Group 1, group 3, or nothing.
- **No reordering.** Statement order, parameter order, and member order follow the donor, even
  where another order reads better.
- **No opportunistic fix.** A donor defect is reproduced as-is and recorded for a follow-up spec.
  Fixing it inline is group 4 only when the fix was agreed at the gate before implementation began.
- **Host constitution beats donor precedent.** "It is only a copy" exempts nothing. A donor form
  that violates the host constitution is a cited group 2 deviation, never a verbatim import.

---

## Gate tables (sd-spec-architect)

A port spec carries three tables. Each has a completeness condition the gate evaluates
mechanically - it counts and matches, it never assesses whether a reason is good. A table failing
its condition is incomplete and the gate refuses it.

The spec must also carry a **fidelity acceptance criterion**: the criterion these tables are
evidence for. It is what review findings anchor to, and without it a fidelity finding has no legal
anchor (see **sd-severity-taxonomy**). A port spec missing it fails the gate.

### Path mapping table

| Column | Contents |
|---|---|
| `Donor path` | repo-relative path in the donor |
| `Host path` | repo-relative destination in the host |
| `Kind` | `mirror` / `merge` / `omit` |
| `Reason` | required when `Kind` is not `mirror`; `-` when it is |

**Complete when**: one row per file in the declared donor scope and no others; every `Host path`
unique; no empty cell; every non-`mirror` row carries a non-empty `Reason`.

### Member manifest

| Column | Contents |
|---|---|
| `Donor path` | the donor file the member comes from |
| `Member` | donor symbol name, verbatim |
| `Ordinal` | 1-based position of the member within that donor file |
| `Host path` | destination, copied from the path mapping table |
| `Status` | `ported` / `deviated` / `omitted` |
| `Deviation ID` | `D<NN>` when `Status` is not `ported`; `-` when it is |

**Complete when**: one row per member of every non-`omit` donor file; the `Ordinal` values within
each `Donor path` form `1..N` with no gap and no duplicate; each `Host path` equals the mapping row
for its `Donor path`; every non-`ported` row names a `Deviation ID` present in the deviation table.

### Deviation table

| Column | Contents |
|---|---|
| `ID` | `D<NN>`, unique, ascending |
| `Donor form` | the donor name, order, or text departed from |
| `Host form` | what the host uses instead |
| `Group` | `1`, `2`, `3`, or `4` from the allowlist |
| `Citation` | the citation that group requires, verbatim |

**Complete when**: every `ID` unique; every `Group` is one of `1` to `4`; every `Citation` is
non-empty and in the shape its group requires; every `Deviation ID` named in the member manifest
appears here exactly once; no row here is unreferenced by the manifest.

---

## Snapshot artifacts (sd-spec-architect)

Under a port spec's `04-artifacts/source/`: the bridged contract always, and under
`snapshot: contract+source`, the donor files too. `MANIFEST.md` sits at that directory's root.

### Snapshot manifest format

- **Donor**: <repo url or path>
- **Commit**: <full sha>
- **Captured**: <YYYY-MM-DD>
- **Mode**: contract | contract+source
- **Hash algorithm**: sha256, lowercase hex, over the bytes as captured

| Snapshot path | Donor path | Commit | Bytes | SHA-256 | Member ranges |
|---|---|---|---|---|---|
| `orders/order-intake` | `src/orders/order-intake` | `<sha>` | 4821 | `3f9a...` | `1: CreateOrder 12-58; 2: ValidateTotals 60-93` |

One row per captured file. `Member ranges` is `<ordinal>: <member> <firstLine>-<lastLine>`,
semicolon-separated, ordinals contiguous from 1 - the same ordinals the Member manifest table uses.

### Two snapshot rules

1. **Cite the snapshot, not the donor.** Path mapping and Member manifest rows cite `Snapshot
   path`, never a donor-repo path - donor line numbers rot the moment the donor changes; the
   snapshot is frozen. Donor paths, the commit, and line ranges live only in `MANIFEST.md`,
   addressed by `(Snapshot path, Ordinal)` - the Member manifest table carries no line-range
   column of its own.
2. **Quarantine.** The snapshot directory is evidence, never a copy source handed to an
   implementer without a Member manifest row and an allowed-deviation list scoping it.

### Immutability

At freeze, every file under `04-artifacts/source/` plus `MANIFEST.md` is appended as an
**individual literal string** to `paths.protected` in `.claude/project-config.json`. Both
`spec-gate` hooks match `paths.protected` by exact string equality, not glob - the enumeration
*is* the mechanism, not a workaround for one. The append must be idempotent. `/sd:spec` cannot
perform this step itself (it never touches `.claude/`); `/sd:port` Phase 2 performs the freeze.
Outside that pipeline it stays a documented manual step. `spec-gate` guards `Edit`/`Write` only -
it does not stop a shell delete.

Per-file hashes are recorded now so a later drift check (re-hashing the donor at a newer commit)
remains possible; consuming them is out of scope for this story.

---

## Parity artifacts (main thread)

The diff `sd-reviewer` adjudicates is produced by the main thread, never by an agent. The reviewer
has no `Bash` and no write tool - that allowlist is what structurally stops the adjudicator from
fixing what it judges - so the diff must already be a file on disk when the reviewer is invoked.

Output root is `04-artifacts/parity/`, a sibling of the frozen `04-artifacts/source/`: same spec,
same artifacts folder, evidence produced at a later phase by a different actor. Nothing under
`parity/` is frozen or appended to `paths.protected` - it is regenerated on every parity run and
overwrites the previous one.

- One diff per non-`omit` path mapping row, snapshot side first, host side second, unified format,
  at least 3 lines of context. File name is the `Host path` with `/` replaced by `__`, suffix
  `.diff`.
- A mapping row whose `Host path` does not exist still gets its diff - an all-deletion one. That is
  what makes a `missing` member visible without the reviewer listing the host tree itself.
- Every changeset file with no mapping row gets an all-addition diff, named the same way. Path
  conformance is then a property of the diff set rather than a second traversal.
- `INDEX.md` at the parity root, one row per diff file: `Diff file`, `Snapshot path`, `Host path`,
  `Mapping row` (the path mapping row number, or `-` when there is none).

`INDEX.md` is the reviewer's `DIFF_REF`. A run that cannot produce a diff for a row says so in that
row's `Mapping row` cell instead of dropping the row - a silently absent row reads as a clean file.

---

## Hunk classification (sd-reviewer)

Classify every hunk of the port changeset into exactly one class. The vocabulary is closed - there
is no sixth class and no "probably fine".

| Class | Condition | Verdict |
|---|---|---|
| `justified` | maps to a deviation row whose citation satisfies its group | accept |
| `unjustified` | departs from the donor form with no deviation row covering it | BLOCK |
| `missing` | a manifest member has no host counterpart and no `omitted` status | BLOCK |
| `extra` | host content with no donor counterpart and no deviation row | BLOCK |
| `overreached` | a deviation row covers the hunk, but the hunk changes more than that row's `Host form` states | BLOCK |

`overreached` is where a rubber stamp hides: one legitimately cited rename carrying an unrelated
reordering in the same hunk. Judge the hunk against the row's `Host form` text, never against the
mere existence of a row.

A `justified` hunk is a PASS and is not written up as a finding - report the count in the summary
line. Listing them individually buries the BLOCKs they outnumber.

Anchor every fidelity BLOCK to the port spec's fidelity acceptance criterion - a spec acceptance
criterion is a legal anchor for a code target under **sd-severity-taxonomy**. Cite the deviation
row, or its absence, as the supporting `file:line` per **sd-evidence-citation**. A deviation row is
evidence; it is never the anchor by itself.

### Whole-artifact checks

Two checks no hunk class can express, because each is a property of the changeset as a whole. Both
run once per parity review, both are BLOCK, and both are reported even when they pass - the count
is the evidence the check ran.

| Check | Question | Reported as |
|---|---|---|
| Member completeness | does every manifest row with `Status` `ported` or `deviated` have a host counterpart? | `<n>/<total> members present`, plus one BLOCK naming the `Donor path`, `Member` and `Ordinal` of each absent row |
| Path conformance | does every changeset file appear as a `Host path` in the path mapping table? | one BLOCK per unmapped file, citing the file and the table it is missing from |

Both belong to the reviewer rather than to `/sd:verify`, which decides everything from the spec's
own artifacts and reads no host source - the reasoning is recorded in `docs/architecture.md`.

### The parity gate

A HARD gate. Any BLOCK from the classification or from either whole-artifact check refuses
close-out. Two resolutions exist: revert the host toward the snapshot, or add a deviation row whose
group and citation hold up, then regenerate the parity artifacts and re-run. There is no third, and
no override - a gate that can be waived measures nothing. Deriving the missing rows from the
unexplained hunks is not a resolution either; it makes the diff justify itself.

---

## Anti-patterns

- **Improving the donor while porting.** The port is not the moment. Reproduce it, record it, and
  raise the follow-up.
- **A deviation row citing nothing.** "Host style" is not a citation; group 3 needs `file:line`.
- **Renaming to local taste.** Taste is not one of the four groups.
- **Reordering for readability.** Donor order is the order, attribute order included.
- **Waving a table through because it looks right.** The completeness conditions are counted, not
  judged. An incomplete table is refused without a discussion of intent.
- **Treating a donor defect as an invitation.** Record it; fix it in its own spec.

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.