chati-dev 4.5.5 → 4.5.7

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 (52) hide show
  1. package/bin/chati.js +35 -1
  2. package/framework/agents/plan/tasks.md +1 -1
  3. package/framework/config.yaml +8 -17
  4. package/framework/constitution.md +30 -20
  5. package/framework/context/governance.md +3 -1
  6. package/framework/context/root.md +1 -1
  7. package/framework/data/entity-registry.yaml +2 -2
  8. package/framework/domains/agents/orchestrator.yaml +1 -1
  9. package/framework/domains/constitution.yaml +1 -1
  10. package/framework/domains/global.yaml +2 -2
  11. package/framework/hooks/model-governance.js +9 -0
  12. package/framework/manifest.json +38 -38
  13. package/framework/manifest.sig +1 -1
  14. package/framework/orchestrator/chati.md +27 -3
  15. package/framework/schemas/session.schema.json +27 -10
  16. package/framework/tasks/brownfield-wu-architecture-map.md +1 -1
  17. package/framework/tasks/brownfield-wu-deep-discovery.md +1 -1
  18. package/framework/tasks/brownfield-wu-dependency-scan.md +1 -1
  19. package/framework/tasks/brownfield-wu-migration-plan.md +1 -1
  20. package/framework/tasks/brownfield-wu-report.md +1 -1
  21. package/framework/tasks/brownfield-wu-risk-assess.md +1 -1
  22. package/framework/tasks/greenfield-wu-report.md +1 -1
  23. package/node_modules/@chati/provider-registry/src/index.js +3 -2
  24. package/node_modules/@chati/tracking-clickup/src/index.js +22 -0
  25. package/package.json +2 -1
  26. package/src/config/gemini-hooks-generator.js +10 -4
  27. package/src/dashboard/layout.js +6 -4
  28. package/src/installer/core.js +20 -0
  29. package/src/installer/templates.js +21 -1
  30. package/src/installer-v2/clickup-preflight.js +32 -0
  31. package/src/installer-v2/model-catalog-envelope.json +15 -13
  32. package/src/installer-v2/model-catalog.json +5 -5
  33. package/src/installer-v2/model-catalog.sig +1 -1
  34. package/src/installer-v2/wizard-installation.js +1 -1
  35. package/src/intelligence/registry-manager.js +9 -3
  36. package/src/orchestrator/cli.js +41 -23
  37. package/src/orchestrator/clickup-projection.js +25 -8
  38. package/src/orchestrator/clickup-runtime.js +89 -1
  39. package/src/orchestrator/planning-runtime.js +1 -2
  40. package/src/orchestrator/rail-runtime.js +1 -2
  41. package/src/orchestrator/runtime-installation-v2.js +10 -1
  42. package/src/orchestrator/session-manager.js +134 -96
  43. package/src/terminal/adapters/claude-adapter.js +9 -2
  44. package/src/terminal/adapters/codex-adapter.js +9 -2
  45. package/src/terminal/adapters/gemini-adapter.js +5 -2
  46. package/src/terminal/adapters/grok-adapter.js +13 -3
  47. package/src/terminal/cli-registry.js +5 -0
  48. package/src/terminal/run-agent.js +5 -0
  49. package/src/terminal/run-parallel.js +7 -0
  50. package/src/terminal/spawner.js +49 -10
  51. package/src/wizard/index.js +8 -0
  52. package/src/wizard/questions.js +7 -3
@@ -11,6 +11,7 @@ import { spawn } from 'child_process';
11
11
  import { validateWriteScopes, buildIsolationEnv } from './isolation.js';
12
12
  import { getProvider } from './cli-registry.js';
13
13
  import { getRateLimiter } from './rate-limiter.js';
14
+ import { recordModelSelection } from '../orchestrator/session-manager.js';
14
15
 
15
16
  // ---------------------------------------------------------------------------
16
17
  // Constants
@@ -108,6 +109,9 @@ export function cleanParentEnv(env) {
108
109
  * @property {string} taskId - Task identifier
109
110
  * @property {string} [model] - LLM model tier name (e.g. opus, pro, codex, claude-sonnet)
110
111
  * @property {string} [provider] - CLI provider name (claude, gemini, codex, grok)
112
+ * @property {string} [providerId] - Vendor provider identifier (anthropic, openai, xai)
113
+ * @property {string} [reasoningConfiguration] - Requested reasoning effort
114
+ * @property {string} [catalogSnapshotRef] - Capability catalog snapshot used for routing
111
115
  * @property {boolean} [strictProvider] - Reject a missing provider rather than using the legacy fallback
112
116
  * @property {string} [prompt] - Full prompt string (from prompt-builder, piped via stdin)
113
117
  * @property {object} [contextPayload] - Context to inject via env var
@@ -159,6 +163,7 @@ export function buildSpawnCommand(config) {
159
163
  CHATI_AGENT: config.agent,
160
164
  CHATI_TASK_ID: config.taskId,
161
165
  CHATI_SPAWNED: 'true',
166
+ ...(config.reasoningConfiguration ? { CHATI_REASONING_CONFIGURATION: config.reasoningConfiguration } : {}),
162
167
  };
163
168
 
164
169
  if (config.contextPayload) {
@@ -174,13 +179,20 @@ export function buildSpawnCommand(config) {
174
179
  const providerName = config.provider || 'claude';
175
180
  let command, args, prompt;
176
181
  let providerFallback = null;
182
+ let actualProvider = providerName;
183
+ let actualModel;
184
+ let actualReasoningConfiguration = null;
177
185
 
178
186
  try {
179
187
  const provider = getProvider(providerName);
180
- const adapterResult = provider.adapter.buildCommand(config, provider);
188
+ const requestedModel = config.model || provider.defaultModel;
189
+ actualModel = provider.modelMap[requestedModel] || requestedModel;
190
+ const adapterResult = provider.adapter.buildCommand({ ...config, model: actualModel }, provider);
181
191
  command = adapterResult.command;
182
192
  args = adapterResult.args;
183
193
  prompt = adapterResult.stdinPrompt;
194
+ actualModel = adapterResult.effectiveModel;
195
+ actualReasoningConfiguration = adapterResult.effectiveReasoningConfiguration;
184
196
  } catch (err) {
185
197
  if (config.strictProvider) {
186
198
  const failure = new Error(`Selected provider "${providerName}" is unavailable: ${err.message}`);
@@ -194,18 +206,26 @@ export function buildSpawnCommand(config) {
194
206
  reason: err.message,
195
207
  timestamp: new Date().toISOString(),
196
208
  };
209
+ actualProvider = 'claude';
197
210
  console.error(`[chati] Provider "${providerName}" resolution failed: ${err.message}. Falling back to claude.`);
198
211
  command = 'claude';
199
212
  args = ['--print', '--dangerously-skip-permissions'];
200
- if (config.model) {
201
- const claudeProvider = getProvider('claude');
202
- const resolvedModel = claudeProvider.modelMap[config.model] || config.model;
203
- args.push('--model', resolvedModel);
213
+ const claudeProvider = getProvider('claude');
214
+ const requestedClaudeModel = config.model || 'sonnet';
215
+ actualModel = claudeProvider.modelMap[requestedClaudeModel]
216
+ || (requestedClaudeModel.startsWith('claude-') ? requestedClaudeModel : claudeProvider.modelMap.sonnet);
217
+ args.push('--model', actualModel);
218
+ if (config.reasoningConfiguration) {
219
+ args.push('--effort', config.reasoningConfiguration);
220
+ actualReasoningConfiguration = config.reasoningConfiguration;
204
221
  }
205
222
  prompt = config.prompt || null;
206
223
  }
207
224
 
208
- return { command, args, env, terminalId, prompt, providerFallback };
225
+ return {
226
+ command, args, env, terminalId, prompt, providerFallback,
227
+ actualProvider, actualModel, actualReasoningConfiguration,
228
+ };
209
229
  }
210
230
 
211
231
  /**
@@ -215,11 +235,29 @@ export function buildSpawnCommand(config) {
215
235
  * @returns {TerminalHandle}
216
236
  */
217
237
  export function spawnTerminal(config) {
218
- const { command, args, env, terminalId, prompt, providerFallback } = buildSpawnCommand(config);
238
+ const {
239
+ command, args, env, terminalId, prompt, providerFallback,
240
+ actualProvider, actualModel, actualReasoningConfiguration,
241
+ } = buildSpawnCommand(config);
219
242
 
220
243
  const cwd = config.workingDir || process.cwd();
221
244
  const timeout = config.timeout || 300_000; // default 5 minutes
222
245
 
246
+ const selectionRecord = recordModelSelection(cwd, {
247
+ agent: config.agent,
248
+ taskId: config.taskId,
249
+ provider: actualProvider,
250
+ providerId: providerFallback ? null : (config.providerId || null),
251
+ model: actualModel,
252
+ reasoningConfiguration: actualReasoningConfiguration,
253
+ catalogSnapshotRef: providerFallback ? null : (config.catalogSnapshotRef || null),
254
+ });
255
+ if (!selectionRecord.saved) {
256
+ const auditError = new Error(selectionRecord.error || 'Failed to persist model selection audit');
257
+ auditError.code = 'MODEL_SELECTION_AUDIT_FAILED';
258
+ throw auditError;
259
+ }
260
+
223
261
  const child = spawn(command, args, {
224
262
  cwd,
225
263
  env: { ...cleanParentEnv(process.env), ...env },
@@ -238,8 +276,9 @@ export function spawnTerminal(config) {
238
276
  process: child,
239
277
  agent: config.agent,
240
278
  taskId: config.taskId,
241
- model: config.model || 'unknown',
242
- provider: config.provider || 'claude',
279
+ model: actualModel || config.model || 'provider-default',
280
+ provider: actualProvider,
281
+ reasoningConfiguration: config.reasoningConfiguration || null,
243
282
  providerFallback,
244
283
  startedAt: new Date().toISOString(),
245
284
  status: 'running',
@@ -250,7 +289,7 @@ export function spawnTerminal(config) {
250
289
  };
251
290
 
252
291
  // Record spawn in rate limiter for throttling
253
- const providerForRate = config.provider || 'claude';
292
+ const providerForRate = actualProvider;
254
293
  getRateLimiter(providerForRate).recordSpawn();
255
294
 
256
295
  // Capture output (capped at ~10MB to prevent unbounded memory growth)
@@ -9,6 +9,7 @@ import { installFramework } from '../installer/core.js';
9
9
  import { INSTALLATION_ARTIFACT_PATH, dryRunV2, installV2, reconfigureV2 } from '../installer-v2/index.js';
10
10
  import { buildWizardV2InstallationInput } from '../installer-v2/wizard-installation.js';
11
11
  import { resolveCapabilityCatalog, verifySignedCapabilityCatalog } from '../installer-v2/catalog-client.js';
12
+ import { checkClickUpMcp } from '../installer-v2/clickup-preflight.js';
12
13
  import { validateInstallation } from '../installer/validator.js';
13
14
  import { initCollector, track as telemetryTrack, flush as telemetryFlush } from '../telemetry/collector.js';
14
15
  import { sendEvents } from '../telemetry/sender.js';
@@ -72,6 +73,7 @@ export async function runWizard(targetDir, options = {}) {
72
73
  let catalogResolution;
73
74
  let modelSelections;
74
75
  let installationMode;
76
+ let clickupPreflight = null;
75
77
  // Editor rule files are a legacy programmatic integration. The interactive
76
78
  // installer configures provider CLIs only, which are the actual runtimes.
77
79
  const selectedEditors = options.editors || [];
@@ -152,6 +154,11 @@ export async function runWizard(targetDir, options = {}) {
152
154
  p.log.error(error.message);
153
155
  continue;
154
156
  }
157
+ clickupPreflight = options.clickupPreflight || checkClickUpMcp(selectedProviders);
158
+ if (!clickupPreflight.passed) {
159
+ p.log.error('Internal mode requires an authorized ClickUp MCP connection in at least one selected CLI. Configure ClickUp in Claude, Codex or Grok, then retry.');
160
+ continue;
161
+ }
155
162
  }
156
163
  stage = 'confirm';
157
164
  continue;
@@ -173,6 +180,7 @@ export async function runWizard(targetDir, options = {}) {
173
180
  selectedIDEs,
174
181
  selectedMCPs,
175
182
  installationMode,
183
+ clickupPreflight,
176
184
  modelSelections,
177
185
  targetDir,
178
186
  version: VERSION,
@@ -120,8 +120,8 @@ export async function stepProviderSelection({ allowBack = false } = {}) {
120
120
  }
121
121
 
122
122
  /**
123
- * Selects the operational policy profile. Focus AI internal projects require
124
- * ClickUp tracking; standard projects do not gain that external dependency.
123
+ * Selects the operational policy profile. Authorized internal projects require
124
+ * ClickUp tracking; open projects do not gain that external dependency.
125
125
  */
126
126
  export async function stepInstallationMode({ allowBack = false } = {}) {
127
127
  const mode = await p.select({
@@ -257,7 +257,7 @@ export async function stepModelSelection(providers, capabilityCatalog) {
257
257
  * Step 4: Confirmation
258
258
  */
259
259
  export async function stepConfirmation(config, { allowBack = false } = {}) {
260
- const { projectName, projectType, language, selectedMCPs, selectedIDEs, allProviders, installationMode } = config;
260
+ const { projectName, projectType, language, selectedMCPs, selectedIDEs, allProviders, installationMode, clickupPreflight } = config;
261
261
 
262
262
  const langName = SUPPORTED_LANGUAGES.find(l => l.value === language)?.label || language;
263
263
 
@@ -288,6 +288,10 @@ export async function stepConfirmation(config, { allowBack = false } = {}) {
288
288
  summaryData[t('installer.ides_label')] = editorNames;
289
289
  }
290
290
 
291
+ if (installationMode === 'internal') {
292
+ summaryData.ClickUp = `Connected via ${(clickupPreflight?.connected_providers || []).join(', ')}`;
293
+ }
294
+
291
295
  summaryData[t('installer.mcps_label')] = mcpNames;
292
296
 
293
297
  console.log();