ai-factory 2.13.2 → 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 (30) 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 +4 -2
  10. package/skills/aif-distillation/references/LARGE-MATERIALS.md +21 -1
  11. package/skills/aif-explore/SKILL.md +29 -4
  12. package/skills/aif-fix/SKILL.md +23 -2
  13. package/skills/aif-implement/SKILL.md +3 -0
  14. package/skills/aif-improve/SKILL.md +96 -177
  15. package/skills/aif-improve/references/CHECK-MODE.md +101 -0
  16. package/skills/aif-improve/references/EXAMPLES.md +88 -0
  17. package/skills/aif-improve/references/LIST-MODE.md +83 -0
  18. package/skills/aif-improve/references/VALIDATOR.md +89 -0
  19. package/skills/aif-plan/SKILL.md +23 -3
  20. package/skills/aif-reference/SKILL.md +22 -3
  21. package/skills/aif-review/SKILL.md +44 -17
  22. package/skills/aif-review/references/CHECK-MODE.md +109 -0
  23. package/skills/aif-review/references/SEVERITY.md +35 -0
  24. package/skills/aif-review/references/VALIDATOR.md +103 -0
  25. package/skills/aif-rules/SKILL.md +18 -2
  26. package/skills/aif-security-checklist/SKILL.md +20 -3
  27. package/skills/aif-skill-generator/SKILL.md +39 -19
  28. package/skills/aif-skill-generator/references/SECURITY-SCANNING.md +5 -3
  29. package/skills/aif-skill-generator/scripts/cleanup-blocked-skill.py +617 -0
  30. 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.2",
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`
@@ -6,7 +6,7 @@ description: >-
6
6
  split set of focused skills, each with a concise SKILL.md plus detailed
7
7
  references and examples.
8
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 *) WebFetch WebSearch AskUserQuestion
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
@@ -72,7 +72,9 @@ Do not save distilled skills into the package `skills/` directory unless the use
72
72
 
73
73
  1. Prepare sources.
74
74
  - For normal text, markdown, JSON, YAML, HTML, or code files, read directly.
75
- - 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.
76
78
  - For URLs, fetch the source and any critical linked pages needed to understand the topic.
77
79
 
78
80
  2. Distill, do not copy.
@@ -4,12 +4,30 @@ Large books, PDFs, and source folders need staged processing. The goal is to fit
4
4
 
5
5
  ## Helper Script
6
6
 
7
- Use:
7
+ Use the helper only when a working Python 3 interpreter is available. Detect and verify it by running these version probes in order:
8
+
9
+ ```bash
10
+ python3 --version
11
+ python --version
12
+ py -3 --version
13
+ py --version
14
+ ```
15
+
16
+ Use the first command that exits successfully and reports `Python 3.x`:
17
+
18
+ - `python3 --version` -> `python3`
19
+ - `python --version` -> `python`
20
+ - `py -3 --version` -> `py -3`
21
+ - `py --version` -> `py`
22
+
23
+ Then run the helper with that concrete command shape:
8
24
 
9
25
  ```bash
10
26
  python3 {{skills_dir}}/aif-distillation/scripts/material-prep.py <source...>
11
27
  ```
12
28
 
29
+ Use `python`, `py -3`, or `py` only if that was the selected Python 3 command. If no probe reports Python 3, do not call the helper. Use direct reads/searches for text sources, ask the user for text/markdown exports for PDFs or very large sources, and state the coverage limitation in the final result.
30
+
13
31
  The script:
14
32
 
15
33
  - accepts local files, local folders, and URLs
@@ -61,6 +79,8 @@ Preferred cleanup command:
61
79
  python3 {{skills_dir}}/aif-distillation/scripts/material-prep.py --cleanup <temp-dir>
62
80
  ```
63
81
 
82
+ Use `python`, `py -3`, or `py` only if that was the selected Python 3 command. If no probe reports Python 3, remove only known helper-generated temporary files manually.
83
+
64
84
  The cleanup guard removes only directories with this helper's dedicated marker file.
65
85
 
66
86
  If cleanup cannot be completed, report the exact temporary path to the user.
@@ -16,7 +16,12 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher
16
16
 
17
17
  **FIRST:** Read `.ai-factory/config.yaml` if it exists to resolve:
18
18
  - **Paths:** `paths.description`, `paths.architecture`, `paths.rules_file`, `paths.roadmap`, `paths.research`, `paths.plan`, `paths.plans`, and `paths.rules`
19
- - **Language:** `language.ui` for communication
19
+ - **Language:**
20
+ - `language.ui` for all user-facing responses: prompts, progress updates, explanations, exploration summaries, and next-step guidance
21
+ - `language.artifacts` for generated or persisted exploration artifacts, including the resolved `paths.research`
22
+ - `language.technical_terms` for human-readable technical terminology style in artifacts and summaries
23
+ - If `language.artifacts` is missing, use `language.ui`
24
+ - If both are missing, use `en`
20
25
  - **Workflow:** `workflow.plan_id_format` (default: `slug`) — used by the optional active-plan-context lookup when explore mode references an existing plan for the current branch.
21
26
  Active values: `slug` and `sequential`. When `sequential`, glob
22
27
  `<paths.plans>/[0-9]{4}_<branch_stem>.md` first and fall back to
@@ -26,9 +31,27 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher
26
31
 
27
32
  If config.yaml doesn't exist, use defaults:
28
33
  - Paths: `.ai-factory/` for all artifacts
29
- - Language: `en` (English)
34
+ - `ui_language`: `en`
35
+ - `artifact_language`: `en`
36
+ - `technical_terms_policy`: `keep`
30
37
  - `workflow.plan_id_format`: `slug`
31
38
 
39
+ Store:
40
+ - `ui_language = language.ui || "en"`
41
+ - `artifact_language = language.artifacts || language.ui || "en"`
42
+ - `technical_terms_policy = language.technical_terms || "keep"`
43
+
44
+ If `technical_terms_policy` is not one of `keep`, `translate`, or `mixed`, treat it as `keep`. Legacy values such as `english` also behave like `keep`.
45
+
46
+ All user-facing responses from `/aif-explore` MUST be written in `ui_language`.
47
+
48
+ Persisted exploration artifacts under `paths.research` MUST be written in `artifact_language`.
49
+
50
+ Apply `technical_terms_policy` while writing summaries and persisted artifacts:
51
+ - `keep` - keep commands, paths, identifiers, config keys, API names, package names, branch names, code terms, and raw error messages unchanged
52
+ - `translate` - translate human-readable technical terms where a natural target-language term exists
53
+ - `mixed` - translate ordinary prose terms while keeping code, infrastructure, and ecosystem terms unchanged
54
+
32
55
  **This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
33
56
 
34
57
  ---
@@ -207,6 +230,8 @@ If the conversation is crystallizing (you're about to plan, you want to `/clear`
207
230
 
208
231
  **Hard rule in explore mode:** If the user chooses to save, you may write/edit **only** the resolved research path (and create its parent directory if missing). Do not write or modify any other project files.
209
232
 
233
+ Write the saved research content in `artifact_language`. The skeleton below defines structure, not fixed English output. If `artifact_language` is not `en`, translate human-readable headings, labels, notes, and prose before saving. Preserve markdown markers, paths, commands, config keys, issue URLs, branch names, code identifiers, package names, and raw error messages unchanged.
234
+
210
235
  Ask:
211
236
 
212
237
  ```
@@ -220,7 +245,7 @@ Options:
220
245
 
221
246
  If user selects (1) or (2):
222
247
  - Ensure the parent directory of the resolved research path exists (`mkdir -p "$(dirname "<resolved research path>")"`)
223
- - If the resolved research path does not exist, create it with this skeleton:
248
+ - If the resolved research path does not exist, create it with this skeleton, localized to `artifact_language` before saving:
224
249
 
225
250
  ```markdown
226
251
  # Research
@@ -245,7 +270,7 @@ Next step:
245
270
  ```
246
271
 
247
272
  - Update the `Updated:` timestamp
248
- - Replace only the content inside `aif:active-summary:start/end`
273
+ - Replace only the content inside `aif:active-summary:start/end`, written in `artifact_language`
249
274
  - If user selected option (1), append a new session entry just before `<!-- aif:sessions:end -->`:
250
275
 
251
276
  ```markdown
@@ -48,7 +48,7 @@ When creating a new FIX_PLAN.md: if there is no existing annotation and no Hando
48
48
  **FIRST:** Read `.ai-factory/config.yaml` if it exists to resolve:
49
49
 
50
50
  - **Paths:** `paths.description`, `paths.architecture`, `paths.rules_file`, `paths.rules`, `paths.fix_plan`, and `paths.patches`
51
- - **Language:** `language.ui` for prompts
51
+ - **Language:** `language.ui` for prompts and summaries, `language.artifacts` for `FIX_PLAN.md` and patch artifacts, and `language.technical_terms` for human-readable technical terminology in artifacts
52
52
  - **Rules:** `rules.base` plus any named `rules.<area>` entries
53
53
 
54
54
  If config.yaml doesn't exist, use defaults:
@@ -59,7 +59,22 @@ If config.yaml doesn't exist, use defaults:
59
59
  - rules/: `.ai-factory/rules/`
60
60
  - FIX_PLAN.md: `.ai-factory/FIX_PLAN.md`
61
61
  - patches/: `.ai-factory/patches/`
62
- - Language: `en` (English)
62
+ - `ui_language`: `en`
63
+ - `artifact_language`: `en`
64
+ - `technical_terms_policy`: `keep`
65
+
66
+ Resolved language values:
67
+ - `ui_language = language.ui || "en"`
68
+ - `artifact_language = language.artifacts || language.ui || "en"`
69
+ - `technical_terms_policy = language.technical_terms || "keep"`
70
+
71
+ If `technical_terms_policy` is not one of `keep`, `translate`, or `mixed`, treat it as `keep`. Legacy values such as `english` also behave like `keep`.
72
+
73
+ All AskUserQuestion prompts, progress updates, fix summaries, test prompts, and next-step guidance MUST be written in `ui_language`.
74
+
75
+ Generated `FIX_PLAN.md` and self-improvement patch files under `paths.patches` MUST be written in `artifact_language`.
76
+
77
+ Templates and examples define structure, not fixed English output. If `artifact_language` is not `en`, translate human-readable headings, labels, analysis text, fix steps, risks, prevention notes, and patch prose before saving. Preserve Handoff annotations, markdown structure, checkbox syntax, paths, commands, config keys, code identifiers, package names, API names, raw error messages, code snippets, log prefixes such as `[FIX]`, and patch tags unchanged. Apply `technical_terms_policy` to other human-readable terminology.
63
78
 
64
79
  ### Step 0.1: Check for Existing Fix Plan
65
80
 
@@ -181,6 +196,8 @@ After agents return, synthesize findings to:
181
196
 
182
197
  Then create the resolved fix plan file (default: `.ai-factory/FIX_PLAN.md`).
183
198
 
199
+ Write the fix plan in `artifact_language`. The template below is the required structure only; translate human-readable headings, labels, and prose before saving when `artifact_language` is not `en`, while preserving stable technical tokens from Step 0.
200
+
184
201
  **Before writing:** If `HANDOFF_MODE` is `1` and `HANDOFF_TASK_ID` is non-empty, the very first line of the file MUST be `<!-- handoff:task:<HANDOFF_TASK_ID> -->` followed by a blank line, then the plan content below. If in manual mode and a task ID was extracted from an existing annotation, preserve it.
185
202
 
186
203
  Structure:
@@ -326,6 +343,8 @@ try {
326
343
 
327
344
  **ALWAYS suggest covering this case with a test:**
328
345
 
346
+ The Step 5 and After Fixing output templates define structure only. Render all human-readable text in these user-facing responses in `ui_language`. Preserve code snippets, commands, file paths, line references, log prefixes such as `[FIX]`, and AskUserQuestion option structure unchanged.
347
+
329
348
  ```
330
349
  ## Fix Applied ✅
331
350
 
@@ -483,6 +502,8 @@ function fixedFunction(input) {
483
502
 
484
503
  3. Use this template:
485
504
 
505
+ Write the patch artifact in `artifact_language`. The template below is the required structure only; translate human-readable headings, labels, root-cause text, solution text, and prevention text before saving when `artifact_language` is not `en`, while preserving stable technical tokens from Step 0.
506
+
486
507
  ```markdown
487
508
  # [Brief title describing the fix]
488
509