@llm-dev-ops/agentics-cli 1.4.14 → 1.4.16

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 (153) hide show
  1. package/README.md +0 -1
  2. package/dist/adapters/base-adapter.d.ts +109 -1
  3. package/dist/adapters/base-adapter.d.ts.map +1 -1
  4. package/dist/adapters/base-adapter.js +368 -18
  5. package/dist/adapters/base-adapter.js.map +1 -1
  6. package/dist/adapters/index.d.ts +1 -1
  7. package/dist/adapters/index.d.ts.map +1 -1
  8. package/dist/adapters/index.js +3 -1
  9. package/dist/adapters/index.js.map +1 -1
  10. package/dist/agents/cli-ux-agent.d.ts +9 -3
  11. package/dist/agents/cli-ux-agent.d.ts.map +1 -1
  12. package/dist/agents/cli-ux-agent.js +13 -67
  13. package/dist/agents/cli-ux-agent.js.map +1 -1
  14. package/dist/agents/decision-event.d.ts +1 -1
  15. package/dist/agents/decision-event.d.ts.map +1 -1
  16. package/dist/agents/decision-event.js +12 -7
  17. package/dist/agents/decision-event.js.map +1 -1
  18. package/dist/auth/index.d.ts +1 -3
  19. package/dist/auth/index.d.ts.map +1 -1
  20. package/dist/auth/index.js +1 -3
  21. package/dist/auth/index.js.map +1 -1
  22. package/dist/auth/internal-allowlist.d.ts +19 -17
  23. package/dist/auth/internal-allowlist.d.ts.map +1 -1
  24. package/dist/auth/internal-allowlist.js +20 -90
  25. package/dist/auth/internal-allowlist.js.map +1 -1
  26. package/dist/auth/role-permissions.d.ts +23 -6
  27. package/dist/auth/role-permissions.d.ts.map +1 -1
  28. package/dist/auth/role-permissions.js +25 -37
  29. package/dist/auth/role-permissions.js.map +1 -1
  30. package/dist/cli/index.js +430 -27
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/commands/agents.d.ts +77 -0
  33. package/dist/commands/agents.d.ts.map +1 -0
  34. package/dist/commands/agents.js +378 -0
  35. package/dist/commands/agents.js.map +1 -0
  36. package/dist/commands/demo.d.ts +30 -0
  37. package/dist/commands/demo.d.ts.map +1 -0
  38. package/dist/commands/demo.js +393 -0
  39. package/dist/commands/demo.js.map +1 -0
  40. package/dist/commands/diligence.d.ts.map +1 -1
  41. package/dist/commands/diligence.js +10 -15
  42. package/dist/commands/diligence.js.map +1 -1
  43. package/dist/commands/export.d.ts.map +1 -1
  44. package/dist/commands/export.js +5 -7
  45. package/dist/commands/export.js.map +1 -1
  46. package/dist/commands/index.d.ts +2 -0
  47. package/dist/commands/index.d.ts.map +1 -1
  48. package/dist/commands/index.js +1 -0
  49. package/dist/commands/index.js.map +1 -1
  50. package/dist/commands/inspect.d.ts +17 -4
  51. package/dist/commands/inspect.d.ts.map +1 -1
  52. package/dist/commands/inspect.js +189 -77
  53. package/dist/commands/inspect.js.map +1 -1
  54. package/dist/commands/quantify.d.ts.map +1 -1
  55. package/dist/commands/quantify.js +12 -0
  56. package/dist/commands/quantify.js.map +1 -1
  57. package/dist/commands/readiness.d.ts +47 -0
  58. package/dist/commands/readiness.d.ts.map +1 -0
  59. package/dist/commands/readiness.js +270 -0
  60. package/dist/commands/readiness.js.map +1 -0
  61. package/dist/commands/simulate.d.ts +6 -0
  62. package/dist/commands/simulate.d.ts.map +1 -1
  63. package/dist/commands/simulate.js +167 -123
  64. package/dist/commands/simulate.js.map +1 -1
  65. package/dist/commands/whoami.d.ts +1 -6
  66. package/dist/commands/whoami.d.ts.map +1 -1
  67. package/dist/commands/whoami.js +4 -28
  68. package/dist/commands/whoami.js.map +1 -1
  69. package/dist/config/endpoints.d.ts.map +1 -1
  70. package/dist/config/endpoints.js +150 -2
  71. package/dist/config/endpoints.js.map +1 -1
  72. package/dist/contracts/adr-command-semantics.d.ts.map +1 -1
  73. package/dist/contracts/adr-command-semantics.js +17 -3
  74. package/dist/contracts/adr-command-semantics.js.map +1 -1
  75. package/dist/contracts/canonical.d.ts +207 -0
  76. package/dist/contracts/canonical.d.ts.map +1 -0
  77. package/dist/contracts/canonical.js +191 -0
  78. package/dist/contracts/canonical.js.map +1 -0
  79. package/dist/contracts/index.d.ts +3 -1
  80. package/dist/contracts/index.d.ts.map +1 -1
  81. package/dist/contracts/index.js +2 -0
  82. package/dist/contracts/index.js.map +1 -1
  83. package/dist/contracts/schemas/index.d.ts +709 -5
  84. package/dist/contracts/schemas/index.d.ts.map +1 -1
  85. package/dist/contracts/schemas/index.js +415 -0
  86. package/dist/contracts/schemas/index.js.map +1 -1
  87. package/dist/contracts/validator.d.ts +3 -3
  88. package/dist/contracts/validator.d.ts.map +1 -1
  89. package/dist/contracts/validator.js +48 -5
  90. package/dist/contracts/validator.js.map +1 -1
  91. package/dist/gates/argument-guard.js +1 -1
  92. package/dist/gates/argument-guard.js.map +1 -1
  93. package/dist/gates/auth-session-gate.d.ts +2 -2
  94. package/dist/gates/auth-session-gate.d.ts.map +1 -1
  95. package/dist/gates/auth-session-gate.js +2 -26
  96. package/dist/gates/auth-session-gate.js.map +1 -1
  97. package/dist/gates/execution-gate.d.ts +23 -54
  98. package/dist/gates/execution-gate.d.ts.map +1 -1
  99. package/dist/gates/execution-gate.js +66 -166
  100. package/dist/gates/execution-gate.js.map +1 -1
  101. package/dist/gates/index.d.ts +6 -0
  102. package/dist/gates/index.d.ts.map +1 -1
  103. package/dist/gates/index.js +8 -0
  104. package/dist/gates/index.js.map +1 -1
  105. package/dist/gates/meta-simulation-detector.d.ts +48 -0
  106. package/dist/gates/meta-simulation-detector.d.ts.map +1 -0
  107. package/dist/gates/meta-simulation-detector.js +45 -0
  108. package/dist/gates/meta-simulation-detector.js.map +1 -0
  109. package/dist/gates/readiness-gate.d.ts +108 -0
  110. package/dist/gates/readiness-gate.d.ts.map +1 -0
  111. package/dist/gates/readiness-gate.js +194 -0
  112. package/dist/gates/readiness-gate.js.map +1 -0
  113. package/dist/gates/ruvector-acceptance-gate.d.ts +78 -0
  114. package/dist/gates/ruvector-acceptance-gate.d.ts.map +1 -0
  115. package/dist/gates/ruvector-acceptance-gate.js +191 -0
  116. package/dist/gates/ruvector-acceptance-gate.js.map +1 -0
  117. package/dist/modules/artifact-handoff.d.ts.map +1 -1
  118. package/dist/modules/artifact-handoff.js +26 -0
  119. package/dist/modules/artifact-handoff.js.map +1 -1
  120. package/dist/modules/command-parser.d.ts +1 -1
  121. package/dist/modules/command-parser.d.ts.map +1 -1
  122. package/dist/modules/command-parser.js +5 -1
  123. package/dist/modules/command-parser.js.map +1 -1
  124. package/dist/modules/output-renderer.d.ts +13 -1
  125. package/dist/modules/output-renderer.d.ts.map +1 -1
  126. package/dist/modules/output-renderer.js +68 -0
  127. package/dist/modules/output-renderer.js.map +1 -1
  128. package/dist/runtime/claude-code-runner.d.ts.map +1 -1
  129. package/dist/runtime/claude-code-runner.js +165 -0
  130. package/dist/runtime/claude-code-runner.js.map +1 -1
  131. package/dist/server/index.d.ts.map +1 -1
  132. package/dist/server/index.js +59 -1
  133. package/dist/server/index.js.map +1 -1
  134. package/dist/server/routes/agents.d.ts +36 -0
  135. package/dist/server/routes/agents.d.ts.map +1 -0
  136. package/dist/server/routes/agents.js +263 -0
  137. package/dist/server/routes/agents.js.map +1 -0
  138. package/dist/server/routes/index.d.ts +1 -0
  139. package/dist/server/routes/index.d.ts.map +1 -1
  140. package/dist/server/routes/index.js +2 -0
  141. package/dist/server/routes/index.js.map +1 -1
  142. package/dist/synthesis/dynamic-router.d.ts +80 -0
  143. package/dist/synthesis/dynamic-router.d.ts.map +1 -0
  144. package/dist/synthesis/dynamic-router.js +63 -0
  145. package/dist/synthesis/dynamic-router.js.map +1 -0
  146. package/dist/synthesis/prompts/index.d.ts.map +1 -1
  147. package/dist/synthesis/prompts/index.js +100 -23
  148. package/dist/synthesis/prompts/index.js.map +1 -1
  149. package/dist/types/index.d.ts +86 -0
  150. package/dist/types/index.d.ts.map +1 -1
  151. package/dist/types/index.js +8 -0
  152. package/dist/types/index.js.map +1 -1
  153. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -17,7 +17,7 @@ import * as path from 'node:path';
17
17
  import { fileURLToPath } from 'node:url';
18
18
  import { createCommandParser, SUPPORTED_COMMANDS } from '../modules/command-parser.js';
19
19
  import { createOutputRenderer } from '../modules/output-renderer.js';
20
- import { CLIError, errorHandler, toError } from '../errors/index.js';
20
+ import { CLIError, ServiceError, errorHandler, toError } from '../errors/index.js';
21
21
  import { LocalhostInProductionError } from '../config/endpoints.js';
22
22
  import { EXIT_CODES, parseFlexibleInput, isNaturalLanguage } from '../types/index.js';
23
23
  // ============================================================================
@@ -72,6 +72,24 @@ import { executeDiligenceCommand } from '../commands/diligence.js';
72
72
  import { executeUsageCommand, executeUsageHistoryCommand, executeUsageLimitsCommand, executeUsageResetCommand, formatUsageForDisplay, formatHistoryForDisplay, formatLimitsForDisplay, } from '../commands/usage.js';
73
73
  import { executePolicyListCommand, executePolicyInspectCommand, executePolicyCreateCommand, executePolicyEditCommand, executePolicyDeleteCommand, executePolicyEnableCommand, executePolicyDisableCommand, executePolicyDryRunCommand, executePolicyScopeCommand, formatPolicyForDisplay, formatPoliciesListForDisplay, formatDryRunForDisplay, formatScopeForDisplay, } from '../commands/policy.js';
74
74
  import { executeErpListCommand, executeErpInspectCommand, executeErpSurfaceCommand, executeErpMapCommand, executeErpExportCommand, formatErpListForDisplay, formatErpInspectForDisplay, formatErpSurfaceForDisplay, formatErpMapForDisplay, formatErpExportForDisplay, } from '../commands/erp.js';
75
+ import { executeReadinessShowCommand, executeReadinessExplainCommand, formatReadinessForDisplay, formatReadinessExplainForDisplay, } from '../commands/readiness.js';
76
+ import { executeDemoStartCommand, } from '../commands/demo.js';
77
+ import { executeAgentsListCommand, executeAgentsHealthCommand, executeAgentsInvokeCommand, executeNaturalLanguageRoute, formatAgentsListForDisplay, formatAgentResultForDisplay, formatNaturalLanguageRouteForDisplay, AGENT_DOMAINS, } from '../commands/agents.js';
78
+ // ============================================================================
79
+ // Utility Helpers
80
+ // ============================================================================
81
+ /**
82
+ * Slugify a description string into a short kebab-case policy name.
83
+ * Takes the first ~40 characters, lowercases, replaces non-alphanum with hyphens,
84
+ * collapses runs, and trims leading/trailing hyphens.
85
+ */
86
+ function slugifyPolicyName(description) {
87
+ return description
88
+ .slice(0, 40)
89
+ .toLowerCase()
90
+ .replace(/[^a-z0-9]+/g, '-')
91
+ .replace(/^-+|-+$/g, '');
92
+ }
75
93
  // ============================================================================
76
94
  // CONTROL PLANE HARDENING GATES
77
95
  // ============================================================================
@@ -95,12 +113,16 @@ import { enforceOutputFormatGate, requiresStructuredOutput, getDefaultFormat } f
95
113
  import { enforceArgumentGuard, requiresArgumentValidation } from '../gates/argument-guard.js';
96
114
  // Lineage Gate - Enforces simulation traceability per ADR-004
97
115
  import { enforceLineageGate, requiresLineageValidation } from '../gates/lineage-gate.js';
116
+ // Readiness Gate - Enforces execution safety when execution-gated
117
+ import { enforceReadinessGate, requiresReadinessValidation } from '../gates/readiness-gate.js';
98
118
  // Help Renderer - Schema-driven help from COMMAND_REGISTRY (ADR-002 Decision 1)
99
119
  import { renderHelp } from '../modules/help-renderer.js';
100
120
  // Synthesis Router - ADR-006/007/008 Claude Code integration
101
121
  import { routeSynthesis, isDecisionGrade } from '../synthesis/router.js';
102
122
  import { createArtifactWriter } from '../synthesis/artifact-writer.js';
103
123
  import { lookupCommand } from '../contracts/adr-command-semantics.js';
124
+ // Dynamic routing — resolves downstream repos/agents based on request content
125
+ // dynamic-router import removed — routing is now platform-side
104
126
  // ============================================================================
105
127
  // Synthesis Artifact Persistence (ADR-008)
106
128
  // ============================================================================
@@ -202,12 +224,12 @@ async function main() {
202
224
  // execution is explicitly enabled. Only identity/help commands are allowed
203
225
  // when execution is disabled. This gate does NOT check entitlements, usage,
204
226
  // or billing - it is a binary on/off switch.
205
- enforceExecutionGate(parsed.command);
227
+ await enforceExecutionGate(parsed.command);
206
228
  // ============================================================================
207
229
  // GATE 2: AUTHENTICATION SESSION GATE - Requires valid credentials
208
230
  // ============================================================================
209
231
  // CLI requires authenticated session for ALL operational commands.
210
- // Checks platform credentials first, then falls back to GCP credentials.
232
+ // Checks platform credentials (API key, internal key, or stored login).
211
233
  // CRITICAL: No anonymous operations are permitted.
212
234
  if (requiresAuthentication(parsed.command)) {
213
235
  await enforceAuthSessionGate();
@@ -254,6 +276,17 @@ async function main() {
254
276
  if (requiresLineageValidation(parsed.command, parsed.subcommand)) {
255
277
  enforceLineageGate(parsed);
256
278
  }
279
+ // ============================================================================
280
+ // GATE 7: READINESS GATE - Enforces execution safety
281
+ // ============================================================================
282
+ // Write-path commands (deploy run, deploy rollback) are blocked when the
283
+ // platform readiness state is not EXECUTION_READY. This gate reads from
284
+ // ~/.agentics/exports/decision-readiness/readiness-state.json and prevents
285
+ // production writes until all prerequisites are met.
286
+ // CRITICAL: No ERP writes or production deployments without readiness.
287
+ if (requiresReadinessValidation(parsed.command, parsed.subcommand)) {
288
+ enforceReadinessGate(parsed);
289
+ }
257
290
  // Dispatch to command handlers
258
291
  try {
259
292
  let result = null;
@@ -462,16 +495,28 @@ async function main() {
462
495
  },
463
496
  });
464
497
  if (synthesisResult) {
465
- // Create the simulation using the synthesis output as metadata
498
+ // Extract actual synthesis content (scenario, steps, etc.)
499
+ const synthData = synthesisResult.data;
500
+ const scenario = synthData?.['scenario'];
501
+ const synthDescription = (scenario?.['description'] ??
502
+ synthData?.['description'] ??
503
+ parsed.options['description'] ??
504
+ simName);
505
+ const synthName = (scenario?.['name'] ??
506
+ synthData?.['name'] ??
507
+ simName);
508
+ // Create the simulation record with synthesis-derived content
466
509
  const simCreateResult = await executeSimulateCreateCommand({
467
- name: simName,
468
- description: parsed.options['description'],
510
+ name: synthName || simName,
511
+ description: synthDescription,
469
512
  plan_id: parsed.options['plan-id'],
470
513
  iterations: parsed.options['iterations'] ? parseInt(parsed.options['iterations'], 10) : undefined,
471
514
  metadata: {
472
515
  ...(parsed.options['metadata'] ? JSON.parse(parsed.options['metadata']) : {}),
473
516
  synthesis_run_id: synthesisResult.runId,
474
517
  synthesis_model: synthesisResult.model,
518
+ // Store the full synthesis content in metadata
519
+ synthesis_data: synthData,
475
520
  },
476
521
  }, options);
477
522
  // Persist synthesis artifacts (ADR-008)
@@ -488,9 +533,12 @@ async function main() {
488
533
  orgId: 'cli-org',
489
534
  traceId: options.trace_id ?? '',
490
535
  });
536
+ // Routing profile is now platform-side — not resolved locally.
491
537
  if (options.format === 'json') {
538
+ // Output the FULL synthesis content — not just the CRUD record
492
539
  console.log(JSON.stringify({
493
540
  simulation: simCreateResult.simulation,
541
+ data: synthData,
494
542
  synthesis: {
495
543
  run_id: synthesisResult.runId,
496
544
  model: synthesisResult.model,
@@ -820,7 +868,7 @@ async function main() {
820
868
  process.exit(EXIT_CODES.SUCCESS);
821
869
  }
822
870
  // Default quantify behavior (execute via orchestration)
823
- const quantifyInput = parsed.positionalArgs[0] ?? '';
871
+ const quantifyInput = parsed.positionalArgs[0] ?? parsed.subcommand ?? '';
824
872
  const quantifyFlexibleInput = parseFlexibleInput(quantifyInput);
825
873
  result = await executeQuantifyCommand({
826
874
  simRef: isNaturalLanguage(quantifyFlexibleInput)
@@ -934,7 +982,7 @@ async function main() {
934
982
  process.exit(EXIT_CODES.SUCCESS);
935
983
  }
936
984
  // Default deploy behavior (execute via orchestration)
937
- const deployInput = parsed.positionalArgs[0] ?? '';
985
+ const deployInput = parsed.positionalArgs[0] ?? parsed.subcommand ?? '';
938
986
  const deployFlexibleInput = parseFlexibleInput(deployInput);
939
987
  result = await executeDeployCommand({
940
988
  simRef: isNaturalLanguage(deployFlexibleInput)
@@ -1023,7 +1071,9 @@ async function main() {
1023
1071
  process.exit(EXIT_CODES.SUCCESS);
1024
1072
  }
1025
1073
  // Default export behavior (execute via orchestration)
1026
- const exportInput = parsed.positionalArgs[0] ?? '';
1074
+ // Note: parser consumes first arg as subcommand for commands with subcommands,
1075
+ // so use subcommand as input if it wasn't a known subcommand and no positional args
1076
+ const exportInput = parsed.positionalArgs[0] ?? parsed.subcommand ?? '';
1027
1077
  const exportFlexibleInput = parseFlexibleInput(exportInput);
1028
1078
  result = await executeExportCommand({
1029
1079
  intentRef: isNaturalLanguage(exportFlexibleInput)
@@ -1158,6 +1208,78 @@ async function main() {
1158
1208
  console.error('Supported subcommands: list, inspect, surface, map, export');
1159
1209
  process.exit(EXIT_CODES.USAGE_ERROR);
1160
1210
  }
1211
+ case 'readiness': {
1212
+ // Handle readiness subcommands: show, explain
1213
+ if (parsed.subcommand === 'show' || !parsed.subcommand) {
1214
+ const scenario = parsed.positionalArgs[0] ?? '';
1215
+ const readinessResult = await executeReadinessShowCommand({ scenario }, options);
1216
+ if (options.format === 'json') {
1217
+ console.log(JSON.stringify({
1218
+ state: readinessResult.state,
1219
+ found: readinessResult.found,
1220
+ scenario: readinessResult.scenario,
1221
+ timing: readinessResult.timing,
1222
+ }, null, parsed.flags['pretty'] ? 2 : 0));
1223
+ }
1224
+ else {
1225
+ console.log(formatReadinessForDisplay(readinessResult));
1226
+ }
1227
+ if (options.verbose) {
1228
+ console.error(`Query completed in ${readinessResult.timing}ms`);
1229
+ }
1230
+ process.exit(EXIT_CODES.SUCCESS);
1231
+ }
1232
+ if (parsed.subcommand === 'explain') {
1233
+ const scenario = parsed.positionalArgs[0] ?? '';
1234
+ const explainResult = await executeReadinessExplainCommand({ scenario }, options);
1235
+ // explain is always human-readable — no JSON mode
1236
+ console.log(formatReadinessExplainForDisplay(explainResult));
1237
+ if (options.verbose) {
1238
+ console.error(`Query completed in ${explainResult.timing}ms`);
1239
+ }
1240
+ process.exit(EXIT_CODES.SUCCESS);
1241
+ }
1242
+ // Unknown readiness subcommand
1243
+ console.error(`Unknown readiness subcommand: ${parsed.subcommand}`);
1244
+ console.error('Supported subcommands: show, explain');
1245
+ process.exit(EXIT_CODES.USAGE_ERROR);
1246
+ }
1247
+ case 'demo': {
1248
+ // Demo mode: read-only, gate-exempt, human-readable only
1249
+ const executionKeywords = ['execute', 'run', 'deploy', 'rollback', 'unlock', 'force', 'override'];
1250
+ if (parsed.subcommand && executionKeywords.includes(parsed.subcommand.toLowerCase())) {
1251
+ console.error(`Demo mode does not support "${parsed.subcommand}".`);
1252
+ console.error('');
1253
+ console.error('Demo mode is a read-only walkthrough of the platform. It cannot:');
1254
+ console.error(' - Execute deployments');
1255
+ console.error(' - Unlock the execution gate');
1256
+ console.error(' - Write to any system');
1257
+ console.error(' - Modify the readiness state');
1258
+ console.error('');
1259
+ console.error('Usage: agentics demo start [scenario]');
1260
+ process.exit(EXIT_CODES.USAGE_ERROR);
1261
+ }
1262
+ if (parsed.subcommand !== 'start' && parsed.subcommand) {
1263
+ console.error(`Unknown demo subcommand: ${parsed.subcommand}`);
1264
+ console.error('Usage: agentics demo start [scenario]');
1265
+ console.error('');
1266
+ console.error('Demo mode is read-only. The only valid subcommand is "start".');
1267
+ process.exit(EXIT_CODES.USAGE_ERROR);
1268
+ }
1269
+ const demoScenario = parsed.positionalArgs[0] ?? '';
1270
+ const demoResult = await executeDemoStartCommand({
1271
+ scenario: demoScenario,
1272
+ extraArgs: parsed.subcommand ? parsed.positionalArgs : [],
1273
+ });
1274
+ // Demo is always human-readable — never JSON
1275
+ console.log(demoResult.output);
1276
+ if (options.verbose) {
1277
+ console.error(`Demo completed in ${demoResult.timing}ms`);
1278
+ }
1279
+ console.log('');
1280
+ console.log('This demo is read-only. No systems were contacted. No data was written.');
1281
+ process.exit(EXIT_CODES.SUCCESS);
1282
+ }
1161
1283
  case 'diligence': {
1162
1284
  const diligenceInput = parsed.positionalArgs[0] ?? '';
1163
1285
  const diligenceFlexibleInput = parseFlexibleInput(diligenceInput);
@@ -1298,10 +1420,16 @@ async function main() {
1298
1420
  process.exit(EXIT_CODES.SUCCESS);
1299
1421
  }
1300
1422
  if (parsed.subcommand === 'create') {
1301
- const policyName = parsed.options['name'] ?? parsed.positionalArgs[0] ?? '';
1423
+ const positionalDesc = parsed.positionalArgs[0];
1424
+ const explicitName = parsed.options['name'];
1425
+ const explicitDesc = parsed.options['description'];
1426
+ // Derive description: --description flag > positional arg > fallback to name
1427
+ const description = explicitDesc ?? positionalDesc ?? explicitName ?? '';
1428
+ // Derive name: --name flag > slugified description
1429
+ const policyName = explicitName ?? slugifyPolicyName(description);
1302
1430
  const policyCreateResult = await executePolicyCreateCommand({
1303
1431
  name: policyName,
1304
- description: parsed.options['description'],
1432
+ description,
1305
1433
  type: parsed.options['type'],
1306
1434
  rules: parsed.options['rules'] ? JSON.parse(parsed.options['rules']) : undefined,
1307
1435
  metadata: parsed.options['metadata'] ? JSON.parse(parsed.options['metadata']) : undefined,
@@ -1449,10 +1577,166 @@ async function main() {
1449
1577
  console.error('Supported subcommands: list, inspect, create, edit, delete, enable, disable, dry-run, scope');
1450
1578
  process.exit(EXIT_CODES.USAGE_ERROR);
1451
1579
  }
1452
- default:
1580
+ case 'agents': {
1581
+ // Subcommand: list
1582
+ if (parsed.subcommand === 'list' || (!parsed.subcommand && parsed.positionalArgs.length === 0)) {
1583
+ const listResult = await executeAgentsListCommand(options);
1584
+ if (options.format === 'json') {
1585
+ console.log(JSON.stringify(listResult, null, parsed.flags['pretty'] ? 2 : 0));
1586
+ }
1587
+ else {
1588
+ console.log(formatAgentsListForDisplay(listResult));
1589
+ }
1590
+ if (options.verbose) {
1591
+ console.error(`Listed ${listResult.totalDomains} domains (${listResult.totalAgents} agents) in ${listResult.timing}ms`);
1592
+ }
1593
+ process.exit(EXIT_CODES.SUCCESS);
1594
+ }
1595
+ // Subcommand: health <domain>
1596
+ if (parsed.subcommand === 'health') {
1597
+ const domain = parsed.positionalArgs[0];
1598
+ if (!domain) {
1599
+ console.error('Usage: agentics agents health <domain>');
1600
+ console.error(`Valid domains: ${Object.keys(AGENT_DOMAINS).join(', ')}`);
1601
+ process.exit(EXIT_CODES.USAGE_ERROR);
1602
+ }
1603
+ const healthResult = await executeAgentsHealthCommand(domain, options);
1604
+ if (options.format === 'json') {
1605
+ console.log(JSON.stringify(healthResult, null, parsed.flags['pretty'] ? 2 : 0));
1606
+ }
1607
+ else {
1608
+ const status = healthResult.healthy ? 'HEALTHY' : 'UNHEALTHY';
1609
+ console.log(`${domain}: ${status} (${healthResult.timing}ms)`);
1610
+ console.log(JSON.stringify(healthResult.response, null, 2));
1611
+ }
1612
+ process.exit(healthResult.healthy ? EXIT_CODES.SUCCESS : EXIT_CODES.GENERAL_ERROR);
1613
+ }
1614
+ // Subcommand: invoke <domain> <agent> [payload]
1615
+ if (parsed.subcommand === 'invoke') {
1616
+ const domain = parsed.positionalArgs[0];
1617
+ const agent = parsed.positionalArgs[1];
1618
+ const payloadStr = parsed.positionalArgs[2];
1619
+ if (!domain || !agent) {
1620
+ console.error('Usage: agentics agents invoke <domain> <agent> [json-payload]');
1621
+ console.error(`Valid domains: ${Object.keys(AGENT_DOMAINS).join(', ')}`);
1622
+ if (domain && AGENT_DOMAINS[domain]) {
1623
+ console.error(`Valid agents for ${domain}: ${AGENT_DOMAINS[domain].agents.join(', ')}`);
1624
+ }
1625
+ process.exit(EXIT_CODES.USAGE_ERROR);
1626
+ }
1627
+ let payload = {};
1628
+ if (payloadStr) {
1629
+ try {
1630
+ payload = JSON.parse(payloadStr);
1631
+ }
1632
+ catch {
1633
+ console.error(`Invalid JSON payload: ${payloadStr}`);
1634
+ process.exit(EXIT_CODES.USAGE_ERROR);
1635
+ }
1636
+ }
1637
+ const invokeResult = await executeAgentsInvokeCommand(domain, agent, payload, options);
1638
+ if (options.format === 'json') {
1639
+ console.log(JSON.stringify(invokeResult, null, parsed.flags['pretty'] ? 2 : 0));
1640
+ }
1641
+ else {
1642
+ console.log(formatAgentResultForDisplay(invokeResult));
1643
+ }
1644
+ if (options.verbose) {
1645
+ console.error(`Agent ${domain}/${agent} responded in ${invokeResult.timing}ms (HTTP ${invokeResult.status})`);
1646
+ }
1647
+ process.exit(EXIT_CODES.SUCCESS);
1648
+ }
1649
+ // Unknown subcommand
1650
+ console.error(`Unknown agents subcommand: ${parsed.subcommand}`);
1651
+ console.error('Supported subcommands: list, health, invoke');
1652
+ process.exit(EXIT_CODES.USAGE_ERROR);
1653
+ }
1654
+ case 'ask': {
1655
+ // Natural language routing: agentics ask "check this for injection attacks"
1656
+ const queryParts = [];
1657
+ if (parsed.subcommand)
1658
+ queryParts.push(parsed.subcommand);
1659
+ queryParts.push(...parsed.positionalArgs);
1660
+ const nlQuery = queryParts.join(' ').trim();
1661
+ if (!nlQuery) {
1662
+ console.error('Usage: agentics ask "<natural language query>"');
1663
+ console.error('');
1664
+ console.error('Examples:');
1665
+ console.error(' agentics ask "check this prompt for injection attacks"');
1666
+ console.error(' agentics ask "how much am I spending on AI"');
1667
+ console.error(' agentics ask "detect anomalies in my latency metrics"');
1668
+ process.exit(EXIT_CODES.USAGE_ERROR);
1669
+ }
1670
+ try {
1671
+ const routeResult = await executeNaturalLanguageRoute(nlQuery, options);
1672
+ if (options.format === 'json') {
1673
+ console.log(JSON.stringify({
1674
+ query: nlQuery,
1675
+ intent: routeResult.intent,
1676
+ result: routeResult.invocation,
1677
+ timing: routeResult.timing,
1678
+ }, null, parsed.flags['pretty'] ? 2 : 0));
1679
+ }
1680
+ else {
1681
+ console.log(formatNaturalLanguageRouteForDisplay(routeResult));
1682
+ }
1683
+ if (options.verbose) {
1684
+ console.error(`NL routing completed in ${routeResult.timing}ms`);
1685
+ }
1686
+ process.exit(EXIT_CODES.SUCCESS);
1687
+ }
1688
+ catch (error) {
1689
+ if (error instanceof ServiceError && error.message.includes('unavailable')) {
1690
+ console.error('Natural language routing unavailable (copilot service unreachable).');
1691
+ console.error('');
1692
+ console.error('Use explicit agent invocation instead:');
1693
+ console.error(' agentics agents list # show available agents');
1694
+ console.error(' agentics agents invoke <domain> <agent> \'{}\' # invoke directly');
1695
+ process.exit(EXIT_CODES.SERVICE_UNAVAILABLE);
1696
+ }
1697
+ throw error;
1698
+ }
1699
+ }
1700
+ default: {
1701
+ // Before failing, attempt NL routing for unrecognized multi-word input
1702
+ const nlParts = [parsed.command];
1703
+ if (parsed.subcommand)
1704
+ nlParts.push(parsed.subcommand);
1705
+ nlParts.push(...parsed.positionalArgs);
1706
+ const nlFallback = nlParts.join(' ').trim();
1707
+ // Only attempt NL for inputs that look like natural language (not typos)
1708
+ const looksLikeNL = nlFallback.includes(' ') || nlFallback.length > 20;
1709
+ if (looksLikeNL) {
1710
+ try {
1711
+ // Auth is required for NL routing (calls copilot-agents)
1712
+ await enforceAuthSessionGate();
1713
+ console.error(`Unknown command '${parsed.command}'. Attempting natural language routing...`);
1714
+ console.error('');
1715
+ const routeResult = await executeNaturalLanguageRoute(nlFallback, options);
1716
+ if (options.format === 'json') {
1717
+ console.log(JSON.stringify({
1718
+ query: nlFallback,
1719
+ intent: routeResult.intent,
1720
+ result: routeResult.invocation,
1721
+ timing: routeResult.timing,
1722
+ }, null, parsed.flags['pretty'] ? 2 : 0));
1723
+ }
1724
+ else {
1725
+ console.log(formatNaturalLanguageRouteForDisplay(routeResult));
1726
+ }
1727
+ process.exit(EXIT_CODES.SUCCESS);
1728
+ }
1729
+ catch {
1730
+ // NL routing failed -- fall through to standard error
1731
+ }
1732
+ }
1453
1733
  console.error(`Unknown command: ${parsed.command}`);
1454
1734
  console.error(`Supported commands: ${SUPPORTED_COMMANDS.join(', ')}`);
1735
+ console.error('');
1736
+ console.error('Or use natural language:');
1737
+ console.error(' agentics ask "your question here"');
1455
1738
  process.exit(EXIT_CODES.USAGE_ERROR);
1739
+ }
1456
1740
  }
1457
1741
  // Output result (skip for commands that handle their own output)
1458
1742
  if (result) {
@@ -1503,7 +1787,16 @@ function gatherStatusState() {
1503
1787
  simulations: 0,
1504
1788
  deployments: 0,
1505
1789
  policies: 0,
1790
+ erp: 0,
1791
+ artifacts: 0,
1792
+ inspections: 0,
1793
+ totalRuns: 0,
1506
1794
  tools: 48,
1795
+ agentsRunning: 0,
1796
+ agentsAvailable: 100,
1797
+ activeAgentTypes: [],
1798
+ activeCalls: 0,
1799
+ activeCallServices: [],
1507
1800
  };
1508
1801
  // Auth & identity
1509
1802
  try {
@@ -1519,6 +1812,15 @@ function gatherStatusState() {
1519
1812
  }
1520
1813
  }
1521
1814
  catch { /* not logged in */ }
1815
+ // Identity file (display name, org, role)
1816
+ try {
1817
+ const idRaw = fs.readFileSync(path.join(agenticsDir, 'identity.json'), 'utf-8');
1818
+ const id = JSON.parse(idRaw);
1819
+ state.displayName = id.user?.display_name;
1820
+ state.orgName = id.org?.org_name;
1821
+ state.role = id.role;
1822
+ }
1823
+ catch { /* no identity */ }
1522
1824
  // Check internal allowlist for tier override
1523
1825
  if (state.authenticated && state.email) {
1524
1826
  try {
@@ -1532,14 +1834,16 @@ function gatherStatusState() {
1532
1834
  }
1533
1835
  catch { /* no allowlist */ }
1534
1836
  }
1535
- // Count runs (plans, simulations, deployments)
1837
+ // Count runs by category + artifacts
1536
1838
  try {
1537
1839
  const runsDir = path.join(agenticsDir, 'runs');
1538
1840
  if (fs.existsSync(runsDir)) {
1539
1841
  const entries = fs.readdirSync(runsDir);
1842
+ state.totalRuns = entries.length;
1540
1843
  for (const entry of entries) {
1541
1844
  try {
1542
- const metaPath = path.join(runsDir, entry, 'meta.json');
1845
+ const entryDir = path.join(runsDir, entry);
1846
+ const metaPath = path.join(entryDir, 'meta.json');
1543
1847
  if (fs.existsSync(metaPath)) {
1544
1848
  const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
1545
1849
  const cmd = meta.command ?? meta.type ?? '';
@@ -1549,7 +1853,14 @@ function gatherStatusState() {
1549
1853
  state.simulations++;
1550
1854
  else if (cmd.includes('deploy'))
1551
1855
  state.deployments++;
1552
- }
1856
+ else if (cmd.includes('erp'))
1857
+ state.erp++;
1858
+ else if (cmd.includes('inspect') || cmd.includes('query'))
1859
+ state.inspections++;
1860
+ }
1861
+ // Count artifact files (everything except meta.json)
1862
+ const files = fs.readdirSync(entryDir);
1863
+ state.artifacts += files.filter(f => f !== 'meta.json').length;
1553
1864
  }
1554
1865
  catch { /* skip bad entry */ }
1555
1866
  }
@@ -1564,6 +1875,53 @@ function gatherStatusState() {
1564
1875
  }
1565
1876
  }
1566
1877
  catch { /* no policies */ }
1878
+ // Running agents (tracked via per-agent JSON files in ~/.agentics/agents/)
1879
+ try {
1880
+ const agentsTrackDir = path.join(agenticsDir, 'agents');
1881
+ if (fs.existsSync(agentsTrackDir)) {
1882
+ const agentFiles = fs.readdirSync(agentsTrackDir).filter(f => f.endsWith('.json'));
1883
+ state.agentsRunning = agentFiles.length;
1884
+ const types = new Set();
1885
+ for (const file of agentFiles) {
1886
+ try {
1887
+ const raw = fs.readFileSync(path.join(agentsTrackDir, file), 'utf-8');
1888
+ const data = JSON.parse(raw);
1889
+ if (data.type)
1890
+ types.add(data.type);
1891
+ }
1892
+ catch { /* skip bad file */ }
1893
+ }
1894
+ state.activeAgentTypes = Array.from(types);
1895
+ }
1896
+ }
1897
+ catch { /* no agents dir */ }
1898
+ // Active downstream calls (tracked via per-call JSON files in ~/.agentics/calls/)
1899
+ try {
1900
+ const callsDir = path.join(agenticsDir, 'calls');
1901
+ if (fs.existsSync(callsDir)) {
1902
+ const callFiles = fs.readdirSync(callsDir).filter(f => f.endsWith('.json'));
1903
+ state.activeCalls = callFiles.length;
1904
+ const services = new Set();
1905
+ for (const file of callFiles) {
1906
+ try {
1907
+ const raw = fs.readFileSync(path.join(callsDir, file), 'utf-8');
1908
+ const data = JSON.parse(raw);
1909
+ if (data.service) {
1910
+ const short = data.service
1911
+ .replace(/^agentics-simulation-/, '')
1912
+ .replace(/^agentics-deployment-/, '')
1913
+ .replace(/^agentics-org-/, '')
1914
+ .replace(/^agentics-/, '')
1915
+ .replace(/^enterprise-/, '');
1916
+ services.add(short);
1917
+ }
1918
+ }
1919
+ catch { /* skip bad file */ }
1920
+ }
1921
+ state.activeCallServices = Array.from(services);
1922
+ }
1923
+ }
1924
+ catch { /* no calls dir */ }
1567
1925
  return state;
1568
1926
  }
1569
1927
  function printStatusLine(jsonMode) {
@@ -1572,25 +1930,70 @@ function printStatusLine(jsonMode) {
1572
1930
  console.log(JSON.stringify({ name: 'agentics-cli', version: VERSION, ...s }));
1573
1931
  return;
1574
1932
  }
1933
+ // ANSI colors (matching claude-flow CLI style)
1934
+ const R = '\x1b[0m';
1935
+ const D = '\x1b[2m';
1936
+ const PP = '\x1b[1;35m'; // bright purple
1937
+ const CC = '\x1b[1;36m'; // bright cyan
1938
+ const BB = '\x1b[1;34m'; // bright blue
1939
+ const GG = '\x1b[1;32m'; // bright green
1940
+ const YY = '\x1b[1;33m'; // bright yellow
1941
+ const WW = '\x1b[1;37m'; // bright white
1942
+ const cn = '\x1b[0;36m'; // cyan (labels)
1943
+ const sep = `${D}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${R}`;
1944
+ const pipe = ` ${D}\u2502${R} `;
1575
1945
  if (!s.authenticated) {
1576
- console.log('\u25CB Agentics | not authenticated | run: agentics login');
1946
+ const lines = [
1947
+ `${PP}\u258A Agentics.dev v${VERSION}${R} ${D}\u25C7 not authenticated${R}`,
1948
+ sep,
1949
+ `${cn}Run ${WW}agentics login${R}${cn} to get started${R}`,
1950
+ sep,
1951
+ ];
1952
+ console.log(lines.join('\n'));
1577
1953
  return;
1578
1954
  }
1579
- const user = s.email ? s.email.split('@')[0] : 'user';
1955
+ const user = s.displayName
1956
+ ?? (s.email ? s.email.split('@')[0] ?? 'user' : 'user');
1580
1957
  const tierBadge = s.tier === 'internal' ? 'INT'
1581
1958
  : s.tier === 'paid' ? 'PRO'
1582
1959
  : s.tier === 'free' ? 'FREE'
1583
1960
  : 'ACT';
1584
- const parts = [
1585
- `\u25C8 Agentics [${tierBadge}]`,
1586
- user,
1587
- `Plans:${s.plans}`,
1588
- `Sims:${s.simulations}`,
1589
- `Deploy:${s.deployments}`,
1590
- `Policy:${s.policies}`,
1591
- `Tools:${s.tools}`,
1592
- ];
1593
- console.log(parts.join(' | '));
1961
+ // Header: Agentics v1.4.5 ● user │ PRO │ owner
1962
+ let header = `${PP}\u258A Agentics.dev v${VERSION}${R}`;
1963
+ header += ` ${CC}\u25CF ${user}${R}`;
1964
+ header += pipe + `${BB}${tierBadge}${R}`;
1965
+ if (s.role)
1966
+ header += pipe + `${D}${s.role}${R}`;
1967
+ if (s.orgName)
1968
+ header += pipe + `${D}${s.orgName}${R}`;
1969
+ // Line 1: 🤖 Agents ● [2] coder,tester │ ⇅ Calls [1] planner │ 📋 Plans 0 🧪 Simulate 0 🚀 Deploy 0
1970
+ const agentOn = s.agentsRunning > 0;
1971
+ const agentDot = agentOn ? `${GG}\u25C9${R}` : `${D}\u25CB${R}`;
1972
+ const agentClr = agentOn ? GG : D;
1973
+ let line1 = `${YY}\uD83E\uDD16 Agents${R} ${agentDot} [${agentClr}${s.agentsRunning}${R}]`;
1974
+ if (s.activeAgentTypes.length > 0) {
1975
+ line1 += ` ${D}${s.activeAgentTypes.join(',')}${R}`;
1976
+ }
1977
+ if (s.activeCalls > 0) {
1978
+ line1 += pipe + `${CC}\u21C5 Calls${R} [${CC}${s.activeCalls}${R}]`;
1979
+ if (s.activeCallServices.length > 0) {
1980
+ line1 += ` ${D}${s.activeCallServices.join(',')}${R}`;
1981
+ }
1982
+ }
1983
+ line1 += pipe;
1984
+ line1 += `${cn}\uD83D\uDCCB Plans${R} ${WW}${s.plans}${R}`;
1985
+ line1 += ` ${cn}\uD83E\uDDEA Simulate${R} ${WW}${s.simulations}${R}`;
1986
+ line1 += ` ${cn}\uD83D\uDE80 Deploy${R} ${WW}${s.deployments}${R}`;
1987
+ // Line 2: 📜 Policy 0 🏭 ERP 0 │ 📦 Artifacts 0 🔍 Inspect 0 📊 Usage 0
1988
+ let line2 = `${cn}\uD83D\uDCDC Policy${R} ${WW}${s.policies}${R}`;
1989
+ line2 += ` ${cn}\uD83C\uDFED ERP${R} ${WW}${s.erp}${R}`;
1990
+ line2 += pipe;
1991
+ line2 += `${cn}\uD83D\uDCE6 Artifacts${R} ${WW}${s.artifacts}${R}`;
1992
+ line2 += ` ${cn}\uD83D\uDD0D Inspect${R} ${WW}${s.inspections}${R}`;
1993
+ line2 += ` ${cn}\uD83D\uDCCA Usage${R} ${WW}${s.totalRuns}${R}`;
1994
+ line2 += pipe;
1995
+ line2 += `${D}\uD83D\uDEE0\uFE0F ${s.tools} tools${R}`;
1996
+ console.log([header, sep, line1, line2, sep].join('\n'));
1594
1997
  }
1595
1998
  // ============================================================================
1596
1999
  // Help Output