Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
.vite/
94 changes: 94 additions & 0 deletions src/contracts/layer2-integrity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Layer 2 Validation record validators. Implements TC-L2-01..06.
*
* See: https://github.com/Source-Engineering/source-engineering-specifications/blob/main/compatibility-test-suite.md
* See: RFC-0001 (v0.2 floor: Layer 2).
*/

import type { Cots } from "../types.js";
import { type Result, combine, fail, pass } from "../result.js";

const FLAG_TYPES = [
"drift-detected",
"segment-signal-divergence",
"parameter-set-out-of-range",
"temporal-validity-expired",
] as const;

const DECISIONS_ON_VALIDATION = ["passed", "flagged", "escalated"] as const;

const isIso8601 = (value: string): boolean => !Number.isNaN(Date.parse(value));

/**
* TC-L2-01 .. TC-L2-06. Validates every DecisionRecord's optional
* `validation` field. The field is optional: a missing field passes
* (TC-L2-06, the producer has not floored Layer 2).
*/
export const validateLayer2Records = (cots: Cots): Result => {
const errors: Result[] = [];

cots.decisions.forEach((decision, index) => {
const v = decision.validation;
if (v === undefined) {
return;
}

if (!Array.isArray(v.flags)) {
errors.push(fail("TC-L2-01", `decisions[${index}].validation.flags is not an array`));
return;
}

v.flags.forEach((flag, fIndex) => {
if (!(FLAG_TYPES as readonly string[]).includes(flag.flag_type)) {
errors.push(
fail(
"TC-L2-02",
`decisions[${index}].validation.flags[${fIndex}].flag_type '${flag.flag_type}' is not in the declared enum`
)
);
}
if (!isIso8601(flag.detected_at)) {
errors.push(
fail(
"TC-L2-01",
`decisions[${index}].validation.flags[${fIndex}].detected_at is not a valid ISO-8601 timestamp`
)
);
}
});

if (!(DECISIONS_ON_VALIDATION as readonly string[]).includes(v.decision_on_validation)) {
errors.push(
fail(
"TC-L2-03",
`decisions[${index}].validation.decision_on_validation '${v.decision_on_validation}' is not in the declared enum (passed, flagged, escalated). Layer 2 does not reject; it flags.`
)
);
} else if (
(v.flags.length > 0 && v.decision_on_validation === "passed") ||
(v.flags.length === 0 && v.decision_on_validation !== "passed")
) {
errors.push(
fail(
"TC-L2-04",
`decisions[${index}].validation: decision_on_validation '${v.decision_on_validation}' is inconsistent with ${v.flags.length} flags`
)
);
}

if (!isIso8601(v.validated_at)) {
errors.push(
fail("TC-L2-05", `decisions[${index}].validation.validated_at is not a valid ISO-8601 timestamp`)
);
}

if (typeof v.validated_by !== "string" || v.validated_by.length === 0) {
errors.push(fail("TC-L2-01", `decisions[${index}].validation.validated_by is missing or empty`));
}
});

if (errors.length === 0) {
return pass();
}
return combine(...errors);
};
163 changes: 163 additions & 0 deletions src/fixtures/layer2-bad-decision.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
{
"cots_version": "0.1.0",
"cots_id": "urn:source-engineering:cots:00000000-0000-0000-0000-000000000001",
"produced_at": "2026-10-11T12:00:00Z",
"produced_by": {
"system_name": "test-fixture",
"system_version": "0.1.0"
},
"inputs": {
"source_artifacts": [
{
"id": "urn:source-engineering:source:contract-2026-001",
"origin": {
"system_name": "Acme Contracts",
"system_version": "1.0.0",
"configuration_hash": "0000000000000000000000000000000000000000000000000000000000000001"
},
"version": {
"content_hash": "1111111111111111111111111111111111111111111111111111111111111111",
"issued_at": "2026-10-10T08:00:00Z"
},
"authority": {
"asserted_by": "acme-contracts",
"trust_score": 0.95
},
"temporal_validity": {
"valid_from": "2026-10-10T08:00:00Z",
"valid_until": null
},
"content_reference": {
"uri": "https://example.com/contracts/2026-001.pdf",
"media_type": "application/pdf"
}
}
]
},
"context": {
"model": {
"model_name": "claude-sonnet-4-5",
"model_version": "2026-09-15"
},
"parameters": {
"temperature": 0.3,
"top_p": 0.95,
"prompt_cache_id": null,
"tool_budget": 8,
"retrieval_depth": 5
},
"constraints": [
{
"id": "urn:source-engineering:constraint:jurisdiction-001",
"type": "jurisdiction",
"scope": "all_decisions",
"value": "US-NY"
}
]
},
"decisions": [
{
"id": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"decision_text": "The contract is a standard commercial services agreement with mutual indemnification, a 30-day termination notice, and a New York governing-law clause.",
"basis_id": "urn:source-engineering:basis:00000000-0000-0000-0000-000000000001",
"evidence_chain_ref": "urn:source-engineering:evidence-chain:00000000-0000-0000-0000-000000000001",
"validation_status": {
"status": "pending",
"last_changed_at": "2026-10-11T12:00:00Z",
"last_changed_by": "test-fixture"
},
"responsible_authority": {
"authority_id": "claude-sonnet-4-5",
"authority_type": "automated"
},
"audit_history": [
{
"id": "urn:source-engineering:audit:00000000-0000-0000-0000-000000000001",
"action": "created",
"performed_by": "test-fixture",
"performed_at": "2026-10-11T12:00:00Z",
"notes": "Initial creation."
}
],
"created_at": "2026-10-11T12:00:00Z",
"validation": {
"flags": [],
"decision_on_validation": "rejected",
"validated_at": "2026-10-11T12:00:00Z",
"validated_by": "layer2-runtime-validation"
}
}
],
"evidence": {
"evidence_chain": [
{
"decision_id": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"supporting_evidence": [
{
"id": "urn:source-engineering:evidence:00000000-0000-0000-0000-000000000001",
"claim_id": "urn:source-engineering:claim:00000000-0000-0000-0000-000000000001",
"source_id": "urn:source-engineering:source:contract-2026-001",
"transformation": {
"operation": "extract_clause",
"inputs": [
"https://example.com/contracts/2026-001.pdf#section-7"
],
"output": "Section 7.1: Each party shall indemnify and hold harmless...",
"recorded_at": "2026-10-11T12:00:00Z"
},
"uncertainty": {
"calibrated_score": 0.92,
"basis": "Direct extraction from the section 7.1 text."
},
"polarity": "supports"
}
],
"contradicting_evidence": [
{
"id": "urn:source-engineering:evidence:00000000-0000-0000-0000-000000000002",
"claim_id": "urn:source-engineering:claim:00000000-0000-0000-0000-000000000001",
"source_id": "urn:source-engineering:source:contract-2026-001",
"transformation": {
"operation": "search_clause",
"inputs": [
"https://example.com/contracts/2026-001.pdf#section-12"
],
"output": "Section 12.4: This agreement shall be governed by the laws of the State of Delaware.",
"recorded_at": "2026-10-11T12:00:00Z"
},
"uncertainty": {
"calibrated_score": 0.78,
"basis": "Contradictory governing-law clause in section 12.4 (the model rejected it because section 14.1 is the prevailing clause)."
},
"polarity": "contradicts"
}
],
"claims": [
{
"id": "urn:source-engineering:claim:00000000-0000-0000-0000-000000000001",
"decision_record_id": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"claim_text": "The contract contains a mutual indemnification clause in section 7.1.",
"claim_type": "factual",
"supporting_evidence": [
"urn:source-engineering:evidence:00000000-0000-0000-0000-000000000001"
],
"contradicting_evidence": [
"urn:source-engineering:evidence:00000000-0000-0000-0000-000000000002"
]
}
]
}
]
},
"validation": {
"feedback_surfaces": [
{
"id": "urn:source-engineering:surface:00000000-0000-0000-0000-000000000001",
"type": "appeal",
"target": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"endpoint": "https://example.com/appeal/00000000-0000-0000-0000-000000000001",
"description": "File an appeal against this decision."
}
]
}
}
Loading
Loading