Skip to content
Open
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
7 changes: 7 additions & 0 deletions artifacts/cacert.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"decision_id": "dec-001",
"verdict": "PASS",
"admissibility_score": 100,
"evidence_hash": "adb2ce6d5995be6b1e12e139825c5d309b1c6232fc256f3a2195e0c49839a042",
"signed": true
}
27 changes: 27 additions & 0 deletions artifacts/sample-decision-bundle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"decision_id": "dec-001",
"input_sources": [
{
"source_id": "src-1",
"uri": "https://intelgraph.local/source/1",
"content_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"verified": true
}
],
"transformation_steps": [
{
"step_id": "step-1",
"operation": "normalize",
"input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
}
],
"model_used": "summit-cac-model-v1",
"confidence_score": 0.93,
"uncertainty_flag": false,
"decision_output": {
"action": "ALLOW",
"rationale": "Sources verified and evidence consistent"
},
"reproducibility_hash": "828003e4bbc1dda644c776428735ca2ba184f89a6ebbabf573041396de874fdc"
}
19 changes: 19 additions & 0 deletions demos/cac_failures/01-missing-provenance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"decision_id": "dec-fail-01",
"input_sources": [],
"transformation_steps": [
{
"step_id": "step-1",
"operation": "normalize",
"input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
}
],
"model_used": "summit-cac-model-v1",
"confidence_score": 0.8,
"uncertainty_flag": false,
"decision_output": {
"action": "ALLOW"
},
"reproducibility_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
27 changes: 27 additions & 0 deletions demos/cac_failures/02-nondeterministic-output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"decision_id": "dec-fail-02",
"input_sources": [
{
"source_id": "src-1",
"uri": "https://intelgraph.local/source/1",
"content_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"verified": true
}
],
"transformation_steps": [
{
"step_id": "step-1",
"operation": "normalize",
"input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
}
],
"model_used": "summit-cac-model-v1",
"confidence_score": 0.8,
"uncertainty_flag": false,
"decision_output": {
"action": "ALLOW",
"timestamp": "2026-03-31T00:00:00Z"
},
"reproducibility_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
32 changes: 32 additions & 0 deletions demos/cac_failures/03-conflicting-sources.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"decision_id": "dec-fail-03",
"input_sources": [
{
"source_id": "src-1",
"uri": "https://intelgraph.local/source/1",
"content_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"verified": false
},
{
"source_id": "src-2",
"uri": "https://intelgraph.local/source/2",
"content_hash": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"verified": true
}
],
"transformation_steps": [
{
"step_id": "step-1",
"operation": "resolve_conflict",
"input_hash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"output_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
}
],
"model_used": "summit-cac-model-v1",
"confidence_score": 0.5,
"uncertainty_flag": true,
"decision_output": {
"action": "ALLOW"
},
"reproducibility_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
67 changes: 67 additions & 0 deletions docs/cac/CAC_SPEC_v0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Cognitive Admissibility Criteria (CAC) Specification v0.1

## 1. Purpose

This specification defines the mandatory admissibility contract for any decision artifact emitted by Summit execution paths.

A decision artifact is admissible only when it satisfies all normative requirements in this specification and passes the CAC validator with a `PASS` verdict.

## 2. Required Decision Fields

Each decision bundle **MUST** include the following top-level fields:

- `decision_id` (string, non-empty)
- `input_sources` (array, at least one entry)
- `transformation_steps` (array, at least one entry)
- `model_used` (string, non-empty)
- `confidence_score` (number between 0 and 1, inclusive)
- `uncertainty_flag` (boolean)
- `reproducibility_hash` (string, SHA-256 hex)

## 3. Input Source Admissibility

For each `input_sources[]` entry:

- `source_id` **MUST** be present and non-empty.
- `uri` **MUST** be present and non-empty.
- `content_hash` **MUST** be present and must be SHA-256 hex.
- `verified` **MUST** be `true` for admissibility.
- Unverified or unverifiable sources **MUST NOT** pass CAC.

## 4. Transformation Step Admissibility

For each `transformation_steps[]` entry:

- `step_id` **MUST** be present and non-empty.
- `operation` **MUST** be present and non-empty.
- `input_hash` **MUST** be SHA-256 hex.
- `output_hash` **MUST** be SHA-256 hex.

Transformation steps **MUST** represent a deterministic chain for identical input evidence and model configuration.

## 5. Determinism Requirements

- Decision bundles **MUST NOT** embed runtime-dependent fields inside deterministic artifacts (for example: dynamic timestamps, random seeds, hostnames, process IDs).
- Reproducibility **MUST** be checked by recomputing `reproducibility_hash` from a canonicalized payload that excludes `reproducibility_hash` itself.
- If recomputed hash differs from supplied hash, validation **MUST** fail.

## 6. Verdict Rules

- CAC validation **MUST** output a binary verdict: `PASS` or `FAIL`.
- Any missing required field **MUST** produce `FAIL`.
- Any determinism violation **MUST** produce `FAIL`.
- Any unverifiable source **MUST** produce `FAIL`.

## 7. Certification Requirements (CACert)

A CACert artifact may be generated only when verdict is `PASS`.

CACert **MUST** include:

- `decision_id`
- `verdict` (`PASS`)
- `admissibility_score`
- `evidence_hash`
- `signed` (`true` only when signing succeeds)

Unsigned artifacts **MUST NOT** be treated as certified.
53 changes: 53 additions & 0 deletions docs/cac/cac.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://summit.dev/schemas/cac.schema.json",
"title": "Cognitive Admissibility Decision Bundle",
"type": "object",
"required": [
"decision_id",
"input_sources",
"transformation_steps",
"model_used",
"confidence_score",
"uncertainty_flag",
"reproducibility_hash"
],
"additionalProperties": false,
"properties": {
Comment on lines +13 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align CAC schema with emitted decision_output field

The schema sets additionalProperties: false but does not define decision_output, while the emitted/validated bundles include that field as required. Any consumer that validates bundles against docs/cac/cac.schema.json will reject otherwise valid artifacts, so the machine-readable contract is internally inconsistent with the implemented validator and sample bundle format.

Useful? React with 👍 / 👎.

"decision_id": { "type": "string", "minLength": 1 },
"model_used": { "type": "string", "minLength": 1 },
"confidence_score": { "type": "number", "minimum": 0, "maximum": 1 },
"uncertainty_flag": { "type": "boolean" },
"reproducibility_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
"input_sources": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["source_id", "uri", "content_hash", "verified"],
"additionalProperties": false,
"properties": {
"source_id": { "type": "string", "minLength": 1 },
"uri": { "type": "string", "minLength": 1 },
"content_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
"verified": { "type": "boolean" }
}
}
},
"transformation_steps": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["step_id", "operation", "input_hash", "output_hash"],
"additionalProperties": false,
"properties": {
"step_id": { "type": "string", "minLength": 1 },
"operation": { "type": "string", "minLength": 1 },
"input_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
"output_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
}
}
}
}
}
19 changes: 19 additions & 0 deletions docs/governance/evidence_map.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: 1
owner: governance
flow:
- stage: decision
artifact: decision-trace
path: packages/core/decision-trace.ts
- stage: artifacts
artifact: decision-bundle
path: artifacts/sample-decision-bundle.json
- stage: validation
artifact: cac-verdict
path: artifacts/cac-verdict.json
- stage: certification
artifact: cacert
path: artifacts/cacert.json
contracts:
admissibility_spec: docs/cac/CAC_SPEC_v0.1.md
schema: docs/cac/cac.schema.json
validator: packages/validators/cac-validator.ts
16 changes: 8 additions & 8 deletions docs/roadmap/STATUS.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"last_updated": "2026-04-03T00:00:00Z",
"revision_note": "Added the canonical Decision Object v1 schema package, example payload, and standards documentation to anchor CAC-bound decision interoperability and external verification workflows.",
"last_updated": "2026-03-31T00:00:00Z",
"revision_note": "Bound CAC admissibility into CI as a hard gate, added deterministic decision trace emission, validator-enforced PASS/FAIL verdicts, CACert generation, and governed failure demos for missing provenance, non-determinism, and conflicting sources.",
"initiatives": [
{
"id": "one-verified-workflow-lane",
Expand Down Expand Up @@ -60,7 +60,7 @@
"id": "provable-system-governance-provenance-unification",
"status": "in_progress",
"owner": "codex",
"notes": "Implementation-ready governance, provenance, isolation, sovereignty, and ATO-native evidence bundle specifications are published and awaiting narrowed execution through one golden workflow. Published C2PA-aligned CAC Decision Manifest profile and external verification contract for admissible cognition artifacts."
"notes": "Implementation-ready governance, provenance, isolation, sovereignty, and ATO-native evidence bundle specifications are published and awaiting narrowed execution through one golden workflow."
},
{
"id": "antigravity-multi-agent-ga-convergence",
Expand All @@ -69,16 +69,16 @@
"notes": "Multi-agent prompt suites, bounded charters, and router activation are in place, but GA still depends on proving one deterministic closed loop rather than widening orchestration."
},
{
"id": "decision-object-canonicalization",
"status": "completed",
"id": "cac-enforcement-pipeline",
"status": "in_progress",
"owner": "codex",
"notes": "Published schemas/decision-object.schema.json plus a complete example and standards profile for CAC-bound deterministic verification."
"notes": "CAC spec and schema published, deterministic decision trace emitter and validator implemented, ci.yml now enforces cac_gate, CACert artifact generation wired for PASS verdicts, and demo failure cases are asserted in CI."
}
],
"summary": {
"total_initiatives": 12,
"completed": 5,
"in_progress": 7,
"completed": 4,
"in_progress": 8,
"at_risk": 0
}
}
96 changes: 96 additions & 0 deletions packages/core/decision-trace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { createHash } from 'node:crypto';

export interface CACInputSource {
source_id: string;
uri: string;
content_hash: string;
verified: boolean;
}

export interface CACTransformationStep {
step_id: string;
operation: string;
input_hash: string;
output_hash: string;
}

export interface DecisionTraceBundle {
decision_id: string;
input_sources: CACInputSource[];
transformation_steps: CACTransformationStep[];
model_used: string;
confidence_score: number;
uncertainty_flag: boolean;
decision_output: Record<string, unknown>;
reproducibility_hash: string;
}

interface DecisionTraceInput {
decision_id: string;
input_sources: CACInputSource[];
transformation_steps: CACTransformationStep[];
model_used: string;
confidence_score: number;
uncertainty_flag: boolean;
decision_output: Record<string, unknown>;
}

function stableSortObject(value: unknown): unknown {
if (Array.isArray(value)) {
return value.map(stableSortObject);
}

if (value && typeof value === 'object') {
return Object.keys(value as Record<string, unknown>)
.sort((a, b) => a.localeCompare(b))
.reduce<Record<string, unknown>>((acc, key) => {
acc[key] = stableSortObject((value as Record<string, unknown>)[key]);
return acc;
}, {});
}

return value;
}

export function canonicalize(value: unknown): string {
return JSON.stringify(stableSortObject(value));
}

export function sha256Hex(value: string): string {
return createHash('sha256').update(value).digest('hex');
}

export function computeReproducibilityHash(
payload: Omit<DecisionTraceBundle, 'reproducibility_hash'>,
): string {
return sha256Hex(canonicalize(payload));
}

export function emitDecisionTrace(input: DecisionTraceInput): DecisionTraceBundle {
const bundleWithoutHash: Omit<DecisionTraceBundle, 'reproducibility_hash'> = {
decision_id: input.decision_id,
input_sources: input.input_sources,
transformation_steps: input.transformation_steps,
model_used: input.model_used,
confidence_score: input.confidence_score,
uncertainty_flag: input.uncertainty_flag,
decision_output: input.decision_output,
};

return {
...bundleWithoutHash,
reproducibility_hash: computeReproducibilityHash(bundleWithoutHash),
};
}

export async function withDecisionTrace<T>(
traceInput: Omit<DecisionTraceInput, 'decision_output'>,
decisionFn: () => Promise<T> | T,
): Promise<DecisionTraceBundle> {
const decision_output = (await decisionFn()) as Record<string, unknown>;

return emitDecisionTrace({
...traceInput,
decision_output,
});
}
Loading
Loading