Archive a completed SDD change by syncing delta specs. Trigger: orchestrator launches archive after implementation and verification.
60
70%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./internal/assets/skills/sdd-archive/SKILL.mdConfirm your role before acting. You are the dedicated sdd-archive sub-agent unless you loaded this skill directly through the skill() tool.
sdd-archive sub-agent, continue with the phase work below. Do not delegate. Do not call the Skill tool.skill() tool, you are the orchestrator. Stop here and delegate to the dedicated sdd-archive sub-agent using your platform's delegation primitive (for example, task(...) or a sub-agent invocation).Generated technical artifacts default to English. Do not inherit the user's conversational language or the active persona's regional voice for SDD artifacts unless the user explicitly requests that artifact language or the project convention requires it.
If technical artifacts are explicitly requested in another language, use a neutral/professional register unless the user explicitly requests a different tone or regional variant.
Public/contextual comments follow the target context language by default. Explicit user language or tone overrides win; otherwise use a neutral/professional register unless the target context clearly calls for another tone or regional variant.
You are a sub-agent responsible for ARCHIVING. You merge delta specs into the main specs (source of truth), then move the change folder to the archive. You complete the SDD cycle.
From the orchestrator:
engram | openspec | hybrid | none)skills/_shared/sdd-status-contract.md, including artifact paths, task progress, dependency states, and actionContextThe archive report is the terminal record of the cycle. It describes the state of the change AT CLOSE, not the state at earlier points during the cycle. A future reader consults the archive to learn what actually shipped; a stale claim sends them to redo finished work — or to trust that something is pending when it already closed.
apply-progress and verify-report are intermediate snapshots. Each describes the state of the work at the time it was written, and work routinely continues after they are persisted: verify warnings get fixed in later commits, blocked tasks get completed, test counts change. A snapshot's "done" stays true — work does not un-complete — but its "pending", "blocked", or "open gap" claims are only valid for the moment the snapshot was written. Never present an intermediate snapshot's statement as the current state of the change.
When sources disagree about a fact, rank them — most authoritative first:
reviewGate, the terminal receipt, and post-apply gate context. Validated delivery facts; they win for everything they cover.verify-report and apply-progress — intermediate snapshots. Lowest rank: valid history of what was true at their time, never evidence of final state.Reporting rules that follow:
verify-report {observation-id}, at verification time ..."). Do not restate them in bare present tense as current facts.verify-report or apply-progress when later work changed them.This hierarchy governs how the archive REPORTS facts. It does not weaken gates: CRITICAL issues in verify-report still block archive with no prompt override (a claim that a CRITICAL was fixed requires re-running sdd-verify, not a prompt assertion), and the Native Review Receipt Gate and Task Completion Gate below keep their own authority rules.
Follow Section B (retrieval) and Section C (persistence) from
skills/_shared/sdd-phase-common.md.
sdd/{change-name}/proposal, sdd/{change-name}/spec, sdd/{change-name}/design, sdd/{change-name}/tasks, and sdd/{change-name}/verify-report (all required). Read the exact sdd/{change-name}/review/{transaction,ledger,receipt,gate-context} topics only when the Native Review Receipt Gate below finds reviewGate present (a review was actually discovered) — when reviewGate is structurally absent, no review ever happened for this candidate and none of those topics exist to read. Record all observation IDs actually read in the archive report for traceability. Save as sdd/{change-name}/archive-report.skills/_shared/openspec-convention.md. Perform merge and archive folder moves.Before any task reconciliation, spec sync, or archive move, require structured status. reviewGate is a structurally ABSENT key — not a populated value — in every case except a genuine, discovered review artifact for this candidate:
reviewGate absent, archive proceeds under ordinary repository policy in both of these cases; there is no disabled/unmanaged value to check for, and no explicit-artifact carve-out either:
reviewOffer) is present in the SAME status output — an invitation, never a gate. Declining is proceeding to archive without acting on it, not a verb; nothing about the decline is recorded, and dependencies.archive: ready here means proceed, not "investigate why the gate is missing".reviewGate present with result: allow (a discovered receipt that governs this candidate and validates): proceed. Read the exact transaction, frozen ledger, approved terminal receipt, and post-apply gate context referenced by status; the receipt must match final candidate tree, paths digest, policy, ledger, fix delta, current independent verification evidence, mode counters, and base relationship.allow only when native final-verify settlement attests the exact canonical passing report bytes and resulting candidate tree, the receipt-to-current delta is that report path alone, and restoring its receipt blob reconstructs the receipt candidate. This archive-status exception never changes generic review or delivery gates.reviewGate present with any other result (pending, malformed, scope-changed, invalidated, or escalated — a review was actually discovered and failed validation): blocks archive with no override and no automatic reviewer launch. The gate never manufactures allow, and re-enabling a disabled switch revalidates from the current state.Do not treat reviewGate's absence itself as a defect to investigate or as grounds to demand a receipt — only a present, non-allow value blocks.
sdd-apply is responsible for marking completed tasks in the persisted tasks artifact. sdd-archive is responsible for validating that the persisted artifact reflects the final state before closing the cycle.
Before syncing specs or moving any archive folder, inspect the tasks artifact:
sdd/{change-name}/tasks observation.openspec/changes/{change-name}/tasks.md.If any implementation task remains unchecked (- [ ]):
blocked; do not sync specs, move the change folder, or claim the SDD cycle is complete.sdd-apply must be rerun or corrected so it marks completed tasks in the persisted tasks artifact.apply-progress/verify-report prove every unchecked task is complete. If you do this exceptional repair, record the exact reconciliation reason in the archive report.The archived audit trail MUST NOT contain stale unchecked tasks for completed work. Internal todo state is not enough; the persisted SDD task artifact is the source of truth for completion visibility.
OpenSpec permits archiving with incomplete artifacts or tasks after a user confirmation. gentle-ai is stricter by default:
verify-report always block archive. Do not accept an override for CRITICAL verification issues.sdd-archive does not own normal task completion. sdd-apply owns checkbox completion; archive may only perform exceptional mechanical reconciliation with proof from apply-progress and verify-report.actionContext.mode: workspace-planning, STOP. Do not move workspace changes into repo-local archives or edit linked repos.allowedEditRoots is present, archive operations must stay inside those roots.Archival is a mechanical filesystem operation. File content MUST NEVER pass through the model's Read/Write path to be copied — a model that summarizes, truncates, or alters even one byte while reporting success corrupts the audit trail silently. The only acceptable copy mechanism is a native shell command (cp -R, mv, or git mv), verified by a structural readback.
cp -R, mv, or git mv. NEVER use Read → Write to reproduce artifact content into the archive or main specs — that routes bytes through model generation, where truncation is silent and undetectable without an independent diff.diff -r (source vs. destination) as a MANDATORY readback. The archive-report file is additive-only and excluded from the source/destination comparison (it did not exist in the source change folder).diff -r output MUST appear in the phase result. An empty diff -r (no differences) is the only passing evidence; any difference is a truncation or alteration and FAILS the phase. A skipped or missing diff -r also FAILS the phase — agent self-report is never sufficient.blocked with the reason shell access required for mechanical archive copy is unavailable — do NOT fall back to Read/Write copying.Follow Section A from skills/_shared/sdd-phase-common.md.
Do not start this step until the Task Completion Gate above passes.
IF mode is engram: Skip filesystem sync — artifacts live in Engram only. The archive report (Step 5) records all observation IDs for traceability.
IF mode is none: Skip — no artifacts to sync.
IF mode is openspec or hybrid: For each delta spec in openspec/changes/{change-name}/specs/:
openspec/specs/{domain}/spec.md)Read the existing main spec and apply the delta:
FOR EACH SECTION in delta spec:
├── ADDED Requirements → Append to main spec's Requirements section
├── MODIFIED Requirements → Replace the matching requirement in main spec
├── REMOVED Requirements → Delete the matching requirement from main spec after recording Reason/Migration
└── RENAMED Requirements → Rename the matching requirement while preserving scenarios unless the delta also modifies themMerge carefully:
(Reason: ...) and (Migration: ...) notes in the delta before deleting from main specsThe delta spec IS a full spec (not a delta). Copy it mechanically with the shell — do NOT Read the file and Write its content back, which routes bytes through the model and can truncate silently:
# Mechanical copy (MANDATORY): never Read → Write artifact content
target_dir="openspec/specs/{domain}"
target_path="$target_dir/spec.md"
mkdir -p "$target_dir"
temp_path=
cleanup_temp() {
if [ -n "$temp_path" ]; then
rm -f "$temp_path" || :
fi
}
trap cleanup_temp EXIT
temp_path="$(mktemp "$target_dir/.spec.md.XXXXXX")"
if cp "openspec/changes/{change-name}/specs/{domain}/spec.md" "$temp_path"; then
:
else
copy_status=$?
exit "$copy_status"
fi
if diff -r "openspec/changes/{change-name}/specs/{domain}/spec.md" "$temp_path"; then
diff_status=0
else
diff_status=$?
fi
if [ "$diff_status" -ne 0 ]; then
exit "$diff_status"
fi
if mv "$temp_path" "$target_path"; then
temp_path=
else
move_status=$?
exit "$move_status"
fi
# Empty diff above is the only passing evidence; include verbatim output in the result.IF mode is engram: Skip — there are no openspec/ directories to move. The archive report in Engram serves as the audit trail.
IF mode is none: Skip — no filesystem operations.
IF mode is openspec or hybrid: Move the entire change folder to archive with date prefix, using a mechanical shell move. NEVER Read each artifact and Write it into the archive — that routes file content through the model and can truncate or alter bytes silently:
# Run this block as one shell transaction so the EXIT trap remains active.
# The snapshot is recursive and must be created before either move attempt.
snapshot_root="$(mktemp -d "${TMPDIR:-/tmp}/sdd-archive.XXXXXX")"
trap 'rm -rf -- "$snapshot_root"' EXIT
cp -R "openspec/changes/{change-name}" "$snapshot_root/source"
# Mechanical move (MANDATORY): git mv when tracked, mv otherwise
mkdir -p openspec/changes/archive
if git mv openspec/changes/{change-name} openspec/changes/archive/YYYY-MM-DD-{change-name}; then
:
else
if mv openspec/changes/{change-name} openspec/changes/archive/YYYY-MM-DD-{change-name}; then
:
else
move_status=$?
exit "$move_status"
fi
fi
# The source must be gone before comparing the archived tree with its snapshot.
if [ -e "openspec/changes/{change-name}" ] || [ -L "openspec/changes/{change-name}" ]; then
printf 'archive move left the source directory in place\n' >&2
exit 1
fi
# MANDATORY readback: only empty diff output passes.
if diff -r "$snapshot_root/source" "openspec/changes/archive/YYYY-MM-DD-{change-name}"; then
diff_status=0
else
diff_status=$?
fi
if [ "$diff_status" -ne 0 ]; then
exit "$diff_status"
fiUse today's date in ISO format (e.g., 2026-02-16).
The snapshot_root is removed safely by the EXIT trap after the readback, including when the move or comparison fails. Compare the archived folder against that pre-move recursive snapshot; do not substitute a model readback, staged tree, or post-move source. The archive-report you write in Step 5 is additive and excluded from the comparison because it did not exist in the source snapshot. Any non-empty diff -r output or non-zero status is truncation, alteration, or an operational failure and FAILS the phase; a missing diff -r also FAILS the phase.
IF mode is openspec or hybrid: The Mechanical Copy Contract above is the verification: the verbatim diff -r output from Steps 2 and 3 MUST appear in the phase result, and an empty diff is the only passing evidence. In addition, confirm:
tasks.md has no unchecked implementation tasks, unless the orchestrator explicitly approved archive-time stale-checkbox reconciliation backed by apply-progress/verify-report proofdiff -r readback output is included in the result and is empty (no differences)A failed or skipped diff -r FAILS the phase regardless of the checkboxes above — agent self-report is never sufficient evidence of byte-identity.
IF mode is engram: Confirm all artifact observation IDs are recorded in the archive report and the tasks observation has no unchecked implementation tasks unless the orchestrator explicitly approved archive-time stale-checkbox reconciliation backed by apply-progress/verify-report proof.
IF mode is none: Skip verification — no persisted artifacts.
This step is MANDATORY — do NOT skip it.
Follow Section C from skills/_shared/sdd-phase-common.md.
archive-reportsdd/{change-name}/archive-reportarchitectureReturn to the orchestrator:
## Change Archived
**Change**: {change-name}
**Archived to**: `openspec/changes/archive/{YYYY-MM-DD}-{change-name}/` (openspec/hybrid) | Engram archive report (engram) | inline (none)
### Specs Synced
| Domain | Action | Details |
|--------|--------|---------|
| {domain} | Created/Updated | {N added, M modified, K removed requirements} |
### Archive Contents
- proposal.md ✅
- specs/ ✅
- design.md ✅
- tasks.md ✅ ({N}/{N} tasks complete)
### Source of Truth Updated
The following specs now reflect the new behavior:
- `openspec/specs/{domain}/spec.md`
### SDD Cycle Complete
The change has been fully planned, implemented, verified, and archived.
Ready for the next change.cp -R/mv/git mv via the shell only, NEVER via model Read/Write — a model can truncate or alter bytes silently while reporting success, and only an independent diff -r catches itdiff -r (source vs. destination, archive-report additive-only) and include its verbatim output in the phase result; an empty diff is the only passing evidence, and a skipped/missing diff -r FAILS the phaseblocked — do NOT fall back to Read/Write copyingverify-report/apply-progress claims as current facts, and record unrankable contradictions explicitly instead of resolving them silentlytasks.md / the tasks observation still shows stale unchecked implementation tasksopenspec/changes/archive/ doesn't exist, create itrules.archive from openspec/config.yamlskills/_shared/sdd-phase-common.md.a245f26
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.