ai-consultants 2.10.8 → 2.14.1
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 +121 -6
- package/README.md +22 -26
- package/SKILL.md +2 -2
- package/bin/ai-consultants +99 -1
- package/docs/COST_RATES.md +1 -1
- package/docs/SMART_ROUTING.md +62 -15
- package/docs/cost_rates.json +1 -1
- 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/package.json +6 -1
- package/references/affinity.json +57 -0
- package/references/configuration.md +89 -1
- package/references/details.md +13 -0
- package/scripts/build_context.sh +96 -36
- package/scripts/config.sh +68 -13
- package/scripts/configure.sh +32 -30
- package/scripts/consult_all.sh +41 -7
- package/scripts/doctor.sh +468 -9
- 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 +6 -6
- 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 +7 -5
- package/scripts/lib/costs.sh +2 -2
- package/scripts/lib/progress.sh +2 -2
- package/scripts/lib/reflection.sh +2 -2
- 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 +5 -4
- package/scripts/preflight_check.sh +19 -442
- package/scripts/query_ollama.sh +1 -0
- package/scripts/setup_wizard.sh +1 -1
- 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_routing_parity.sh +180 -0
- package/scripts/test_set_e_safety.sh +118 -0
- package/scripts/test_user_config.sh +316 -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.14.1
|
|
10
10
|
|
|
11
11
|
## Distribution
|
|
12
12
|
|
|
@@ -47,7 +47,7 @@ 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
|
|
@@ -732,16 +732,36 @@ For detailed information, see:
|
|
|
732
732
|
|
|
733
733
|
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
734
|
|
|
735
|
+
### Pre-commit hook (v2.14.1+)
|
|
736
|
+
|
|
737
|
+
A git pre-commit hook runs `shellcheck` on staged `.sh` files using the exact CI invocation. Install it once per checkout:
|
|
738
|
+
|
|
739
|
+
```bash
|
|
740
|
+
npm run install-hooks # copies scripts/hooks/pre-commit into .git/hooks/
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
Manual lint of the full repo: `npm run lint`. Bypass the hook: `git commit --no-verify` (use sparingly — CI will catch the same warnings).
|
|
744
|
+
|
|
735
745
|
## Release Process
|
|
736
746
|
|
|
737
747
|
Every version bump **must** include a release note in `docs/releases/v<VERSION>.md`. Use the template below.
|
|
738
748
|
|
|
739
749
|
### Steps
|
|
740
750
|
|
|
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.
|
|
751
|
+
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)
|
|
752
|
+
2. **Add `## Changelog` entry** in CLAUDE.md (developer-facing, long-form, rationale + line-level commentary)
|
|
753
|
+
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)
|
|
754
|
+
4. **Create `docs/releases/v<VERSION>.md`** using the template below (highlights + upgrade guide — for GitHub releases / users)
|
|
755
|
+
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)
|
|
756
|
+
6. **Run tests**: `npm test` must pass before committing
|
|
757
|
+
7. **Commit, push**, and optionally create a GitHub release pointing to the release note
|
|
758
|
+
|
|
759
|
+
**Why three changelog surfaces?** They serve different audiences:
|
|
760
|
+
- `CLAUDE.md ## Changelog` — what the *next maintainer* needs (file/line references, rationale, latent bugs uncovered)
|
|
761
|
+
- `CHANGELOG.md` — what *users on a specific version* need (concise, categorized, scannable)
|
|
762
|
+
- `docs/releases/v<VERSION>.md` — what *people deciding to upgrade* need (highlights, breaking changes, upgrade guide)
|
|
763
|
+
|
|
764
|
+
Drift between these is the most common release-process bug. Keep them in sync per release.
|
|
745
765
|
|
|
746
766
|
### Release Note Template
|
|
747
767
|
|
|
@@ -802,6 +822,101 @@ curl -fsSL https://raw.githubusercontent.com/matteoscurati/ai-consultants/main/s
|
|
|
802
822
|
|
|
803
823
|
## Changelog
|
|
804
824
|
|
|
825
|
+
### v2.14.1
|
|
826
|
+
- **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`.
|
|
827
|
+
- **`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.
|
|
828
|
+
- **`npm run lint`**: convenience wrapper for the full-repo shellcheck invocation. Useful pre-push when you want to validate without staging.
|
|
829
|
+
- **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.
|
|
830
|
+
- **No runtime behavior change**: this is contributor-only tooling. Tests still pass (7 suites, ~510 assertions).
|
|
831
|
+
|
|
832
|
+
### v2.14.0
|
|
833
|
+
- **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.
|
|
834
|
+
- **`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.
|
|
835
|
+
- **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`).
|
|
836
|
+
- **`--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.
|
|
837
|
+
- **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.
|
|
838
|
+
- **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).
|
|
839
|
+
- **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.
|
|
840
|
+
- **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.
|
|
841
|
+
- **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`.
|
|
842
|
+
- **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.
|
|
843
|
+
- **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.
|
|
844
|
+
|
|
845
|
+
### v2.13.1
|
|
846
|
+
- **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).
|
|
847
|
+
- **Perf**: `apply_launch_stagger()` switched from `awk "BEGIN{printf}"` to pure-bash `printf '%d.%03d'` — 14 forks eliminated per consultation (~50-70ms aggregate).
|
|
848
|
+
- **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.
|
|
849
|
+
- **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`.
|
|
850
|
+
- **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`.
|
|
851
|
+
- **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.
|
|
852
|
+
- **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).
|
|
853
|
+
- **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`.
|
|
854
|
+
- All 6 test suites pass (493 assertions). Zero behavioral change for end users; XDG cache export is the only new env-var contract.
|
|
855
|
+
|
|
856
|
+
### v2.13.0
|
|
857
|
+
- 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.
|
|
858
|
+
- 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`.
|
|
859
|
+
- `--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.
|
|
860
|
+
- `_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.
|
|
861
|
+
- `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.
|
|
862
|
+
- XDG Base Directory compliance for transient and persistent paths (per freedesktop.org spec):
|
|
863
|
+
- `DEFAULT_OUTPUT_DIR_BASE`: `/tmp/ai_consultations` → `$XDG_CACHE_HOME/ai-consultants/consultations` (typically `~/.cache/...`)
|
|
864
|
+
- `CACHE_DIR`: `/tmp/ai_consultants_cache` → `$XDG_CACHE_HOME/ai-consultants/cache`
|
|
865
|
+
- `RATE_LIMIT_DIR`, `CHUNK_TEMP_DIR`: `/tmp/ai_consultants_*` → `$XDG_CACHE_HOME/ai-consultants/{ratelimit,chunks}`
|
|
866
|
+
- `SESSION_DIR`: `/tmp/ai_consultants_sessions` → `$XDG_STATE_HOME/ai-consultants/sessions` (`~/.local/state/...`)
|
|
867
|
+
- `COST_TRACKING_FILE`: `/tmp/ai_consultants_costs.json` → `$XDG_DATA_HOME/ai-consultants/costs.json` (`~/.local/share/...`)
|
|
868
|
+
- All env vars still respected; restore old behavior with `export DEFAULT_OUTPUT_DIR_BASE=/tmp/ai_consultations` etc.
|
|
869
|
+
- 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.
|
|
870
|
+
- 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.
|
|
871
|
+
- `RATE_LIMIT_DIR` and `CHUNK_TEMP_DIR` lifted to `config.sh` for consistency (were lib-only defaults).
|
|
872
|
+
- `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).
|
|
873
|
+
- 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.
|
|
874
|
+
- `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.
|
|
875
|
+
- 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.
|
|
876
|
+
- 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).
|
|
877
|
+
- 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.
|
|
878
|
+
- 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}`.
|
|
879
|
+
- 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.
|
|
880
|
+
- `scripts/test_doctor.sh` extended to 31 assertions: + self-exclusion regression, + jq preflight, + schema_version/recommended_command shape.
|
|
881
|
+
|
|
882
|
+
### v2.12.0
|
|
883
|
+
- New persistent user-config dir at `~/.config/ai-consultants/` (XDG-compliant; honors `AI_CONSULTANTS_CONFIG_DIR` and `XDG_CONFIG_HOME`)
|
|
884
|
+
- New `lib/user_config.sh` with `load_user_config()` — sourced from `config.sh` at the very top, before any defaults are applied
|
|
885
|
+
- `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
|
|
886
|
+
- `.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)
|
|
887
|
+
- `.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)
|
|
888
|
+
- 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`
|
|
889
|
+
- `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
|
|
890
|
+
- `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
|
|
891
|
+
- 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)
|
|
892
|
+
- `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
|
|
893
|
+
- `doctor.sh` adds `check_user_config()` reporting dir presence, files loaded, and warns on `.env` lax permissions — total checks now 22
|
|
894
|
+
- 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**
|
|
895
|
+
- 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)
|
|
896
|
+
- `scripts/test_routing_parity.sh` extended to 146 assertions (added user-dir branch of `_resolve_affinity_path`)
|
|
897
|
+
|
|
898
|
+
### v2.11.0
|
|
899
|
+
- Externalized routing affinity matrix from nested `case` statements in `lib/routing.sh` to `references/affinity.json` (~190 lines of bash → 60 lines of JSON)
|
|
900
|
+
- Custom matrix at runtime via `AFFINITY_FILE=/path/to/custom.json` (e.g. tweak scores per project, disable consultants by category)
|
|
901
|
+
- `get_affinity()` now performs JSON lookup with two-level cache: file content cached on first read, per-(category, consultant) result cached after first lookup
|
|
902
|
+
- 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)
|
|
903
|
+
- `doctor.sh` adds 3 new checks for affinity: file presence, JSON schema validity, coverage (every consultant in every category) — total checks now 21
|
|
904
|
+
- 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)
|
|
905
|
+
- `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
|
|
906
|
+
- `references/affinity.json` `_comment` documents the asymmetric 3-tier fallback (unknown consultant → 5, unknown category → 8, missing cell → 5) and the rationale
|
|
907
|
+
- 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
|
|
908
|
+
- `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)
|
|
909
|
+
- Cleaned `((attempt++)) || true || true` artifacts in `lib/api.sh` (introduced by the v2.10.9 mechanical sweep on lines that were already protected)
|
|
910
|
+
|
|
911
|
+
### v2.10.9
|
|
912
|
+
- 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
|
|
913
|
+
- 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 "$@"`
|
|
914
|
+
- 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)
|
|
915
|
+
- Added `--quick` flag to `doctor.sh` (accepted as no-op for backward compat with preflight)
|
|
916
|
+
- Updated `consult_all.sh` ENABLE_PREFLIGHT path to invoke `doctor.sh` directly
|
|
917
|
+
- 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)
|
|
918
|
+
- 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)
|
|
919
|
+
|
|
805
920
|
### v2.10.8
|
|
806
921
|
- 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
922
|
- 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`
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# AI Consultants v2.
|
|
1
|
+
# AI Consultants v2.14.1
|
|
2
2
|
|
|
3
3
|
> Query multiple AI models simultaneously for expert opinions on coding questions. Get diverse perspectives, automatic synthesis, confidence-weighted recommendations, and multi-agent debate.
|
|
4
4
|
|
|
5
|
-
[](https://github.com/matteoscurati/ai-consultants)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://docs.anthropic.com/en/docs/claude-code/skills)
|
|
8
8
|
[](https://github.com/matteoscurati/ai-consultants)
|
|
@@ -548,39 +548,35 @@ Control how responses are combined:
|
|
|
548
548
|
|
|
549
549
|
### Environment Variables
|
|
550
550
|
|
|
551
|
-
|
|
552
|
-
# Core features
|
|
553
|
-
ENABLE_DEBATE=true # Multi-agent debate
|
|
554
|
-
ENABLE_SYNTHESIS=true # Automatic synthesis
|
|
555
|
-
ENABLE_SMART_ROUTING=true # Intelligent consultant selection
|
|
556
|
-
ENABLE_PANIC_MODE=auto # Automatic rigor for uncertainty
|
|
557
|
-
|
|
558
|
-
# Defaults
|
|
559
|
-
DEFAULT_PRESET=balanced # Preset when --preset not given
|
|
560
|
-
DEFAULT_STRATEGY=majority # Strategy when --strategy not given
|
|
551
|
+
**Most users only need:**
|
|
561
552
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
553
|
+
```bash
|
|
554
|
+
ai-consultants init # creates ~/.config/ai-consultants/{config.sh,.env}
|
|
555
|
+
$EDITOR ~/.config/ai-consultants/.env
|
|
556
|
+
```
|
|
566
557
|
|
|
567
|
-
|
|
568
|
-
MAX_SESSION_COST=1.00 # Budget limit in USD
|
|
569
|
-
WARN_AT_COST=0.50 # Warning threshold
|
|
558
|
+
For ad-hoc overrides without persisting, the most common knobs:
|
|
570
559
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
560
|
+
```bash
|
|
561
|
+
DEFAULT_PRESET=balanced # minimal | balanced | thorough | high-stakes | fast | local | security
|
|
562
|
+
DEFAULT_STRATEGY=majority # majority | risk_averse | security_first | cost_capped | compare_only
|
|
563
|
+
ENABLE_DEBATE=true # Multi-agent debate (auto-skipped when consensus is high since v2.13)
|
|
564
|
+
ENABLE_OLLAMA=true # Enable local Ollama consultant
|
|
565
|
+
MAX_SESSION_COST=1.00 # USD budget cap (paired with ENABLE_BUDGET_LIMIT=true to enforce)
|
|
574
566
|
```
|
|
575
567
|
|
|
568
|
+
Full reference (~150 vars): [`references/configuration.md`](references/configuration.md). For category-aware preset suggestions: `ai-consultants doctor --suggest-preset --question "..."`.
|
|
569
|
+
|
|
576
570
|
### Doctor Command
|
|
577
571
|
|
|
578
|
-
Diagnose and fix
|
|
572
|
+
Diagnose, suggest, and fix:
|
|
579
573
|
|
|
580
574
|
```bash
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
575
|
+
ai-consultants doctor # 22 health checks
|
|
576
|
+
ai-consultants doctor --fix # Auto-fix common issues
|
|
577
|
+
ai-consultants doctor --json # JSON for automation
|
|
578
|
+
ai-consultants doctor --suggest-config # Print recommended ENABLE_* based on detected CLIs
|
|
579
|
+
ai-consultants doctor --suggest-preset --question "..." # Recommend preset + strategy for a question
|
|
584
580
|
```
|
|
585
581
|
|
|
586
582
|
---
|
package/SKILL.md
CHANGED
|
@@ -5,10 +5,10 @@ license: MIT
|
|
|
5
5
|
compatibility: Requires bash, jq, and at least 2 AI CLI tools (gemini, codex, vibe, etc.). macOS and Linux.
|
|
6
6
|
metadata:
|
|
7
7
|
author: matteoscurati
|
|
8
|
-
version: 2.
|
|
8
|
+
version: 2.14.1
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
# AI Consultants v2.
|
|
11
|
+
# AI Consultants v2.14.1 - AI Expert Panel
|
|
12
12
|
|
|
13
13
|
Simultaneously consult multiple AIs as "consultants" for coding questions. Each consultant has a **configurable persona** that influences their response style.
|
|
14
14
|
|
package/bin/ai-consultants
CHANGED
|
@@ -29,7 +29,16 @@ ensure_permissions() {
|
|
|
29
29
|
ensure_permissions
|
|
30
30
|
|
|
31
31
|
# --- Version ---
|
|
32
|
-
|
|
32
|
+
# Single source of truth: scripts/config.sh AI_CONSULTANTS_VERSION.
|
|
33
|
+
# We grep instead of sourcing to avoid pulling in the full config (cost).
|
|
34
|
+
# The sed pipeline succeeds even when its regex doesn't match (it returns
|
|
35
|
+
# the input verbatim), so we explicitly validate the result is semver — else
|
|
36
|
+
# the help banner would print garbage like "vAI_CONSULTANTS_VERSION=2.12.0".
|
|
37
|
+
VERSION=$(grep -E '^AI_CONSULTANTS_VERSION=' "$SCRIPTS_DIR/config.sh" 2>/dev/null \
|
|
38
|
+
| head -1 | sed -E 's/.*"([^"]+)".*/\1/' || true)
|
|
39
|
+
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
|
40
|
+
VERSION="unknown"
|
|
41
|
+
fi
|
|
33
42
|
|
|
34
43
|
# --- Subcommand routing ---
|
|
35
44
|
case "${1:-}" in
|
|
@@ -46,6 +55,7 @@ Usage:
|
|
|
46
55
|
ai-consultants --preset <name> "question" Use a configuration preset
|
|
47
56
|
ai-consultants --strategy <name> "question" Use a synthesis strategy
|
|
48
57
|
ai-consultants doctor [--fix] [--json] Run diagnostics
|
|
58
|
+
ai-consultants init [--force] Scaffold ~/.config/ai-consultants/{config.sh,.env}
|
|
49
59
|
ai-consultants install Install slash commands to ~/.claude/commands/
|
|
50
60
|
ai-consultants version Show version
|
|
51
61
|
ai-consultants help Show this help
|
|
@@ -68,6 +78,94 @@ EOF
|
|
|
68
78
|
shift
|
|
69
79
|
exec "$SCRIPTS_DIR/doctor.sh" "$@"
|
|
70
80
|
;;
|
|
81
|
+
init)
|
|
82
|
+
shift
|
|
83
|
+
FORCE=false
|
|
84
|
+
for arg in "$@"; do
|
|
85
|
+
[ "$arg" = "--force" ] && FORCE=true
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
# Reuse the canonical resolution from lib/user_config.sh.
|
|
89
|
+
# shellcheck source=../scripts/lib/user_config.sh
|
|
90
|
+
source "$SCRIPTS_DIR/lib/user_config.sh"
|
|
91
|
+
USER_DIR=$(get_user_config_dir)
|
|
92
|
+
if [ -z "$USER_DIR" ]; then
|
|
93
|
+
echo "Error: cannot resolve user config dir (HOME and XDG_CONFIG_HOME both unset)" >&2
|
|
94
|
+
echo " export AI_CONSULTANTS_CONFIG_DIR=/path/to/your/config to override" >&2
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# Refuse to write through a symlinked dir — protects against root running
|
|
99
|
+
# init when ~/.config/ai-consultants is a symlink to a sensitive path.
|
|
100
|
+
if [ -L "$USER_DIR" ]; then
|
|
101
|
+
echo "Error: $USER_DIR is a symlink. Refusing to scaffold into it." >&2
|
|
102
|
+
echo " Remove the symlink, or point AI_CONSULTANTS_CONFIG_DIR elsewhere." >&2
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Pre-flight a write check so the user gets a friendly error instead of a
|
|
107
|
+
# mid-scaffold mkdir/cp failure.
|
|
108
|
+
parent="$(dirname "$USER_DIR")"
|
|
109
|
+
if [ ! -w "$parent" ] && [ ! -d "$USER_DIR" ]; then
|
|
110
|
+
echo "Error: cannot write to $parent" >&2
|
|
111
|
+
echo " export AI_CONSULTANTS_CONFIG_DIR=/path/you/can/write to override" >&2
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
mkdir -p "$USER_DIR"
|
|
116
|
+
echo "User config dir: $USER_DIR"
|
|
117
|
+
|
|
118
|
+
# .env: copy from .env.example if present
|
|
119
|
+
DEST_ENV="$USER_DIR/.env"
|
|
120
|
+
SRC_ENV="$PROJECT_ROOT/.env.example"
|
|
121
|
+
if [ -f "$DEST_ENV" ] && [ "$FORCE" != true ]; then
|
|
122
|
+
echo " ○ .env already exists (use --force to overwrite)"
|
|
123
|
+
elif [ -f "$SRC_ENV" ]; then
|
|
124
|
+
cp "$SRC_ENV" "$DEST_ENV"
|
|
125
|
+
chmod 600 "$DEST_ENV"
|
|
126
|
+
echo " ✓ .env created from .env.example (chmod 600 — contains API keys)"
|
|
127
|
+
else
|
|
128
|
+
cat > "$DEST_ENV" <<'EOF'
|
|
129
|
+
# AI Consultants user environment
|
|
130
|
+
# KEY=value lines. Existing env vars take precedence.
|
|
131
|
+
# Uncomment what you want to override.
|
|
132
|
+
|
|
133
|
+
# ENABLE_DEBATE=true
|
|
134
|
+
# DEFAULT_PRESET=balanced
|
|
135
|
+
# DEFAULT_STRATEGY=majority
|
|
136
|
+
# MAX_SESSION_COST=2.00
|
|
137
|
+
# ENABLE_BUDGET_LIMIT=true
|
|
138
|
+
EOF
|
|
139
|
+
chmod 600 "$DEST_ENV"
|
|
140
|
+
echo " ✓ .env created (minimal template)"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# config.sh: minimal sourceable bash starter
|
|
144
|
+
DEST_CFG="$USER_DIR/config.sh"
|
|
145
|
+
if [ -f "$DEST_CFG" ] && [ "$FORCE" != true ]; then
|
|
146
|
+
echo " ○ config.sh already exists (use --force to overwrite)"
|
|
147
|
+
else
|
|
148
|
+
cat > "$DEST_CFG" <<'EOF'
|
|
149
|
+
#!/bin/bash
|
|
150
|
+
# ~/.config/ai-consultants/config.sh
|
|
151
|
+
# Sourced after .env, before scripts/config.sh defaults are applied.
|
|
152
|
+
# Use full bash logic. To defer to env vars, use ${VAR:-value}.
|
|
153
|
+
#
|
|
154
|
+
# Examples:
|
|
155
|
+
# export DEFAULT_PRESET="${DEFAULT_PRESET:-balanced}"
|
|
156
|
+
# export ENABLE_DEBATE="${ENABLE_DEBATE:-true}"
|
|
157
|
+
# export AFFINITY_FILE="${AFFINITY_FILE:-$HOME/.config/ai-consultants/affinity.json}"
|
|
158
|
+
EOF
|
|
159
|
+
echo " ✓ config.sh created (minimal template)"
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
echo ""
|
|
163
|
+
echo "Next steps:"
|
|
164
|
+
echo " 1. Edit $DEST_ENV to set API keys and overrides"
|
|
165
|
+
echo " 2. Run: ai-consultants doctor # verify config is loaded"
|
|
166
|
+
echo " 3. Run: ai-consultants \"your question\" # use the new defaults"
|
|
167
|
+
exit 0
|
|
168
|
+
;;
|
|
71
169
|
install)
|
|
72
170
|
COMMANDS_SRC="$PROJECT_ROOT/.claude/commands"
|
|
73
171
|
COMMANDS_DST="$HOME/.claude/commands"
|
package/docs/COST_RATES.md
CHANGED
package/docs/SMART_ROUTING.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Smart Routing - AI Consultants v2.
|
|
1
|
+
# Smart Routing - AI Consultants v2.11
|
|
2
2
|
|
|
3
3
|
The Smart Routing system automatically selects the most suitable consultants based on the question category.
|
|
4
4
|
|
|
@@ -17,20 +17,24 @@ MIN_AFFINITY=7
|
|
|
17
17
|
|
|
18
18
|
## Affinity Matrix
|
|
19
19
|
|
|
20
|
-
Consultant-category affinity scores (scale 1-10)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
|
29
|
-
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
20
|
+
Consultant-category affinity scores (scale 1-10) live in
|
|
21
|
+
[`references/affinity.json`](../references/affinity.json) — the single source
|
|
22
|
+
of truth at runtime. Prior to v2.11.0 the matrix was hard-coded as nested
|
|
23
|
+
case statements in `scripts/lib/routing.sh`; it was extracted to JSON to make
|
|
24
|
+
customization possible without editing bash.
|
|
25
|
+
|
|
26
|
+
**Highlights from the default matrix:**
|
|
27
|
+
|
|
28
|
+
| Category | Best match | Why |
|
|
29
|
+
|----------|-----------|-----|
|
|
30
|
+
| CODE_REVIEW | Codex (10), DeepSeek (10) | Code-specialist personas |
|
|
31
|
+
| BUG_DEBUG | Codex (10) | Pragmatic debugger |
|
|
32
|
+
| ARCHITECTURE | Gemini (10), Amp (10) | Big-picture design |
|
|
33
|
+
| ALGORITHM | DeepSeek (10) | Algorithm specialist |
|
|
34
|
+
| SECURITY | Mistral (10) | Devil's Advocate persona |
|
|
35
|
+
| QUICK_SYNTAX | Gemini (10) | Fast turnaround |
|
|
36
|
+
| API_DESIGN | Gemini (10) | API/system design |
|
|
37
|
+
| TESTING | Codex (10), GLM (10) | Test generation |
|
|
34
38
|
|
|
35
39
|
**Legend:**
|
|
36
40
|
- **10**: Perfect match
|
|
@@ -38,6 +42,49 @@ Consultant-category affinity scores (scale 1-10):
|
|
|
38
42
|
- 5-6: Medium match
|
|
39
43
|
- 1-4: Poor match
|
|
40
44
|
|
|
45
|
+
### Schema
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"version": "1.0",
|
|
50
|
+
"default_score": 5,
|
|
51
|
+
"general_score": 8,
|
|
52
|
+
"known_consultants": ["Gemini", "Codex", "..."],
|
|
53
|
+
"categories": {
|
|
54
|
+
"CODE_REVIEW": { "Gemini": 7, "Codex": 10, "..." },
|
|
55
|
+
"BUG_DEBUG": { "..." }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Lookup logic in `get_affinity(category, consultant)`:
|
|
61
|
+
|
|
62
|
+
1. If `consultant` is not in `known_consultants` → `default_score`
|
|
63
|
+
2. Else if `category` is not in `categories` (e.g. `GENERAL` or unrecognized) → `general_score`
|
|
64
|
+
3. Else → `categories[category][consultant]`, falling back to `default_score` if missing
|
|
65
|
+
|
|
66
|
+
### Custom Matrix Override
|
|
67
|
+
|
|
68
|
+
Override the matrix at runtime by pointing `AFFINITY_FILE` at a custom JSON
|
|
69
|
+
file with the same schema:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
AFFINITY_FILE=~/my-affinity.json ./scripts/consult_all.sh "your question"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This is useful for:
|
|
76
|
+
- Tweaking scores for a specific project (e.g., favoring DeepSeek for
|
|
77
|
+
algorithm-heavy codebases)
|
|
78
|
+
- Disabling consultants for a category by setting their score below
|
|
79
|
+
`MIN_AFFINITY`
|
|
80
|
+
- Experimenting with new categories before upstreaming them
|
|
81
|
+
|
|
82
|
+
`./scripts/doctor.sh` validates the JSON schema and reports coverage gaps
|
|
83
|
+
(consultants missing from a category).
|
|
84
|
+
|
|
85
|
+
The matrix is loaded once per shell and cached in memory — no jq overhead
|
|
86
|
+
on subsequent calls.
|
|
87
|
+
|
|
41
88
|
## Routing Modes
|
|
42
89
|
|
|
43
90
|
The system automatically determines how many consultants to involve:
|
package/docs/cost_rates.json
CHANGED