- commit
- 419ae8d
- parent
- 164c06a
- author
- codex@macbookpro
- date
- 2026-03-31 17:36:55 +0800 CST
branch-a: task04 unified validation + reporting
7 files changed,
+2053,
-2
+476,
-0
1@@ -0,0 +1,476 @@
2+from __future__ import annotations
3+
4+import argparse
5+import json
6+import subprocess
7+import sys
8+from pathlib import Path
9+from typing import Any, Dict, Iterable, List, Sequence
10+
11+from .runtime import CIERuntime, REQUIRED_SNAPSHOT_KEYS
12+
13+BASE_COMMIT = "164c06af63812c69cab32d8f8a6c770b96f38ef6"
14+DEFAULT_BRANCH = "branch-a/task04-validation-reporting"
15+REPO_ROOT = Path(__file__).resolve().parent.parent
16+DEFAULT_JSON_REPORT_PATH = REPO_ROOT / "reports" / "2026-03-31_task04_branch_a_validation.json"
17+DEFAULT_MARKDOWN_REPORT_PATH = REPO_ROOT / "reports" / "2026-03-31_task04_branch_a_validation.md"
18+REPORT_TOP_LEVEL_KEYS = (
19+ "branch",
20+ "base_commit",
21+ "runtime_summary",
22+ "interface_checks",
23+ "smoke_checks",
24+ "dynamics_checks",
25+ "sedimentation_checks",
26+ "snapshot_checks",
27+ "known_limitations",
28+ "overall_status",
29+)
30+LOCKED_INTERFACE = (
31+ "ingest",
32+ "step",
33+ "emit",
34+ "commit_feedback",
35+ "snapshot_state",
36+ "reset_session",
37+)
38+OUTPUT_MODES = ("full", "degraded", "minimal")
39+
40+
41+def _git_stdout(args: Sequence[str], fallback: str) -> str:
42+ try:
43+ completed = subprocess.run(
44+ ["git", *args],
45+ cwd=REPO_ROOT,
46+ check=True,
47+ capture_output=True,
48+ text=True,
49+ )
50+ except (FileNotFoundError, subprocess.CalledProcessError):
51+ return fallback
52+ value = completed.stdout.strip()
53+ return value or fallback
54+
55+
56+def _current_branch() -> str:
57+ return _git_stdout(["rev-parse", "--abbrev-ref", "HEAD"], DEFAULT_BRANCH)
58+
59+
60+def _check(name: str, ok: bool, detail: str, **extra: Any) -> Dict[str, Any]:
61+ entry: Dict[str, Any] = {
62+ "name": name,
63+ "status": "pass" if ok else "fail",
64+ "detail": detail,
65+ }
66+ entry.update(extra)
67+ return entry
68+
69+
70+def _section(checks: List[Dict[str, Any]], **summary: Any) -> Dict[str, Any]:
71+ failed = sum(1 for item in checks if item["status"] != "pass")
72+ return {
73+ "status": "pass" if failed == 0 else "fail",
74+ "passed": len(checks) - failed,
75+ "failed": failed,
76+ "checks": checks,
77+ "summary": summary,
78+ }
79+
80+
81+def _section_statuses(report: Dict[str, Any]) -> List[str]:
82+ return [
83+ report["interface_checks"]["status"],
84+ report["smoke_checks"]["status"],
85+ report["dynamics_checks"]["status"],
86+ report["sedimentation_checks"]["status"],
87+ report["snapshot_checks"]["status"],
88+ ]
89+
90+
91+def _interface_checks() -> Dict[str, Any]:
92+ runtime = CIERuntime()
93+ snapshot = runtime.snapshot_state()
94+ checks = [
95+ _check(
96+ "runtime_initializes",
97+ snapshot["output_mode"] == "minimal" and snapshot["active_region"] == [],
98+ "A fresh runtime exposes minimal output mode and no active region.",
99+ observed_output_mode=snapshot["output_mode"],
100+ observed_active_region=snapshot["active_region"],
101+ ),
102+ _check(
103+ "locked_interface_presence",
104+ all(callable(getattr(runtime, name, None)) for name in LOCKED_INTERFACE),
105+ "Branch A exposes the locked runtime interface required by the spec.",
106+ interface=list(LOCKED_INTERFACE),
107+ ),
108+ ]
109+ return _section(
110+ checks,
111+ snapshot_keys=sorted(snapshot),
112+ required_snapshot_keys=sorted(REQUIRED_SNAPSHOT_KEYS),
113+ )
114+
115+
116+def _smoke_checks() -> Dict[str, Any]:
117+ runtime = CIERuntime(capacity_limit=8.0)
118+ initial = runtime.snapshot_state()
119+ queued = runtime.ingest(
120+ "graph native observability",
121+ context="branch a validation smoke",
122+ anchors="anchor",
123+ )
124+ stepped = runtime.step(2)
125+ output = runtime.emit()
126+ queued_feedback = runtime.snapshot_state()
127+ after_feedback = runtime.step()
128+ checks = [
129+ _check(
130+ "ingest_queues_signal",
131+ bool(queued["queued_tokens"]) and bool(queued["queued_anchors"]),
132+ "Ingest stores external tokens and anchor hints before the step loop runs.",
133+ queued_tokens=queued["queued_tokens"],
134+ queued_anchors=queued["queued_anchors"],
135+ ),
136+ _check(
137+ "step_materializes_graph_state",
138+ stepped["phi_summary"]["node_count"] > initial["phi_summary"]["node_count"]
139+ and stepped["mu_summary"]["total_activation"] > 0.0
140+ and stepped["J_summary"]["edge_count"] > 0,
141+ "Stepping from a queued input creates observable phi/mu/J state.",
142+ phi_summary=stepped["phi_summary"],
143+ mu_summary=stepped["mu_summary"],
144+ J_summary=stepped["J_summary"],
145+ ),
146+ _check(
147+ "emit_queues_output_feedback",
148+ queued_feedback["feedback_effect"].get("source") == "emit"
149+ and bool(queued_feedback["feedback_effect"].get("queued_tokens")),
150+ "Emit creates a real output-to-input feedback signal rather than a log-only artifact.",
151+ emitted_output=output,
152+ feedback_effect=queued_feedback["feedback_effect"],
153+ ),
154+ _check(
155+ "feedback_changes_later_state",
156+ after_feedback["feedback_effect"].get("last_applied_step") == runtime.state.step_index
157+ and bool(after_feedback["feedback_effect"].get("applied_tokens")),
158+ "Queued feedback is applied on the next step and changes later runtime state.",
159+ feedback_effect=after_feedback["feedback_effect"],
160+ ),
161+ ]
162+ return _section(
163+ checks,
164+ emitted_output=output,
165+ bound_ability_core=after_feedback["bound_ability_core"],
166+ active_region=after_feedback["active_region"],
167+ )
168+
169+
170+def _dynamics_checks() -> Dict[str, Any]:
171+ evolution_runtime = CIERuntime(capacity_limit=8.0)
172+ evolution_runtime.ingest("alpha beta alpha", context="gamma", anchors="anchor")
173+ step_one = evolution_runtime.step()
174+ step_three = evolution_runtime.step(2)
175+
176+ full_runtime = CIERuntime(capacity_limit=10.0)
177+ full_runtime.ingest("focus focus focus", anchors="anchor")
178+ full_runtime.step(2)
179+ full_mode = full_runtime.snapshot_state()["output_mode"]
180+ full_output = full_runtime.emit()
181+
182+ degraded_runtime = CIERuntime(capacity_limit=6.0)
183+ degraded_runtime.ingest("alpha beta gamma delta epsilon", anchors="anchor")
184+ degraded_runtime.step(2)
185+ degraded_mode = degraded_runtime.snapshot_state()["output_mode"]
186+ degraded_output = degraded_runtime.emit()
187+
188+ minimal_runtime = CIERuntime(capacity_limit=0.9)
189+ minimal_runtime.ingest("alpha beta gamma delta epsilon", anchors="anchor")
190+ minimal_runtime.step(2)
191+ minimal_mode = minimal_runtime.snapshot_state()["output_mode"]
192+ minimal_output = minimal_runtime.emit()
193+
194+ decay_runtime = CIERuntime(capacity_limit=10.0)
195+ for _ in range(4):
196+ decay_runtime.ingest("stale alpha beta", anchors="anchor")
197+ decay_runtime.step()
198+ decay_runtime.reset_session()
199+ decay_snapshot = decay_runtime.step(6)
200+
201+ observed_modes = sorted({full_mode, degraded_mode, minimal_mode})
202+ checks = [
203+ _check(
204+ "phi_mu_J_are_observable",
205+ step_one["phi_summary"]["total_potential"] != step_three["phi_summary"]["total_potential"]
206+ and step_one["mu_summary"]["total_activation"] != step_three["mu_summary"]["total_activation"]
207+ and step_one["J_summary"]["total_flow"] != step_three["J_summary"]["total_flow"],
208+ "Multi-step dynamics produce visible changes across phi, mu, and J.",
209+ step_one=step_one,
210+ step_three=step_three,
211+ ),
212+ _check(
213+ "homing_signals_are_populated",
214+ step_three["bound_ability_core"] is not None
215+ and step_three["anchor_pull"] > 0.0
216+ and 0.0 <= step_three["drift_score"] <= 1.0,
217+ "The runtime exposes bound_ability_core, anchor_pull, and drift_score as active homing signals.",
218+ bound_ability_core=step_three["bound_ability_core"],
219+ anchor_pull=step_three["anchor_pull"],
220+ drift_score=step_three["drift_score"],
221+ ),
222+ _check(
223+ "decay_and_forgetting_are_visible",
224+ bool(decay_snapshot["decay_events"])
225+ and any(event["kind"] == "sedimentation_demote" for event in decay_snapshot["decay_events"]),
226+ "Decay/forgetting remains real and observable through decay events and stage demotion.",
227+ decay_events=decay_snapshot["decay_events"][-6:],
228+ ),
229+ _check(
230+ "degraded_output_modes_exist",
231+ observed_modes == sorted(OUTPUT_MODES)
232+ and full_output.startswith("full:")
233+ and degraded_output.startswith("degraded:")
234+ and minimal_output.startswith("minimal:"),
235+ "The runtime emits full, degraded, and minimal outputs under different runtime conditions.",
236+ observed_modes=observed_modes,
237+ outputs={
238+ "full": full_output,
239+ "degraded": degraded_output,
240+ "minimal": minimal_output,
241+ },
242+ ),
243+ ]
244+ return _section(
245+ checks,
246+ observed_modes=observed_modes,
247+ total_decay_events=len(decay_snapshot["decay_events"]),
248+ )
249+
250+
251+def _sedimentation_checks() -> Dict[str, Any]:
252+ runtime = CIERuntime(capacity_limit=10.0)
253+ for _ in range(4):
254+ runtime.ingest("alpha beta alpha", anchors="anchor")
255+ runtime.step()
256+ snapshot = runtime.snapshot_state()
257+ alpha_trace = [
258+ event for event in snapshot["sedimentation_trace"] if event["node"] == "alpha"
259+ ]
260+ alpha_candidate = next(
261+ item for item in snapshot["skill_belt_candidates"] if item["node"] == "alpha"
262+ )
263+ checks = [
264+ _check(
265+ "sedimentation_trace_exists",
266+ bool(snapshot["sedimentation_trace"]),
267+ "Sedimentation history is exported as explicit runtime trace entries.",
268+ trace_tail=snapshot["sedimentation_trace"][-5:],
269+ ),
270+ _check(
271+ "stage_progression_matches_locked_path",
272+ [event["to"] for event in alpha_trace] == ["experience", "skill_belt", "ability_core"],
273+ "Repeated activation follows the locked memory -> experience -> skill_belt -> ability_core path.",
274+ alpha_trace=alpha_trace,
275+ ),
276+ _check(
277+ "skill_belt_candidates_have_evidence",
278+ alpha_candidate["stage"] in {"skill_belt", "ability_core"}
279+ and alpha_candidate["stable_steps"] >= 2,
280+ "Skill-belt candidates are backed by repeated activation, stability, and flow evidence.",
281+ alpha_candidate=alpha_candidate,
282+ ),
283+ _check(
284+ "merge_events_are_recorded",
285+ bool(snapshot["merge_events"])
286+ and any(event["node"] == "alpha" for event in snapshot["merge_events"]),
287+ "Stable skill-belt structures can produce explicit merge events into ability-core structures.",
288+ merge_events=snapshot["merge_events"],
289+ ),
290+ ]
291+ return _section(
292+ checks,
293+ experience_regions=snapshot["experience_regions"],
294+ bound_ability_core=snapshot["bound_ability_core"],
295+ )
296+
297+
298+def _snapshot_checks() -> Dict[str, Any]:
299+ runtime = CIERuntime(capacity_limit=8.0)
300+ runtime.ingest("branch a graph native feedback", context="runtime state", anchors="anchor")
301+ runtime.step(2)
302+ runtime.emit()
303+ snapshot = runtime.step()
304+ checks = [
305+ _check(
306+ "locked_snapshot_fields_present",
307+ set(snapshot) == REQUIRED_SNAPSHOT_KEYS,
308+ "snapshot_state returns the locked comparable field set.",
309+ observed_keys=sorted(snapshot),
310+ required_keys=sorted(REQUIRED_SNAPSHOT_KEYS),
311+ ),
312+ _check(
313+ "summary_fields_are_meaningful",
314+ snapshot["phi_summary"]["node_count"] > 0
315+ and snapshot["mu_summary"]["active_count"] > 0
316+ and snapshot["J_summary"]["edge_count"] > 0,
317+ "phi_summary, mu_summary, and J_summary expose non-empty observable summaries after activity.",
318+ phi_summary=snapshot["phi_summary"],
319+ mu_summary=snapshot["mu_summary"],
320+ J_summary=snapshot["J_summary"],
321+ ),
322+ _check(
323+ "feedback_and_output_fields_are_populated",
324+ snapshot["output_mode"] in OUTPUT_MODES
325+ and bool(snapshot["feedback_effect"].get("applied_tokens")),
326+ "snapshot_state exposes output_mode and feedback_effect with applied feedback evidence.",
327+ output_mode=snapshot["output_mode"],
328+ feedback_effect=snapshot["feedback_effect"],
329+ ),
330+ _check(
331+ "locked_homing_and_sedimentation_fields_are_populated",
332+ snapshot["bound_ability_core"] is not None
333+ and snapshot["anchor_pull"] > 0.0
334+ and snapshot["skill_belt_candidates"]
335+ and snapshot["sedimentation_trace"],
336+ "The locked homing and sedimentation-facing snapshot fields are populated under a controlled scenario.",
337+ bound_ability_core=snapshot["bound_ability_core"],
338+ anchor_pull=snapshot["anchor_pull"],
339+ drift_score=snapshot["drift_score"],
340+ ),
341+ ]
342+ return _section(
343+ checks,
344+ output_mode=snapshot["output_mode"],
345+ free_capacity=snapshot["free_capacity"],
346+ )
347+
348+
349+def _known_limitations() -> List[str]:
350+ return [
351+ "The validation harness is scenario-based and compact; it is not a benchmark or long-run stability suite.",
352+ "Checks focus on the locked observable runtime surface rather than richer semantic task performance.",
353+ "Sedimentation and homing remain explicit but heuristic, which is acceptable for the review/comparison stage.",
354+ ]
355+
356+
357+def _runtime_summary(report: Dict[str, Any], json_path: Path, markdown_path: Path) -> Dict[str, Any]:
358+ section_statuses = _section_statuses(report)
359+ return {
360+ "status": "pass" if all(status == "pass" for status in section_statuses) else "fail",
361+ "scenarios": ["interface", "smoke", "dynamics", "sedimentation", "snapshot"],
362+ "output_modes_observed": list(OUTPUT_MODES),
363+ "reports_generated": {
364+ "json": str(json_path),
365+ "markdown": str(markdown_path),
366+ },
367+ "ready_for_review": all(status == "pass" for status in section_statuses),
368+ }
369+
370+
371+def _overall_status(report: Dict[str, Any]) -> Dict[str, Any]:
372+ section_statuses = _section_statuses(report)
373+ passed_sections = sum(1 for status in section_statuses if status == "pass")
374+ failed_sections = len(section_statuses) - passed_sections
375+ ready = failed_sections == 0
376+ return {
377+ "status": "pass" if ready else "fail",
378+ "passed_sections": passed_sections,
379+ "failed_sections": failed_sections,
380+ "ready_for_review": ready,
381+ "summary": (
382+ "Branch A validation passed and is ready for review/comparison."
383+ if ready
384+ else "Branch A validation found issues that should be reviewed before comparison."
385+ ),
386+ }
387+
388+
389+def _render_markdown(report: Dict[str, Any]) -> str:
390+ lines = [
391+ "# Branch A Validation Report",
392+ "",
393+ f"- Branch: `{report['branch']}`",
394+ f"- Base commit: `{report['base_commit']}`",
395+ f"- Overall status: `{report['overall_status']['status'].upper()}`",
396+ f"- Ready for review/comparison: `{report['overall_status']['ready_for_review']}`",
397+ "",
398+ "## Runtime Summary",
399+ f"- Status: `{report['runtime_summary']['status'].upper()}`",
400+ f"- Scenarios: {', '.join(report['runtime_summary']['scenarios'])}",
401+ f"- Output modes observed: {', '.join(report['runtime_summary']['output_modes_observed'])}",
402+ "",
403+ ]
404+ for key, title in (
405+ ("interface_checks", "Interface Checks"),
406+ ("smoke_checks", "Smoke Checks"),
407+ ("dynamics_checks", "Dynamics Checks"),
408+ ("sedimentation_checks", "Sedimentation Checks"),
409+ ("snapshot_checks", "Snapshot Checks"),
410+ ):
411+ section = report[key]
412+ lines.extend(
413+ [
414+ f"## {title}",
415+ f"- Status: `{section['status'].upper()}`",
416+ f"- Passed: `{section['passed']}`",
417+ f"- Failed: `{section['failed']}`",
418+ ]
419+ )
420+ for check in section["checks"]:
421+ lines.append(f"- `{check['status'].upper()}` {check['name']}: {check['detail']}")
422+ lines.append("")
423+ lines.extend(
424+ [
425+ "## Known Limitations",
426+ *[f"- {item}" for item in report["known_limitations"]],
427+ "",
428+ "## Readiness",
429+ f"- {report['overall_status']['summary']}",
430+ "",
431+ ]
432+ )
433+ return "\n".join(lines)
434+
435+
436+def generate_validation_report(
437+ json_path: Path | str = DEFAULT_JSON_REPORT_PATH,
438+ markdown_path: Path | str = DEFAULT_MARKDOWN_REPORT_PATH,
439+) -> Dict[str, Any]:
440+ json_path = Path(json_path)
441+ markdown_path = Path(markdown_path)
442+ report: Dict[str, Any] = {
443+ "branch": _current_branch(),
444+ "base_commit": BASE_COMMIT,
445+ "runtime_summary": {},
446+ "interface_checks": _interface_checks(),
447+ "smoke_checks": _smoke_checks(),
448+ "dynamics_checks": _dynamics_checks(),
449+ "sedimentation_checks": _sedimentation_checks(),
450+ "snapshot_checks": _snapshot_checks(),
451+ "known_limitations": _known_limitations(),
452+ "overall_status": {},
453+ }
454+ report["runtime_summary"] = _runtime_summary(report, json_path, markdown_path)
455+ report["overall_status"] = _overall_status(report)
456+ json_path.parent.mkdir(parents=True, exist_ok=True)
457+ markdown_path.parent.mkdir(parents=True, exist_ok=True)
458+ json_path.write_text(json.dumps(report, indent=2, ensure_ascii=True) + "\n", encoding="utf-8")
459+ markdown_path.write_text(_render_markdown(report), encoding="utf-8")
460+ return report
461+
462+
463+def _parse_args(argv: Sequence[str]) -> argparse.Namespace:
464+ parser = argparse.ArgumentParser(description="Branch A validation and report generation.")
465+ parser.add_argument("--json-out", default=str(DEFAULT_JSON_REPORT_PATH))
466+ parser.add_argument("--markdown-out", default=str(DEFAULT_MARKDOWN_REPORT_PATH))
467+ return parser.parse_args(argv)
468+
469+
470+def main(argv: Sequence[str] | None = None) -> int:
471+ args = _parse_args(sys.argv[1:] if argv is None else argv)
472+ report = generate_validation_report(args.json_out, args.markdown_out)
473+ return 0 if report["overall_status"]["status"] == "pass" else 1
474+
475+
476+if __name__ == "__main__":
477+ raise SystemExit(main())
+2,
-2
1@@ -19,5 +19,5 @@ Branch A is the pure graph-native minimal runtime line:
2 Runtime dynamics, output feedback, observable decay, and mode degradation are now implemented and validated.
3 3. **Task 03: sedimentation path + skill belt candidates + merge/decay events** `[completed]`
4 Explicit sedimentation profiles, stage transitions, merge events, and decay-linked demotion are now implemented and validated.
5-4. **Task 04: unified validation/reporting against locked spec**
6- Produce the comparable validation and reporting layer required by the locked docs.
7+4. **Task 04: unified validation/reporting against locked spec** `[completed]`
8+ Comparable JSON/Markdown validation reports and the review-ready acceptance harness are now in place.
1@@ -0,0 +1,1307 @@
2+{
3+ "branch": "branch-a/task04-validation-reporting",
4+ "base_commit": "164c06af63812c69cab32d8f8a6c770b96f38ef6",
5+ "runtime_summary": {
6+ "status": "pass",
7+ "scenarios": [
8+ "interface",
9+ "smoke",
10+ "dynamics",
11+ "sedimentation",
12+ "snapshot"
13+ ],
14+ "output_modes_observed": [
15+ "full",
16+ "degraded",
17+ "minimal"
18+ ],
19+ "reports_generated": {
20+ "json": "/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.json",
21+ "markdown": "/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.md"
22+ },
23+ "ready_for_review": true
24+ },
25+ "interface_checks": {
26+ "status": "pass",
27+ "passed": 2,
28+ "failed": 0,
29+ "checks": [
30+ {
31+ "name": "runtime_initializes",
32+ "status": "pass",
33+ "detail": "A fresh runtime exposes minimal output mode and no active region.",
34+ "observed_output_mode": "minimal",
35+ "observed_active_region": []
36+ },
37+ {
38+ "name": "locked_interface_presence",
39+ "status": "pass",
40+ "detail": "Branch A exposes the locked runtime interface required by the spec.",
41+ "interface": [
42+ "ingest",
43+ "step",
44+ "emit",
45+ "commit_feedback",
46+ "snapshot_state",
47+ "reset_session"
48+ ]
49+ }
50+ ],
51+ "summary": {
52+ "snapshot_keys": [
53+ "J_summary",
54+ "active_region",
55+ "anchor_pull",
56+ "bound_ability_core",
57+ "decay_events",
58+ "drift_score",
59+ "experience_regions",
60+ "feedback_effect",
61+ "free_capacity",
62+ "merge_events",
63+ "mu_summary",
64+ "output_mode",
65+ "phi_summary",
66+ "sedimentation_trace",
67+ "skill_belt_candidates"
68+ ],
69+ "required_snapshot_keys": [
70+ "J_summary",
71+ "active_region",
72+ "anchor_pull",
73+ "bound_ability_core",
74+ "decay_events",
75+ "drift_score",
76+ "experience_regions",
77+ "feedback_effect",
78+ "free_capacity",
79+ "merge_events",
80+ "mu_summary",
81+ "output_mode",
82+ "phi_summary",
83+ "sedimentation_trace",
84+ "skill_belt_candidates"
85+ ]
86+ }
87+ },
88+ "smoke_checks": {
89+ "status": "pass",
90+ "passed": 4,
91+ "failed": 0,
92+ "checks": [
93+ {
94+ "name": "ingest_queues_signal",
95+ "status": "pass",
96+ "detail": "Ingest stores external tokens and anchor hints before the step loop runs.",
97+ "queued_tokens": [
98+ "graph",
99+ "native",
100+ "observability"
101+ ],
102+ "queued_anchors": [
103+ "anchor"
104+ ]
105+ },
106+ {
107+ "name": "step_materializes_graph_state",
108+ "status": "pass",
109+ "detail": "Stepping from a queued input creates observable phi/mu/J state.",
110+ "phi_summary": {
111+ "node_count": 8,
112+ "total_potential": 0.9771,
113+ "top_nodes": [
114+ {
115+ "node": "native",
116+ "value": 0.3148
117+ },
118+ {
119+ "node": "observability",
120+ "value": 0.2646
121+ },
122+ {
123+ "node": "graph",
124+ "value": 0.2556
125+ },
126+ {
127+ "node": "anchor",
128+ "value": 0.1245
129+ },
130+ {
131+ "node": "smoke",
132+ "value": 0.0165
133+ }
134+ ]
135+ },
136+ "mu_summary": {
137+ "active_count": 4,
138+ "total_activation": 1.2823,
139+ "top_nodes": [
140+ {
141+ "node": "native",
142+ "value": 0.6435
143+ },
144+ {
145+ "node": "observability",
146+ "value": 0.2917
147+ },
148+ {
149+ "node": "graph",
150+ "value": 0.2746
151+ },
152+ {
153+ "node": "smoke",
154+ "value": 0.0725
155+ }
156+ ]
157+ },
158+ "J_summary": {
159+ "edge_count": 15,
160+ "total_flow": 1.7255,
161+ "top_flows": [
162+ {
163+ "edge": "native->observability",
164+ "flow": 0.2709
165+ },
166+ {
167+ "edge": "graph->native",
168+ "flow": 0.2703
169+ },
170+ {
171+ "edge": "smoke->graph",
172+ "flow": 0.2143
173+ },
174+ {
175+ "edge": "a->validation",
176+ "flow": 0.2053
177+ },
178+ {
179+ "edge": "anchor->branch",
180+ "flow": 0.2053
181+ }
182+ ]
183+ }
184+ },
185+ {
186+ "name": "emit_queues_output_feedback",
187+ "status": "pass",
188+ "detail": "Emit creates a real output-to-input feedback signal rather than a log-only artifact.",
189+ "emitted_output": "degraded: native / observability",
190+ "feedback_effect": {
191+ "source": "emit",
192+ "mode": "degraded",
193+ "queued_tokens": [
194+ "native",
195+ "observability"
196+ ],
197+ "queued_strength": 0.38,
198+ "confidence_proxy": 0.4379,
199+ "queued_step": 2,
200+ "last_applied_step": null
201+ }
202+ },
203+ {
204+ "name": "feedback_changes_later_state",
205+ "status": "pass",
206+ "detail": "Queued feedback is applied on the next step and changes later runtime state.",
207+ "feedback_effect": {
208+ "source": "emit",
209+ "mode": "degraded",
210+ "queued_tokens": [
211+ "native",
212+ "observability"
213+ ],
214+ "queued_strength": 0.38,
215+ "confidence_proxy": 0.4379,
216+ "queued_step": 2,
217+ "last_applied_step": 3,
218+ "applied_tokens": [
219+ "native",
220+ "observability",
221+ "graph"
222+ ],
223+ "phi_delta": 0.0401,
224+ "mu_delta": 0.0552,
225+ "flow_delta": 0.0492,
226+ "stage_after": {
227+ "native": "skill_belt",
228+ "observability": "skill_belt",
229+ "graph": "experience"
230+ },
231+ "bound_ability_core": "native"
232+ }
233+ }
234+ ],
235+ "summary": {
236+ "emitted_output": "degraded: native / observability",
237+ "bound_ability_core": "native",
238+ "active_region": [
239+ "native",
240+ "observability",
241+ "graph",
242+ "smoke"
243+ ]
244+ }
245+ },
246+ "dynamics_checks": {
247+ "status": "pass",
248+ "passed": 4,
249+ "failed": 0,
250+ "checks": [
251+ {
252+ "name": "phi_mu_J_are_observable",
253+ "status": "pass",
254+ "detail": "Multi-step dynamics produce visible changes across phi, mu, and J.",
255+ "step_one": {
256+ "phi_summary": {
257+ "node_count": 4,
258+ "total_potential": 0.8956,
259+ "top_nodes": [
260+ {
261+ "node": "alpha",
262+ "value": 0.4895
263+ },
264+ {
265+ "node": "beta",
266+ "value": 0.2604
267+ },
268+ {
269+ "node": "anchor",
270+ "value": 0.1219
271+ },
272+ {
273+ "node": "gamma",
274+ "value": 0.0238
275+ }
276+ ]
277+ },
278+ "mu_summary": {
279+ "active_count": 3,
280+ "total_activation": 1.7591,
281+ "top_nodes": [
282+ {
283+ "node": "alpha",
284+ "value": 1.0548
285+ },
286+ {
287+ "node": "beta",
288+ "value": 0.5423
289+ },
290+ {
291+ "node": "gamma",
292+ "value": 0.162
293+ }
294+ ]
295+ },
296+ "J_summary": {
297+ "edge_count": 7,
298+ "total_flow": 0.828,
299+ "top_flows": [
300+ {
301+ "edge": "alpha->beta",
302+ "flow": 0.2788
303+ },
304+ {
305+ "edge": "gamma->alpha",
306+ "flow": 0.2351
307+ },
308+ {
309+ "edge": "anchor->gamma",
310+ "flow": 0.2256
311+ },
312+ {
313+ "edge": "beta->alpha",
314+ "flow": 0.0486
315+ },
316+ {
317+ "edge": "alpha->gamma",
318+ "flow": 0.0357
319+ }
320+ ]
321+ },
322+ "active_region": [
323+ "alpha",
324+ "beta",
325+ "gamma"
326+ ],
327+ "bound_ability_core": "alpha",
328+ "anchor_pull": 0.0,
329+ "drift_score": 0.2401,
330+ "free_capacity": 0.7801,
331+ "experience_regions": [
332+ {
333+ "region": "alpha",
334+ "nodes": [
335+ "alpha",
336+ "anchor",
337+ "beta",
338+ "gamma"
339+ ],
340+ "stage": "experience",
341+ "activation": 1.7591,
342+ "potential": 0.8956,
343+ "candidate_score": 3.2778,
344+ "stable_steps": 1
345+ }
346+ ],
347+ "skill_belt_candidates": [
348+ {
349+ "node": "alpha",
350+ "score": 1.1178,
351+ "stage": "experience",
352+ "flow": 0.5983,
353+ "stable_steps": 1,
354+ "touches": 2,
355+ "target_core": "alpha"
356+ },
357+ {
358+ "node": "beta",
359+ "score": 0.8617,
360+ "stage": "experience",
361+ "flow": 0.3274,
362+ "stable_steps": 1,
363+ "touches": 2,
364+ "target_core": "alpha"
365+ },
366+ {
367+ "node": "gamma",
368+ "score": 0.7247,
369+ "stage": "experience",
370+ "flow": 0.4974,
371+ "stable_steps": 1,
372+ "touches": 2,
373+ "target_core": "alpha"
374+ },
375+ {
376+ "node": "anchor",
377+ "score": 0.5736,
378+ "stage": "experience",
379+ "flow": 0.2265,
380+ "stable_steps": 1,
381+ "touches": 1,
382+ "target_core": "alpha"
383+ }
384+ ],
385+ "sedimentation_trace": [
386+ {
387+ "step": 1,
388+ "node": "alpha",
389+ "direction": "promote",
390+ "from": "memory",
391+ "to": "experience",
392+ "touches": 2,
393+ "stable_steps": 1,
394+ "dormant_steps": 0,
395+ "candidate_score": 1.1178,
396+ "resonance": 1.3338,
397+ "flow": 0.5983
398+ },
399+ {
400+ "step": 1,
401+ "node": "anchor",
402+ "direction": "promote",
403+ "from": "memory",
404+ "to": "experience",
405+ "touches": 1,
406+ "stable_steps": 1,
407+ "dormant_steps": 0,
408+ "candidate_score": 0.5736,
409+ "resonance": 0.0834,
410+ "flow": 0.2265
411+ },
412+ {
413+ "step": 1,
414+ "node": "beta",
415+ "direction": "promote",
416+ "from": "memory",
417+ "to": "experience",
418+ "touches": 2,
419+ "stable_steps": 1,
420+ "dormant_steps": 0,
421+ "candidate_score": 0.8617,
422+ "resonance": 0.6924,
423+ "flow": 0.3274
424+ },
425+ {
426+ "step": 1,
427+ "node": "gamma",
428+ "direction": "promote",
429+ "from": "memory",
430+ "to": "experience",
431+ "touches": 2,
432+ "stable_steps": 1,
433+ "dormant_steps": 0,
434+ "candidate_score": 0.7247,
435+ "resonance": 0.2598,
436+ "flow": 0.4974
437+ }
438+ ],
439+ "merge_events": [],
440+ "decay_events": [
441+ {
442+ "step": 1,
443+ "kind": "phi_decay",
444+ "target": "alpha",
445+ "amount": 0.0151,
446+ "age": 0
447+ },
448+ {
449+ "step": 1,
450+ "kind": "mu_decay",
451+ "target": "alpha",
452+ "amount": 0.0794,
453+ "age": 0
454+ },
455+ {
456+ "step": 1,
457+ "kind": "mu_decay",
458+ "target": "gamma",
459+ "amount": 0.0221,
460+ "age": 0
461+ },
462+ {
463+ "step": 1,
464+ "kind": "mu_decay",
465+ "target": "beta",
466+ "amount": 0.0739,
467+ "age": 0
468+ },
469+ {
470+ "step": 1,
471+ "kind": "mu_prune",
472+ "target": "anchor",
473+ "amount": 0.0283,
474+ "age": 0
475+ },
476+ {
477+ "step": 1,
478+ "kind": "J_decay",
479+ "target": "anchor->gamma",
480+ "amount": 0.0144,
481+ "age": 0
482+ }
483+ ],
484+ "output_mode": "degraded",
485+ "feedback_effect": {}
486+ },
487+ "step_three": {
488+ "phi_summary": {
489+ "node_count": 4,
490+ "total_potential": 1.1043,
491+ "top_nodes": [
492+ {
493+ "node": "alpha",
494+ "value": 0.548
495+ },
496+ {
497+ "node": "beta",
498+ "value": 0.3074
499+ },
500+ {
501+ "node": "anchor",
502+ "value": 0.1883
503+ },
504+ {
505+ "node": "gamma",
506+ "value": 0.0606
507+ }
508+ ]
509+ },
510+ "mu_summary": {
511+ "active_count": 3,
512+ "total_activation": 0.9573,
513+ "top_nodes": [
514+ {
515+ "node": "alpha",
516+ "value": 0.5346
517+ },
518+ {
519+ "node": "beta",
520+ "value": 0.2701
521+ },
522+ {
523+ "node": "gamma",
524+ "value": 0.1526
525+ }
526+ ]
527+ },
528+ "J_summary": {
529+ "edge_count": 9,
530+ "total_flow": 0.9228,
531+ "top_flows": [
532+ {
533+ "edge": "alpha->beta",
534+ "flow": 0.3151
535+ },
536+ {
537+ "edge": "gamma->alpha",
538+ "flow": 0.2352
539+ },
540+ {
541+ "edge": "anchor->gamma",
542+ "flow": 0.1807
543+ },
544+ {
545+ "edge": "beta->alpha",
546+ "flow": 0.1007
547+ },
548+ {
549+ "edge": "alpha->gamma",
550+ "flow": 0.0737
551+ }
552+ ]
553+ },
554+ "active_region": [
555+ "alpha",
556+ "beta",
557+ "gamma"
558+ ],
559+ "bound_ability_core": "alpha",
560+ "anchor_pull": 0.0001,
561+ "drift_score": 0.2462,
562+ "free_capacity": 0.8803,
563+ "experience_regions": [
564+ {
565+ "region": "alpha",
566+ "nodes": [
567+ "alpha",
568+ "anchor",
569+ "beta",
570+ "gamma"
571+ ],
572+ "stage": "skill_belt",
573+ "activation": 0.9573,
574+ "potential": 1.1043,
575+ "candidate_score": 7.4796,
576+ "stable_steps": 3
577+ }
578+ ],
579+ "skill_belt_candidates": [
580+ {
581+ "node": "alpha",
582+ "score": 2.4896,
583+ "stage": "skill_belt",
584+ "flow": 0.7247,
585+ "stable_steps": 3,
586+ "touches": 4,
587+ "target_core": "alpha"
588+ },
589+ {
590+ "node": "beta",
591+ "score": 2.0219,
592+ "stage": "skill_belt",
593+ "flow": 0.4158,
594+ "stable_steps": 3,
595+ "touches": 4,
596+ "target_core": "alpha"
597+ },
598+ {
599+ "node": "gamma",
600+ "score": 1.6643,
601+ "stage": "skill_belt",
602+ "flow": 0.5001,
603+ "stable_steps": 3,
604+ "touches": 3,
605+ "target_core": "alpha"
606+ },
607+ {
608+ "node": "anchor",
609+ "score": 1.3038,
610+ "stage": "experience",
611+ "flow": 0.1912,
612+ "stable_steps": 3,
613+ "touches": 1,
614+ "target_core": "alpha"
615+ }
616+ ],
617+ "sedimentation_trace": [
618+ {
619+ "step": 1,
620+ "node": "alpha",
621+ "direction": "promote",
622+ "from": "memory",
623+ "to": "experience",
624+ "touches": 2,
625+ "stable_steps": 1,
626+ "dormant_steps": 0,
627+ "candidate_score": 1.1178,
628+ "resonance": 1.3338,
629+ "flow": 0.5983
630+ },
631+ {
632+ "step": 1,
633+ "node": "anchor",
634+ "direction": "promote",
635+ "from": "memory",
636+ "to": "experience",
637+ "touches": 1,
638+ "stable_steps": 1,
639+ "dormant_steps": 0,
640+ "candidate_score": 0.5736,
641+ "resonance": 0.0834,
642+ "flow": 0.2265
643+ },
644+ {
645+ "step": 1,
646+ "node": "beta",
647+ "direction": "promote",
648+ "from": "memory",
649+ "to": "experience",
650+ "touches": 2,
651+ "stable_steps": 1,
652+ "dormant_steps": 0,
653+ "candidate_score": 0.8617,
654+ "resonance": 0.6924,
655+ "flow": 0.3274
656+ },
657+ {
658+ "step": 1,
659+ "node": "gamma",
660+ "direction": "promote",
661+ "from": "memory",
662+ "to": "experience",
663+ "touches": 2,
664+ "stable_steps": 1,
665+ "dormant_steps": 0,
666+ "candidate_score": 0.7247,
667+ "resonance": 0.2598,
668+ "flow": 0.4974
669+ },
670+ {
671+ "step": 2,
672+ "node": "alpha",
673+ "direction": "promote",
674+ "from": "experience",
675+ "to": "skill_belt",
676+ "touches": 3,
677+ "stable_steps": 2,
678+ "dormant_steps": 0,
679+ "candidate_score": 1.8591,
680+ "resonance": 2.175,
681+ "flow": 0.6764
682+ },
683+ {
684+ "step": 2,
685+ "node": "beta",
686+ "direction": "promote",
687+ "from": "experience",
688+ "to": "skill_belt",
689+ "touches": 3,
690+ "stable_steps": 2,
691+ "dormant_steps": 0,
692+ "candidate_score": 1.4692,
693+ "resonance": 1.1255,
694+ "flow": 0.3827
695+ },
696+ {
697+ "step": 3,
698+ "node": "gamma",
699+ "direction": "promote",
700+ "from": "experience",
701+ "to": "skill_belt",
702+ "touches": 3,
703+ "stable_steps": 3,
704+ "dormant_steps": 0,
705+ "candidate_score": 1.6643,
706+ "resonance": 0.6859,
707+ "flow": 0.5001
708+ }
709+ ],
710+ "merge_events": [],
711+ "decay_events": [
712+ {
713+ "step": 1,
714+ "kind": "phi_decay",
715+ "target": "alpha",
716+ "amount": 0.0151,
717+ "age": 0
718+ },
719+ {
720+ "step": 1,
721+ "kind": "mu_decay",
722+ "target": "alpha",
723+ "amount": 0.0794,
724+ "age": 0
725+ },
726+ {
727+ "step": 1,
728+ "kind": "mu_decay",
729+ "target": "gamma",
730+ "amount": 0.0221,
731+ "age": 0
732+ },
733+ {
734+ "step": 1,
735+ "kind": "mu_decay",
736+ "target": "beta",
737+ "amount": 0.0739,
738+ "age": 0
739+ },
740+ {
741+ "step": 1,
742+ "kind": "mu_prune",
743+ "target": "anchor",
744+ "amount": 0.0283,
745+ "age": 0
746+ },
747+ {
748+ "step": 1,
749+ "kind": "J_decay",
750+ "target": "anchor->gamma",
751+ "amount": 0.0144,
752+ "age": 0
753+ },
754+ {
755+ "step": 2,
756+ "kind": "phi_decay",
757+ "target": "alpha",
758+ "amount": 0.0162,
759+ "age": 0
760+ },
761+ {
762+ "step": 2,
763+ "kind": "mu_decay",
764+ "target": "alpha",
765+ "amount": 0.0564,
766+ "age": 0
767+ },
768+ {
769+ "step": 2,
770+ "kind": "mu_decay",
771+ "target": "gamma",
772+ "amount": 0.0242,
773+ "age": 0
774+ },
775+ {
776+ "step": 2,
777+ "kind": "mu_decay",
778+ "target": "beta",
779+ "amount": 0.051,
780+ "age": 0
781+ },
782+ {
783+ "step": 2,
784+ "kind": "mu_prune",
785+ "target": "anchor",
786+ "amount": 0.0188,
787+ "age": 0
788+ },
789+ {
790+ "step": 2,
791+ "kind": "J_decay",
792+ "target": "anchor->gamma",
793+ "amount": 0.0203,
794+ "age": 1
795+ },
796+ {
797+ "step": 3,
798+ "kind": "phi_decay",
799+ "target": "alpha",
800+ "amount": 0.0169,
801+ "age": 0
802+ },
803+ {
804+ "step": 3,
805+ "kind": "mu_decay",
806+ "target": "alpha",
807+ "amount": 0.0402,
808+ "age": 0
809+ },
810+ {
811+ "step": 3,
812+ "kind": "mu_decay",
813+ "target": "gamma",
814+ "amount": 0.0208,
815+ "age": 0
816+ },
817+ {
818+ "step": 3,
819+ "kind": "mu_decay",
820+ "target": "beta",
821+ "amount": 0.0368,
822+ "age": 0
823+ },
824+ {
825+ "step": 3,
826+ "kind": "mu_prune",
827+ "target": "anchor",
828+ "amount": 0.0207,
829+ "age": 0
830+ },
831+ {
832+ "step": 3,
833+ "kind": "J_decay",
834+ "target": "anchor->gamma",
835+ "amount": 0.0246,
836+ "age": 2
837+ }
838+ ],
839+ "output_mode": "degraded",
840+ "feedback_effect": {}
841+ }
842+ },
843+ {
844+ "name": "homing_signals_are_populated",
845+ "status": "pass",
846+ "detail": "The runtime exposes bound_ability_core, anchor_pull, and drift_score as active homing signals.",
847+ "bound_ability_core": "alpha",
848+ "anchor_pull": 0.0001,
849+ "drift_score": 0.2462
850+ },
851+ {
852+ "name": "decay_and_forgetting_are_visible",
853+ "status": "pass",
854+ "detail": "Decay/forgetting remains real and observable through decay events and stage demotion.",
855+ "decay_events": [
856+ {
857+ "step": 10,
858+ "kind": "J_decay",
859+ "target": "anchor->stale",
860+ "amount": 0.0905,
861+ "age": 6
862+ },
863+ {
864+ "step": 10,
865+ "kind": "J_decay",
866+ "target": "stale->alpha",
867+ "amount": 0.1172,
868+ "age": 6
869+ },
870+ {
871+ "step": 10,
872+ "kind": "J_decay",
873+ "target": "alpha->beta",
874+ "amount": 0.1203,
875+ "age": 6
876+ },
877+ {
878+ "step": 10,
879+ "kind": "J_decay",
880+ "target": "stale->anchor",
881+ "amount": 0.0137,
882+ "age": 6
883+ },
884+ {
885+ "step": 10,
886+ "kind": "J_decay",
887+ "target": "alpha->stale",
888+ "amount": 0.0181,
889+ "age": 6
890+ },
891+ {
892+ "step": 10,
893+ "kind": "J_decay",
894+ "target": "beta->alpha",
895+ "amount": 0.0331,
896+ "age": 6
897+ }
898+ ]
899+ },
900+ {
901+ "name": "degraded_output_modes_exist",
902+ "status": "pass",
903+ "detail": "The runtime emits full, degraded, and minimal outputs under different runtime conditions.",
904+ "observed_modes": [
905+ "degraded",
906+ "full",
907+ "minimal"
908+ ],
909+ "outputs": {
910+ "full": "full: focus -> anchor",
911+ "degraded": "degraded: delta / gamma",
912+ "minimal": "minimal: delta"
913+ }
914+ }
915+ ],
916+ "summary": {
917+ "observed_modes": [
918+ "degraded",
919+ "full",
920+ "minimal"
921+ ],
922+ "total_decay_events": 24
923+ }
924+ },
925+ "sedimentation_checks": {
926+ "status": "pass",
927+ "passed": 4,
928+ "failed": 0,
929+ "checks": [
930+ {
931+ "name": "sedimentation_trace_exists",
932+ "status": "pass",
933+ "detail": "Sedimentation history is exported as explicit runtime trace entries.",
934+ "trace_tail": [
935+ {
936+ "step": 2,
937+ "node": "anchor",
938+ "direction": "promote",
939+ "from": "experience",
940+ "to": "skill_belt",
941+ "touches": 4,
942+ "stable_steps": 2,
943+ "dormant_steps": 0,
944+ "candidate_score": 1.619,
945+ "resonance": 0.9619,
946+ "flow": 0.5802
947+ },
948+ {
949+ "step": 2,
950+ "node": "beta",
951+ "direction": "promote",
952+ "from": "experience",
953+ "to": "skill_belt",
954+ "touches": 4,
955+ "stable_steps": 2,
956+ "dormant_steps": 0,
957+ "candidate_score": 1.8566,
958+ "resonance": 1.7754,
959+ "flow": 0.7005
960+ },
961+ {
962+ "step": 4,
963+ "node": "alpha",
964+ "direction": "promote",
965+ "from": "skill_belt",
966+ "to": "ability_core",
967+ "touches": 8,
968+ "stable_steps": 4,
969+ "dormant_steps": 0,
970+ "candidate_score": 3.7893,
971+ "resonance": 6.0,
972+ "flow": 2.7831
973+ },
974+ {
975+ "step": 4,
976+ "node": "anchor",
977+ "direction": "promote",
978+ "from": "skill_belt",
979+ "to": "ability_core",
980+ "touches": 8,
981+ "stable_steps": 4,
982+ "dormant_steps": 0,
983+ "candidate_score": 3.5277,
984+ "resonance": 2.926,
985+ "flow": 1.2539
986+ },
987+ {
988+ "step": 4,
989+ "node": "beta",
990+ "direction": "promote",
991+ "from": "skill_belt",
992+ "to": "ability_core",
993+ "touches": 8,
994+ "stable_steps": 4,
995+ "dormant_steps": 0,
996+ "candidate_score": 3.5592,
997+ "resonance": 4.7325,
998+ "flow": 1.5292
999+ }
1000+ ]
1001+ },
1002+ {
1003+ "name": "stage_progression_matches_locked_path",
1004+ "status": "pass",
1005+ "detail": "Repeated activation follows the locked memory -> experience -> skill_belt -> ability_core path.",
1006+ "alpha_trace": [
1007+ {
1008+ "step": 1,
1009+ "node": "alpha",
1010+ "direction": "promote",
1011+ "from": "memory",
1012+ "to": "experience",
1013+ "touches": 2,
1014+ "stable_steps": 1,
1015+ "dormant_steps": 0,
1016+ "candidate_score": 1.1178,
1017+ "resonance": 1.3338,
1018+ "flow": 0.5983
1019+ },
1020+ {
1021+ "step": 2,
1022+ "node": "alpha",
1023+ "direction": "promote",
1024+ "from": "experience",
1025+ "to": "skill_belt",
1026+ "touches": 4,
1027+ "stable_steps": 2,
1028+ "dormant_steps": 0,
1029+ "candidate_score": 2.3563,
1030+ "resonance": 3.546,
1031+ "flow": 1.2806
1032+ },
1033+ {
1034+ "step": 4,
1035+ "node": "alpha",
1036+ "direction": "promote",
1037+ "from": "skill_belt",
1038+ "to": "ability_core",
1039+ "touches": 8,
1040+ "stable_steps": 4,
1041+ "dormant_steps": 0,
1042+ "candidate_score": 3.7893,
1043+ "resonance": 6.0,
1044+ "flow": 2.7831
1045+ }
1046+ ]
1047+ },
1048+ {
1049+ "name": "skill_belt_candidates_have_evidence",
1050+ "status": "pass",
1051+ "detail": "Skill-belt candidates are backed by repeated activation, stability, and flow evidence.",
1052+ "alpha_candidate": {
1053+ "node": "alpha",
1054+ "score": 3.7893,
1055+ "stage": "ability_core",
1056+ "flow": 2.7831,
1057+ "stable_steps": 4,
1058+ "touches": 8,
1059+ "target_core": "alpha"
1060+ }
1061+ },
1062+ {
1063+ "name": "merge_events_are_recorded",
1064+ "status": "pass",
1065+ "detail": "Stable skill-belt structures can produce explicit merge events into ability-core structures.",
1066+ "merge_events": [
1067+ {
1068+ "step": 4,
1069+ "event": "skill_belt_merge",
1070+ "node": "alpha",
1071+ "target_core": "alpha",
1072+ "support_nodes": [
1073+ "anchor",
1074+ "beta"
1075+ ],
1076+ "candidate_score": 3.7893,
1077+ "stable_steps": 4
1078+ },
1079+ {
1080+ "step": 4,
1081+ "event": "skill_belt_merge",
1082+ "node": "anchor",
1083+ "target_core": "alpha",
1084+ "support_nodes": [
1085+ "alpha"
1086+ ],
1087+ "candidate_score": 3.5277,
1088+ "stable_steps": 4
1089+ },
1090+ {
1091+ "step": 4,
1092+ "event": "skill_belt_merge",
1093+ "node": "beta",
1094+ "target_core": "alpha",
1095+ "support_nodes": [
1096+ "alpha"
1097+ ],
1098+ "candidate_score": 3.5592,
1099+ "stable_steps": 4
1100+ }
1101+ ]
1102+ }
1103+ ],
1104+ "summary": {
1105+ "experience_regions": [
1106+ {
1107+ "region": "alpha",
1108+ "nodes": [
1109+ "alpha",
1110+ "anchor",
1111+ "beta"
1112+ ],
1113+ "stage": "ability_core",
1114+ "activation": 5.0299,
1115+ "potential": 4.2739,
1116+ "candidate_score": 10.8762,
1117+ "stable_steps": 4
1118+ }
1119+ ],
1120+ "bound_ability_core": "alpha"
1121+ }
1122+ },
1123+ "snapshot_checks": {
1124+ "status": "pass",
1125+ "passed": 4,
1126+ "failed": 0,
1127+ "checks": [
1128+ {
1129+ "name": "locked_snapshot_fields_present",
1130+ "status": "pass",
1131+ "detail": "snapshot_state returns the locked comparable field set.",
1132+ "observed_keys": [
1133+ "J_summary",
1134+ "active_region",
1135+ "anchor_pull",
1136+ "bound_ability_core",
1137+ "decay_events",
1138+ "drift_score",
1139+ "experience_regions",
1140+ "feedback_effect",
1141+ "free_capacity",
1142+ "merge_events",
1143+ "mu_summary",
1144+ "output_mode",
1145+ "phi_summary",
1146+ "sedimentation_trace",
1147+ "skill_belt_candidates"
1148+ ],
1149+ "required_keys": [
1150+ "J_summary",
1151+ "active_region",
1152+ "anchor_pull",
1153+ "bound_ability_core",
1154+ "decay_events",
1155+ "drift_score",
1156+ "experience_regions",
1157+ "feedback_effect",
1158+ "free_capacity",
1159+ "merge_events",
1160+ "mu_summary",
1161+ "output_mode",
1162+ "phi_summary",
1163+ "sedimentation_trace",
1164+ "skill_belt_candidates"
1165+ ]
1166+ },
1167+ {
1168+ "name": "summary_fields_are_meaningful",
1169+ "status": "pass",
1170+ "detail": "phi_summary, mu_summary, and J_summary expose non-empty observable summaries after activity.",
1171+ "phi_summary": {
1172+ "node_count": 8,
1173+ "total_potential": 1.9781,
1174+ "top_nodes": [
1175+ {
1176+ "node": "native",
1177+ "value": 0.4828
1178+ },
1179+ {
1180+ "node": "graph",
1181+ "value": 0.417
1182+ },
1183+ {
1184+ "node": "a",
1185+ "value": 0.2996
1186+ },
1187+ {
1188+ "node": "feedback",
1189+ "value": 0.2814
1190+ },
1191+ {
1192+ "node": "branch",
1193+ "value": 0.2513
1194+ }
1195+ ]
1196+ },
1197+ "mu_summary": {
1198+ "active_count": 7,
1199+ "total_activation": 2.0156,
1200+ "top_nodes": [
1201+ {
1202+ "node": "native",
1203+ "value": 0.8468
1204+ },
1205+ {
1206+ "node": "graph",
1207+ "value": 0.4725
1208+ },
1209+ {
1210+ "node": "feedback",
1211+ "value": 0.2321
1212+ },
1213+ {
1214+ "node": "a",
1215+ "value": 0.2241
1216+ },
1217+ {
1218+ "node": "branch",
1219+ "value": 0.1324
1220+ }
1221+ ]
1222+ },
1223+ "J_summary": {
1224+ "edge_count": 26,
1225+ "total_flow": 2.2016,
1226+ "top_flows": [
1227+ {
1228+ "edge": "graph->native",
1229+ "flow": 0.2947
1230+ },
1231+ {
1232+ "edge": "native->feedback",
1233+ "flow": 0.2864
1234+ },
1235+ {
1236+ "edge": "a->graph",
1237+ "flow": 0.2406
1238+ },
1239+ {
1240+ "edge": "branch->a",
1241+ "flow": 0.2362
1242+ },
1243+ {
1244+ "edge": "state->branch",
1245+ "flow": 0.2034
1246+ }
1247+ ]
1248+ }
1249+ },
1250+ {
1251+ "name": "feedback_and_output_fields_are_populated",
1252+ "status": "pass",
1253+ "detail": "snapshot_state exposes output_mode and feedback_effect with applied feedback evidence.",
1254+ "output_mode": "degraded",
1255+ "feedback_effect": {
1256+ "source": "emit",
1257+ "mode": "degraded",
1258+ "queued_tokens": [
1259+ "native",
1260+ "graph"
1261+ ],
1262+ "queued_strength": 0.38,
1263+ "confidence_proxy": 0.3667,
1264+ "queued_step": 2,
1265+ "last_applied_step": 3,
1266+ "applied_tokens": [
1267+ "native",
1268+ "graph",
1269+ "a"
1270+ ],
1271+ "phi_delta": 0.0401,
1272+ "mu_delta": 0.0552,
1273+ "flow_delta": 0.0492,
1274+ "stage_after": {
1275+ "native": "skill_belt",
1276+ "graph": "skill_belt",
1277+ "a": "skill_belt"
1278+ },
1279+ "bound_ability_core": "native"
1280+ }
1281+ },
1282+ {
1283+ "name": "locked_homing_and_sedimentation_fields_are_populated",
1284+ "status": "pass",
1285+ "detail": "The locked homing and sedimentation-facing snapshot fields are populated under a controlled scenario.",
1286+ "bound_ability_core": "native",
1287+ "anchor_pull": 0.0484,
1288+ "drift_score": 0.6508
1289+ }
1290+ ],
1291+ "summary": {
1292+ "output_mode": "degraded",
1293+ "free_capacity": 0.7481
1294+ }
1295+ },
1296+ "known_limitations": [
1297+ "The validation harness is scenario-based and compact; it is not a benchmark or long-run stability suite.",
1298+ "Checks focus on the locked observable runtime surface rather than richer semantic task performance.",
1299+ "Sedimentation and homing remain explicit but heuristic, which is acceptable for the review/comparison stage."
1300+ ],
1301+ "overall_status": {
1302+ "status": "pass",
1303+ "passed_sections": 5,
1304+ "failed_sections": 0,
1305+ "ready_for_review": true,
1306+ "summary": "Branch A validation passed and is ready for review/comparison."
1307+ }
1308+}
1@@ -0,0 +1,62 @@
2+# Branch A Validation Report
3+
4+- Branch: `branch-a/task04-validation-reporting`
5+- Base commit: `164c06af63812c69cab32d8f8a6c770b96f38ef6`
6+- Overall status: `PASS`
7+- Ready for review/comparison: `True`
8+
9+## Runtime Summary
10+- Status: `PASS`
11+- Scenarios: interface, smoke, dynamics, sedimentation, snapshot
12+- Output modes observed: full, degraded, minimal
13+
14+## Interface Checks
15+- Status: `PASS`
16+- Passed: `2`
17+- Failed: `0`
18+- `PASS` runtime_initializes: A fresh runtime exposes minimal output mode and no active region.
19+- `PASS` locked_interface_presence: Branch A exposes the locked runtime interface required by the spec.
20+
21+## Smoke Checks
22+- Status: `PASS`
23+- Passed: `4`
24+- Failed: `0`
25+- `PASS` ingest_queues_signal: Ingest stores external tokens and anchor hints before the step loop runs.
26+- `PASS` step_materializes_graph_state: Stepping from a queued input creates observable phi/mu/J state.
27+- `PASS` emit_queues_output_feedback: Emit creates a real output-to-input feedback signal rather than a log-only artifact.
28+- `PASS` feedback_changes_later_state: Queued feedback is applied on the next step and changes later runtime state.
29+
30+## Dynamics Checks
31+- Status: `PASS`
32+- Passed: `4`
33+- Failed: `0`
34+- `PASS` phi_mu_J_are_observable: Multi-step dynamics produce visible changes across phi, mu, and J.
35+- `PASS` homing_signals_are_populated: The runtime exposes bound_ability_core, anchor_pull, and drift_score as active homing signals.
36+- `PASS` decay_and_forgetting_are_visible: Decay/forgetting remains real and observable through decay events and stage demotion.
37+- `PASS` degraded_output_modes_exist: The runtime emits full, degraded, and minimal outputs under different runtime conditions.
38+
39+## Sedimentation Checks
40+- Status: `PASS`
41+- Passed: `4`
42+- Failed: `0`
43+- `PASS` sedimentation_trace_exists: Sedimentation history is exported as explicit runtime trace entries.
44+- `PASS` stage_progression_matches_locked_path: Repeated activation follows the locked memory -> experience -> skill_belt -> ability_core path.
45+- `PASS` skill_belt_candidates_have_evidence: Skill-belt candidates are backed by repeated activation, stability, and flow evidence.
46+- `PASS` merge_events_are_recorded: Stable skill-belt structures can produce explicit merge events into ability-core structures.
47+
48+## Snapshot Checks
49+- Status: `PASS`
50+- Passed: `4`
51+- Failed: `0`
52+- `PASS` locked_snapshot_fields_present: snapshot_state returns the locked comparable field set.
53+- `PASS` summary_fields_are_meaningful: phi_summary, mu_summary, and J_summary expose non-empty observable summaries after activity.
54+- `PASS` feedback_and_output_fields_are_populated: snapshot_state exposes output_mode and feedback_effect with applied feedback evidence.
55+- `PASS` locked_homing_and_sedimentation_fields_are_populated: The locked homing and sedimentation-facing snapshot fields are populated under a controlled scenario.
56+
57+## Known Limitations
58+- The validation harness is scenario-based and compact; it is not a benchmark or long-run stability suite.
59+- Checks focus on the locked observable runtime surface rather than richer semantic task performance.
60+- Sedimentation and homing remain explicit but heuristic, which is acceptable for the review/comparison stage.
61+
62+## Readiness
63+- Branch A validation passed and is ready for review/comparison.
1@@ -120,3 +120,5 @@ Those documents remain locked and define the Branch A requirements for graph-nat
2 - unified validation/reporting against the locked comparison format is still pending
3 - sedimentation merge logic is explicit and inspectable, but still heuristic and node/region centric rather than richer loop-level structure analysis
4 - snapshot observability is ready for Task 04, but the final cross-branch report/export layer is not yet implemented
5+
6+Task 04 for Branch A was then branched independently from commit `164c06af63812c69cab32d8f8a6c770b96f38ef6` on `branch-a/task04-validation-reporting` to add unified validation/reporting and review-ready exports.
1@@ -0,0 +1,130 @@
2+# Task 04: Branch A Validation and Reporting
3+
4+## Title
5+
6+Task 04: unified validation + reporting against locked spec
7+
8+## Direct Prompt
9+
10+Continue Branch A from commit `164c06af63812c69cab32d8f8a6c770b96f38ef6`, keep the implementation independent from other branches, add a small unified validation/reporting entrypoint against the locked docs, generate machine-readable and human-readable reports, and record execution results in-repo.
11+
12+## Suggested Branch Name
13+
14+`branch-a/task04-validation-reporting`
15+
16+## Goal
17+
18+Implement the smallest explicit Branch A validation/reporting layer that checks the locked runtime surface, summarizes smoke/dynamics/sedimentation readiness in one schema, and documents Branch A as ready for review/comparison.
19+
20+## Background
21+
22+This round continues to follow the locked conceptual and engineering constraints in:
23+
24+- `/Users/george/code/CIE-Unified/README.md`
25+- `/Users/george/code/CIE-Unified/LOCKED_IMPLEMENTATION_SPEC.md`
26+
27+Those documents remain locked and define the Branch A requirements for graph-native runtime state, the unified interface, output-to-input feedback, homing, decay, degraded output, sedimentation observability, and comparable reporting.
28+
29+## Involved Repo
30+
31+- `/Users/george/code/CIE-Unified`
32+
33+## Scope
34+
35+- update the Branch A plan for Task 04 completion
36+- create this Task 04 prompt document in-repo
37+- add a stdlib-only `cie.validation` entrypoint for compact controlled scenarios
38+- validate smoke, dynamics, sedimentation, and locked snapshot requirements in a consistent schema
39+- generate a machine-readable JSON report and a human-readable Markdown report
40+- add tests for the validation entrypoint and report schema
41+- append the Task 04 continuation note to the Task 03 record
42+- leave Branch A documented as ready for review/comparison rather than adding new runtime subsystems
43+
44+## Allowed Modifications
45+
46+- `/Users/george/code/CIE-Unified/plans/2026-03-31_branch_a_plan.md`
47+- `/Users/george/code/CIE-Unified/tasks/2026-03-31_task03_branch_a_sedimentation.md`
48+- `/Users/george/code/CIE-Unified/tasks/2026-03-31_task04_branch_a_validation_reporting.md`
49+- `/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.md`
50+- `/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.json`
51+- `/Users/george/code/CIE-Unified/cie/__init__.py`
52+- `/Users/george/code/CIE-Unified/cie/runtime.py`
53+- `/Users/george/code/CIE-Unified/cie/validation.py`
54+- `/Users/george/code/CIE-Unified/tests/__init__.py`
55+- `/Users/george/code/CIE-Unified/tests/test_smoke.py`
56+- `/Users/george/code/CIE-Unified/tests/test_dynamics.py`
57+- `/Users/george/code/CIE-Unified/tests/test_sedimentation.py`
58+- `/Users/george/code/CIE-Unified/tests/test_validation.py`
59+
60+## Avoid Modifying
61+
62+- `/Users/george/code/CIE-Unified/README.md`
63+- `/Users/george/code/CIE-Unified/LOCKED_IMPLEMENTATION_SPEC.md`
64+
65+## Must Complete
66+
67+- mark Task 03 complete and Task 04 complete in the Branch A plan
68+- create this Task 04 prompt document in-repo
69+- implement a unified validation/reporting entrypoint for Branch A
70+- validate smoke + dynamics + sedimentation expectations in one consistent report schema
71+- check locked `snapshot_state()` fields and required runtime behaviors
72+- generate `/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.json`
73+- generate `/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.md`
74+- run the recommended validation commands
75+- record execution details and remaining review-stage limitations here
76+
77+## Acceptance Criteria
78+
79+1. there is a unified validation/reporting entrypoint for Branch A
80+2. validation covers smoke + dynamics + sedimentation expectations in a consistent schema
81+3. validation checks locked `snapshot_state` fields and required runtime behaviors
82+4. a machine-readable JSON report is generated
83+5. a human-readable Markdown report is generated
84+6. tests pass
85+7. Branch A is documented as ready for review/comparison
86+
87+## Evaluation Requirements
88+
89+- use only the Python standard library in new runtime/validation code
90+- keep Branch A graph-native with `(phi, mu, J)` as the canonical state
91+- keep state minimal, parameters few, and observability explicit
92+- avoid `exact_text_map`
93+- avoid MoE-style substitution
94+- avoid latent-vector ontology as the real runtime state
95+- prefer an explicit readable harness over a larger framework
96+
97+## Recommended Validation Commands
98+
99+- `python3 -m unittest discover -s tests -v`
100+- `python3 -m cie.validation`
101+
102+## Delivery Requirements
103+
104+- commit on `branch-a/task04-validation-reporting`
105+- push the branch to `origin`
106+- keep the implementation independent from `branch-b` and other later branches
107+- include execution record details for branch/base/backup/files/validation/results/limitations
108+- leave Branch A ready for review/comparison rather than feature-expanded
109+
110+## Execution Record
111+
112+- actual branch name: `branch-a/task04-validation-reporting`
113+- base commit: `164c06af63812c69cab32d8f8a6c770b96f38ef6`
114+- backup path used for dirty-worktree handling: `none`
115+- files changed:
116+ - `/Users/george/code/CIE-Unified/plans/2026-03-31_branch_a_plan.md`
117+ - `/Users/george/code/CIE-Unified/tasks/2026-03-31_task03_branch_a_sedimentation.md`
118+ - `/Users/george/code/CIE-Unified/tasks/2026-03-31_task04_branch_a_validation_reporting.md`
119+ - `/Users/george/code/CIE-Unified/cie/validation.py`
120+ - `/Users/george/code/CIE-Unified/tests/test_validation.py`
121+ - `/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.json`
122+ - `/Users/george/code/CIE-Unified/reports/2026-03-31_task04_branch_a_validation.md`
123+- validation commands:
124+ - `python3 -m unittest discover -s tests -v`
125+ - `python3 -m cie.validation`
126+- concise test summary: `Ran 18 tests; all passed.`
127+- concise report summary: `Validation report status PASS; interface, smoke, dynamics, sedimentation, and snapshot sections all passed; Branch A is ready for review/comparison.`
128+- remaining known limitations for review stage:
129+ - the validation harness is compact and scenario-based rather than a benchmark or long-run stability suite
130+ - checks target the locked observable runtime surface, not richer semantic task-performance evaluation
131+ - homing and sedimentation remain explicit but heuristic, which is acceptable for this comparison-ready stage
+74,
-0
1@@ -0,0 +1,74 @@
2+from __future__ import annotations
3+
4+import json
5+import subprocess
6+import sys
7+import tempfile
8+import unittest
9+from pathlib import Path
10+
11+from cie.validation import (
12+ DEFAULT_JSON_REPORT_PATH,
13+ DEFAULT_MARKDOWN_REPORT_PATH,
14+ REPORT_TOP_LEVEL_KEYS,
15+ generate_validation_report,
16+)
17+
18+
19+REPO_ROOT = Path(__file__).resolve().parent.parent
20+
21+
22+class ValidationReportTests(unittest.TestCase):
23+ def test_validation_entrypoint_runs_with_default_paths(self) -> None:
24+ completed = subprocess.run(
25+ [sys.executable, "-m", "cie.validation"],
26+ cwd=REPO_ROOT,
27+ capture_output=True,
28+ text=True,
29+ )
30+ self.assertEqual(completed.returncode, 0, msg=completed.stderr)
31+ self.assertTrue(DEFAULT_JSON_REPORT_PATH.exists())
32+ self.assertTrue(DEFAULT_MARKDOWN_REPORT_PATH.exists())
33+
34+ def test_json_report_has_stable_top_level_keys(self) -> None:
35+ with tempfile.TemporaryDirectory() as temp_dir:
36+ json_path = Path(temp_dir) / "validation.json"
37+ markdown_path = Path(temp_dir) / "validation.md"
38+ report = generate_validation_report(json_path, markdown_path)
39+ self.assertEqual(tuple(report), REPORT_TOP_LEVEL_KEYS)
40+ payload = json.loads(json_path.read_text(encoding="utf-8"))
41+ self.assertEqual(tuple(payload), REPORT_TOP_LEVEL_KEYS)
42+ self.assertEqual(payload["overall_status"]["status"], "pass")
43+ self.assertTrue(payload["overall_status"]["ready_for_review"])
44+
45+ def test_markdown_report_contains_pass_fail_style_checks(self) -> None:
46+ with tempfile.TemporaryDirectory() as temp_dir:
47+ json_path = Path(temp_dir) / "validation.json"
48+ markdown_path = Path(temp_dir) / "validation.md"
49+ generate_validation_report(json_path, markdown_path)
50+ markdown = markdown_path.read_text(encoding="utf-8")
51+ self.assertIn("# Branch A Validation Report", markdown)
52+ self.assertIn("## Smoke Checks", markdown)
53+ self.assertIn("`PASS`", markdown)
54+ self.assertIn("ready for review/comparison", markdown.lower())
55+
56+ def test_report_sections_expose_expected_schema(self) -> None:
57+ with tempfile.TemporaryDirectory() as temp_dir:
58+ json_path = Path(temp_dir) / "validation.json"
59+ markdown_path = Path(temp_dir) / "validation.md"
60+ report = generate_validation_report(json_path, markdown_path)
61+ for key in (
62+ "interface_checks",
63+ "smoke_checks",
64+ "dynamics_checks",
65+ "sedimentation_checks",
66+ "snapshot_checks",
67+ ):
68+ section = report[key]
69+ self.assertEqual(section["status"], "pass")
70+ self.assertIn("checks", section)
71+ self.assertGreater(len(section["checks"]), 0)
72+
73+
74+if __name__ == "__main__":
75+ unittest.main()