@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.
Files changed (126) hide show
  1. package/.claude/skills/mutagent-evaluator/SKILL.md +538 -0
  2. package/.claude/skills/mutagent-evaluator/assets/agents/audit-executor.md +169 -0
  3. package/.claude/skills/mutagent-evaluator/assets/agents/dataset-builder.md +160 -0
  4. package/.claude/skills/mutagent-evaluator/assets/agents/discovery.md +425 -0
  5. package/.claude/skills/mutagent-evaluator/assets/agents/evaluator.md +1044 -0
  6. package/.claude/skills/mutagent-evaluator/assets/brand/theme.css +213 -0
  7. package/.claude/skills/mutagent-evaluator/assets/brand/wordmark.html +9 -0
  8. package/.claude/skills/mutagent-evaluator/lenses/context-flow-lens.md +85 -0
  9. package/.claude/skills/mutagent-evaluator/lenses/data-lens.md +47 -0
  10. package/.claude/skills/mutagent-evaluator/lenses/decision-lens.md +48 -0
  11. package/.claude/skills/mutagent-evaluator/lenses/methodology-critic-lens.md +53 -0
  12. package/.claude/skills/mutagent-evaluator/lenses/trajectory-lens.md +44 -0
  13. package/.claude/skills/mutagent-evaluator/references/build-review-interface.md +83 -0
  14. package/.claude/skills/mutagent-evaluator/references/edd-loop.md +134 -0
  15. package/.claude/skills/mutagent-evaluator/references/error-analysis.md +113 -0
  16. package/.claude/skills/mutagent-evaluator/references/eval-audit.md +154 -0
  17. package/.claude/skills/mutagent-evaluator/references/eval-stage.md +168 -0
  18. package/.claude/skills/mutagent-evaluator/references/generate-synthetic-data.md +81 -0
  19. package/.claude/skills/mutagent-evaluator/references/grounded-adjudication.md +221 -0
  20. package/.claude/skills/mutagent-evaluator/references/memory-format.md +65 -0
  21. package/.claude/skills/mutagent-evaluator/references/methodology.md +201 -0
  22. package/.claude/skills/mutagent-evaluator/references/operation-inventory.md +196 -0
  23. package/.claude/skills/mutagent-evaluator/references/validate-evaluator.md +125 -0
  24. package/.claude/skills/mutagent-evaluator/references/workflows/orchestrator-protocol.md +287 -0
  25. package/.claude/skills/mutagent-evaluator/references/write-judge-prompt.md +123 -0
  26. package/.claude/skills/mutagent-evaluator/schemas/behavior-tree.schema.yaml +73 -0
  27. package/.claude/skills/mutagent-evaluator/schemas/dataset.schema.yaml +66 -0
  28. package/.claude/skills/mutagent-evaluator/schemas/edd-change-request.schema.yaml +114 -0
  29. package/.claude/skills/mutagent-evaluator/schemas/eval-matrix.schema.yaml +74 -0
  30. package/.claude/skills/mutagent-evaluator/schemas/flow-graph.schema.yaml +69 -0
  31. package/.claude/skills/mutagent-evaluator/schemas/flow-profile.schema.yaml +49 -0
  32. package/.claude/skills/mutagent-evaluator/schemas/methodology-review.schema.yaml +40 -0
  33. package/.claude/skills/mutagent-evaluator/schemas/scorecard.schema.yaml +85 -0
  34. package/.claude/skills/mutagent-evaluator/scripts/agent-dispatch.ts +0 -0
  35. package/.claude/skills/mutagent-evaluator/scripts/aggregate-discover.ts +543 -0
  36. package/.claude/skills/mutagent-evaluator/scripts/artifact-paths.ts +99 -0
  37. package/.claude/skills/mutagent-evaluator/scripts/assemble-scorecard.ts +172 -0
  38. package/.claude/skills/mutagent-evaluator/scripts/build-dataset.ts +186 -0
  39. package/.claude/skills/mutagent-evaluator/scripts/build-evals.ts +93 -0
  40. package/.claude/skills/mutagent-evaluator/scripts/build-review-ui.ts +393 -0
  41. package/.claude/skills/mutagent-evaluator/scripts/check-method-router.ts +170 -0
  42. package/.claude/skills/mutagent-evaluator/scripts/cli/aggregate.ts +112 -0
  43. package/.claude/skills/mutagent-evaluator/scripts/cli/audit-run.ts +175 -0
  44. package/.claude/skills/mutagent-evaluator/scripts/cli/doctor.ts +211 -0
  45. package/.claude/skills/mutagent-evaluator/scripts/cli/dogfood.ts +133 -0
  46. package/.claude/skills/mutagent-evaluator/scripts/cli/init.ts +601 -0
  47. package/.claude/skills/mutagent-evaluator/scripts/cli/methodology-review.ts +122 -0
  48. package/.claude/skills/mutagent-evaluator/scripts/cli/prep.ts +279 -0
  49. package/.claude/skills/mutagent-evaluator/scripts/cli/profile-subject.ts +165 -0
  50. package/.claude/skills/mutagent-evaluator/scripts/cli/run.sh +56 -0
  51. package/.claude/skills/mutagent-evaluator/scripts/cli/variance-check.ts +105 -0
  52. package/.claude/skills/mutagent-evaluator/scripts/code-eval.ts +248 -0
  53. package/.claude/skills/mutagent-evaluator/scripts/codegen-evals.ts +173 -0
  54. package/.claude/skills/mutagent-evaluator/scripts/cold-start-project.ts +151 -0
  55. package/.claude/skills/mutagent-evaluator/scripts/cold-start-sampler.ts +267 -0
  56. package/.claude/skills/mutagent-evaluator/scripts/config/load.ts +307 -0
  57. package/.claude/skills/mutagent-evaluator/scripts/config/schema.ts +325 -0
  58. package/.claude/skills/mutagent-evaluator/scripts/contracts/agentspec-evals.ts +85 -0
  59. package/.claude/skills/mutagent-evaluator/scripts/contracts/dataset.ts +149 -0
  60. package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-engine.ts +118 -0
  61. package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-matrix.ts +577 -0
  62. package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-types.ts +1074 -0
  63. package/.claude/skills/mutagent-evaluator/scripts/contracts/flow-graph.ts +194 -0
  64. package/.claude/skills/mutagent-evaluator/scripts/contracts/types.ts +303 -0
  65. package/.claude/skills/mutagent-evaluator/scripts/contracts/validation.ts +193 -0
  66. package/.claude/skills/mutagent-evaluator/scripts/derive-dataset.ts +152 -0
  67. package/.claude/skills/mutagent-evaluator/scripts/determine-outcome.ts +219 -0
  68. package/.claude/skills/mutagent-evaluator/scripts/diff-discriminate.ts +160 -0
  69. package/.claude/skills/mutagent-evaluator/scripts/discover-criteria.ts +348 -0
  70. package/.claude/skills/mutagent-evaluator/scripts/edd/change-request.ts +232 -0
  71. package/.claude/skills/mutagent-evaluator/scripts/edd/edd-types.ts +210 -0
  72. package/.claude/skills/mutagent-evaluator/scripts/edd/variance-gate.ts +186 -0
  73. package/.claude/skills/mutagent-evaluator/scripts/emit-completeness.ts +111 -0
  74. package/.claude/skills/mutagent-evaluator/scripts/eval-engine.ts +160 -0
  75. package/.claude/skills/mutagent-evaluator/scripts/evaluate.ts +333 -0
  76. package/.claude/skills/mutagent-evaluator/scripts/flow-graph.ts +230 -0
  77. package/.claude/skills/mutagent-evaluator/scripts/judge-prompt-template.ts +253 -0
  78. package/.claude/skills/mutagent-evaluator/scripts/judge-provider.ts +135 -0
  79. package/.claude/skills/mutagent-evaluator/scripts/lint-grounding.ts +229 -0
  80. package/.claude/skills/mutagent-evaluator/scripts/lint-uniformity.ts +168 -0
  81. package/.claude/skills/mutagent-evaluator/scripts/living-suite.ts +109 -0
  82. package/.claude/skills/mutagent-evaluator/scripts/load-bundle.ts +203 -0
  83. package/.claude/skills/mutagent-evaluator/scripts/load-profile-vocab.ts +64 -0
  84. package/.claude/skills/mutagent-evaluator/scripts/load-profile.ts +106 -0
  85. package/.claude/skills/mutagent-evaluator/scripts/mask.ts +138 -0
  86. package/.claude/skills/mutagent-evaluator/scripts/materialize-dataset.ts +113 -0
  87. package/.claude/skills/mutagent-evaluator/scripts/matrix-judge.ts +750 -0
  88. package/.claude/skills/mutagent-evaluator/scripts/memory/append.ts +215 -0
  89. package/.claude/skills/mutagent-evaluator/scripts/memory/read.ts +168 -0
  90. package/.claude/skills/mutagent-evaluator/scripts/prep-tasks.ts +125 -0
  91. package/.claude/skills/mutagent-evaluator/scripts/profile-subject.ts +310 -0
  92. package/.claude/skills/mutagent-evaluator/scripts/publish-report.ts +131 -0
  93. package/.claude/skills/mutagent-evaluator/scripts/read-unitf-traces.ts +81 -0
  94. package/.claude/skills/mutagent-evaluator/scripts/render-build-cards.ts +195 -0
  95. package/.claude/skills/mutagent-evaluator/scripts/render-discover-report.ts +1640 -0
  96. package/.claude/skills/mutagent-evaluator/scripts/render-eval-report.ts +3823 -0
  97. package/.claude/skills/mutagent-evaluator/scripts/render-report.ts +212 -0
  98. package/.claude/skills/mutagent-evaluator/scripts/resolve-credential.ts +110 -0
  99. package/.claude/skills/mutagent-evaluator/scripts/resolve-ref.ts +98 -0
  100. package/.claude/skills/mutagent-evaluator/scripts/result-verify.ts +129 -0
  101. package/.claude/skills/mutagent-evaluator/scripts/route-failures.ts +320 -0
  102. package/.claude/skills/mutagent-evaluator/scripts/run-deterministic.ts +271 -0
  103. package/.claude/skills/mutagent-evaluator/scripts/run-evaluate.ts +715 -0
  104. package/.claude/skills/mutagent-evaluator/scripts/run-judge.ts +155 -0
  105. package/.claude/skills/mutagent-evaluator/scripts/run-pipeline.ts +175 -0
  106. package/.claude/skills/mutagent-evaluator/scripts/sample-traces.ts +210 -0
  107. package/.claude/skills/mutagent-evaluator/scripts/self-audit.ts +387 -0
  108. package/.claude/skills/mutagent-evaluator/scripts/source-map.ts +106 -0
  109. package/.claude/skills/mutagent-evaluator/scripts/subject-profile.ts +134 -0
  110. package/.claude/skills/mutagent-evaluator/scripts/substrate.ts +162 -0
  111. package/.claude/skills/mutagent-evaluator/scripts/ui-slots.ts +119 -0
  112. package/.claude/skills/mutagent-evaluator/scripts/unitf-to-evaltrace.ts +284 -0
  113. package/.claude/skills/mutagent-evaluator/scripts/validate-judge.ts +358 -0
  114. package/.claude/skills/mutagent-evaluator/scripts/variance-compare.ts +177 -0
  115. package/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/behavior-tree.yaml +140 -0
  116. package/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/eval-matrix.yaml +1270 -0
  117. package/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/methodology-review.yaml +105 -0
  118. package/.claude/skills/mutagent-evaluator/workflows/audit.workflow.js +82 -0
  119. package/.claude/skills/mutagent-evaluator/workflows/data-leak.workflow.js +236 -0
  120. package/.claude/skills/mutagent-evaluator/workflows/variance.workflow.js +163 -0
  121. package/LICENSE +201 -0
  122. package/NOTICE +23 -0
  123. package/README.md +90 -0
  124. package/bin/mutagent-cli.mjs +9263 -0
  125. package/bin/mutagent-evaluator.mjs +96 -0
  126. 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
+ }