amicus 4.9.3 → 4.9.4

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.
Files changed (60) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +242 -0
  3. package/README.md +1 -1
  4. package/docs/ROADMAP.md +5 -4
  5. package/docs/architecture-map.md +732 -0
  6. package/docs/configuration.md +148 -26
  7. package/docs/council.md +9 -0
  8. package/docs/doc-system.md +12 -9
  9. package/docs/testing.md +2 -1
  10. package/docs/troubleshooting.md +76 -0
  11. package/docs/usage.md +11 -6
  12. package/package.json +1 -1
  13. package/schemas/model-catalog.schema.json +2 -1
  14. package/schemas/run.schema.json +13 -0
  15. package/skills/sidecar/SKILL.md +1 -8
  16. package/src/cli-handlers-doctor.js +3 -0
  17. package/src/cli-handlers-fanout.js +10 -1
  18. package/src/cli-handlers-resume-continue.js +25 -0
  19. package/src/cli.js +5 -8
  20. package/src/council/briefings-chair.js +4 -2
  21. package/src/council/run-assemble.js +7 -2
  22. package/src/council/run-retry-notes.js +21 -1
  23. package/src/council/run-stages.js +8 -1
  24. package/src/headless.js +125 -7
  25. package/src/mcp-server.js +26 -0
  26. package/src/mcp-tools.js +4 -4
  27. package/src/opencode-client.js +84 -8
  28. package/src/pack/pack-validate.js +3 -0
  29. package/src/session-manager.js +2 -2
  30. package/src/sidecar/continue.js +6 -1
  31. package/src/sidecar/conversation-mirror.js +35 -11
  32. package/src/sidecar/fanout-leg-fallback.js +1 -0
  33. package/src/sidecar/fanout-leg.js +10 -2
  34. package/src/sidecar/fanout.js +2 -2
  35. package/src/sidecar/interactive.js +31 -4
  36. package/src/sidecar/models-ceiling-line.js +72 -0
  37. package/src/sidecar/models.js +4 -2
  38. package/src/sidecar/reopen-notices.js +97 -0
  39. package/src/sidecar/reopen-spend.js +3 -2
  40. package/src/sidecar/resume.js +15 -2
  41. package/src/sidecar/session-finalize.js +4 -1
  42. package/src/sidecar/session-utils.js +5 -1
  43. package/src/sidecar/start-metadata.js +1 -1
  44. package/src/sidecar/start.js +10 -5
  45. package/src/utils/config.js +33 -12
  46. package/src/utils/curated-models.js +8 -8
  47. package/src/utils/degrade.js +7 -0
  48. package/src/utils/doctor-output-budget-check.js +198 -0
  49. package/src/utils/engine-output-flag.js +105 -0
  50. package/src/utils/engine-variants.js +298 -0
  51. package/src/utils/http-get.js +284 -0
  52. package/src/utils/model-catalog.js +36 -4
  53. package/src/utils/model-ceilings-modelsdev.js +230 -0
  54. package/src/utils/model-fetcher.js +12 -36
  55. package/src/utils/model-output-limit.js +21 -13
  56. package/src/utils/output-length.js +90 -0
  57. package/src/utils/result-schema.js +7 -2
  58. package/src/utils/spend-ledger.js +5 -1
  59. package/src/utils/thinking-validators.js +27 -80
  60. package/src/utils/validators.js +2 -3
@@ -1,92 +1,39 @@
1
1
  /**
2
2
  * Thinking Level Validators
3
3
  *
4
- * Model-specific thinking level validation.
5
- * Extracted from validators.js to keep modules under 300 lines.
4
+ * #218 PR 4: the CLI's `--thinking` check is a VOCABULARY check only — the seven
5
+ * levels the curated routes declare between them (engine-variants.js ::
6
+ * VARIANT_LEVELS, measured on the engine's /config/providers dump, probe M0).
7
+ * Whether a given MODEL declares the level is the engine's call, read from that
8
+ * same dump at send time (opencode-client.js :: sendPrompt), where a level the
9
+ * model does not declare is refused before anything is sent. The per-model table
10
+ * this file carried until PR 4 (gpt-5 "without minimal", gemini "with everything")
11
+ * was a static guess the dump CONFIRMS on one row and contradicts on the other
12
+ * (M0: both exclude `minimal` for gpt-5 — gpt-5.6-terra declares none, low, medium,
13
+ * high, xhigh, max — while the table gave gemini `none` and `xhigh` and
14
+ * gemini-3.6-flash declares neither, only minimal, low, medium, high), and its "use
15
+ * medium instead" adjustment sent a level the user never asked for. Both are gone;
16
+ * nothing is adjusted here — guessing right on one row does not make a guess a
17
+ * declaration (council #235 r1 wave 2: this docblock had cited the CONFIRMING row
18
+ * as the contradiction, the same inversion the CHANGELOG carried).
6
19
  */
7
20
 
8
- /**
9
- * Model-specific thinking level support (static fallback)
10
- * Maps model patterns to their supported thinking levels.
11
- *
12
- * NOTE: For dynamic, up-to-date capabilities, use model-capabilities.js
13
- * which fetches from OpenRouter API and caches the results.
14
- * This static map is used as a fast fallback for CLI validation.
15
- */
16
- const MODEL_THINKING_SUPPORT = {
17
- // OpenAI GPT-5.x does NOT support 'minimal'
18
- 'gpt-5': ['none', 'low', 'medium', 'high', 'xhigh'],
19
- // o3/o3-mini supports all levels
20
- 'o3': ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'],
21
- // Gemini supports all levels
22
- 'gemini': ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'],
23
- // Default: all levels supported
24
- 'default': ['none', 'minimal', 'low', 'medium', 'high', 'xhigh']
25
- };
26
-
27
- /**
28
- * Get supported thinking levels for a model (synchronous, static fallback)
29
- *
30
- * For dynamic lookup from OpenRouter API cache, use:
31
- * const { getSupportedThinkingLevels } = require('./model-capabilities');
32
- *
33
- * @param {string} model - Model identifier
34
- * @returns {string[]} Array of supported thinking levels
35
- */
36
- function getSupportedThinkingLevels(model) {
37
- if (!model) {return MODEL_THINKING_SUPPORT.default;}
38
-
39
- const modelLower = model.toLowerCase();
40
-
41
- // Check each known model pattern
42
- for (const [pattern, levels] of Object.entries(MODEL_THINKING_SUPPORT)) {
43
- if (pattern !== 'default' && modelLower.includes(pattern)) {
44
- return levels;
45
- }
46
- }
47
-
48
- return MODEL_THINKING_SUPPORT.default;
49
- }
21
+ const { VARIANT_LEVELS } = require('./engine-variants');
50
22
 
51
23
  /**
52
- * Validate thinking level for a specific model (synchronous)
53
- *
54
- * For async validation with dynamic API cache, use:
55
- * const { validateThinkingForModel } = require('./model-capabilities');
56
- *
57
- * @param {string} thinking - Thinking level ('minimal', 'low', 'medium', 'high', 'xhigh', 'none')
58
- * @param {string} model - Model identifier
59
- * @returns {{valid: boolean, error?: string, warning?: string, adjustedLevel?: string}}
24
+ * @param {string} [thinking] the requested level; omitted (undefined/null) is valid (nothing is sent then)
25
+ * @returns {{valid: boolean, error?: string}}
60
26
  */
61
- function validateThinkingLevel(thinking, model) {
62
- if (!thinking) {
63
- return { valid: true };
27
+ function validateThinkingLevel(thinking) {
28
+ // council #235 r2 (A2): presence, not truthiness. `--thinking=` parses to '' (cli.js's
29
+ // inline-value branch) and a truthiness test accepted it as "flag omitted", so the level
30
+ // was silently dropped. An omitted flag is undefined/null; anything else the user typed
31
+ // must face the vocabulary check. Named mutant "FALSYLEVELACCEPTED": restore `if (!thinking)`.
32
+ if (thinking === undefined || thinking === null) { return { valid: true }; }
33
+ if (!VARIANT_LEVELS.includes(thinking)) {
34
+ return { valid: false, error: `Error: --thinking must be one of: ${VARIANT_LEVELS.join(', ')}` };
64
35
  }
65
-
66
- const allLevels = MODEL_THINKING_SUPPORT.default;
67
- if (!allLevels.includes(thinking)) {
68
- return {
69
- valid: false,
70
- error: `Error: --thinking must be one of: ${allLevels.join(', ')}`
71
- };
72
- }
73
-
74
- const supportedLevels = getSupportedThinkingLevels(model);
75
- if (!supportedLevels.includes(thinking)) {
76
- // Map to nearest supported level
77
- const fallback = thinking === 'minimal' ? 'low' : 'medium';
78
- return {
79
- valid: true,
80
- warning: `Warning: Model '${model}' does not support thinking level '${thinking}'. Using '${fallback}' instead.`,
81
- adjustedLevel: fallback
82
- };
83
- }
84
-
85
36
  return { valid: true };
86
37
  }
87
38
 
88
- module.exports = {
89
- MODEL_THINKING_SUPPORT,
90
- getSupportedThinkingLevels,
91
- validateThinkingLevel
92
- };
39
+ module.exports = { VARIANT_LEVELS, validateThinkingLevel };
@@ -214,7 +214,7 @@ function validateHeadlessAgent(agent) {
214
214
  }
215
215
 
216
216
  const { validateMcpSpec, validateMcpConfigFile } = require('./mcp-validators');
217
- const { MODEL_THINKING_SUPPORT, getSupportedThinkingLevels, validateThinkingLevel } = require('./thinking-validators');
217
+ const { VARIANT_LEVELS, validateThinkingLevel } = require('./thinking-validators');
218
218
 
219
219
  /**
220
220
  * Validate API key is present for the given model's provider.
@@ -260,7 +260,7 @@ function validateApiKey(model) {
260
260
  module.exports = {
261
261
  VALID_AGENT_MODES,
262
262
  PROVIDER_KEY_MAP,
263
- MODEL_THINKING_SUPPORT,
263
+ VARIANT_LEVELS,
264
264
  TASK_ID_PATTERN,
265
265
  validateTaskId,
266
266
  TAG_PATTERN,
@@ -278,7 +278,6 @@ module.exports = {
278
278
  validateMcpConfigFile,
279
279
  validateApiKey,
280
280
  validateThinkingLevel,
281
- getSupportedThinkingLevels,
282
281
  findSessionInProjectDirs,
283
282
  // Re-exported from input-validators.js
284
283
  validateStartInputs: require('./input-validators').validateStartInputs,