Skip to content

Commit 586e8a3

Browse files
authored
Refactor artifact file handling in evidence.py
1 parent 7c4c2d1 commit 586e8a3

1 file changed

Lines changed: 164 additions & 16 deletions

File tree

ix/evidence.py

Lines changed: 164 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,26 @@ def write_bundle(
4242
generated_at = datetime.now(UTC).isoformat().replace("+00:00", "Z")
4343
source_hash = self._sha256_file(source_file)
4444
result_payload = result.to_dict()
45+
contract_metadata = self._contract_metadata(result)
46+
contract_counts = self._contract_counts(contract_metadata)
47+
48+
artifact_files = [
49+
"summary.json",
50+
"trace.json",
51+
"policies.json",
52+
"tool-results.json",
53+
"handoffs.json",
54+
"branches.json",
55+
"approvals-required.json",
56+
"contract.json",
57+
"obligations.json",
58+
"falsification-gates.json",
59+
"claim-boundaries.json",
60+
"outputs.txt",
61+
"replies.txt",
62+
"assurance-claims.md",
63+
"limitations.md",
64+
]
4565

4666
files: list[Path] = []
4767
files.append(
@@ -55,19 +75,7 @@ def write_bundle(
5575
"source_file": str(source_file),
5676
"source_sha256": source_hash,
5777
"status": result.status,
58-
"artifact_files": [
59-
"summary.json",
60-
"trace.json",
61-
"policies.json",
62-
"tool-results.json",
63-
"handoffs.json",
64-
"branches.json",
65-
"approvals-required.json",
66-
"outputs.txt",
67-
"replies.txt",
68-
"assurance-claims.md",
69-
"limitations.md",
70-
],
78+
"artifact_files": artifact_files,
7179
},
7280
)
7381
)
@@ -88,6 +96,14 @@ def write_bundle(
8896
"handoffs": len(result.handoffs),
8997
"branches": len(result.branches),
9098
"approvals_required": len(result.approvals_required),
99+
"contract_attempts": contract_counts["attempts"],
100+
"contract_obligations": contract_counts["obligations"],
101+
"contract_evidence_requirements": contract_counts[
102+
"evidence_requirements"
103+
],
104+
"contract_falsification_gates": contract_counts[
105+
"falsification_gates"
106+
],
91107
},
92108
"variables": result_payload["variables"],
93109
"memory": result_payload["memory"],
@@ -99,14 +115,136 @@ def write_bundle(
99115
files.append(self._write_json(output_dir / "tool-results.json", result.tool_results))
100116
files.append(self._write_json(output_dir / "handoffs.json", result.handoffs))
101117
files.append(self._write_json(output_dir / "branches.json", result.branches))
102-
files.append(self._write_json(output_dir / "approvals-required.json", result.approvals_required))
118+
files.append(
119+
self._write_json(output_dir / "approvals-required.json", result.approvals_required)
120+
)
121+
files.append(self._write_json(output_dir / "contract.json", contract_metadata))
122+
files.append(
123+
self._write_json(
124+
output_dir / "obligations.json",
125+
self._obligations_payload(contract_metadata),
126+
)
127+
)
128+
files.append(
129+
self._write_json(
130+
output_dir / "falsification-gates.json",
131+
self._falsification_payload(contract_metadata),
132+
)
133+
)
134+
files.append(
135+
self._write_json(
136+
output_dir / "claim-boundaries.json",
137+
self._claim_boundaries_payload(contract_metadata),
138+
)
139+
)
103140
files.append(self._write_text(output_dir / "outputs.txt", "\n".join(result.outputs) + "\n"))
104141
files.append(self._write_text(output_dir / "replies.txt", "\n".join(result.replies) + "\n"))
105142
files.append(self._write_text(output_dir / "assurance-claims.md", self._claims_text(result)))
106143
files.append(self._write_text(output_dir / "limitations.md", self._limitations_text()))
107144

108145
return EvidenceBundle(output_dir=output_dir, files=tuple(files))
109146

147+
def _contract_metadata(self, result: ExecutionResult) -> dict[str, Any]:
148+
metadata = getattr(result, "contract_metadata", None)
149+
if isinstance(metadata, dict):
150+
return metadata
151+
return {
152+
"contract_type": "ix.cognition.contracts",
153+
"schema_version": "1.0",
154+
"runtime_semantics": "metadata_only_not_executed",
155+
"counts": {
156+
"attempts": 0,
157+
"obligations": 0,
158+
"evidence_requirements": 0,
159+
"falsification_gates": 0,
160+
},
161+
"attempts": [],
162+
}
163+
164+
def _contract_counts(self, metadata: dict[str, Any]) -> dict[str, int]:
165+
counts = metadata.get("counts", {})
166+
if not isinstance(counts, dict):
167+
counts = {}
168+
return {
169+
"attempts": int(counts.get("attempts", 0)),
170+
"obligations": int(counts.get("obligations", 0)),
171+
"evidence_requirements": int(counts.get("evidence_requirements", 0)),
172+
"falsification_gates": int(counts.get("falsification_gates", 0)),
173+
}
174+
175+
def _obligations_payload(self, metadata: dict[str, Any]) -> dict[str, Any]:
176+
obligations: list[dict[str, Any]] = []
177+
for attempt in self._attempts(metadata):
178+
attempt_name = str(attempt.get("name", ""))
179+
for obligation in self._obligations(attempt):
180+
obligations.append(
181+
{
182+
"attempt": attempt_name,
183+
"id": obligation.get("id"),
184+
"source": obligation.get("source"),
185+
"evidence_required": list(obligation.get("evidence_required", [])),
186+
"falsify_if": list(obligation.get("falsify_if", [])),
187+
}
188+
)
189+
return {
190+
"schema_version": "1.0",
191+
"runtime_semantics": metadata.get("runtime_semantics"),
192+
"obligations": obligations,
193+
}
194+
195+
def _falsification_payload(self, metadata: dict[str, Any]) -> dict[str, Any]:
196+
gates: list[dict[str, Any]] = []
197+
for attempt in self._attempts(metadata):
198+
attempt_name = str(attempt.get("name", ""))
199+
for obligation in self._obligations(attempt):
200+
obligation_id = obligation.get("id")
201+
for condition in obligation.get("falsify_if", []):
202+
gates.append(
203+
{
204+
"attempt": attempt_name,
205+
"obligation": obligation_id,
206+
"condition": condition,
207+
}
208+
)
209+
return {
210+
"schema_version": "1.0",
211+
"runtime_semantics": metadata.get("runtime_semantics"),
212+
"falsification_gates": gates,
213+
}
214+
215+
def _claim_boundaries_payload(self, metadata: dict[str, Any]) -> dict[str, Any]:
216+
attempts: list[dict[str, Any]] = []
217+
for attempt in self._attempts(metadata):
218+
attempts.append(
219+
{
220+
"attempt": attempt.get("name"),
221+
"purpose": list(attempt.get("purpose", [])),
222+
"non_goals": list(attempt.get("non_goals", [])),
223+
"claim_boundaries": list(attempt.get("claim_boundaries", [])),
224+
"human_approval_required": list(
225+
attempt.get("human_approval_required", [])
226+
),
227+
"handoff_contracts": list(attempt.get("handoff_contracts", [])),
228+
}
229+
)
230+
return {
231+
"schema_version": "1.0",
232+
"runtime_semantics": metadata.get("runtime_semantics"),
233+
"attempts": attempts,
234+
}
235+
236+
def _attempts(self, metadata: dict[str, Any]) -> list[dict[str, Any]]:
237+
attempts = metadata.get("attempts", [])
238+
if not isinstance(attempts, list):
239+
return []
240+
return [attempt for attempt in attempts if isinstance(attempt, dict)]
241+
242+
def _obligations(self, attempt: dict[str, Any]) -> list[dict[str, Any]]:
243+
obligations = attempt.get("obligations", [])
244+
if not isinstance(obligations, list):
245+
return []
246+
return [obligation for obligation in obligations if isinstance(obligation, dict)]
247+
110248
def _write_json(self, path: Path, payload: Any) -> Path:
111249
path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
112250
return path
@@ -123,6 +261,8 @@ def _sha256_file(self, path: Path) -> str:
123261
return digest.hexdigest()
124262

125263
def _claims_text(self, result: ExecutionResult) -> str:
264+
contract_metadata = self._contract_metadata(result)
265+
contract_counts = self._contract_counts(contract_metadata)
126266
return (
127267
"# IX Assurance Claims\n\n"
128268
"This evidence bundle supports only bounded, runtime-observed claims.\n\n"
@@ -133,10 +273,14 @@ def _claims_text(self, result: ExecutionResult) -> str:
133273
f"- Tool results captured: {len(result.tool_results)}.\n"
134274
f"- Agent handoffs captured: {len(result.handoffs)}.\n"
135275
f"- Conditional branches captured: {len(result.branches)}.\n"
136-
f"- Human approval requirements captured: {len(result.approvals_required)}.\n\n"
276+
f"- Human approval requirements captured: {len(result.approvals_required)}.\n"
277+
f"- Cognition attempt contracts captured: {contract_counts['attempts']}.\n"
278+
f"- Cognition obligations captured: {contract_counts['obligations']}.\n\n"
137279
"## Not claimed\n\n"
138280
"- This bundle does not certify the script as safe, complete, lawful, or production-ready.\n"
139281
"- This bundle does not prove external system behavior beyond the deterministic IX runtime output.\n"
282+
"- This bundle does not execute or certify cognition-contract obligations.\n"
283+
"- This bundle does not certify AGI, AGI-candidate status, or deployment readiness.\n"
140284
"- This bundle does not replace human review.\n"
141285
)
142286

@@ -149,5 +293,9 @@ def _limitations_text(self) -> str:
149293
"automation, or legal compliance.\n\n"
150294
"Current IX built-in tools are deterministic and side-effect free. External network, "
151295
"email, filesystem mutation, procurement, deployment, and real-world actuation tools "
152-
"are intentionally not part of this bundle model.\n"
296+
"are intentionally not part of this bundle model.\n\n"
297+
"Cognition-contract artifacts are declarative metadata. They record the contract, "
298+
"obligations, claim boundaries, and falsification gates that a downstream cognition "
299+
"system may later attempt. They do not execute cognition, prove learning, prove "
300+
"transfer, certify AGI, or authorize self-approval.\n"
153301
)

0 commit comments

Comments
 (0)