@mutagent/evaluator 0.1.0-alpha.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.
- package/.claude/skills/mutagent-evaluator/SKILL.md +538 -0
- package/.claude/skills/mutagent-evaluator/assets/agents/audit-executor.md +169 -0
- package/.claude/skills/mutagent-evaluator/assets/agents/dataset-builder.md +160 -0
- package/.claude/skills/mutagent-evaluator/assets/agents/discovery.md +425 -0
- package/.claude/skills/mutagent-evaluator/assets/agents/evaluator.md +1044 -0
- package/.claude/skills/mutagent-evaluator/assets/brand/theme.css +213 -0
- package/.claude/skills/mutagent-evaluator/assets/brand/wordmark.html +9 -0
- package/.claude/skills/mutagent-evaluator/lenses/context-flow-lens.md +85 -0
- package/.claude/skills/mutagent-evaluator/lenses/data-lens.md +47 -0
- package/.claude/skills/mutagent-evaluator/lenses/decision-lens.md +48 -0
- package/.claude/skills/mutagent-evaluator/lenses/methodology-critic-lens.md +53 -0
- package/.claude/skills/mutagent-evaluator/lenses/trajectory-lens.md +44 -0
- package/.claude/skills/mutagent-evaluator/references/build-review-interface.md +83 -0
- package/.claude/skills/mutagent-evaluator/references/edd-loop.md +134 -0
- package/.claude/skills/mutagent-evaluator/references/error-analysis.md +113 -0
- package/.claude/skills/mutagent-evaluator/references/eval-audit.md +154 -0
- package/.claude/skills/mutagent-evaluator/references/eval-stage.md +168 -0
- package/.claude/skills/mutagent-evaluator/references/generate-synthetic-data.md +81 -0
- package/.claude/skills/mutagent-evaluator/references/grounded-adjudication.md +221 -0
- package/.claude/skills/mutagent-evaluator/references/memory-format.md +65 -0
- package/.claude/skills/mutagent-evaluator/references/methodology.md +201 -0
- package/.claude/skills/mutagent-evaluator/references/operation-inventory.md +196 -0
- package/.claude/skills/mutagent-evaluator/references/validate-evaluator.md +125 -0
- package/.claude/skills/mutagent-evaluator/references/workflows/orchestrator-protocol.md +287 -0
- package/.claude/skills/mutagent-evaluator/references/write-judge-prompt.md +123 -0
- package/.claude/skills/mutagent-evaluator/schemas/behavior-tree.schema.yaml +73 -0
- package/.claude/skills/mutagent-evaluator/schemas/dataset.schema.yaml +66 -0
- package/.claude/skills/mutagent-evaluator/schemas/edd-change-request.schema.yaml +114 -0
- package/.claude/skills/mutagent-evaluator/schemas/eval-matrix.schema.yaml +74 -0
- package/.claude/skills/mutagent-evaluator/schemas/flow-graph.schema.yaml +69 -0
- package/.claude/skills/mutagent-evaluator/schemas/flow-profile.schema.yaml +49 -0
- package/.claude/skills/mutagent-evaluator/schemas/methodology-review.schema.yaml +40 -0
- package/.claude/skills/mutagent-evaluator/schemas/scorecard.schema.yaml +85 -0
- package/.claude/skills/mutagent-evaluator/scripts/agent-dispatch.ts +0 -0
- package/.claude/skills/mutagent-evaluator/scripts/aggregate-discover.ts +543 -0
- package/.claude/skills/mutagent-evaluator/scripts/artifact-paths.ts +99 -0
- package/.claude/skills/mutagent-evaluator/scripts/assemble-scorecard.ts +172 -0
- package/.claude/skills/mutagent-evaluator/scripts/build-dataset.ts +186 -0
- package/.claude/skills/mutagent-evaluator/scripts/build-evals.ts +93 -0
- package/.claude/skills/mutagent-evaluator/scripts/build-review-ui.ts +393 -0
- package/.claude/skills/mutagent-evaluator/scripts/check-method-router.ts +170 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/aggregate.ts +112 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/audit-run.ts +175 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/doctor.ts +211 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/dogfood.ts +133 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/init.ts +601 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/methodology-review.ts +122 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/prep.ts +279 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/profile-subject.ts +165 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/run.sh +56 -0
- package/.claude/skills/mutagent-evaluator/scripts/cli/variance-check.ts +105 -0
- package/.claude/skills/mutagent-evaluator/scripts/code-eval.ts +248 -0
- package/.claude/skills/mutagent-evaluator/scripts/codegen-evals.ts +173 -0
- package/.claude/skills/mutagent-evaluator/scripts/cold-start-project.ts +151 -0
- package/.claude/skills/mutagent-evaluator/scripts/cold-start-sampler.ts +267 -0
- package/.claude/skills/mutagent-evaluator/scripts/config/load.ts +307 -0
- package/.claude/skills/mutagent-evaluator/scripts/config/schema.ts +325 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/agentspec-evals.ts +85 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/dataset.ts +149 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-engine.ts +118 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-matrix.ts +577 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-types.ts +1074 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/flow-graph.ts +194 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/types.ts +303 -0
- package/.claude/skills/mutagent-evaluator/scripts/contracts/validation.ts +193 -0
- package/.claude/skills/mutagent-evaluator/scripts/derive-dataset.ts +152 -0
- package/.claude/skills/mutagent-evaluator/scripts/determine-outcome.ts +219 -0
- package/.claude/skills/mutagent-evaluator/scripts/diff-discriminate.ts +160 -0
- package/.claude/skills/mutagent-evaluator/scripts/discover-criteria.ts +348 -0
- package/.claude/skills/mutagent-evaluator/scripts/edd/change-request.ts +232 -0
- package/.claude/skills/mutagent-evaluator/scripts/edd/edd-types.ts +210 -0
- package/.claude/skills/mutagent-evaluator/scripts/edd/variance-gate.ts +186 -0
- package/.claude/skills/mutagent-evaluator/scripts/emit-completeness.ts +111 -0
- package/.claude/skills/mutagent-evaluator/scripts/eval-engine.ts +160 -0
- package/.claude/skills/mutagent-evaluator/scripts/evaluate.ts +333 -0
- package/.claude/skills/mutagent-evaluator/scripts/flow-graph.ts +230 -0
- package/.claude/skills/mutagent-evaluator/scripts/judge-prompt-template.ts +253 -0
- package/.claude/skills/mutagent-evaluator/scripts/judge-provider.ts +135 -0
- package/.claude/skills/mutagent-evaluator/scripts/lint-grounding.ts +229 -0
- package/.claude/skills/mutagent-evaluator/scripts/lint-uniformity.ts +168 -0
- package/.claude/skills/mutagent-evaluator/scripts/living-suite.ts +109 -0
- package/.claude/skills/mutagent-evaluator/scripts/load-bundle.ts +203 -0
- package/.claude/skills/mutagent-evaluator/scripts/load-profile-vocab.ts +64 -0
- package/.claude/skills/mutagent-evaluator/scripts/load-profile.ts +106 -0
- package/.claude/skills/mutagent-evaluator/scripts/mask.ts +138 -0
- package/.claude/skills/mutagent-evaluator/scripts/materialize-dataset.ts +113 -0
- package/.claude/skills/mutagent-evaluator/scripts/matrix-judge.ts +750 -0
- package/.claude/skills/mutagent-evaluator/scripts/memory/append.ts +215 -0
- package/.claude/skills/mutagent-evaluator/scripts/memory/read.ts +168 -0
- package/.claude/skills/mutagent-evaluator/scripts/prep-tasks.ts +125 -0
- package/.claude/skills/mutagent-evaluator/scripts/profile-subject.ts +310 -0
- package/.claude/skills/mutagent-evaluator/scripts/publish-report.ts +131 -0
- package/.claude/skills/mutagent-evaluator/scripts/read-unitf-traces.ts +81 -0
- package/.claude/skills/mutagent-evaluator/scripts/render-build-cards.ts +195 -0
- package/.claude/skills/mutagent-evaluator/scripts/render-discover-report.ts +1640 -0
- package/.claude/skills/mutagent-evaluator/scripts/render-eval-report.ts +3823 -0
- package/.claude/skills/mutagent-evaluator/scripts/render-report.ts +212 -0
- package/.claude/skills/mutagent-evaluator/scripts/resolve-credential.ts +110 -0
- package/.claude/skills/mutagent-evaluator/scripts/resolve-ref.ts +98 -0
- package/.claude/skills/mutagent-evaluator/scripts/result-verify.ts +129 -0
- package/.claude/skills/mutagent-evaluator/scripts/route-failures.ts +320 -0
- package/.claude/skills/mutagent-evaluator/scripts/run-deterministic.ts +271 -0
- package/.claude/skills/mutagent-evaluator/scripts/run-evaluate.ts +715 -0
- package/.claude/skills/mutagent-evaluator/scripts/run-judge.ts +155 -0
- package/.claude/skills/mutagent-evaluator/scripts/run-pipeline.ts +175 -0
- package/.claude/skills/mutagent-evaluator/scripts/sample-traces.ts +210 -0
- package/.claude/skills/mutagent-evaluator/scripts/self-audit.ts +387 -0
- package/.claude/skills/mutagent-evaluator/scripts/source-map.ts +106 -0
- package/.claude/skills/mutagent-evaluator/scripts/subject-profile.ts +134 -0
- package/.claude/skills/mutagent-evaluator/scripts/substrate.ts +162 -0
- package/.claude/skills/mutagent-evaluator/scripts/ui-slots.ts +119 -0
- package/.claude/skills/mutagent-evaluator/scripts/unitf-to-evaltrace.ts +284 -0
- package/.claude/skills/mutagent-evaluator/scripts/validate-judge.ts +358 -0
- package/.claude/skills/mutagent-evaluator/scripts/variance-compare.ts +177 -0
- package/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/behavior-tree.yaml +140 -0
- package/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/eval-matrix.yaml +1270 -0
- package/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/methodology-review.yaml +105 -0
- package/.claude/skills/mutagent-evaluator/workflows/audit.workflow.js +82 -0
- package/.claude/skills/mutagent-evaluator/workflows/data-leak.workflow.js +236 -0
- package/.claude/skills/mutagent-evaluator/workflows/variance.workflow.js +163 -0
- package/LICENSE +201 -0
- package/NOTICE +23 -0
- package/README.md +90 -0
- package/bin/mutagent-cli.mjs +9263 -0
- package/bin/mutagent-evaluator.mjs +96 -0
- package/package.json +52 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/config/schema.ts — the evaluator's FIRST config contract (v0.2.0).
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* PORTED IN, standalone. The evaluator reads the UNIFIED local
|
|
5
|
+
* `.mutagent/config.yaml` (operator decision 2026-06-29): ONE file drives the
|
|
6
|
+
* orchestrator + every skill. This module TypeBox-types the two blocks the
|
|
7
|
+
* evaluator reads:
|
|
8
|
+
*
|
|
9
|
+
* global.sources[] — the SOURCE catalog (where traces live). Bound BY ROLE
|
|
10
|
+
* (the evaluator is a source-CONSUMER → it binds
|
|
11
|
+
* `global.sources`). A single entry auto-binds; multiple
|
|
12
|
+
* ⇒ disambiguation is deferred (Fork A).
|
|
13
|
+
* global.models — { default, judge_model }. `judge_model` (renamed from
|
|
14
|
+
* `pinned_judge` in v0.2.0) is the C-PIN pinned judge.
|
|
15
|
+
* lifecycle.evaluator — the evaluator's OWN section: `context[]` (stage-
|
|
16
|
+
* specific links) + `judge_runtime` (renamed from
|
|
17
|
+
* `substrate` in v0.2.0 — HOW judges run).
|
|
18
|
+
*
|
|
19
|
+
* SEALED-SIBLING (coding-rules): the source/target SHAPE is a PARITY PORT of
|
|
20
|
+
* mutagent-orchestrator's `scripts/config-schema.ts` GlobalSourceSchema /
|
|
21
|
+
* GlobalTargetSchema — NEVER cross-imported (like resolve-credential.ts). A
|
|
22
|
+
* parity test asserts the shapes stay in lockstep.
|
|
23
|
+
*
|
|
24
|
+
* SHAPE vs COMPLETENESS (mirrors the orchestrator): this schema enforces SHAPE
|
|
25
|
+
* only. Sub-fields of `global` are OPTIONAL so a partial, mid-onboarding config
|
|
26
|
+
* still validates structurally. The per-skill `lifecycle.evaluator` section is
|
|
27
|
+
* OPEN (additionalProperties:true) beyond the typed fields — the evaluator owns
|
|
28
|
+
* the rest of its knobs; the orchestrator types only the gate-relevant ones.
|
|
29
|
+
*
|
|
30
|
+
* Determinism: pure schema + a `Value.Check` validator. No clock, no random, no
|
|
31
|
+
* network. The loader (config/load.ts) reads an INJECTED path; the pure core
|
|
32
|
+
* never resolves a path on its own (tests run against committed fixtures).
|
|
33
|
+
*
|
|
34
|
+
* NO raw secrets: a `credential_ref` is an env-var NAME (or `{env,path}`),
|
|
35
|
+
* resolved at use-time via resolve-credential.ts (env → .env → .mutagentrc).
|
|
36
|
+
*/
|
|
37
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
38
|
+
import { Value } from "@sinclair/typebox/value";
|
|
39
|
+
|
|
40
|
+
/** The FROZEN config-contract version this loader understands. */
|
|
41
|
+
export const CONFIG_VERSION = "0.2.0" as const;
|
|
42
|
+
|
|
43
|
+
/** Legacy version(s) whose configs must NOT be parsed at runtime (hard-cut). */
|
|
44
|
+
export const LEGACY_CONFIG_VERSIONS = ["0.1.0"] as const;
|
|
45
|
+
|
|
46
|
+
// ── Categorical constants (no magic strings — coding-rules) ──────────────────
|
|
47
|
+
|
|
48
|
+
/** Source platforms a `global.sources[]` entry can pull traces from. */
|
|
49
|
+
export const SourcePlatform = {
|
|
50
|
+
Langfuse: "langfuse",
|
|
51
|
+
Otel: "otel",
|
|
52
|
+
LocalJsonl: "local-jsonl",
|
|
53
|
+
ClaudeCode: "claude-code",
|
|
54
|
+
Codex: "codex",
|
|
55
|
+
} as const;
|
|
56
|
+
export type SourcePlatformValue =
|
|
57
|
+
(typeof SourcePlatform)[keyof typeof SourcePlatform];
|
|
58
|
+
|
|
59
|
+
/** Normalizer format hint for a source (how to parse the records). */
|
|
60
|
+
export const SourceFormat = {
|
|
61
|
+
LangfuseExport: "langfuse-export",
|
|
62
|
+
ClaudeCode: "claude-code",
|
|
63
|
+
Codex: "codex",
|
|
64
|
+
Raw: "raw",
|
|
65
|
+
} as const;
|
|
66
|
+
export type SourceFormatValue = (typeof SourceFormat)[keyof typeof SourceFormat];
|
|
67
|
+
|
|
68
|
+
/** Latency-unit override for a source (`auto` = infer from the record). */
|
|
69
|
+
export const LatencyUnit = {
|
|
70
|
+
Auto: "auto",
|
|
71
|
+
Ms: "ms",
|
|
72
|
+
S: "s",
|
|
73
|
+
} as const;
|
|
74
|
+
export type LatencyUnitValue = (typeof LatencyUnit)[keyof typeof LatencyUnit];
|
|
75
|
+
|
|
76
|
+
/** Target platforms a `global.targets[]` entry can write a fix TO. */
|
|
77
|
+
export const TargetPlatform = {
|
|
78
|
+
LocalClaude: "local-claude",
|
|
79
|
+
LocalCodex: "local-codex",
|
|
80
|
+
LocalCursor: "local-cursor",
|
|
81
|
+
LocalOpencode: "local-opencode",
|
|
82
|
+
LocalMastra: "local-mastra",
|
|
83
|
+
LocalCloudAgentSdk: "local-cloud-agent-sdk",
|
|
84
|
+
CloudRest: "cloud-rest",
|
|
85
|
+
ReportOnly: "report-only",
|
|
86
|
+
} as const;
|
|
87
|
+
export type TargetPlatformValue =
|
|
88
|
+
(typeof TargetPlatform)[keyof typeof TargetPlatform];
|
|
89
|
+
|
|
90
|
+
/** Whether a target's writes go through local files (worktree) or a remote API. */
|
|
91
|
+
export const TargetMode = {
|
|
92
|
+
Local: "local",
|
|
93
|
+
Remote: "remote",
|
|
94
|
+
} as const;
|
|
95
|
+
export type TargetModeValue = (typeof TargetMode)[keyof typeof TargetMode];
|
|
96
|
+
|
|
97
|
+
/** HOW a fix is applied to a target (`report-only` ⇒ no target write). */
|
|
98
|
+
export const ApplyKind = {
|
|
99
|
+
CodePr: "code-pr",
|
|
100
|
+
Markdown: "markdown",
|
|
101
|
+
CloudDeploy: "cloud-deploy",
|
|
102
|
+
ReportOnly: "report-only",
|
|
103
|
+
} as const;
|
|
104
|
+
export type ApplyKindValue = (typeof ApplyKind)[keyof typeof ApplyKind];
|
|
105
|
+
|
|
106
|
+
// ── Shared building-block schemas (PARITY PORT — orchestrator config-schema) ──
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* A credential REFERENCE — an ENV-VAR NAME (string) or `{ env, path? }`. NEVER a
|
|
110
|
+
* raw secret value (mirrors resolve-credential.ts CredentialRef; no cross-import).
|
|
111
|
+
*/
|
|
112
|
+
export const CredentialRefSchema = Type.Union([
|
|
113
|
+
Type.String({ minLength: 1 }),
|
|
114
|
+
Type.Object(
|
|
115
|
+
{
|
|
116
|
+
env: Type.String({ minLength: 1 }),
|
|
117
|
+
path: Type.Optional(Type.String({ minLength: 1 })),
|
|
118
|
+
},
|
|
119
|
+
{ additionalProperties: false },
|
|
120
|
+
),
|
|
121
|
+
]);
|
|
122
|
+
export type CredentialRefValue = Static<typeof CredentialRefSchema>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* A PROJECT-WIDE (or stage-specific) context link — a pointer to a supplementary
|
|
126
|
+
* doc with WHAT / WHY / WHEN. All four fields REQUIRED (a link with no rationale
|
|
127
|
+
* is noise).
|
|
128
|
+
*/
|
|
129
|
+
export const ContextLinkSchema = Type.Object(
|
|
130
|
+
{
|
|
131
|
+
path: Type.String({ minLength: 1 }),
|
|
132
|
+
what: Type.String({ minLength: 1 }),
|
|
133
|
+
why: Type.String({ minLength: 1 }),
|
|
134
|
+
when: Type.String({ minLength: 1 }),
|
|
135
|
+
},
|
|
136
|
+
{ additionalProperties: false },
|
|
137
|
+
);
|
|
138
|
+
export type ContextLink = Static<typeof ContextLinkSchema>;
|
|
139
|
+
|
|
140
|
+
/** The default model + the pinned judge model (`judge_model` — was `pinned_judge`). */
|
|
141
|
+
export const ModelsSchema = Type.Object(
|
|
142
|
+
{
|
|
143
|
+
default: Type.Optional(Type.String({ minLength: 1 })),
|
|
144
|
+
judge_model: Type.Optional(Type.String({ minLength: 1 })),
|
|
145
|
+
},
|
|
146
|
+
{ additionalProperties: false },
|
|
147
|
+
);
|
|
148
|
+
export type Models = Static<typeof ModelsSchema>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* One SOURCE catalog entry — where traces live. PARITY PORT of the orchestrator's
|
|
152
|
+
* GlobalSourceSchema. `paths` (file sources) is mutually exclusive with `endpoint`
|
|
153
|
+
* (remote); the schema tolerates both — onboarding cares.
|
|
154
|
+
*/
|
|
155
|
+
export const GlobalSourceSchema = Type.Object(
|
|
156
|
+
{
|
|
157
|
+
name: Type.String({ minLength: 1 }),
|
|
158
|
+
platform: Type.Union([
|
|
159
|
+
Type.Literal(SourcePlatform.Langfuse),
|
|
160
|
+
Type.Literal(SourcePlatform.Otel),
|
|
161
|
+
Type.Literal(SourcePlatform.LocalJsonl),
|
|
162
|
+
Type.Literal(SourcePlatform.ClaudeCode),
|
|
163
|
+
Type.Literal(SourcePlatform.Codex),
|
|
164
|
+
]),
|
|
165
|
+
project: Type.Optional(Type.String({ minLength: 1 })),
|
|
166
|
+
endpoint: Type.Optional(Type.String({ minLength: 1 })),
|
|
167
|
+
credential_ref: Type.Optional(CredentialRefSchema),
|
|
168
|
+
paths: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
169
|
+
format: Type.Optional(
|
|
170
|
+
Type.Union([
|
|
171
|
+
Type.Literal(SourceFormat.LangfuseExport),
|
|
172
|
+
Type.Literal(SourceFormat.ClaudeCode),
|
|
173
|
+
Type.Literal(SourceFormat.Codex),
|
|
174
|
+
Type.Literal(SourceFormat.Raw),
|
|
175
|
+
]),
|
|
176
|
+
),
|
|
177
|
+
agent_field: Type.Optional(Type.String({ minLength: 1 })),
|
|
178
|
+
latency_unit: Type.Optional(
|
|
179
|
+
Type.Union([
|
|
180
|
+
Type.Literal(LatencyUnit.Auto),
|
|
181
|
+
Type.Literal(LatencyUnit.Ms),
|
|
182
|
+
Type.Literal(LatencyUnit.S),
|
|
183
|
+
]),
|
|
184
|
+
),
|
|
185
|
+
// PARITY (orchestrator SourceSchema): the catalog's DEFAULT pick when >1 entry
|
|
186
|
+
// exists — the selection contract's silent-bind marker (exactly one `default:true`
|
|
187
|
+
// ⇒ auto-bind, skipping the disambiguation prompt). Optional: absent ⇒ no default.
|
|
188
|
+
default: Type.Optional(Type.Boolean()),
|
|
189
|
+
},
|
|
190
|
+
{ additionalProperties: false },
|
|
191
|
+
);
|
|
192
|
+
export type GlobalSource = Static<typeof GlobalSourceSchema>;
|
|
193
|
+
|
|
194
|
+
/** A precise link to an Agent / Tooling definition file in a code target. */
|
|
195
|
+
export const CodeRefSchema = Type.Object(
|
|
196
|
+
{
|
|
197
|
+
path: Type.String({ minLength: 1 }),
|
|
198
|
+
why: Type.String({ minLength: 1 }),
|
|
199
|
+
},
|
|
200
|
+
{ additionalProperties: false },
|
|
201
|
+
);
|
|
202
|
+
export type CodeRef = Static<typeof CodeRefSchema>;
|
|
203
|
+
|
|
204
|
+
/** HOW a fix is applied for a target. `kind` gates the report-only branch. */
|
|
205
|
+
export const ApplySchema = Type.Object(
|
|
206
|
+
{
|
|
207
|
+
kind: Type.Union([
|
|
208
|
+
Type.Literal(ApplyKind.CodePr),
|
|
209
|
+
Type.Literal(ApplyKind.Markdown),
|
|
210
|
+
Type.Literal(ApplyKind.CloudDeploy),
|
|
211
|
+
Type.Literal(ApplyKind.ReportOnly),
|
|
212
|
+
]),
|
|
213
|
+
versioning: Type.Optional(Type.Boolean()),
|
|
214
|
+
pr: Type.Optional(Type.Boolean()),
|
|
215
|
+
},
|
|
216
|
+
{ additionalProperties: false },
|
|
217
|
+
);
|
|
218
|
+
export type Apply = Static<typeof ApplySchema>;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* One TARGET catalog entry — where agent defs live + how a fix is applied. PARITY
|
|
222
|
+
* PORT of the orchestrator's GlobalTargetSchema. The evaluator is JUDGE-ONLY
|
|
223
|
+
* (EV-051) so it never WRITES a target; it ports the shape for parity + so the
|
|
224
|
+
* loader can validate a full `global` block without rejecting a present target.
|
|
225
|
+
*/
|
|
226
|
+
export const GlobalTargetSchema = Type.Object(
|
|
227
|
+
{
|
|
228
|
+
name: Type.String({ minLength: 1 }),
|
|
229
|
+
platform: Type.Union([
|
|
230
|
+
Type.Literal(TargetPlatform.LocalClaude),
|
|
231
|
+
Type.Literal(TargetPlatform.LocalCodex),
|
|
232
|
+
Type.Literal(TargetPlatform.LocalCursor),
|
|
233
|
+
Type.Literal(TargetPlatform.LocalOpencode),
|
|
234
|
+
Type.Literal(TargetPlatform.LocalMastra),
|
|
235
|
+
Type.Literal(TargetPlatform.LocalCloudAgentSdk),
|
|
236
|
+
Type.Literal(TargetPlatform.CloudRest),
|
|
237
|
+
Type.Literal(TargetPlatform.ReportOnly),
|
|
238
|
+
]),
|
|
239
|
+
mode: Type.Union([
|
|
240
|
+
Type.Literal(TargetMode.Local),
|
|
241
|
+
Type.Literal(TargetMode.Remote),
|
|
242
|
+
]),
|
|
243
|
+
root: Type.Optional(Type.String({ minLength: 1 })),
|
|
244
|
+
rest_base_url: Type.Optional(Type.String({ minLength: 1 })),
|
|
245
|
+
repo_url: Type.Optional(Type.String({ minLength: 1 })),
|
|
246
|
+
code_refs: Type.Optional(Type.Array(CodeRefSchema)),
|
|
247
|
+
credential_ref: Type.Optional(CredentialRefSchema),
|
|
248
|
+
apply: ApplySchema,
|
|
249
|
+
// PARITY (orchestrator TargetSchema): the catalog's DEFAULT pick when >1 entry
|
|
250
|
+
// exists. The evaluator is JUDGE-ONLY (EV-051) and never binds a target, but the
|
|
251
|
+
// shape stays in lockstep with the orchestrator (parity test). Optional.
|
|
252
|
+
default: Type.Optional(Type.Boolean()),
|
|
253
|
+
},
|
|
254
|
+
{ additionalProperties: false },
|
|
255
|
+
);
|
|
256
|
+
export type GlobalTarget = Static<typeof GlobalTargetSchema>;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* The GLOBAL cross-cutting resources the evaluator reads. Sub-fields OPTIONAL (a
|
|
260
|
+
* partial mid-onboarding config still validates). The evaluator only READS
|
|
261
|
+
* `models` + `sources` (+ `targets` for shape parity); the orchestrator owns the
|
|
262
|
+
* rest of `global` (providers/workspace/brand/context) — passed through here as
|
|
263
|
+
* OPEN so a full unified config doesn't fail the evaluator's structural check.
|
|
264
|
+
*/
|
|
265
|
+
export const GlobalSchema = Type.Object(
|
|
266
|
+
{
|
|
267
|
+
models: Type.Optional(ModelsSchema),
|
|
268
|
+
context: Type.Optional(Type.Array(ContextLinkSchema)),
|
|
269
|
+
sources: Type.Optional(Type.Array(GlobalSourceSchema)),
|
|
270
|
+
targets: Type.Optional(Type.Array(GlobalTargetSchema)),
|
|
271
|
+
},
|
|
272
|
+
// OPEN: the orchestrator-owned global fields (providers/workspace/brand) pass
|
|
273
|
+
// through — the evaluator doesn't type them but must not reject them.
|
|
274
|
+
{ additionalProperties: true },
|
|
275
|
+
);
|
|
276
|
+
export type Global = Static<typeof GlobalSchema>;
|
|
277
|
+
|
|
278
|
+
// ── `lifecycle.evaluator` — the evaluator's OWN section ───────────────────────
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* `lifecycle.evaluator` — the evaluator's config section. The typed fields:
|
|
282
|
+
* context[] — stage-specific supplementary context links (eval rubric).
|
|
283
|
+
* judge_runtime — HOW judges run (renamed from `substrate` in v0.2.0):
|
|
284
|
+
* agent-dispatch (DEFAULT) | in-house | code-based | user-framework.
|
|
285
|
+
* OPEN (additionalProperties:true): the evaluator owns any further knobs
|
|
286
|
+
* (subject profile path, dataset opts, …) — passthrough, validated elsewhere.
|
|
287
|
+
*/
|
|
288
|
+
export const LifecycleEvaluatorSchema = Type.Object(
|
|
289
|
+
{
|
|
290
|
+
context: Type.Optional(Type.Array(ContextLinkSchema)),
|
|
291
|
+
judge_runtime: Type.Optional(Type.String({ minLength: 1 })),
|
|
292
|
+
},
|
|
293
|
+
{ additionalProperties: true },
|
|
294
|
+
);
|
|
295
|
+
export type LifecycleEvaluator = Static<typeof LifecycleEvaluatorSchema>;
|
|
296
|
+
|
|
297
|
+
// ── Validation ────────────────────────────────────────────────────────────────
|
|
298
|
+
|
|
299
|
+
export interface ValidationResult {
|
|
300
|
+
ok: boolean;
|
|
301
|
+
/** Human-readable error strings (path: message), empty when ok. */
|
|
302
|
+
errors: string[];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/** Validate a value against the evaluator's `global` block. Pure; never throws. */
|
|
306
|
+
export function validateGlobal(obj: unknown): ValidationResult {
|
|
307
|
+
const errors: string[] = [];
|
|
308
|
+
if (!Value.Check(GlobalSchema, obj)) {
|
|
309
|
+
for (const e of Value.Errors(GlobalSchema, obj)) {
|
|
310
|
+
errors.push(`${e.path === "" ? "/" : e.path}: ${e.message}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return { ok: errors.length === 0, errors };
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Validate a value against `lifecycle.evaluator`. Pure; never throws. */
|
|
317
|
+
export function validateLifecycleEvaluator(obj: unknown): ValidationResult {
|
|
318
|
+
const errors: string[] = [];
|
|
319
|
+
if (!Value.Check(LifecycleEvaluatorSchema, obj)) {
|
|
320
|
+
for (const e of Value.Errors(LifecycleEvaluatorSchema, obj)) {
|
|
321
|
+
errors.push(`${e.path === "" ? "/" : e.path}: ${e.message}`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return { ok: errors.length === 0, errors };
|
|
325
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/contracts/agentspec-evals.ts — the MINIMAL agentspec.evals slice the
|
|
3
|
+
* EVAL stage consumes (standalone — NEVER imports the agentspec skill's schema).
|
|
4
|
+
* ---------------------------------------------------------------------------
|
|
5
|
+
* The ADL `*build` stage emits an agentspec whose `definition.evals` block carries
|
|
6
|
+
* the SEED material the evaluator materializes into a real dataset (F8) + criteria:
|
|
7
|
+
*
|
|
8
|
+
* - dataset_categories[] — `{ id, description, edge_cases[] }` — the golden
|
|
9
|
+
* eval-suite slices + the explicit edge_cases each must exercise (the dataset
|
|
10
|
+
* DEFINITION the spec hands forward; "seed, don't duplicate").
|
|
11
|
+
* - scenarios[] — `{ id, description, expected_behavior, category?,
|
|
12
|
+
* edge_case? }` — representative situations + the correct behavior (extra seed
|
|
13
|
+
* material, optionally tagged into a category).
|
|
14
|
+
* - success_criteria[] — `{ id, criterion, type, goal }` — binary-actionable
|
|
15
|
+
* pass/fail criteria (type ∈ llm-judge | code-check).
|
|
16
|
+
*
|
|
17
|
+
* We DECLARE only the fields we read, with `additionalProperties: true` on the
|
|
18
|
+
* objects so a richer agentspec still parses (forward-compatible). The cross-skill
|
|
19
|
+
* import ban (coding-rules "Sealed-Sibling" + standalone discipline) is why this is
|
|
20
|
+
* a local re-declaration, not an import. PURE — no clock / random / network.
|
|
21
|
+
*/
|
|
22
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
23
|
+
import { Value } from "@sinclair/typebox/value";
|
|
24
|
+
|
|
25
|
+
/** A dataset CATEGORY slice + the edge-cases it must exercise. */
|
|
26
|
+
export const AgentspecDatasetCategorySchema = Type.Object(
|
|
27
|
+
{
|
|
28
|
+
id: Type.String({ minLength: 1 }),
|
|
29
|
+
description: Type.String({ minLength: 1 }),
|
|
30
|
+
edge_cases: Type.Array(Type.String()),
|
|
31
|
+
},
|
|
32
|
+
{ additionalProperties: true },
|
|
33
|
+
);
|
|
34
|
+
export type AgentspecDatasetCategory = Static<typeof AgentspecDatasetCategorySchema>;
|
|
35
|
+
|
|
36
|
+
/** A representative SCENARIO (the situation + correct behavior). */
|
|
37
|
+
export const AgentspecScenarioSchema = Type.Object(
|
|
38
|
+
{
|
|
39
|
+
id: Type.String({ minLength: 1 }),
|
|
40
|
+
description: Type.String({ minLength: 1 }),
|
|
41
|
+
expected_behavior: Type.String({ minLength: 1 }),
|
|
42
|
+
category: Type.Optional(Type.String()),
|
|
43
|
+
edge_case: Type.Optional(Type.Boolean()),
|
|
44
|
+
},
|
|
45
|
+
{ additionalProperties: true },
|
|
46
|
+
);
|
|
47
|
+
export type AgentspecScenario = Static<typeof AgentspecScenarioSchema>;
|
|
48
|
+
|
|
49
|
+
/** A binary-actionable SUCCESS CRITERION. */
|
|
50
|
+
export const AgentspecSuccessCriterionSchema = Type.Object(
|
|
51
|
+
{
|
|
52
|
+
id: Type.String({ minLength: 1 }),
|
|
53
|
+
criterion: Type.String({ minLength: 1 }),
|
|
54
|
+
type: Type.Union([Type.Literal("llm-judge"), Type.Literal("code-check")]),
|
|
55
|
+
goal: Type.String({ minLength: 1 }),
|
|
56
|
+
},
|
|
57
|
+
{ additionalProperties: true },
|
|
58
|
+
);
|
|
59
|
+
export type AgentspecSuccessCriterion = Static<typeof AgentspecSuccessCriterionSchema>;
|
|
60
|
+
|
|
61
|
+
/** The `definition.evals` slice. Each array may be empty structurally. */
|
|
62
|
+
export const AgentspecEvalsSchema = Type.Object(
|
|
63
|
+
{
|
|
64
|
+
success_criteria: Type.Array(AgentspecSuccessCriterionSchema),
|
|
65
|
+
scenarios: Type.Array(AgentspecScenarioSchema),
|
|
66
|
+
dataset_categories: Type.Array(AgentspecDatasetCategorySchema),
|
|
67
|
+
},
|
|
68
|
+
{ additionalProperties: true },
|
|
69
|
+
);
|
|
70
|
+
export type AgentspecEvals = Static<typeof AgentspecEvalsSchema>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Parse + narrow the agentspec.evals slice (guarded). THROWS on schema violation —
|
|
74
|
+
* a malformed seed must never silently reach materialization. PURE.
|
|
75
|
+
*/
|
|
76
|
+
export function parseAgentspecEvals(value: unknown): AgentspecEvals {
|
|
77
|
+
if (!Value.Check(AgentspecEvalsSchema, value)) {
|
|
78
|
+
const first = [...Value.Errors(AgentspecEvalsSchema, value)][0];
|
|
79
|
+
throw new Error(
|
|
80
|
+
`parseAgentspecEvals: schema violation at '${first?.path ?? "(root)"}': ` +
|
|
81
|
+
`${first?.message ?? "invalid agentspec evals slice"}`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/contracts/dataset.ts — the W2 DATASET data contract.
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* The executable (TypeBox) companion to `schemas/dataset.schema.yaml`. Declares
|
|
5
|
+
* the shapes for `*build-dataset` (EV-046, synthetic) + `*discover-dataset`
|
|
6
|
+
* (EV-047, distilled-from-traces) + the `living-suite` (EV-053) append target:
|
|
7
|
+
*
|
|
8
|
+
* - `Dimension` — one axis of variation (generate-synthetic-data Step 1).
|
|
9
|
+
* - `DatasetTuple` — one combination of dimension→value (Step 2).
|
|
10
|
+
* - `DatasetCase` — a tuple + its natural-language query + provenance.
|
|
11
|
+
* - `Dataset` — the subject's growing case set (append-only, EV-053).
|
|
12
|
+
*
|
|
13
|
+
* Strict austerity: Type A — data contract only. NO judge prompt, NO LLM
|
|
14
|
+
* reasoning, NO pass/fail decision. The LLM tuple/query GENERATION lives in
|
|
15
|
+
* `assets/agents/dataset-builder.md`; this file only declares + validates the
|
|
16
|
+
* DATA. PURE — no clock / random / network.
|
|
17
|
+
*
|
|
18
|
+
* Disjointness (W2-OWN): NEW W2 contract file — does NOT touch the shared
|
|
19
|
+
* `contracts/eval-types.ts`. Subject-agnostic (EV-002): dimensions + values are
|
|
20
|
+
* DATA carried here, never hard-coded engine constants.
|
|
21
|
+
*/
|
|
22
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
23
|
+
import { Value } from "@sinclair/typebox/value";
|
|
24
|
+
|
|
25
|
+
// ── Dimension — one axis of variation (target a failure-prone region) ────────
|
|
26
|
+
export const DimensionSchema = Type.Object(
|
|
27
|
+
{
|
|
28
|
+
name: Type.String({ minLength: 1 }),
|
|
29
|
+
description: Type.Optional(Type.String()),
|
|
30
|
+
/** the discrete values this dimension can take (≥1). */
|
|
31
|
+
values: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
|
|
32
|
+
},
|
|
33
|
+
{ additionalProperties: false },
|
|
34
|
+
);
|
|
35
|
+
export type Dimension = Static<typeof DimensionSchema>;
|
|
36
|
+
|
|
37
|
+
// ── DatasetTuple — one combination of dimension→value ────────────────────────
|
|
38
|
+
//
|
|
39
|
+
// A flat map (dimension name → chosen value). Canonicalized for dedup by
|
|
40
|
+
// `tupleKey` (sorted dimension names) so two tuples with the same assignments
|
|
41
|
+
// in any insertion order collapse to one.
|
|
42
|
+
export const DatasetTupleSchema = Type.Record(Type.String({ minLength: 1 }), Type.String(), {
|
|
43
|
+
minProperties: 1,
|
|
44
|
+
});
|
|
45
|
+
export type DatasetTuple = Static<typeof DatasetTupleSchema>;
|
|
46
|
+
|
|
47
|
+
// ── Case provenance + source ─────────────────────────────────────────────────
|
|
48
|
+
export const CaseSource = {
|
|
49
|
+
/** a user-confirmed seed tuple (the ~10 HITL interview). */
|
|
50
|
+
Seed: "seed",
|
|
51
|
+
/** LLM-generated by the dataset-builder agent (synthetic extension). */
|
|
52
|
+
Synthetic: "synthetic",
|
|
53
|
+
/** distilled from a real past trace (`*discover-dataset`, EV-047). */
|
|
54
|
+
Derived: "derived",
|
|
55
|
+
} as const;
|
|
56
|
+
export type CaseSourceValue = (typeof CaseSource)[keyof typeof CaseSource];
|
|
57
|
+
|
|
58
|
+
// ── DatasetCase — a tuple + its NL query + provenance ────────────────────────
|
|
59
|
+
export const DatasetCaseSchema = Type.Object(
|
|
60
|
+
{
|
|
61
|
+
/** deterministic stable id (content-derived; never a clock/random). */
|
|
62
|
+
id: Type.String({ minLength: 1 }),
|
|
63
|
+
/** the dimension assignment this case realizes. */
|
|
64
|
+
tuple: DatasetTupleSchema,
|
|
65
|
+
/** the natural-language query (Step 4 — from the dataset-builder agent). */
|
|
66
|
+
query: Type.String({ minLength: 1 }),
|
|
67
|
+
source: Type.Union([
|
|
68
|
+
Type.Literal(CaseSource.Seed),
|
|
69
|
+
Type.Literal(CaseSource.Synthetic),
|
|
70
|
+
Type.Literal(CaseSource.Derived),
|
|
71
|
+
]),
|
|
72
|
+
/** optional pointer back to the originating trace (for `derived` cases). */
|
|
73
|
+
originTraceId: Type.Optional(Type.String()),
|
|
74
|
+
/**
|
|
75
|
+
* DETERMINISTIC provenance — which EV-052 regression selector nominated this
|
|
76
|
+
* case ("the data link"). One of: failure-driven (a confirmed ✗ catastrophe) ·
|
|
77
|
+
* outlier (an edge metric) · uncertainty (a brittle boundary call) · stratified
|
|
78
|
+
* (a known-✓ anchor). Code-derived, byte-identical on re-derive. Optional so
|
|
79
|
+
* non-derived (seed/synthetic) cases omit it.
|
|
80
|
+
*/
|
|
81
|
+
selectedBy: Type.Optional(Type.String()),
|
|
82
|
+
/**
|
|
83
|
+
* The HUMAN-READABLE "why is this item high-value as a held-out test" — a
|
|
84
|
+
* JUDGMENT authored by whoever SELECTS the case (the discover/judge agent),
|
|
85
|
+
* not a code derivation. Explains what failure mode / uncertainty / coverage
|
|
86
|
+
* gap makes this trace worth keeping in the suite forever. Grounded in the
|
|
87
|
+
* originating trace. Optional (populated at selection time).
|
|
88
|
+
*/
|
|
89
|
+
rationale: Type.Optional(Type.String()),
|
|
90
|
+
},
|
|
91
|
+
{ additionalProperties: false },
|
|
92
|
+
);
|
|
93
|
+
export type DatasetCase = Static<typeof DatasetCaseSchema>;
|
|
94
|
+
|
|
95
|
+
// ── Dataset — the subject's growing case set (append-only, EV-053) ───────────
|
|
96
|
+
export const DatasetSchema = Type.Object(
|
|
97
|
+
{
|
|
98
|
+
/** subject display name (from the subject profile — subject-agnostic). */
|
|
99
|
+
subject: Type.String({ minLength: 1 }),
|
|
100
|
+
/** the dimensions this dataset varies over. */
|
|
101
|
+
dimensions: Type.Array(DimensionSchema),
|
|
102
|
+
/** the cases (append-only; monotonic-growth enforced by living-suite). */
|
|
103
|
+
cases: Type.Array(DatasetCaseSchema),
|
|
104
|
+
/** monotonically-increasing version (bumped on every append). */
|
|
105
|
+
version: Type.Integer({ minimum: 0 }),
|
|
106
|
+
},
|
|
107
|
+
{ additionalProperties: false },
|
|
108
|
+
);
|
|
109
|
+
export type Dataset = Static<typeof DatasetSchema>;
|
|
110
|
+
|
|
111
|
+
/** Parse a dataset file (raw JSON). THROWS on schema violation. PURE. */
|
|
112
|
+
export function parseDataset(raw: string): Dataset {
|
|
113
|
+
let parsed: unknown;
|
|
114
|
+
try {
|
|
115
|
+
parsed = JSON.parse(raw);
|
|
116
|
+
} catch {
|
|
117
|
+
throw new Error(`parseDataset: not valid JSON: ${raw.slice(0, 120)}`);
|
|
118
|
+
}
|
|
119
|
+
if (!Value.Check(DatasetSchema, parsed)) {
|
|
120
|
+
const first = [...Value.Errors(DatasetSchema, parsed)][0];
|
|
121
|
+
throw new Error(
|
|
122
|
+
`parseDataset: schema violation at '${first?.path ?? "?"}': ` +
|
|
123
|
+
`${first?.message ?? "invalid Dataset"}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return parsed;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Assert a DatasetCase conforms (used before append). THROWS on violation. */
|
|
130
|
+
export function assertDatasetCase(c: unknown): asserts c is DatasetCase {
|
|
131
|
+
if (!Value.Check(DatasetCaseSchema, c)) {
|
|
132
|
+
const first = [...Value.Errors(DatasetCaseSchema, c)][0];
|
|
133
|
+
throw new Error(
|
|
134
|
+
`assertDatasetCase: schema violation at '${first?.path ?? "?"}': ` +
|
|
135
|
+
`${first?.message ?? "invalid DatasetCase"}`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Canonical dedup key for a tuple — dimension names sorted, so assignment order
|
|
142
|
+
* never matters. PURE + deterministic.
|
|
143
|
+
*/
|
|
144
|
+
export function tupleKey(tuple: DatasetTuple): string {
|
|
145
|
+
return Object.keys(tuple)
|
|
146
|
+
.sort()
|
|
147
|
+
.map((k) => `${k}=${tuple[k]}`)
|
|
148
|
+
.join("");
|
|
149
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/contracts/eval-engine.ts — the ADL EVAL-stage ENGINE FORK contract.
|
|
3
|
+
* ---------------------------------------------------------------------------
|
|
4
|
+
* The TypeBox companion for the F7/F9/F14 eval-implementation fork: when the ADL
|
|
5
|
+
* `*build` stage hands a freshly-built agent to the evaluator, the user must
|
|
6
|
+
* choose HOW the eval suite is implemented. Two engines:
|
|
7
|
+
*
|
|
8
|
+
* - Path A — `native-matrix` (mutagent NATIVE evals): the eval-matrix format
|
|
9
|
+
* judged by LLM-as-judge SUB-AGENTS. HARD DEPENDENCY on a Claude-Code host
|
|
10
|
+
* to spawn the judge sub-agents. For a CODE-framework target (Mastra/TS) the
|
|
11
|
+
* native matrix ALSO requires the built agent to EMIT logs/traces to a known
|
|
12
|
+
* output SINK (CC session transcripts / a declared log file) for the judge to
|
|
13
|
+
* read. Surfaced UP FRONT so a user is never silently "stuck with the matrix".
|
|
14
|
+
* - Path B — `code-written` (CODE-written evals): evals written in the target's
|
|
15
|
+
* OWN language (bun/TS for Mastra) — deterministic code-checks + an LLM-judge
|
|
16
|
+
* call VIA SDK + eval-criteria checks. PORTABLE — needs NO Claude-Code
|
|
17
|
+
* sub-agents, so a non-CC user is NOT trapped in the matrix (F14).
|
|
18
|
+
*
|
|
19
|
+
* The fork is TARGET-CONDITIONAL (F9): a code-framework target (e.g. Mastra/TS)
|
|
20
|
+
* may pick EITHER engine; a harness target (harness:claude-code) is native-only.
|
|
21
|
+
* This file declares the DATA (the menu options + the resolved plan + the gates);
|
|
22
|
+
* the AskUserQuestion gate + the actual codegen live elsewhere. Subject-agnostic.
|
|
23
|
+
*
|
|
24
|
+
* Standalone: this skill NEVER imports the agentspec schema (cross-skill import is
|
|
25
|
+
* banned). It consumes a MINIMAL local slice (`EngineTargetInput`) the caller maps
|
|
26
|
+
* from the agentspec's `build` block. PURE — no clock / random / network.
|
|
27
|
+
*/
|
|
28
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
29
|
+
import { Value } from "@sinclair/typebox/value";
|
|
30
|
+
|
|
31
|
+
// ── EvalEngine — the two implementation paths (the fork) ─────────────────────
|
|
32
|
+
export const EvalEngine = {
|
|
33
|
+
/** Path A — mutagent native eval-matrix + LLM-judge SUB-AGENTS (needs a CC host). */
|
|
34
|
+
NativeMatrix: "native-matrix",
|
|
35
|
+
/** Path B — code-written evals in the target's language (portable, no CC sub-agents). */
|
|
36
|
+
CodeWritten: "code-written",
|
|
37
|
+
} as const;
|
|
38
|
+
export type EvalEngineValue = (typeof EvalEngine)[keyof typeof EvalEngine];
|
|
39
|
+
|
|
40
|
+
// ── EngineTargetInput — the MINIMAL slice the caller maps from agentspec.build ─
|
|
41
|
+
//
|
|
42
|
+
// We do NOT import the agentspec contract (standalone skill). The caller reads
|
|
43
|
+
// `agentspec.build.{target_framework, runtime}` and hands us this slice.
|
|
44
|
+
export const EngineTargetInputSchema = Type.Object(
|
|
45
|
+
{
|
|
46
|
+
/** e.g. "mastra" | "deepagents" | "langgraph" | "harness:claude-code" | "harness:codex". */
|
|
47
|
+
targetFramework: Type.String({ minLength: 1 }),
|
|
48
|
+
/** e.g. "bun" | "node" | "deno" | "python" | "shell". */
|
|
49
|
+
runtime: Type.String({ minLength: 1 }),
|
|
50
|
+
},
|
|
51
|
+
{ additionalProperties: false },
|
|
52
|
+
);
|
|
53
|
+
export type EngineTargetInput = Static<typeof EngineTargetInputSchema>;
|
|
54
|
+
|
|
55
|
+
// ── EvalEngineOption — one selectable menu entry (target-conditional) ─────────
|
|
56
|
+
//
|
|
57
|
+
// What the AskUserQuestion gate renders. `requiresClaudeCode` + `requiresLogSink`
|
|
58
|
+
// are the F7/F9 SURFACED dependencies — shown UP FRONT, never discovered late.
|
|
59
|
+
export const EvalEngineOptionSchema = Type.Object(
|
|
60
|
+
{
|
|
61
|
+
engine: Type.Union([
|
|
62
|
+
Type.Literal(EvalEngine.NativeMatrix),
|
|
63
|
+
Type.Literal(EvalEngine.CodeWritten),
|
|
64
|
+
]),
|
|
65
|
+
/** short human label for the picker. */
|
|
66
|
+
label: Type.String({ minLength: 1 }),
|
|
67
|
+
/** one-line description of what this engine does for THIS target. */
|
|
68
|
+
summary: Type.String({ minLength: 1 }),
|
|
69
|
+
/** TRUE iff this engine needs a Claude-Code host to spawn judge sub-agents (Path A). */
|
|
70
|
+
requiresClaudeCode: Type.Boolean(),
|
|
71
|
+
/** TRUE iff this engine needs the built agent to emit logs/traces to a sink (F9). */
|
|
72
|
+
requiresLogSink: Type.Boolean(),
|
|
73
|
+
/** TRUE iff this engine is portable to a non-CC user (Path B). */
|
|
74
|
+
portable: Type.Boolean(),
|
|
75
|
+
/** TRUE iff this is the recommended default for the target. */
|
|
76
|
+
recommended: Type.Boolean(),
|
|
77
|
+
},
|
|
78
|
+
{ additionalProperties: false },
|
|
79
|
+
);
|
|
80
|
+
export type EvalEngineOption = Static<typeof EvalEngineOptionSchema>;
|
|
81
|
+
|
|
82
|
+
// ── EvalEnginePlan — the RESOLVED choice (what *evaluate runs against) ────────
|
|
83
|
+
export const EvalEnginePlanSchema = Type.Object(
|
|
84
|
+
{
|
|
85
|
+
engine: Type.Union([
|
|
86
|
+
Type.Literal(EvalEngine.NativeMatrix),
|
|
87
|
+
Type.Literal(EvalEngine.CodeWritten),
|
|
88
|
+
]),
|
|
89
|
+
target: EngineTargetInputSchema,
|
|
90
|
+
/** TRUE iff the target is a coding-FRAMEWORK (vs a `harness:*` target). */
|
|
91
|
+
targetIsFramework: Type.Boolean(),
|
|
92
|
+
/** the SURFACED dependency: needs a CC host (Path A). */
|
|
93
|
+
requiresClaudeCode: Type.Boolean(),
|
|
94
|
+
/**
|
|
95
|
+
* the SURFACED dependency: the built agent must emit logs/traces to THIS sink
|
|
96
|
+
* for the native matrix judge to read it. Present iff `requiresLogSink`.
|
|
97
|
+
*/
|
|
98
|
+
requiresLogSink: Type.Boolean(),
|
|
99
|
+
/** the discoverable OUTPUT SINK the engine writes to (always set — discoverability gate). */
|
|
100
|
+
outputSink: Type.String({ minLength: 1 }),
|
|
101
|
+
/** human-readable rationale (echoed into the entity card + report). */
|
|
102
|
+
rationale: Type.String({ minLength: 1 }),
|
|
103
|
+
},
|
|
104
|
+
{ additionalProperties: false },
|
|
105
|
+
);
|
|
106
|
+
export type EvalEnginePlan = Static<typeof EvalEnginePlanSchema>;
|
|
107
|
+
|
|
108
|
+
/** Parse + narrow an EvalEnginePlan (guarded). THROWS on schema violation. PURE. */
|
|
109
|
+
export function parseEvalEnginePlan(value: unknown): EvalEnginePlan {
|
|
110
|
+
if (!Value.Check(EvalEnginePlanSchema, value)) {
|
|
111
|
+
const first = [...Value.Errors(EvalEnginePlanSchema, value)][0];
|
|
112
|
+
throw new Error(
|
|
113
|
+
`parseEvalEnginePlan: schema violation at '${first?.path ?? "(root)"}': ` +
|
|
114
|
+
`${first?.message ?? "invalid EvalEnginePlan"}`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return value;
|
|
118
|
+
}
|