@relipa/ai-flow-kit 0.1.8 → 0.1.9

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/scripts/remove.js CHANGED
@@ -1,224 +1,251 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const chalk = require('chalk');
4
- const { confirm } = require('@inquirer/prompts');
5
-
6
- const PROJECT_DIR = process.cwd();
7
- const AIFLOW_DIR = path.join(PROJECT_DIR, '.aiflow');
8
- const STATE_FILE = path.join(AIFLOW_DIR, 'state.json');
9
-
10
- // ──────────────────────────────────────────────────────────────
11
- // Entry point
12
- // ──────────────────────────────────────────────────────────────
13
-
14
- module.exports = async function remove(options = {}) {
15
- try {
16
- if (options.global) return await removeGlobal();
17
- if (options.version) return await removeVersion(options.version);
18
- return await removeFromProject();
19
- } catch (err) {
20
- console.error(chalk.red(`Error: ${err.message}`));
21
- }
22
- };
23
-
24
- // ──────────────────────────────────────────────────────────────
25
- // Case 1: Remove ai-flow-kit setup from current project
26
- // Deletes .aiflow/, .claude/skills, .claude/hooks, .claude/settings.json, .rules/
27
- // Does NOT delete CLAUDE.md or .mcp.json (user content)
28
- // ──────────────────────────────────────────────────────────────
29
-
30
- async function removeFromProject() {
31
- if (!(await fs.pathExists(AIFLOW_DIR))) {
32
- console.log(chalk.yellow('ai-flow-kit is not initialized in this project.'));
33
- return;
34
- }
35
-
36
- console.log(chalk.yellow('\nThis will remove ai-flow-kit from the current project:'));
37
- console.log(chalk.gray(' • .aiflow/ (state, versions, context, memory)'));
38
- console.log(chalk.gray(' • .claude/skills/ (superpowers + custom skills)'));
39
- console.log(chalk.gray(' • .claude/hooks/ (SessionStart hook)'));
40
- console.log(chalk.gray(' • .claude/settings.json (hook config)'));
41
- console.log(chalk.gray(' • .rules/ (team rules)'));
42
- console.log(chalk.gray(' CLAUDE.md and .mcp.json are NOT removed (your content)\n'));
43
-
44
- const ok = await confirm({ message: 'Continue?' });
45
- if (!ok) {
46
- console.log(chalk.gray('Cancelled.'));
47
- return;
48
- }
49
-
50
- // Remove .aiflow/
51
- await fs.remove(AIFLOW_DIR);
52
- console.log(chalk.green('✓ Removed .aiflow/'));
53
-
54
- // Remove .claude/skills, hooks, settings.json but keep the rest (e.g. context user may want)
55
- const claudeDir = path.join(PROJECT_DIR, '.claude');
56
- const skillsDir = path.join(claudeDir, 'skills');
57
- const hooksDir = path.join(claudeDir, 'hooks');
58
- const settingsFile = path.join(claudeDir, 'settings.json');
59
-
60
- if (await fs.pathExists(skillsDir)) {
61
- await fs.remove(skillsDir);
62
- console.log(chalk.green('✓ Removed .claude/skills/'));
63
- }
64
-
65
- if (await fs.pathExists(hooksDir)) {
66
- await fs.remove(hooksDir);
67
- console.log(chalk.green('✓ Removed .claude/hooks/'));
68
- }
69
-
70
- if (await fs.pathExists(settingsFile)) {
71
- // Only remove the _aiflowKit hook entry, not the whole file
72
- const settings = await fs.readJson(settingsFile).catch(() => ({}));
73
- if (settings.hooks?.SessionStart) {
74
- settings.hooks.SessionStart = settings.hooks.SessionStart.filter(
75
- h => !h._aiflowKit
76
- );
77
- if (settings.hooks.SessionStart.length === 0) {
78
- delete settings.hooks.SessionStart;
79
- }
80
- await fs.writeJson(settingsFile, settings, { spaces: 2 });
81
- console.log(chalk.green('✓ Removed ai-flow-kit hook from .claude/settings.json'));
82
- }
83
- }
84
-
85
- // Remove .rules/
86
- const rulesDir = path.join(PROJECT_DIR, '.rules');
87
- if (await fs.pathExists(rulesDir)) {
88
- await fs.remove(rulesDir);
89
- console.log(chalk.green('✓ Removed .rules/'));
90
- }
91
-
92
- // Clean up AI Tool files (CLAUDE.md, .cursorrules, etc.)
93
- const { AI_TOOL_FILES } = require('./init');
94
- const markerStart = '<!-- aiflow-kit-start -->';
95
- const markerEnd = '<!-- aiflow-kit-end -->';
96
-
97
- for (const tool in AI_TOOL_FILES) {
98
- const filePath = path.join(PROJECT_DIR, AI_TOOL_FILES[tool]);
99
- if (!(await fs.pathExists(filePath))) continue;
100
-
101
- let content = await fs.readFile(filePath, 'utf-8');
102
- let cleaned = false;
103
-
104
- if (content.includes(markerStart) && content.includes(markerEnd)) {
105
- // Precise removal using markers
106
- const startIndex = content.indexOf(markerStart);
107
- const endIndex = content.indexOf(markerEnd) + markerEnd.length;
108
- content = content.slice(0, startIndex).trim() + '\n' + content.slice(endIndex).trim();
109
- content = content.trim();
110
- cleaned = true;
111
- } else if (content.includes('## AI Skill Registry (Superpowers)')) {
112
- // Fallback for legacy installs: remove sections by headers
113
- console.log(chalk.yellow(` ⚠ Found legacy aiflow sections in ${AI_TOOL_FILES[tool]}`));
114
- const ok = await confirm({ message: `Remove ai-flow-kit sections from ${AI_TOOL_FILES[tool]}?`, default: true });
115
- if (ok) {
116
- // Heuristic: remove from "## AI Skill Registry" or "# Claude AI System Instructions"
117
- // This is simple and covers most cases. For complex cases, user should manual clean.
118
- const headers = [
119
- '# Claude AI System Instructions',
120
- '## AI Skill Registry (Superpowers)',
121
- '## MANDATORY: Strict Gate Workflow'
122
- ];
123
- let minIndex = content.length;
124
- for (const h of headers) {
125
- const idx = content.indexOf(h);
126
- if (idx !== -1 && idx < minIndex) minIndex = idx;
127
- }
128
- if (minIndex < content.length) {
129
- content = content.slice(0, minIndex).trim();
130
- cleaned = true;
131
- }
132
- }
133
- }
134
-
135
- if (cleaned) {
136
- if (content.length === 0) {
137
- await fs.remove(filePath);
138
- console.log(chalk.green(`✓ Deleted ${AI_TOOL_FILES[tool]} (it was aiflow-only)`));
139
- } else {
140
- await fs.writeFile(filePath, content);
141
- console.log(chalk.green(`✓ Cleaned up ai-flow-kit instructions from ${AI_TOOL_FILES[tool]}`));
142
- }
143
- }
144
- }
145
-
146
- console.log(chalk.green('\n✨ ai-flow-kit removed from project.'));
147
- console.log(chalk.gray('To reinstall: aiflow init'));
148
- }
149
-
150
- // ──────────────────────────────────────────────────────────────
151
- // Case 2: Uninstall the global npm package
152
- // ──────────────────────────────────────────────────────────────
153
-
154
- async function removeGlobal() {
155
- console.log(chalk.yellow('\nThis will uninstall ai-flow-kit globally from your system.'));
156
- console.log(chalk.gray('Project files (.aiflow/, .claude/, .rules/) are NOT affected.\n'));
157
-
158
- const ok = await confirm({ message: 'Uninstall global package?' });
159
- if (!ok) {
160
- console.log(chalk.gray('Cancelled.'));
161
- return;
162
- }
163
-
164
- const { execSync } = require('child_process');
165
- try {
166
- console.log(chalk.blue('Running: npm uninstall -g ai-flow-kit ...'));
167
- execSync('npm uninstall -g ai-flow-kit', { stdio: 'inherit' });
168
- console.log(chalk.green('\n✨ ai-flow-kit uninstalled globally.'));
169
- console.log(chalk.gray('The `aiflow` command is no longer available.'));
170
- } catch (err) {
171
- // execSync throws on non-zero exit; message already printed via stdio: inherit
172
- console.log(chalk.red('\nFailed to uninstall. Try manually: npm uninstall -g ai-flow-kit'));
173
- }
174
- }
175
-
176
- // ──────────────────────────────────────────────────────────────
177
- // Case 3: Remove a specific cached version from .aiflow/versions/
178
- // ──────────────────────────────────────────────────────────────
179
-
180
- async function removeVersion(version) {
181
- if (!(await fs.pathExists(STATE_FILE))) {
182
- console.log(chalk.red('Project is not initialized. Run `aiflow init` first.'));
183
- return;
184
- }
185
-
186
- const versionsDir = path.join(AIFLOW_DIR, 'versions');
187
- const targetDir = path.join(versionsDir, version);
188
-
189
- if (!(await fs.pathExists(targetDir))) {
190
- console.log(chalk.red(`Version v${version} is not cached in this project.`));
191
-
192
- // Show what's available
193
- if (await fs.pathExists(versionsDir)) {
194
- const available = await fs.readdir(versionsDir);
195
- if (available.length) {
196
- console.log(chalk.gray(`Cached versions: ${available.map(v => `v${v}`).join(', ')}`));
197
- }
198
- }
199
- return;
200
- }
201
-
202
- // Prevent removing the currently active version
203
- const state = await fs.readJson(STATE_FILE);
204
- if (state.current_version === version) {
205
- console.log(chalk.red(`v${version} is currently active — cannot remove it.`));
206
- console.log(chalk.gray('Switch to another version first: aiflow use <version>'));
207
- return;
208
- }
209
-
210
- const ok = await confirm({ message: `Delete cached version v${version}?` });
211
- if (!ok) {
212
- console.log(chalk.gray('Cancelled.'));
213
- return;
214
- }
215
-
216
- await fs.remove(targetDir);
217
- console.log(chalk.green(`✓ Removed cached version v${version}.`));
218
-
219
- // Show remaining versions
220
- const remaining = await fs.readdir(versionsDir).catch(() => []);
221
- if (remaining.length) {
222
- console.log(chalk.gray(`Remaining: ${remaining.map(v => `v${v}`).join(', ')}`));
223
- }
224
- }
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { confirm } = require('@inquirer/prompts');
5
+
6
+ const PROJECT_DIR = process.cwd();
7
+ const AIFLOW_DIR = path.join(PROJECT_DIR, '.aiflow');
8
+ const STATE_FILE = path.join(AIFLOW_DIR, 'state.json');
9
+
10
+ // ──────────────────────────────────────────────────────────────
11
+ // Entry point
12
+ // ──────────────────────────────────────────────────────────────
13
+
14
+ module.exports = async function remove(options = {}) {
15
+ try {
16
+ if (options.global) return await removeGlobal();
17
+ if (options.version) return await removeVersion(options.version);
18
+ return await removeFromProject();
19
+ } catch (err) {
20
+ console.error(chalk.red(`Error: ${err.message}`));
21
+ }
22
+ };
23
+
24
+ // ──────────────────────────────────────────────────────────────
25
+ // Case 1: Remove ai-flow-kit setup from current project
26
+ // Deletes .aiflow/, .claude/skills, .claude/hooks, .claude/settings.json, .rules/
27
+ // Does NOT delete CLAUDE.md or .mcp.json (user content)
28
+ // ──────────────────────────────────────────────────────────────
29
+
30
+ async function removeFromProject() {
31
+ if (!(await fs.pathExists(AIFLOW_DIR))) {
32
+ console.log(chalk.yellow('ai-flow-kit is not initialized in this project.'));
33
+ return;
34
+ }
35
+
36
+ console.log(chalk.yellow('\nThis will remove ai-flow-kit from the current project:'));
37
+ console.log(chalk.gray(' • .aiflow/ (state, versions, context, memory)'));
38
+ console.log(chalk.gray(' • .claude/skills/ (superpowers + custom skills)'));
39
+ console.log(chalk.gray(' • .claude/hooks/ (SessionStart hook)'));
40
+ console.log(chalk.gray(' • .claude/settings.json (hook config)'));
41
+ console.log(chalk.gray(' • .rules/ (team rules)'));
42
+ console.log(chalk.gray(' .codex/skills/ (Codex skill mirror)'));
43
+ console.log(chalk.gray(' • .codex/config.toml (only if kit-managed)'));
44
+ console.log(chalk.gray(' ✗ CLAUDE.md, AGENTS.md and .mcp.json are NOT removed (your content)\n'));
45
+
46
+ const ok = await confirm({ message: 'Continue?' });
47
+ if (!ok) {
48
+ console.log(chalk.gray('Cancelled.'));
49
+ return;
50
+ }
51
+
52
+ // Remove .aiflow/
53
+ await fs.remove(AIFLOW_DIR);
54
+ console.log(chalk.green('✓ Removed .aiflow/'));
55
+
56
+ // Remove .claude/skills, hooks, settings.json — but keep the rest (e.g. context user may want)
57
+ const claudeDir = path.join(PROJECT_DIR, '.claude');
58
+ const skillsDir = path.join(claudeDir, 'skills');
59
+ const hooksDir = path.join(claudeDir, 'hooks');
60
+ const settingsFile = path.join(claudeDir, 'settings.json');
61
+
62
+ if (await fs.pathExists(skillsDir)) {
63
+ await fs.remove(skillsDir);
64
+ console.log(chalk.green('✓ Removed .claude/skills/'));
65
+ }
66
+
67
+ if (await fs.pathExists(hooksDir)) {
68
+ await fs.remove(hooksDir);
69
+ console.log(chalk.green('✓ Removed .claude/hooks/'));
70
+ }
71
+
72
+ if (await fs.pathExists(settingsFile)) {
73
+ // Only remove the _aiflowKit hook entry, not the whole file
74
+ const settings = await fs.readJson(settingsFile).catch(() => ({}));
75
+ if (settings.hooks?.SessionStart) {
76
+ settings.hooks.SessionStart = settings.hooks.SessionStart.filter(
77
+ h => !h._aiflowKit
78
+ );
79
+ if (settings.hooks.SessionStart.length === 0) {
80
+ delete settings.hooks.SessionStart;
81
+ }
82
+ await fs.writeJson(settingsFile, settings, { spaces: 2 });
83
+ console.log(chalk.green('✓ Removed ai-flow-kit hook from .claude/settings.json'));
84
+ }
85
+ }
86
+
87
+ // Remove .rules/
88
+ const rulesDir = path.join(PROJECT_DIR, '.rules');
89
+ if (await fs.pathExists(rulesDir)) {
90
+ await fs.remove(rulesDir);
91
+ console.log(chalk.green('✓ Removed .rules/'));
92
+ }
93
+
94
+ // Remove Codex assets. config.toml only if it still carries our header —
95
+ // a hand-edited config belongs to the developer.
96
+ const codexDir = path.join(PROJECT_DIR, '.codex');
97
+ const codexSkillsDir = path.join(codexDir, 'skills');
98
+ const codexConfig = path.join(codexDir, 'config.toml');
99
+
100
+ if (await fs.pathExists(codexSkillsDir)) {
101
+ await fs.remove(codexSkillsDir);
102
+ console.log(chalk.green('✓ Removed .codex/skills/'));
103
+ }
104
+ if (await fs.pathExists(codexConfig)) {
105
+ const cfg = await fs.readFile(codexConfig, 'utf-8').catch(() => '');
106
+ if (cfg.includes('# ai-flow-kit managed')) {
107
+ await fs.remove(codexConfig);
108
+ console.log(chalk.green(' Removed .codex/config.toml'));
109
+ } else {
110
+ console.log(chalk.gray(' Kept .codex/config.toml (hand-managed — not ours to delete)'));
111
+ }
112
+ }
113
+ // Drop .codex/ only when nothing of the developer's is left in it
114
+ if (await fs.pathExists(codexDir)) {
115
+ const leftovers = await fs.readdir(codexDir);
116
+ if (leftovers.length === 0) await fs.remove(codexDir);
117
+ }
118
+
119
+ // Clean up AI Tool files (CLAUDE.md, AGENTS.md, .cursorrules, etc.)
120
+ const { AI_TOOL_FILES } = require('./init');
121
+ const markerStart = '<!-- aiflow-kit-start -->';
122
+ const markerEnd = '<!-- aiflow-kit-end -->';
123
+
124
+ for (const tool in AI_TOOL_FILES) {
125
+ const filePath = path.join(PROJECT_DIR, AI_TOOL_FILES[tool]);
126
+ if (!(await fs.pathExists(filePath))) continue;
127
+
128
+ let content = await fs.readFile(filePath, 'utf-8');
129
+ let cleaned = false;
130
+
131
+ if (content.includes(markerStart) && content.includes(markerEnd)) {
132
+ // Precise removal using markers
133
+ const startIndex = content.indexOf(markerStart);
134
+ const endIndex = content.indexOf(markerEnd) + markerEnd.length;
135
+ content = content.slice(0, startIndex).trim() + '\n' + content.slice(endIndex).trim();
136
+ content = content.trim();
137
+ cleaned = true;
138
+ } else if (content.includes('## AI Skill Registry (Superpowers)')) {
139
+ // Fallback for legacy installs: remove sections by headers
140
+ console.log(chalk.yellow(` ⚠ Found legacy aiflow sections in ${AI_TOOL_FILES[tool]}`));
141
+ const ok = await confirm({ message: `Remove ai-flow-kit sections from ${AI_TOOL_FILES[tool]}?`, default: true });
142
+ if (ok) {
143
+ // Heuristic: remove from "## AI Skill Registry" or "# Claude AI System Instructions"
144
+ // This is simple and covers most cases. For complex cases, user should manual clean.
145
+ const headers = [
146
+ '# Claude AI System Instructions',
147
+ '## AI Skill Registry (Superpowers)',
148
+ '## MANDATORY: Strict Gate Workflow'
149
+ ];
150
+ let minIndex = content.length;
151
+ for (const h of headers) {
152
+ const idx = content.indexOf(h);
153
+ if (idx !== -1 && idx < minIndex) minIndex = idx;
154
+ }
155
+ if (minIndex < content.length) {
156
+ content = content.slice(0, minIndex).trim();
157
+ cleaned = true;
158
+ }
159
+ }
160
+ }
161
+
162
+ if (cleaned) {
163
+ if (content.length === 0) {
164
+ await fs.remove(filePath);
165
+ console.log(chalk.green(`✓ Deleted ${AI_TOOL_FILES[tool]} (it was aiflow-only)`));
166
+ } else {
167
+ await fs.writeFile(filePath, content);
168
+ console.log(chalk.green(`✓ Cleaned up ai-flow-kit instructions from ${AI_TOOL_FILES[tool]}`));
169
+ }
170
+ }
171
+ }
172
+
173
+ console.log(chalk.green('\n✨ ai-flow-kit removed from project.'));
174
+ console.log(chalk.gray('To reinstall: aiflow init'));
175
+ }
176
+
177
+ // ──────────────────────────────────────────────────────────────
178
+ // Case 2: Uninstall the global npm package
179
+ // ──────────────────────────────────────────────────────────────
180
+
181
+ async function removeGlobal() {
182
+ console.log(chalk.yellow('\nThis will uninstall ai-flow-kit globally from your system.'));
183
+ console.log(chalk.gray('Project files (.aiflow/, .claude/, .rules/) are NOT affected.\n'));
184
+
185
+ const ok = await confirm({ message: 'Uninstall global package?' });
186
+ if (!ok) {
187
+ console.log(chalk.gray('Cancelled.'));
188
+ return;
189
+ }
190
+
191
+ const { execSync } = require('child_process');
192
+ try {
193
+ console.log(chalk.blue('Running: npm uninstall -g ai-flow-kit ...'));
194
+ execSync('npm uninstall -g ai-flow-kit', { stdio: 'inherit' });
195
+ console.log(chalk.green('\n✨ ai-flow-kit uninstalled globally.'));
196
+ console.log(chalk.gray('The `aiflow` command is no longer available.'));
197
+ } catch (err) {
198
+ // execSync throws on non-zero exit; message already printed via stdio: inherit
199
+ console.log(chalk.red('\nFailed to uninstall. Try manually: npm uninstall -g ai-flow-kit'));
200
+ }
201
+ }
202
+
203
+ // ──────────────────────────────────────────────────────────────
204
+ // Case 3: Remove a specific cached version from .aiflow/versions/
205
+ // ──────────────────────────────────────────────────────────────
206
+
207
+ async function removeVersion(version) {
208
+ if (!(await fs.pathExists(STATE_FILE))) {
209
+ console.log(chalk.red('Project is not initialized. Run `aiflow init` first.'));
210
+ return;
211
+ }
212
+
213
+ const versionsDir = path.join(AIFLOW_DIR, 'versions');
214
+ const targetDir = path.join(versionsDir, version);
215
+
216
+ if (!(await fs.pathExists(targetDir))) {
217
+ console.log(chalk.red(`Version v${version} is not cached in this project.`));
218
+
219
+ // Show what's available
220
+ if (await fs.pathExists(versionsDir)) {
221
+ const available = await fs.readdir(versionsDir);
222
+ if (available.length) {
223
+ console.log(chalk.gray(`Cached versions: ${available.map(v => `v${v}`).join(', ')}`));
224
+ }
225
+ }
226
+ return;
227
+ }
228
+
229
+ // Prevent removing the currently active version
230
+ const state = await fs.readJson(STATE_FILE);
231
+ if (state.current_version === version) {
232
+ console.log(chalk.red(`v${version} is currently active — cannot remove it.`));
233
+ console.log(chalk.gray('Switch to another version first: aiflow use <version>'));
234
+ return;
235
+ }
236
+
237
+ const ok = await confirm({ message: `Delete cached version v${version}?` });
238
+ if (!ok) {
239
+ console.log(chalk.gray('Cancelled.'));
240
+ return;
241
+ }
242
+
243
+ await fs.remove(targetDir);
244
+ console.log(chalk.green(`✓ Removed cached version v${version}.`));
245
+
246
+ // Show remaining versions
247
+ const remaining = await fs.readdir(versionsDir).catch(() => []);
248
+ if (remaining.length) {
249
+ console.log(chalk.gray(`Remaining: ${remaining.map(v => `v${v}`).join(', ')}`));
250
+ }
251
+ }
package/scripts/update.js CHANGED
@@ -126,7 +126,7 @@ module.exports = async function update(options = {}) {
126
126
 
127
127
  // Sync instruction files with the updated skills.
128
128
  // Support both old 'framework' (singular string) and new 'frameworks' (array).
129
- const { setupFramework, AI_TOOL_FILES, ensureAiflowGitignored, setupClaudeCommands, copyDocsToProject } = require('./init');
129
+ const { setupFramework, AI_TOOL_FILES, ensureAiflowGitignored, setupClaudeCommands, copyDocsToProject, setupCodex } = require('./init');
130
130
  const frameworks = state.frameworks || (state.framework ? [state.framework] : []);
131
131
  const selectedTools = state.aiTools || Object.keys(AI_TOOL_FILES);
132
132
  for (const fw of frameworks) {
@@ -136,6 +136,10 @@ module.exports = async function update(options = {}) {
136
136
  // Install / refresh Claude Code custom commands (.claude/commands/)
137
137
  await setupClaudeCommands(projectDir);
138
138
 
139
+ // Refresh Codex assets (.codex/skills/, .codex/config.toml) when codex is selected.
140
+ // Runs after the skill copy above so the mirror picks up the new version's skills.
141
+ await setupCodex(projectDir, selectedTools);
142
+
139
143
  // Refresh .aiflow/docs with the latest docs/common/ (feeds `ak ask` / aiflow-help).
140
144
  // Without this, docs promoted after the project's `ak init` never reach the project.
141
145
  await copyDocsToProject(projectDir);
package/scripts/use.js CHANGED
@@ -1072,11 +1072,15 @@ async function suggestNextStep() {
1072
1072
 
1073
1073
  console.log(chalk.cyan("\nNext Steps:"));
1074
1074
 
1075
- const hasCLI = aiTools.includes("claude") || aiTools.includes("gemini");
1075
+ const hasCLI =
1076
+ aiTools.includes("claude") ||
1077
+ aiTools.includes("gemini") ||
1078
+ aiTools.includes("codex");
1076
1079
  const hasIDE =
1077
1080
  aiTools.includes("claude") ||
1078
1081
  aiTools.includes("cursor") ||
1079
- aiTools.includes("copilot");
1082
+ aiTools.includes("copilot") ||
1083
+ aiTools.includes("codex");
1080
1084
 
1081
1085
  if (hasCLI) {
1082
1086
  console.log(chalk.white("\n CLI:"));
@@ -1091,6 +1095,11 @@ async function suggestNextStep() {
1091
1095
  ` ${++step}. ${chalk.white("Gemini:")} Run ${chalk.bold.green("gemini")} then type ${chalk.bold.green('"start"')} or ${chalk.bold.green('"Gate 1"')}.`,
1092
1096
  );
1093
1097
  }
1098
+ if (aiTools.includes("codex")) {
1099
+ console.log(
1100
+ ` ${++step}. ${chalk.white("Codex:")} Run ${chalk.bold.green("codex")} then use ${chalk.bold.green("/ak-coding")} ${chalk.gray("(or type \"Gate 1\")")}.`,
1101
+ );
1102
+ }
1094
1103
  }
1095
1104
 
1096
1105
  if (hasIDE) {
@@ -1098,6 +1107,16 @@ async function suggestNextStep() {
1098
1107
  console.log(
1099
1108
  ` Run ${chalk.bold.green("aiflow prompt")} → prompt auto-copied to clipboard → paste into your AI extension chat.`,
1100
1109
  );
1110
+ if (aiTools.includes("codex")) {
1111
+ console.log(
1112
+ ` ${chalk.white("Codex (VS Code extension / ChatGPT desktop app):")} open this folder, then run ${chalk.bold.green("/ak-coding")} in the Codex panel.`,
1113
+ );
1114
+ console.log(
1115
+ chalk.gray(
1116
+ " Codex has no session-start hook — start a NEW Codex session after `ak use` so it re-reads AGENTS.md and the ticket context.",
1117
+ ),
1118
+ );
1119
+ }
1101
1120
  }
1102
1121
 
1103
1122
  console.log(
@@ -1,36 +0,0 @@
1
- # Code Review Checklist — Java / Spring Boot
2
-
3
- ## Architecture
4
- - [ ] Controller only handles HTTP (parse request, call service, return response) — no business logic
5
- - [ ] Business logic resides in Service, not in Controller or Repository
6
- - [ ] Repository only performs data access — no business logic
7
- - [ ] Entity is not exposed directly — always use DTOs
8
-
9
- ## Code Quality
10
- - [ ] No `@Autowired` field injection — use constructor injection (Lombok `@RequiredArgsConstructor`)
11
- - [ ] No `@Data` on Entity — use `@Getter @Setter` separately
12
- - [ ] No `new RuntimeException()` — create specific custom exceptions
13
- - [ ] No magic numbers/strings — use named constants
14
- - [ ] No dead code (commented-out code, unused variables)
15
-
16
- ## Database & Performance
17
- - [ ] No N+1 queries — use `@EntityGraph` or `JOIN FETCH`
18
- - [ ] Lists are paginated — do not return the entire table
19
- - [ ] Read-only service methods have `@Transactional(readOnly = true)`
20
- - [ ] Indexes on columns frequently used in WHERE/JOIN
21
-
22
- ## Testing
23
- - [ ] Unit tests for Service layer (Mockito)
24
- - [ ] Tests cover: happy path, error cases, edge cases
25
- - [ ] Do not mock things that don't need mocking
26
-
27
- ## Security
28
- - [ ] Input is validated using Bean Validation (`@Valid`)
29
- - [ ] No logging of passwords, tokens, or PII
30
- - [ ] SQL injection is not possible (use parameterized JPA/JPQL)
31
- - [ ] Stack traces are not returned to the client
32
-
33
- ## Logging
34
- - [ ] Use `@Slf4j` + SLF4J — no `System.out.println`
35
- - [ ] Correct log levels: `info` (normal), `warn` (recoverable), `error` (unexpected + exception)
36
- - [ ] Log messages have enough context for debugging (include ID, action)
@@ -1,14 +0,0 @@
1
- # ML Review Checklist
2
-
3
- Before completing Gate 4 and creating a Pull Request, verify:
4
-
5
- - [ ] Evaluation metric matches the problem type and business goal defined in Gate 1.
6
- - [ ] Model beats the baseline by at least the success threshold defined in Gate 1.
7
- - [ ] No data leakage — all three types re-checked: target leakage, train/test contamination, and temporal leakage.
8
- - [ ] Result is reproducible: re-run with the logged seed, pinned environment, and saved config produces the same metric.
9
- - [ ] No overfitting: train / validation / test metric gap is acceptable and documented.
10
- - [ ] Error analysis performed: worst slices, classes, or failure cases identified and documented.
11
- - [ ] Robustness assessed: behavior under noise, shifted inputs, or edge cases verified; fairness across sensitive slices checked where applicable.
12
- - [ ] All experiments tracked: params, metrics, data version, and git commit SHA logged in MLflow / wandb for every run (including failures).
13
- - [ ] Model card present: intended use, training data, evaluation metrics, known limitations, and owner documented.
14
- - [ ] Impact on data pipeline assessed via `impact-analysis` skill and implications documented.
@@ -1,9 +0,0 @@
1
- # Code Review Checklist
2
-
3
- Before creating a Pull Request, verify:
4
- - [ ] Code compiles and passes all local tests.
5
- - [ ] No strict dependency on local environment (hardcoded IPs, paths).
6
- - [ ] Security checks: No exposed API keys, no raw SQL vulnerability.
7
- - [ ] Impact Analysis run (via `impact-analysis` skill) and implications documented.
8
- - [ ] Naming and Code Style rules observed.
9
- - [ ] Feature is covered by unit/feature tests where applicable.