@kweaver-ai/kweaver-sdk 0.7.4 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +39 -5
  2. package/README.zh.md +37 -5
  3. package/dist/agent-providers/index.d.ts +7 -0
  4. package/dist/agent-providers/index.js +5 -0
  5. package/dist/agent-providers/prompt-template.d.ts +62 -0
  6. package/dist/agent-providers/prompt-template.js +105 -0
  7. package/dist/agent-providers/prompts/rubric-judge-v1.prompt.md +51 -0
  8. package/dist/agent-providers/prompts/within-trace-synthesizer-v1.prompt.md +60 -0
  9. package/dist/agent-providers/providers/claude-code-subprocess.d.ts +74 -0
  10. package/dist/agent-providers/providers/claude-code-subprocess.js +259 -0
  11. package/dist/agent-providers/providers/stub.d.ts +47 -0
  12. package/dist/agent-providers/providers/stub.js +77 -0
  13. package/dist/agent-providers/registry.d.ts +45 -0
  14. package/dist/agent-providers/registry.js +77 -0
  15. package/dist/agent-providers/types.d.ts +91 -0
  16. package/dist/agent-providers/types.js +25 -0
  17. package/dist/api/agent-chat.js +8 -6
  18. package/dist/api/agent-observability.d.ts +51 -0
  19. package/dist/api/agent-observability.js +108 -0
  20. package/dist/api/context-loader.d.ts +1 -0
  21. package/dist/api/conversations.d.ts +4 -8
  22. package/dist/api/conversations.js +16 -58
  23. package/dist/api/datasources.d.ts +2 -20
  24. package/dist/api/datasources.js +7 -123
  25. package/dist/api/semantic-search.d.ts +5 -0
  26. package/dist/api/semantic-search.js +5 -0
  27. package/dist/api/skills.d.ts +75 -2
  28. package/dist/api/skills.js +108 -12
  29. package/dist/api/trace.d.ts +49 -0
  30. package/dist/api/trace.js +85 -0
  31. package/dist/api/vega.d.ts +53 -0
  32. package/dist/api/vega.js +144 -0
  33. package/dist/cli.js +12 -5
  34. package/dist/commands/agent/mode.d.ts +6 -0
  35. package/dist/commands/agent/mode.js +75 -0
  36. package/dist/commands/agent.js +101 -29
  37. package/dist/commands/bkn-ops.js +12 -6
  38. package/dist/commands/bkn-utils.d.ts +9 -0
  39. package/dist/commands/bkn-utils.js +17 -0
  40. package/dist/commands/context-loader.js +608 -38
  41. package/dist/commands/ds.js +7 -2
  42. package/dist/commands/skill.d.ts +21 -1
  43. package/dist/commands/skill.js +389 -1
  44. package/dist/commands/trace.d.ts +39 -0
  45. package/dist/commands/trace.js +668 -0
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.js +1 -1
  48. package/dist/resources/bkn.d.ts +5 -0
  49. package/dist/resources/bkn.js +5 -0
  50. package/dist/resources/datasources.js +2 -1
  51. package/dist/resources/skills.d.ts +17 -1
  52. package/dist/resources/skills.js +32 -1
  53. package/dist/trace-ai/diagnose/agent-binding.d.ts +67 -0
  54. package/dist/trace-ai/diagnose/agent-binding.js +257 -0
  55. package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.d.ts +2 -0
  56. package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.js +15 -0
  57. package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.yaml +16 -0
  58. package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.d.ts +2 -0
  59. package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.js +44 -0
  60. package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.yaml +15 -0
  61. package/dist/trace-ai/diagnose/builtin-rules/register.d.ts +1 -0
  62. package/dist/trace-ai/diagnose/builtin-rules/register.js +11 -0
  63. package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.d.ts +2 -0
  64. package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.js +29 -0
  65. package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.yaml +15 -0
  66. package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.d.ts +2 -0
  67. package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.js +45 -0
  68. package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.yaml +15 -0
  69. package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.d.ts +2 -0
  70. package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.js +38 -0
  71. package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.yaml +16 -0
  72. package/dist/trace-ai/diagnose/builtin-rules/tool-retry-intent-mismatch.yaml +68 -0
  73. package/dist/trace-ai/diagnose/index.d.ts +32 -0
  74. package/dist/trace-ai/diagnose/index.js +246 -0
  75. package/dist/trace-ai/diagnose/output-schema-converter.d.ts +24 -0
  76. package/dist/trace-ai/diagnose/output-schema-converter.js +81 -0
  77. package/dist/trace-ai/diagnose/predicate-registry.d.ts +7 -0
  78. package/dist/trace-ai/diagnose/predicate-registry.js +30 -0
  79. package/dist/trace-ai/diagnose/query-extractor.d.ts +14 -0
  80. package/dist/trace-ai/diagnose/query-extractor.js +45 -0
  81. package/dist/trace-ai/diagnose/report-assembler.d.ts +31 -0
  82. package/dist/trace-ai/diagnose/report-assembler.js +100 -0
  83. package/dist/trace-ai/diagnose/report-markdown.d.ts +18 -0
  84. package/dist/trace-ai/diagnose/report-markdown.js +192 -0
  85. package/dist/trace-ai/diagnose/rule-loader.d.ts +11 -0
  86. package/dist/trace-ai/diagnose/rule-loader.js +120 -0
  87. package/dist/trace-ai/diagnose/schemas.d.ts +184 -0
  88. package/dist/trace-ai/diagnose/schemas.js +154 -0
  89. package/dist/trace-ai/diagnose/signal-probe.d.ts +17 -0
  90. package/dist/trace-ai/diagnose/signal-probe.js +39 -0
  91. package/dist/trace-ai/diagnose/synthesizer-agent.d.ts +40 -0
  92. package/dist/trace-ai/diagnose/synthesizer-agent.js +158 -0
  93. package/dist/trace-ai/diagnose/synthesizer-template.d.ts +2 -0
  94. package/dist/trace-ai/diagnose/synthesizer-template.js +49 -0
  95. package/dist/trace-ai/diagnose/trace-shaper.d.ts +3 -0
  96. package/dist/trace-ai/diagnose/trace-shaper.js +73 -0
  97. package/dist/trace-ai/diagnose/types.d.ts +173 -0
  98. package/dist/trace-ai/diagnose/types.js +1 -0
  99. package/dist/trace-ai/eval-set/assertion-evaluator.d.ts +29 -0
  100. package/dist/trace-ai/eval-set/assertion-evaluator.js +100 -0
  101. package/dist/trace-ai/eval-set/builder.d.ts +36 -0
  102. package/dist/trace-ai/eval-set/builder.js +126 -0
  103. package/dist/trace-ai/eval-set/index.d.ts +15 -0
  104. package/dist/trace-ai/eval-set/index.js +10 -0
  105. package/dist/trace-ai/eval-set/output-writer.d.ts +27 -0
  106. package/dist/trace-ai/eval-set/output-writer.js +126 -0
  107. package/dist/trace-ai/eval-set/query-picker.d.ts +37 -0
  108. package/dist/trace-ai/eval-set/query-picker.js +147 -0
  109. package/dist/trace-ai/eval-set/redactor.d.ts +42 -0
  110. package/dist/trace-ai/eval-set/redactor.js +133 -0
  111. package/dist/trace-ai/eval-set/rubric-templates/answer-match-reference.prompt.md +19 -0
  112. package/dist/trace-ai/eval-set/schemas.d.ts +136 -0
  113. package/dist/trace-ai/eval-set/schemas.js +130 -0
  114. package/dist/trace-ai/eval-set/semantic-match-provider.d.ts +33 -0
  115. package/dist/trace-ai/eval-set/semantic-match-provider.js +51 -0
  116. package/dist/trace-ai/eval-set/test-runner.d.ts +34 -0
  117. package/dist/trace-ai/eval-set/test-runner.js +153 -0
  118. package/dist/trace-ai/eval-set/types.d.ts +46 -0
  119. package/dist/trace-ai/eval-set/types.js +8 -0
  120. package/dist/trace-ai/exp/bundle-writer.d.ts +10 -0
  121. package/dist/trace-ai/exp/bundle-writer.js +54 -0
  122. package/dist/trace-ai/exp/claude-binary.d.ts +5 -0
  123. package/dist/trace-ai/exp/claude-binary.js +30 -0
  124. package/dist/trace-ai/exp/coordinator.d.ts +45 -0
  125. package/dist/trace-ai/exp/coordinator.js +203 -0
  126. package/dist/trace-ai/exp/eval-runner.d.ts +14 -0
  127. package/dist/trace-ai/exp/eval-runner.js +47 -0
  128. package/dist/trace-ai/exp/exp-store/abort-signal.d.ts +3 -0
  129. package/dist/trace-ai/exp/exp-store/abort-signal.js +27 -0
  130. package/dist/trace-ai/exp/exp-store/candidate-lineage-yaml.d.ts +4 -0
  131. package/dist/trace-ai/exp/exp-store/candidate-lineage-yaml.js +37 -0
  132. package/dist/trace-ai/exp/exp-store/events-jsonl.d.ts +17 -0
  133. package/dist/trace-ai/exp/exp-store/events-jsonl.js +60 -0
  134. package/dist/trace-ai/exp/exp-store/exp-registry.d.ts +6 -0
  135. package/dist/trace-ai/exp/exp-store/exp-registry.js +41 -0
  136. package/dist/trace-ai/exp/exp-store/index.d.ts +46 -0
  137. package/dist/trace-ai/exp/exp-store/index.js +59 -0
  138. package/dist/trace-ai/exp/exp-store/lock.d.ts +3 -0
  139. package/dist/trace-ai/exp/exp-store/lock.js +73 -0
  140. package/dist/trace-ai/exp/exp-store/mission-md.d.ts +3 -0
  141. package/dist/trace-ai/exp/exp-store/mission-md.js +37 -0
  142. package/dist/trace-ai/exp/exp-store/readme-template.d.ts +5 -0
  143. package/dist/trace-ai/exp/exp-store/readme-template.js +25 -0
  144. package/dist/trace-ai/exp/exp-store/round-yaml.d.ts +3 -0
  145. package/dist/trace-ai/exp/exp-store/round-yaml.js +33 -0
  146. package/dist/trace-ai/exp/index.d.ts +8 -0
  147. package/dist/trace-ai/exp/index.js +238 -0
  148. package/dist/trace-ai/exp/info.d.ts +35 -0
  149. package/dist/trace-ai/exp/info.js +120 -0
  150. package/dist/trace-ai/exp/patch/agent-config.d.ts +1 -0
  151. package/dist/trace-ai/exp/patch/agent-config.js +26 -0
  152. package/dist/trace-ai/exp/patch/index.d.ts +2 -0
  153. package/dist/trace-ai/exp/patch/index.js +13 -0
  154. package/dist/trace-ai/exp/patch/skill.d.ts +1 -0
  155. package/dist/trace-ai/exp/patch/skill.js +24 -0
  156. package/dist/trace-ai/exp/providers/synthesizer-client.d.ts +14 -0
  157. package/dist/trace-ai/exp/providers/synthesizer-client.js +39 -0
  158. package/dist/trace-ai/exp/providers/triage-client.d.ts +19 -0
  159. package/dist/trace-ai/exp/providers/triage-client.js +51 -0
  160. package/dist/trace-ai/exp/schemas.d.ts +147 -0
  161. package/dist/trace-ai/exp/schemas.js +50 -0
  162. package/dist/trace-ai/exp/scoring.d.ts +2 -0
  163. package/dist/trace-ai/exp/scoring.js +46 -0
  164. package/dist/trace-ai/scan/aggregator.d.ts +20 -0
  165. package/dist/trace-ai/scan/aggregator.js +26 -0
  166. package/dist/trace-ai/scan/artifacts/paths.d.ts +12 -0
  167. package/dist/trace-ai/scan/artifacts/paths.js +18 -0
  168. package/dist/trace-ai/scan/artifacts/writer.d.ts +67 -0
  169. package/dist/trace-ai/scan/artifacts/writer.js +96 -0
  170. package/dist/trace-ai/scan/batched-rubric.d.ts +55 -0
  171. package/dist/trace-ai/scan/batched-rubric.js +159 -0
  172. package/dist/trace-ai/scan/cross-trace-synthesizer.d.ts +24 -0
  173. package/dist/trace-ai/scan/cross-trace-synthesizer.js +93 -0
  174. package/dist/trace-ai/scan/index.d.ts +31 -0
  175. package/dist/trace-ai/scan/index.js +390 -0
  176. package/dist/trace-ai/scan/prompts/builtin/cross-trace-synthesizer-v1.prompt.md +44 -0
  177. package/dist/trace-ai/scan/prompts/builtin/rubric-judge-batch-v1.prompt.md +44 -0
  178. package/dist/trace-ai/scan/runner.d.ts +25 -0
  179. package/dist/trace-ai/scan/runner.js +42 -0
  180. package/dist/trace-ai/scan/sampler.d.ts +18 -0
  181. package/dist/trace-ai/scan/sampler.js +81 -0
  182. package/dist/trace-ai/scan/scan-summary-markdown.d.ts +2 -0
  183. package/dist/trace-ai/scan/scan-summary-markdown.js +71 -0
  184. package/dist/trace-ai/scan/scan-summary-schema.d.ts +73 -0
  185. package/dist/trace-ai/scan/scan-summary-schema.js +61 -0
  186. package/dist/trace-ai/scan/single-agent-validator.d.ts +23 -0
  187. package/dist/trace-ai/scan/single-agent-validator.js +42 -0
  188. package/dist/trace-ai/scan/traces-list-parser.d.ts +15 -0
  189. package/dist/trace-ai/scan/traces-list-parser.js +46 -0
  190. package/package.json +14 -4
@@ -0,0 +1,184 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Rubric input source descriptor. The supported source prefixes are
4
+ * resolved by `diagnose/agent-binding.ts` against the in-memory TraceTree:
5
+ *
6
+ * - `extract_from_root_attr:<dot.path>` → root span attribute by name
7
+ * - `filter_by_kind:[kind1,kind2,...]` → ordered span subset by kind
8
+ * - `literal:<json>` → constant blob (debug / fixtures)
9
+ *
10
+ * Authors describe **which slice of the trace** the agent needs as context;
11
+ * the binding does the actual extraction so rule YAML stays declarative.
12
+ */
13
+ declare const RubricInputSchema: z.ZodObject<{
14
+ kind: z.ZodString;
15
+ source: z.ZodString;
16
+ }, z.core.$strip>;
17
+ declare const RubricSchema: z.ZodObject<{
18
+ judge_question: z.ZodString;
19
+ inputs: z.ZodDefault<z.ZodArray<z.ZodObject<{
20
+ kind: z.ZodString;
21
+ source: z.ZodString;
22
+ }, z.core.$strip>>>;
23
+ output_schema: z.ZodObject<{
24
+ type: z.ZodLiteral<"object">;
25
+ required: z.ZodDefault<z.ZodArray<z.ZodString>>;
26
+ properties: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>;
27
+ }, z.core.$strip>;
28
+ agent_binding: z.ZodObject<{
29
+ provider: z.ZodString;
30
+ prompt_template_ref: z.ZodString;
31
+ }, z.core.$strip>;
32
+ gates_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ }, z.core.$strip>;
34
+ export type RubricYaml = z.infer<typeof RubricSchema>;
35
+ export type RubricInputYaml = z.infer<typeof RubricInputSchema>;
36
+ export declare const RuleSchema: z.ZodObject<{
37
+ schema_version: z.ZodLiteral<"diagnosis-rule/v1">;
38
+ id: z.ZodString;
39
+ severity: z.ZodEnum<{
40
+ low: "low";
41
+ medium: "medium";
42
+ high: "high";
43
+ }>;
44
+ symptom: z.ZodString;
45
+ taxonomy: z.ZodObject<{
46
+ signals_axis: z.ZodEnum<{
47
+ interaction: "interaction";
48
+ execution: "execution";
49
+ environment: "environment";
50
+ }>;
51
+ ms_class: z.ZodEnum<{
52
+ retry_loop: "retry_loop";
53
+ tool_misuse: "tool_misuse";
54
+ context_loss: "context_loss";
55
+ goal_drift: "goal_drift";
56
+ cascading_error: "cascading_error";
57
+ silent_quality_degradation: "silent_quality_degradation";
58
+ }>;
59
+ }, z.core.$strip>;
60
+ suggested_fix: z.ZodObject<{
61
+ target: z.ZodString;
62
+ change_template: z.ZodString;
63
+ }, z.core.$strip>;
64
+ verify_with: z.ZodObject<{
65
+ assertion_templates: z.ZodDefault<z.ZodArray<z.ZodString>>;
66
+ }, z.core.$strip>;
67
+ predicate: z.ZodOptional<z.ZodString>;
68
+ rubric: z.ZodOptional<z.ZodObject<{
69
+ judge_question: z.ZodString;
70
+ inputs: z.ZodDefault<z.ZodArray<z.ZodObject<{
71
+ kind: z.ZodString;
72
+ source: z.ZodString;
73
+ }, z.core.$strip>>>;
74
+ output_schema: z.ZodObject<{
75
+ type: z.ZodLiteral<"object">;
76
+ required: z.ZodDefault<z.ZodArray<z.ZodString>>;
77
+ properties: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>;
78
+ }, z.core.$strip>;
79
+ agent_binding: z.ZodObject<{
80
+ provider: z.ZodString;
81
+ prompt_template_ref: z.ZodString;
82
+ }, z.core.$strip>;
83
+ gates_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
84
+ }, z.core.$strip>>;
85
+ params: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
86
+ }, z.core.$strip>;
87
+ export type RuleYaml = z.infer<typeof RuleSchema>;
88
+ export declare const ReportSchema: z.ZodObject<{
89
+ schema_version: z.ZodLiteral<"trace-diagnose-report/v1">;
90
+ trace: z.ZodObject<{
91
+ trace_id: z.ZodString;
92
+ agent_id: z.ZodNullable<z.ZodString>;
93
+ tenant: z.ZodNullable<z.ZodString>;
94
+ }, z.core.$strip>;
95
+ run: z.ZodObject<{
96
+ diagnosed_at: z.ZodString;
97
+ cli_version: z.ZodString;
98
+ mode: z.ZodEnum<{
99
+ "symbolic-only": "symbolic-only";
100
+ "rubric-only": "rubric-only";
101
+ hybrid: "hybrid";
102
+ }>;
103
+ rules_applied: z.ZodArray<z.ZodString>;
104
+ rules_skipped: z.ZodArray<z.ZodObject<{
105
+ rule_id: z.ZodString;
106
+ reason: z.ZodString;
107
+ }, z.core.$strip>>;
108
+ synthesizer_mode: z.ZodEnum<{
109
+ agent: "agent";
110
+ template: "template";
111
+ }>;
112
+ }, z.core.$strip>;
113
+ summary: z.ZodObject<{
114
+ headline: z.ZodString;
115
+ primary_root_cause: z.ZodNullable<z.ZodObject<{
116
+ finding_ids: z.ZodArray<z.ZodNumber>;
117
+ description: z.ZodString;
118
+ target_for_fix: z.ZodString;
119
+ }, z.core.$strip>>;
120
+ fix_priority: z.ZodArray<z.ZodObject<{
121
+ finding_id: z.ZodNumber;
122
+ reason: z.ZodString;
123
+ }, z.core.$strip>>;
124
+ cross_finding_links: z.ZodArray<z.ZodObject<{
125
+ finding_ids: z.ZodArray<z.ZodNumber>;
126
+ relation: z.ZodString;
127
+ }, z.core.$strip>>;
128
+ }, z.core.$strip>;
129
+ findings: z.ZodArray<z.ZodObject<{
130
+ rule_id: z.ZodString;
131
+ judgment_kind: z.ZodEnum<{
132
+ symbolic: "symbolic";
133
+ rubric: "rubric";
134
+ }>;
135
+ severity: z.ZodEnum<{
136
+ low: "low";
137
+ medium: "medium";
138
+ high: "high";
139
+ }>;
140
+ symptom: z.ZodString;
141
+ likely_cause: z.ZodString;
142
+ evidence: z.ZodObject<{
143
+ spans: z.ZodArray<z.ZodString>;
144
+ excerpt: z.ZodString;
145
+ }, z.core.$strip>;
146
+ suggested_fix: z.ZodObject<{
147
+ target: z.ZodString;
148
+ change: z.ZodString;
149
+ }, z.core.$strip>;
150
+ confidence: z.ZodEnum<{
151
+ low: "low";
152
+ medium: "medium";
153
+ high: "high";
154
+ }>;
155
+ verify_with: z.ZodObject<{
156
+ suggested_eval_case: z.ZodObject<{
157
+ query_id: z.ZodNullable<z.ZodString>;
158
+ query: z.ZodNullable<z.ZodString>;
159
+ assertions: z.ZodArray<z.ZodString>;
160
+ }, z.core.$strip>;
161
+ }, z.core.$strip>;
162
+ }, z.core.$strip>>;
163
+ }, z.core.$strip>;
164
+ export type ReportYaml = z.infer<typeof ReportSchema>;
165
+ /** The Summary section in isolation — exported so the agent synthesizer
166
+ * can validate its LLM output against the same shape the report uses. */
167
+ export declare const SummaryOutputSchema: z.ZodObject<{
168
+ headline: z.ZodString;
169
+ primary_root_cause: z.ZodNullable<z.ZodObject<{
170
+ finding_ids: z.ZodArray<z.ZodNumber>;
171
+ description: z.ZodString;
172
+ target_for_fix: z.ZodString;
173
+ }, z.core.$strip>>;
174
+ fix_priority: z.ZodArray<z.ZodObject<{
175
+ finding_id: z.ZodNumber;
176
+ reason: z.ZodString;
177
+ }, z.core.$strip>>;
178
+ cross_finding_links: z.ZodArray<z.ZodObject<{
179
+ finding_ids: z.ZodArray<z.ZodNumber>;
180
+ relation: z.ZodString;
181
+ }, z.core.$strip>>;
182
+ }, z.core.$strip>;
183
+ export type SummaryOutput = z.infer<typeof SummaryOutputSchema>;
184
+ export {};
@@ -0,0 +1,154 @@
1
+ import { z } from "zod";
2
+ const TaxonomySchema = z.object({
3
+ signals_axis: z.enum(["interaction", "execution", "environment"]),
4
+ ms_class: z.enum([
5
+ "retry_loop",
6
+ "tool_misuse",
7
+ "context_loss",
8
+ "goal_drift",
9
+ "cascading_error",
10
+ "silent_quality_degradation",
11
+ ]),
12
+ });
13
+ const SuggestedFixSchema = z.object({
14
+ target: z.string().min(1),
15
+ change_template: z.string().min(1),
16
+ });
17
+ const VerifyWithSchema = z.object({
18
+ assertion_templates: z.array(z.string()).default([]),
19
+ });
20
+ /**
21
+ * Rubric input source descriptor. The supported source prefixes are
22
+ * resolved by `diagnose/agent-binding.ts` against the in-memory TraceTree:
23
+ *
24
+ * - `extract_from_root_attr:<dot.path>` → root span attribute by name
25
+ * - `filter_by_kind:[kind1,kind2,...]` → ordered span subset by kind
26
+ * - `literal:<json>` → constant blob (debug / fixtures)
27
+ *
28
+ * Authors describe **which slice of the trace** the agent needs as context;
29
+ * the binding does the actual extraction so rule YAML stays declarative.
30
+ */
31
+ const RubricInputSchema = z.object({
32
+ kind: z.string().min(1),
33
+ source: z.string().min(1),
34
+ });
35
+ /**
36
+ * Minimal JSON-Schema-ish shape we accept for rubric output_schema. We
37
+ * convert to a zod schema at load time (see `output-schema-converter.ts`);
38
+ * keeping this loose here lets authors paste literal JSON Schema without
39
+ * us re-implementing the whole spec — just the subset we need (object
40
+ * with required[] + properties{type,enum,items}).
41
+ */
42
+ const RubricOutputSchemaSchema = z.object({
43
+ type: z.literal("object"),
44
+ required: z.array(z.string()).default([]),
45
+ properties: z.record(z.string(), z.record(z.string(), z.unknown())),
46
+ });
47
+ const AgentBindingSchema = z.object({
48
+ provider: z.string().min(1),
49
+ prompt_template_ref: z.string().regex(/^builtin:[a-zA-Z0-9_-]+$/),
50
+ });
51
+ const RubricSchema = z.object({
52
+ judge_question: z.string().min(1),
53
+ inputs: z.array(RubricInputSchema).default([]),
54
+ output_schema: RubricOutputSchemaSchema,
55
+ agent_binding: AgentBindingSchema,
56
+ /**
57
+ * Optional symbolic rule_ids that act as gate for this rubric in batch mode.
58
+ * Empty/missing → rubric runs on all traces (PR-B fallback). In single-trace
59
+ * mode this field is ignored; rubric always runs.
60
+ */
61
+ gates_on: z.array(z.string()).optional(),
62
+ });
63
+ /**
64
+ * The convergence contract between Stage-1 (symbolic) and Stage-2 (rubric):
65
+ * every rubric verdict MUST emit `first_violating_step_id` so cross-finding
66
+ * links can correlate rubric findings with the spans symbolic rules cite.
67
+ *
68
+ * Enforced as a YAML-load-time check rather than at runtime so authors
69
+ * see the violation in `trace diagnose rules validate <path>`.
70
+ */
71
+ const FIRST_VIOLATING_STEP_ID = "first_violating_step_id";
72
+ export const RuleSchema = z
73
+ .object({
74
+ schema_version: z.literal("diagnosis-rule/v1"),
75
+ id: z.string().regex(/^[a-z][a-z0-9_]*$/),
76
+ severity: z.enum(["low", "medium", "high"]),
77
+ symptom: z.string().min(1),
78
+ taxonomy: TaxonomySchema,
79
+ suggested_fix: SuggestedFixSchema,
80
+ verify_with: VerifyWithSchema,
81
+ predicate: z.string().regex(/^builtin:[a-z][a-z0-9_]*$/).optional(),
82
+ rubric: RubricSchema.optional(),
83
+ params: z.record(z.string(), z.unknown()).default({}),
84
+ })
85
+ .refine((r) => Boolean(r.predicate) !== Boolean(r.rubric), { message: "exactly one of `predicate` or `rubric` must be present" })
86
+ .refine((r) => !r.rubric || r.rubric.output_schema.required.includes(FIRST_VIOLATING_STEP_ID), {
87
+ message: `rubric.output_schema.required must include '${FIRST_VIOLATING_STEP_ID}' (Stage-1↔Stage-2 convergence contract)`,
88
+ path: ["rubric", "output_schema", "required"],
89
+ });
90
+ const FindingSchema = z.object({
91
+ rule_id: z.string(),
92
+ judgment_kind: z.enum(["symbolic", "rubric"]),
93
+ severity: z.enum(["low", "medium", "high"]),
94
+ symptom: z.string(),
95
+ likely_cause: z.string(),
96
+ evidence: z.object({
97
+ spans: z.array(z.string()),
98
+ excerpt: z.string(),
99
+ }),
100
+ suggested_fix: z.object({
101
+ target: z.string(),
102
+ change: z.string(),
103
+ }),
104
+ // Symbolic findings always emit `low` (no semantic basis for higher).
105
+ // Rubric agent supplies its own confidence; rule-loader propagates the
106
+ // value the agent returned in the rubric output. Accept the union.
107
+ confidence: z.enum(["low", "medium", "high"]),
108
+ verify_with: z.object({
109
+ suggested_eval_case: z.object({
110
+ query_id: z.string().nullable(),
111
+ query: z.string().nullable(),
112
+ assertions: z.array(z.string()),
113
+ }),
114
+ }),
115
+ });
116
+ const SummarySchema = z.object({
117
+ headline: z.string().max(160),
118
+ primary_root_cause: z
119
+ .object({
120
+ finding_ids: z.array(z.number().int().nonnegative()).min(1),
121
+ description: z.string(),
122
+ target_for_fix: z.string(),
123
+ })
124
+ .nullable(),
125
+ fix_priority: z.array(z.object({
126
+ finding_id: z.number().int().nonnegative(),
127
+ reason: z.string(),
128
+ })),
129
+ cross_finding_links: z.array(z.object({
130
+ finding_ids: z.array(z.number().int().nonnegative()).min(2),
131
+ relation: z.string(),
132
+ })),
133
+ });
134
+ export const ReportSchema = z.object({
135
+ schema_version: z.literal("trace-diagnose-report/v1"),
136
+ trace: z.object({
137
+ trace_id: z.string(),
138
+ agent_id: z.string().nullable(),
139
+ tenant: z.string().nullable(),
140
+ }),
141
+ run: z.object({
142
+ diagnosed_at: z.string(),
143
+ cli_version: z.string(),
144
+ mode: z.enum(["symbolic-only", "rubric-only", "hybrid"]),
145
+ rules_applied: z.array(z.string()),
146
+ rules_skipped: z.array(z.object({ rule_id: z.string(), reason: z.string() })),
147
+ synthesizer_mode: z.enum(["template", "agent"]),
148
+ }),
149
+ summary: SummarySchema,
150
+ findings: z.array(FindingSchema),
151
+ });
152
+ /** The Summary section in isolation — exported so the agent synthesizer
153
+ * can validate its LLM output against the same shape the report uses. */
154
+ export const SummaryOutputSchema = SummarySchema;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Stage-1 (symbolic) runner. Rubric rules are handled separately in
3
+ * `agent-binding.ts` and merged into the findings list by `index.ts`.
4
+ *
5
+ * Rationale for keeping the split here: symbolic predicates are cheap,
6
+ * deterministic, sync; rubric judgments are slow, non-deterministic,
7
+ * async. Running them in one loop would entangle backpressure,
8
+ * timeout, and retry concerns that only apply to one of the two paths.
9
+ */
10
+ import type { Hit, Rule, TraceTree } from "./types.js";
11
+ export declare class RuleProbeError extends Error {
12
+ constructor(ruleId: string, cause: Error);
13
+ }
14
+ export declare function runRules(rules: Rule[], tree: TraceTree): Promise<Map<string, Hit[]>>;
15
+ /** Helpers that split a rule list by which stage owns them. */
16
+ export declare function symbolicRules(rules: Rule[]): Rule[];
17
+ export declare function rubricRules(rules: Rule[]): Rule[];
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Stage-1 (symbolic) runner. Rubric rules are handled separately in
3
+ * `agent-binding.ts` and merged into the findings list by `index.ts`.
4
+ *
5
+ * Rationale for keeping the split here: symbolic predicates are cheap,
6
+ * deterministic, sync; rubric judgments are slow, non-deterministic,
7
+ * async. Running them in one loop would entangle backpressure,
8
+ * timeout, and retry concerns that only apply to one of the two paths.
9
+ */
10
+ import { resolvePredicate } from "./predicate-registry.js";
11
+ export class RuleProbeError extends Error {
12
+ constructor(ruleId, cause) {
13
+ super(`predicate failed for rule '${ruleId}': ${cause.message}`);
14
+ this.name = "RuleProbeError";
15
+ }
16
+ }
17
+ export async function runRules(rules, tree) {
18
+ const out = new Map();
19
+ for (const rule of rules) {
20
+ if (!rule.predicateRef)
21
+ continue; // rubric rule — handled by agent-binding
22
+ const fn = resolvePredicate(rule.predicateRef);
23
+ try {
24
+ const hits = fn(tree, rule.params);
25
+ out.set(rule.id, hits);
26
+ }
27
+ catch (e) {
28
+ throw new RuleProbeError(rule.id, e);
29
+ }
30
+ }
31
+ return out;
32
+ }
33
+ /** Helpers that split a rule list by which stage owns them. */
34
+ export function symbolicRules(rules) {
35
+ return rules.filter((r) => r.predicateRef !== null);
36
+ }
37
+ export function rubricRules(rules) {
38
+ return rules.filter((r) => r.rubric !== null);
39
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Stage-3 — agent-driven within-trace synthesizer.
3
+ *
4
+ * Takes the N findings produced by Stages 1+2 and asks the LLM to compose
5
+ * a `Summary` (headline + root cause + ordered fix priority + cross-finding
6
+ * links). Falls back to the deterministic `templateSynthesize` if:
7
+ * - findings.length === 0 (no narrative needed)
8
+ * - no provider registered / provider unavailable
9
+ * - the agent invocation fails for any reason (we still want a usable
10
+ * report even when the LLM judge times out)
11
+ *
12
+ * The agent path remains a *narrative* layer — symbolic and rubric findings
13
+ * are already in hand; the synthesizer doesn't fabricate new findings, only
14
+ * organizes the ones it was given. This keeps the contract small and the
15
+ * failure modes containable.
16
+ */
17
+ import type { Finding, Summary } from "./types.js";
18
+ import type { AgentProvider } from "../../agent-providers/types.js";
19
+ import { PromptTemplateRegistry, type AgentOutputLang } from "../../agent-providers/prompt-template.js";
20
+ import type { ArtifactWriter } from "../scan/artifacts/writer.js";
21
+ export interface AgentSynthesizeOpts {
22
+ findings: Finding[];
23
+ traceId: string;
24
+ agentId: string | null;
25
+ provider: AgentProvider | null;
26
+ promptRegistry: PromptTemplateRegistry;
27
+ promptRef?: string;
28
+ timeoutMs?: number;
29
+ /** Output locale for synthesizer prose. Default 'en'. */
30
+ lang?: AgentOutputLang;
31
+ /** When provided, writes Stage-3 prompt/response artifacts. */
32
+ artifacts?: ArtifactWriter;
33
+ }
34
+ export interface AgentSynthesizeResult {
35
+ summary: Summary;
36
+ mode: "agent" | "template";
37
+ /** Reason set when mode === 'template' under a non-default branch. */
38
+ fallbackReason?: string;
39
+ }
40
+ export declare function agentSynthesize(opts: AgentSynthesizeOpts): Promise<AgentSynthesizeResult>;
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Stage-3 — agent-driven within-trace synthesizer.
3
+ *
4
+ * Takes the N findings produced by Stages 1+2 and asks the LLM to compose
5
+ * a `Summary` (headline + root cause + ordered fix priority + cross-finding
6
+ * links). Falls back to the deterministic `templateSynthesize` if:
7
+ * - findings.length === 0 (no narrative needed)
8
+ * - no provider registered / provider unavailable
9
+ * - the agent invocation fails for any reason (we still want a usable
10
+ * report even when the LLM judge times out)
11
+ *
12
+ * The agent path remains a *narrative* layer — symbolic and rubric findings
13
+ * are already in hand; the synthesizer doesn't fabricate new findings, only
14
+ * organizes the ones it was given. This keeps the contract small and the
15
+ * failure modes containable.
16
+ */
17
+ import { AgentProviderError } from "../../agent-providers/types.js";
18
+ import { render as renderPrompt, languageInstructionFor, } from "../../agent-providers/prompt-template.js";
19
+ import { SummaryOutputSchema } from "./schemas.js";
20
+ import { templateSynthesize } from "./synthesizer-template.js";
21
+ /** Map zod-validated agent output (snake_case Summary) → internal camelCase Summary. */
22
+ function toInternalSummary(out) {
23
+ return {
24
+ headline: out.headline,
25
+ primaryRootCause: out.primary_root_cause === null
26
+ ? null
27
+ : {
28
+ findingIds: out.primary_root_cause.finding_ids,
29
+ description: out.primary_root_cause.description,
30
+ targetForFix: out.primary_root_cause.target_for_fix,
31
+ },
32
+ fixPriority: out.fix_priority.map((p) => ({ findingId: p.finding_id, reason: p.reason })),
33
+ crossFindingLinks: out.cross_finding_links.map((l) => ({
34
+ findingIds: l.finding_ids,
35
+ relation: l.relation,
36
+ })),
37
+ };
38
+ }
39
+ /** Snake-case projection of Finding for the prompt — matches the YAML
40
+ * representation users already see, so the model doesn't have to translate. */
41
+ function findingForPrompt(f, idx) {
42
+ return {
43
+ index: idx,
44
+ rule_id: f.ruleId,
45
+ judgment_kind: f.judgmentKind,
46
+ severity: f.severity,
47
+ symptom: f.symptom,
48
+ likely_cause: f.likelyCause,
49
+ evidence_spans: f.evidence.spans,
50
+ excerpt: f.evidence.excerpt,
51
+ suggested_fix_target: f.suggestedFix.target,
52
+ suggested_fix_change: f.suggestedFix.change,
53
+ confidence: f.confidence,
54
+ };
55
+ }
56
+ /**
57
+ * The output_schema rendered into the prompt is a JSON-Schema-ish
58
+ * description of the Summary contract. Authored inline rather than
59
+ * derived from the zod schema to keep the prompt human-readable.
60
+ */
61
+ const SUMMARY_OUTPUT_SCHEMA_DESCRIPTION = {
62
+ type: "object",
63
+ required: ["headline", "primary_root_cause", "fix_priority", "cross_finding_links"],
64
+ properties: {
65
+ headline: { type: "string", maxLength: 160 },
66
+ primary_root_cause: {
67
+ type: "object_or_null",
68
+ required: ["finding_ids", "description", "target_for_fix"],
69
+ properties: {
70
+ finding_ids: { type: "array", items: { type: "integer" } },
71
+ description: { type: "string" },
72
+ target_for_fix: { type: "string" },
73
+ },
74
+ },
75
+ fix_priority: {
76
+ type: "array",
77
+ items: {
78
+ type: "object",
79
+ required: ["finding_id", "reason"],
80
+ properties: { finding_id: { type: "integer" }, reason: { type: "string" } },
81
+ },
82
+ },
83
+ cross_finding_links: {
84
+ type: "array",
85
+ items: {
86
+ type: "object",
87
+ required: ["finding_ids", "relation"],
88
+ properties: {
89
+ finding_ids: { type: "array", items: { type: "integer" }, minItems: 2 },
90
+ relation: { type: "string" },
91
+ },
92
+ },
93
+ },
94
+ },
95
+ };
96
+ export async function agentSynthesize(opts) {
97
+ // Empty findings: no narrative to compose. Both modes produce the same
98
+ // summary here, so default to `template` so reports don't claim the
99
+ // agent ran when it didn't.
100
+ if (opts.findings.length === 0) {
101
+ return { summary: templateSynthesize([]), mode: "template" };
102
+ }
103
+ if (!opts.provider) {
104
+ return {
105
+ summary: templateSynthesize(opts.findings),
106
+ mode: "template",
107
+ fallbackReason: "no-provider-registered",
108
+ };
109
+ }
110
+ const ref = opts.promptRef ?? "builtin:within-trace-synthesizer-v1";
111
+ if (!opts.promptRegistry.has(ref)) {
112
+ return {
113
+ summary: templateSynthesize(opts.findings),
114
+ mode: "template",
115
+ fallbackReason: `prompt-template-missing:${ref}`,
116
+ };
117
+ }
118
+ const tpl = opts.promptRegistry.get(ref);
119
+ const prompt = renderPrompt(tpl, {
120
+ trace_id: opts.traceId,
121
+ agent_id: opts.agentId ?? "<unknown>",
122
+ findings: opts.findings.map((f, i) => findingForPrompt(f, i)),
123
+ output_schema: SUMMARY_OUTPUT_SCHEMA_DESCRIPTION,
124
+ language_instruction: languageInstructionFor(opts.lang ?? "en"),
125
+ });
126
+ try {
127
+ if (!(await opts.provider.isAvailable())) {
128
+ return {
129
+ summary: templateSynthesize(opts.findings),
130
+ mode: "template",
131
+ fallbackReason: `provider-not-available:${opts.provider.name}`,
132
+ };
133
+ }
134
+ if (opts.artifacts) {
135
+ await opts.artifacts.writeStageThreeSynthPrompt(prompt);
136
+ }
137
+ const resp = await opts.provider.invoke({
138
+ prompt,
139
+ outputSchema: SummaryOutputSchema,
140
+ timeoutMs: opts.timeoutMs,
141
+ correlationId: `synthesize:${opts.traceId}`,
142
+ });
143
+ if (opts.artifacts) {
144
+ await opts.artifacts.writeStageThreeSynthResponse(resp.output);
145
+ }
146
+ return { summary: toInternalSummary(resp.output), mode: "agent" };
147
+ }
148
+ catch (e) {
149
+ if (e instanceof AgentProviderError) {
150
+ return {
151
+ summary: templateSynthesize(opts.findings),
152
+ mode: "template",
153
+ fallbackReason: `agent-error:${e.kind}`,
154
+ };
155
+ }
156
+ throw e;
157
+ }
158
+ }
@@ -0,0 +1,2 @@
1
+ import type { Finding, Summary } from "./types.js";
2
+ export declare function templateSynthesize(findings: Finding[]): Summary;
@@ -0,0 +1,49 @@
1
+ const SEVERITY_RANK = { high: 3, medium: 2, low: 1 };
2
+ function overlapRatio(a, b) {
3
+ if (a.length === 0 || b.length === 0)
4
+ return 0;
5
+ const setA = new Set(a);
6
+ const intersect = b.filter((x) => setA.has(x)).length;
7
+ const smaller = Math.min(a.length, b.length);
8
+ return intersect / smaller;
9
+ }
10
+ export function templateSynthesize(findings) {
11
+ if (findings.length === 0) {
12
+ return {
13
+ headline: "No findings",
14
+ primaryRootCause: null,
15
+ fixPriority: [],
16
+ crossFindingLinks: [],
17
+ };
18
+ }
19
+ // Sort indices by severity desc, stable on original index (so same input → same output).
20
+ const indices = findings.map((_, i) => i);
21
+ indices.sort((i, j) => {
22
+ const r = SEVERITY_RANK[findings[j].severity] - SEVERITY_RANK[findings[i].severity];
23
+ return r !== 0 ? r : i - j;
24
+ });
25
+ const topIdx = indices[0];
26
+ const top = findings[topIdx];
27
+ const headline = `see findings[${topIdx}]: ${top.symptom}`;
28
+ const primaryRootCause = {
29
+ findingIds: [topIdx],
30
+ description: `Top-severity finding from rule '${top.ruleId}': ${top.symptom}`,
31
+ targetForFix: top.suggestedFix.target,
32
+ };
33
+ const fixPriority = indices.map((i) => ({
34
+ findingId: i,
35
+ reason: `severity=${findings[i].severity}`,
36
+ }));
37
+ const crossFindingLinks = [];
38
+ for (let i = 0; i < findings.length; i++) {
39
+ for (let j = i + 1; j < findings.length; j++) {
40
+ if (overlapRatio(findings[i].evidence.spans, findings[j].evidence.spans) >= 0.5) {
41
+ crossFindingLinks.push({
42
+ findingIds: [i, j],
43
+ relation: "overlapping_evidence_spans",
44
+ });
45
+ }
46
+ }
47
+ }
48
+ return { headline, primaryRootCause, fixPriority, crossFindingLinks };
49
+ }
@@ -0,0 +1,3 @@
1
+ import type { TraceTree } from "./types.js";
2
+ import type { RawSpan } from "../../api/trace.js";
3
+ export declare function assembleTraceTree(traceId: string, raw: RawSpan[]): TraceTree;