CommunityCodierung & Entwicklunggithub.com

marcioaltoe/archive-spec

Archiviere eine abgeschlossene Spezifikation – überprüfe, ob alle Aufgaben erledigt, die Qualitätssicherung bestanden und die indizierten Referenzen in sich geschlossen sind, schreibe dann <slug>.md unter dem aufgelösten Archivstamm (<spec-root>/_archived/ oder docs/history/specs/ für das integrierte docs/specs-Wurzelverzeichnis) und entferne den Spec-Ordner, der in Git mit der source_revision des Datensatzes verbleibt. Wird automatisch am Ende eines Roundfix Spec Run nach einem QA-Durchlauf ausgeführt oder immer dann, wenn der Benutzer die Archivierung einer Spezifikation anfordert.

Was ist archive-spec?

Diese Fähigkeit archiviert eine abgeschlossene Spezifikation (Spec) in einem AI-Agenten-Workflow, wie er von Roundfix verwendet wird. Sie stellt sicher, dass die Spezifikation vollständig und in sich geschlossen ist, indem sie überprüft, ob alle Aufgaben erledigt sind, die Qualitätssicherung (QA) bestanden ist und alle indizierten Referenzen innerhalb der Spezifikation aufgelöst sind. Nach erfolgreicher Prüfung wird ein Archivdatensatz (ein Markdown-Dokument) in einem bestimmten Archivverzeichnis erstellt, der den Status und die Begründung der Spezifikation festhält. Der ursprüngliche Spezifikationsordner wird gelöscht, bleibt aber in der Git-Historie des Repositorys erhalten. Die Fähigkeit unterstützt verschiedene Szenarien, darunter eine normale Archivierung, eine QA-Überschreibung für Spezifikationen, die die QA nicht bestanden haben, und eine Stornierung von Spezifikationen, die nicht ausgeliefert werden. Sie behandelt auch die Umverlinkung von Referenzen, um die Selbstständigkeit des Archivs zu gewährleisten, und setzt strenge Vorbedingungen durch, um die Datenintegrität zu wahren.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/marcioaltoe/roundfix/tree/HEAD/skills/archive-spec

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Spezifikation archivieren

Archiviere eine abgeschlossene Spezifikation, indem du <slug>.md unter dem aufgelösten Archivstamm schreibst und <resolved-spec-root>/<slug>/ entfernst, das in Git bei der source_revision des Datensatzes verbleibt. Die Quelle ist das konfigurierte Spec-Wurzelverzeichnis; das Ziel ist sein aufgelöster Archivstamm – docs/history/specs/ für das integrierte docs/specs-Wurzelverzeichnis oder <spec-root>/_archived/ für ein externes oder nicht standardmäßiges Wurzelverzeichnis, entsprechend dem Ziel von roundfix archive. Eine normale Archivierung bedeutet implementiert, verifiziert und in sich geschlossen – jede Aufgabe erledigt, QA bestanden, wenn der Aufgaben-Graph ein QA-Gate erstellt, und jeder indizierte Verweis im Besitz der Spezifikation. Eine QA-Archivierungsüberschreibung hält die explizite Ausnahme fest, ohne eine Verifizierung zu beanspruchen. Nach jeder Entscheidung trennt ein ls <spec-root>/ die aktive Arbeit von der Historie, und das Archiv bleibt durchsuchbar als Aufzeichnung dessen, was gebaut wurde und warum.

Der Auslöser ist der Spezifikationsabschluss, nicht die Veröffentlichung: Führe dies automatisch am Ende eines Roundfix Spec Run aus, sobald das QA-Gate bestanden ist, oder immer dann, wenn der Benutzer es anfordert. Merge und Release sind separate, benutzergesteuerte Schritte – der Archiv-Commit reist einfach mit dem Branch und wird innerhalb des eigenen PR des Features ausgeliefert.

Archiv-Umverlinkung

Bevor der Archivdatensatz geschrieben wird, führt die Archivierung eine Archiv-Umverlinkung durch. Sie befördert automatisch jede zitierte, nicht zum Kern gehörende Datei, auf die ein Live-Dokument aus der Besitzer-Spezifikation verweist, nach docs/references/<basename> und schreibt dann Zitate von jedem Live-Dokument auf die beförderte Kopie um; Zitate des Spezifikationsordners oder eines Kern-Artefakts zeigen auf den Archivdatensatz. Der Datensatz listet umgeschriebene Dateien unter relinked auf, wenn welche vorhanden sind. Die Quelle behält einen Besitzer, sodass eine sekundäre Spezifikation keine Kopie benötigt (ADR-0260, ADR-0083).

Der Spezifikationsordner wird durch Löschung stillgelegt. Im kopierten Ergebnis und in jeder beförderten Kopie benennt ein Ziel innerhalb des entfernten Ordners eine beförderte Kopie oder wird zu einem Git-Locator, `<path>@<commit>`; es zeigt niemals auf den Datensatz selbst. Der Commit enthält den Pfad und ist vom Standard-Branch oder einem Tag aus erreichbar. Wenn ein solcher Commit nicht existiert, benennt der Locator den Pfad und den Pull-Request des Datensatzes. Andere Ziele behalten ihr Repository-Ziel bei (ADR-0278).

Die Archivierung weigert sich zu schreiben, wenn ein Beförderungsziel bereits existiert, wenn zwei Beförderungen einen Basisnamen gemeinsam haben oder wenn ein Live-Dokument, das umgeschrieben werden soll, nicht committete Änderungen bei HEAD aufweist. Zitate in Dateien, die keine Live-Dokumente sind, oder Zitate, die nach dem Umschreiben verbleiben, sind Warnungen, die die Datei, Zeile und das Ziel nennen; die Archivierung belässt diese Dateien unverändert.

Squash-Merges

Ein Squash-Merge behält source_revision nur im Head-Ref des Pull-Requests; der Datensatz nennt diesen Pull-Request in pull_request.

Deklinierte QA-Erklärung

Ein Aufgaben-Graph, der qa: declined mit einer nicht-leeren qa_reason deklariert, archiviert, sobald jede Aufgabe abgeschlossen ist, ohne einen QA-Bericht und ohne Überschreibung, und sein Archivdatensatz hat die Disposition no-qa. --qa-override wird für eine solche Spezifikation verweigert. Jede andere Archivierungsvorbedingung gilt weiterhin.

QA-Erledigung

Das gleiche Ergebnis erledigt die verfasste qa-Aufgabe und bestimmt, was die Archivierung hinterlässt:

ErgebnisErledigtArchiviert
passErledigt die QA-Aufgabe als completed und macht die Spezifikation archivierungsfähig, wenn der Bericht keine unzulässigen blockierten Zeilen enthält.Der Archivdatensatz, der den QA-Bericht und das Urteil nennt; die Spezifikation, ihr QA-Bericht und die Beweise bleiben in Git bei der source_revision des Datensatzes.
qualifizierend deklariert partialErledigt die QA-Aufgabe als completed, wenn keine Zeile fehlgeschlagen, übersprungen oder durch einen Fund blockiert ist, jede als blockiert deklarierte Zeile durch eine passende ## Unreachable Acceptance-Deklaration abgedeckt ist und jede umgebungsblockierte Zeile die Pre-PR Pull-Request-Zeile ist, aufgezeichnet als blocked (environment: no open Pull Request) mit der Pull-Request-Zeile in ihrer Herkunft, oder eine Außenbeweis-Zeile, die die Run-Sandbox nicht erreichen konnte, aufgezeichnet als blocked (environment: network denied: <host>) mit der Außenbeweis-Zeile in ihrer Herkunft. Keine der Zeilen benötigt eine Unreachable Acceptance-Deklaration, und ein Teil, dessen einzige unerfüllte Zeilen solche Zeilen sind, qualifiziert.Der Archivdatensatz, der den QA-Bericht und das Urteil nennt und den satisfied-by-Datensatz der Deklarationen als unproven führt; die Spezifikation, ihr QA-Bericht und die Beweise bleiben in Git bei der source_revision des Datensatzes.
environment-blockedBelässt die Zeile blockiert; der Bericht kann sich dennoch als pass erledigen, wenn gleichwertige Beweise die Umgebungsrichtlinie erfüllen.Nichts für sich; ein qualifizierender Bericht kann die Spezifikation archivieren.
failedBelässt die QA-Aufgabe ungelöst und verweigert die Archivierung, es sei denn, eine autorisierte Überschreibung liegt vor.Nichts.
missingBelässt die QA-Aufgabe ungelöst und verweigert die Archivierung, es sei denn, eine autorisierte Überschreibung liegt vor.Nichts.
overrideÄndert den QA-Aufgabenstatus oder das Berichtsurteil nicht; erledigt die Archivierung als explizit autorisiert trotz fehlgeschlagener oder fehlender QA.Der Archivdatensatz mit qa_override, qa_override_approval, qa_override_reason, qa_override_qa_outcome, qa_override_qa_task_status wenn die QA-Aufgabe unvollständig ist, und qa_override_revision; die QA-Aufgabe und Berichte bleiben unverändert in Git bei der source_revision des Datensatzes.

Zeilen, die die Autorisierung der Spezifikation offline hält

Das qualifizierende deklarierte partial oben akzeptiert auch eine Außenbeweis-Zeile, die das Gate nicht nachgeschlagen hat, weil die eigene Autorisierung der Spezifikation diesen Nachschlag verbietet, aufgezeichnet als blocked (environment: <subject> prohibited by Spec authorization) mit der Außenbeweis-Zeile in ihrer Herkunft. Das Subjekt nennt, was die Autorisierung verbietet, in ihren Worten: network für einen Netzwerknachschlag oder another repository; es ist 1 bis 80 Zeichen lang und enthält keine Klammern. Wie die netzwerkverweigerte Zeile entscheidet sie niemals über ein qualifizierendes Teil und benötigt keine Unreachable Acceptance-Deklaration, eine Zeile zählt höchstens zu einer ausgenommenen Art, und die Erledigung, roundfix qa-report accept und roundfix archive lesen es durch dieselbe Richtlinie (ADR-0276, ADR-0335).

Eine Spezifikation stornieren

Eine Spezifikation, die nicht ausgeliefert wird, wird mit roundfix cancel <slug> --reason <text> storniert, niemals von Hand gelöscht. Der Befehl schreibt einen Archivdatensatz mit der Disposition cancelled, gibt jede übernommene Backlog-Eintrag nach docs/backlog/ mit status: open und jeden übernommenen Fund nach docs/findings/ mit status: pending zurück und entfernt dann den Spezifikationsordner, während seine Bytes in Git bei source_revision bleiben. Ein stornierter Datensatz erfüllt niemals eine Voraussetzung, ersetzt niemals eine andere Spezifikation und wird von der Lieferwiederholung verweigert.

Ignorierte Dateien und eine fehlgeschlagene Entfernung

Der Archivierungsbefehl und der Stornierungsbefehl verweigern die Ausführung, während Git irgendeine Datei im Spezifikationsordner ignoriert. Jeder Befehl listet jede ignorierte Datei auf und schreibt nichts. Der Bediener muss jede Datei entfernen oder mit git add -f committen und dann wiederholen.

Wenn die endgültige Entfernung des Spezifikationsordners fehlschlägt, behalten beide Befehle jedes Schreiben, beenden mit 1 und geben den Befehl aus, der die Entfernung abschließt: chmod -R u+w '<folder>' && rm -rf '<folder>'.

Vorbedingungen – verifizieren, nicht vertrauen

Überprüfe alle drei mit frischem Befehlsnachweis, bevor du etwas anfasst:

  1. Erforderliche Aufgaben abgeschlossen. Für eine normale Archivierung lese jede task_NN.md, die in _tasks.md aufgeführt ist; jeder status muss completed sein. Für eine QA-Archivierungsüberschreibung muss jede Nicht-QA-Aufgabe completed sein; die QA-Aufgabe kann pending oder failed bleiben. Wenn die QA-Aufgabe auch completed ist, muss der neueste Bericht unzulässig bleiben oder die Überschreibung ist unnötig und wird verweigert.

    Befehl: führe grep -n '^status:' <each-task-file-listed-in-_tasks.md> aus und behalte seine Ausgabe. Jeder andere Wert als status: completed blockiert eine normale Archivierung. Während einer Überschreibung blockiert nur eine Nicht-QA-Aufgabe mit einem anderen Status die Archivierung; nenne diese Aufgabendatei.

  2. QA bestanden. Der neueste Bericht in qa/ muss den QA-Verifizierer des Repositorys bestehen. Ersetze keine Zeilensuche durch eine strukturierte Validierung. Verwende in Roundfix denselben internal/spec.QAVerdict-Vertrag wie der Archivierungsbefehl: wähle den neuesten Bericht nach dem Dateinamenvertrag qa-report-YYYY-MM-DD[-NN].md, parse sein YAML-Frontmatter, erfordere ein unterstütztes verdict, erfordere, dass beide blockierten Zeilenfelder nicht-negative ganze Zahlen sind, wenn vorhanden, und lehne verdict: pass ab, wenn rows_blocked_finding ungleich Null ist. Behalte den Berichtspfad und das Ergebnis des Verifizierers als Nachweis. Ein fehlendes qa/-Verzeichnis, ein fehlerhafter neuester Bericht oder ein nicht bestehendes Urteil blockiert die normale Archivierung. Fahre nur unter einer expliziten QA-Archivierungsüberschreibung fort, die durch roundfix archive <slug> --qa-override --approval <source> --reason <text> durchgeführt wird. Zeichne die Überschreibung niemals durch Bearbeiten des Archivdatensatzes auf. Ein qualifizierender neuester Bericht macht eine fehlgeschlagene oder ausstehende QA-Aufgabe nicht abgeschlossen; die Überschreibung wird nur verweigert, wenn der Bericht qualifiziert und jede Aufgabe abgeschlossen ist.

  3. Die Spezifikation ist in sich geschlossen. Wende diese Vorbedingung an, wenn docs/specs/<slug>/references/_index.md existiert oder ein symbolischer Link ist; ein symbolischer Link, einschließlich eines defekten, ist ein ungültiger Indexzustand und keine Legacy-Spezifikation. Nur eine Spezifikation, bei der dieser Pfad weder existiert noch ein symbolischer Link ist, stammt aus der Zeit vor diesem Vertrag und besteht ohne Nachrüstung historischer Artefakte. Für eine indizierte Spezifikation muss jeder indizierte path relativ zu _index.md existieren, jeder nie aktualisierte source-Pfad muss abwesend sein, und kein Markdown-Linkziel innerhalb der Spezifikation darf auf docs/_inbox/ oder docs/findings/ zeigen.

    Befehle: führe zuerst diese Linkzielprüfung durch; ihre Syntax stimmt absichtlich mit Inline- oder Referenzstil-Markdown-Links überein, nicht mit Prosa, die lediglich einen der beiden Bäume nennt:

    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 "Selbstständigkeit fehlgeschlagen: schreibe jeden aufgeführten Link bei Übernahmeschritt 8 um"
      exit 1
    fi
    test "$link_status" -eq 1 || exit "$link_status"
    

    Dann parse und validiere jede Datenzeile. Der Index gehört zur aktuellen Spezifikation: owner muss gleich ihrem vierstelligen Präfix sein, type muss inbox, finding oder backlog sein, und jeder source und path darf nur einmal vorkommen. Ein path muss ein Basisname relativ zu _index.md sein; lehne absolute Pfade, ., .., Pfadtrennzeichen und symbolische Links ab, anstatt Traversierung oder einen Link außerhalb von references/ zu erlauben. Führe Folgendes vom Repository-Stamm aus und behalte die normalisierten Zeilen sowie alle Diagnosen als Nachweis:

    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 'Selbstständigkeit fehlgeschlagen: references/ darf kein symbolischer Link sein\n' >&2
      exit 1
    fi
    
    if test -L "$index" || test ! -f "$index"; then
      printf 'Selbstständigkeit fehlgeschlagen: references/_index.md muss eine reguläre, nicht symbolische Linkdatei sein\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 "Selbstständigkeit fehlgeschlagen: " 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 muss den festen Header source | type | owner | adopted date | path verwenden")
      } else {
        header = 1
      }
      next
    }
    !divider {
      if (NF != 7 || !separator($2) || !separator($3) || !separator($4) ||
          !separator($5) || !separator($6)) {
        reject("_index.md hat einen ungültigen Tabellentrenner")
      } 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("ungültige Indexzeile bei Zeile " NR ": " $0)
        next
      }
      if (type != "inbox" && type != "finding" && type != "backlog") {
        reject("type muss `inbox`, `finding` oder `backlog` sein bei Zeile " NR ": " type)
      }
      if (owner != expected_owner) {
        reject("owner muss " expected_owner " sein bei Zeile " NR ": " owner)
      }
      if (seen_source[source]++) {
        reject("doppelter source bei Zeile " NR ": " source)
      }
      if (seen_path[path]++) {
        reject("doppelter path bei Zeile " NR ": " path)
      }
      if (adopted !~ /^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) {
        reject("adopted date muss YYYY-MM-DD sein bei Zeile " NR ": " adopted)
      }
      if ((type == "inbox" && source !~ /^docs\/_inbox\/[^\/]+\.md$/) ||
          (type == "finding" && source !~ /^docs\/findings\/[^\/]+\.md$/) ||
          (type == "backlog" && source !~ /^docs\/backlog\/[^\/]+\.md$/)) {
        reject("source stimmt nicht mit type überein bei Zeile " NR ": " source)
      }
      print source "|" type "|" owner "|" adopted "|" path
    }
    END {
      if (!header || !divider) {
        reject("_index.md fehlt der feste Tabellenheader")
      }
      if (invalid) {
        exit 1
      }
    }
    ' "$index" > "$parsed_index" || exit $?
    
    while IFS='|' read -r source type owner adopted path; do
      case "$path" in
        ""|.|..|/*|*/*|*\\*)
          printf 'Selbstständigkeit fehlgeschlagen: path muss ein Basisname relativ zu `_index.md` sein: %s\n' "$path" >&2
          exit 1
          ;;
      esac
      source_basename=${source##*/}
      if test "$path" != "$source_basename"
    
    ...
    
    [für die Übersetzung gekürzt]
    

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.

Verwandte Skills