newaflux 1.2.0 → 1.3.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.
@@ -2,6 +2,7 @@
2
2
  name: fluxn-executor
3
3
  description: Executa fases do plano Newa Flux com commits atômicos. Spawned por /fluxn:execute.
4
4
  tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch
5
+ permissionMode: acceptEdits
5
6
  color: green
6
7
  ---
7
8
 
@@ -2,6 +2,7 @@
2
2
  name: fluxn-researcher
3
3
  description: Pesquisa codebase e web para Newa Flux. Spawned por /fluxn:init e /fluxn:research.
4
4
  tools: Read, Bash, Grep, Glob, Write, WebSearch, WebFetch
5
+ permissionMode: acceptEdits
5
6
  color: cyan
6
7
  ---
7
8
 
@@ -2,6 +2,7 @@
2
2
  name: fluxn-verifier
3
3
  description: Verificação READ-ONLY de implementação vs plano. Spawned por /fluxn:verify.
4
4
  tools: Read, Write, Bash, Grep, Glob
5
+ permissionMode: acceptEdits
5
6
  color: yellow
6
7
  ---
7
8
 
package/bin/install.js CHANGED
@@ -32,6 +32,27 @@ function error(msg) {
32
32
  log(`${c.red} ✗${c.reset} ${msg}`);
33
33
  }
34
34
 
35
+ // --- Recommended permissions ---
36
+ const RECOMMENDED_PERMISSIONS = [
37
+ "WebSearch",
38
+ "WebFetch",
39
+ "Task(fluxn-researcher)",
40
+ "Task(fluxn-executor)",
41
+ "Task(fluxn-verifier)",
42
+ "Bash(mkdir -p *)",
43
+ "Bash(rm -f .fluxn/*)",
44
+ "Bash(rm -rf .fluxn/init)",
45
+ "Bash(cp *)",
46
+ "Bash(ls *)",
47
+ "Bash(git status)",
48
+ "Bash(git log *)",
49
+ "Bash(git diff *)",
50
+ "Bash(git show *)",
51
+ "Bash(git add *)",
52
+ "Bash(git commit *)",
53
+ "Bash(npx *)",
54
+ ];
55
+
35
56
  // --- Args ---
36
57
  const args = process.argv.slice(2);
37
58
  const flags = new Set(args.map((a) => a.toLowerCase()));
@@ -39,6 +60,7 @@ const flags = new Set(args.map((a) => a.toLowerCase()));
39
60
  const isUninstall = flags.has("--uninstall") || flags.has("-u");
40
61
  const isLocal = flags.has("--local") || flags.has("-l");
41
62
  const isGlobal = flags.has("--global") || flags.has("-g");
63
+ const isOptimized = flags.has("--optimized") || flags.has("-o");
42
64
  const isHelp = flags.has("--help") || flags.has("-h");
43
65
 
44
66
  if (isHelp) {
@@ -49,12 +71,14 @@ Simplified multi-agent workflow for Claude Code.
49
71
  ${c.bold}Usage:${c.reset}
50
72
  npx newaflux Install globally (default)
51
73
  npx newaflux --local Install in current project
74
+ npx newaflux --optimized Install with optimized model profile
52
75
  npx newaflux --uninstall Remove installation
53
76
  npx newaflux --help Show this help
54
77
 
55
78
  ${c.bold}Options:${c.reset}
56
79
  -g, --global Install to ~/.claude/ (all projects)
57
80
  -l, --local Install to ./.claude/ (current project)
81
+ -o, --optimized Set optimized model profile (sonnet/opus routing)
58
82
  -u, --uninstall Remove Newa Flux files
59
83
  -h, --help Show help
60
84
  `);
@@ -83,6 +107,7 @@ const COMMANDS = [
83
107
  "verify.md",
84
108
  "go.md",
85
109
  "language.md",
110
+ "profile.md",
86
111
  ];
87
112
 
88
113
  // --- Copy helper ---
@@ -137,6 +162,63 @@ function install() {
137
162
  copied++;
138
163
  }
139
164
 
165
+ // Set optimized profile if requested
166
+ if (isOptimized) {
167
+ const fluxnDir = path.join(process.cwd(), ".fluxn");
168
+ if (!fs.existsSync(fluxnDir)) {
169
+ fs.mkdirSync(fluxnDir, { recursive: true });
170
+ }
171
+ const configPath = path.join(fluxnDir, "config.md");
172
+ let configContent = "# Newa Flux Config\n\n**Model Profile:** optimized\n";
173
+ if (fs.existsSync(configPath)) {
174
+ const existing = fs.readFileSync(configPath, "utf8");
175
+ const langMatch = existing.match(/^\*\*Language:\*\*.*$/m);
176
+ if (langMatch) {
177
+ configContent = "# Newa Flux Config\n\n" + langMatch[0] + "\n\n**Model Profile:** optimized\n";
178
+ }
179
+ }
180
+ fs.writeFileSync(configPath, configContent, "utf8");
181
+ success("Optimized profile set: researchers=sonnet, executor=opus, verifier=sonnet");
182
+ }
183
+
184
+ // Merge recommended permissions into settings.json
185
+ const settingsDir = isLocal
186
+ ? path.join(process.cwd(), ".claude")
187
+ : path.join(os.homedir(), ".claude");
188
+ const settingsPath = path.join(settingsDir, "settings.json");
189
+ let rulesAdded = 0;
190
+
191
+ try {
192
+ if (!fs.existsSync(settingsDir)) {
193
+ fs.mkdirSync(settingsDir, { recursive: true });
194
+ }
195
+
196
+ let settings = { permissions: { allow: [] } };
197
+ if (fs.existsSync(settingsPath)) {
198
+ const raw = fs.readFileSync(settingsPath, "utf8");
199
+ settings = JSON.parse(raw);
200
+ if (!settings.permissions) {
201
+ settings.permissions = {};
202
+ }
203
+ if (!Array.isArray(settings.permissions.allow)) {
204
+ settings.permissions.allow = [];
205
+ }
206
+ }
207
+
208
+ const existingRules = new Set(settings.permissions.allow);
209
+ for (const rule of RECOMMENDED_PERMISSIONS) {
210
+ if (!existingRules.has(rule)) {
211
+ settings.permissions.allow.push(rule);
212
+ rulesAdded++;
213
+ }
214
+ }
215
+
216
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
217
+ success(`${rulesAdded} permission rules configured`);
218
+ } catch (err) {
219
+ warn(`Could not update settings.json: ${err.message}`);
220
+ }
221
+
140
222
  // Write version file
141
223
  const versionFile = path.join(targetDir, "newaflux-version.txt");
142
224
  fs.writeFileSync(versionFile, VERSION, "utf8");
@@ -154,6 +236,7 @@ function install() {
154
236
  log(` ${c.cyan}/fluxn:verify${c.reset} Verify implementation`);
155
237
  log(` ${c.cyan}/fluxn:go${c.reset} Research + Plan in one shot`);
156
238
  log(` ${c.cyan}/fluxn:language${c.reset} Set output language`);
239
+ log(` ${c.cyan}/fluxn:profile${c.reset} Switch model profile`);
157
240
  log("");
158
241
  log(
159
242
  ` ${c.dim}Start with: /fluxn:init in Claude Code${c.reset}`
@@ -43,6 +43,11 @@ mkdir -p .fluxn/phases
43
43
 
44
44
  ## Step 4: Execute Phase
45
45
 
46
+ ### Model Resolution
47
+ Read `.fluxn/config.md`. If it contains `**Model Profile:** optimized`:
48
+ - Add `model: "opus"` to the executor Task tool call below
49
+ If `default` or no Model Profile line: do not pass model parameter.
50
+
46
51
  For the target phase, spawn ONE `fluxn-executor` agent:
47
52
 
48
53
  ```
@@ -71,6 +71,11 @@ rm -f .fluxn/research/agent-*.md
71
71
 
72
72
  ### 1.4: Launch 4 Researchers in Parallel
73
73
 
74
+ ### Model Resolution
75
+ Read `.fluxn/config.md`. If it contains `**Model Profile:** optimized`:
76
+ - Add `model: "sonnet"` to each researcher Task tool call below
77
+ If `default` or no Model Profile line: do not pass model parameter.
78
+
74
79
  Spawn 4 `fluxn-researcher` agents using the Task tool, ALL IN PARALLEL.
75
80
 
76
81
  **If new-project:**
@@ -28,6 +28,11 @@ mkdir -p .fluxn/init
28
28
 
29
29
  ## Step 3: Launch 4 Researchers in Parallel
30
30
 
31
+ ### Model Resolution
32
+ Read `.fluxn/config.md`. If it contains `**Model Profile:** optimized`:
33
+ - Add `model: "sonnet"` to each researcher Task tool call below
34
+ If `default` or no Model Profile line: do not pass model parameter.
35
+
31
36
  Spawn 4 `fluxn-researcher` agents using the Task tool, ALL IN PARALLEL (same message, 4 tool calls):
32
37
 
33
38
  ### Agent 1 — Tech Stack
@@ -0,0 +1,83 @@
1
+ ---
2
+ description: "Switch model profile (default/optimized): /fluxn:profile [default | optimized]"
3
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob
4
+ ---
5
+
6
+ # /fluxn:profile — Model Profile Configuration
7
+
8
+ $ARGUMENTS
9
+
10
+ You are the **model profile handler** for Newa Flux. Your job: show or switch the active model profile that controls which AI models are assigned to each agent.
11
+
12
+ ## Step 1: Load Context
13
+
14
+ **Language check:** Read `.fluxn/config.md` if it exists. If it contains a `**Language:**` setting, use that language for ALL user-facing output (confirmations, tables, status messages). Internal files (config.md) remain in English.
15
+
16
+ Read `.fluxn/config.md` if it exists. Look for the `**Model Profile:**` line to determine the current profile.
17
+
18
+ If the file does not exist or has no `**Model Profile:**` line, the current profile is `default`.
19
+
20
+ ## Step 2: Parse Argument
21
+
22
+ The profile argument comes from the user's arguments: **$ARGUMENTS**
23
+
24
+ Valid values:
25
+ - `default` — all agents inherit the parent model (no model parameter passed)
26
+ - `optimized` — assigns specific models per agent for cost/speed optimization
27
+
28
+ If the argument is not `default` or `optimized` and is not empty, tell the user the argument is invalid and show the two valid options.
29
+
30
+ ## Step 3: Show or Update
31
+
32
+ ### If no argument was provided
33
+
34
+ Show the current profile status and the model assignment table for that profile. Do not modify any files.
35
+
36
+ ### If an argument was provided
37
+
38
+ Update `.fluxn/config.md`:
39
+
40
+ ```bash
41
+ mkdir -p .fluxn
42
+ ```
43
+
44
+ - If `.fluxn/config.md` does not exist, create it with the profile setting.
45
+ - If it exists, read it first and add or replace the `**Model Profile:**` line. Preserve all other settings (e.g., `**Language:**`).
46
+
47
+ The `**Model Profile:**` line format:
48
+ ```
49
+ **Model Profile:** [default | optimized]
50
+ ```
51
+
52
+ ## Step 4: Display Profile Table
53
+
54
+ Show the user (in the configured language) the model assignment table for the active profile:
55
+
56
+ ### Default Profile
57
+
58
+ | Role | Agent | Model |
59
+ |------|-------|-------|
60
+ | Researcher | fluxn-researcher | inherit (parent model) |
61
+ | Executor | fluxn-executor | inherit (parent model) |
62
+ | Verifier | fluxn-verifier | inherit (parent model) |
63
+ | Plan | inline (orchestrator) | inherit (parent model) |
64
+
65
+ All agents use the same model as the parent Claude Code session. No `model` parameter is passed to Task tool calls.
66
+
67
+ ### Optimized Profile
68
+
69
+ | Role | Agent | Model |
70
+ |------|-------|-------|
71
+ | Researcher | fluxn-researcher | sonnet |
72
+ | Executor | fluxn-executor | opus |
73
+ | Verifier | fluxn-verifier | sonnet |
74
+ | Plan | inline (orchestrator) | inherit (parent model) |
75
+
76
+ Researchers and verifier use Sonnet for speed and cost savings. Executor uses Opus for maximum code quality. Planning runs inline and inherits the parent model.
77
+
78
+ ## Step 5: Confirm
79
+
80
+ Tell the user (in the configured language):
81
+ - Current profile: `[profile name]`
82
+ - If they just changed it: "Profile updated. The new model assignments will apply to all future agent spawns."
83
+ - If they just viewed it: "To switch profiles, run `/fluxn:profile default` or `/fluxn:profile optimized`."
@@ -71,6 +71,11 @@ rm -f .fluxn/research/agent-*.md
71
71
 
72
72
  ## Step 4: Launch 4 Researchers in Parallel
73
73
 
74
+ ### Model Resolution
75
+ Read `.fluxn/config.md`. If it contains `**Model Profile:** optimized`:
76
+ - Add `model: "sonnet"` to each researcher Task tool call below
77
+ If `default` or no Model Profile line: do not pass model parameter.
78
+
74
79
  Spawn 4 `fluxn-researcher` agents using the Task tool, ALL IN PARALLEL.
75
80
 
76
81
  Each agent receives PROJECT.md content as base context in their prompt.
@@ -23,6 +23,11 @@ If no phase-done.md files exist, tell the user to run `/fluxn:execute` first.
23
23
 
24
24
  ## Step 2: Spawn Verifier
25
25
 
26
+ ### Model Resolution
27
+ Read `.fluxn/config.md`. If it contains `**Model Profile:** optimized`:
28
+ - Add `model: "sonnet"` to the verifier Task tool call below
29
+ If `default` or no Model Profile line: do not pass model parameter.
30
+
26
31
  Spawn ONE `fluxn-verifier` agent:
27
32
 
28
33
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newaflux",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Simplified multi-agent workflow framework for Claude Code. 3 agents + 7 commands = 10 files.",
5
5
  "bin": {
6
6
  "newaflux": "bin/install.js"