zelari-code 2.1.0 → 2.1.2

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 (114) hide show
  1. package/README.md +4 -4
  2. package/package.json +8 -5
  3. package/dist/cli/ast/engine.test.js +0 -101
  4. package/dist/cli/ast/engine.test.js.map +0 -1
  5. package/dist/cli/ast/tools.test.js +0 -124
  6. package/dist/cli/ast/tools.test.js.map +0 -1
  7. package/dist/cli/headless.test.js +0 -107
  8. package/dist/cli/headless.test.js.map +0 -1
  9. package/dist/cli/headlessE2eSession.test.js +0 -189
  10. package/dist/cli/headlessE2eSession.test.js.map +0 -1
  11. package/dist/cli/headlessHistorySeed.test.js +0 -158
  12. package/dist/cli/headlessHistorySeed.test.js.map +0 -1
  13. package/dist/cli/headlessSessionEvent.test.js +0 -83
  14. package/dist/cli/headlessSessionEvent.test.js.map +0 -1
  15. package/dist/cli/headlessSpine.test.js +0 -153
  16. package/dist/cli/headlessSpine.test.js.map +0 -1
  17. package/dist/cli/hooks/observationStore.test.js +0 -135
  18. package/dist/cli/hooks/observationStore.test.js.map +0 -1
  19. package/dist/cli/hooks/sessionSurface.test.js +0 -112
  20. package/dist/cli/hooks/sessionSurface.test.js.map +0 -1
  21. package/dist/cli/kraken/candidateRegistry.test.js +0 -211
  22. package/dist/cli/kraken/candidateRegistry.test.js.map +0 -1
  23. package/dist/cli/kraken/completionGate.test.js +0 -172
  24. package/dist/cli/kraken/completionGate.test.js.map +0 -1
  25. package/dist/cli/kraken/evidenceAnchoring.test.js +0 -92
  26. package/dist/cli/kraken/evidenceAnchoring.test.js.map +0 -1
  27. package/dist/cli/kraken/evidenceProvenance.test.js +0 -113
  28. package/dist/cli/kraken/evidenceProvenance.test.js.map +0 -1
  29. package/dist/cli/kraken/executor.workbench.test.js +0 -134
  30. package/dist/cli/kraken/executor.workbench.test.js.map +0 -1
  31. package/dist/cli/kraken/metrics.test.js +0 -145
  32. package/dist/cli/kraken/metrics.test.js.map +0 -1
  33. package/dist/cli/kraken/nativeVerification.test.js +0 -207
  34. package/dist/cli/kraken/nativeVerification.test.js.map +0 -1
  35. package/dist/cli/kraken/planner.test.js +0 -43
  36. package/dist/cli/kraken/planner.test.js.map +0 -1
  37. package/dist/cli/kraken/scriptPlanner.test.js +0 -152
  38. package/dist/cli/kraken/scriptPlanner.test.js.map +0 -1
  39. package/dist/cli/kraken/selectionPlaybook.test.js +0 -55
  40. package/dist/cli/kraken/selectionPlaybook.test.js.map +0 -1
  41. package/dist/cli/kraken/skillSuggest.test.js +0 -157
  42. package/dist/cli/kraken/skillSuggest.test.js.map +0 -1
  43. package/dist/cli/kraken/strictDefaults.test.js +0 -149
  44. package/dist/cli/kraken/strictDefaults.test.js.map +0 -1
  45. package/dist/cli/kraken/strictGatePackIndependence.test.js +0 -112
  46. package/dist/cli/kraken/strictGatePackIndependence.test.js.map +0 -1
  47. package/dist/cli/kraken/turnRuntime.test.js +0 -377
  48. package/dist/cli/kraken/turnRuntime.test.js.map +0 -1
  49. package/dist/cli/kraken/verificationBridge.session.test.js +0 -104
  50. package/dist/cli/kraken/verificationBridge.session.test.js.map +0 -1
  51. package/dist/cli/kraken/verificationBridge.test.js +0 -177
  52. package/dist/cli/kraken/verificationBridge.test.js.map +0 -1
  53. package/dist/cli/kraken/verifier.test.js +0 -232
  54. package/dist/cli/kraken/verifier.test.js.map +0 -1
  55. package/dist/cli/kraken/verifierAdvisoryLock.test.js +0 -154
  56. package/dist/cli/kraken/verifierAdvisoryLock.test.js.map +0 -1
  57. package/dist/cli/kraken/verifierLifecycle.test.js +0 -181
  58. package/dist/cli/kraken/verifierLifecycle.test.js.map +0 -1
  59. package/dist/cli/kraken/verifierRoundTrip.test.js +0 -166
  60. package/dist/cli/kraken/verifierRoundTrip.test.js.map +0 -1
  61. package/dist/cli/kraken/verifierSettings.test.js +0 -237
  62. package/dist/cli/kraken/verifierSettings.test.js.map +0 -1
  63. package/dist/cli/kraken/verifyReport.test.js +0 -111
  64. package/dist/cli/kraken/verifyReport.test.js.map +0 -1
  65. package/dist/cli/kraken/weaknessMeter.test.js +0 -212
  66. package/dist/cli/kraken/weaknessMeter.test.js.map +0 -1
  67. package/dist/cli/kraken/workbench.test.js +0 -253
  68. package/dist/cli/kraken/workbench.test.js.map +0 -1
  69. package/dist/cli/kraken/workbenchView.test.js +0 -130
  70. package/dist/cli/kraken/workbenchView.test.js.map +0 -1
  71. package/dist/cli/legacyContextIsolation.test.js +0 -65
  72. package/dist/cli/legacyContextIsolation.test.js.map +0 -1
  73. package/dist/cli/lsp/tools.test.js +0 -90
  74. package/dist/cli/lsp/tools.test.js.map +0 -1
  75. package/dist/cli/missionContinuation.test.js +0 -117
  76. package/dist/cli/missionContinuation.test.js.map +0 -1
  77. package/dist/cli/profileMatrix.test.js +0 -130
  78. package/dist/cli/profileMatrix.test.js.map +0 -1
  79. package/dist/cli/provider/capabilities.test.js +0 -46
  80. package/dist/cli/provider/capabilities.test.js.map +0 -1
  81. package/dist/cli/provider/openai-compatible.timeout.test.js +0 -72
  82. package/dist/cli/provider/openai-compatible.timeout.test.js.map +0 -1
  83. package/dist/cli/providerConfig.test.js +0 -85
  84. package/dist/cli/providerConfig.test.js.map +0 -1
  85. package/dist/cli/sessionReplayInvariant.test.js +0 -187
  86. package/dist/cli/sessionReplayInvariant.test.js.map +0 -1
  87. package/dist/cli/sessionSpine.test.js +0 -171
  88. package/dist/cli/sessionSpine.test.js.map +0 -1
  89. package/dist/cli/thinking.test.js +0 -214
  90. package/dist/cli/thinking.test.js.map +0 -1
  91. package/dist/cli/tools/inspectCommand.schema.test.js +0 -82
  92. package/dist/cli/tools/inspectCommand.schema.test.js.map +0 -1
  93. package/dist/cli/tools/inspectCommand.test.js +0 -311
  94. package/dist/cli/tools/inspectCommand.test.js.map +0 -1
  95. package/dist/cli/tools/krakenCsvFanout.test.js +0 -200
  96. package/dist/cli/tools/krakenCsvFanout.test.js.map +0 -1
  97. package/dist/cli/tools/krakenSelectTool.test.js +0 -246
  98. package/dist/cli/tools/krakenSelectTool.test.js.map +0 -1
  99. package/dist/cli/tools/observeBatch.test.js +0 -329
  100. package/dist/cli/tools/observeBatch.test.js.map +0 -1
  101. package/dist/cli/tools/taskTool.dynamicChecks.test.js +0 -156
  102. package/dist/cli/tools/taskTool.dynamicChecks.test.js.map +0 -1
  103. package/dist/cli/tools/taskTool.planSafety.test.js +0 -280
  104. package/dist/cli/tools/taskTool.planSafety.test.js.map +0 -1
  105. package/dist/cli/tools/taskTool.verifyReport.test.js +0 -140
  106. package/dist/cli/tools/taskTool.verifyReport.test.js.map +0 -1
  107. package/dist/cli/utils/contextGrowthSummary.test.js +0 -74
  108. package/dist/cli/utils/contextGrowthSummary.test.js.map +0 -1
  109. package/dist/cli/workspace/planDriftCheck.test.js +0 -146
  110. package/dist/cli/workspace/planDriftCheck.test.js.map +0 -1
  111. package/dist/cli/workspace/planStore.test.js +0 -295
  112. package/dist/cli/workspace/planStore.test.js.map +0 -1
  113. package/dist/cli/zelariMission.test.js +0 -44
  114. package/dist/cli/zelariMission.test.js.map +0 -1
@@ -1,214 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { parseThinkingSpec, stringifyThinkingSpec, isValidThinkingInput, thinkingCapabilityFor, effortLevelsFor, thinkingSelectOptions, clampEffort, translateOpenAiCompatibleThinking, translateResponsesThinking, translateAnthropicThinking, } from './thinking.js';
3
- describe('parseThinkingSpec', () => {
4
- it('maps canonical strings', () => {
5
- expect(parseThinkingSpec('auto')).toBe('auto');
6
- expect(parseThinkingSpec(undefined)).toBe('auto');
7
- expect(parseThinkingSpec('off')).toEqual({ kind: 'off' });
8
- expect(parseThinkingSpec('low')).toEqual({ kind: 'effort', effort: 'low' });
9
- expect(parseThinkingSpec('high')).toEqual({ kind: 'effort', effort: 'high' });
10
- expect(parseThinkingSpec('xhigh')).toEqual({ kind: 'effort', effort: 'xhigh' });
11
- expect(parseThinkingSpec('max')).toEqual({ kind: 'effort', effort: 'max' });
12
- expect(parseThinkingSpec('budget:16000')).toEqual({ kind: 'budget', budgetTokens: 16000 });
13
- });
14
- it('degrades unknown input to auto (never throws)', () => {
15
- expect(parseThinkingSpec('garbage')).toBe('auto');
16
- expect(parseThinkingSpec('budget:0')).toBe('auto');
17
- expect(parseThinkingSpec('')).toBe('auto');
18
- });
19
- });
20
- describe('stringifyThinkingSpec / isValidThinkingInput', () => {
21
- it('round-trips', () => {
22
- expect(stringifyThinkingSpec(parseThinkingSpec('high'))).toBe('high');
23
- expect(stringifyThinkingSpec(parseThinkingSpec('xhigh'))).toBe('xhigh');
24
- expect(stringifyThinkingSpec(parseThinkingSpec('max'))).toBe('max');
25
- expect(stringifyThinkingSpec(parseThinkingSpec('budget:16000'))).toBe('budget:16000');
26
- expect(stringifyThinkingSpec('auto')).toBe('auto');
27
- });
28
- it('validates strictly', () => {
29
- expect(isValidThinkingInput('auto')).toBe(true);
30
- expect(isValidThinkingInput('off')).toBe(true);
31
- expect(isValidThinkingInput('medium')).toBe(true);
32
- expect(isValidThinkingInput('xhigh')).toBe(true);
33
- expect(isValidThinkingInput('max')).toBe(true);
34
- expect(isValidThinkingInput('budget:16000')).toBe(true);
35
- expect(isValidThinkingInput('garbage')).toBe(false);
36
- expect(isValidThinkingInput('budget:0')).toBe(false);
37
- });
38
- });
39
- describe('thinkingCapabilityFor / effortLevelsFor', () => {
40
- it('flags effort vs budget providers', () => {
41
- expect(thinkingCapabilityFor('grok').effort).toBe(true);
42
- expect(thinkingCapabilityFor('anthropic').budget).toBe(true);
43
- expect(thinkingCapabilityFor('glm').budget).toBe(true);
44
- expect(thinkingCapabilityFor('deepseek').effort).toBe(true);
45
- });
46
- it('gates xhigh/max on the model family', () => {
47
- expect(effortLevelsFor('grok', 'grok-4.5')).toEqual(['low', 'medium', 'high']);
48
- expect(effortLevelsFor('grok', 'grok-4.6')).toEqual(['low', 'medium', 'high', 'xhigh']);
49
- expect(effortLevelsFor('chatgpt', 'gpt-5.2-codex')).toEqual(['low', 'medium', 'high']);
50
- expect(effortLevelsFor('chatgpt', 'gpt-5.4')).toEqual(['low', 'medium', 'high', 'xhigh']);
51
- expect(effortLevelsFor('chatgpt', 'gpt-5.6-codex')).toEqual(['low', 'medium', 'high', 'xhigh', 'max']);
52
- expect(effortLevelsFor('deepseek', 'deepseek-v4-pro')).toEqual(['high', 'max']);
53
- expect(effortLevelsFor('anthropic', 'claude-sonnet-4-5')).toEqual([]);
54
- expect(effortLevelsFor('anthropic', 'claude-sonnet-4-6')).toEqual(['high', 'max']);
55
- expect(effortLevelsFor('anthropic', 'claude-opus-4-7')).toEqual(['high', 'xhigh', 'max']);
56
- expect(effortLevelsFor('glm', 'glm-4.6')).toEqual([]);
57
- expect(effortLevelsFor('glm', 'glm-5.3')).toEqual(['low', 'high', 'max']);
58
- expect(effortLevelsFor('minimax', 'MiniMax-M2.5')).toEqual(['low', 'medium', 'high']);
59
- });
60
- it('exposes native efforts on the capability snapshot', () => {
61
- expect(thinkingCapabilityFor('grok', 'grok-4.6').efforts).toContain('xhigh');
62
- expect(thinkingCapabilityFor('chatgpt', 'gpt-5.6').efforts).toContain('max');
63
- expect(thinkingCapabilityFor('anthropic', 'claude-sonnet-4-6').effort).toBe(true);
64
- expect(thinkingCapabilityFor('anthropic', 'claude-sonnet-4-6').budget).toBe(true);
65
- expect(thinkingCapabilityFor('glm', 'glm-5.3').budget).toBe(false);
66
- expect(thinkingCapabilityFor('glm', 'glm-5.3').effort).toBe(true);
67
- });
68
- });
69
- describe('thinkingSelectOptions', () => {
70
- it('shows xHigh for grok-4.6 and not grok-4.5', () => {
71
- const v46 = thinkingSelectOptions('grok', 'grok-4.6').map((o) => o.value);
72
- const v45 = thinkingSelectOptions('grok', 'grok-4.5').map((o) => o.value);
73
- expect(v46).toEqual(['auto', 'off', 'low', 'medium', 'high', 'xhigh']);
74
- expect(v45).toEqual(['auto', 'off', 'low', 'medium', 'high']);
75
- });
76
- it('shows Max (not Low/Medium) for DeepSeek regardless of model id', () => {
77
- const v = thinkingSelectOptions('deepseek', 'deepseek-v4-flash').map((o) => o.value);
78
- expect(v).toEqual(['auto', 'off', 'high', 'max']);
79
- expect(v).not.toContain('low');
80
- expect(v).not.toContain('medium');
81
- });
82
- it('shows xHigh+Max for gpt-5.6-codex', () => {
83
- const v = thinkingSelectOptions('chatgpt', 'gpt-5.6-codex').map((o) => o.value);
84
- expect(v).toContain('xhigh');
85
- expect(v).toContain('max');
86
- });
87
- });
88
- describe('clampEffort', () => {
89
- it('keeps native levels', () => {
90
- expect(clampEffort('grok', 'grok-4.6', 'xhigh')).toEqual({
91
- effort: 'xhigh',
92
- clamped: false,
93
- });
94
- });
95
- it('clamps xhigh on grok-4.5 to high', () => {
96
- const r = clampEffort('grok', 'grok-4.5', 'xhigh');
97
- expect(r.effort).toBe('high');
98
- expect(r.clamped).toBe(true);
99
- });
100
- it('clamps xhigh on glm-5.3 to max', () => {
101
- const r = clampEffort('glm', 'glm-5.3', 'xhigh');
102
- expect(r.effort).toBe('max');
103
- expect(r.clamped).toBe(true);
104
- });
105
- it('clamps low on deepseek to high', () => {
106
- const r = clampEffort('deepseek', 'deepseek-v4-pro', 'low');
107
- expect(r.effort).toBe('high');
108
- expect(r.clamped).toBe(true);
109
- });
110
- });
111
- describe('translateOpenAiCompatibleThinking', () => {
112
- it('auto → empty patch', () => {
113
- expect(translateOpenAiCompatibleThinking('grok', 'auto')).toEqual({ patch: {}, degraded: false });
114
- });
115
- it('off on effort providers → reasoning_effort low', () => {
116
- expect(translateOpenAiCompatibleThinking('grok', { kind: 'off' }))
117
- .toEqual({ patch: { reasoning_effort: 'low' }, degraded: false });
118
- });
119
- it('effort on effort providers → reasoning_effort', () => {
120
- expect(translateOpenAiCompatibleThinking('grok', { kind: 'effort', effort: 'high' }))
121
- .toEqual({ patch: { reasoning_effort: 'high' }, degraded: false });
122
- });
123
- it('xhigh on grok-4.6 is sent native', () => {
124
- expect(translateOpenAiCompatibleThinking('grok', { kind: 'effort', effort: 'xhigh' }, 'grok-4.6'))
125
- .toEqual({ patch: { reasoning_effort: 'xhigh' }, degraded: false });
126
- });
127
- it('xhigh on grok-4.5 clamps to high (still sent)', () => {
128
- const r = translateOpenAiCompatibleThinking('grok', { kind: 'effort', effort: 'xhigh' }, 'grok-4.5');
129
- expect(r.patch).toEqual({ reasoning_effort: 'high' });
130
- expect(r.degraded).toBe(false);
131
- expect(r.note).toMatch(/xhigh/);
132
- });
133
- it('max on deepseek is sent native', () => {
134
- expect(translateOpenAiCompatibleThinking('deepseek', { kind: 'effort', effort: 'max' }, 'deepseek-v4-pro'))
135
- .toEqual({
136
- patch: { thinking: { type: 'enabled' }, reasoning_effort: 'max' },
137
- degraded: false,
138
- });
139
- });
140
- it('high on deepseek stays high (max is a separate level)', () => {
141
- expect(translateOpenAiCompatibleThinking('deepseek', { kind: 'effort', effort: 'high' }))
142
- .toEqual({
143
- patch: { thinking: { type: 'enabled' }, reasoning_effort: 'high' },
144
- degraded: false,
145
- });
146
- });
147
- it('glm-5.3 effort uses reasoning_effort + thinking toggle', () => {
148
- expect(translateOpenAiCompatibleThinking('glm', { kind: 'effort', effort: 'max' }, 'glm-5.3'))
149
- .toEqual({
150
- patch: { thinking: { type: 'enabled' }, reasoning_effort: 'max' },
151
- degraded: false,
152
- });
153
- });
154
- it('budget on effort-only providers degrades to auto', () => {
155
- const r = translateOpenAiCompatibleThinking('grok', { kind: 'budget', budgetTokens: 1000 });
156
- expect(r.degraded).toBe(true);
157
- expect(r.patch).toEqual({});
158
- });
159
- it('off on deepseek → thinking disabled', () => {
160
- expect(translateOpenAiCompatibleThinking('deepseek', { kind: 'off' }))
161
- .toEqual({ patch: { thinking: { type: 'disabled' } }, degraded: false });
162
- });
163
- it('budget on glm → thinking budget block', () => {
164
- expect(translateOpenAiCompatibleThinking('glm', { kind: 'budget', budgetTokens: 16000 }))
165
- .toEqual({ patch: { thinking: { type: 'enabled', budget_tokens: 16000 } }, degraded: false });
166
- });
167
- });
168
- describe('translateResponsesThinking', () => {
169
- it('off → reasoning minimal', () => {
170
- expect(translateResponsesThinking({ kind: 'off' }))
171
- .toEqual({ patch: { reasoning: { effort: 'minimal' } }, degraded: false });
172
- });
173
- it('effort → reasoning effort', () => {
174
- expect(translateResponsesThinking({ kind: 'effort', effort: 'high' }))
175
- .toEqual({ patch: { reasoning: { effort: 'high' } }, degraded: false });
176
- });
177
- it('xhigh/max on gpt-5.6 are sent native', () => {
178
- expect(translateResponsesThinking({ kind: 'effort', effort: 'xhigh' }, 'gpt-5.6'))
179
- .toEqual({ patch: { reasoning: { effort: 'xhigh' } }, degraded: false });
180
- expect(translateResponsesThinking({ kind: 'effort', effort: 'max' }, 'gpt-5.6-codex'))
181
- .toEqual({ patch: { reasoning: { effort: 'max' } }, degraded: false });
182
- });
183
- it('max on gpt-5.2 clamps to high', () => {
184
- const r = translateResponsesThinking({ kind: 'effort', effort: 'max' }, 'gpt-5.2-codex');
185
- expect(r.patch).toEqual({ reasoning: { effort: 'high' } });
186
- expect(r.degraded).toBe(false);
187
- expect(r.note).toMatch(/max/);
188
- });
189
- it('budget → degraded', () => {
190
- expect(translateResponsesThinking({ kind: 'budget', budgetTokens: 1000 }).degraded).toBe(true);
191
- });
192
- });
193
- describe('translateAnthropicThinking', () => {
194
- it('off → thinking disabled', () => {
195
- expect(translateAnthropicThinking({ kind: 'off' }))
196
- .toEqual({ patch: { thinking: { type: 'disabled' } }, degraded: false });
197
- });
198
- it('budget → enabled + budget_tokens', () => {
199
- expect(translateAnthropicThinking({ kind: 'budget', budgetTokens: 32000 }))
200
- .toEqual({ patch: { thinking: { type: 'enabled', budget_tokens: 32000 } }, degraded: false });
201
- });
202
- it('effort on sonnet 4.5 → degraded', () => {
203
- expect(translateAnthropicThinking({ kind: 'effort', effort: 'high' }, 'claude-sonnet-4-5').degraded).toBe(true);
204
- });
205
- it('effort on sonnet 4.6 → output_config.effort', () => {
206
- expect(translateAnthropicThinking({ kind: 'effort', effort: 'max' }, 'claude-sonnet-4-6'))
207
- .toEqual({ patch: { output_config: { effort: 'max' } }, degraded: false });
208
- });
209
- it('xhigh on opus 4.7 is native', () => {
210
- expect(translateAnthropicThinking({ kind: 'effort', effort: 'xhigh' }, 'claude-opus-4-7'))
211
- .toEqual({ patch: { output_config: { effort: 'xhigh' } }, degraded: false });
212
- });
213
- });
214
- //# sourceMappingURL=thinking.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"thinking.test.js","sourceRoot":"","sources":["../../src/cli/thinking.test.ts"],"names":[],"mappings":"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"}
@@ -1,82 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { tmpdir } from 'node:os';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { createInspectCommandTool } from './inspectCommand.js';
6
- import { createBuiltinToolRegistry } from '../toolRegistry.js';
7
- import { AuditLogger } from '../safety/auditLogger.js';
8
- import { defaultPermissionPolicy } from '../safety/toolPermissions.js';
9
- import { cliToolToEnhanced } from '@zelari/core/skills';
10
- /**
11
- * v1.47.2 regression — DeepSeek (strict JSON Schema validation, live report
12
- * 2026-08-17) rejected the whole tool catalog with HTTP 400
13
- * `Invalid schema for function 'inspect_command': schema must be a JSON
14
- * Schema of 'type: "object"', got 'type: null'.` because inspect_command's
15
- * inputSchema is a root discriminated union (Zod 4 → root `anyOf`, no type).
16
- *
17
- * These tests pin the three layers of the fix:
18
- * 1. the tool carries an explicit flattened `jsonSchema` (operation enum)
19
- * 2. every registry profile serializes EVERY tool with `parameters.type
20
- * === 'object'` (jsonSchema preference + zodBridge union flattening)
21
- * 3. the council catalog bridge (cliToolToEnhanced) does not degrade the
22
- * union tool to `properties: {}`
23
- */
24
- const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
25
- function makeRegistry(extra = {}) {
26
- return createBuiltinToolRegistry({
27
- root: repoRoot,
28
- lspProvider: null,
29
- audit: new AuditLogger(path.join(tmpdir(), `zelari-schema-audit-${Date.now()}-${Math.random().toString(36).slice(2)}.log`)),
30
- permissionPolicy: defaultPermissionPolicy({ auto: true }),
31
- ...extra,
32
- });
33
- }
34
- describe('inspect_command provider schema (DeepSeek 400 regression)', () => {
35
- const tool = createInspectCommandTool(repoRoot);
36
- const jsonSchema = tool.jsonSchema;
37
- it('exposes an explicit flattened object schema (no root anyOf/oneOf)', () => {
38
- expect(jsonSchema.type).toBe('object');
39
- expect(jsonSchema.anyOf).toBeUndefined();
40
- expect(jsonSchema.oneOf).toBeUndefined();
41
- });
42
- it('derives the operation enum from the zod union (all 11 operations)', () => {
43
- const ops = jsonSchema.properties?.operation?.enum;
44
- expect(ops).toHaveLength(11);
45
- expect(ops).toContain('git_status');
46
- expect(ops).toContain('typecheck');
47
- expect(ops).toContain('npm_view');
48
- });
49
- it('requires only `operation` at the schema level (per-op requirements stay runtime-enforced)', () => {
50
- expect(jsonSchema.required).toEqual(['operation']);
51
- });
52
- it.each([
53
- ['readOnly', { readOnly: true }],
54
- ['planMode', { planMode: true }],
55
- ['full', {}],
56
- ])('%s registry: EVERY serialized tool has parameters.type === "object"', (_label, extra) => {
57
- const { registry } = makeRegistry(extra);
58
- const serialized = registry.toOpenAITools();
59
- expect(serialized.length).toBeGreaterThan(0);
60
- for (const entry of serialized) {
61
- expect(entry.function.parameters.type).toBe('object');
62
- }
63
- });
64
- it('readOnly/planMode registries serialize inspect_command through the curated schema', () => {
65
- for (const extra of [{ readOnly: true }, { planMode: true }]) {
66
- const { registry } = makeRegistry(extra);
67
- const entry = registry.toOpenAITools().find((t) => t.function.name === 'inspect_command');
68
- expect(entry).toBeDefined();
69
- const params = entry.function.parameters;
70
- expect(params.type).toBe('object');
71
- expect(params.properties?.operation?.enum).toHaveLength(11);
72
- }
73
- });
74
- it('council catalog bridge keeps the union tool intact (no properties:{} degradation)', () => {
75
- const enhanced = cliToolToEnhanced(tool);
76
- const params = enhanced.parameters;
77
- expect(params.type).toBe('object');
78
- expect(params.properties?.operation?.enum).toHaveLength(11);
79
- expect(Object.keys(params.properties ?? {}).length).toBeGreaterThan(1);
80
- });
81
- });
82
- //# sourceMappingURL=inspectCommand.schema.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"inspectCommand.schema.test.js","sourceRoot":"","sources":["../../../src/cli/tools/inspectCommand.schema.test.ts"],"names":[],"mappings":"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"}
@@ -1,311 +0,0 @@
1
- import { mkdtemp, writeFile, readdir, rm, mkdir } from 'node:fs/promises';
2
- import { tmpdir } from 'node:os';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { describe, it, expect, afterAll } from 'vitest';
6
- import { createInspectCommandTool, buildInspectCommand, resolveNodeModuleBin, runSpawn, } from './inspectCommand.js';
7
- import { scanTsbuildinfo, diffFingerprints, cleanupArtifacts, classifyTypecheckRefusal, } from './inspectTypecheckSafety.js';
8
- import { createBuiltinToolRegistry } from '../toolRegistry.js';
9
- import { AuditLogger } from '../safety/auditLogger.js';
10
- import { defaultPermissionPolicy } from '../safety/toolPermissions.js';
11
- /**
12
- * WS3 — inspect_command (piano §3/§7/§9, t3).
13
- *
14
- * S3.4: pure argv-builder table, registry gating, spawn semantics.
15
- * S3.5: typecheck artifact safety fixtures — plain, incremental-with-explicit-
16
- * in-workspace tsBuildInfoFile (the CLI redirect must win), and composite
17
- * (the real packages/core shape). Common assertion: the workspace stays
18
- * byte-for-byte unchanged (zero new *.tsbuildinfo).
19
- */
20
- // This file lives at <repo>/src/cli/tools/… — do NOT use path.resolve() (cwd
21
- // is packages/core under `npm test --workspace=@zelari/core`, which is what
22
- // the publish workflow runs).
23
- const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
24
- const tscPath = resolveNodeModuleBin(repoRoot, path.join('typescript', 'bin', 'tsc'))
25
- ?? path.join(repoRoot, 'node_modules', 'typescript', 'bin', 'tsc');
26
- const fixtures = [];
27
- afterAll(async () => {
28
- await Promise.all(fixtures.map((d) => rm(d, { recursive: true, force: true }).catch(() => { })));
29
- });
30
- async function newFixture() {
31
- const dir = await mkdtemp(path.join(tmpdir(), 'zelari-inspect-'));
32
- fixtures.push(dir);
33
- return dir;
34
- }
35
- function build(op, root = repoRoot) {
36
- return buildInspectCommand(op, { root, cwd: root, tscPath });
37
- }
38
- function buildOk(op, root = repoRoot) {
39
- const r = build(op, root);
40
- if (!r.ok)
41
- throw new Error(`expected ok, got: ${r.reason}`);
42
- return r;
43
- }
44
- describe('resolveNodeModuleBin — hoisted monorepo walk-up', () => {
45
- it('finds root-hoisted typescript from a nested package dir', () => {
46
- const nested = path.join(repoRoot, 'packages', 'core');
47
- const fromNested = resolveNodeModuleBin(nested, path.join('typescript', 'bin', 'tsc'));
48
- const fromRoot = resolveNodeModuleBin(repoRoot, path.join('typescript', 'bin', 'tsc'));
49
- expect(fromNested).toBe(fromRoot);
50
- expect(fromNested).toBeTruthy();
51
- });
52
- it('returns undefined when nothing is found', () => {
53
- expect(resolveNodeModuleBin(tmpdir(), path.join('definitely-not-a-pkg', 'bin', 'x'))).toBeUndefined();
54
- });
55
- });
56
- describe('buildInspectCommand — pure argv builder', () => {
57
- it('git_status plain and --short', () => {
58
- expect(build({ operation: 'git_status' })).toMatchObject({
59
- ok: true,
60
- command: 'git',
61
- argv: ['status'],
62
- inspectionClass: 'git-inspection',
63
- });
64
- expect(buildOk({ operation: 'git_status', short: true }).argv).toEqual(['status', '--short']);
65
- });
66
- it('git_log maps limit/oneline to safe flags only', () => {
67
- const r = build({ operation: 'git_log', limit: 10, oneline: true });
68
- if (!r.ok)
69
- throw new Error('expected ok');
70
- expect(r.command).toBe('git');
71
- expect(r.argv).toEqual(['log', '--oneline', '-n', '10']);
72
- });
73
- it('git_diff forces --no-ext-diff --no-textconv (cannot be disabled by input)', () => {
74
- const r = build({ operation: 'git_diff' });
75
- if (!r.ok)
76
- throw new Error('expected ok');
77
- expect(r.argv.slice(0, 3)).toEqual(['diff', '--no-ext-diff', '--no-textconv']);
78
- const staged = build({ operation: 'git_diff', staged: true, path: 'src/a.ts' });
79
- if (!staged.ok)
80
- throw new Error('expected ok');
81
- expect(staged.argv).toEqual(['diff', '--no-ext-diff', '--no-textconv', '--staged', '--', 'src/a.ts']);
82
- });
83
- it('rejects flag-like free strings (git_diff path, git_show ref, npm_view package)', () => {
84
- expect(build({ operation: 'git_diff', path: '--evil' })).toMatchObject({ ok: false });
85
- expect(build({ operation: 'git_show', ref: '-x' })).toMatchObject({ ok: false });
86
- expect(build({ operation: 'npm_view', package: '--json' })).toMatchObject({ ok: false });
87
- });
88
- it('git_show carries safety flags; branch_current/ls_files are fixed argv', () => {
89
- expect(buildOk({ operation: 'git_show', ref: 'HEAD~2' }).argv).toEqual([
90
- 'show',
91
- '--no-ext-diff',
92
- '--no-textconv',
93
- 'HEAD~2',
94
- ]);
95
- expect(buildOk({ operation: 'git_branch_current' }).argv).toEqual(['branch', '--show-current']);
96
- expect(buildOk({ operation: 'git_ls_files' }).argv).toEqual(['ls-files']);
97
- });
98
- it('node_version and npm_* run via node (no .cmd shim, no shell)', () => {
99
- const nv = build({ operation: 'node_version' });
100
- if (!nv.ok)
101
- throw new Error('expected ok');
102
- expect(nv.command).toBe(process.execPath);
103
- expect(nv.inspectionClass).toBe('env-info');
104
- const ls = build({ operation: 'npm_ls' });
105
- if (!ls.ok)
106
- throw new Error('expected ok');
107
- expect(ls.command).toBe(process.execPath);
108
- expect(ls.argv[0].endsWith('npm-cli.js')).toBe(true);
109
- expect(ls.argv[1]).toBe('ls');
110
- const view = build({ operation: 'npm_view', package: 'typescript' });
111
- if (!view.ok)
112
- throw new Error('expected ok');
113
- expect(view.argv.slice(1)).toEqual(['view', 'typescript']);
114
- });
115
- it('typecheck: --noEmit + temp-dir tsBuildInfoFile redirect + resolved project', () => {
116
- const r = build({ operation: 'typecheck' });
117
- if (!r.ok)
118
- throw new Error('expected ok');
119
- expect(r.inspectionClass).toBe('project-code-execution');
120
- expect(r.argv[0]).toBe(tscPath);
121
- expect(r.argv).toContain('--noEmit');
122
- expect(r.argv).toContain('--incremental');
123
- const i = r.argv.indexOf('--tsBuildInfoFile');
124
- expect(i).toBeGreaterThan(-1);
125
- expect(r.argv[i + 1]).toContain(path.join('zelari-inspect'));
126
- expect(r.argv[i + 1].endsWith('.tsbuildinfo')).toBe(true);
127
- expect(r.argv[r.argv.length - 1].endsWith('tsconfig.json')).toBe(true);
128
- });
129
- it('typecheck: different projects hash to different redirect targets', () => {
130
- const a = build({ operation: 'typecheck', project: 'tsconfig.json' });
131
- const b = build({ operation: 'typecheck', project: 'packages/core/tsconfig.json' });
132
- if (!a.ok || !b.ok)
133
- throw new Error('expected ok');
134
- const ai = a.argv.indexOf('--tsBuildInfoFile');
135
- const bi = b.argv.indexOf('--tsBuildInfoFile');
136
- expect(a.argv[ai + 1]).not.toBe(b.argv[bi + 1]);
137
- });
138
- });
139
- describe('runSpawn — no-shell semantics', () => {
140
- it('kills the process on timeout and reports it', async () => {
141
- const r = await runSpawn(process.execPath, ['-e', 'setTimeout(() => {}, 60000)'], {
142
- cwd: repoRoot,
143
- timeoutMs: 250,
144
- });
145
- expect(r.timedOut).toBe(true);
146
- expect(r.code).not.toBe(0);
147
- });
148
- it('spawn error (missing binary) resolves with spawnError, never rejects', async () => {
149
- const r = await runSpawn('definitely-not-a-real-binary-xyz', [], {
150
- cwd: repoRoot,
151
- timeoutMs: 1000,
152
- });
153
- expect(r.spawnError).toBeTruthy();
154
- });
155
- });
156
- describe('S3.5 artifact-safety guard units', () => {
157
- it('diffFingerprints detects new tsbuildinfo files and git changes', () => {
158
- const pre = { gitStatus: '', tsbuildinfoFiles: ['a.tsbuildinfo'] };
159
- const post = { gitStatus: ' M x.ts', tsbuildinfoFiles: ['a.tsbuildinfo', 'b.tsbuildinfo'] };
160
- const d = diffFingerprints(pre, post);
161
- expect(d.newTsbuildinfo).toEqual(['b.tsbuildinfo']);
162
- expect(d.gitStatusChanged).toBe(true);
163
- expect(diffFingerprints(pre, pre)).toEqual({ newTsbuildinfo: [], gitStatusChanged: false });
164
- });
165
- it('cleanupArtifacts removes what it can and reports failures', async () => {
166
- const dir = await newFixture();
167
- const keep = path.join(dir, 'real.tsbuildinfo');
168
- await writeFile(keep, 'x');
169
- const { cleaned, failed } = await cleanupArtifacts(dir, ['real.tsbuildinfo', 'ghost.tsbuildinfo']);
170
- expect(cleaned).toEqual(['real.tsbuildinfo']);
171
- expect(failed).toEqual(['ghost.tsbuildinfo']);
172
- });
173
- it('classifyTypecheckRefusal: composite refusal is loud, type errors are not', () => {
174
- expect(classifyTypecheckRefusal('error TS6379: Composite projects may not disable incremental emit.')).toMatch(/composite/i);
175
- expect(classifyTypecheckRefusal('index.ts(1,1): error TS2322: Type \'string\' is not assignable')).toBeNull();
176
- });
177
- it('scanTsbuildinfo skips node_modules and finds nested files', async () => {
178
- const dir = await newFixture();
179
- await mkdir(path.join(dir, 'node_modules', 'x'), { recursive: true });
180
- await mkdir(path.join(dir, 'sub'), { recursive: true });
181
- await writeFile(path.join(dir, 'node_modules', 'x', 'junk.tsbuildinfo'), 'x');
182
- await writeFile(path.join(dir, 'sub', 'real.tsbuildinfo'), 'x');
183
- expect(await scanTsbuildinfo(dir)).toEqual(['sub/real.tsbuildinfo']);
184
- });
185
- });
186
- describe('S3.5 typecheck fixtures — the workspace must stay untouched', () => {
187
- async function writeProject(dir, tsconfig) {
188
- await mkdir(path.join(dir, 'src'), { recursive: true });
189
- await writeFile(path.join(dir, 'src', 'main.ts'), 'export const answer: number = 42;\n');
190
- await writeFile(path.join(dir, 'tsconfig.json'), tsconfig);
191
- }
192
- async function runTypecheck(dir) {
193
- const tool = createInspectCommandTool({ root: dir, tscPath });
194
- const res = await tool.execute({ operation: 'typecheck' }, { cwd: dir });
195
- if (!res.ok)
196
- throw new Error(`typecheck failed hard: ${res.error}`);
197
- return res.value;
198
- }
199
- it('(a) plain tsconfig: status ok, zero artifacts, tmp redirect used', async () => {
200
- const dir = await newFixture();
201
- await writeProject(dir, JSON.stringify({ compilerOptions: { strict: true } }));
202
- const v = await runTypecheck(dir);
203
- expect(v['status']).toBe('ok');
204
- expect(v['exitCode']).toBe(0);
205
- expect(v['inspectionClass']).toBe('project-code-execution');
206
- expect(await scanTsbuildinfo(dir)).toEqual([]);
207
- });
208
- it('(b) incremental + tsBuildInfoFile explicitly in the workspace: the CLI redirect WINS', async () => {
209
- const dir = await newFixture();
210
- await writeProject(dir, JSON.stringify({
211
- compilerOptions: { incremental: true, tsBuildInfoFile: './in-workspace.tsbuildinfo' },
212
- }));
213
- const v = await runTypecheck(dir);
214
- expect(v['status']).toBe('ok');
215
- expect(v['exitCode']).toBe(0);
216
- // The in-workspace target must NOT exist; only the tmp redirect was used.
217
- const entries = await readdir(dir);
218
- expect(entries).not.toContain('in-workspace.tsbuildinfo');
219
- expect(await scanTsbuildinfo(dir)).toEqual([]);
220
- });
221
- it('(c) composite: true (the real packages/core shape): workspace unchanged', async () => {
222
- const dir = await newFixture();
223
- await writeProject(dir, JSON.stringify({ compilerOptions: { composite: true, rootDir: 'src', outDir: 'dist' } }));
224
- const v = await runTypecheck(dir);
225
- expect(v['status']).toBe('ok');
226
- expect(v['exitCode']).toBe(0);
227
- expect(await scanTsbuildinfo(dir)).toEqual([]);
228
- const entries = await readdir(dir);
229
- expect(entries).not.toContain('tsconfig.tsbuildinfo');
230
- expect(entries).not.toContain('dist');
231
- });
232
- it('typecheck reports real type errors as a successful observation (exit != 0, status ok)', async () => {
233
- const dir = await newFixture();
234
- await mkdir(path.join(dir, 'src'), { recursive: true });
235
- await writeFile(path.join(dir, 'src', 'bad.ts'), 'export const x: number = "not a number";\n');
236
- await writeFile(path.join(dir, 'tsconfig.json'), JSON.stringify({ compilerOptions: { strict: true } }));
237
- const v = await runTypecheck(dir);
238
- // The RUN succeeded (a scoped observation); the compiler verdict is the exit code.
239
- expect(v['status']).toBe('ok');
240
- expect(v['exitCode']).toBe(2);
241
- expect(String(v['output'])).toContain('TS2322');
242
- expect(await scanTsbuildinfo(dir)).toEqual([]);
243
- });
244
- it('TYPESCRIPT_UNAVAILABLE when tsc is missing (loud, no fake empty)', async () => {
245
- const dir = await newFixture();
246
- await writeProject(dir, JSON.stringify({ compilerOptions: {} }));
247
- const tool = createInspectCommandTool({ root: dir, tscPath: path.join(dir, 'nope', 'tsc') });
248
- const res = await tool.execute({ operation: 'typecheck' }, { cwd: dir });
249
- expect(res.ok).toBe(false);
250
- if (!res.ok)
251
- expect(res.error).toContain('TYPESCRIPT_UNAVAILABLE');
252
- });
253
- });
254
- describe('registry gating (S3.2)', () => {
255
- it('readOnly registry registers inspect_command INSTEAD of bash', () => {
256
- const dir = repoRoot;
257
- const { tools } = createBuiltinToolRegistry({
258
- root: dir,
259
- readOnly: true,
260
- lspProvider: null,
261
- audit: new AuditLogger(path.join(tmpdir(), `zelari-inspect-audit-${Date.now()}.log`)),
262
- permissionPolicy: defaultPermissionPolicy({ auto: true }),
263
- });
264
- const names = tools.map((t) => t.name);
265
- expect(names).toContain('inspect_command');
266
- expect(names).not.toContain('bash');
267
- expect(names).not.toContain('write_file');
268
- });
269
- it('planMode registry gets inspect_command too', () => {
270
- const { tools } = createBuiltinToolRegistry({
271
- root: repoRoot,
272
- planMode: true,
273
- lspProvider: null,
274
- audit: new AuditLogger(path.join(tmpdir(), `zelari-inspect-audit-${Date.now()}.log`)),
275
- permissionPolicy: defaultPermissionPolicy({ auto: true }),
276
- });
277
- expect(tools.map((t) => t.name)).toContain('inspect_command');
278
- });
279
- it('full registry keeps bash and does NOT register inspect_command', () => {
280
- const { tools } = createBuiltinToolRegistry({
281
- root: repoRoot,
282
- lspProvider: null,
283
- audit: new AuditLogger(path.join(tmpdir(), `zelari-inspect-audit-${Date.now()}.log`)),
284
- permissionPolicy: defaultPermissionPolicy({ auto: true }),
285
- });
286
- const names = tools.map((t) => t.name);
287
- expect(names).toContain('bash');
288
- expect(names).not.toContain('inspect_command');
289
- });
290
- it('kill-switch ZELARI_INSPECT_COMMAND=0 removes it', () => {
291
- const prev = process.env.ZELARI_INSPECT_COMMAND;
292
- process.env.ZELARI_INSPECT_COMMAND = '0';
293
- try {
294
- const { tools } = createBuiltinToolRegistry({
295
- root: repoRoot,
296
- readOnly: true,
297
- lspProvider: null,
298
- audit: new AuditLogger(path.join(tmpdir(), `zelari-inspect-audit-${Date.now()}.log`)),
299
- permissionPolicy: defaultPermissionPolicy({ auto: true }),
300
- });
301
- expect(tools.map((t) => t.name)).not.toContain('inspect_command');
302
- }
303
- finally {
304
- if (prev === undefined)
305
- delete process.env.ZELARI_INSPECT_COMMAND;
306
- else
307
- process.env.ZELARI_INSPECT_COMMAND = prev;
308
- }
309
- });
310
- });
311
- //# sourceMappingURL=inspectCommand.test.js.map