Community코딩 & 개발github.com

marcioaltoe/archive-spec

완료된 스펙(Spec)을 아카이브합니다. 모든 작업 완료, QA 통과, 색인된 참조의 자체 포함 여부를 확인한 후, 확인된 아카이브 루트에 `<slug>.md`를 작성하고 Spec 폴더를 제거합니다. 이 과정은 Git의 `source_revision`에 기록되며, Roundfix Spec Run 종료 시 QA 통과 후 자동 실행되거나 사용자가 요청할 때 실행됩니다.

archive-spec란 무엇인가요?

이 스킬은 완료된 스펙을 아카이브하는 자동화 프로세스를 제공합니다. 주요 기능은 스펙 완료 검증, QA 상태 확인, 참조 자체 포함 여부 확인, 아카이브 레코드 작성, 그리고 스펙 폴더 제거입니다. 정상 아카이브는 모든 작업이 완료되고 QA가 통과되었으며 모든 참조가 자체 포함된 경우에만 수행됩니다. QA 아카이브 재정의(QA Archive Override)는 명시적 예외를 기록하며 검증을 주장하지 않습니다. 또한 아카이브 릴링크(Archive Relink) 기능을 통해 라이브 문서가 참조하는 파일을 `docs/references/` 디렉토리로 승격시키고 인용을 다시 작성합니다. 이 스킬은 Roundfix, Cursor, Claude Code 등의 AI 에이전트 플랫폼과 호환되며, `roundfix archive` 명령어를 통해 실행됩니다. 스펙 취소(Cancelling a Spec) 기능도 제공하여, 전달되지 않을 스펙을 `roundfix cancel` 명령어로 처리할 수 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/marcioaltoe/roundfix/tree/HEAD/skills/archive-spec

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

스펙 아카이브 (Archive Spec)

완료된 스펙을 아카이브하려면 확인된 아카이브 루트 아래에 <slug>.md를 작성하고 <확인된-스펙-루트>/<slug>/를 제거합니다. 이는 Git의 source_revision에 기록됩니다. 소스는 설정된 스펙 루트(Spec Root)이고, 대상은 확인된 아카이브 루트입니다. 기본 제공 docs/specs 루트의 경우 docs/history/specs/이고, 외부 또는 기본이 아닌 루트의 경우 <스펙-루트>/_archived/이며, 이는 roundfix archive 대상과 일치합니다. 정상 아카이브는 _구현, 검증, 자체 포함_을 의미합니다. 즉, 모든 작업이 완료되고, 작업 그래프(Task Graph)가 QA 게이트를 작성할 때 QA가 통과되었으며, 모든 색인된 참조가 스펙 소유여야 합니다. QA 아카이브 재정의(QA Archive Override)는 검증을 주장하지 않고 명시적 예외를 기록합니다. 두 처리 방식 후에 ls <스펙-루트>/는 활성 작업과 기록을 구분하며, 아카이브는 무엇이 왜 구축되었는지에 대한 기록으로 검색 가능한 상태를 유지합니다.

트리거는 스펙 완료이지 게시가 아닙니다. Roundfix Spec Run 종료 시 QA 게이트가 통과되면 자동으로 실행되거나, 사용자가 요청할 때 실행됩니다. 병합 및 릴리스는 별도의 사용자 주도 단계입니다. 아카이브 커밋은 단순히 브랜치와 함께 이동하며 해당 기능의 자체 PR 내에서 배송됩니다.

아카이브 릴링크 (Archive Relink)

아카이브 레코드를 작성하기 전에 아카이브는 아카이브 릴링크(Archive Relink)를 수행합니다. 라이브 문서가 소유자 스펙에서 참조하는 각 인용된 비핵심 파일을 자동으로 docs/references/<기본이름>으로 승격시킨 후, 각 라이브 문서의 인용을 승격된 복사본으로 다시 작성합니다. 스펙 폴더 또는 핵심 아티팩트에 대한 인용은 아카이브 레코드를 가리킵니다. 레코드는 다시 작성된 파일이 있을 때 relinked 아래에 나열됩니다. 소스는 하나의 소유자를 유지하므로 보조 스펙은 복사본이 필요하지 않습니다(ADR-0260, ADR-0083).

스펙 폴더는 삭제되어 은퇴합니다. 복사된 결과 및 각 승격된 복사본에서 제거된 폴더 내의 대상은 승격된 복사본의 이름을 지정하거나 Git 로케이터(Git Locator) <path>@<commit>가 됩니다. 이는 결코 레코드 자체를 가리키지 않습니다. 커밋은 경로를 보유하며 기본 브랜치 또는 태그에서 도달 가능해야 합니다. 그러한 커밋이 없을 때 로케이터는 경로와 레코드의 풀 리퀘스트를 지정합니다. 다른 대상은 저장소 대상을 유지합니다(ADR-0278).

아카이브는 승격 대상이 이미 존재하거나, 두 승격이 기본 이름을 공유하거나, 다시 작성될 라이브 문서가 HEAD에 커밋되지 않은 변경 사항이 있을 때 작성을 거부합니다. 라이브 문서가 아닌 파일의 인용 또는 다시 작성 후 남은 인용은 파일, 줄 및 대상을 지정하는 경고이며, 아카이브는 해당 파일을 변경하지 않은 채로 둡니다.

스쿼시 병합 (Squash merges)

스쿼시 병합은 풀 리퀘스트의 헤드 참조에만 source_revision을 유지합니다. 레코드는 pull_request에 해당 풀 리퀘스트를 지정합니다.

선언된 QA 거부 (Declared QA decline)

비어 있지 않은 qa_reason과 함께 qa: declined를 선언하는 작업 그래프(Task Graph)는 QA 보고서 없이, 재정의 없이 모든 작업이 완료되면 아카이브되며, 해당 아카이브 레코드는 no-qa 처리 방식을 갖습니다. 이러한 스펙에는 --qa-override가 거부됩니다. 다른 모든 아카이브 전제 조건은 여전히 적용됩니다.

QA 정산 (QA settlement)

동일한 결과가 작성된 qa 작업을 정산하고 아카이브가 남기는 것을 결정합니다:

결과정산아카이브
pass보고서에 허용되지 않은 차단 행이 없을 때 QA 작업을 completed로 정산하고 스펙을 아카이브 가능하게 만듭니다.아카이브 레코드, QA 보고서 및 평결을 지정합니다. 스펙, QA 보고서 및 증거는 Git의 source_revision에 유지됩니다.
적격 선언 partial실패, 건너뛰기, 또는 찾기 차단된 행이 없고, 모든 선언 차단 행이 일치하는 ## 도달 불가능한 승인(Unreachable Acceptance) 선언으로 처리되며, 모든 환경 차단 행이 PR 전 풀 리퀘스트 행(차단 사유 blocked (environment: no open Pull Request), 출처에 풀 리퀘스트 행 명시)이거나, 실행 샌드박스가 도달할 수 없는 외부 증거 행(blocked (environment: network denied: <host>), 출처에 외부 증거 행 명시)일 때 QA 작업을 completed로 정산합니다. 두 행 모두 도달 불가능한 승인 선언이 필요하지 않으며, 유일하게 충족되지 않은 행이 이러한 행인 부분은 적격합니다.아카이브 레코드, QA 보고서 및 평결을 지정하고 선언의 satisfied-by 레코드를 unproven으로 전달합니다. 스펙, QA 보고서 및 증거는 Git의 source_revision에 유지됩니다.
environment-blocked행을 차단된 상태로 둡니다. 동등한 증거가 환경 정책을 충족할 때 보고서는 여전히 pass로 정산될 수 있습니다.그 자체로는 아무것도 없습니다. 적격 보고서는 스펙을 아카이브할 수 있습니다.
failed권한이 있는 재정의가 적용되지 않는 한 QA 작업을 해결되지 않은 상태로 두고 아카이브를 거부합니다.없음.
missing권한이 있는 재정의가 적용되지 않는 한 QA 작업을 해결되지 않은 상태로 두고 아카이브를 거부합니다.없음.
overrideQA 작업 상태나 보고서 평결을 변경하지 않습니다. 실패 또는 누락된 QA에도 불구하고 명시적으로 권한이 부여된 아카이브를 정산합니다.qa_override, qa_override_approval, qa_override_reason, qa_override_qa_outcome, QA 작업이 불완전할 때 qa_override_qa_task_status, qa_override_revision을 포함하는 아카이브 레코드. QA 작업 및 보고서는 Git의 source_revision에 변경되지 않은 채 유지됩니다.

스펙의 권한이 오프라인으로 유지하는 행

위의 적격 선언 partial은 또한 게이트가 조회하지 않은 외부 증거 행을 허용합니다. 이는 스펙 자체의 권한이 해당 조회를 금지하기 때문이며, blocked (environment: <subject> prohibited by Spec authorization)로 기록되고 외부 증거 행이 출처에 지정됩니다. 주제는 권한이 금지하는 대상을 그 표현으로 지정합니다: 네트워크 조회의 경우 network, 또는 another repository. 길이는 1~80자이며 괄호를 포함하지 않습니다. 네트워크 거부 행과 마찬가지로 적격 부분을 결정하지 않으며 도달 불가능한 승인 선언이 필요하지 않습니다. 행은 최대 하나의 면제 종류에 포함되며, 정산, roundfix qa-report accept 및 roundfix archive는 동일한 정책을 통해 이를 읽습니다(ADR-0276, ADR-0335).

스펙 취소 (Cancelling a Spec)

전달되지 않을 스펙은 roundfix cancel <slug> --reason <text>로 취소되며, 수동으로 삭제되지 않습니다. 이 명령은 cancelled 처리 방식을 가진 아카이브 레코드를 작성하고, 각 채택된 백로그 항목을 status: open 상태로 docs/backlog/에 반환하며, 각 채택된 파인딩을 status: pending 상태로 docs/findings/에 반환한 다음, 스펙 폴더를 제거합니다. 바이트는 source_revision에 Git에 유지됩니다. 취소된 기록은 전제 조건을 충족하지 않으며, 다른 스펙을 대체하지 않으며, 전달 재시도(Delivery Retry)에서 거부됩니다.

무시된 파일 및 실패한 제거

아카이브 명령 및 취소 명령은 Git이 스펙 폴더 아래의 파일을 무시하는 동안 거부합니다. 각 명령은 무시된 모든 파일을 나열하고 아무것도 쓰지 않습니다. 운영자는 각 파일을 제거하거나 git add -f로 커밋한 후 재시도해야 합니다.

스펙 폴더의 최종 제거가 실패하면 두 명령 모두 모든 쓰기를 유지하고, 종료 코드 1로 종료하며 제거를 완료하는 명령을 출력합니다: chmod -R u+w '<folder>' && rm -rf '<folder>'.

전제 조건 — 신뢰하지 말고 검증 (Preconditions — verify, don't trust)

무언가를 건드리기 전에 세 가지 모두 신선한 명령 증거로 확인하십시오:

  1. 필요한 작업이 완료됨. 정상 아카이브의 경우 _tasks.md에 나열된 각 task_NN.md를 읽으십시오. 모든 status는 completed여야 합니다. QA 아카이브 재정의의 경우 모든 비-QA 작업이 completed여야 합니다. QA 작업은 pending 또는 failed로 남을 수 있습니다. QA 작업도 completed인 경우 최신 보고서가 여전히 부적격이어야 하며, 그렇지 않으면 재정의가 불필요하여 거부됩니다.

    명령: grep -n '^status:' <_tasks.md에-나열된-각-작업-파일>을 실행하고 출력을 유지하십시오. status: completed 이외의 값은 정상 아카이브를 차단합니다. 재정의 중에는 다른 상태의 비-QA 작업만 아카이브를 차단합니다. 해당 작업 파일의 이름을 지정하십시오.

  2. QA 통과됨. qa/의 최신 보고서는 저장소의 QA 검증기를 통과해야 합니다. 구조화된 검증을 줄 grep으로 대체하지 마십시오. Roundfix에서는 아카이브 명령과 동일한 internal/spec.QAVerdict 계약을 사용하십시오: qa-report-YYYY-MM-DD[-NN].md 파일명 계약으로 최신 보고서를 선택하고, YAML 프론트매터를 파싱하고, 지원되는 verdict를 요구하고, 차단 행 필드가 있을 때 음수가 아닌 정수여야 하며, rows_blocked_finding이 0이 아닐 때 verdict: pass를 거부하십시오. 검증기의 보고서 경로와 결과를 증거로 유지하십시오. qa/ 디렉토리 누락, 잘못된 형식의 최신 보고서 또는 통과하지 못한 평결은 정상 아카이브를 차단합니다. roundfix archive <slug> --qa-override --approval <source> --reason <text>를 통한 명시적 QA 아카이브 재정의 하에서만 진행하십시오. 아카이브 레코드를 편집하여 재정의를 기록하지 마십시오. 적격한 최신 보고서는 실패하거나 보류 중인 QA 작업을 완료로 만들지 않습니다. 재정의는 보고서가 적격하고 모든 작업이 완료된 경우에만 거부됩니다.

  3. 스펙이 자체 포함됨. docs/specs/<slug>/references/_index.md가 존재하거나 심볼릭 링크일 때 이 전제 조건을 적용하십시오. 심볼릭 링크(깨진 링크 포함)는 레거시 스펙이 아닌 잘못된 인덱스 상태입니다. 해당 경로가 존재하지도 않고 심볼릭 링크도 아닌 스펙만이 이 계약 이전의 것이며 과거 아티팩트를 개조하지 않고 통과합니다. 인덱싱된 스펙의 경우 모든 인덱싱된 path는 _index.md에 대해 상대적으로 존재해야 하며, 모든 업데이트되지 않은 source 경로는 없어야 하며, 스펙 내부의 Markdown 링크 대상이 docs/_inbox/ 또는 docs/findings/를 가리키지 않아야 합니다.

    명령: 먼저 이 링크 대상 검사를 실행하십시오. 구문은 의도적으로 인라인 또는 참조 스타일 Markdown 링크와 일치하며, 두 트리 중 하나를 단순히 언급하는 산문과 일치하지 않습니다:

    spec_dir=docs/specs/<slug>
    link_hits=$(grep --include='*.md' -RInE '(\]\([^)]*(docs/)?(_inbox|findings)/[^)]*\)|^[[:space:]]*\[[^]]+\]:[[:space:]]*<?[^[:space:]>]*(docs/)?(_inbox|findings)/)' "$spec_dir")
    link_status=$?
    if test "$link_status" -eq 0; then
      printf '%s\n' "$link_hits"
      echo "self-containment failed: rewrite each listed link at adoption step 8"
      exit 1
    fi
    test "$link_status" -eq 1 || exit "$link_status"
    

    그런 다음 모든 데이터 행을 파싱하고 검증하십시오. 인덱스는 현재 스펙에 속합니다: owner는 4자리 접두사와 같아야 하며, type은 inbox, finding 또는 backlog여야 하며, 각 source 및 path는 한 번만 나타나야 합니다. path는 _index.md에 대한 하나의 기본 이름이어야 합니다. 절대 경로, ., .., 경로 구분 기호, 심볼릭 링크는 거부하십시오. 저장소 루트에서 다음을 실행하고 정규화된 행과 진단을 증거로 유지하십시오:

    slug=<slug>
    index="docs/specs/$slug/references/_index.md"
    expected_owner=${slug%%-*}
    parsed_index=$(mktemp) || exit 1
    trap 'rm -f "$parsed_index"' EXIT HUP INT TERM
    
    if test -L "$(dirname "$index")"; then
      printf 'self-containment failed: references/ must not be a symbolic link\n' >&2
      exit 1
    fi
    
    if test -L "$index" || test ! -f "$index"; then
      printf 'self-containment failed: references/_index.md must be a regular, non-symbolic-link file\n' >&2
      exit 1
    fi
    
    awk -F '|' -v expected_owner="$expected_owner" '
    function trim(value) {
      gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
      return value
    }
    function reject(message) {
      print "self-containment failed: " message > "/dev/stderr"
      invalid = 1
    }
    function separator(value) {
      value = trim(value)
      return value ~ /^:?-{3,}:?$/
    }
    /^[[:space:]]*$/ || /^[[:space:]]*#/ { next }
    !header {
      if (NF != 7 || trim($2) != "source" || trim($3) != "type" ||
          trim($4) != "owner" || trim($5) != "adopted date" ||
          trim($6) != "path") {
        reject("_index.md must use the fixed source | type | owner | adopted date | path header")
      } else {
        header = 1
      }
      next
    }
    !divider {
      if (NF != 7 || !separator($2) || !separator($3) || !separator($4) ||
          !separator($5) || !separator($6)) {
        reject("_index.md has an invalid table separator")
      } else {
        divider = 1
      }
      next
    }
    {
      source = trim($2)
      type = trim($3)
      owner = trim($4)
      adopted = trim($5)
      path = trim($6)
      if (NF != 7 || source == "" || type == "" || owner == "" ||
          adopted == "" || path == "") {
        reject("invalid index row at line " NR ": " $0)
        next
      }
      if (type != "inbox" && type != "finding" && type != "backlog") {
        reject("type must be `inbox`, `finding`, or `backlog` at line " NR ": " type)
      }
      if (owner != expected_owner) {
        reject("owner must be " expected_owner " at line " NR ": " owner)
      }
      if (seen_source[source]++) {
        reject("duplicate source at line " NR ": " source)
      }
      if (seen_path[path]++) {
        reject("duplicate path at line " NR ": " path)
      }
      if (adopted !~ /^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) {
        reject("adopted date must be YYYY-MM-DD at line " NR ": " adopted)
      }
      if ((type == "inbox" && source !~ /^docs\/_inbox\/[^\/]+\.md$/) ||
          (type == "finding" && source !~ /^docs\/findings\/[^\/]+\.md$/) ||
          (type == "backlog" && source !~ /^docs\/backlog\/[^\/]+\.md$/)) {
        reject("source does not match type at line " NR ": " source)
      }
      print source "|" type "|" owner "|" adopted "|" path
    }
    END {
      if (!header || !divider) {
        reject("_index.md is missing its fixed table header")
      }
      if (invalid) {
        exit 1
      }
    }
    ' "$index" > "$parsed_index" || exit $?
    
    while IFS='|' read -r source type owner adopted path; do
      case "$path" in
        ""|.|..|/*|*/*|*\\*)
          printf 'self-containment failed: path must be one basename relative to `_index.md`: %s\n' "$path" >&2
          exit 1
          ;;
      esac
      source_basename=${source##*/}
      if test "$path" != "$source_basename"
    

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

marcioaltoe/roundfix

Use Roundfix to plan releases with the read-only Release Plan Command, clean CodeRabbit pull request feedback, diagnose runtime readiness with the Doctor Command, execute a Spec's Task Graph with the Implement Command, monitor Runs through the Supervisor Run Event Stream, reclaim Run storage with the GC Command, archive completed Specs, run its `--follow-up`, `--status` and `--unattended` Skill Modes, and, inside daemon-assigned Batch runs, follow the bounded Review Issue or Task resolution contract.

marcioaltoe/write-prd

Write a PRD as a durable local artifact at docs/specs/<slug>/_prd.md — research first, clarify with one multiple-choice question at a time, record decisions as ADRs, then write directly without draft-approval rounds.

marcioaltoe/write-tasks

Decompose a spec's PRD/TechSpec into a dependency-ordered task graph — vertical-slice task files plus a machine-parseable _tasks.md DAG manifest under docs/specs/<slug>/, including the authored QA gate decision, decided autonomously from the Spec and escalated only when authority, architecture, or blast radius is at stake.

marcioaltoe/write-techspec

Write the technical spec at docs/specs/<slug>/_techspec.md — explore the architecture, settle technical decisions one question at a time, record them as ADRs, and produce a build order that write-tasks can decompose. Entry point for feature work with an approved PRD, and also for refactors and bug fixes, where it mints the spec folder with a minimal _prd.md instead of requiring a product interview.

관련 스킬