@llm-dev-ops/agentics-cli 2.5.3 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +334 -31
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/agents.d.ts +7 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +130 -23
- package/dist/commands/agents.js.map +1 -1
- package/dist/contracts/adr-command-semantics.d.ts.map +1 -1
- package/dist/contracts/adr-command-semantics.js +12 -0
- package/dist/contracts/adr-command-semantics.js.map +1 -1
- package/dist/errors/transient.d.ts +67 -0
- package/dist/errors/transient.d.ts.map +1 -0
- package/dist/errors/transient.js +260 -0
- package/dist/errors/transient.js.map +1 -0
- package/dist/gates/execution-gate.d.ts.map +1 -1
- package/dist/gates/execution-gate.js +11 -0
- package/dist/gates/execution-gate.js.map +1 -1
- package/dist/mcp/mcp-server.js +13 -1
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/modules/command-parser.d.ts +1 -1
- package/dist/modules/command-parser.d.ts.map +1 -1
- package/dist/modules/command-parser.js +5 -0
- package/dist/modules/command-parser.js.map +1 -1
- package/dist/observability/degradations.d.ts +58 -0
- package/dist/observability/degradations.d.ts.map +1 -0
- package/dist/observability/degradations.js +74 -0
- package/dist/observability/degradations.js.map +1 -0
- package/dist/pipeline/phase1-verdict.d.ts +55 -0
- package/dist/pipeline/phase1-verdict.d.ts.map +1 -0
- package/dist/pipeline/phase1-verdict.js +186 -0
- package/dist/pipeline/phase1-verdict.js.map +1 -0
- package/dist/pipeline/phase2-preflight.d.ts +44 -0
- package/dist/pipeline/phase2-preflight.d.ts.map +1 -0
- package/dist/pipeline/phase2-preflight.js +120 -0
- package/dist/pipeline/phase2-preflight.js.map +1 -0
- package/dist/pipeline/swarm-orchestrator.d.ts.map +1 -1
- package/dist/pipeline/swarm-orchestrator.js +67 -5
- package/dist/pipeline/swarm-orchestrator.js.map +1 -1
- package/dist/synthesis/financial-claim-extractor.d.ts +11 -0
- package/dist/synthesis/financial-claim-extractor.d.ts.map +1 -1
- package/dist/synthesis/financial-claim-extractor.js +24 -0
- package/dist/synthesis/financial-claim-extractor.js.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.d.ts.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.js +28 -3
- package/dist/synthesis/simulation-artifact-generator.js.map +1 -1
- package/dist/synthesis/simulation-renderers.d.ts +1 -1
- package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
- package/dist/synthesis/simulation-renderers.js +39 -13
- package/dist/synthesis/simulation-renderers.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/agents.js
CHANGED
|
@@ -14,6 +14,9 @@ import { createAdapter } from '../adapters/base-adapter.js';
|
|
|
14
14
|
import { getAnthropicApiKey } from '../utils/credentials.js';
|
|
15
15
|
import { executeSimulateCommand } from './simulate.js';
|
|
16
16
|
import { execFileSync } from 'node:child_process';
|
|
17
|
+
import { isTransientFailure, isTerminalFailure } from '../errors/transient.js';
|
|
18
|
+
import { recordDegradation, drainDegradations } from '../observability/degradations.js';
|
|
19
|
+
import { computePhase1Verdict } from '../pipeline/phase1-verdict.js';
|
|
17
20
|
// ============================================================================
|
|
18
21
|
// ADR-066: Copilot agents via claude --print (Claude Max — no API key needed)
|
|
19
22
|
// ============================================================================
|
|
@@ -513,6 +516,16 @@ export async function executeAgentsInvokeCommand(domain, agent, payload, options
|
|
|
513
516
|
// data we already built in buildDomainPayload().
|
|
514
517
|
// -------------------------------------------------------------------------
|
|
515
518
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
519
|
+
// ADR-PIPELINE-089 §2: every throw-based local fallback path below is a
|
|
520
|
+
// Phase 1 degradation. Record once here (above the per-domain branches)
|
|
521
|
+
// so the Phase 1 verdict sees every backend that failed over to local
|
|
522
|
+
// compute without needing to instrument each return site.
|
|
523
|
+
recordDegradation(correlationId, {
|
|
524
|
+
code: 'local-fallback',
|
|
525
|
+
message: `${domain}/${agent} cloud backend unavailable (${errMsg.slice(0, 120)}) — using local compute`,
|
|
526
|
+
phase: 1,
|
|
527
|
+
source: `agents/${domain}/${agent}`,
|
|
528
|
+
});
|
|
516
529
|
// costops: ANY costops agent failure gets routed to its dedicated local compute function
|
|
517
530
|
if (domain === 'costops') {
|
|
518
531
|
if (options.verbose) {
|
|
@@ -619,6 +632,14 @@ export async function executeAgentsInvokeCommand(domain, agent, payload, options
|
|
|
619
632
|
if (options.verbose) {
|
|
620
633
|
console.error(`[local] ${domain}/${agent} using local compute (health-check response)`);
|
|
621
634
|
}
|
|
635
|
+
// ADR-PIPELINE-089 §2: cloud function returned a generic health page
|
|
636
|
+
// instead of a real agent response — count as a local fallback.
|
|
637
|
+
recordDegradation(correlationId, {
|
|
638
|
+
code: 'local-fallback',
|
|
639
|
+
message: `${domain}/${agent} returned generic health response — using local compute`,
|
|
640
|
+
phase: 1,
|
|
641
|
+
source: `agents/${domain}/${agent}`,
|
|
642
|
+
});
|
|
622
643
|
return {
|
|
623
644
|
domain,
|
|
624
645
|
agent,
|
|
@@ -3792,16 +3813,16 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
3792
3813
|
}
|
|
3793
3814
|
catch (err) {
|
|
3794
3815
|
lastErr = err instanceof Error ? err : new Error(String(err));
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
if (!
|
|
3804
|
-
console.error(` [RUVECTOR]
|
|
3816
|
+
// ADR-PIPELINE-089 §1: centralized transient/terminal classifier
|
|
3817
|
+
// replaces the narrow substring list. Terminal failures (payload /
|
|
3818
|
+
// auth / canonical 404) short-circuit; transient failures (5xx,
|
|
3819
|
+
// ECONN*, ETIMEDOUT, rate limits, "unreachable") retry.
|
|
3820
|
+
if (isTerminalFailure(err)) {
|
|
3821
|
+
console.error(` [RUVECTOR] Terminal error (not retrying): ${lastErr.message}`);
|
|
3822
|
+
break;
|
|
3823
|
+
}
|
|
3824
|
+
if (!isTransientFailure(err)) {
|
|
3825
|
+
console.error(` [RUVECTOR] Unrecognized error (not retrying): ${lastErr.message}`);
|
|
3805
3826
|
break;
|
|
3806
3827
|
}
|
|
3807
3828
|
console.error(` [RUVECTOR] Attempt ${attempt + 1}/${MAX_RETRIES + 1} failed: ${lastErr.message.slice(0, 150)}`);
|
|
@@ -3875,6 +3896,8 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
3875
3896
|
}
|
|
3876
3897
|
}
|
|
3877
3898
|
// Non-fatal: generate artifacts
|
|
3899
|
+
let artifactFilesGraphRouted = [];
|
|
3900
|
+
let artifactRunDirGraphRouted;
|
|
3878
3901
|
try {
|
|
3879
3902
|
const { generateSimulationArtifacts } = await import('../synthesis/simulation-artifact-generator.js');
|
|
3880
3903
|
const simSettled = allResults[0];
|
|
@@ -3895,6 +3918,8 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
3895
3918
|
timing: elapsed,
|
|
3896
3919
|
});
|
|
3897
3920
|
console.error(`Graph-routed artifacts: ${artifacts.runDir}`);
|
|
3921
|
+
artifactFilesGraphRouted = artifacts.filesWritten;
|
|
3922
|
+
artifactRunDirGraphRouted = artifacts.runDir;
|
|
3898
3923
|
}
|
|
3899
3924
|
catch (artifactErr) {
|
|
3900
3925
|
const artMsg = artifactErr instanceof Error ? artifactErr.message : String(artifactErr);
|
|
@@ -3906,6 +3931,43 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
3906
3931
|
const routingMeta = graphResult.unresolved.length > 0
|
|
3907
3932
|
? { unresolved: graphResult.unresolved.map(u => ({ stage: u.stage, agentName: u.agentName, capability: u.capability })) }
|
|
3908
3933
|
: { unresolved: [] };
|
|
3934
|
+
// ADR-PIPELINE-089 §2: compute Phase 1 verdict from dispatch
|
|
3935
|
+
// results + drained degradations. The degradation sink is
|
|
3936
|
+
// process-local keyed by correlationId; draining here prevents
|
|
3937
|
+
// leaking state into subsequent runs (tests, daemons).
|
|
3938
|
+
const degradations = drainDegradations(correlationId);
|
|
3939
|
+
const phase1Verdict = computePhase1Verdict(invocations, degradations, artifactFilesGraphRouted);
|
|
3940
|
+
// ADR-PIPELINE-089 §2: patch verdict into manifest.json so
|
|
3941
|
+
// downstream phases (and `agentics status`) can read it without
|
|
3942
|
+
// keeping state in memory. Best-effort; manifest may not exist if
|
|
3943
|
+
// the artifact generator itself threw.
|
|
3944
|
+
if (artifactRunDirGraphRouted) {
|
|
3945
|
+
try {
|
|
3946
|
+
const fsMod = await import('node:fs');
|
|
3947
|
+
const pathMod = await import('node:path');
|
|
3948
|
+
const mPath = pathMod.join(artifactRunDirGraphRouted, 'manifest.json');
|
|
3949
|
+
if (fsMod.existsSync(mPath)) {
|
|
3950
|
+
const m = JSON.parse(fsMod.readFileSync(mPath, 'utf-8'));
|
|
3951
|
+
m['phase1_verdict'] = phase1Verdict.verdict;
|
|
3952
|
+
m['phase1_reason'] = phase1Verdict.reason;
|
|
3953
|
+
m['phase1_degradations'] = phase1Verdict.degradations;
|
|
3954
|
+
m['phase1_stats'] = phase1Verdict.stats;
|
|
3955
|
+
fsMod.writeFileSync(mPath, JSON.stringify(m, null, 2), 'utf-8');
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3958
|
+
catch { /* non-fatal */ }
|
|
3959
|
+
}
|
|
3960
|
+
// One-line verdict banner — visible on the terminal and captured by
|
|
3961
|
+
// the MCP tool wrapper for status surfacing.
|
|
3962
|
+
if (phase1Verdict.verdict !== 'healthy') {
|
|
3963
|
+
const label = phase1Verdict.verdict.toUpperCase();
|
|
3964
|
+
console.error(`Phase 1 verdict: ${label} — ${phase1Verdict.reason}`);
|
|
3965
|
+
if (phase1Verdict.degradations.length > 0) {
|
|
3966
|
+
for (const d of phase1Verdict.degradations) {
|
|
3967
|
+
console.error(` · [${d.code}] ${d.message}`);
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3909
3971
|
return {
|
|
3910
3972
|
kind: 'multi',
|
|
3911
3973
|
result: {
|
|
@@ -3913,6 +3975,7 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
3913
3975
|
intents,
|
|
3914
3976
|
invocations,
|
|
3915
3977
|
routing: routingMeta,
|
|
3978
|
+
phase1Verdict,
|
|
3916
3979
|
timing: elapsed,
|
|
3917
3980
|
},
|
|
3918
3981
|
};
|
|
@@ -4111,19 +4174,15 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
4111
4174
|
}
|
|
4112
4175
|
catch (err) {
|
|
4113
4176
|
lastErr = err instanceof Error ? err : new Error(String(err));
|
|
4114
|
-
|
|
4115
|
-
//
|
|
4116
|
-
//
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|| msg.includes('network error')
|
|
4124
|
-
|| msg.includes('aborterror');
|
|
4125
|
-
if (!isRetryable) {
|
|
4126
|
-
console.error(` [RUVECTOR] Non-retryable error: ${lastErr.message}`);
|
|
4177
|
+
// ADR-PIPELINE-089 §1: centralized transient/terminal classifier.
|
|
4178
|
+
// Contract validation / auth errors are terminal; 5xx, ECONN*,
|
|
4179
|
+
// ETIMEDOUT, rate limits, and "unreachable" variants retry.
|
|
4180
|
+
if (isTerminalFailure(err)) {
|
|
4181
|
+
console.error(` [RUVECTOR] Terminal error (not retrying): ${lastErr.message}`);
|
|
4182
|
+
break;
|
|
4183
|
+
}
|
|
4184
|
+
if (!isTransientFailure(err)) {
|
|
4185
|
+
console.error(` [RUVECTOR] Unrecognized error (not retrying): ${lastErr.message}`);
|
|
4127
4186
|
break;
|
|
4128
4187
|
}
|
|
4129
4188
|
console.error(` [RUVECTOR] Attempt ${attempt + 1}/${MAX_RETRIES + 1} failed: ${lastErr.message.slice(0, 150)}`);
|
|
@@ -4216,6 +4275,8 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
4216
4275
|
}
|
|
4217
4276
|
}
|
|
4218
4277
|
// Non-fatal: generate simulation + engineering artifacts
|
|
4278
|
+
let artifactFilesFleet = [];
|
|
4279
|
+
let artifactRunDirFleet;
|
|
4219
4280
|
try {
|
|
4220
4281
|
const { generateSimulationArtifacts } = await import('../synthesis/simulation-artifact-generator.js');
|
|
4221
4282
|
const simResult = allResults[0]?.status === 'fulfilled' ? allResults[0].value : undefined;
|
|
@@ -4240,18 +4301,49 @@ export async function executeNaturalLanguageRoute(query, options) {
|
|
|
4240
4301
|
timing: elapsed,
|
|
4241
4302
|
});
|
|
4242
4303
|
console.error(`Full-fleet artifacts: ${artifacts.runDir}`);
|
|
4304
|
+
artifactFilesFleet = artifacts.filesWritten;
|
|
4305
|
+
artifactRunDirFleet = artifacts.runDir;
|
|
4243
4306
|
}
|
|
4244
4307
|
catch (artifactErr) {
|
|
4245
4308
|
const artMsg = artifactErr instanceof Error ? artifactErr.message : String(artifactErr);
|
|
4246
4309
|
console.error(`[WARN] Phase 1 artifact generation failed: ${artMsg}`);
|
|
4247
4310
|
console.error(' Auto-chain Phases 2-6 may fail without Phase 1 manifest.');
|
|
4248
4311
|
}
|
|
4312
|
+
// ADR-PIPELINE-089 §2: Phase 1 verdict for the full-fleet path.
|
|
4313
|
+
const fleetDegradations = drainDegradations(correlationId);
|
|
4314
|
+
const fleetPhase1Verdict = computePhase1Verdict(invocations, fleetDegradations, artifactFilesFleet);
|
|
4315
|
+
if (artifactRunDirFleet) {
|
|
4316
|
+
try {
|
|
4317
|
+
const fsMod = await import('node:fs');
|
|
4318
|
+
const pathMod = await import('node:path');
|
|
4319
|
+
const mPath = pathMod.join(artifactRunDirFleet, 'manifest.json');
|
|
4320
|
+
if (fsMod.existsSync(mPath)) {
|
|
4321
|
+
const m = JSON.parse(fsMod.readFileSync(mPath, 'utf-8'));
|
|
4322
|
+
m['phase1_verdict'] = fleetPhase1Verdict.verdict;
|
|
4323
|
+
m['phase1_reason'] = fleetPhase1Verdict.reason;
|
|
4324
|
+
m['phase1_degradations'] = fleetPhase1Verdict.degradations;
|
|
4325
|
+
m['phase1_stats'] = fleetPhase1Verdict.stats;
|
|
4326
|
+
fsMod.writeFileSync(mPath, JSON.stringify(m, null, 2), 'utf-8');
|
|
4327
|
+
}
|
|
4328
|
+
}
|
|
4329
|
+
catch { /* non-fatal */ }
|
|
4330
|
+
}
|
|
4331
|
+
if (fleetPhase1Verdict.verdict !== 'healthy') {
|
|
4332
|
+
const label = fleetPhase1Verdict.verdict.toUpperCase();
|
|
4333
|
+
console.error(`Phase 1 verdict: ${label} — ${fleetPhase1Verdict.reason}`);
|
|
4334
|
+
if (fleetPhase1Verdict.degradations.length > 0) {
|
|
4335
|
+
for (const d of fleetPhase1Verdict.degradations) {
|
|
4336
|
+
console.error(` · [${d.code}] ${d.message}`);
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4249
4340
|
return {
|
|
4250
4341
|
kind: 'multi',
|
|
4251
4342
|
result: {
|
|
4252
4343
|
query,
|
|
4253
4344
|
intents,
|
|
4254
4345
|
invocations,
|
|
4346
|
+
phase1Verdict: fleetPhase1Verdict,
|
|
4255
4347
|
timing: elapsed,
|
|
4256
4348
|
},
|
|
4257
4349
|
};
|
|
@@ -4278,6 +4370,21 @@ export function formatMultiAgentRouteForDisplay(result) {
|
|
|
4278
4370
|
lines.push(`Multi-agent query: "${result.query}"`);
|
|
4279
4371
|
lines.push(`Agents invoked: ${agentCount} (${succeeded} succeeded${failed > 0 ? `, ${failed} failed` : ''})`);
|
|
4280
4372
|
lines.push(`Total Timing: ${result.timing}ms`);
|
|
4373
|
+
// ADR-PIPELINE-089 §2: surface the Phase 1 verdict prominently so the
|
|
4374
|
+
// display output (shell or MCP-stdout-relay) shows HEALTHY / DEGRADED /
|
|
4375
|
+
// FAILED with the specific degradation list. Healthy runs stay terse.
|
|
4376
|
+
const v = result.phase1Verdict;
|
|
4377
|
+
if (v) {
|
|
4378
|
+
if (v.verdict === 'healthy') {
|
|
4379
|
+
lines.push(`Phase 1 verdict: HEALTHY — ${v.reason}`);
|
|
4380
|
+
}
|
|
4381
|
+
else {
|
|
4382
|
+
lines.push(`Phase 1 verdict: ${v.verdict.toUpperCase()} — ${v.reason}`);
|
|
4383
|
+
for (const d of v.degradations) {
|
|
4384
|
+
lines.push(` · [${d.code}] ${d.message}`);
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
}
|
|
4281
4388
|
lines.push('');
|
|
4282
4389
|
// ADR-PIPELINE-087 §4: surface unresolved classifier selections at the top
|
|
4283
4390
|
// of the display so operators (and MCP clients relaying stdout) see the
|