Archive — Move completed plans and roadmap snapshots
Archive completed single-file plans and ultra bundle directories from
paths.plans/ into paths.archive/plans/ and
optionally trim closed milestones from ROADMAP.md into dated snapshots
under paths.archive/roadmap/.
Workflow
Step 0: Load Config
Read .ai-factory/config.yaml if it exists to resolve:
paths.plans (default: .ai-factory/plans/)
paths.archive (default: .ai-factory/archive/)
paths.plan (default: .ai-factory/PLAN.md)
paths.fix_plan (default: .ai-factory/FIX_PLAN.md)
paths.roadmap (default: .ai-factory/ROADMAP.md)
workflow.plan_id_format (default: slug) — active values: slug and
sequential. timestamp and uuid are reserved and behave like slug.
Treat any unknown value as slug.
language.ui for user-facing prompts
If config doesn't exist, use defaults listed above.
Read .ai-factory/skill-context/aif-archive/SKILL.md if it exists —
project-specific overrides take priority over general instructions.
Step 1: Parse Arguments
Extract mode from arguments:
(no args) → interactive mode: scan, show completable plans, ask which to archive
list → show archive contents, then STOP
--roadmap → trim closed milestones from ROADMAP.md into a snapshot
--all → archive ALL completed plans (ask confirmation first)
<plan-name> → archive a specific plan by filename or partial stem match
Parsing rules:
list and --roadmap are mutually exclusive with <plan-name> and --all
- If multiple conflicting modes are given, emit error and STOP
<plan-name> can be:
- full filename:
0005_feature-auth.md
- ultra directory/entrypoint:
0005_feature-auth or 0005_feature-auth/index.md
- stem without extension:
0005_feature-auth
- partial match:
feature-auth (must match exactly one plan)
Step 2: Execute Mode
Mode: Interactive (no arguments)
- Scan
paths.plans/ for root *.md files and direct child */index.md
candidates using Glob. Exclude the resolved paths.plan and
paths.fix_plan; count a directory only when its entrypoint declares
<!-- aif:plan-mode:ultra -->. Do not treat phase files or unrelated directories as plans.
- For each artifact, read the entrypoint's
## Tasks section.
- Determine completion: a plan is completed when ALL task checkboxes
are
- [x]. Plans with any - [ ] are incomplete.
- If no completed plans found:
No completed plans found in <paths.plans/>.
→ STOP.
- Display completed plans:
Completed plans ready to archive:
1. 0001_feature-alpha.md (completed 2026-05-20)
2. 0003_feature-gamma.md (completed 2026-05-24)
Incomplete plans (skipped):
- 0005_feature-delta.md (3/7 tasks done)
- Ask which to archive:
AskUserQuestion: Which plans to archive?
Options:
1. All completed plans listed above
2. Select specific plans (enter numbers)
3. Cancel
- Execute archive operation for selected plans (see Archive Operation).
Mode: list
- Check if
<paths.archive>/plans/ exists.
- If not:
Archive is empty. No plans have been archived yet. → STOP.
- Glob root
<paths.archive>/plans/*.md files and direct child
<paths.archive>/plans/*/index.md entrypoints containing exactly one
<!-- aif:plan-mode:ultra -->.
- For each archived artifact, extract its date from YAML frontmatter (full
plans) or
<!-- aif:archived:YYYY-MM-DD --> immediately after the ultra
marker (index.md).
- Display:
Archived plans (<paths.archive>/plans/):
1. 0001_feature-alpha.md (archived: 2026-05-20)
2. 0003_feature-gamma.md (archived: 2026-05-24)
Total: 2 archived plans
- Check
<paths.archive>/roadmap/ for snapshots and list them if present:Roadmap snapshots (<paths.archive>/roadmap/):
1. 2026-05-20_roadmap-snapshot.md (3 milestones)
- STOP.
Mode: <plan-name>
- Resolve
<plan-name> to one artifact in paths.plans/:
- Try exact root filename, exact ultra directory, or exact
*/index.md match
- Then try with
.md extension appended
- Then try partial match against root filenames and ultra directory names
- If no match:
Plan not found: <plan-name> with suggestions → STOP.
- If multiple matches: list them and ask user to be more specific → STOP.
- For a directory match, read the entrypoint and require
<!-- aif:plan-mode:ultra -->;
otherwise it is not an archivable AI Factory plan.
- Read the matched entrypoint and check completion status.
- If incomplete:
Plan <filename> is not completed (5/8 tasks done).
Only completed plans can be archived.
→ STOP.
- Execute archive operation (see Archive Operation).
Mode: --all
- Scan
paths.plans/ for completed plans (same logic as interactive mode).
- If no completed plans: inform and STOP.
- Display list and ask confirmation:
AskUserQuestion: Archive ALL completed plans?
1. 0001_feature-alpha.md
2. 0003_feature-gamma.md
Options:
1. Yes, archive all 2 plans
2. Cancel
- Execute archive operation for all confirmed plans.
Mode: --roadmap
- Read the resolved
paths.roadmap file.
- If it doesn't exist:
No ROADMAP.md found at <path>. → STOP.
- Find milestones with
- [x] checkbox (completed milestones).
- If no completed milestones:
No closed milestones to archive. → STOP.
- Display and ask confirmation:
Closed milestones found in ROADMAP.md:
- [x] MVP Launch — core features shipped
- [x] Beta Testing — user feedback round
AskUserQuestion: Trim these milestones from ROADMAP.md into a snapshot?
Options:
1. Yes, create snapshot and trim
2. Cancel
- Create snapshot:
mkdir -p <paths.archive>/roadmap/
- Determine snapshot filename:
YYYY-MM-DD_roadmap-snapshot.md
- Collision check. Before writing, verify the destination does not already exist:
Read <paths.archive>/roadmap/YYYY-MM-DD_roadmap-snapshot.md
If the file exists, append a counter suffix to produce a non-colliding name:
YYYY-MM-DD_roadmap-snapshot-2.md, YYYY-MM-DD_roadmap-snapshot-3.md, etc.
Check each candidate until a free name is found.
- Write the resolved snapshot path with:
# Roadmap Snapshot — YYYY-MM-DD
Archived from: <paths.roadmap>
## Archived Milestones
- [x] MVP Launch — core features shipped
- [x] Beta Testing — user feedback round
- Edit
paths.roadmap: remove the archived - [x] lines from the
## Milestones section. Keep the ## Completed table if it exists.
Do NOT edit paths.roadmap unless the snapshot write in step 6 succeeded.
- Logging:
INFO [aif-archive] roadmap snapshot: <resolved-path> (<N> milestones archived)
Archive Operation (plans)
For each plan artifact to archive:
mkdir -p <paths.archive>/plans/
Collision check. Before moving, verify the destination does not already exist:
Read <paths.archive>/plans/<original-name> # full plan
Read <paths.archive>/plans/<original-name>/index.md # ultra bundle
If the file exists:
- Single plan (interactive or
<plan-name>): STOP with an error:ERROR [aif-archive] destination already exists: <paths.archive>/plans/<filename>
A previously archived plan has the same filename. This can happen when
sequential numbering reuses a freed number after archiving.
To resolve: rename the existing archive file, or delete it if it is no
longer needed.
- Batch (
--all): SKIP this plan with a warning, continue to the next:WARN [aif-archive] skipped: <filename> — destination already exists
Do NOT overwrite in either case.
Validate an ultra bundle before moving it. Read index.md and require:
- exactly one
<!-- aif:plan-mode:ultra -->, as the first line or immediately
after an optional first-line <!-- handoff:task:<id> -->;
- a non-empty
## Phase Index;
- every linked phase path is a direct child of the bundle and exists.
A malformed bundle is not safe to archive. STOP for a single plan, or emit
WARN [aif-archive] skipped malformed ultra bundle: <filename> and continue
in --all mode.
Move the complete source artifact into the archive path first:
mv <paths.plans>/<name> <paths.archive>/plans/<name>
For ultra, <name> is the whole directory, so all linked phase files move
together. This atomically removes the plan from active discovery.
Add archive metadata to the moved entrypoint using Edit (index.md for
ultra, the moved plan file otherwise).
For ultra, preserve the canonical header and insert this comment immediately
after <!-- aif:plan-mode:ultra -->:
<!-- aif:archived:YYYY-MM-DD -->
Never prepend YAML or move the ultra marker: it must remain the first line or
immediately after an optional first-line Handoff annotation.
For a full plan, if the file already has YAML frontmatter (between ---
markers at the top):
- Use
Edit to add archived: YYYY-MM-DD field inside the existing frontmatter block.
If the full plan has no YAML frontmatter:
The original filename or directory name is preserved exactly, including any
sequential NNNN_ prefix.
Logging: INFO [aif-archive] archived: <filename> -> <paths.archive>/plans/<filename>
After all plans are processed, display summary:
## Archive Complete
Archived N plan(s) to <paths.archive>/plans/:
- 0001_feature-alpha.md
- 0003_feature-gamma.md
Skipped: K (destination already exists)
- 0002_feature-beta.md
Plans directory: <paths.plans/> (M plans remaining)
Omit the "Skipped" section when K is 0.
Completion Detection Algorithm
A plan is completed when:
- The plan entrypoint contains a
## Tasks section (case-insensitive header match).
- ALL lines matching the pattern
- [x] or - [ ] within the Tasks section
(and its subsections) are checked: every checkbox is - [x].
- If the Tasks section contains zero checkboxes, the plan is considered
not completed (empty plans are not archivable).
Edge cases:
- Checkboxes outside
## Tasks (e.g., in ## Settings or ## Commit Plan)
are NOT counted for completion.
- Nested checkboxes (indented
- [x]) ARE counted.
- Plans whose entrypoint lacks
## Tasks are not archivable — emit
WARN [aif-archive] <name> has no ## Tasks section; skipping.
Completion Date Inference
When displaying "completed" dates in interactive mode:
- Check YAML frontmatter for a
completed field — use if present.
- Fall back to git:
git log -1 --format=%ai -- <plan-file> to get last
modification date.
- Fall back to filesystem: entrypoint modification time.
Important Rules
- Never archive incomplete plans — all tasks must be
- [x]
- Always ask confirmation before
--all and --roadmap operations
- Preserve original file/directory names — including sequential
NNNN_ prefix
- Add archive metadata — YAML frontmatter for full plans; the stable
<!-- aif:archived:YYYY-MM-DD --> comment after the ultra marker for bundles
- Do not modify fast plans (
paths.plan) or fix plans (paths.fix_plan) —
those are single-file artifacts managed by /aif-implement and /aif-fix
- Do not count archived plans for sequential numbering — archived plans
live in
paths.archive/plans/, not paths.plans/, so /aif-plan
sequential scan does not include them
Artifact Ownership
- Owns:
paths.archive/plans/*.md, archived ultra bundle directories, and paths.archive/roadmap/*.md
- Reads: root
paths.plans/*.md, direct child ultra */index.md + linked phases, and paths.roadmap
- Modifies:
paths.roadmap (only with --roadmap, only after confirmation)
- Does NOT touch:
paths.plan, paths.fix_plan, paths.description,
paths.architecture, paths.rules_file
1---2name: aif-archive3description: Archive completed plans and roadmap milestones. Moves finished plans to the archive directory and optionally trims closed milestones from ROADMAP.md. Use when user says "archive plans", "clean up plans", "archive completed", or "trim roadmap".4---56# Archive — Move completed plans and roadmap snapshots78Archive completed single-file plans and ultra bundle directories from9`paths.plans/` into `paths.archive/plans/` and10optionally trim closed milestones from `ROADMAP.md` into dated snapshots11under `paths.archive/roadmap/`.1213## Workflow1415### Step 0: Load Config1617Read `.ai-factory/config.yaml` if it exists to resolve:1819- `paths.plans` (default: `.ai-factory/plans/`)20- `paths.archive` (default: `.ai-factory/archive/`)21- `paths.plan` (default: `.ai-factory/PLAN.md`)22- `paths.fix_plan` (default: `.ai-factory/FIX_PLAN.md`)23- `paths.roadmap` (default: `.ai-factory/ROADMAP.md`)24- `workflow.plan_id_format` (default: `slug`) — active values: `slug` and25 `sequential`. `timestamp` and `uuid` are **reserved** and behave like `slug`.26 Treat any unknown value as `slug`.27- `language.ui` for user-facing prompts2829If config doesn't exist, use defaults listed above.3031Read `.ai-factory/skill-context/aif-archive/SKILL.md` if it exists —32project-specific overrides take priority over general instructions.3334### Step 1: Parse Arguments3536Extract mode from arguments:3738```39(no args) → interactive mode: scan, show completable plans, ask which to archive40list → show archive contents, then STOP41--roadmap → trim closed milestones from ROADMAP.md into a snapshot42--all → archive ALL completed plans (ask confirmation first)43<plan-name> → archive a specific plan by filename or partial stem match44```4546Parsing rules:4748- `list` and `--roadmap` are mutually exclusive with `<plan-name>` and `--all`49- If multiple conflicting modes are given, emit error and STOP50- `<plan-name>` can be:51 - full filename: `0005_feature-auth.md`52 - ultra directory/entrypoint: `0005_feature-auth` or `0005_feature-auth/index.md`53 - stem without extension: `0005_feature-auth`54 - partial match: `feature-auth` (must match exactly one plan)5556### Step 2: Execute Mode5758---5960#### Mode: Interactive (no arguments)61621. Scan `paths.plans/` for root `*.md` files and direct child `*/index.md`63 candidates using `Glob`. Exclude the resolved `paths.plan` and64 `paths.fix_plan`; count a directory only when its entrypoint declares65 `<!-- aif:plan-mode:ultra -->`. Do not treat phase files or unrelated directories as plans.662. For each artifact, read the entrypoint's `## Tasks` section.673. Determine completion: a plan is **completed** when ALL task checkboxes68 are `- [x]`. Plans with any `- [ ]` are incomplete.694. If no completed plans found:70 ```71 No completed plans found in <paths.plans/>.72 ```73 → STOP.745. Display completed plans:75 ```76 Completed plans ready to archive:7778 1. 0001_feature-alpha.md (completed 2026-05-20)79 2. 0003_feature-gamma.md (completed 2026-05-24)8081 Incomplete plans (skipped):82 - 0005_feature-delta.md (3/7 tasks done)83 ```846. Ask which to archive:85 ```86 AskUserQuestion: Which plans to archive?8788 Options:89 1. All completed plans listed above90 2. Select specific plans (enter numbers)91 3. Cancel92 ```937. Execute archive operation for selected plans (see **Archive Operation**).9495---9697#### Mode: `list`98991. Check if `<paths.archive>/plans/` exists.1002. If not: `Archive is empty. No plans have been archived yet.` → STOP.1013. Glob root `<paths.archive>/plans/*.md` files and direct child102 `<paths.archive>/plans/*/index.md` entrypoints containing exactly one103 `<!-- aif:plan-mode:ultra -->`.1044. For each archived artifact, extract its date from YAML frontmatter (full105 plans) or `<!-- aif:archived:YYYY-MM-DD -->` immediately after the ultra106 marker (`index.md`).1075. Display:108 ```109 Archived plans (<paths.archive>/plans/):110111 1. 0001_feature-alpha.md (archived: 2026-05-20)112 2. 0003_feature-gamma.md (archived: 2026-05-24)113114 Total: 2 archived plans115 ```1166. Check `<paths.archive>/roadmap/` for snapshots and list them if present:117 ```118 Roadmap snapshots (<paths.archive>/roadmap/):119120 1. 2026-05-20_roadmap-snapshot.md (3 milestones)121 ```1227. STOP.123124---125126#### Mode: `<plan-name>`1271281. Resolve `<plan-name>` to one artifact in `paths.plans/`:129 - Try exact root filename, exact ultra directory, or exact `*/index.md` match130 - Then try with `.md` extension appended131 - Then try partial match against root filenames and ultra directory names1322. If no match: `Plan not found: <plan-name>` with suggestions → STOP.1333. If multiple matches: list them and ask user to be more specific → STOP.1344. For a directory match, read the entrypoint and require135 `<!-- aif:plan-mode:ultra -->`;136 otherwise it is not an archivable AI Factory plan.1375. Read the matched entrypoint and check completion status.1386. If incomplete:139 ```140 Plan <filename> is not completed (5/8 tasks done).141 Only completed plans can be archived.142 ```143 → STOP.1447. Execute archive operation (see **Archive Operation**).145146---147148#### Mode: `--all`1491501. Scan `paths.plans/` for completed plans (same logic as interactive mode).1512. If no completed plans: inform and STOP.1523. Display list and ask confirmation:153 ```154 AskUserQuestion: Archive ALL completed plans?155156 1. 0001_feature-alpha.md157 2. 0003_feature-gamma.md158159 Options:160 1. Yes, archive all 2 plans161 2. Cancel162 ```1634. Execute archive operation for all confirmed plans.164165---166167#### Mode: `--roadmap`1681691. Read the resolved `paths.roadmap` file.1702. If it doesn't exist: `No ROADMAP.md found at <path>.` → STOP.1713. Find milestones with `- [x]` checkbox (completed milestones).1724. If no completed milestones: `No closed milestones to archive.` → STOP.1735. Display and ask confirmation:174 ```175 Closed milestones found in ROADMAP.md:176177 - [x] MVP Launch — core features shipped178 - [x] Beta Testing — user feedback round179180 AskUserQuestion: Trim these milestones from ROADMAP.md into a snapshot?181182 Options:183 1. Yes, create snapshot and trim184 2. Cancel185 ```1866. Create snapshot:187 - `mkdir -p <paths.archive>/roadmap/`188 - Determine snapshot filename: `YYYY-MM-DD_roadmap-snapshot.md`189 - **Collision check.** Before writing, verify the destination does not already exist:190 ```191 Read <paths.archive>/roadmap/YYYY-MM-DD_roadmap-snapshot.md192 ```193 If the file exists, append a counter suffix to produce a non-colliding name:194 `YYYY-MM-DD_roadmap-snapshot-2.md`, `YYYY-MM-DD_roadmap-snapshot-3.md`, etc.195 Check each candidate until a free name is found.196 - Write the resolved snapshot path with:197 ```markdown198 # Roadmap Snapshot — YYYY-MM-DD199200 Archived from: <paths.roadmap>201202 ## Archived Milestones203204 - [x] MVP Launch — core features shipped205 - [x] Beta Testing — user feedback round206 ```2077. Edit `paths.roadmap`: remove the archived `- [x]` lines from the208 `## Milestones` section. Keep the `## Completed` table if it exists.209 **Do NOT edit `paths.roadmap` unless the snapshot write in step 6 succeeded.**2108. Logging: `INFO [aif-archive] roadmap snapshot: <resolved-path> (<N> milestones archived)`211212---213214### Archive Operation (plans)215216For each plan artifact to archive:2172181. `mkdir -p <paths.archive>/plans/`2192202. **Collision check.** Before moving, verify the destination does not already exist:221 ```222 Read <paths.archive>/plans/<original-name> # full plan223 Read <paths.archive>/plans/<original-name>/index.md # ultra bundle224 ```225 If the file exists:226 - **Single plan** (interactive or `<plan-name>`): STOP with an error:227 ```228 ERROR [aif-archive] destination already exists: <paths.archive>/plans/<filename>229 A previously archived plan has the same filename. This can happen when230 sequential numbering reuses a freed number after archiving.231 To resolve: rename the existing archive file, or delete it if it is no232 longer needed.233 ```234 - **Batch** (`--all`): SKIP this plan with a warning, continue to the next:235 ```236 WARN [aif-archive] skipped: <filename> — destination already exists237 ```238 Do NOT overwrite in either case.2392403. **Validate an ultra bundle before moving it.** Read `index.md` and require:241 - exactly one `<!-- aif:plan-mode:ultra -->`, as the first line or immediately242 after an optional first-line `<!-- handoff:task:<id> -->`;243 - a non-empty `## Phase Index`;244 - every linked phase path is a direct child of the bundle and exists.245246 A malformed bundle is not safe to archive. STOP for a single plan, or emit247 `WARN [aif-archive] skipped malformed ultra bundle: <filename>` and continue248 in `--all` mode.2492504. **Move the complete source artifact** into the archive path first:251 ```bash252 mv <paths.plans>/<name> <paths.archive>/plans/<name>253 ```254 For ultra, `<name>` is the whole directory, so all linked phase files move255 together. This atomically removes the plan from active discovery.2562575. **Add archive metadata** to the moved entrypoint using `Edit` (`index.md` for258 ultra, the moved plan file otherwise).259260 For ultra, preserve the canonical header and insert this comment immediately261 after `<!-- aif:plan-mode:ultra -->`:262 ```markdown263 <!-- aif:archived:YYYY-MM-DD -->264 ```265 Never prepend YAML or move the ultra marker: it must remain the first line or266 immediately after an optional first-line Handoff annotation.267268 For a full plan, if the file already has YAML frontmatter (between `---`269 markers at the top):270 - Use `Edit` to add `archived: YYYY-MM-DD` field inside the existing frontmatter block.271272 If the full plan has no YAML frontmatter:273 - Use `Edit` to prepend a minimal frontmatter block before the first line:274 ```yaml275 ---276 archived: YYYY-MM-DD277 ---278 ```279280 The original filename or directory name is preserved exactly, including any281 sequential `NNNN_` prefix.2822836. Logging: `INFO [aif-archive] archived: <filename> -> <paths.archive>/plans/<filename>`2842857. After all plans are processed, display summary:286 ```287 ## Archive Complete288289 Archived N plan(s) to <paths.archive>/plans/:290 - 0001_feature-alpha.md291 - 0003_feature-gamma.md292293 Skipped: K (destination already exists)294 - 0002_feature-beta.md295296 Plans directory: <paths.plans/> (M plans remaining)297 ```298 Omit the "Skipped" section when K is 0.299300### Completion Detection Algorithm301302A plan is **completed** when:3033041. The plan entrypoint contains a `## Tasks` section (case-insensitive header match).3052. ALL lines matching the pattern `- [x]` or `- [ ]` within the Tasks section306 (and its subsections) are checked: every checkbox is `- [x]`.3073. If the Tasks section contains zero checkboxes, the plan is considered308 **not completed** (empty plans are not archivable).309310Edge cases:311312- Checkboxes outside `## Tasks` (e.g., in `## Settings` or `## Commit Plan`)313 are NOT counted for completion.314- Nested checkboxes (indented ` - [x]`) ARE counted.315- Plans whose entrypoint lacks `## Tasks` are not archivable — emit316 `WARN [aif-archive] <name> has no ## Tasks section; skipping`.317318### Completion Date Inference319320When displaying "completed" dates in interactive mode:3213221. Check YAML frontmatter for a `completed` field — use if present.3232. Fall back to git: `git log -1 --format=%ai -- <plan-file>` to get last324 modification date.3253. Fall back to filesystem: entrypoint modification time.326327## Important Rules3283291. **Never archive incomplete plans** — all tasks must be `- [x]`3302. **Always ask confirmation** before `--all` and `--roadmap` operations3313. **Preserve original file/directory names** — including sequential `NNNN_` prefix3324. **Add archive metadata** — YAML frontmatter for full plans; the stable333 `<!-- aif:archived:YYYY-MM-DD -->` comment after the ultra marker for bundles3345. **Do not modify fast plans** (`paths.plan`) or fix plans (`paths.fix_plan`) —335 those are single-file artifacts managed by `/aif-implement` and `/aif-fix`3366. **Do not count archived plans for sequential numbering** — archived plans337 live in `paths.archive/plans/`, not `paths.plans/`, so `/aif-plan`338 sequential scan does not include them339340## Artifact Ownership341342- **Owns:** `paths.archive/plans/*.md`, archived ultra bundle directories, and `paths.archive/roadmap/*.md`343- **Reads:** root `paths.plans/*.md`, direct child ultra `*/index.md` + linked phases, and `paths.roadmap`344- **Modifies:** `paths.roadmap` (only with `--roadmap`, only after confirmation)345- **Does NOT touch:** `paths.plan`, `paths.fix_plan`, `paths.description`,346 `paths.architecture`, `paths.rules_file`