docs(evidence): publish curated-only workspace contract

This commit is contained in:
2026-08-25 01:52:27 +02:00
parent 619ac2e141
commit 9f0184388d
7 changed files with 153 additions and 14 deletions
+31 -3
View File
@@ -115,6 +115,7 @@ export type EvidenceSource =
};
export interface WorkspaceEvidence {
schema_version: 1 | 2;
source: EvidenceSource;
policy: EvidencePolicy;
}
@@ -246,10 +247,10 @@ const evidencePattern = z.string().refine(isSafeEvidencePattern, {
const filesystemEvidenceSourceSchema = z.object({
type: z.literal("filesystem"),
uri: z.string(),
patterns: z.array(evidencePattern).min(1).default(["**/*.md"]),
patterns: z.array(evidencePattern).min(1).optional(),
max_bytes: positiveSafeInteger.default(10 * 1024 * 1024),
}).strict().superRefine((source, context) => {
if (new Set(source.patterns).size !== source.patterns.length) {
if (source.patterns !== undefined && new Set(source.patterns).size !== source.patterns.length) {
context.addIssue({ code: "custom", path: ["patterns"], message: "evidence patterns must not repeat" });
}
});
@@ -323,12 +324,39 @@ const evidencePolicySchema = z.object({
retain_published_generations: positiveSafeInteger.default(3),
}).strict();
const workspaceEvidenceSchema = z.object({
schema_version: z.union([z.literal(1), z.literal(2)]).default(1),
source: evidenceSourceSchema,
policy: evidencePolicySchema.default({
max_chunk_chars: 4_000,
retain_published_generations: 3,
}),
}).strict();
}).strict().superRefine((evidence, context) => {
if (evidence.schema_version !== 2 || evidence.source.type !== "filesystem") return;
const patterns = evidence.source.patterns ?? ["curated/**/*.md"];
const selectsSource = patterns.some((pattern) => pattern === "source" || pattern.startsWith("source/"));
const selectsCurated = patterns.some((pattern) => pattern === "curated" || pattern.startsWith("curated/"));
if (selectsSource && selectsCurated) {
context.addIssue({
code: "custom",
path: ["source", "patterns"],
message: "schema-versioned filesystem Evidence patterns cannot span source and curated",
});
} else if (!patterns.every((pattern) => pattern === "curated" || pattern.startsWith("curated/"))) {
context.addIssue({
code: "custom",
path: ["source", "patterns"],
message: "schema-versioned filesystem Evidence patterns must acquire curated documents only",
});
}
}).transform((evidence) => ({
...evidence,
source: evidence.source.type !== "filesystem" || evidence.source.patterns !== undefined
? evidence.source
: {
...evidence.source,
patterns: evidence.schema_version === 2 ? ["curated/**/*.md"] : ["**/*.md"],
},
}));
function unique<T>(values: readonly T[], context: z.RefinementCtx, path: PropertyKey[]) {
if (new Set(values).size !== values.length) {
@@ -139,8 +139,14 @@ function evidenceSecretFile(name: string, contents: string): string {
return path;
}
function evidenceWorkspace(source: Record<string, unknown>, policy?: Record<string, unknown>) {
return parseWorkspaceYaml(`${canonicalEvidenceWorkspace}\nevidence:\n source: ${JSON.stringify(source)}${
function evidenceWorkspace(
source: Record<string, unknown>,
policy?: Record<string, unknown>,
evidenceSchemaVersion?: number,
) {
return parseWorkspaceYaml(`${canonicalEvidenceWorkspace}\nevidence:${
evidenceSchemaVersion === undefined ? "" : `\n schema_version: ${evidenceSchemaVersion}`
}\n source: ${JSON.stringify(source)}${
policy === undefined ? "" : `\n policy: ${JSON.stringify(policy)}`
}\n`);
}
@@ -180,9 +186,10 @@ function evidenceRender(
source: Record<string, unknown>,
evidenceBinding: RuntimeBindings["evidence"] = { missing: [], values: {} },
policy?: Record<string, unknown>,
evidenceSchemaVersion?: number,
) {
return renderRuntimeConfig(
evidenceWorkspace(source, policy),
evidenceWorkspace(source, policy, evidenceSchemaVersion),
{ ...directBindings, evidence: evidenceBinding },
paths,
evidenceContext,
@@ -195,7 +202,7 @@ test("renders filesystem Evidence below the immutable revision content root with
const yaml = evidenceRender({
type: "filesystem",
uri: "psd-clinical/evidence",
});
}, undefined, undefined, 2);
const rendered = parse(yaml);
expect(rendered.runtime_identity.workspace_revision).toBe(evidenceRevision);
@@ -203,7 +210,7 @@ test("renders filesystem Evidence below the immutable revision content root with
sources: [{
type: "filesystem",
root: `/srv/registry/snapshots/${evidenceRevision}/psd-clinical/evidence`,
patterns: ["**/*.md"],
patterns: ["curated/**/*.md"],
max_bytes: 10_485_760,
}],
});
+52
View File
@@ -390,6 +390,58 @@ test("applies filesystem and policy defaults to the canonical descriptor", () =>
});
});
test("defaults schema-versioned filesystem Evidence to curated documents only", () => {
const parsed = validateWorkspaceDescriptor({
...withEvidence({
type: "filesystem",
uri: "psd-clinical/evidence",
}),
evidence: {
schema_version: 2,
source: { type: "filesystem", uri: "psd-clinical/evidence" },
},
});
expect(parsed.evidence).toMatchObject({
schema_version: 2,
source: { patterns: ["curated/**/*.md"] },
});
});
test("rejects a schema-versioned Evidence layout that mixes source and curated runtime patterns", () => {
expectSafeEvidenceError({
...withEvidence({
type: "filesystem",
uri: "psd-clinical/evidence",
}),
evidence: {
schema_version: 2,
source: {
type: "filesystem",
uri: "psd-clinical/evidence",
patterns: ["source/**/*.md", "curated/**/*.md"],
},
},
}, /source.*curated|curated.*source/i);
});
test("rejects a schema-versioned Evidence layout that acquires source documents at runtime", () => {
expectSafeEvidenceError({
...withEvidence({
type: "filesystem",
uri: "psd-clinical/evidence",
}),
evidence: {
schema_version: 2,
source: {
type: "filesystem",
uri: "psd-clinical/evidence",
patterns: ["source/**/*.md"],
},
},
}, /curated/i);
});
test("keeps evidence optional on schema v3", () => {
expect(validateWorkspaceDescriptor(validWorkspaceObject())).not.toHaveProperty("evidence");
});