ai-consultants 2.10.8 → 2.17.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.
- package/.claude/commands/ai-consultants:consult.md +18 -15
- package/.claude/commands/ai-consultants:debate.md +14 -15
- package/CLAUDE.md +222 -31
- package/README.md +72 -61
- package/SKILL.md +9 -7
- package/bin/ai-consultants +99 -1
- package/docs/COST_RATES.md +55 -51
- package/docs/SETUP.md +23 -13
- package/docs/SMART_ROUTING.md +62 -15
- package/docs/cost_rates.json +364 -100
- package/docs/releases/v2.10.9.md +123 -0
- package/docs/releases/v2.11.0.md +163 -0
- package/docs/releases/v2.12.0.md +182 -0
- package/docs/releases/v2.13.0.md +179 -0
- package/docs/releases/v2.13.1.md +133 -0
- package/docs/releases/v2.14.0.md +124 -0
- package/docs/releases/v2.14.1.md +70 -0
- package/docs/releases/v2.14.2.md +77 -0
- package/docs/releases/v2.15.0.md +72 -0
- package/docs/releases/v2.15.1.md +80 -0
- package/docs/releases/v2.16.0.md +71 -0
- package/docs/releases/v2.17.0.md +62 -0
- package/package.json +10 -2
- package/references/affinity.json +57 -0
- package/references/configuration.md +137 -13
- package/references/details.md +13 -0
- package/scripts/build_context.sh +96 -36
- package/scripts/config.sh +152 -44
- package/scripts/configure.sh +34 -32
- package/scripts/consult_all.sh +97 -43
- package/scripts/doctor.sh +483 -10
- package/scripts/hooks/pre-commit +39 -0
- package/scripts/install-hooks.sh +49 -0
- package/scripts/install.sh +1 -1
- package/scripts/lib/api.sh +7 -7
- package/scripts/lib/api_query.sh +1 -0
- package/scripts/lib/cache.sh +1 -1
- package/scripts/lib/chunking.sh +4 -3
- package/scripts/lib/code_optimizer.sh +2 -2
- package/scripts/lib/common.sh +39 -8
- package/scripts/lib/costs.sh +19 -3
- package/scripts/lib/orchestration.sh +374 -0
- package/scripts/lib/progress.sh +2 -2
- package/scripts/lib/reflection.sh +7 -4
- package/scripts/lib/routing.sh +104 -189
- package/scripts/lib/session.sh +4 -3
- package/scripts/lib/symbol_map.sh +2 -0
- package/scripts/lib/test_helpers.sh +82 -0
- package/scripts/lib/user_config.sh +161 -0
- package/scripts/lib/voting.sh +1 -1
- package/scripts/peer_review.sh +6 -5
- package/scripts/preflight_check.sh +19 -442
- package/scripts/query_claude.sh +2 -2
- package/scripts/query_gemini.sh +26 -9
- package/scripts/query_ollama.sh +1 -0
- package/scripts/setup_wizard.sh +6 -6
- package/scripts/synthesize.sh +7 -0
- package/scripts/test_all.sh +65 -0
- package/scripts/test_bin.sh +139 -0
- package/scripts/test_context_optimization.sh +300 -0
- package/scripts/test_doctor.sh +264 -0
- package/scripts/test_fixtures/context/sample.json +13 -0
- package/scripts/test_fixtures/context/sample.py +90 -0
- package/scripts/test_fixtures/context/sample.sh +66 -0
- package/scripts/test_fixtures/context/sample.txt +11 -0
- package/scripts/test_orchestration.sh +203 -0
- package/scripts/test_routing_parity.sh +180 -0
- package/scripts/test_set_e_safety.sh +118 -0
- package/scripts/test_suite.sh +59 -6
- package/scripts/test_user_config.sh +359 -0
|
@@ -14,26 +14,28 @@ Query multiple AI models for expert opinions on a coding question.
|
|
|
14
14
|
|
|
15
15
|
1. If no question provided in $ARGUMENTS, ask the user what they want to consult about.
|
|
16
16
|
|
|
17
|
-
2. **File context handling**:
|
|
18
|
-
If file paths are found:
|
|
19
|
-
- Extract each file path token from $ARGUMENTS
|
|
20
|
-
- Read each file using the **Read** tool
|
|
21
|
-
- Build an enriched query by replacing file path tokens with their inline contents:
|
|
22
|
-
```
|
|
23
|
-
<original question text without file paths>
|
|
17
|
+
2. **File context handling**: Identify which strings in $ARGUMENTS refer to files the user wants the consultants to look at. Use your judgment — verify existence via `Glob` or `Bash ls` when uncertain. This replaces fragile regex detection: a `Makefile`, `Dockerfile`, dotfile, or path without a common extension is still a file; an URL or regex pattern in the question text is not.
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
For each file you identify:
|
|
20
|
+
- Strip the file path from the question text.
|
|
21
|
+
- Decide its relevance tag: `PRIMARY` (the focus of the question — what the consultants should critique) or `CONTEXT` (ambient reference — the consultants should read but not necessarily critique). Default to `PRIMARY` if every referenced file is central.
|
|
22
|
+
- Pass each path as a positional argument to `consult_all.sh` with the syntax `path/to/file@TAG` (omit `@TAG` to default to `PRIMARY`).
|
|
23
|
+
|
|
24
|
+
**Do not inline file contents into the query string.** `build_context.sh` reads files directly from the filesystem and runs the AST optimization pipeline — passing file paths as arguments is what enables it. Inlining defeats the optimization and inflates the consultants' context.
|
|
25
|
+
|
|
26
|
+
**Note (Claude only):** Do not use your `Read` tool to dump file contents into the query. `build_context.sh` handles file reading itself, without the `N\t` line-number prefix that `Read` adds.
|
|
30
27
|
|
|
31
28
|
3. **Run the consultation**:
|
|
32
29
|
```bash
|
|
33
|
-
cd "${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}" && INVOKING_AGENT=claude ./scripts/consult_all.sh '<
|
|
30
|
+
cd "${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}" && INVOKING_AGENT=claude ./scripts/consult_all.sh '<question>' <file1[@TAG]> <file2[@TAG]> ...
|
|
34
31
|
```
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
- `<question>` is the question text with file paths stripped. Use single quotes to prevent shell expansion.
|
|
33
|
+
- Each `<fileN>` is a file path, optionally suffixed with `@PRIMARY` or `@CONTEXT`.
|
|
34
|
+
- **If the question text exceeds ~8KB or contains awkward quoting**, write it to a tmpfile and use `--query-file <path>` instead:
|
|
35
|
+
```bash
|
|
36
|
+
cd "${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}" && INVOKING_AGENT=claude ./scripts/consult_all.sh --query-file /tmp/question.txt <file1[@TAG]> ...
|
|
37
|
+
```
|
|
38
|
+
- **Capture the last line of stdout** — it contains the output directory path (e.g., `/tmp/ai_consultations/20260315_143022_12345/`).
|
|
37
39
|
|
|
38
40
|
4. **Read the results** from the output directory captured in step 3:
|
|
39
41
|
- Read `<output_dir>/report.md` using the **Read** tool
|
|
@@ -85,6 +87,7 @@ Query multiple AI models for expert opinions on a coding question.
|
|
|
85
87
|
| `ENABLE_DEBATE=true` | Enable multi-round debate for deeper analysis |
|
|
86
88
|
| `ENABLE_SMART_ROUTING=true` | Auto-select best consultants for the question type |
|
|
87
89
|
| `DEBATE_ROUNDS=2` | Number of debate rounds (1-3) |
|
|
90
|
+
| `FORCE_PROJECT_TREE=true` | Include the project tree even for pointed categories (SECURITY, QUICK_SYNTAX, etc.) |
|
|
88
91
|
|
|
89
92
|
## Follow-up
|
|
90
93
|
|
|
@@ -21,26 +21,25 @@ Run a multi-round debate where AI consultants critique each other's responses an
|
|
|
21
21
|
|
|
22
22
|
1. If no question provided in $ARGUMENTS, ask the user what they want to debate.
|
|
23
23
|
|
|
24
|
-
2. **File context handling**:
|
|
25
|
-
If file paths are found:
|
|
26
|
-
- Extract each file path token from $ARGUMENTS
|
|
27
|
-
- Read each file using the **Read** tool
|
|
28
|
-
- Build an enriched query by replacing file path tokens with their inline contents:
|
|
29
|
-
```
|
|
30
|
-
<original question text without file paths>
|
|
24
|
+
2. **File context handling**: Identify which strings in $ARGUMENTS refer to files the user wants the consultants to debate over. Use your judgment — verify existence via `Glob` or `Bash ls` when uncertain. A `Makefile`, `Dockerfile`, dotfile, or path without a common extension is still a file; an URL or regex pattern in the question text is not.
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
For each file you identify:
|
|
27
|
+
- Strip the file path from the question text.
|
|
28
|
+
- Decide its relevance tag: `PRIMARY` (the focus of the debate — what the consultants should critique) or `CONTEXT` (ambient reference — read but not necessarily critiqued). Default to `PRIMARY` if every referenced file is central.
|
|
29
|
+
- Pass each path as a positional argument to `consult_all.sh` with the syntax `path/to/file@TAG` (omit `@TAG` to default to `PRIMARY`).
|
|
30
|
+
|
|
31
|
+
**Do not inline file contents into the query string.** `build_context.sh` reads files directly from the filesystem and runs the AST optimization pipeline.
|
|
32
|
+
|
|
33
|
+
**Note (Claude only):** Do not use your `Read` tool to dump file contents into the query. `build_context.sh` handles file reading itself, without the `N\t` line-number prefix that `Read` adds.
|
|
37
34
|
|
|
38
35
|
3. **Run the debate consultation**:
|
|
39
36
|
```bash
|
|
40
|
-
cd "${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}" && INVOKING_AGENT=claude ENABLE_DEBATE=true DEBATE_ROUNDS="${DEBATE_ROUNDS:-2}" ./scripts/consult_all.sh '<
|
|
37
|
+
cd "${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}" && INVOKING_AGENT=claude ENABLE_DEBATE=true DEBATE_ROUNDS="${DEBATE_ROUNDS:-2}" ./scripts/consult_all.sh '<question>' <file1[@TAG]> <file2[@TAG]> ...
|
|
41
38
|
```
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
- `<question>` is the question text with file paths stripped. Use single quotes to prevent shell expansion.
|
|
40
|
+
- Each `<fileN>` is a file path, optionally suffixed with `@PRIMARY` or `@CONTEXT`.
|
|
41
|
+
- **If the question text exceeds ~8KB or contains awkward quoting**, write it to a tmpfile and pass `--query-file <path>` instead of the inline question.
|
|
42
|
+
- **Capture the last line of stdout** — it contains the output directory path.
|
|
44
43
|
|
|
45
44
|
4. **Read the results** from the output directory captured in step 3:
|
|
46
45
|
- Read `<output_dir>/report.md` using the **Read** tool
|
package/CLAUDE.md
CHANGED
|
@@ -6,7 +6,7 @@ AI Consultants is a multi-model AI deliberation system that queries up to 15 AI
|
|
|
6
6
|
|
|
7
7
|
**Self-Exclusion**: The invoking agent is automatically excluded from the panel to prevent self-consultation. Claude Code won't query Claude, Codex CLI won't query Codex, etc.
|
|
8
8
|
|
|
9
|
-
**Version**: 2.
|
|
9
|
+
**Version**: 2.17.0
|
|
10
10
|
|
|
11
11
|
## Distribution
|
|
12
12
|
|
|
@@ -47,13 +47,14 @@ ai-consultants/
|
|
|
47
47
|
│ ├── debate_round.sh # Multi-Agent Debate
|
|
48
48
|
│ ├── classify_question.sh # Question classifier
|
|
49
49
|
│ ├── followup.sh # Follow-up queries
|
|
50
|
-
│ ├── preflight_check.sh #
|
|
50
|
+
│ ├── preflight_check.sh # DEPRECATED v2.10.9 (thin wrapper -> doctor.sh)
|
|
51
51
|
│ └── lib/
|
|
52
52
|
│ ├── common.sh # Shared utilities (logging, panic mode)
|
|
53
53
|
│ ├── personas.sh # Consultant persona definitions
|
|
54
54
|
│ ├── schema.json # JSON output schema
|
|
55
55
|
│ ├── voting.sh # Voting/consensus + confidence intervals
|
|
56
56
|
│ ├── routing.sh # Smart routing + cost-aware routing
|
|
57
|
+
│ ├── orchestration.sh # Dynamic orchestration planner + shapes (v2.16)
|
|
57
58
|
│ ├── session.sh # Session management
|
|
58
59
|
│ ├── costs.sh # Cost tracking + response limits
|
|
59
60
|
│ ├── cache.sh # Semantic caching (v2.3)
|
|
@@ -154,13 +155,15 @@ Each consultant must produce JSON with this minimum structure:
|
|
|
154
155
|
1. `consult_all.sh` receives query, optional files, and flags (`--preset`, `--strategy`)
|
|
155
156
|
2. Applies preset if specified (`apply_preset()` in config.sh)
|
|
156
157
|
3. Classifies the question (`classify_question.sh`)
|
|
157
|
-
4.
|
|
158
|
-
5.
|
|
159
|
-
6.
|
|
160
|
-
7.
|
|
161
|
-
8.
|
|
162
|
-
9.
|
|
163
|
-
10.
|
|
158
|
+
4. Plans orchestration: complexity + intent → shape (`select_orchestration_shape()` in `lib/orchestration.sh`); `ORCHESTRATION_MODE=fixed` bypasses to the legacy path
|
|
159
|
+
5. Selects consultants (smart routing or all)
|
|
160
|
+
6. Launches parallel queries (`query_*.sh`)
|
|
161
|
+
7. Deliberates per the chosen shape: convergence loop / adversarial gate / tournament / exhaustive sweep (`run_orchestration()`), or fixed debate rounds in `fixed` mode
|
|
162
|
+
8. Calculates voting/consensus with confidence intervals (`lib/voting.sh`)
|
|
163
|
+
9. Checks for panic mode triggers (`lib/common.sh`)
|
|
164
|
+
10. Generates synthesis with selected strategy (`synthesize.sh`)
|
|
165
|
+
11. Optionally runs peer review (`peer_review.sh`)
|
|
166
|
+
12. Produces final report
|
|
164
167
|
|
|
165
168
|
## v2.2 Features
|
|
166
169
|
|
|
@@ -223,7 +226,7 @@ OLLAMA_MODEL=codellama ./scripts/consult_all.sh "question"
|
|
|
223
226
|
```
|
|
224
227
|
|
|
225
228
|
Configuration in `config.sh`:
|
|
226
|
-
- `OLLAMA_MODEL` - Model to use (default:
|
|
229
|
+
- `OLLAMA_MODEL` - Model to use (default: hf.co/prithivMLmods/VibeThinker-3B-GGUF)
|
|
227
230
|
- `OLLAMA_HOST` - Server URL (default: http://localhost:11434)
|
|
228
231
|
- `OLLAMA_TIMEOUT` - Timeout in seconds (default: 300)
|
|
229
232
|
|
|
@@ -367,7 +370,7 @@ New environment variables in `config.sh`:
|
|
|
367
370
|
|
|
368
371
|
| Variable | Default | Description |
|
|
369
372
|
|----------|---------|-------------|
|
|
370
|
-
| `GEMINI_USE_API` | false | Use Google AI API instead of
|
|
373
|
+
| `GEMINI_USE_API` | false | Use Google AI API instead of the agy CLI |
|
|
371
374
|
| `CODEX_USE_API` | false | Use OpenAI API instead of codex CLI |
|
|
372
375
|
| `CLAUDE_USE_API` | false | Use Anthropic API instead of claude CLI |
|
|
373
376
|
| `MISTRAL_USE_API` | false | Use Mistral API instead of vibe CLI |
|
|
@@ -414,9 +417,9 @@ Three tiers of models are available for each consultant, configurable via `apply
|
|
|
414
417
|
|
|
415
418
|
| Tier | Description | Example Models |
|
|
416
419
|
|------|-------------|----------------|
|
|
417
|
-
| **premium** | Latest flagship models | claude-opus-4-
|
|
418
|
-
| **standard** | Good quality at reasonable cost | claude-sonnet-4-6,
|
|
419
|
-
| **economy** | Optimized for speed and low cost | claude-haiku-4-5,
|
|
420
|
+
| **premium** | Latest flagship models | claude-opus-4-8, Gemini 3.1 Pro (High), gpt-5.5 |
|
|
421
|
+
| **standard** | Good quality at reasonable cost | claude-sonnet-4-6, Gemini 3.5 Flash (High), gpt-5.4 |
|
|
422
|
+
| **economy** | Optimized for speed and low cost | claude-haiku-4-5, Gemini 3.5 Flash (Low), gpt-5.4-nano |
|
|
420
423
|
|
|
421
424
|
**Default models are now premium tier** for maximum quality.
|
|
422
425
|
|
|
@@ -428,7 +431,7 @@ apply_model_tier "standard" # Set all consultants to standard models
|
|
|
428
431
|
apply_model_tier "economy" # Set all consultants to economy models
|
|
429
432
|
|
|
430
433
|
# Get model for a specific consultant and tier (v2.8.1)
|
|
431
|
-
get_model_for_tier "gemini" "premium" # →
|
|
434
|
+
get_model_for_tier "gemini" "premium" # → Gemini 3.1 Pro (High)
|
|
432
435
|
get_model_for_tier "claude" "economy" # → claude-haiku-4-5
|
|
433
436
|
```
|
|
434
437
|
|
|
@@ -446,25 +449,25 @@ Three new presets leverage the model tiers:
|
|
|
446
449
|
./scripts/consult_all.sh --preset fast "quick syntax question"
|
|
447
450
|
```
|
|
448
451
|
|
|
449
|
-
### Premium Model Defaults (
|
|
452
|
+
### Premium Model Defaults (June 2026)
|
|
450
453
|
All consultants now use premium models by default:
|
|
451
454
|
|
|
452
455
|
| Consultant | Default Model |
|
|
453
456
|
|------------|---------------|
|
|
454
|
-
| Claude | claude-opus-4-
|
|
455
|
-
| Gemini |
|
|
457
|
+
| Claude | claude-opus-4-8 |
|
|
458
|
+
| Gemini | Gemini 3.1 Pro (High) (via agy CLI) |
|
|
456
459
|
| Codex | gpt-5.5 |
|
|
457
460
|
| Mistral | mistral-large-3 |
|
|
458
|
-
| Cursor | composer-2 |
|
|
461
|
+
| Cursor | composer-2.5 |
|
|
459
462
|
| DeepSeek | deepseek-v4-pro |
|
|
460
|
-
| GLM | glm-5.
|
|
463
|
+
| GLM | glm-5.2 |
|
|
461
464
|
| Grok | grok-4.3 |
|
|
462
|
-
| Qwen3 | qwen3.
|
|
465
|
+
| Qwen3 | qwen3.7-max |
|
|
463
466
|
| Kimi | kimi-code/kimi-for-coding |
|
|
464
|
-
| Aider |
|
|
467
|
+
| Aider | qwen3-coder:free |
|
|
465
468
|
| MiniMax | MiniMax-M2.7 |
|
|
466
469
|
| Kilo | auto |
|
|
467
|
-
| Ollama |
|
|
470
|
+
| Ollama | hf.co/prithivMLmods/VibeThinker-3B-GGUF |
|
|
468
471
|
|
|
469
472
|
Override with environment variables: `CLAUDE_MODEL`, `GEMINI_MODEL`, `CODEX_MODEL`, `KIMI_MODEL`, etc.
|
|
470
473
|
|
|
@@ -652,9 +655,10 @@ for f in scripts/*.sh scripts/lib/*.sh; do bash -n "$f" && echo "OK: $f"; done
|
|
|
652
655
|
| `ENABLE_PANIC_MODE` | auto | Panic mode trigger (v2.2) |
|
|
653
656
|
| `PANIC_CONFIDENCE_THRESHOLD` | 5 | Panic threshold (v2.2) |
|
|
654
657
|
| `ENABLE_OLLAMA` | false | Local model support (v2.2) |
|
|
655
|
-
| `OLLAMA_MODEL` |
|
|
656
|
-
| `CLAUDE_MODEL` | claude-opus-4-
|
|
657
|
-
| `GEMINI_MODEL` |
|
|
658
|
+
| `OLLAMA_MODEL` | hf.co/prithivMLmods/VibeThinker-3B-GGUF | Ollama model (v2.17 default) |
|
|
659
|
+
| `CLAUDE_MODEL` | claude-opus-4-8 | Claude model (v2.5) |
|
|
660
|
+
| `GEMINI_MODEL` | Gemini 3.1 Pro (High) | Gemini agy CLI model (v2.15) |
|
|
661
|
+
| `GEMINI_API_MODEL` | gemini-3.1-pro-preview | Gemini API-mode model ID (v2.15) |
|
|
658
662
|
| `CODEX_MODEL` | gpt-5.5 | Codex model (v2.5) |
|
|
659
663
|
| `MISTRAL_MODEL` | mistral-large-3 | Mistral model (v2.5) |
|
|
660
664
|
| `SYNTHESIS_STRATEGY` | majority | Synthesis strategy (v2.2) |
|
|
@@ -677,7 +681,7 @@ for f in scripts/*.sh scripts/lib/*.sh; do bash -n "$f" && echo "OK: $f"; done
|
|
|
677
681
|
|
|
678
682
|
## External Dependencies
|
|
679
683
|
|
|
680
|
-
- `
|
|
684
|
+
- `agy` CLI - Antigravity CLI (Gemini consultant; successor to the deprecated Gemini CLI, v2.15)
|
|
681
685
|
- `codex` CLI - OpenAI Codex
|
|
682
686
|
- `vibe` CLI - Mistral Vibe
|
|
683
687
|
- `kilocode` CLI - Kilo Code
|
|
@@ -732,16 +736,36 @@ For detailed information, see:
|
|
|
732
736
|
|
|
733
737
|
Use [Conventional Commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`, `perf:`, `ci:`. Scope is optional (e.g., `feat(routing): add fallback escalation`).
|
|
734
738
|
|
|
739
|
+
### Pre-commit hook (v2.14.1+)
|
|
740
|
+
|
|
741
|
+
A git pre-commit hook runs `shellcheck` on staged `.sh` files using the exact CI invocation. Install it once per checkout:
|
|
742
|
+
|
|
743
|
+
```bash
|
|
744
|
+
npm run install-hooks # copies scripts/hooks/pre-commit into .git/hooks/
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
Manual lint of the full repo: `npm run lint`. Bypass the hook: `git commit --no-verify` (use sparingly — CI will catch the same warnings).
|
|
748
|
+
|
|
735
749
|
## Release Process
|
|
736
750
|
|
|
737
751
|
Every version bump **must** include a release note in `docs/releases/v<VERSION>.md`. Use the template below.
|
|
738
752
|
|
|
739
753
|
### Steps
|
|
740
754
|
|
|
741
|
-
1. Update version in all files: `package.json`, `SKILL.md` (frontmatter + title), `README.md` (title + badge), `CLAUDE.md` (`**Version**`), `docs/cost_rates.json`, `docs/COST_RATES.md` (title)
|
|
742
|
-
2. Add
|
|
743
|
-
3.
|
|
744
|
-
4.
|
|
755
|
+
1. **Update version** in all files: `package.json`, `scripts/config.sh` (`AI_CONSULTANTS_VERSION`), `SKILL.md` (frontmatter + title), `README.md` (title + badge), `CLAUDE.md` (`**Version**`), `docs/cost_rates.json`, `docs/COST_RATES.md` (title)
|
|
756
|
+
2. **Add `## Changelog` entry** in CLAUDE.md (developer-facing, long-form, rationale + line-level commentary)
|
|
757
|
+
3. **Add `CHANGELOG.md` entry** at the top of `CHANGELOG.md` (Keep a Changelog format: `## [VERSION] - YYYY-MM-DD` with `### Added/Changed/Fixed/Removed/Deprecated/Security` subsections — user-facing, one-line bullets)
|
|
758
|
+
4. **Create `docs/releases/v<VERSION>.md`** using the template below (highlights + upgrade guide — for GitHub releases / users)
|
|
759
|
+
5. **Update workspace sync surfaces** if applicable: `aiconsultants.sh/index.html` (`softwareVersion` schema + badge), `../CLAUDE.md` workspace guide ("Latest at time of last sync" + Recent release line)
|
|
760
|
+
6. **Run tests**: `npm test` must pass before committing
|
|
761
|
+
7. **Commit, push**, and optionally create a GitHub release pointing to the release note
|
|
762
|
+
|
|
763
|
+
**Why three changelog surfaces?** They serve different audiences:
|
|
764
|
+
- `CLAUDE.md ## Changelog` — what the *next maintainer* needs (file/line references, rationale, latent bugs uncovered)
|
|
765
|
+
- `CHANGELOG.md` — what *users on a specific version* need (concise, categorized, scannable)
|
|
766
|
+
- `docs/releases/v<VERSION>.md` — what *people deciding to upgrade* need (highlights, breaking changes, upgrade guide)
|
|
767
|
+
|
|
768
|
+
Drift between these is the most common release-process bug. Keep them in sync per release.
|
|
745
769
|
|
|
746
770
|
### Release Note Template
|
|
747
771
|
|
|
@@ -802,6 +826,173 @@ curl -fsSL https://raw.githubusercontent.com/matteoscurati/ai-consultants/main/s
|
|
|
802
826
|
|
|
803
827
|
## Changelog
|
|
804
828
|
|
|
829
|
+
### v2.17.0
|
|
830
|
+
- **Model catalog refresh (June 2026)** across all three tiers + cost rates, for every agent. Source of truth stays `config.sh::get_model_for_tier` (+ default `*_MODEL` vars) mirrored by `docs/cost_rates.json` (`model_tiers` + `consultant_fallbacks` + per-1K `models` rates). CLI-addressed models verified by querying the installed binaries (`agy models`, `agent --list-models`, kimi config); API/provider models + pricing researched against official sources. Superseded IDs kept in `cost_rates.json` for historical/pinned lookups.
|
|
831
|
+
- **Changed models** (premium / standard / economy):
|
|
832
|
+
- **codex**: gpt-5.5 / **gpt-5.4** (was gpt-5.3) / **gpt-5.4-nano** (was gpt-4o-mini).
|
|
833
|
+
- **cursor**: **composer-2.5** / **composer-2** / **gemini-3-flash** (was composer-2 / composer-1.5 / gemini-2.0-flash).
|
|
834
|
+
- **deepseek**: deepseek-v4-pro / **deepseek-v4-flash** ×2 (was deepseek-v3.2 / deepseek-chat; chat+reasoner deprecate 2026-07-24).
|
|
835
|
+
- **glm**: **glm-5.2** premium+standard (was glm-5.1) / glm-4-flash.
|
|
836
|
+
- **grok**: grok-4.3 / **grok-4.1-fast** ×2 (was grok-3 / grok-3-mini).
|
|
837
|
+
- **qwen3**: **qwen3.7-max** (was qwen3.6-plus) / qwen3.6-35b-a3b / qwen3-32b.
|
|
838
|
+
- **aider**: **qwen3-coder:free** (was nvidia/nemotron…:free) / **gpt-5.4** / **gpt-5.4-nano**.
|
|
839
|
+
- **ollama**: **hf.co/prithivMLmods/VibeThinker-3B-GGUF** default (was qwen2.5-coder:32b); standard/economy keep llama3.3/llama3.2.
|
|
840
|
+
- **Unchanged (verified current)**: claude, gemini (agy display names — no newer Gemini), mistral, minimax, kimi/amp/kilo.
|
|
841
|
+
- **Cost-rate corrections (per-1K)**: `gpt-5.5` → 0.005/0.030 (was understated 0.003/0.012), `deepseek-v4-pro` → 0.000435/0.00087, `minimax-m2.7` → 0.00025/0.001, `composer-2` → 0.0005/0.0025, Gemini Flash → 0.0015/0.009, Gemini 3.1 Pro → 0.002/0.012, mistral-medium → 0.001/0.003, devstral-small-2 → 0 (free). New IDs added with researched per-1K rates. `COST_RATES.md` regenerated to match the JSON.
|
|
842
|
+
- **Estimates flagged**: `glm-5.2` (mirrors glm-5.1) and `qwen3.7-max` (mirrors qwen3-max) pending official pricing.
|
|
843
|
+
- **Docs synced**: README, configuration.md, .env.example (+ fixed pre-existing GROK/DEEPSEEK default drift), SETUP.md, CLAUDE.md tables. Tests: tier assertions updated +10 new; 8 suites pass; shellcheck clean.
|
|
844
|
+
- **Found in `/code-review max` (workflow-backed, 61 agents): case-insensitive cost lookup.** `lib/costs.sh::get_rate_from_file` did an exact-case jq key match, but callers lowercase the model name first — so every **mixed-case** rate key silently missed and fell to `default_rate` ($0.005/$0.015 per 1K). This diff newly tripped it with the Ollama default `hf.co/prithivMLmods/VibeThinker-3B-GGUF` (a free local model billed at $0.02/query → wrong session cost reports, pre-run estimates, and budget halts under `ENABLE_BUDGET_LIMIT`), and it had silently rendered the **Gemini** agy display-name rates inert since v2.15 (every Gemini consultation cost-reported at default, not its real rate). Fixed by matching keys case-insensitively (`ascii_downcase` both sides via `first(.models|to_entries[]|select(...))`) — lowercase keys (minimax/gpt-5.5) still match; mixed-case (Gemini, VibeThinker) now resolve. Verified: VibeThinker → $0, Gemini 3.1 Pro → $0.014 for 1k+1k. Regression tests added (VibeThinker=0, Gemini resolves, local model free).
|
|
845
|
+
- **Also from review**: `estimate_query_cost`/`format_cost` now restore the leading zero bc drops on sub-1 values (".014000"/".03¢" → "0.014000"/"0.03¢") — surfaced by the diff's many sub-cent rates. README roster + `references/configuration.md` Grok/DeepSeek default cells synced to grok-4.3 / deepseek-v4-pro (the partial sync had left them stale). `config.sh` codex + ollama inline comments corrected to the new defaults. `cost_rates.json` premium-block date comment → Jun 2026. (Skipped as deliberate: re-ordering legacy entries under `_comment_legacy`, and the `gemini-3-flash-preview` vs `gemini-3-flash` coexistence — the former is the historical Gemini-API id, the latter Cursor's economy model, kept separately on purpose.)
|
|
846
|
+
|
|
847
|
+
### v2.16.0
|
|
848
|
+
- **Dynamic orchestration engine** — the fixed `classify → query → debate(N fixed rounds) → synth` pipeline becomes adaptive, inspired by Claude Code's dynamic workflows but implemented entirely in standalone bash (no Workflow tool / Claude-Code dependency). A planner picks an orchestration **shape** per question; debate becomes a **convergence loop**.
|
|
849
|
+
- **New module `lib/orchestration.sh`** (sourced by `consult_all.sh` after voting/costs). Public surface:
|
|
850
|
+
- `detect_intent <query>` → `advise|compare|exhaustive` (heuristic regex over the query; zero-dep).
|
|
851
|
+
- `select_orchestration_shape <category> <complexity> <intent>` → `quick|converge|adversarial|tournament|exhaustive|fixed`. Auto resolution priority: explicit `ORCHESTRATION_MODE` override → intent (`exhaustive`/`compare`) → category (`SECURITY`→adversarial) → complexity (≤`COMPLEXITY_THRESHOLD_SIMPLE`→quick, else converge).
|
|
852
|
+
- `run_orchestration <shape> <dir> <category>` dispatcher; skips multi-round shapes when `SUCCESS_COUNT ≤ 1`.
|
|
853
|
+
- Pure decision helpers, unit-tested without live CLIs: `_convergence_should_stop <score> <prev> <target> <epsilon>` (→`converged|stalled|continue`) and `_approach_signature <dir>` (sorted-unique approach set, the loop-until-dry stop signal).
|
|
854
|
+
- **Convergence loop (`run_convergence_loop`)** replaces the fixed `for round=2..DEBATE_ROUNDS`. Stops on: consensus ≥ `CONVERGENCE_TARGET_CONSENSUS` (converged), per-round gain < `CONVERGENCE_STALL_EPSILON` (stalled), `CONVERGENCE_MAX_ROUNDS` reached, or budget. `min_rounds` param forces ≥N critique rounds even on early consensus (adversarial uses 2). Reuses `calculate_consensus_score` (voting.sh) for the stop signal and the extracted `_apply_debate_round` helper (the legacy loop body, now shared) for execution+merge. Trajectory + stop reason written to `orchestration.json`.
|
|
855
|
+
- **Shapes**: `quick` (no debate), `converge` (loop to consensus), `adversarial` (forced critique round + peer review as refutation gate — `SECURITY`), `tournament` (converge, then synthesis declares one winner via `ORCHESTRATION_SELECT_WINNER` directive in `synthesize.sh`), `exhaustive` (`run_exhaustive_loop`: iterate until a round adds no new `.response.approach`).
|
|
856
|
+
- **`consult_all.sh` integration**: after classification, computes `QUERY_COMPLEXITY` (`calculate_query_complexity`, costs.sh) + `QUERY_INTENT` + `ORCH_SHAPE`; the debate block dispatches on `ORCHESTRATION_MODE` (`fixed` → byte-equivalent legacy loop via `_apply_debate_round`; else → `run_orchestration`). Adversarial shape force-enables `ENABLE_PEER_REVIEW`. Shape/complexity/intent recorded in `optimization_metrics.json`.
|
|
857
|
+
- **Config (all back-compat)**: `ORCHESTRATION_MODE` (default `auto`), `CONVERGENCE_MAX_ROUNDS` (4), `CONVERGENCE_TARGET_CONSENSUS` (75), `CONVERGENCE_STALL_EPSILON` (5), `ENABLE_ADVERSARIAL_VERIFY` (true). `ORCHESTRATION_MODE=fixed` restores the exact pre-2.16 pipeline.
|
|
858
|
+
- **Behavioral change (default)**: with `auto` the panel may run more or fewer rounds than the old fixed default, driven by consensus — complex/contested questions iterate further, simple ones short-circuit to `quick`. Every round still passes `enforce_budget`, so `MAX_SESSION_COST` continues to cap spend. Set `ORCHESTRATION_MODE=fixed` to opt out.
|
|
859
|
+
- **Minor robustness**: `_apply_debate_round` swallows a failed `debate_round.sh` (`|| true`) instead of aborting the whole consultation under `set -e` (the legacy inline `$()` capture would abort). Applies to both `fixed` and dynamic paths.
|
|
860
|
+
- **Convergence actually converges (fixed in `/code-review max`).** The round file carries the consultant's *updated* top-level `.response.approach` (`build_structured_response` uses `$inner.response`), but the legacy merge grafts only `.debate` (which `build_structured_response` doesn't even preserve → null). Since `calculate_consensus_score` reads `.response.approach`, the consensus signal was invariant under debate → the loop stalled after exactly one round every time. Fix: `_apply_debate_round` gained a `promote` flag; the dynamic loops (`promote=true`) adopt the round file's post-debate `.response`/`.confidence` so consensus reflects evolved positions. The legacy `fixed` path (`promote=false`) keeps the original `.debate`-only graft. Verified: a stubbed converging panel now moves 0 → 100 (`converged`), where before it logged `stalled` at round 1. Regression tests assert promote adopts the updated approach and legacy preserves the original.
|
|
861
|
+
- **ARCHITECTURE keeps its mandatory debate (fixed in `/code-review max`).** The legacy pipeline always debated `SECURITY` *and* `ARCHITECTURE`; the first planner cut only special-cased `SECURITY`→adversarial, letting `ARCHITECTURE` fall through to `converge` (min_rounds=1), which early-exits with zero debate rounds when the fan-out already agrees. Now `ARCHITECTURE` pins to `converge` (never `quick`) and `run_orchestration` forces `min_rounds=2` for both mandatory categories, so they always run ≥1 critique round — restoring pre-2.16 behavior.
|
|
862
|
+
- **Tests**: new `scripts/test_orchestration.sh` (32 assertions, 13 tests) — intent detection, shape selection (intent/category/complexity priority + overrides + fixed bypass + threshold boundary + ARCHITECTURE mandatory-debate), convergence stop decision (converged/stalled incl. negative-gain/continue), `_apply_debate_round` promote-vs-legacy merge, `_approach_signature` over fixtures, `ORCHESTRATION_MODE=auto` default. Auto-discovered by `test_all.sh` → now **8 suites**. Convergence loop smoke-tested end-to-end with a stubbed `debate_round.sh` (0 → 100 converged).
|
|
863
|
+
|
|
864
|
+
### v2.15.1
|
|
865
|
+
- **Markdown-fence parsing fix — Gemini's default model produced degraded (fallback) responses under v2.15.0.** The v2.15.0 migration note claimed "agy prints the model JSON directly (top-level `.response`)"; verified against agy 1.0.10, that is only true for some models (e.g. `Gemini 3.5 Flash (Low)` returns bare JSON). The **default** `Gemini 3.1 Pro (High)` wraps the envelope in a ```` ```json … ``` ```` markdown fence, so `process_consultant_response` failed the `.response.summary` jq probe and fell through to `build_fallback_response` — emitting `summary: "Unstructured response - see detailed"`, `confidence: 5`, and empty pros/cons for every Gemini reply, with the real structured envelope buried as a fenced string inside `.detailed`. Fix: new shared helper `lib/common.sh::strip_json_fence` — returns the text unchanged when it already parses as JSON (a real fence makes the text invalid JSON, so the gate reliably detects it), otherwise drops pure fence-marker lines (`/^[[:space:]]*```[[:alnum:]]*[[:space:]]*$/d`). Consultant-agnostic; the bare-JSON path (Flash, every other consultant) is untouched. Verified end-to-end against live agy: `Gemini 3.1 Pro (High)` now yields a populated `build_structured_response` (summary/approach/pros/cons/confidence=10). Regression test in `test_functions.sh::test_process_consultant_response_fence`.
|
|
866
|
+
- **Fence fix applied to ALL agy output paths (caught in `/code-review max`).** The fence isn't only seen by `process_consultant_response` — two other paths consume agy output directly and were still corrupting it:
|
|
867
|
+
- **`lib/reflection.sh::run_reflection_cycle`**: `_exec_consultant` returns raw (fenced) agy output. The critique's `jq -r '.needs_refinement'` returned `""` on fenced text (so the early-stop never fired and every cycle ran), and the refined response was written back as fenced non-JSON, making downstream voting/synthesis/report `jq` reads silently fall back — discarding the refined Gemini answer. Now de-fences `critique` and `refined` via `strip_json_fence` at the consumption points.
|
|
868
|
+
- (`peer_review.sh` already had its own `extract_json_from_response` fence handler applied before aggregation — verified safe, left as-is.)
|
|
869
|
+
- **Synthesis via agy was broken (caught in `/code-review max`).** `lib/common.sh::build_synthesis_args` gemini branch produced a bare `agy` invocation (`SYNTHESIS_ARGS=("${GEMINI_CMD:-agy}")`), invoked as `echo "$prompt" | agy`. Unlike codex (`--full-auto`) and claude (`--print`), agy with no `--print`/`-p` launches its **interactive** session and never reads the piped prompt, so synthesis hung/produced nothing whenever agy was the chosen synthesizer (reachable e.g. when Claude Code is the invoking agent and agy is on PATH). Fixed to `("${GEMINI_CMD:-agy}" "-p" "-")` + `--model`, mirroring `query_gemini.sh`.
|
|
870
|
+
- **Comment rot (caught in `/code-review max`)**: `query_gemini.sh` comments claimed agy emits raw JSON "no envelope to unwrap"; corrected to note the default model fences its JSON and that the fence is stripped centrally.
|
|
871
|
+
- **Gemini transport auto-resolution — makes the Gemini consultant work out-of-the-box for npm/npx users.** v2.15.0 left Gemini enabled by default (`ENABLE_GEMINI=true`) in CLI mode (`GEMINI_USE_API=false`), but the agy (Antigravity) CLI cannot be installed via npm (it's a `curl|bash` binary into `~/.local/bin/agy`) and is OAuth-only (no headless/API-key auth). Net effect: every fresh `npx ai-consultants` run silently dropped Gemini from the panel (`consult_all.sh` marks it FAILED and continues) — *even when the user had `GEMINI_API_KEY` exported*, because API mode was opt-in with no auto-detection. The API path (pure `curl` + key, no binary, no browser) is the npm-friendly one but was off by default.
|
|
872
|
+
- **`config.sh`**: removed the hardcoded `GEMINI_USE_API="${GEMINI_USE_API:-false}"` at the mode-switching block (`scripts/config.sh:69-72`). The mode is now auto-resolved in the Gemini config section (`scripts/config.sh:113-131`), *after* `GEMINI_CMD`/`GEMINI_API_KEY` are known: when `GEMINI_USE_API` is unset, pick `true` if `GEMINI_API_KEY` is present, else `false` (agy CLI). An explicit `GEMINI_USE_API=true/false` is always honored (back-compat, via the `${GEMINI_USE_API+x}` set-vs-unset guard). Idempotent across the 15-30 `config.sh` re-sources per consultation: once resolved and `export`ed, subsequent sources see it as user-set. Only Gemini auto-resolves; the other four switchable agents (Codex, Claude, Mistral, Qwen3) keep their hardcoded `:-false` defaults since their CLIs are npm/pip-installable.
|
|
873
|
+
- **`doctor.sh`**: `check_cli_consultant` now skips the CLI install check when the consultant is in API mode (`${env_var}_USE_API == true`) — previously it would flag a missing CLI as a hard `✗ NOT INSTALLED` failure regardless of mode, which after auto-resolution would false-fail for every key-only Gemini user. This also fixes the same pre-existing latent false-positive for Codex/Claude/Mistral/Qwen3 when those run in API mode. Additionally, when Gemini *is* in CLI mode and `agy` is missing, the failure now prints a `tip: set GEMINI_API_KEY to use API mode (no CLI install needed)` remediation pointing at the npm-friendly path.
|
|
874
|
+
- **Tests**: `test_user_config.sh` +4 assertions (Tests 19-22): auto-API with key, auto-CLI without key, explicit `false` wins over a present key, explicit `true` honored without a key. Suite now 42 checks; all 7 suites pass.
|
|
875
|
+
- **No breaking change**: agy/OAuth users without a key keep CLI mode; anyone who pinned `GEMINI_USE_API` keeps their value. The only behavioral change is that a key-only environment now reaches Gemini over the API instead of silently dropping it.
|
|
876
|
+
|
|
877
|
+
### v2.15.0
|
|
878
|
+
- **Gemini consultant migrated from the Gemini CLI to the Antigravity CLI (`agy`)**. Google deprecated the Gemini CLI on 2026-06-18 (transitioning all individual/Pro/Ultra users to Antigravity CLI); the `gemini` binary stops serving requests for non-enterprise accounts. The consultant stays "Gemini" / "The Architect" (ID 1) — only the transport binary, model addressing, and auth change. Verified against `agy` 1.0.10.
|
|
879
|
+
- **`config.sh`**: `GEMINI_CMD` default `gemini` → `agy` (`scripts/config.sh:106`); `GEMINI_MODEL` default `gemini-3.1-pro-preview` → `Gemini 3.1 Pro (High)` (agy addresses models by display name, not API ID); new `GEMINI_API_MODEL` (default `gemini-3.1-pro-preview`) decouples the API-mode model ID from the CLI display name. `get_model_for_tier "gemini"` now returns agy display names: premium `Gemini 3.1 Pro (High)`, standard `Gemini 3.5 Flash (High)`, economy `Gemini 3.5 Flash (Low)`.
|
|
880
|
+
- **`query_gemini.sh`** — three verified flag/parse changes:
|
|
881
|
+
- `-m` → `--model` (agy has no `-m` short alias).
|
|
882
|
+
- **Dropped `--output-format json`** — agy has no such flag and prints the model's response as plain text. Because the persona instruction already forces the model to emit our JSON schema, that plain text *is* the JSON envelope we need.
|
|
883
|
+
- **Dropped the `native_json_field="response"` argument** to `process_consultant_response`. The old Gemini CLI wrapped output as `{"response":"<text>","stats":{…}}` and we extracted `.response`; agy's output is the model JSON directly (top-level `.response`), so extracting `.response` would strip a level and force every structured reply into the fallback path. Confirmed end-to-end: a real `agy` call now yields a correct `build_structured_response` (consultant=Gemini, model="Gemini 3.1 Pro (High)", persona=The Architect, populated pros/cons/confidence).
|
|
884
|
+
- API-mode branch now passes `$GEMINI_API_MODEL` (not `$GEMINI_MODEL`) to `run_api_mode_query`, since the Google AI endpoint builds `…/${model}:generateContent` and needs an API ID, not a display name.
|
|
885
|
+
- **CLI invocation parity**: same `-m`→`--model` change applied to the two other call sites — `peer_review.sh:150` and `lib/reflection.sh:71`.
|
|
886
|
+
- **Install/auth surfaces** repointed to agy: `doctor.sh` (install hint + `${GEMINI_CMD:-gemini}`→`:-agy` in the two config-dump fallbacks), `setup_wizard.sh`, `configure.sh` (`CLI_AGENT_CMDS`/`CLI_AGENT_HINTS`), `lib/common.sh` synthesis fallbacks (`:-agy`), `.env.example`, `docs/SETUP.md`, `references/configuration.md`. Install is now `curl -fsSL https://antigravity.google/cli/install.sh | bash` (binary lands in `~/.local/bin/agy`). Auth is **OAuth-only** (`agy` with no args → browser sign-in; creds cached); `agy` does **not** honor an API-key env var for headless use — that path remains exclusive to API mode.
|
|
887
|
+
- **Cost catalog**: added `Gemini 3.1 Pro (High)` / `Gemini 3.5 Flash (High)` / `Gemini 3.5 Flash (Low)` keys to `cost_rates.json` (per-1K, mirroring the matching Gemini API tier; agy itself bills via OAuth/subscription) and repointed `consultant_fallbacks.gemini` + all three `model_tiers.*.gemini` to the display names. The old `gemini-3.1-pro-preview`/`gemini-3-flash-preview`/`gemini-2.0-flash` entries are kept for API mode and historical lookups. `COST_RATES.md` synced.
|
|
888
|
+
- **Tests**: `test_suite.sh` tier assertions updated (`get_model_for_tier "gemini" premium/economy` and `get_economic_model "gemini"` now expect the agy display names) — same pattern as the v2.14.2 claude-opus-4-8 bump. All 7 suites pass.
|
|
889
|
+
- **Known follow-up (out of scope, flagged in the release note)**: the *host-side* integration — running ai-consultants **from** Gemini CLI as a slash-command host (`~/.gemini/skills/`, `INVOKING_AGENT=gemini`) — is affected by the same deprecation (Antigravity rebrands Extensions as "plugins", `agy plugin …`). That migration is **not** done here; this release covers only the Gemini *consultant* (the model we query). The relevant README/SETUP host sections were left intact rather than rewritten on unverified plugin mechanics.
|
|
890
|
+
|
|
891
|
+
### v2.14.2
|
|
892
|
+
- **Claude premium tier upgraded `claude-opus-4-7` → `claude-opus-4-8`** (Opus 4.8 released 2026-05-29). Single source of truth is the `premium` case in `config.sh::get_model_for_tier` (`scripts/config.sh:583`) and the `CLAUDE_MODEL` default (`scripts/config.sh:223`); both now resolve to `claude-opus-4-8`. Standard (`claude-sonnet-4-6`) and economy (`claude-haiku-4-5`) tiers are unchanged — Sonnet 4.6 and Haiku 4.5 remain the latest in their classes.
|
|
893
|
+
- **`docs/cost_rates.json`**: added a `claude-opus-4-8` entry; repointed `consultant_fallbacks.claude` and `model_tiers.premium.claude` to it; moved `claude-opus-4-7` into the `_comment_legacy` block so cost lookups for cached/historical responses and pinned overrides still resolve. Value entered in per-1K (see units fix below).
|
|
894
|
+
- **CRITICAL — cost-catalog unit normalization (fixes ~1000× cost overstatement)**: `lib/costs.sh` computes cost as `(token_count / 1000) * rate`, i.e. every value in `cost_rates.json` MUST be USD **per-1K** tokens (the hardcoded fallback table in `costs.sh`, e.g. `claude-3-haiku → 0.00025`, confirms this contract). But the premium/standard blocks had been populated with **per-MTok** dollar figures (`claude-opus-4-7: 5.00`, `claude-sonnet-4-6: 3.00`, `gpt-5.5: 3.00`, …) — so `estimate_query_cost` reported ~1000× the true cost for almost every premium/standard model (e.g. a ~1k-in/1k-out Opus query was reported as **$30** instead of **$0.03**). The economy block (incl. `claude-haiku-4-5: 0.001`) was already correct per-1K. Normalized the **entire** catalog (premium, standard, economy, legacy, `default_rate`) to per-1K by dividing the per-MTok entries by 1000; left the already-correct per-1K entries untouched. Added a `_comment_units` field documenting the contract to prevent regression. Verified: Opus 1k+1k = $0.03, 1M+1M = $30; Haiku 1k+1k = $0.006; gpt-5.5 1M+1M = $15; gemini-pro 1M+1M = $6.25 — all match provider pricing.
|
|
895
|
+
- **`docs/COST_RATES.md`**: Claude rows synced to the corrected per-1K values (`claude-opus-4-8` $0.005/$0.025, `claude-sonnet-4-6` $0.003/$0.015, `claude-haiku-4-5` $0.001/$0.005). Note: non-Claude rows in this human-facing doc may still lag the JSON and should be re-synced in a follow-up — `cost_rates.json` is the runtime source of truth, not this file.
|
|
896
|
+
- **Stale-alias cleanup (pre-existing, fixed in passing)**: five spots still carried pre-v2.10.6 short aliases and now use canonical IDs — `scripts/query_claude.sh` (header comment + `MODEL_USED` fallback), `.env.example` (`CLAUDE_MODEL=opus-4.6`), `references/configuration.md`, and the README "Models by Tier" table all → `claude-opus-4-8`; plus `lib/api.sh::build_anthropic_request` default `sonnet-4.6` → `claude-sonnet-4-6`. All were latent (callers always pass an explicit model / `config.sh` always exports `CLAUDE_MODEL`), but would have surfaced if those scripts were invoked standalone or the example `.env` copied verbatim.
|
|
897
|
+
- **Test**: `scripts/test_suite.sh::test_model_for_tier` premium assertion updated to expect `claude-opus-4-8`. No other test references the Claude premium ID.
|
|
898
|
+
- **Correction of an earlier mis-diagnosis (for the record)**: during development this was first flagged as "Haiku is 1000× *understated*". That was wrong — under the per-1K contract `claude-haiku-4-5: 0.001` is correct ($1/$5 per MTok). The real bug was the *opposite*: premium/standard entries were 1000× *overstated*. The unit normalization above is the actual fix.
|
|
899
|
+
- **Behavioral change**: cost *reporting* now drops ~1000× for premium/standard models (it was massively overstating). Orchestration, routing, and synthesis are unaffected. Note: `ENABLE_COST_AWARE_ROUTING` / budget thresholds compare against these figures, so anyone who tuned `MAX_SESSION_COST` against the old inflated numbers should revisit their threshold. Remaining out-of-scope item: a few legacy per-model rates (e.g. Mistral/DeepSeek/GLM tier orderings) reflect pre-existing catalog figures I couldn't verify against authoritative pricing — only the unit bug was fixed, not per-model price accuracy.
|
|
900
|
+
|
|
901
|
+
### v2.14.1
|
|
902
|
+
- **Pre-commit hook**: `scripts/hooks/pre-commit` runs `shellcheck` on staged `.sh` files under `scripts/` using the exact CI invocation (`-S warning -x -e SC1091,SC1090,SC2034,SC2155`). Mirrors `.github/workflows/ci.yml:32` so the same warnings that fail CI also fail the local commit. Filtered with the regex `^scripts/(lib/)?[^/]+\.sh$` to match the CI glob exactly (test fixtures under `scripts/test_fixtures/` are correctly excluded). Bypass: `git commit --no-verify`.
|
|
903
|
+
- **`scripts/install-hooks.sh`**: idempotent installer wired to `npm run install-hooks`. Backs up any existing different hook to `.git/hooks/pre-commit.backup.<timestamp>` to avoid clobbering contributor customizations (`FORCE=1` skips backup). Silent no-op outside a git checkout, so it's safe to wire to npm `prepare` or similar lifecycle hooks if ever needed.
|
|
904
|
+
- **`npm run lint`**: convenience wrapper for the full-repo shellcheck invocation. Useful pre-push when you want to validate without staging.
|
|
905
|
+
- **Motivation**: v2.14.0 push to `main` failed CI due to SC2164 in `scripts/test_context_optimization.sh:18` (`cd "$PROJECT_ROOT"` lacked `|| exit`). The new script passed `bash -n` locally but `bash -n` is purely a parser check — it doesn't run any linter. The pre-commit hook closes that gap. Documented in `CONTRIBUTING.md` Development Environment Setup section and briefly in `## Git Conventions` here.
|
|
906
|
+
- **No runtime behavior change**: this is contributor-only tooling. Tests still pass (7 suites, ~510 assertions).
|
|
907
|
+
|
|
908
|
+
### v2.14.0
|
|
909
|
+
- **Context handoff: AST optimization pipeline now engages on the primary slash-command path**. Pre-fix, `/ai-consultants:consult` instructed the invoking agent (Claude/Codex/Gemini) to inline file contents into the query string, which meant `build_context.sh` ran with zero `FILES` and the entire `lib/code_optimizer.sh` + `lib/chunking.sh` + `lib/symbol_map.sh` stack was dead code. The three `.{claude,codex,gemini}/commands/ai-consultants:{consult,debate}.md` slash commands now instruct agents to pass file paths as positional arguments to `consult_all.sh`; `build_context.sh` does the file reading and runs the optimizer.
|
|
910
|
+
- **`build_context.sh` reads exported `QUESTION_CATEGORY`** to decide whether to include the project tree section. SECURITY, QUICK_SYNTAX, ALGORITHM, BUG_DEBUG, DATABASE, TESTING categories skip it (noise for pointed questions); ARCHITECTURE, CODE_REVIEW, API_DESIGN, GENERAL include it; unknown categories default to "include" (conservative). New env var `FORCE_PROJECT_TREE=true` bypasses the heuristic. Categories source: `classify_question.sh` already exports `QUESTION_CATEGORY` in `consult_all.sh:241-242` — zero new code path, just consumes existing signal.
|
|
911
|
+
- **File relevance tags**: `path/to/file@PRIMARY` (focus of the question) vs `path/to/file@CONTEXT` (ambient reference). Default `PRIMARY` when omitted. Unknown tags fall back to PRIMARY with a `log_warn`. New parallel `FILE_TAGS` array in `build_context.sh`. Rendered as `### File: \`path\` (TAG)` in the `## Relevant Files` section, with a header explaining the two values to consultants. Downstream synthesis/debate/peer_review unaffected (they don't read `context.md`).
|
|
912
|
+
- **`--query-file <path>` flag in `consult_all.sh`** as escape hatch for queries exceeding shell ARG_MAX (~256KB on macOS) or containing mixed-quote payloads. Conflicts with positional question arg (parser-level error). Validates file existence at parse time.
|
|
913
|
+
- **Slash-command file detection**: replaced the hardcoded extension regex + `/`-in-token heuristic with "use your judgment, verify via Glob/Bash when uncertain". Pre-fix missed `Makefile`, `Dockerfile`, dotfiles; false-positive on URLs and regex patterns in question text. The invoking agent has full conversation context so it's better placed than a regex.
|
|
914
|
+
- **Claude-only note in `.claude/commands/ai-consultants:consult.md`**: explicit instruction not to use `Read` tool output (which carries `N\t` line-number prefix) since `build_context.sh` reads files itself. Codex and Gemini variants don't carry this note (their tools don't add the prefix).
|
|
915
|
+
- **First test coverage for `lib/code_optimizer.sh` and `lib/chunking.sh`**: new `scripts/test_context_optimization.sh` (17 assertions, 14 tests). Covers: @TAG default/explicit/unknown, QUESTION_CATEGORY routing (SECURITY drops, ARCHITECTURE keeps, unknown includes), FORCE_PROJECT_TREE override, Python AST extraction over MAX_CONTEXT_FILE_BYTES threshold, `optimize_code_file` smoke, `chunk_file_semantically` JSON shape, --query-file parsing (valid/missing/conflict), legacy no-FILES path preservation. Picked up automatically by `test_all.sh`'s `find`-based discovery — no manual wire-up needed. Total: 7 suites, ~510 assertions.
|
|
916
|
+
- **Test fixtures**: new `scripts/test_fixtures/context/` with `sample.py` (Python class + methods + main), `sample.sh` (Bash with functions), `sample.json` (config), `sample.txt` (plain text). Deterministic, no timestamps or randomness.
|
|
917
|
+
- **Help text updates**: `consult_all.sh --help` documents `--query-file` and `@TAG` syntax; `build_context.sh` usage error documents `QUESTION_CATEGORY` and `FORCE_PROJECT_TREE`.
|
|
918
|
+
- **Known gap surfaced**: `_supports_ast_extraction` declares 13 languages (Python, JS, TS, Go, Rust, Java, C++, C, C#, Ruby, PHP, Swift) but `lib/code_optimizer.sh` has dedicated extractors for only 4 (Python, JS/TS, Bash, Go); the other 9 fall back to `_extract_generic` (grep-based). Documented in release note; tracked for future tree-sitter-backed extraction.
|
|
919
|
+
- **Backwards compat**: agents that still inline file contents into the query (pinned old slash commands) keep working — `build_context.sh` degrades to no-FILES branch, just without the optimization benefit. Direct bash users of `./scripts/consult_all.sh "q" file1 file2` get the same behavior plus the new optimization.
|
|
920
|
+
|
|
921
|
+
### v2.13.1
|
|
922
|
+
- **Perf**: XDG roots resolved once at first `config.sh` source and **exported** as `_AI_CONSULTANTS_XDG_{CACHE,STATE,DATA}` — child query subshells inherit the values and skip ~6 subshells/child × 14 children = ~84 forks per consultation (~200-400ms saving on macOS).
|
|
923
|
+
- **Perf**: `apply_launch_stagger()` switched from `awk "BEGIN{printf}"` to pure-bash `printf '%d.%03d'` — 14 forks eliminated per consultation (~50-70ms aggregate).
|
|
924
|
+
- **Perf/DRY**: `_count_available_consultants` entries pre-uppercased (`"GEMINI|ENABLE_GEMINI|gemini"`) — 15 `to_upper` subshells eliminated per `--suggest-preset` invocation. Also fixes the latent self-exclusion case-mismatch the round-2 review caught.
|
|
925
|
+
- **Latent bug fix**: 5 `lib/*.sh` files (`cache.sh`, `session.sh`, `api.sh`, `chunking.sh`, `costs.sh`) had hardcoded `/tmp/...` defaults that drifted from the v2.13 XDG migration. Their fallbacks now reference `${_AI_CONSULTANTS_XDG_*}` so they stay aligned even if sourced standalone (e.g. from a future test). `lib/session.sh::cleanup_old_sessions` no longer hardcodes `/tmp/ai_consultations` either — uses `$DEFAULT_OUTPUT_DIR_BASE`.
|
|
926
|
+
- **DRY**: extracted `scripts/lib/test_helpers.sh` (~80 LOC) — `assert_eq`, `assert_match`, `run_test`, `test_summary`, `_reset_state` hook. Eliminates the ~90 LOC of triplication across `test_user_config.sh`, `test_doctor.sh`, `test_bin.sh`. Future test suites just `source lib/test_helpers.sh`.
|
|
927
|
+
- **CI**: `scripts/test_all.sh` (master runner introduced post-v2.13.0) now also includes `test_suite.sh` — adds 258 library assertions to `npm test`, closing the "tests on disk but not gating CI" gap. Total: 6 suites, ~493 assertions.
|
|
928
|
+
- **Style**: 37 → 0 shellcheck warnings under the project exclusions (`-e SC2034,SC2086,SC1091,SC2155,SC2154`). Touches: `configure.sh` (26 SC2004 + 1 SC2129), `lib/routing.sh` (4 SC2004/2321), `lib/code_optimizer.sh` (2 SC2001 sed → param expansion), `lib/chunking.sh` (2 SC2001), `lib/voting.sh` (1 SC2126), `lib/common.sh` (1 SC2005, 1 SC2317 annotated), `lib/api_query.sh` (1 SC2317 annotated), `lib/symbol_map.sh` (2 SC1090 annotated), `config.sh` (1 SC2317 annotated), `test_set_e_safety.sh` (1 SC2001 annotated).
|
|
929
|
+
- **Code quality**: `consult_all.sh` `_MODEL` var resolution switched from inline `tr` to `to_upper()` helper for consistency. Stale `name_upper` variable in `_count_available_consultants` renamed to `name`. `find_user_config_file` redundant `|| echo ""` simplified to `|| true`.
|
|
930
|
+
- All 6 test suites pass (493 assertions). Zero behavioral change for end users; XDG cache export is the only new env-var contract.
|
|
931
|
+
|
|
932
|
+
### v2.13.0
|
|
933
|
+
- New `doctor --suggest-preset --question "..."` recommends a preset + strategy combo for a question, based on category classification (`classify_question.sh`) and the count of available consultants (gated by `ENABLE_*` flags and self-exclusion). Outputs a one-line `ai-consultants` command + reasoning, or structured JSON via `--json` for tooling/automation.
|
|
934
|
+
- Classifier failures now surface explicitly as `Warning: classification of your question failed` (with the underlying error). Pre-fix the failure was masked by `2>/dev/null` and silently degraded to `GENERAL`.
|
|
935
|
+
- `--suggest-preset` short-circuits to "install more CLIs" hint when fewer than 2 consultants are usable — previously could recommend e.g. `minimal` preset with 0 consultants.
|
|
936
|
+
- `_count_available_consultants()` now respects `ENABLE_*` flags and subtracts the invoking agent (self-exclusion). Pre-fix the count included disabled consultants, leading `_recommend_combo` boundaries to fire on a phantom panel size.
|
|
937
|
+
- `ENABLE_DEBATE_OPTIMIZATION` promoted from opt-in to default `true` based on operator experience over 4 stable releases — debate is auto-skipped when confidence spread < `DEBATE_CONFIDENCE_SPREAD_THRESHOLD` (default 2). SECURITY and ARCHITECTURE remain mandatory-debate. No empirical benchmark in-tree yet; tracked for v2.14.
|
|
938
|
+
- XDG Base Directory compliance for transient and persistent paths (per freedesktop.org spec):
|
|
939
|
+
- `DEFAULT_OUTPUT_DIR_BASE`: `/tmp/ai_consultations` → `$XDG_CACHE_HOME/ai-consultants/consultations` (typically `~/.cache/...`)
|
|
940
|
+
- `CACHE_DIR`: `/tmp/ai_consultants_cache` → `$XDG_CACHE_HOME/ai-consultants/cache`
|
|
941
|
+
- `RATE_LIMIT_DIR`, `CHUNK_TEMP_DIR`: `/tmp/ai_consultants_*` → `$XDG_CACHE_HOME/ai-consultants/{ratelimit,chunks}`
|
|
942
|
+
- `SESSION_DIR`: `/tmp/ai_consultants_sessions` → `$XDG_STATE_HOME/ai-consultants/sessions` (`~/.local/state/...`)
|
|
943
|
+
- `COST_TRACKING_FILE`: `/tmp/ai_consultants_costs.json` → `$XDG_DATA_HOME/ai-consultants/costs.json` (`~/.local/share/...`)
|
|
944
|
+
- All env vars still respected; restore old behavior with `export DEFAULT_OUTPUT_DIR_BASE=/tmp/ai_consultations` etc.
|
|
945
|
+
- New `lib/user_config.sh::get_xdg_dir()` helper — single source of truth for XDG resolution; falls back to `$HOME/.{cache,local/state,local/share}` then `/tmp/ai-consultants-{kind}` for distroless containers.
|
|
946
|
+
- README slimmed: env-var section now points to `references/configuration.md` for the full ~150-var list and recommends `ai-consultants init` as the primary onboarding path.
|
|
947
|
+
- `RATE_LIMIT_DIR` and `CHUNK_TEMP_DIR` lifted to `config.sh` for consistency (were lib-only defaults).
|
|
948
|
+
- `config.sh` now hard-fails with `FATAL: ... get_xdg_dir()` if `lib/user_config.sh` is missing — pre-fix the v2.13 XDG defaults silently regressed to `/tmp/ai_consultants/...` when the helper was absent (corrupt install, refactor regression).
|
|
949
|
+
- New `scripts/test_doctor.sh` — 25 assertions in 12 tests: `--suggest-preset` across categories (SECURITY, QUICK_SYNTAX, ARCHITECTURE, ALGORITHM, GENERAL), no-question default, long-question truncation, short-circuit behavior, **+ review fixes**: `--json` output schema, count<2 install hint, classifier failure warning, `config.sh` FATAL on missing helper, count respects ENABLE_* flags.
|
|
950
|
+
- `scripts/test_user_config.sh` extended to 38 assertions in 18 tests — added: `get_xdg_dir` cache/state/data resolution, fallback to `~/.{cache,local/state,local/share}`, distroless `/tmp/ai-consultants-*` fallback, invalid kind handling, `config.sh` XDG path defaults, explicit env var override precedence, `ENABLE_DEBATE_OPTIMIZATION=true` default assertion.
|
|
951
|
+
- Round-2 review fix: `_count_available_consultants` self-exclusion was dead code due to UPPERCASE vs MixedCase mismatch — counter compared `Claude` to `get_self_consultant_name`'s `CLAUDE`. Now uppercases the entry name via `to_upper`; `INVOKING_AGENT` correctly drops 1 from the count. Regression test added.
|
|
952
|
+
- Round-2 fix: `--suggest-preset --json` pre-flights `jq` with a clear error message instead of aborting under `set -e` with `command not found` (the main `check_dependencies` jq probe doesn't run when `--suggest-preset` short-circuits).
|
|
953
|
+
- Round-2 fix: `--json` schema gains `schema_version: 1` and `recommended_command` fields — tooling no longer has to reconstruct the invocation client-side and has a signal for future schema evolution.
|
|
954
|
+
- Round-2 fix: `_count_available_consultants` no longer hardcodes a "default-true" list that drifted from `config.sh` (claimed Aider default-true; actually false). Removed; relies solely on `config.sh` defaults via `${!flag:-false}`.
|
|
955
|
+
- New `scripts/test_all.sh` master runner aggregates all 5 standalone test suites; `npm test` wired in `package.json`. Closes the "tests on disk but not gating CI" gap from v2.11/v2.12 review carryovers.
|
|
956
|
+
- `scripts/test_doctor.sh` extended to 31 assertions: + self-exclusion regression, + jq preflight, + schema_version/recommended_command shape.
|
|
957
|
+
|
|
958
|
+
### v2.12.0
|
|
959
|
+
- New persistent user-config dir at `~/.config/ai-consultants/` (XDG-compliant; honors `AI_CONSULTANTS_CONFIG_DIR` and `XDG_CONFIG_HOME`)
|
|
960
|
+
- New `lib/user_config.sh` with `load_user_config()` — sourced from `config.sh` at the very top, before any defaults are applied
|
|
961
|
+
- `load_user_config` is **idempotent** via a process-wide guard `_AI_CONSULTANTS_USER_CONFIG_LOADED` — `config.sh` is sourced 15-30 times per consultation transitively, and without the guard non-idempotent user config (PATH appends, counters, log appends) would compound silently
|
|
962
|
+
- `.env` (KEY=value) and `config.sh` (full bash) both supported; existing env vars always win over user config (precedence: CLI > env > user config > defaults > hardcoded)
|
|
963
|
+
- `.env` parser **strips trailing CR** so Windows CR-LF line endings don't silently corrupt values (`ENABLE_DEBATE=true\r` would otherwise break every `[[ "$X" == "true" ]]` comparison downstream)
|
|
964
|
+
- New `ai-consultants init [--force]` subcommand scaffolds the user config dir with `.env` (copied from `.env.example`, chmod 600) and `config.sh` (minimal sourceable template); refuses to scaffold into a symlinked dir (root + hostile symlink protection); pre-flights write permission with a friendly error pointing to `AI_CONSULTANTS_CONFIG_DIR`
|
|
965
|
+
- `bin/ai-consultants` no longer hardcodes the version (was stuck at 2.10.0 since v2.10.0 release); reads `AI_CONSULTANTS_VERSION` from `scripts/config.sh` and **validates it as semver** — falls back to `vunknown` instead of `vAI_CONSULTANTS_VERSION=2.12.0` when the parse fails
|
|
966
|
+
- `get_user_config_dir` returns empty + exit 1 when both `HOME` and `XDG_CONFIG_HOME` are unset (e.g. distroless container) instead of computing the broken path `/.config/ai-consultants`; callers (`doctor.sh`, `bin/init`) handle this with a clear error
|
|
967
|
+
- Single source of truth for user-dir resolution: `lib/user_config.sh::get_user_config_dir()`; `routing.sh`, `doctor.sh`, and `bin/ai-consultants` now all source it instead of duplicating the precedence ladder (was DRY-violated 4x)
|
|
968
|
+
- `lib/routing.sh::_load_affinity_data` extended with search path: `AFFINITY_FILE` env > `~/.config/ai-consultants/affinity.json` > bundled default — drops a custom matrix in the user dir without setting any env var
|
|
969
|
+
- `doctor.sh` adds `check_user_config()` reporting dir presence, files loaded, and warns on `.env` lax permissions — total checks now 22
|
|
970
|
+
- New regression test `scripts/test_user_config.sh` — 20 assertions in 11 tests: .env loading + quote stripping, env precedence, edge cases (comments/blanks/`export`/quoted/indented), invalid keys, config.sh ordering, XDG fallback, missing-files silence (now also asserts no stderr output), AI_CONSULTANTS_CONFIG_DIR priority, **CR-LF stripping**, **idempotency guard**, **HOME-unset fallback**
|
|
971
|
+
- New `scripts/test_bin.sh` — 10 assertions in 8 tests covering `bin/ai-consultants version` (matches config.sh, semver-shaped, fallback to "unknown" on malformed config) and `init` (chmod 600 enforcement, both files created, idempotent without --force, --force overwrites, refuses symlinked dir)
|
|
972
|
+
- `scripts/test_routing_parity.sh` extended to 146 assertions (added user-dir branch of `_resolve_affinity_path`)
|
|
973
|
+
|
|
974
|
+
### v2.11.0
|
|
975
|
+
- Externalized routing affinity matrix from nested `case` statements in `lib/routing.sh` to `references/affinity.json` (~190 lines of bash → 60 lines of JSON)
|
|
976
|
+
- Custom matrix at runtime via `AFFINITY_FILE=/path/to/custom.json` (e.g. tweak scores per project, disable consultants by category)
|
|
977
|
+
- `get_affinity()` now performs JSON lookup with two-level cache: file content cached on first read, per-(category, consultant) result cached after first lookup
|
|
978
|
+
- Cache uses leading-space delimiter to prevent substring collisions (e.g. `DEBUG|X=` would have falsely matched a cached `BUG_DEBUG|X=10` — caught in review pass before release)
|
|
979
|
+
- `doctor.sh` adds 3 new checks for affinity: file presence, JSON schema validity, coverage (every consultant in every category) — total checks now 21
|
|
980
|
+
- Golden parity test in `scripts/test_routing_parity.sh`: 144 assertions covering all 9 categories × 14 consultants + edge cases (unknown consultant, unknown category, AFFINITY_FILE override, cache auto-invalidation, cache substring-collision regression)
|
|
981
|
+
- `docs/SMART_ROUTING.md` rewritten: removed stale per-consultant table (was out of sync with code since v2.8/v2.9/v2.10 added Amp, Kimi, MiniMax), now points to JSON as source of truth and documents schema + override
|
|
982
|
+
- `references/affinity.json` `_comment` documents the asymmetric 3-tier fallback (unknown consultant → 5, unknown category → 8, missing cell → 5) and the rationale
|
|
983
|
+
- Bug class regression test in `scripts/test_set_e_safety.sh`: static lint covers `((var++))` AND `((var--))` AND `let var++` family, plus dynamic check on bash 4+ for the abort pattern fixed in v2.8.1, v2.10.1, v2.10.9
|
|
984
|
+
- `consult_all.sh` ENABLE_PREFLIGHT path no longer swallows doctor output — the diagnostic is now captured to a tmpfile and dumped on failure (previously `>/dev/null 2>&1` repeated the original preflight silent-failure bug)
|
|
985
|
+
- Cleaned `((attempt++)) || true || true` artifacts in `lib/api.sh` (introduced by the v2.10.9 mechanical sweep on lines that were already protected)
|
|
986
|
+
|
|
987
|
+
### v2.10.9
|
|
988
|
+
- Fixed silent failure of `preflight_check.sh` under `set -euo pipefail`: helper functions like `check_cli_installed` returned non-zero on missing CLIs, and call sites lacked `|| true` — the script aborted after "Checking CLI installations..." with no diagnostic output
|
|
989
|
+
- Deprecated `preflight_check.sh` in favor of `doctor.sh` (stale v2.0 script covering only 6/15 consultants and missing CLI/API mode checks); `preflight_check.sh` is now a thin wrapper that prints a deprecation warning and execs `doctor.sh "$@"`
|
|
990
|
+
- Ported `--suggest-config` from preflight to `doctor.sh`, expanded coverage from 6 to 15 consultants (now also detects API-only consultants via API key presence)
|
|
991
|
+
- Added `--quick` flag to `doctor.sh` (accepted as no-op for backward compat with preflight)
|
|
992
|
+
- Updated `consult_all.sh` ENABLE_PREFLIGHT path to invoke `doctor.sh` directly
|
|
993
|
+
- Defensive sweep: protected 15 latent `((var++))` increments across `peer_review.sh`, `setup_wizard.sh`, `test_functions.sh`, `lib/api.sh`, `lib/common.sh`, `lib/reflection.sh`, and `doctor.sh` with `|| true` (matches v2.8.1/v2.10.1 codebase convention; latent because bash 3.2 doesn't abort but bash 4+ does)
|
|
994
|
+
- Fixed real shellcheck warnings: SC2059 unsafe printf format string in `lib/progress.sh`, SC2012 `ls | wc -l` race in `install.sh` (replaced with `find`), SC2329 false positive in `query_ollama.sh` cleanup trap (annotated), SC2016 intentional sed pattern in `peer_review.sh` (annotated)
|
|
995
|
+
|
|
805
996
|
### v2.10.8
|
|
806
997
|
- Fixed `docs/cost_rates.json` drift introduced by v2.10.6: `consultant_fallbacks` (used at runtime by `lib/costs.sh`) and `model_tiers` were still pointing at the old IDs (`opus-4.6`, `gpt-5.3-codex`, `composer-1.5`, `deepseek-reasoner`, `sonnet-4.6`, `haiku-4.5`)
|
|
807
998
|
- Added price entries for the v2.10.6 model IDs: `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5`, `gpt-5.5`, `composer-2`, `deepseek-v4-pro`, `nvidia/nemotron-3-super-120b-a12b:free`
|