5-phase-workflow 2.0.0 → 2.0.2

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.
package/README.md CHANGED
@@ -1,6 +1,29 @@
1
1
  # foifi
2
2
 
3
- A structured AI-assisted development workflow for Claude Code and Codex.
3
+ **foifi** is an opinionated AI development workflow layer that sits on top of Claude Code and Codex. It handles project setup, structured feature implementation, and code review — so you spend less time managing the AI and more time shipping.
4
+
5
+ ### What it does
6
+
7
+ **Project setup** — The `/5:configure` command detects your stack, generates a `CLAUDE.md` / `AGENTS.md` tailored to your project, writes a `.5/index/` knowledge base, and installs project-specific skills and rules. This gives every AI session the right context from the start rather than letting the model guess.
8
+
9
+ **Status line** — foifi installs an informative Claude Code status line that surfaces the active feature, current workflow phase, and relevant state directly in the terminal footer. No more digging through files to remember where you left off.
10
+
11
+ **Structured implementation workflow** — Instead of asking Claude or Codex to "just implement this," foifi enforces a three-phase loop:
12
+ 1. **Plan** (`/5:plan`) — writes a single human-reviewed `plan.md` with scope, acceptance criteria, component checklist, and decisions.
13
+ 2. **Implement** (`/5:implement`) — an orchestrator agent turns the plan into a typed execution graph (`state.json`), then delegates each component to a focused executor agent. A verification agent checks completeness, correctness, and test coverage at the end of every run.
14
+ 3. **Review** (`/5:review`) — triages changed files, produces structured findings, and feeds them into `/5:address-review-findings` for interactive fix decisions and PR replies.
15
+
16
+ This separation keeps planning readable, implementation mechanical, and review structured.
17
+
18
+ **Code review and findings** — `/5:review` triages changed files and produces structured `review-findings-*.md`. `/5:address-review-findings` presents each finding interactively, records `fix`/`wont_fix`/`wait` decisions, applies approved local fixes, handles PR comment replies, and keeps a decision log — all without losing context between sessions.
19
+
20
+ **Plan management helpers** — `/5:discuss-feature` refines an existing plan in conversation. `/5:split` breaks a large plan into smaller linked child plans. `/5:unlock` clears a stale planning lock. `/5:reconfigure` refreshes docs and skills when the project evolves.
21
+
22
+ **Codex support** — Every command has a `$5-*` Codex equivalent. Codex runs are token-budgeted: simple steps use a lighter model and low reasoning, complex or security-sensitive steps escalate automatically.
23
+
24
+ ### The name
25
+
26
+ "foifi" is Swiss German for *five*. The name comes from the project's original 5-phase workflow. That workflow has since been streamlined into the current 3-phase plan → implement → review loop, but the name stuck — and all commands still carry the `/5:` prefix.
4
27
 
5
28
  ## Install
6
29
 
package/bin/install.js CHANGED
@@ -393,7 +393,8 @@ function getWorkflowManagedFiles() {
393
393
  skills: [
394
394
  'configure-docs-index',
395
395
  'configure-skills',
396
- 'generate-readme'
396
+ 'generate-readme',
397
+ 'use-index'
397
398
  ],
398
399
 
399
400
  // Hooks: specific hook files
@@ -569,6 +570,13 @@ During the planning phase ($5-plan):
569
570
  - Do NOT write to any file outside \`.5/\`
570
571
  - Do NOT write source code — only the unified plan and scan cache
571
572
  - Do NOT spawn implementation agents — only Explore/research agents
573
+
574
+ ## Update & Migration Notices (replaces statusline hooks)
575
+ At the very start of this skill, before doing anything else, read these two files if they exist:
576
+ - \`.5/.update-cache.json\` — if \`latestAvailableVersion\` is set, compare it to \`packageVersion\` in \`.5/version.json\`. If a newer version is available, tell the user: "foifi update available: <version> — run \`npx foifi --codex --upgrade\` to update."
577
+ - \`.5/.migration-v2\` — if this file exists, tell the user: "You upgraded from foifi v1 to v2. Run \`$5-reconfigure\` to update your project configuration."
578
+
579
+ Show each applicable notice once at the top of your response, then continue with the skill normally. Do not abort the skill because of a notice.
572
580
  </codex_skill_adapter>`;
573
581
  }
574
582
 
@@ -828,17 +836,20 @@ function cleanupOrphanedFiles(targetPath, dataDir) {
828
836
  }
829
837
  }
830
838
 
831
- // Ensure .5/.gitignore exists and contains .update-cache.json
839
+ // Ensure .5/.gitignore exists and contains transient runtime files
832
840
  function ensureDotFiveGitignore(dataDir) {
833
841
  const gitignorePath = path.join(dataDir, '.gitignore');
834
- const entry = '.update-cache.json';
842
+ const entries = ['.update-cache.json', '.migration-v*', '.reconfig-reminder'];
835
843
  if (fs.existsSync(gitignorePath)) {
836
- const content = fs.readFileSync(gitignorePath, 'utf8');
837
- if (!content.includes(entry)) {
838
- fs.appendFileSync(gitignorePath, '\n' + entry + '\n');
844
+ let content = fs.readFileSync(gitignorePath, 'utf8');
845
+ for (const entry of entries) {
846
+ if (!content.includes(entry)) {
847
+ content += '\n' + entry;
848
+ }
839
849
  }
850
+ fs.writeFileSync(gitignorePath, content.trimEnd() + '\n');
840
851
  } else {
841
- fs.writeFileSync(gitignorePath, entry + '\n');
852
+ fs.writeFileSync(gitignorePath, entries.join('\n') + '\n');
842
853
  }
843
854
  }
844
855
 
@@ -1070,6 +1081,52 @@ function performFreshInstall(targetPath, sourcePath, isGlobal) {
1070
1081
  showCommandsHelp(isGlobal);
1071
1082
  }
1072
1083
 
1084
+ // Rename create-* generated skill directories to {pattern} (drop the create- prefix).
1085
+ // Earlier versions named them create-dto, create-service, etc. The new convention
1086
+ // uses the bare pattern name so skills work for both create and update.
1087
+ function renameCreateSkills(targetPath) {
1088
+ const skillsDir = path.join(targetPath, 'skills');
1089
+ if (!fs.existsSync(skillsDir)) return;
1090
+ try {
1091
+ for (const entry of fs.readdirSync(skillsDir)) {
1092
+ if (!entry.startsWith('create-')) continue;
1093
+ const oldPath = path.join(skillsDir, entry);
1094
+ const newName = entry.slice('create-'.length);
1095
+ const newPath = path.join(skillsDir, newName);
1096
+ if (fs.existsSync(newPath)) continue; // don't clobber a user-created skill
1097
+ const skillFile = path.join(oldPath, 'SKILL.md');
1098
+ if (!fs.existsSync(skillFile)) continue; // skip non-workflow dirs
1099
+ fs.renameSync(oldPath, newPath);
1100
+ // Update name: and description: in the frontmatter to match
1101
+ const content = fs.readFileSync(path.join(newPath, 'SKILL.md'), 'utf8');
1102
+ const updated = content
1103
+ .replace(/^name: create-/m, 'name: ')
1104
+ .replace(/^description: Creates a /m, 'description: Creates or updates a ');
1105
+ fs.writeFileSync(path.join(newPath, 'SKILL.md'), updated);
1106
+ log.info(`Renamed skill: ${entry} → ${newName}`);
1107
+ }
1108
+ } catch (e) {}
1109
+ }
1110
+
1111
+ // Remove `context: fork` from any skill SKILL.md files under .claude/skills/.
1112
+ // These were generated by earlier versions of configure-skills and cause loops.
1113
+ function removeContextForkFromSkills(targetPath) {
1114
+ const skillsDir = path.join(targetPath, 'skills');
1115
+ if (!fs.existsSync(skillsDir)) return;
1116
+ try {
1117
+ for (const entry of fs.readdirSync(skillsDir)) {
1118
+ const skillFile = path.join(skillsDir, entry, 'SKILL.md');
1119
+ if (!fs.existsSync(skillFile)) continue;
1120
+ const original = fs.readFileSync(skillFile, 'utf8');
1121
+ const updated = original.replace(/^context: fork\s*\n/m, '');
1122
+ if (updated !== original) {
1123
+ fs.writeFileSync(skillFile, updated);
1124
+ log.info(`Removed context: fork from skills/${entry}/SKILL.md`);
1125
+ }
1126
+ }
1127
+ } catch (e) {}
1128
+ }
1129
+
1073
1130
  // Perform update (preserves user-created files, updates .5/ data directory)
1074
1131
  function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1075
1132
  log.header(`Updating from ${versionInfo.installed || 'legacy'} to ${versionInfo.available}`);
@@ -1085,6 +1142,22 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1085
1142
  // Merge settings (deep merge preserves user customizations)
1086
1143
  mergeSettings(targetPath, sourcePath);
1087
1144
 
1145
+ // Rename create-* skill dirs to bare pattern names (create-dto → dto)
1146
+ renameCreateSkills(targetPath);
1147
+
1148
+ // Strip `context: fork` from generated skills — caused infinite loops
1149
+ removeContextForkFromSkills(targetPath);
1150
+
1151
+ // Flag v1 → v2 major upgrade so statusline can prompt for reconfigure
1152
+ const prevMajor = versionInfo.installed ? parseInt(versionInfo.installed.split('.')[0], 10) : 0;
1153
+ const newMajor = versionInfo.available ? parseInt(versionInfo.available.split('.')[0], 10) : 0;
1154
+ if (!isNaN(prevMajor) && !isNaN(newMajor) && prevMajor < newMajor) {
1155
+ try {
1156
+ if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });
1157
+ fs.writeFileSync(path.join(dataDir, '.migration-v' + newMajor), '1');
1158
+ } catch (e) {}
1159
+ }
1160
+
1088
1161
  // Update version.json (per-runtime, preserving other runtime's state)
1089
1162
  writeVersionJson(dataDir, isGlobal, versionInfo.available);
1090
1163
  ensureDotFiveGitignore(dataDir);
@@ -1325,6 +1398,19 @@ function performCodexUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1325
1398
  const dataDir = getDataPath(isGlobal);
1326
1399
  cleanupOrphanedFiles(targetPath, dataDir);
1327
1400
 
1401
+ // Rename create-* skill dirs to bare pattern names (create-dto → dto)
1402
+ renameCreateSkills(targetPath);
1403
+
1404
+ // Flag v1 → v2 major upgrade so skills can prompt for reconfigure
1405
+ const prevMajor = versionInfo.installed ? parseInt(versionInfo.installed.split('.')[0], 10) : 0;
1406
+ const newMajor = versionInfo.available ? parseInt(versionInfo.available.split('.')[0], 10) : 0;
1407
+ if (!isNaN(prevMajor) && !isNaN(newMajor) && prevMajor < newMajor) {
1408
+ try {
1409
+ if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });
1410
+ fs.writeFileSync(path.join(dataDir, '.migration-v' + newMajor), '1');
1411
+ } catch (e) {}
1412
+ }
1413
+
1328
1414
  // Update version.json (per-runtime, preserving other runtime's state)
1329
1415
  writeVersionJson(dataDir, isGlobal, versionInfo.available);
1330
1416
  ensureDotFiveGitignore(dataDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5-phase-workflow",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "A dev-workflow for Claude Code and Codex",
5
5
  "bin": {
6
6
  "foifi": "bin/install.js"
@@ -30,7 +30,7 @@ Do NOT proceed until you have a clear understanding of what to analyze.
30
30
 
31
31
  1. Derive a short kebab-case name from the analysis subject (e.g., `user-auth`, `order-processing`, `payment-integration`). This becomes the filename: `{name}-analysis.md`.
32
32
 
33
- 2. Identify the relevant modules and layers to analyze. If `.5/index/` exists, read the index files for a quick structural overview. Otherwise, use Glob to understand the project layout.
33
+ 2. Identify the relevant modules and layers to analyze. Invoke the `use-index` skill for a quick structural overview. The skill will rebuild the index if stale; fall back to Glob only if the index is missing.
34
34
 
35
35
  3. Use Glob and Grep to locate the relevant source files. Search for key classes, interfaces, functions, and types related to the analysis subject.
36
36
 
@@ -111,7 +111,7 @@ Use `multiSelect: false` to get single focus area initially.
111
111
 
112
112
  Based on the user's focus area, explore the codebase if needed:
113
113
 
114
- **Index shortcut:** Before spawning Explore agents or running Glob/Grep, check if `.5/index/` exists. If it does, read `.5/index/README.md` first for the generation timestamp — if fresh (under 1 day old), read the relevant index files (e.g., modules.md for scope changes, routes.md for API discussions, models.md for data model questions) to quickly gather context and skip broad scanning. If outdated, inform the user they can run `.5/index/rebuild-index.sh` to refresh it. If `.5/index/` does not exist, inform the user they can run `/5:reconfigure` to generate it. In both missing/outdated cases, fall back to Glob/Grep or Explore agents for exploration.
114
+ **Index shortcut:** Before spawning Explore agents or running Glob/Grep, invoke the `use-index` skill to quickly orient in the codebase using the generated index.
115
115
 
116
116
  **For technical constraint discussions:**
117
117
  - Search for similar implementations
@@ -79,6 +79,8 @@ Do not ask technical follow-ups yet.
79
79
 
80
80
  ## Step 3: Explore Codebase
81
81
 
82
+ If `.5/index/` exists, check the `Generated:` timestamp in `.5/index/README.md`. If the index is more than one day old, run `.5/index/rebuild-index.sh` to refresh it before spawning the Explore agent.
83
+
82
84
  Spawn one Explore agent. In Codex, use `agent_type: explorer`, `model: gpt-5.4-mini`, and `reasoning_effort: low`.
83
85
 
84
86
  ```text
@@ -88,7 +90,7 @@ Feature description:
88
90
  {feature description}
89
91
 
90
92
  Tasks:
91
- 1. If `.5/index/` exists, read `.5/index/README.md` first. Use only relevant fresh index files; do not rescan broad project structure. If stale, note it and fall back to targeted Grep/Glob.
93
+ 1. If `.5/index/` exists, read `.claude/skills/use-index/SKILL.md` and follow its guidance to select and read relevant index files. Skip broad project scanning. If the index is missing, fall back to targeted Grep/Glob and note it in the report.
92
94
  2. Identify relevant modules, existing patterns, and likely target files.
93
95
  3. Find at most 3 similar implementations and reusable helpers.
94
96
  4. Identify test framework, test file conventions, and the narrowest relevant build/test commands.
@@ -177,9 +177,9 @@ After the skill completes, update `.5/version.json`:
177
177
 
178
178
  ### Step 8: Clean Up
179
179
 
180
- Remove the `.5/.reconfig-reminder` flag file if it exists:
180
+ Remove the `.5/.reconfig-reminder` and `.5/.migration-v2` flag files if they exist:
181
181
  ```bash
182
- rm -f .5/.reconfig-reminder
182
+ rm -f .5/.reconfig-reminder .5/.migration-v2
183
183
  ```
184
184
 
185
185
  ### Step 9: Report
@@ -113,6 +113,11 @@ process.stdin.on('end', () => {
113
113
  if (fs.existsSync(flagFile)) {
114
114
  parts.push(`\x1b[35m↻ /5:reconfigure\x1b[0m`);
115
115
  }
116
+
117
+ const migrationFlag = path.join(dir, '.5', '.migration-v2');
118
+ if (fs.existsSync(migrationFlag)) {
119
+ parts.push(`\x1b[31m⚠ v1→v2: /5:reconfigure\x1b[0m`);
120
+ }
116
121
  } catch (e) {}
117
122
 
118
123
  process.stdout.write(parts.join(' | '));
@@ -3,7 +3,6 @@ name: configure-docs-index
3
3
  description: Analyzes the codebase, creates project documentation, generates a rebuildable codebase index, and updates AGENTS.md. Used during /5:implement CONFIGURE.
4
4
  allowed-tools: Read, Write, Bash, Glob, Grep
5
5
  model: sonnet
6
- context: fork
7
6
  user-invocable: false
8
7
  ---
9
8
 
@@ -3,7 +3,6 @@ name: configure-skills
3
3
  description: Generates project-specific create-*/run-* skills and scoped rules from the current codebase. Used during /5:implement CONFIGURE.
4
4
  allowed-tools: Read, Write, Bash, Glob, Grep, create-skill, scaffold-skill
5
5
  model: sonnet
6
- context: fork
7
6
  user-invocable: false
8
7
  ---
9
8
 
@@ -77,24 +76,23 @@ For EACH pattern selected by the user in the unified plan:
77
76
 
78
77
  ### A2. Skill Template Structure
79
78
 
80
- For each skill, create `.claude/skills/create-{pattern}/SKILL.md`:
79
+ For each skill, create `.claude/skills/{pattern}/SKILL.md`:
81
80
 
82
81
  ```yaml
83
82
  ---
84
- name: create-{pattern}
85
- description: Creates a {Pattern} following project conventions at {location}.
83
+ name: {pattern}
84
+ description: Creates or updates a {Pattern} following project conventions at {location}.
86
85
  allowed-tools: Read, Write, Glob, Grep
87
86
  model: haiku
88
- context: fork
89
87
  user-invocable: true
90
88
  ---
91
89
  ```
92
90
 
93
91
  ```markdown
94
- # Create {Pattern}
92
+ # {Pattern}
95
93
 
96
- ## What This Skill Creates
97
- A {pattern} following this project's conventions.
94
+ ## What This Skill Does
95
+ Creates or updates a {pattern} following this project's conventions.
98
96
 
99
97
  ## Detected Conventions
100
98
  - **Location:** {detected-location}
@@ -103,14 +101,14 @@ A {pattern} following this project's conventions.
103
101
  - **Imports:** {detected-import-pattern}
104
102
 
105
103
  ## Template
106
- Based on {example-file}, new {patterns} should follow:
104
+ Based on {example-file}, {patterns} should follow:
107
105
 
108
106
  \`\`\`{language}
109
107
  {template-derived-from-analysis}
110
108
  \`\`\`
111
109
 
112
110
  ## Checklist
113
- - [ ] File created at correct location
111
+ - [ ] File at correct location
114
112
  - [ ] Naming convention followed
115
113
  - [ ] Required imports added
116
114
  - [ ] {pattern-specific-items}
@@ -118,7 +116,7 @@ Based on {example-file}, new {patterns} should follow:
118
116
 
119
117
  ### A3. Pattern to Skill Name Mapping
120
118
 
121
- **Rule:** Skill name is `create-{pattern}` (e.g., `controller` → `create-controller`, `component` → `create-component`, `dto` → `create-dto`). For compound patterns, use the short form: `model/entity` → `create-model`, `api-route` → `create-api-route`.
119
+ **Rule:** Skill name is `{pattern}` (e.g., `controller` → `controller`, `component` → `component`, `dto` → `dto`). For compound patterns, use the short form: `model/entity` → `model`, `api-route` → `api-route`.
122
120
 
123
121
  ---
124
122
 
@@ -153,7 +151,6 @@ name: run-{command}
153
151
  description: Runs {command} for this project using {source}.
154
152
  allowed-tools: Bash
155
153
  model: haiku
156
- context: fork
157
154
  user-invocable: true
158
155
  ---
159
156
  ```
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: use-index
3
+ description: Navigate the .5/index/ codebase index to quickly identify target files and understand project structure. Use before running broad Glob/Grep scans when you need to find where a feature lives, where new code should go, which routes exist, or what the data model looks like.
4
+ allowed-tools: Read, Bash
5
+ user-invocable: false
6
+ ---
7
+
8
+ # Use Index
9
+
10
+ Use `.5/index/` to orient in the codebase quickly before resorting to broad file scans.
11
+
12
+ ## Step 1: Check existence
13
+
14
+ ```bash
15
+ ls .5/index/ 2>/dev/null
16
+ ```
17
+
18
+ If the directory is missing or empty, inform the user they can run `/5:reconfigure` to generate it, then fall back to Glob/Grep.
19
+
20
+ ## Step 2: Read the manifest
21
+
22
+ Read `.5/index/README.md`. It lists every generated index file, its purpose, and the generation timestamp.
23
+
24
+ ## Step 3: Check freshness
25
+
26
+ Look for the `Generated:` timestamp in README.md.
27
+
28
+ - **Fresh (≤ 1 day):** proceed with the index.
29
+ - **Stale (> 1 day):** run `.5/index/rebuild-index.sh` to rebuild it, then proceed with the refreshed index.
30
+
31
+ ## Step 4: Read only the relevant file(s)
32
+
33
+ Pick the file that matches the task. Skip unrelated ones.
34
+
35
+ | Task | File |
36
+ |------|------|
37
+ | Where does new code go / what modules exist? | `modules.md` |
38
+ | API surface, HTTP routes, or handlers | `routes.md` |
39
+ | Data models, schemas, or migrations | `models.md` |
40
+ | Shared helpers, utilities, or exported functions | `libraries.md` |
41
+ | Build, run, test, or dev-workflow commands | `commands.md` |
42
+
43
+ ## Step 5: Interpret entries
44
+
45
+ Each file has compact entries — path plus a short descriptor (HTTP method, exported name, key field, etc.). Use them to identify target files directly. Do not read the full index file if a handful of entries answer the question.
46
+
47
+ ## Step 6: Fall back gracefully
48
+
49
+ If a file is too sparse or an area is missing from the index, note the gap and fall back to a targeted Grep/Glob for that area only. Do not re-scan sections already covered by a fresh index entry.
@@ -87,8 +87,6 @@ Strong success criteria let you loop independently. Weak criteria ("make it work
87
87
 
88
88
  {CODEBASE_INDEX_LINKS}
89
89
 
90
- ## Index Freshness
91
-
92
- If the codebase index files are more than one day old, regenerate them by running `.5/index/rebuild-index.sh` before relying on them.
90
+ Use the `use-index` skill before running broad Glob/Grep scans. It handles freshness checks, file selection by task type, and fallback strategies. If index files are more than one day old, regenerate them by running `.5/index/rebuild-index.sh` before relying on them.
93
91
 
94
92
  {CUSTOM_DOCUMENTATION}