@sanity/ailf 7.2.0 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -17,7 +17,11 @@
17
17
  * area: "groq",
18
18
  * prompt: { text: "Write GROQ queries..." },
19
19
  * assertions: [
20
- * { type: "llm-rubric", template: "task-completion", criteria: ["..."] },
20
+ * {
21
+ * type: "llm-rubric",
22
+ * template: "task-completion",
23
+ * criteria: [{ id: "uses-projection", text: "Uses a projection" }],
24
+ * },
21
25
  * ],
22
26
  * })
23
27
  * ```
package/dist/index.js CHANGED
@@ -17,7 +17,11 @@
17
17
  * area: "groq",
18
18
  * prompt: { text: "Write GROQ queries..." },
19
19
  * assertions: [
20
- * { type: "llm-rubric", template: "task-completion", criteria: ["..."] },
20
+ * {
21
+ * type: "llm-rubric",
22
+ * template: "task-completion",
23
+ * criteria: [{ id: "uses-projection", text: "Uses a projection" }],
24
+ * },
21
25
  * ],
22
26
  * })
23
27
  * ```
@@ -153,9 +153,13 @@ function mapTemplatedAssertion(assertion, options) {
153
153
  const result = {
154
154
  type: "llm-rubric",
155
155
  // The rubric prompt will be fully assembled by the PromptfooCompiler
156
- // using rubric templates. Here we pass the template ref + criteria
157
- // as metadata so the compiler can resolve it.
158
- value: `[template:${assertion.template}] ${assertion.criteria.join("; ")}`,
156
+ // using rubric templates. Here we pass the template ref + criteria as
157
+ // metadata so the compiler can resolve it. Criteria are either legacy
158
+ // bare strings or canonical `{ id, text }` objects — render the text of
159
+ // each (interpolating an object directly would emit "[object Object]").
160
+ value: `[template:${assertion.template}] ${assertion.criteria
161
+ .map((c) => (typeof c === "string" ? c : c.text))
162
+ .join("; ")}`,
159
163
  };
160
164
  if (assertion.weight !== undefined) {
161
165
  result.weight = assertion.weight;
@@ -13,7 +13,7 @@
13
13
  * @see docs/design-docs/two-stage-grader-symbol-preflight.md — W0198 Phase 6
14
14
  * @see config/rubrics.ts — template definitions
15
15
  */
16
- import type { PreflightRubricContext } from "../../_vendor/ailf-core/index.d.ts";
16
+ import type { CriterionRef, PreflightRubricContext } from "../../_vendor/ailf-core/index.d.ts";
17
17
  import type { PromptfooAssertion } from "./assertion-mapper.js";
18
18
  export type { PreflightRubricContext } from "../../_vendor/ailf-core/index.d.ts";
19
19
  /** Minimal rubric config needed for template resolution */
@@ -59,7 +59,7 @@ export interface RubricResolutionInput {
59
59
  * Returns null (with a warning) if the template can't be resolved.
60
60
  */
61
61
  export declare function resolveTemplatedAssertion(assertion: {
62
- criteria: string[];
62
+ criteria: (string | CriterionRef)[];
63
63
  template: string;
64
64
  type: string;
65
65
  }, rubricConfig: RubricResolutionInput | undefined, graderProvider: string | undefined, warnings: string[], canonicalReference?: string, preflightContext?: PreflightRubricContext): PromptfooAssertion | null;
@@ -45,7 +45,9 @@ export function resolveTemplatedAssertion(assertion, rubricConfig, graderProvide
45
45
  return null;
46
46
  }
47
47
  const scaleText = template.scale.map((s) => `- ${s}`).join("\n");
48
- const criteriaText = assertion.criteria.map((c) => `- ${c}`).join("\n");
48
+ const criteriaText = assertion.criteria
49
+ .map((c) => renderCriterion(c, assertion.template))
50
+ .join("\n");
49
51
  // W0198 Phase 6 — when the deterministic preflight lane is wired and this
50
52
  // rubric scores `code-correctness`, prefix a system instruction so the
51
53
  // grader does not re-judge symbol existence. The lane separation is the
@@ -79,6 +81,28 @@ export function resolveTemplatedAssertion(assertion, rubricConfig, graderProvide
79
81
  : {}),
80
82
  };
81
83
  }
84
+ /**
85
+ * Render a single rubric criterion to its bullet line.
86
+ *
87
+ * Criteria come in two shapes: the canonical `CriterionRef` object
88
+ * (`{ id, text }`, used by Content Lake / API tasks) and a legacy bare
89
+ * string (still used by many repo `defineTask` task files). Both render to
90
+ * their text. Interpolating a `CriterionRef` object directly (`- ${c}`)
91
+ * silently renders `- [object Object]`, stripping the grader's acceptance
92
+ * criteria and degrading grade quality — that is the bug this guards. A
93
+ * criterion that yields no renderable text (e.g. an object missing `text`)
94
+ * fails loud at compile time rather than reaching the grader.
95
+ */
96
+ function renderCriterion(criterion, template) {
97
+ const text = typeof criterion === "string" ? criterion : criterion?.text;
98
+ if (typeof text !== "string" || text.trim() === "") {
99
+ throw new Error(`Rubric template "${template}" has a criterion with no renderable text ` +
100
+ `(received: ${JSON.stringify(criterion)?.slice(0, 160)}). Each criterion ` +
101
+ `must be a non-empty string or a { id, text } object; an object without ` +
102
+ `text renders "[object Object]" in the grader prompt.`);
103
+ }
104
+ return `- ${text}`;
105
+ }
82
106
  /**
83
107
  * Build the W0198 Phase 6 preflight preface for a `code-correctness`
84
108
  * rubric. Returned with a trailing newline so it composes cleanly with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ailf",
3
- "version": "7.2.0",
3
+ "version": "7.2.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"