ai-factory 2.13.1 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/cli/wizard/skill-hints.d.ts.map +1 -1
  2. package/dist/cli/wizard/skill-hints.js +1 -0
  3. package/dist/cli/wizard/skill-hints.js.map +1 -1
  4. package/package.json +2 -1
  5. package/skills/aif/SKILL.md +23 -12
  6. package/skills/aif/references/config-template.yaml +10 -0
  7. package/skills/aif/references/update-config.mjs +1 -0
  8. package/skills/aif-archive/SKILL.md +317 -0
  9. package/skills/aif-distillation/SKILL.md +32 -17
  10. package/skills/aif-distillation/examples/REQUESTS.md +59 -5
  11. package/skills/aif-distillation/references/DISTILLATION-PROTOCOL.md +53 -9
  12. package/skills/aif-distillation/references/LARGE-MATERIALS.md +26 -1
  13. package/skills/aif-distillation/references/OUTPUT-STRUCTURE.md +55 -15
  14. package/skills/aif-explore/SKILL.md +29 -4
  15. package/skills/aif-fix/SKILL.md +23 -2
  16. package/skills/aif-implement/SKILL.md +3 -0
  17. package/skills/aif-improve/SKILL.md +96 -177
  18. package/skills/aif-improve/references/CHECK-MODE.md +101 -0
  19. package/skills/aif-improve/references/EXAMPLES.md +88 -0
  20. package/skills/aif-improve/references/LIST-MODE.md +83 -0
  21. package/skills/aif-improve/references/VALIDATOR.md +89 -0
  22. package/skills/aif-plan/SKILL.md +23 -3
  23. package/skills/aif-reference/SKILL.md +22 -3
  24. package/skills/aif-review/SKILL.md +44 -17
  25. package/skills/aif-review/references/CHECK-MODE.md +109 -0
  26. package/skills/aif-review/references/SEVERITY.md +35 -0
  27. package/skills/aif-review/references/VALIDATOR.md +103 -0
  28. package/skills/aif-rules/SKILL.md +18 -2
  29. package/skills/aif-security-checklist/SKILL.md +20 -3
  30. package/skills/aif-skill-generator/SKILL.md +39 -19
  31. package/skills/aif-skill-generator/references/SECURITY-SCANNING.md +5 -3
  32. package/skills/aif-skill-generator/scripts/cleanup-blocked-skill.py +617 -0
  33. package/skills/aif-verify/SKILL.md +14 -1
@@ -1 +1 @@
1
- {"version":3,"file":"skill-hints.d.ts","sourceRoot":"","sources":["../../../src/cli/wizard/skill-hints.ts"],"names":[],"mappings":"AAyCA,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACpC,aAAa,GAAE,MAAgC,GAChD,MAAM,CAGR"}
1
+ {"version":3,"file":"skill-hints.d.ts","sourceRoot":"","sources":["../../../src/cli/wizard/skill-hints.ts"],"names":[],"mappings":"AA0CA,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACpC,aAAa,GAAE,MAAgC,GAChD,MAAM,CAGR"}
@@ -1,5 +1,6 @@
1
1
  const SKILL_HINTS = {
2
2
  'aif': 'Set up AI context',
3
+ 'aif-archive': 'Archive completed plans and roadmap',
3
4
  'aif-architecture': 'Generate architecture guide',
4
5
  'aif-best-practices': 'Clean code guidelines',
5
6
  'aif-build-automation': 'Build file automation',
@@ -1 +1 @@
1
- {"version":3,"file":"skill-hints.js","sourceRoot":"","sources":["../../../src/cli/wizard/skill-hints.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAA2B;IACxC,KAAK,EAAE,mBAAmB;IAC1B,kBAAkB,EAAE,6BAA6B;IACjD,oBAAoB,EAAE,uBAAuB;IAC7C,sBAAsB,EAAE,uBAAuB;IAC/C,QAAQ,EAAE,sBAAsB;IAChC,YAAY,EAAE,4BAA4B;IAC1C,kBAAkB,EAAE,6BAA6B;IACjD,eAAe,EAAE,0BAA0B;IAC3C,UAAU,EAAE,iCAAiC;IAC7C,YAAY,EAAE,4BAA4B;IAC1C,aAAa,EAAE,2BAA2B;IAC1C,SAAS,EAAE,2BAA2B;IACtC,cAAc,EAAE,+BAA+B;IAC/C,eAAe,EAAE,4BAA4B;IAC7C,aAAa,EAAE,+BAA+B;IAC9C,UAAU,EAAE,mCAAmC;IAC/C,UAAU,EAAE,wBAAwB;IACpC,QAAQ,EAAE,0CAA0C;IACpD,eAAe,EAAE,sCAAsC;IACvD,YAAY,EAAE,0BAA0B;IACxC,aAAa,EAAE,wBAAwB;IACvC,WAAW,EAAE,+BAA+B;IAC5C,iBAAiB,EAAE,+BAA+B;IAClD,wBAAwB,EAAE,0BAA0B;IACpD,qBAAqB,EAAE,2BAA2B;IAClD,YAAY,EAAE,oCAAoC;CACrD,CAAC;AAEF,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AACrD,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAEnC,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACjD,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACjE,OAAO,GAAG,IAAI,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IACxC,OAAO,WAAW,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,qBAAqB,CACjC,OAAe,EACf,UAAoC,EACpC,gBAAwB,uBAAuB;IAE/C,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC;IAChE,OAAO,GAAG,OAAO,IAAI,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"skill-hints.js","sourceRoot":"","sources":["../../../src/cli/wizard/skill-hints.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAA2B;IACxC,KAAK,EAAE,mBAAmB;IAC1B,aAAa,EAAE,qCAAqC;IACpD,kBAAkB,EAAE,6BAA6B;IACjD,oBAAoB,EAAE,uBAAuB;IAC7C,sBAAsB,EAAE,uBAAuB;IAC/C,QAAQ,EAAE,sBAAsB;IAChC,YAAY,EAAE,4BAA4B;IAC1C,kBAAkB,EAAE,6BAA6B;IACjD,eAAe,EAAE,0BAA0B;IAC3C,UAAU,EAAE,iCAAiC;IAC7C,YAAY,EAAE,4BAA4B;IAC1C,aAAa,EAAE,2BAA2B;IAC1C,SAAS,EAAE,2BAA2B;IACtC,cAAc,EAAE,+BAA+B;IAC/C,eAAe,EAAE,4BAA4B;IAC7C,aAAa,EAAE,+BAA+B;IAC9C,UAAU,EAAE,mCAAmC;IAC/C,UAAU,EAAE,wBAAwB;IACpC,QAAQ,EAAE,0CAA0C;IACpD,eAAe,EAAE,sCAAsC;IACvD,YAAY,EAAE,0BAA0B;IACxC,aAAa,EAAE,wBAAwB;IACvC,WAAW,EAAE,+BAA+B;IAC5C,iBAAiB,EAAE,+BAA+B;IAClD,wBAAwB,EAAE,0BAA0B;IACpD,qBAAqB,EAAE,2BAA2B;IAClD,YAAY,EAAE,oCAAoC;CACrD,CAAC;AAEF,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AACrD,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAEnC,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACjD,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACjE,OAAO,GAAG,IAAI,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IACxC,OAAO,WAAW,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,qBAAqB,CACjC,OAAe,EACf,UAAoC,EACpC,gBAAwB,uBAAuB;IAE/C,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC;IAChE,OAAO,GAAG,OAAO,IAAI,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;AACnD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-factory",
3
- "version": "2.13.1",
3
+ "version": "2.14.0",
4
4
  "type": "module",
5
5
  "description": "CLI tool for automating AI agent context setup in projects",
6
6
  "main": "dist/cli/index.js",
@@ -16,6 +16,7 @@
16
16
  "test:update": "node scripts/run-bash-test.mjs scripts/test-update.sh",
17
17
  "test:extension-schema": "node scripts/test-extension-schema.mjs",
18
18
  "test:extensions": "node scripts/run-bash-test.mjs scripts/test-extensions.sh",
19
+ "test:cleanup-helper": "node scripts/run-bash-test.mjs scripts/test-cleanup-helper.sh",
19
20
  "lint:unused": "tsc --noEmit --noUnusedLocals --noUnusedParameters",
20
21
  "lint:dead": "knip --reporter compact",
21
22
  "lint": "npm run lint:unused && npm run lint:dead",
@@ -2,7 +2,7 @@
2
2
  name: aif
3
3
  description: Set up agent context for a project. Analyzes tech stack, installs relevant skills from skills.sh, generates custom skills, and configures MCP servers. Use when starting new project, setting up AI context, or asking "set up project", "configure AI", "what skills do I need".
4
4
  argument-hint: "[project description]"
5
- allowed-tools: Read Glob Grep Write Bash(mkdir *) Bash(node *update-config.mjs*) Bash(npx skills *) Bash(python *security-scan*) Bash(rm -rf *) Skill WebFetch AskUserQuestion Questions
5
+ allowed-tools: Read Glob Grep Write Bash(mkdir *) Bash(node *update-config.mjs*) Bash(npx skills *) Bash(python3 --version) Bash(python --version) Bash(py -3 --version) Bash(py --version) Bash(python3 *security-scan.py*) Bash(python *security-scan.py*) Bash(py -3 *security-scan.py*) Bash(py *security-scan.py*) Bash(python3 *cleanup-blocked-skill.py*) Bash(python *cleanup-blocked-skill.py*) Bash(py -3 *cleanup-blocked-skill.py*) Bash(py *cleanup-blocked-skill.py*) Skill WebFetch AskUserQuestion Questions
6
6
  ---
7
7
 
8
8
  # AI Factory - Project Setup
@@ -21,19 +21,28 @@ Skills from skills.sh or any external source may contain malicious prompt inject
21
21
 
22
22
  **Python detection (required for security scanner):**
23
23
 
24
- Before running the scanner, find a working Python interpreter:
24
+ Before running the scanner, find a working Python 3 interpreter by running these version probes in order:
25
25
  ```bash
26
- PYTHON=$(command -v python3 || command -v python || echo "")
26
+ python3 --version
27
+ python --version
28
+ py -3 --version
29
+ py --version
27
30
  ```
28
31
 
29
- - If `$PYTHON` is found use it for all `python3` commands below
32
+ - Use the first command that exits successfully and reports `Python 3.x`:
33
+ - `python3 --version` → `PYTHON_CMD=(python3)`
34
+ - `python --version` → `PYTHON_CMD=(python)`
35
+ - `py -3 --version` → `PYTHON_CMD=(py -3)`
36
+ - `py --version` → `PYTHON_CMD=(py)`
37
+ - Do not use Python `-c` one-liners for this detection path. The pre-approved tool contract only covers version probes, `security-scan.py`, and `cleanup-blocked-skill.py` execution.
38
+ - If `PYTHON_CMD` is set — use that selected command for all Python scanner and cleanup helper commands below
30
39
  - If not found — ask the user via `AskUserQuestion`:
31
40
  1. Provide path to Python (e.g., `/usr/local/bin/python3.11`)
32
41
  2. Skip security scan (at your own risk — external skills won't be scanned for prompt injection)
33
42
  3. Install Python first and re-run `/aif`
34
43
 
35
44
  **Based on choice:**
36
- - "Provide path to Python" → use the provided path for all `python3` commands below
45
+ - "Provide path to Python" → verify it is Python 3, then use the provided path for scanner commands below
37
46
  - "Skip security scan" → show a clear warning: "External skills will NOT be scanned. Malicious prompt injections may go undetected." Then skip all Level 1 automated scans, but still perform Level 2 (manual semantic review).
38
47
  - "Install Python first" → **STOP**, user will re-run `/aif` after installing
39
48
 
@@ -46,10 +55,12 @@ PYTHON=$(command -v python3 || command -v python || echo "")
46
55
 
47
56
  **Level 1 — Automated scan:**
48
57
  ```bash
49
- $PYTHON ~/{{skills_dir}}/aif-skill-generator/scripts/security-scan.py <installed-skill-path>
58
+ # Example for PYTHON_CMD=(python3); use python, py -3, or py only if that was the selected Python 3 command.
59
+ python3 ~/{{skills_dir}}/aif-skill-generator/scripts/security-scan.py <installed-skill-path>
50
60
  ```
61
+ - When calling Bash, expand `PYTHON_CMD` to the selected command shape, for example `python3 ...security-scan.py` or `py -3 ...security-scan.py`; do not run arbitrary Python payloads.
51
62
  - **Exit 0** → proceed to Level 2
52
- - **Exit 1 (BLOCKED)** → Remove immediately (`rm -rf <skill-path>`), warn user. **NEVER use.**
63
+ - **Exit 1 (BLOCKED)** → Remove via cleanup helper using the same selected Python 3 command, for example `python3 ~/{{skills_dir}}/aif-skill-generator/scripts/cleanup-blocked-skill.py --skill <skill-name> --installed-path <installed-skill-path>`. Pass the **same `<installed-skill-path>` you just scanned** — do not synthesize the path from `<skill-name>` (upstream `skills` CLI sanitizes the directory name, so a logical name like `"Convex Best Practices"` lives on disk as `convex-best-practices`). The helper deletes the skill directory AND clears its entry from `skills-lock.json` so the blocked skill cannot be resurrected; `--installed-path` lets it verify physical removal and return an exact exit code. Warn user with full threat details. **NEVER use.**
53
64
  - **Exit 2 (WARNINGS)** → proceed to Level 2, include warnings
54
65
 
55
66
  **Level 2 — Semantic review (you do this yourself):**
@@ -90,8 +101,8 @@ If any rule is violated — fix the output before presenting it to the user.
90
101
  For each recommended skill:
91
102
  1. Search: npx skills search <name>
92
103
  2. If found → Install: npx skills install {{skills_cli_agent_flag}} <name>
93
- 3. SECURITY: Scan installed EXTERNAL skill (never built-in aif*) → $PYTHON security-scan.py <path>
94
- - BLOCKED? → rm -rf <path>, warn user, skip this skill
104
+ 3. SECURITY: Scan installed EXTERNAL skill (never built-in aif*) → run the selected concrete Python command with `security-scan.py <path>`
105
+ - BLOCKED? → run the selected concrete Python command with `cleanup-blocked-skill.py --skill <name> --installed-path <path>` (reuse the same <path> from step 3, NOT a synthesized {{skills_dir}}/<name>), warn user, skip this skill
95
106
  - WARNINGS? → show to user, ask confirmation
96
107
  4. If not found → Generate: /aif-skill-generator <name>
97
108
  5. Has reference URLs? → Learn: /aif-skill-generator <url1> [url2]...
@@ -368,10 +379,10 @@ Proceed? [Y/n]
368
379
  7. For each external skill from skills.sh:
369
380
  ```bash
370
381
  npx skills install {{skills_cli_agent_flag}} <name>
371
- # AUTO-SCAN: immediately after install
372
- $PYTHON ~/{{skills_dir}}/aif-skill-generator/scripts/security-scan.py <installed-path>
382
+ # AUTO-SCAN: immediately after install. Example for PYTHON_CMD=(python3).
383
+ python3 ~/{{skills_dir}}/aif-skill-generator/scripts/security-scan.py <installed-path>
373
384
  ```
374
- - Exit 1 (BLOCKED) → `rm -rf <path>`, warn user, skip this skill
385
+ - Exit 1 (BLOCKED) → run the selected concrete Python command with `~/{{skills_dir}}/aif-skill-generator/scripts/cleanup-blocked-skill.py --skill <name> --installed-path <installed-path>` (reuse the same `<installed-path>` you passed to security-scan.py — upstream `skills` sanitizes the directory name, so synthesizing it from `<name>` can miss the real folder), warn user, skip this skill
375
386
  - Exit 2 (WARNINGS) → show to user, ask confirmation
376
387
  - Exit 0 (CLEAN) → read files yourself (Level 2), verify intent, proceed
377
388
  8. Generate custom skills via `/aif-skill-generator` (pass URLs for Learn Mode when docs are available)
@@ -115,6 +115,16 @@ paths:
115
115
  # Default: .ai-factory/qa/
116
116
  qa: .ai-factory/qa/
117
117
 
118
+ # Archive directory for completed plans and roadmap snapshots.
119
+ # /aif-archive moves finished plans here (retaining original filenames,
120
+ # including any sequential NNNN_ prefix). Subdirectories:
121
+ # archive/plans/ — archived plan files
122
+ # archive/roadmap/ — dated roadmap snapshots
123
+ # Referenced by /aif-archive (owner), /aif-plan, /aif-implement,
124
+ # /aif-verify, /aif-improve.
125
+ # Default: .ai-factory/archive/
126
+ archive: .ai-factory/archive/
127
+
118
128
  # =============================================================================
119
129
  # Workflow Settings
120
130
  # =============================================================================
@@ -23,6 +23,7 @@ const SECTION_KEYS = {
23
23
  'specs',
24
24
  'rules',
25
25
  'qa',
26
+ 'archive',
26
27
  ],
27
28
  workflow: ['auto_create_dirs', 'plan_id_format', 'analyze_updates_architecture', 'architecture_updates_roadmap', 'verify_mode'],
28
29
  git: ['enabled', 'base_branch', 'create_branches', 'branch_prefix', 'skip_push_after_commit'],
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: aif-archive
3
+ description: "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
+ argument-hint: "[list | --roadmap | --all | <plan-name>]"
5
+ allowed-tools: Read Write Edit Glob Grep Bash(mv *) Bash(mkdir *) Bash(git *) AskUserQuestion
6
+ disable-model-invocation: false
7
+ metadata:
8
+ author: AI Factory
9
+ version: "1.0"
10
+ category: workflow
11
+ ---
12
+
13
+ # Archive — Move completed plans and roadmap snapshots
14
+
15
+ Archive completed plans from `paths.plans/` into `paths.archive/plans/` and
16
+ optionally trim closed milestones from `ROADMAP.md` into dated snapshots
17
+ under `paths.archive/roadmap/`.
18
+
19
+ ## Workflow
20
+
21
+ ### Step 0: Load Config
22
+
23
+ Read `.ai-factory/config.yaml` if it exists to resolve:
24
+
25
+ - `paths.plans` (default: `.ai-factory/plans/`)
26
+ - `paths.archive` (default: `.ai-factory/archive/`)
27
+ - `paths.plan` (default: `.ai-factory/PLAN.md`)
28
+ - `paths.fix_plan` (default: `.ai-factory/FIX_PLAN.md`)
29
+ - `paths.roadmap` (default: `.ai-factory/ROADMAP.md`)
30
+ - `workflow.plan_id_format` (default: `slug`) — active values: `slug` and
31
+ `sequential`. `timestamp` and `uuid` are **reserved** and behave like `slug`.
32
+ Treat any unknown value as `slug`.
33
+ - `language.ui` for user-facing prompts
34
+
35
+ If config doesn't exist, use defaults listed above.
36
+
37
+ Read `.ai-factory/skill-context/aif-archive/SKILL.md` if it exists —
38
+ project-specific overrides take priority over general instructions.
39
+
40
+ ### Step 1: Parse Arguments
41
+
42
+ Extract mode from arguments:
43
+
44
+ ```
45
+ (no args) → interactive mode: scan, show completable plans, ask which to archive
46
+ list → show archive contents, then STOP
47
+ --roadmap → trim closed milestones from ROADMAP.md into a snapshot
48
+ --all → archive ALL completed plans (ask confirmation first)
49
+ <plan-name> → archive a specific plan by filename or partial stem match
50
+ ```
51
+
52
+ Parsing rules:
53
+
54
+ - `list` and `--roadmap` are mutually exclusive with `<plan-name>` and `--all`
55
+ - If multiple conflicting modes are given, emit error and STOP
56
+ - `<plan-name>` can be:
57
+ - full filename: `0005_feature-auth.md`
58
+ - stem without extension: `0005_feature-auth`
59
+ - partial match: `feature-auth` (must match exactly one plan)
60
+
61
+ ### Step 2: Execute Mode
62
+
63
+ ---
64
+
65
+ #### Mode: Interactive (no arguments)
66
+
67
+ 1. Scan `paths.plans/` for all `*.md` files using `Glob`.
68
+ 2. For each plan file, read the `## Tasks` section.
69
+ 3. Determine completion: a plan is **completed** when ALL task checkboxes
70
+ are `- [x]`. Plans with any `- [ ]` are incomplete.
71
+ 4. If no completed plans found:
72
+ ```
73
+ No completed plans found in <paths.plans/>.
74
+ ```
75
+ → STOP.
76
+ 5. Display completed plans:
77
+ ```
78
+ Completed plans ready to archive:
79
+
80
+ 1. 0001_feature-alpha.md (completed 2026-05-20)
81
+ 2. 0003_feature-gamma.md (completed 2026-05-24)
82
+
83
+ Incomplete plans (skipped):
84
+ - 0005_feature-delta.md (3/7 tasks done)
85
+ ```
86
+ 6. Ask which to archive:
87
+ ```
88
+ AskUserQuestion: Which plans to archive?
89
+
90
+ Options:
91
+ 1. All completed plans listed above
92
+ 2. Select specific plans (enter numbers)
93
+ 3. Cancel
94
+ ```
95
+ 7. Execute archive operation for selected plans (see **Archive Operation**).
96
+
97
+ ---
98
+
99
+ #### Mode: `list`
100
+
101
+ 1. Check if `<paths.archive>/plans/` exists.
102
+ 2. If not: `Archive is empty. No plans have been archived yet.` → STOP.
103
+ 3. Glob `<paths.archive>/plans/*.md`.
104
+ 4. For each archived plan, read the YAML frontmatter to extract `archived` date.
105
+ 5. Display:
106
+ ```
107
+ Archived plans (<paths.archive>/plans/):
108
+
109
+ 1. 0001_feature-alpha.md (archived: 2026-05-20)
110
+ 2. 0003_feature-gamma.md (archived: 2026-05-24)
111
+
112
+ Total: 2 archived plans
113
+ ```
114
+ 6. Check `<paths.archive>/roadmap/` for snapshots and list them if present:
115
+ ```
116
+ Roadmap snapshots (<paths.archive>/roadmap/):
117
+
118
+ 1. 2026-05-20_roadmap-snapshot.md (3 milestones)
119
+ ```
120
+ 7. STOP.
121
+
122
+ ---
123
+
124
+ #### Mode: `<plan-name>`
125
+
126
+ 1. Resolve `<plan-name>` to a file in `paths.plans/`:
127
+ - Try exact filename match first
128
+ - Then try with `.md` extension appended
129
+ - Then try partial stem match (grep for `<plan-name>` in filenames)
130
+ 2. If no match: `Plan not found: <plan-name>` with suggestions → STOP.
131
+ 3. If multiple matches: list them and ask user to be more specific → STOP.
132
+ 4. Read the matched plan file and check completion status.
133
+ 5. If incomplete:
134
+ ```
135
+ Plan <filename> is not completed (5/8 tasks done).
136
+ Only completed plans can be archived.
137
+ ```
138
+ → STOP.
139
+ 6. Execute archive operation (see **Archive Operation**).
140
+
141
+ ---
142
+
143
+ #### Mode: `--all`
144
+
145
+ 1. Scan `paths.plans/` for completed plans (same logic as interactive mode).
146
+ 2. If no completed plans: inform and STOP.
147
+ 3. Display list and ask confirmation:
148
+ ```
149
+ AskUserQuestion: Archive ALL completed plans?
150
+
151
+ 1. 0001_feature-alpha.md
152
+ 2. 0003_feature-gamma.md
153
+
154
+ Options:
155
+ 1. Yes, archive all 2 plans
156
+ 2. Cancel
157
+ ```
158
+ 4. Execute archive operation for all confirmed plans.
159
+
160
+ ---
161
+
162
+ #### Mode: `--roadmap`
163
+
164
+ 1. Read the resolved `paths.roadmap` file.
165
+ 2. If it doesn't exist: `No ROADMAP.md found at <path>.` → STOP.
166
+ 3. Find milestones with `- [x]` checkbox (completed milestones).
167
+ 4. If no completed milestones: `No closed milestones to archive.` → STOP.
168
+ 5. Display and ask confirmation:
169
+ ```
170
+ Closed milestones found in ROADMAP.md:
171
+
172
+ - [x] MVP Launch — core features shipped
173
+ - [x] Beta Testing — user feedback round
174
+
175
+ AskUserQuestion: Trim these milestones from ROADMAP.md into a snapshot?
176
+
177
+ Options:
178
+ 1. Yes, create snapshot and trim
179
+ 2. Cancel
180
+ ```
181
+ 6. Create snapshot:
182
+ - `mkdir -p <paths.archive>/roadmap/`
183
+ - Determine snapshot filename: `YYYY-MM-DD_roadmap-snapshot.md`
184
+ - **Collision check.** Before writing, verify the destination does not already exist:
185
+ ```
186
+ Read <paths.archive>/roadmap/YYYY-MM-DD_roadmap-snapshot.md
187
+ ```
188
+ If the file exists, append a counter suffix to produce a non-colliding name:
189
+ `YYYY-MM-DD_roadmap-snapshot-2.md`, `YYYY-MM-DD_roadmap-snapshot-3.md`, etc.
190
+ Check each candidate until a free name is found.
191
+ - Write the resolved snapshot path with:
192
+ ```markdown
193
+ # Roadmap Snapshot — YYYY-MM-DD
194
+
195
+ Archived from: <paths.roadmap>
196
+
197
+ ## Archived Milestones
198
+
199
+ - [x] MVP Launch — core features shipped
200
+ - [x] Beta Testing — user feedback round
201
+ ```
202
+ 7. Edit `paths.roadmap`: remove the archived `- [x]` lines from the
203
+ `## Milestones` section. Keep the `## Completed` table if it exists.
204
+ **Do NOT edit `paths.roadmap` unless the snapshot write in step 6 succeeded.**
205
+ 8. Logging: `INFO [aif-archive] roadmap snapshot: <resolved-path> (<N> milestones archived)`
206
+
207
+ ---
208
+
209
+ ### Archive Operation (plans)
210
+
211
+ For each plan to archive:
212
+
213
+ 1. `mkdir -p <paths.archive>/plans/`
214
+
215
+ 2. **Collision check.** Before moving, verify the destination does not already exist:
216
+ ```
217
+ Read <paths.archive>/plans/<original-filename>
218
+ ```
219
+ If the file exists:
220
+ - **Single plan** (interactive or `<plan-name>`): STOP with an error:
221
+ ```
222
+ ERROR [aif-archive] destination already exists: <paths.archive>/plans/<filename>
223
+ A previously archived plan has the same filename. This can happen when
224
+ sequential numbering reuses a freed number after archiving.
225
+ To resolve: rename the existing archive file, or delete it if it is no
226
+ longer needed.
227
+ ```
228
+ - **Batch** (`--all`): SKIP this plan with a warning, continue to the next:
229
+ ```
230
+ WARN [aif-archive] skipped: <filename> — destination already exists
231
+ ```
232
+ Do NOT overwrite in either case.
233
+
234
+ 3. **Move the source file** into the archive path first:
235
+ ```bash
236
+ mv <paths.plans>/<filename> <paths.archive>/plans/<filename>
237
+ ```
238
+ This atomically removes the plan from the active directory.
239
+
240
+ 4. **Add archive metadata** to the moved file using `Edit`:
241
+
242
+ If the file already has YAML frontmatter (between `---` markers at the top):
243
+ - Use `Edit` to add `archived: YYYY-MM-DD` field inside the existing frontmatter block.
244
+
245
+ If the file has no YAML frontmatter:
246
+ - Use `Edit` to prepend a minimal frontmatter block before the first line:
247
+ ```yaml
248
+ ---
249
+ archived: YYYY-MM-DD
250
+ ---
251
+ ```
252
+
253
+ The original filename is preserved exactly, including any sequential `NNNN_` prefix.
254
+
255
+ 5. Logging: `INFO [aif-archive] archived: <filename> -> <paths.archive>/plans/<filename>`
256
+
257
+ 6. After all plans are processed, display summary:
258
+ ```
259
+ ## Archive Complete
260
+
261
+ Archived N plan(s) to <paths.archive>/plans/:
262
+ - 0001_feature-alpha.md
263
+ - 0003_feature-gamma.md
264
+
265
+ Skipped: K (destination already exists)
266
+ - 0002_feature-beta.md
267
+
268
+ Plans directory: <paths.plans/> (M plans remaining)
269
+ ```
270
+ Omit the "Skipped" section when K is 0.
271
+
272
+ ### Completion Detection Algorithm
273
+
274
+ A plan is **completed** when:
275
+
276
+ 1. The file contains a `## Tasks` section (case-insensitive header match).
277
+ 2. ALL lines matching the pattern `- [x]` or `- [ ]` within the Tasks section
278
+ (and its subsections) are checked: every checkbox is `- [x]`.
279
+ 3. If the Tasks section contains zero checkboxes, the plan is considered
280
+ **not completed** (empty plans are not archivable).
281
+
282
+ Edge cases:
283
+
284
+ - Checkboxes outside `## Tasks` (e.g., in `## Settings` or `## Commit Plan`)
285
+ are NOT counted for completion.
286
+ - Nested checkboxes (indented ` - [x]`) ARE counted.
287
+ - Plans without a `## Tasks` section are not archivable — emit
288
+ `WARN [aif-archive] <filename> has no ## Tasks section; skipping`.
289
+
290
+ ### Completion Date Inference
291
+
292
+ When displaying "completed" dates in interactive mode:
293
+
294
+ 1. Check YAML frontmatter for a `completed` field — use if present.
295
+ 2. Fall back to git: `git log -1 --format=%ai -- <plan-file>` to get last
296
+ modification date.
297
+ 3. Fall back to filesystem: file modification time.
298
+
299
+ ## Important Rules
300
+
301
+ 1. **Never archive incomplete plans** — all tasks must be `- [x]`
302
+ 2. **Always ask confirmation** before `--all` and `--roadmap` operations
303
+ 3. **Preserve original filenames** — including sequential `NNNN_` prefix
304
+ 4. **Add archive metadata** — `archived: YYYY-MM-DD` in YAML frontmatter
305
+ 5. **Do not modify fast plans** (`paths.plan`) or fix plans (`paths.fix_plan`) —
306
+ those are single-file artifacts managed by `/aif-implement` and `/aif-fix`
307
+ 6. **Do not count archived plans for sequential numbering** — archived plans
308
+ live in `paths.archive/plans/`, not `paths.plans/`, so `/aif-plan`
309
+ sequential scan does not include them
310
+
311
+ ## Artifact Ownership
312
+
313
+ - **Owns:** `paths.archive/plans/*.md`, `paths.archive/roadmap/*.md`
314
+ - **Reads:** `paths.plans/*.md`, `paths.roadmap`
315
+ - **Modifies:** `paths.roadmap` (only with `--roadmap`, only after confirmation)
316
+ - **Does NOT touch:** `paths.plan`, `paths.fix_plan`, `paths.description`,
317
+ `paths.architecture`, `paths.rules_file`
@@ -5,8 +5,8 @@ description: >-
5
5
  Use when source material should become either one reusable skill package or a
6
6
  split set of focused skills, each with a concise SKILL.md plus detailed
7
7
  references and examples.
8
- argument-hint: "<path|url> [path|url...] [--name <skill-name>] [--update] [--split|--split-by <strategy>]"
9
- allowed-tools: Read Write Edit Glob Grep Bash(mkdir *) Bash(ls *) Bash(find *) Bash(wc *) Bash(python3 *) WebFetch WebSearch AskUserQuestion
8
+ argument-hint: "<path|url> [path|url...] [--name <skill-name>] [--path <directory>] [--update] [--redact-source-map] [--split|--split-by <strategy>]"
9
+ allowed-tools: Read Write Edit Glob Grep Bash(mkdir *) Bash(ls *) Bash(find *) Bash(wc *) Bash(python3 --version) Bash(python --version) Bash(py -3 --version) Bash(py --version) Bash(python3 *material-prep.py*) Bash(python *material-prep.py*) Bash(py -3 *material-prep.py*) Bash(py *material-prep.py*) WebFetch WebSearch AskUserQuestion
10
10
  disable-model-invocation: false
11
11
  metadata:
12
12
  author: ai-factory
@@ -32,7 +32,7 @@ If config.yaml doesn't exist, use defaults:
32
32
 
33
33
  **Read `.ai-factory/skill-context/aif-distillation/SKILL.md`** - MANDATORY if the file exists.
34
34
 
35
- Treat skill-context rules as project-level overrides for this skill. They apply to all generated skill files, references, examples, source maps, and final reports.
35
+ Treat skill-context rules as project-level overrides for this skill. They apply to all generated skill files, references, examples, source-map policy, and final reports.
36
36
 
37
37
  ## Inputs
38
38
 
@@ -41,25 +41,30 @@ Accept `$ARGUMENTS` as one or more:
41
41
  - local directories
42
42
  - URLs
43
43
  - optional `--name <skill-name>`
44
+ - optional `--path <directory>` to save generated skill package directories under a custom output root instead of `{{skills_dir}}`
44
45
  - optional `--update` to improve an existing skill instead of creating a duplicate
46
+ - optional `--redact-source-map` to skip generated source-map files and sections entirely, so exact source titles, URLs, local paths, repository paths, and link reference definitions are not written to output
45
47
  - optional `--split` to create several focused skills from one material set
46
48
  - optional `--split-by <strategy>` to choose the split strategy:
47
- - `auto` (default): infer skill boundaries from source topics and use cases
49
+ - `auto` (default): infer skill boundaries from user goals, triggers, workflows, source topics, and use cases
50
+ - `goal`: split by user goals or jobs-to-be-done, regardless of domain
48
51
  - `topic`: split by major source topics or chapters
49
52
  - `workflow`: split by recurring actions an agent performs
50
53
  - `audience`: split by distinct user roles or implementation contexts
51
54
 
52
- If the target skill name is missing, derive a concise, general, lowercase-hyphenated name from the material topic, such as `clean-code-style`, `api-design-rules`, or `ddd-modeling`.
55
+ If the target skill name is missing, derive a concise, general, lowercase-hyphenated name from the material topic or user goal, such as `clean-code-style`, `api-design-rules`, `decision-making`, `writing-feedback`, or `meeting-facilitation`.
53
56
 
54
57
  Before any write, validate the final target skill name:
55
58
  - It must match `^[a-z0-9]+(?:-[a-z0-9]+)*$`.
56
59
  - Reject empty names, overlong names, `.`, `..`, dots, path separators (`/` or `\`), absolute paths, Windows drive paths, and hidden names.
57
60
  - Reject reserved `aif-*` names unless the user explicitly says they are developing AI Factory itself.
58
- - Resolve the final destination path and confirm it is inside `{{skills_dir}}` before creating or updating files.
61
+ - Resolve the output root: `--path <directory>` when present, otherwise `{{skills_dir}}`.
62
+ - Treat relative `--path` values as relative to the current working directory. Create the output root if it does not exist; reject it if it resolves to an existing file.
63
+ - Resolve the final destination path and confirm it is inside the resolved output root before creating or updating files.
59
64
 
60
- Default destination for single-skill mode: `{{skills_dir}}/<skill-name>/` for the current agent.
65
+ Default destination for single-skill mode: `<output-root>/<skill-name>/`, where `<output-root>` is `{{skills_dir}}` unless `--path` is present.
61
66
 
62
- Default destination for split mode: `{{skills_dir}}/<generated-skill-name>/` for each generated child skill. `--name` becomes a naming seed or namespace prefix, not one enclosing package directory, unless the user explicitly asks for an index-only parent skill.
67
+ Default destination for split mode: `<output-root>/<prefix>-<child-scope>/` for each generated child skill. Every split child name must share one namespace prefix to prevent collisions with existing skills. Use `--name` as the preferred prefix when present; otherwise derive a concise prefix from the book title or primary material title. If `--redact-source-map` is present and the exact source title should not be exposed, use `--name` as the public namespace or derive a neutral topic prefix.
63
68
 
64
69
  Do not save distilled skills into the package `skills/` directory unless the user is explicitly developing AI Factory itself.
65
70
 
@@ -67,7 +72,9 @@ Do not save distilled skills into the package `skills/` directory unless the use
67
72
 
68
73
  1. Prepare sources.
69
74
  - For normal text, markdown, JSON, YAML, HTML, or code files, read directly.
70
- - For large folders or PDFs, use `{{skills_dir}}/aif-distillation/scripts/material-prep.py` to extract and chunk material, then clean temporary extraction artifacts with the helper after the skill is generated.
75
+ - For large folders or PDFs, use `{{skills_dir}}/aif-distillation/scripts/material-prep.py` only when a working Python 3 interpreter is available. Detect it with `python3 --version`, `python --version`, `py -3 --version`, then `py --version`; use the first command that exits successfully and reports Python major version 3.
76
+ - When invoking the helper, expand the selected interpreter to the concrete command shape, such as `python3 ...material-prep.py` or `py -3 ...material-prep.py`. Do not run arbitrary Python payloads; the pre-approved tool contract only covers version probes and `material-prep.py` execution.
77
+ - If Python 3 is not available, do not invoke the helper. Continue with direct `Read`/`Glob`/`Grep`/`find`/`wc` sampling for accessible text files, ask the user for a text/markdown export for PDFs or very large sources, and clearly report any reduced coverage.
71
78
  - For URLs, fetch the source and any critical linked pages needed to understand the topic.
72
79
 
73
80
  2. Distill, do not copy.
@@ -79,34 +86,42 @@ Do not save distilled skills into the package `skills/` directory unless the use
79
86
 
80
87
  3. Choose single-skill or split-skill design.
81
88
  - Default to single-skill mode unless `--split` or `--split-by` is present.
82
- - In split mode, create a skill boundary map before writing: proposed skill name, trigger description, owned source topics, references/examples needed, and overlap risks.
83
- - Prefer split mode when the material contains independent practices that should trigger separately, such as readability refactoring, naming cleanup, testability checks, exception-flow review, or framework-specific passes.
89
+ - In split mode, resolve one shared namespace prefix before writing the boundary map. Use `--name` when present; otherwise use a normalized book/material title. Every proposed child name must start with `<prefix>-`.
90
+ - In split mode, create a skill boundary map before writing: proposed prefixed skill name, user-facing job, trigger description, owned source topics, references/examples needed, and overlap risks.
91
+ - Prefer split mode when the material contains independent goals that should trigger separately, such as reviewing, planning, diagnosing, rewriting, teaching, deciding, testing, facilitating, auditing, or troubleshooting.
92
+ - Name split children by the user goal or job-to-be-done, not by an abstract source theme. Choose the goal taxonomy from the material's domain: for software this may be `refactoring-review`, `test-design`, or `framework-fit-review`; for writing this may be `argument-edit` or `style-review`; for operations this may be `incident-triage` or `runbook-review`; for management this may be `decision-brief` or `stakeholder-analysis`; for learning this may be `concept-coach` or `practice-drill`.
93
+ - Avoid vague lifecycle or chapter names such as `framework-evolution`, `principles`, `philosophy`, `chapter-4`, `mindset`, or `overview` unless that exact name is the user's requested public taxonomy.
84
94
  - Do not split into tiny skills that differ only by wording. Merge candidates when their triggers, workflow, and reference needs substantially overlap.
85
- - Keep every generated child skill independently useful: clear frontmatter, focused workflow, relevant references/examples, and its own source map or source-map section.
95
+ - Keep every generated child skill independently useful: clear frontmatter, focused workflow, and relevant references/examples. If `--redact-source-map` is absent, include its own source map; if present, do not create `references/SOURCE-MAP.md` or a source-map section.
86
96
 
87
97
  4. Design the target skill package.
88
98
  - Keep target `SKILL.md` focused on purpose, triggers, and workflow.
99
+ - Make the generated skill self-explanatory from its directory name and frontmatter. The description must start with an action verb and say what the skill reviews, improves, generates, or checks.
100
+ - Near the top of every generated `SKILL.md`, answer in plain language: what this skill does, when to use it, and what output it should produce. A user should not need to inspect the source material to understand why the skill exists.
89
101
  - Put detailed knowledge in `references/`.
90
102
  - Put reusable prompts, cases, and transformed examples in `examples/`.
91
103
  - If the material teaches programming with code examples, create or update an examples file with original before/after snippets or compact code patterns. Do not omit code examples only because verbatim copying is inappropriate.
92
104
  - For book-scale or broad code material, cover every major code-facing topic with an adapted example, or state why a topic does not need one. Split examples into multiple files when one file would become a shallow sampler.
93
105
  - Add scripts only when the workflow needs repeatable processing.
94
- - In single-skill mode, save the package under `{{skills_dir}}/<skill-name>/` using the chosen concise name.
95
- - In split mode, save each child package directly under `{{skills_dir}}/<child-skill-name>/`. If `--name` is present, use it as a concise prefix only when it improves discoverability and does not make names bulky.
106
+ - Resolve `<output-root>` from `--path` or `{{skills_dir}}` before writing. Treat `--path` as a parent directory for generated skill packages, not as the skill package name.
107
+ - In single-skill mode, save the package under `<output-root>/<skill-name>/` using the chosen concise name.
108
+ - In split mode, save each child package directly under `<output-root>/<prefix>-<child-scope>/`. Do not drop the shared prefix even when the child scope is clear on its own.
109
+ - When `--redact-source-map` is present, do not create `references/SOURCE-MAP.md`, do not create a "Source Map" section in any generated file, and remove any empty `SOURCE-MAP.md` accidentally created during drafting. In `--update` mode, leave an existing non-empty `SOURCE-MAP.md` unchanged unless the user explicitly asks to remove or rewrite it.
96
110
  - Use resolved `language.artifacts` for generated skill content unless the source material or user explicitly requires another language.
97
111
 
98
112
  5. Check existing content before writing.
99
113
  - If the target skill already has matching references or examples, update them in place.
100
114
  - Do not create near-duplicate files with different names.
101
115
  - Preserve useful existing material and add only missing or better distilled content.
102
- - In split mode, also check existing sibling skills under `{{skills_dir}}` for matching triggers. Update a matching skill with `--update` instead of creating a new near-duplicate child.
116
+ - In split mode, also check existing sibling skills under `<output-root>` for matching triggers. Update a matching skill with `--update` instead of creating a new near-duplicate child.
103
117
 
104
118
  6. Validate usefulness.
105
119
  - The skill must tell an agent what to do, when to do it, what good output looks like, and what mistakes to avoid.
120
+ - The name and description must be invocation-ready. If a user would ask "what does this skill actually do?", rename it or rewrite the trigger before finishing.
106
121
  - References must be dense and navigable.
107
122
  - Examples must demonstrate decisions or transformations, not decorative filler.
108
123
  - If source material contained meaningful code snippets or worked examples, the generated skill must include adapted examples. Missing adapted examples is a failure to fix before finishing.
109
- - Example coverage must match the source map: major code-facing source areas should point to concrete examples, not just prose references.
124
+ - Example coverage must match source coverage: when `--redact-source-map` is absent, record this in the source map; when present, validate coverage internally without writing source-map files or sections.
110
125
  - Generated skills must include an artifact ownership/config policy section when they write or read project artifacts.
111
126
  - Generated quality-gate skills must follow the `aif-gate-result` contract from `/aif-verify` references.
112
127
  - In split mode, every child skill must have a distinct activation trigger. If two children would activate for the same request and tell the agent to do the same work, merge them before finishing.
@@ -122,6 +137,6 @@ Use `examples/REQUESTS.md` for invocation patterns.
122
137
 
123
138
  ## Artifact Ownership
124
139
 
125
- - Primary ownership: generated or updated skill packages under `{{skills_dir}}/<skill-name>/`, or multiple direct child skill packages under `{{skills_dir}}/<child-skill-name>/` in split mode.
140
+ - Primary ownership: generated or updated skill packages under `<output-root>/<skill-name>/`, or multiple direct child skill packages under `<output-root>/<prefix>-<child-scope>/` in split mode. `<output-root>` is `{{skills_dir}}` unless the user passes `--path <directory>`.
126
141
  - Read-only context: `.ai-factory/config.yaml`, existing AI Factory context artifacts, and existing skill files except the selected target skill in update mode.
127
142
  - Config policy: config-aware for `language.ui`, `language.artifacts`, and `language.technical_terms` only. Do not write `config.yaml`.