Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
054986d
feat(reviewer): add exact-claim evidence receipt contract
seonghobae Sep 7, 2026
2571d7f
test(reviewer): reject ambiguous receipt identities
seonghobae Sep 7, 2026
66c15f2
feat(reviewer): produce time-bounded claim receipts
seonghobae Sep 7, 2026
4b669ef
fix(reviewer): bind trusted receipt semantics
seonghobae Sep 7, 2026
46abf62
fix(reviewer): keep claim evidence in canonical package
seonghobae Sep 7, 2026
db28d7e
fix(reviewer): authenticate claim evidence manifests
seonghobae Sep 7, 2026
6fed7a6
test(reviewer): require canonical source evidence producer
seonghobae Sep 7, 2026
dd547c2
fix(reviewer): add canonical source evidence producer
seonghobae Sep 7, 2026
809aa6d
fix(reviewer): export canonical source evidence producer
seonghobae Sep 7, 2026
b6b25ce
test(reviewer): require canonical claim receipt references
seonghobae Sep 7, 2026
ed243aa
feat(reviewer): admit canonical claim receipt references
seonghobae Sep 7, 2026
9b48419
test(reviewer): require public receipt citation adapter
seonghobae Sep 7, 2026
2b123ec
feat(reviewer): export claim receipt citation port
seonghobae Sep 7, 2026
85d8044
test(reviewer): reproduce unbound publication evidence
seonghobae Sep 7, 2026
68d1cee
feat(reviewer): gate model findings on trusted receipts
seonghobae Sep 7, 2026
7a7168a
feat(reviewer): admit receipt evidence before deterministic gates
seonghobae Sep 7, 2026
942da88
feat(reviewer): load authenticated evidence before review
seonghobae Sep 7, 2026
f39fbbd
feat(reviewer): export trusted evidence runtime port
seonghobae Sep 7, 2026
b52d30e
feat(reviewer): attest source receipts through publication
seonghobae Sep 7, 2026
e8a78ee
test(reviewer): pass boolean CLI flags canonically
seonghobae Sep 7, 2026
863bb2d
test(reviewer): cover receipt producer and admission edges
seonghobae Sep 7, 2026
389cd49
test(reviewer): prove single-assignment receipt handoff
seonghobae Sep 7, 2026
ea0ef25
refactor(reviewer): keep receipt runtime minimal
seonghobae Sep 7, 2026
18431d6
docs(reviewer): record live receipt publication boundary
seonghobae Sep 7, 2026
676747e
docs(gap): bind source receipts and retain adapter gap
seonghobae Sep 7, 2026
45ecc9d
fix(reviewer): attest review and claim manifests separately
seonghobae Sep 7, 2026
c62535d
fix(reviewer): bind source receipts to finding coordinates
seonghobae Sep 7, 2026
5121e1e
test(reviewer): reject source receipt coordinate reuse
seonghobae Sep 7, 2026
81eef2a
test(reviewer): reject unreceipted model publication claims
seonghobae Sep 7, 2026
0d5eab3
fix(reviewer): project only authenticated claim authority
seonghobae Sep 7, 2026
5b5f4de
fix(reviewer): gate normalized model findings
seonghobae Sep 7, 2026
3d0275e
test(reviewer): verify authenticated publication projection
seonghobae Sep 7, 2026
52043d8
docs(reviewer): record model prose authority boundary
seonghobae Sep 7, 2026
174d0b0
docs(reviewer): trace receipt-authority projection
seonghobae Sep 7, 2026
f299381
test(reviewer): require trusted sandboxed_verify execution adapter
seonghobae Sep 7, 2026
ea751bc
feat(reviewer): adapt sandboxed_verify result into execution receipt
seonghobae Sep 7, 2026
fecb03d
feat(reviewer): export sandboxed_verify execution adapter
seonghobae Sep 7, 2026
5503700
merge current reviewer base without dropping evidence work
seonghobae Sep 8, 2026
451683f
test(reviewer): reject source-only runtime verdict authority
seonghobae Sep 8, 2026
9d6d52c
fix(reviewer): separate claim publication authority
seonghobae Sep 8, 2026
29cb77b
fix(docs): retain live PR authority invariant
seonghobae Sep 8, 2026
363d62b
Merge current reviewer base without dropping claim evidence work
seonghobae Sep 8, 2026
bd48185
Restack claim-evidence receipts onto protected #535 integration
seonghobae Sep 8, 2026
dbab4cd
test(reviewer): reject unbound source claim receipts
seonghobae Sep 8, 2026
440346e
fix(reviewer): bind source claims to exact line bytes
seonghobae Sep 8, 2026
920eb7b
test(reviewer): cover exact source-line binding edges
seonghobae Sep 8, 2026
1cd8db5
test(reviewer): align source-kind guard with exact line claim
seonghobae Sep 8, 2026
809ccb7
test(reviewer): remove unused runtime module import
seonghobae Sep 8, 2026
6629f07
test(reviewer): reproduce vacuous blocking verdict
seonghobae Sep 8, 2026
4c21537
fix(reviewer): require evidence for model non-approval
seonghobae Sep 8, 2026
860714c
docs(reviewer): record nonapproval evidence invariant
seonghobae Sep 8, 2026
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changelog

- Add a Noema-owned exact-claim evidence receipt contract for source, sandboxed execution, and immutable research artifacts. Admission binds producer-issued kind, exact repository/head/workflow/run/attempt, claim digest, artifact digest and size; model self-classification, stale identities, cross-kind receipts, and marker-only sandbox output fail closed. This is the owner prerequisite for ContextualWisdomLab/.github#1641 and issue #555; central consumers must wait for an immutable release.

## Unreleased
- Noema/naruon LLM 라우팅을 `contextual-orchestrator`의 paid-inclusive 전체 pool을 선택할 수 있던 bare 별칭 `contextual-orchestrator`에서 정규 라우팅 별칭 `orchestrator/free`(실패-폐쇄 zero-cost pool, ZDR-first)로 고정한다. `scripts/lib/orchestrator-gateway.mjs`의 공유 resolver는 `orchestrator/free`만 canonical alias로 허용하고, process/config anti-corruption boundary는 역사적 bare `contextual-orchestrator` 값만 즉시 `orchestrator/free`로 정규화한다. `orchestrator/auto`, 직접 provider 모델, 후보 목록은 계속 실패-폐쇄하며 `hourly-product-development`는 source에서 `orchestrator/free`를 고정한다. 따라서 관리자 측 model-variable migration은 안전한 rollout의 필수 선행조건이 아니며 provider routing/failover authority는 `contextual-orchestrator`에 남는다.
- Noema reviewer의 strict changed-file evidence를 historical 12-file prefix에서 canonical 80-file CodeGraph scope와 일치시켰다. 13–80 file PR은 선택된 모든 current-head file context를 유지하고 81개 이상은 기존처럼 실패-폐쇄하며, local CodeGraph fallback의 `HOME`·`TEMP`·`TMP`·`TMPDIR`은 ambient host path를 상속하지 않고 실행마다 새 private temporary directory로 격리한다.
Expand Down
18 changes: 18 additions & 0 deletions reviewer/noema_reviewer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@

from __future__ import annotations

from .claim_evidence import (
ClaimEvidenceReceipt,
EvidenceKind,
ExecutionClaimReceipt,
ResearchClaimReceipt,
SourceClaimReceipt,
admit_claim_evidence,
index_claim_evidence_receipts,
sha256_text,
)
from .agent import PydanticAIReviewAgent, ReviewAgent, build_agent
from .manifest import ReviewManifest
from .models import Confidence, Finding, ReviewVerdict, Severity, Verdict
Expand All @@ -32,6 +42,9 @@


__all__ = [
"ClaimEvidenceReceipt",
"EvidenceKind",
"ExecutionClaimReceipt",
"Confidence",
"DockerPatchValidationRunner",
"DockerPatchValidatorImageRunner",
Expand All @@ -45,12 +58,17 @@
"PatchValidatorImageResult",
"PatchValidatorImageStatus",
"PydanticAIReviewAgent",
"ResearchClaimReceipt",
"ReviewAgent",
"ReviewManifest",
"ReviewVerdict",
"Severity",
"SourceClaimReceipt",
"Verdict",
"admit_claim_evidence",
"build_agent",
"inspect_patch_bytes",
"index_claim_evidence_receipts",
"inspect_patch_for_image",
"sha256_text",
]
160 changes: 160 additions & 0 deletions reviewer/noema_reviewer/claim_evidence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
"""Exact-claim evidence receipts admitted by the Noema reviewer boundary.

Receipt producers run outside the untrusted model. This module validates their
sealed metadata and exact bytes; a model citation or self-declared claim kind is
never evidence authority by itself.
"""

from __future__ import annotations

import hashlib
from enum import Enum
from collections.abc import Sequence
from typing import Annotated, Literal

from pydantic import BaseModel, ConfigDict, Field, TypeAdapter


_SHA256_PATTERN = r"^[0-9a-f]{64}$"
_HEAD_SHA_PATTERN = r"^[0-9a-f]{40}$"
_REPOSITORY_PATTERN = r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$"
_WORKFLOW_REF_PATTERN = (
r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+/\.github/workflows/"
r"[A-Za-z0-9_.-]+\.ya?ml@[0-9a-f]{40}$"
)
_SLUG_PATTERN = r"^[a-z0-9][a-z0-9._-]{0,79}$"


class EvidenceKind(str, Enum):
"""Trusted producer classes; model prose cannot select admission authority."""

SOURCE = "source"
EXECUTION = "execution"
RESEARCH = "research"


class _ReceiptIdentity(BaseModel):
"""Exact workflow and artifact identity shared by every receipt class."""

model_config = ConfigDict(extra="forbid", frozen=True)

schema_version: Literal[1]
receipt_id: str = Field(pattern=_SLUG_PATTERN)
repository: str = Field(pattern=_REPOSITORY_PATTERN)
head_sha: str = Field(pattern=_HEAD_SHA_PATTERN)
workflow_ref: str = Field(pattern=_WORKFLOW_REF_PATTERN)
run_id: int = Field(gt=0)
run_attempt: int = Field(gt=0)
claim_sha256: str = Field(pattern=_SHA256_PATTERN)
artifact_sha256: str = Field(pattern=_SHA256_PATTERN)
artifact_size: int = Field(gt=0)
producer_version: str = Field(pattern=_SLUG_PATTERN)
policy_version: str = Field(pattern=_SLUG_PATTERN)


class SourceClaimReceipt(_ReceiptIdentity):
"""Receipt proving exact current-head source bytes, not external behavior."""

evidence_kind: Literal[EvidenceKind.SOURCE]
source_path: str = Field(min_length=1)
source_line: int = Field(gt=0)
source_line_sha256: str = Field(pattern=_SHA256_PATTERN)


class ExecutionClaimReceipt(_ReceiptIdentity):
"""Receipt proving one sandboxed execution result and its bounded output."""

evidence_kind: Literal[EvidenceKind.EXECUTION]
argv: tuple[str, ...] = Field(min_length=1)
tool_identity: str = Field(min_length=1)
tool_version: str = Field(min_length=1)
exit_code: int
stdout_sha256: str = Field(pattern=_SHA256_PATTERN)
stderr_sha256: str = Field(pattern=_SHA256_PATTERN)
isolation_policy: str = Field(min_length=1)
network_policy: str = Field(min_length=1)


class ResearchClaimReceipt(_ReceiptIdentity):
"""Receipt proving one immutable external-source retrieval and excerpt."""

evidence_kind: Literal[EvidenceKind.RESEARCH]
source_uri: str = Field(min_length=1)
source_revision: str = Field(min_length=1)
excerpt_sha256: str = Field(pattern=_SHA256_PATTERN)
retrieval_policy: str = Field(min_length=1)


ClaimEvidenceReceipt = Annotated[
SourceClaimReceipt | ExecutionClaimReceipt | ResearchClaimReceipt,
Field(discriminator="evidence_kind"),
]
_RECEIPT_ADAPTER = TypeAdapter(ClaimEvidenceReceipt)


def sha256_text(value: str) -> str:
"""Return the lowercase SHA-256 digest of exact UTF-8 claim bytes."""
return hashlib.sha256(value.encode("utf-8")).hexdigest()


def index_claim_evidence_receipts(
payloads: Sequence[object],
) -> dict[str, ClaimEvidenceReceipt]:
"""Validate receipt schemas and index unique producer-issued identities."""
indexed: dict[str, ClaimEvidenceReceipt] = {}
for payload in payloads:
receipt = _RECEIPT_ADAPTER.validate_python(payload)
if receipt.receipt_id in indexed:
raise ValueError("duplicate claim evidence receipt ID")
indexed[receipt.receipt_id] = receipt
return indexed


def admit_claim_evidence(
payload: object,
*,
claim: str,
artifact: bytes,
expected_repository: str,
expected_head_sha: str,
expected_workflow_ref: str,
expected_run_id: int,
expected_run_attempt: int,
required_kind: EvidenceKind,
) -> ClaimEvidenceReceipt:
"""Validate a sealed receipt against caller-owned identity and exact bytes.

The required kind comes from the trusted producer channel, never from model
output. The model may only cite a receipt ID after this admission passes.

Raises:
ValueError: If exact identity, kind, claim bytes, or artifact bytes do
not match the producer receipt.
pydantic.ValidationError: If the receipt schema itself is malformed.
"""
receipt = _RECEIPT_ADAPTER.validate_python(payload)
observed_identity = (
receipt.repository,
receipt.head_sha,
receipt.workflow_ref,
receipt.run_id,
receipt.run_attempt,
)
expected_identity = (
expected_repository,
expected_head_sha,
expected_workflow_ref,
expected_run_id,
expected_run_attempt,
)
if observed_identity != expected_identity:
raise ValueError("claim evidence receipt identity mismatch")
if receipt.evidence_kind != required_kind:
raise ValueError("claim evidence receipt kind mismatch")
if receipt.claim_sha256 != sha256_text(claim):
raise ValueError("claim evidence receipt claim digest mismatch")
if receipt.artifact_size != len(artifact):
raise ValueError("claim evidence receipt artifact size mismatch")
if receipt.artifact_sha256 != hashlib.sha256(artifact).hexdigest():
raise ValueError("claim evidence receipt artifact digest mismatch")
return receipt
Loading
Loading