@exellix/ai-tasks 8.1.16 → 8.2.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/core/task-sdk.d.ts.map +1 -1
- package/dist/core/task-sdk.js +1187 -1159
- package/dist/core/task-sdk.js.map +1 -1
- package/dist/errors/runTaskExecutionError.d.ts +63 -0
- package/dist/errors/runTaskExecutionError.d.ts.map +1 -0
- package/dist/errors/runTaskExecutionError.js +167 -0
- package/dist/errors/runTaskExecutionError.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/invocation/buildRunTaskResultMeta.d.ts +7 -0
- package/dist/invocation/buildRunTaskResultMeta.d.ts.map +1 -0
- package/dist/invocation/buildRunTaskResultMeta.js +38 -0
- package/dist/invocation/buildRunTaskResultMeta.js.map +1 -0
- package/dist/invocation/formatEngineLabel.d.ts +4 -0
- package/dist/invocation/formatEngineLabel.d.ts.map +1 -0
- package/dist/invocation/formatEngineLabel.js +19 -0
- package/dist/invocation/formatEngineLabel.js.map +1 -0
- package/dist/invocation/index.d.ts +8 -0
- package/dist/invocation/index.d.ts.map +1 -0
- package/dist/invocation/index.js +7 -0
- package/dist/invocation/index.js.map +1 -0
- package/dist/invocation/invocationPolicy.d.ts +8 -0
- package/dist/invocation/invocationPolicy.d.ts.map +1 -0
- package/dist/invocation/invocationPolicy.js +13 -0
- package/dist/invocation/invocationPolicy.js.map +1 -0
- package/dist/invocation/parseProfileSlot.d.ts +6 -0
- package/dist/invocation/parseProfileSlot.d.ts.map +1 -0
- package/dist/invocation/parseProfileSlot.js +12 -0
- package/dist/invocation/parseProfileSlot.js.map +1 -0
- package/dist/invocation/resolveInvocationPlan.d.ts +7 -0
- package/dist/invocation/resolveInvocationPlan.d.ts.map +1 -0
- package/dist/invocation/resolveInvocationPlan.js +49 -0
- package/dist/invocation/resolveInvocationPlan.js.map +1 -0
- package/dist/invocation/resolveProfileInvocationRouting.d.ts +30 -0
- package/dist/invocation/resolveProfileInvocationRouting.d.ts.map +1 -0
- package/dist/invocation/resolveProfileInvocationRouting.js +118 -0
- package/dist/invocation/resolveProfileInvocationRouting.js.map +1 -0
- package/dist/invocation/types.d.ts +64 -0
- package/dist/invocation/types.d.ts.map +1 -0
- package/dist/invocation/types.js +2 -0
- package/dist/invocation/types.js.map +1 -0
- package/dist/logxer/aiTasksDiagnosticCodes.d.ts +1 -0
- package/dist/logxer/aiTasksDiagnosticCodes.d.ts.map +1 -1
- package/dist/logxer/aiTasksDiagnosticCodes.js +1 -0
- package/dist/logxer/aiTasksDiagnosticCodes.js.map +1 -1
- package/dist/observability/classifyRunTaskFailure.d.ts +33 -0
- package/dist/observability/classifyRunTaskFailure.d.ts.map +1 -0
- package/dist/observability/classifyRunTaskFailure.js +111 -0
- package/dist/observability/classifyRunTaskFailure.js.map +1 -0
- package/dist/observability/llmRouteContext.d.ts +26 -0
- package/dist/observability/llmRouteContext.d.ts.map +1 -0
- package/dist/observability/llmRouteContext.js +92 -0
- package/dist/observability/llmRouteContext.js.map +1 -0
- package/dist/observability/logRunTaskFailure.d.ts +10 -0
- package/dist/observability/logRunTaskFailure.d.ts.map +1 -0
- package/dist/observability/logRunTaskFailure.js +87 -0
- package/dist/observability/logRunTaskFailure.js.map +1 -0
- package/dist/strategies/direct-execution-strategy.d.ts.map +1 -1
- package/dist/strategies/direct-execution-strategy.js +38 -4
- package/dist/strategies/direct-execution-strategy.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/aiProfileModelFormat.d.ts +9 -0
- package/dist/utils/aiProfileModelFormat.d.ts.map +1 -0
- package/dist/utils/aiProfileModelFormat.js +93 -0
- package/dist/utils/aiProfileModelFormat.js.map +1 -0
- package/dist/utils/resolveAiProfileModel.d.ts +1 -6
- package/dist/utils/resolveAiProfileModel.d.ts.map +1 -1
- package/dist/utils/resolveAiProfileModel.js +11 -108
- package/dist/utils/resolveAiProfileModel.js.map +1 -1
- package/documenations/upstream-feature-requests/logxer-failure-classification-and-causal-diagnostics.md +403 -0
- package/package.json +2 -2
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# `@x12i/logxer` — failure classification, causal diagnostics, and provider-route observability
|
|
2
|
+
|
|
3
|
+
Status: open
|
|
4
|
+
Owner: `@x12i/logxer`
|
|
5
|
+
Filed by: `@exellix/ai-tasks` (8.x+)
|
|
6
|
+
Context: graph-engine `TASK_RUN_FAILED` investigation — wrapper errors hid root causes (provider auth, prompt render, content registry). ai-tasks added client-side workarounds; logxer should own the contract.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
When orchestration layers wrap failures (`TASK_RUN_FAILED: <skillKey>`, empty `parsed`, schema validation), operators need logs that answer:
|
|
13
|
+
|
|
14
|
+
1. Is **this line** the root **cause** or a downstream **symptom**?
|
|
15
|
+
2. If symptom — **what event / log / record** should I inspect next?a
|
|
16
|
+
3. For LLM failures — **which adapter/route** was intended (`openai-direct` vs `openrouter`, model id, likely env keys)?
|
|
17
|
+
|
|
18
|
+
Today logxer supports `errorCode` / `warnCode`, `diagnostics.summary`, and `evidence[]` via `fieldEvidence`. That works, but every consumer re-implements classification, causal linking, and provider-route shaping — and typed `LogDiagnostics` is too narrow for structured failure payloads.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Lessons learned (from `@exellix/ai-tasks` + graph-engine)
|
|
23
|
+
|
|
24
|
+
| Observation | Impact |
|
|
25
|
+
|-------------|--------|
|
|
26
|
+
| Graph-engine throws `TASK_RUN_FAILED: <skillKey>` while the real message lives in `res.error.message`, Activix, or ai-tasks logs | Console shows **symptom only** |
|
|
27
|
+
| `runTaskDiagnostics.level: basic` hides gateway/provider detail | Operators cannot see OpenAI vs OpenRouter without trace mode |
|
|
28
|
+
| Fast failures (~300ms) on MAIN often mean pre-LLM causes (auth, content miss, empty prompt) | Duration + phase are useful classification signals |
|
|
29
|
+
| `LogDiagnostics` currently accepts `{ summary }` only | Packages push structured data into `evidence[]` strings — hard to query |
|
|
30
|
+
| Same failure produces logs in ai-tasks, ai-skills, gateway, graph-engine, Activix | No standard **causal link** between symptom and cause entries |
|
|
31
|
+
| Each package would duplicate `FailureRole` / `FailureEvent` types | Needs a shared logxer contract |
|
|
32
|
+
|
|
33
|
+
ai-tasks interim workaround (until logxer ships): `classifyRunTaskFailure`, `RunTaskExecutionError`, `failureClassification` on errors, `fieldEvidence("failureRole", …)` on `RUN_TASK_EXECUTION_FAILED`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## FR-1 — First-class `failureClassification` on coded diagnostics
|
|
38
|
+
|
|
39
|
+
### Problem
|
|
40
|
+
|
|
41
|
+
Consumers encode cause/symptom as ad-hoc evidence strings (`failureRole`, `failureEvent`, `failurePointsTo`). UIs and Mongo queries cannot rely on a stable schema.
|
|
42
|
+
|
|
43
|
+
### Proposed API
|
|
44
|
+
|
|
45
|
+
Extend coded diagnostic meta (`errorCode` / `warnCode` payload) with optional:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
type FailureRole = "cause" | "symptom" | "unknown";
|
|
49
|
+
|
|
50
|
+
type FailureClassification = {
|
|
51
|
+
role: FailureRole;
|
|
52
|
+
/** Stable machine id, e.g. "provider_auth", "graph_engine_task_run_wrapper" */
|
|
53
|
+
event: string;
|
|
54
|
+
/** When role === "symptom": event id(s) or operator hint for next lookup */
|
|
55
|
+
pointsTo?: string | string[];
|
|
56
|
+
note: string;
|
|
57
|
+
confidence: "high" | "medium" | "low";
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
type CodedDiagnosticMeta = {
|
|
61
|
+
source?: string;
|
|
62
|
+
debugKind?: DebugLogAbstract;
|
|
63
|
+
diagnostics?: LogDiagnostics; // see FR-2
|
|
64
|
+
evidence?: EvidenceEntry[];
|
|
65
|
+
failureClassification?: FailureClassification;
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Optional helper:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
logxer.errorCode("RUN_TASK_EXECUTION_FAILED", {
|
|
73
|
+
diagnostics: { summary: "…" },
|
|
74
|
+
failureClassification: {
|
|
75
|
+
role: "cause",
|
|
76
|
+
event: "prompt_template_empty",
|
|
77
|
+
note: "Prompt template resolved to empty text",
|
|
78
|
+
confidence: "high",
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Acceptance
|
|
84
|
+
|
|
85
|
+
- Serialized log records include `failureClassification` at a stable JSON path.
|
|
86
|
+
- `getJobLogs({ filter: { failureRole: "symptom" } })` works (see FR-4).
|
|
87
|
+
- Packages may omit it; logxer does not require catalog entries to define classification.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## FR-2 — Expand `LogDiagnostics` for structured failure detail (not summary-only)
|
|
92
|
+
|
|
93
|
+
### Problem
|
|
94
|
+
|
|
95
|
+
TypeScript consumers hit `Object literal may only specify known properties` when adding `phase`, `llmRoute`, `rootError`, etc. under `diagnostics`. Workaround: flatten everything into `evidence[]` — loses type safety and queryability.
|
|
96
|
+
|
|
97
|
+
### Proposed shape
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
type LogDiagnostics = {
|
|
101
|
+
/** Human one-liner (required for coded diagnostics) */
|
|
102
|
+
summary: string;
|
|
103
|
+
/** Optional structured detail bag — validated as JSON-serializable */
|
|
104
|
+
detail?: Record<string, unknown>;
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Recommended **documented** keys in `detail` (not enforced by logxer, but listed in docs):
|
|
109
|
+
|
|
110
|
+
| Key | Purpose |
|
|
111
|
+
|-----|---------|
|
|
112
|
+
| `phase` | Orchestration phase (`main_skill`, `pipeline_pre`, …) |
|
|
113
|
+
| `stage` | Finer step id (`main-skill`, `pre-synthesis-markdown`, …) |
|
|
114
|
+
| `rootError` | `{ name, message, code?, stack? }` — underlying error |
|
|
115
|
+
| `llmRoute` | See FR-3 |
|
|
116
|
+
| `durationMs` | Call latency |
|
|
117
|
+
| `skillKey`, `graphId`, `nodeId`, `jobId`, `taskId` | Correlation |
|
|
118
|
+
|
|
119
|
+
### Acceptance
|
|
120
|
+
|
|
121
|
+
- `diagnostics.detail` round-trips through runtime capture and `getJobLogs`.
|
|
122
|
+
- Catalog linter allows optional `detailSchema` per diagnostic code (JSON Schema ref).
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## FR-3 — Standard `llmRoute` facet for provider / adapter observability
|
|
127
|
+
|
|
128
|
+
### Problem
|
|
129
|
+
|
|
130
|
+
Operators could not tell whether a run intended **OpenAI direct** (`openai/gpt-4.1` → `OPENAI_API_KEY`) vs **OpenRouter** (`openrouter/...` → `OPEN_ROUTER_KEY`). Gateway routing echo (`routing.provider`) arrives only in trace mode.
|
|
131
|
+
|
|
132
|
+
### Proposed documented type (in logxer docs + optional TS export)
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
type LlmRouteDiagnostics = {
|
|
136
|
+
rawModel?: string;
|
|
137
|
+
providerPrefix?: string;
|
|
138
|
+
modelId?: string;
|
|
139
|
+
adapterHint?: "openrouter" | "openai-direct" | "anthropic-direct" | "google-direct" | "groq-direct" | "unknown" | "unset";
|
|
140
|
+
likelyEnvKeys?: string[];
|
|
141
|
+
routingNote?: string;
|
|
142
|
+
/** When gateway returned routing diagnostics */
|
|
143
|
+
actualRouting?: Record<string, unknown>;
|
|
144
|
+
};
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Optional helper:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { inferLlmRouteFromModel } from "@x12i/logxer/diagnostics"; // or subpath
|
|
151
|
+
|
|
152
|
+
const llmRoute = inferLlmRouteFromModel("openai/gpt-4.1");
|
|
153
|
+
logxer.errorCode("PROVIDER_INVOKE_FAILED", {
|
|
154
|
+
diagnostics: { summary: "…", detail: { llmRoute } },
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
logxer **does not** call providers — it only standardizes the shape and helper for prefix → adapter → env-key hints.
|
|
159
|
+
|
|
160
|
+
### Acceptance
|
|
161
|
+
|
|
162
|
+
- Documented in logxer README.
|
|
163
|
+
- `getJobLogs({ filter: { "detail.llmRoute.adapterHint": "openai-direct" } })` (see FR-4).
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## FR-4 — Query / filter coded diagnostics by classification and route
|
|
168
|
+
|
|
169
|
+
### Problem
|
|
170
|
+
|
|
171
|
+
`getAiTasksJobLogs` / in-process job log viewers cannot answer: “show me **symptoms** for this graph run” or “show failures where `adapterHint=openai-direct`”.
|
|
172
|
+
|
|
173
|
+
### Proposed API
|
|
174
|
+
|
|
175
|
+
Extend `GetJobLogsInput.filter`:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
type GetJobLogsFilter = {
|
|
179
|
+
jobId?: string;
|
|
180
|
+
taskId?: string;
|
|
181
|
+
correlationId?: string;
|
|
182
|
+
code?: string;
|
|
183
|
+
level?: LogLevel;
|
|
184
|
+
failureRole?: FailureRole;
|
|
185
|
+
failureEvent?: string;
|
|
186
|
+
/** Dot-path equality on diagnostics.detail, e.g. detail.llmRoute.adapterHint */
|
|
187
|
+
detail?: Record<string, string | number | boolean>;
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Acceptance
|
|
192
|
+
|
|
193
|
+
- Filters compose (AND).
|
|
194
|
+
- Document performance note: in-process ring buffer only unless host persists logs.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## FR-5 — Causal linking between related diagnostic entries
|
|
199
|
+
|
|
200
|
+
### Problem
|
|
201
|
+
|
|
202
|
+
One user-visible failure produces multiple log lines (graph-engine symptom, ai-tasks cause, gateway error). No standard link.
|
|
203
|
+
|
|
204
|
+
### Proposed fields on coded meta
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
type CausalLink = {
|
|
208
|
+
/** Log entry id of the diagnostic this entry explains or wraps */
|
|
209
|
+
causedByLogId?: string;
|
|
210
|
+
/** Log entry ids this entry supersedes or clarifies */
|
|
211
|
+
relatedLogIds?: string[];
|
|
212
|
+
/** Stable upstream error code/name if known */
|
|
213
|
+
rootCode?: string;
|
|
214
|
+
rootMessage?: string;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
type CodedDiagnosticMeta = {
|
|
218
|
+
// …existing
|
|
219
|
+
causal?: CausalLink;
|
|
220
|
+
};
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Optional: when `failureClassification.role === "symptom"`, logxer **warns in dev** if `causal.rootMessage` is missing.
|
|
224
|
+
|
|
225
|
+
### Acceptance
|
|
226
|
+
|
|
227
|
+
- Job log viewer can render symptom → cause chain.
|
|
228
|
+
- Activix / graph-engine hosts can pass `causal.rootMessage` from wrapped errors without re-logging full stacks.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## FR-6 — Catalog entries declare default classification hints
|
|
233
|
+
|
|
234
|
+
### Problem
|
|
235
|
+
|
|
236
|
+
`.metadata/log-diagnostics.json` describes codes but not whether a code is typically cause or symptom.
|
|
237
|
+
|
|
238
|
+
### Proposed catalog extension (optional per entry)
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"RUN_TASK_EXECUTION_FAILED": {
|
|
243
|
+
"level": "error",
|
|
244
|
+
"summaryTemplate": "runTask failed",
|
|
245
|
+
"defaultClassification": {
|
|
246
|
+
"role": "cause",
|
|
247
|
+
"event": "provider_invoke"
|
|
248
|
+
},
|
|
249
|
+
"symptomExamples": ["graph_engine_task_run_wrapper"]
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
logxer does **not** auto-classify from catalog — catalog is documentation + lint hints for package authors.
|
|
255
|
+
|
|
256
|
+
### Acceptance
|
|
257
|
+
|
|
258
|
+
- Catalog linter validates `defaultClassification.role` enum.
|
|
259
|
+
- `logxer validate-catalog` reports entries missing classification docs for `error`-level codes.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## FR-7 — `fieldEvidence` helpers for causal and route facets
|
|
264
|
+
|
|
265
|
+
### Problem
|
|
266
|
+
|
|
267
|
+
Repeated boilerplate:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
fieldEvidence("failureRole", "symptom"),
|
|
271
|
+
fieldEvidence("adapterHint", "openai-direct"),
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Proposed helpers
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
fieldEvidenceFailureClassification(c: FailureClassification): EvidenceEntry[];
|
|
278
|
+
fieldEvidenceLlmRoute(route: LlmRouteDiagnostics): EvidenceEntry[];
|
|
279
|
+
fieldEvidenceRootError(err: { name: string; message: string; code?: string }): EvidenceEntry[];
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
These should produce **consistent field names** matching FR-1/FR-3 JSON paths so evidence aligns with structured fields when both are present.
|
|
283
|
+
|
|
284
|
+
### Acceptance
|
|
285
|
+
|
|
286
|
+
- Exported from `@x12i/logxer`.
|
|
287
|
+
- ai-tasks can delete duplicate evidence assembly once adopted.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## FR-8 — Symptom deduplication / downgrade when cause already logged
|
|
292
|
+
|
|
293
|
+
### Problem
|
|
294
|
+
|
|
295
|
+
Graph-engine logs `TASK_RUN_FAILED` **after** ai-tasks already logged the root cause — noisy consoles, wrong “primary” error.
|
|
296
|
+
|
|
297
|
+
### Proposed behavior (opt-in per host)
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
createLogxer(config, {
|
|
301
|
+
causalLogging?: {
|
|
302
|
+
/** If a cause with same correlationId + rootMessage was logged in-window, emit symptom as debug/warn instead of error */
|
|
303
|
+
downgradeDuplicateSymptoms?: boolean;
|
|
304
|
+
windowMs?: number;
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Heuristic (logxer-side, best-effort):
|
|
310
|
+
|
|
311
|
+
- Same `jobId`/`taskId`/`correlationId`
|
|
312
|
+
- New entry has `failureClassification.role === "symptom"`
|
|
313
|
+
- Recent entry has `role === "cause"` and matching `rootMessage` or `causal.rootCode`
|
|
314
|
+
|
|
315
|
+
### Acceptance
|
|
316
|
+
|
|
317
|
+
- Off by default (no behavior change).
|
|
318
|
+
- When enabled, graph-engine wrapper lines can downgrade without losing data.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## FR-9 — Preserve wrapped-error context in coded diagnostics
|
|
323
|
+
|
|
324
|
+
### Problem
|
|
325
|
+
|
|
326
|
+
Hosts catch errors and return `{ ok: false, error: { message } }` — stack and `cause` chain lost in logs unless manually copied.
|
|
327
|
+
|
|
328
|
+
### Proposed helper
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
extractErrorDiagnostics(error: unknown): {
|
|
332
|
+
rootError: { name: string; message: string; code?: string; stack?: string };
|
|
333
|
+
failureClassification?: FailureClassification; // if present on error
|
|
334
|
+
llmRoute?: LlmRouteDiagnostics;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
logxer.errorFromCaught("TASK_RUN_FAILED", error, { correlation: { jobId, taskId } });
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Walks `Error.cause`, reads `failureClassification` / `details` / `observation` when present (duck-typed), classifies if absent.
|
|
341
|
+
|
|
342
|
+
### Acceptance
|
|
343
|
+
|
|
344
|
+
- Safe on non-Error throws.
|
|
345
|
+
- Does not mutate the original error.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## FR-10 — Cross-package `DebugLogAbstract` value for causal traces
|
|
350
|
+
|
|
351
|
+
### Problem
|
|
352
|
+
|
|
353
|
+
ai-tasks uses `DebugLogAbstract.TRACE` for failure logs; graph-engine may use different kinds. Hard to filter “actionable failure diagnostics” vs noise.
|
|
354
|
+
|
|
355
|
+
### Proposed enum addition
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
enum DebugLogAbstract {
|
|
359
|
+
// existing…
|
|
360
|
+
/** Actionable failure: includes classification and/or rootError */
|
|
361
|
+
FAILURE = "failure",
|
|
362
|
+
/** Wrapper/surface signal — prefer linked cause entry */
|
|
363
|
+
FAILURE_SYMPTOM = "failure_symptom",
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Document mapping: packages should set `debugKind: FAILURE` for cause, `FAILURE_SYMPTOM` for wrappers when classification is known.
|
|
368
|
+
|
|
369
|
+
### Acceptance
|
|
370
|
+
|
|
371
|
+
- Backward compatible (new enum values).
|
|
372
|
+
- Documented in logxer migration notes.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Suggested implementation order
|
|
377
|
+
|
|
378
|
+
| Priority | FR | Rationale |
|
|
379
|
+
|----------|-----|-----------|
|
|
380
|
+
| P0 | FR-1, FR-2 | Structured classification + detail bag — unlocks everything else |
|
|
381
|
+
| P0 | FR-3 | Provider/route visibility was the main blind spot |
|
|
382
|
+
| P1 | FR-4, FR-7 | Query + helpers — reduces consumer boilerplate |
|
|
383
|
+
| P1 | FR-5, FR-9 | Causal linking across graph-engine ↔ ai-tasks ↔ gateway |
|
|
384
|
+
| P2 | FR-6, FR-8, FR-10 | Catalog, dedup, debugKind polish |
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Consumer migration (`@exellix/ai-tasks`)
|
|
389
|
+
|
|
390
|
+
When logxer ships FR-1–3:
|
|
391
|
+
|
|
392
|
+
1. Replace `fieldEvidence("failureRole", …)` with `failureClassification` + `fieldEvidenceFailureClassification`.
|
|
393
|
+
2. Move `llmRoute` from custom types to `@x12i/logxer` export; keep ai-tasks re-export for one major version.
|
|
394
|
+
3. Pass `causal.rootMessage` from `RunTaskExecutionError` into graph-engine host adapters.
|
|
395
|
+
4. Delete `src/observability/classifyRunTaskFailure.ts` only if logxer ships equivalent + re-export (or keep as thin wrapper).
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## References (ai-tasks)
|
|
400
|
+
|
|
401
|
+
- Interim implementation: `src/observability/classifyRunTaskFailure.ts`, `src/errors/runTaskExecutionError.ts`, `src/observability/logRunTaskFailure.ts`, `src/observability/llmRouteContext.ts`
|
|
402
|
+
- Diagnostic code: `RUN_TASK_EXECUTION_FAILED` in `src/logxer/aiTasksDiagnosticCodes.ts`
|
|
403
|
+
- Related graph-engine behavior: `RealTasksClient` catch → `{ ok: false, error }`; runtime throw `TASK_RUN_FAILED: ${skillKey}`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exellix/ai-tasks",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"description": "Task orchestration for the Exellix stack: runTask() with local handlers or LLM-backed execution, task-scoped memory/context enrichment, and executor dispatch via @exellix/ai-skills. ERC-compliant.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dev": "ts-node src/index.ts",
|
|
23
23
|
"prepublishOnly": "npm run build && node scripts/ensure-nx-content-md-variants.mjs",
|
|
24
24
|
"deps:latest": "npx npm-check-updates -u && npm install",
|
|
25
|
-
"test": "node scripts/ensure-xynthesis-dist.mjs && node scripts/clean-dist-test.mjs && tsc -p tsconfig.test.json && node scripts/copy-test-fixtures.mjs && node --test --test-force-exit --test-concurrency=1 dist-test/test/narrix/*.js dist-test/test/narrix-then-execute/*.js dist-test/test/aiScoping/*.js dist-test/test/intermediateSteps/*.js dist-test/test/post-steps/*.js dist-test/test/planWebScopeQuestions/*.js dist-test/test/synthesis/*.js dist-test/test/utils/*.js dist-test/test/errors/*.js dist-test/test/validation/*.js dist-test/test/compile/*.js dist-test/test/task-strategies/*.js dist-test/test/observability/*.js dist-test/test/run-task/*.js dist-test/test/internal/*.js dist-test/test/execution-strategies/*.js",
|
|
25
|
+
"test": "node scripts/ensure-xynthesis-dist.mjs && node scripts/clean-dist-test.mjs && tsc -p tsconfig.test.json && node scripts/copy-test-fixtures.mjs && node --test --test-force-exit --test-concurrency=1 dist-test/test/narrix/*.js dist-test/test/narrix-then-execute/*.js dist-test/test/aiScoping/*.js dist-test/test/intermediateSteps/*.js dist-test/test/post-steps/*.js dist-test/test/planWebScopeQuestions/*.js dist-test/test/synthesis/*.js dist-test/test/utils/*.js dist-test/test/errors/*.js dist-test/test/validation/*.js dist-test/test/compile/*.js dist-test/test/task-strategies/*.js dist-test/test/observability/*.js dist-test/test/run-task/*.js dist-test/test/internal/*.js dist-test/test/execution-strategies/*.js dist-test/test/invocation/*.js",
|
|
26
26
|
"test:with-narrix-ingest": "node scripts/run-npm-test-with-narrix-ingest.mjs",
|
|
27
27
|
"test:e2e:intermediateSteps": "node scripts/run-with-env.mjs RUN_INTERMEDIATE_STEPS_E2E=1 npm run test",
|
|
28
28
|
"test:e2e:synthesis": "node scripts/run-synthesis-e2e.mjs",
|