From 1ff61be36304db5c525b48655d854d7bc138dfab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 26 Jul 2026 20:50:39 +0000 Subject: [PATCH] feat(validation): improve missing-field error descriptions for constrained string schemas describeSchemaType now returns human-readable hints for s.nonEmptyString, s.url, s.date, and s.path when used as required object fields. Previously all string variants reported 'expected string'; now they report 'non-empty string', 'URL string', 'date string (YYYY-MM-DD)', or 'path string' so repair prompts give the model clearer guidance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/rig/rig.ts | 7 +++++++ src/rig.test.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/skills/rig/rig.ts b/skills/rig/rig.ts index f201a49..8650865 100644 --- a/skills/rig/rig.ts +++ b/skills/rig/rig.ts @@ -2652,6 +2652,13 @@ function describeSchemaType(schema: Schema): string { return `array of ${itemType}`; } if ("type" in schema) { + if ((schema as { type: string }).type === "string") { + const { minLength, format } = schema as StringSchema; + if (format === "uri") return "URL string"; + if (format === "date") return "date string (YYYY-MM-DD)"; + if (format === "path") return "path string"; + if (minLength !== undefined && minLength > 0) return "non-empty string"; + } return (schema as { type: string }).type; } if ("enum" in schema) { diff --git a/src/rig.test.ts b/src/rig.test.ts index 406cc18..a25c693 100644 --- a/src/rig.test.ts +++ b/src/rig.test.ts @@ -1962,4 +1962,48 @@ describe("missing required field error message", () => { expect(result.error.message).toContain("any"); } }); + + it("reports a missing required s.nonEmptyString field as 'non-empty string'", () => { + const schema = s.object({ slug: s.nonEmptyString, name: s.string }); + const result = analyzeResponse(JSON.stringify({ name: "x" }), schema, "test", 1); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error.message).toContain("missing required field"); + expect(result.error.message).toContain("$.slug"); + expect(result.error.message).toContain("non-empty string"); + } + }); + + it("reports a missing required s.url field as 'URL string'", () => { + const schema = s.object({ endpoint: s.url, name: s.string }); + const result = analyzeResponse(JSON.stringify({ name: "x" }), schema, "test", 1); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error.message).toContain("missing required field"); + expect(result.error.message).toContain("$.endpoint"); + expect(result.error.message).toContain("URL string"); + } + }); + + it("reports a missing required s.date field as 'date string (YYYY-MM-DD)'", () => { + const schema = s.object({ createdAt: s.date, name: s.string }); + const result = analyzeResponse(JSON.stringify({ name: "x" }), schema, "test", 1); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error.message).toContain("missing required field"); + expect(result.error.message).toContain("$.createdAt"); + expect(result.error.message).toContain("date string (YYYY-MM-DD)"); + } + }); + + it("reports a missing required s.path field as 'path string'", () => { + const schema = s.object({ filePath: s.path, name: s.string }); + const result = analyzeResponse(JSON.stringify({ name: "x" }), schema, "test", 1); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error.message).toContain("missing required field"); + expect(result.error.message).toContain("$.filePath"); + expect(result.error.message).toContain("path string"); + } + }); });