feat(TASK-I): PL0 passive Experience Ledger — 10 seed Process Experiences #322
No files matched your search
@@ -0,0 +1,10 @@
|
||||
{"experience_id": "PE-1789003210-0001", "task_run_stage": "OUTWARD/164", "result_type": "FAILURE", "symptom": "Worker wrote schema-variant artifact (search_receipts/sources at top level instead of discovery/reading subsections); gate rejected with '0 sources'", "evidence_references": ["research/issue-164/outward.json (pre-normalization)", "stage_OUTWARD.events.jsonl"], "root_cause_layer": "SCHEMA", "confidence": 0.9, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "Schema-variant normalization in _normalize_outward_artifact", "recurrence_class": "worker-output-format", "wall_cost_s": 415, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.388757+00:00"}
|
||||
{"experience_id": "PE-1789003210-0002", "task_run_stage": "OUTWARD/164", "result_type": "FAILURE", "symptom": "Worker used 'urls' (list) instead of 'url' (string) and 'classification' instead of 'source_class'", "evidence_references": ["research/issue-164/outward.json source entries"], "root_cause_layer": "SCHEMA", "confidence": 0.95, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "Compatibility aliases: urls\u2192url, classification\u2192source_class", "recurrence_class": "field-naming", "wall_cost_s": 0, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.388913+00:00"}
|
||||
{"experience_id": "PE-1789003210-0003", "task_run_stage": "ADVERSARIAL/164", "result_type": "FAILURE", "symptom": "Worker omitted the mandatory disposition field; pipeline raised ValueError on advance", "evidence_references": ["research/issue-164/adversarial.json (disposition: None)"], "root_cause_layer": "PROMPT_CONTRACT", "confidence": 0.9, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "ADVERSARIAL prompt now lists disposition as first required key", "recurrence_class": "missing-mandatory-field", "wall_cost_s": 300, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389003+00:00"}
|
||||
{"experience_id": "PE-1789003210-0004", "task_run_stage": "ADVERSARIAL/164", "result_type": "INEFFICIENCY", "symptom": "Attack with dimension 'duplicate_authority / Rune constraint violations' addressed 2 dimensions but the gate only counted 1 (break-after-first-match)", "evidence_references": ["scripts/research_stage_executor.py _validate_adversarial"], "root_cause_layer": "VALIDATOR", "confidence": 0.9, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "Multi-dimension matching (removed break)", "recurrence_class": "validator-semantics", "wall_cost_s": 0, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389077+00:00"}
|
||||
{"experience_id": "PE-1789003210-0005", "task_run_stage": "SYNTHESIS/164", "result_type": "SUCCESS", "symptom": "Gate correctly rejected synthesis v1 for missing binding mitigation M1 (integration surface not decided)", "evidence_references": ["research/issue-164/synthesis.json (no 'integration surface' in invariants)"], "root_cause_layer": "VALIDATOR", "confidence": 1.0, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "Worker must address M1 in synthesis v2", "recurrence_class": "mitigation-enforcement", "wall_cost_s": 0, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "gate blocked incomplete design", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389163+00:00"}
|
||||
{"experience_id": "PE-1789003210-0006", "task_run_stage": "APPLICABILITY/164", "result_type": "SUCCESS", "symptom": "Route STANDARD_SOLUTION_SUFFICIENT correctly determined \u2014 INNOVATION skipped on merit (existing warm-neuron propagation sufficient)", "evidence_references": ["research/issue-164/applicability.json"], "root_cause_layer": "STAGE_ARCHITECTURE", "confidence": 0.95, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "", "recurrence_class": "conditional-routing", "wall_cost_s": 0, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "correct skip", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389244+00:00"}
|
||||
{"experience_id": "PE-1789003210-0007", "task_run_stage": "OUTWARD/164", "result_type": "SUCCESS", "symptom": "Real external HippoRAG 2 evidence found (13 sources, 6 read from arxiv.org) that grounded the evaluation", "evidence_references": ["research/issue-164/outward.json"], "root_cause_layer": "MODEL_BEHAVIOR", "confidence": 0.95, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "", "recurrence_class": "external-research", "wall_cost_s": 415, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389330+00:00"}
|
||||
{"experience_id": "PE-1789003210-0008", "task_run_stage": "OUTWARD/B1-v2", "result_type": "INEFFICIENCY", "symptom": "384s cognition on a LOCAL_FIX-class task with zero external evidence surface; worker even attempted to fix the bug during research", "evidence_references": ["research/issue-314/telemetry/attempts.jsonl", "#310 contamination record"], "root_cause_layer": "ROUTING", "confidence": 1.0, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "D1 disposition: LOCAL_FIX and STANDARD_CHANGE bypass OUTWARD (ADAPT-2/3/4)", "recurrence_class": "fixed-depth-routing", "wall_cost_s": 384, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389413+00:00"}
|
||||
{"experience_id": "PE-1789003210-0009", "task_run_stage": "D5/mutation_boundary", "result_type": "FAILURE", "symptom": "Porcelain-line comparison couldn't detect mutation of an already-dirty file", "evidence_references": ["tests/test_adapt9_artifact_authority.py fingerprint test"], "root_cause_layer": "DETERMINISTIC_RUNTIME", "confidence": 1.0, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "D5.1: content fingerprints replace porcelain comparison", "recurrence_class": "detection-gap", "wall_cost_s": 0, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389500+00:00"}
|
||||
{"experience_id": "PE-1789003210-0010", "task_run_stage": "ADVERSARIAL+OUTWARD/contracts", "result_type": "FAILURE", "symptom": "Stage-output requirements defined in two places (template + inline prompt) that drifted independently", "evidence_references": ["prompts/research-stages/adversarial.md (had disposition)", "scripts/research_stage_executor.py pp list (lacked disposition)"], "root_cause_layer": "STAGE_ARCHITECTURE", "confidence": 1.0, "human_intervention": false, "pipeline_sha": "2ef2d55", "correction_applied": "TASK D: single-source stage_contracts.py \u2014 prompts, validators, aliases all derive from one registry", "recurrence_class": "duplicate-authority", "wall_cost_s": 0, "model_cost_s": 0, "tool_cost_s": 0, "quality_outcome": "", "reusable_lesson": true, "candidate_status": "SEED", "recorded_at": "2026-09-10T01:20:10.389590+00:00"}
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""process_experience.py — PL0 passive Experience Ledger (TASK I, epic #284).
|
||||
|
||||
Observation and evidence capture only. No autonomous self-editing.
|
||||
Records Process Experience entries from pipeline runs: failures, successes,
|
||||
inefficiencies — with root-cause attribution, evidence references, and
|
||||
confidence. These are EVIDENCE RECORDS, not permanent rules.
|
||||
|
||||
Root-cause layers:
|
||||
MODEL_BEHAVIOR — the model did something unexpected
|
||||
PROMPT_CONTRACT — the prompt didn't communicate requirements clearly
|
||||
SCHEMA — field names/structure mismatch
|
||||
NORMALIZER — normalization was missing or incorrect
|
||||
TOOL_INTERFACE — tool behavior differed from expectation
|
||||
ARTIFACT_ASSEMBLY — artifact file composition issue
|
||||
VALIDATOR — gate checked the wrong thing or missed something
|
||||
ROUTING — the stage shouldn't have run for this task class
|
||||
STAGE_ARCHITECTURE — the stage design itself is the problem
|
||||
DETERMINISTIC_RUNTIME — deterministic code issue (not model)
|
||||
EXTERNAL_DEPENDENCY — external service behaved unexpectedly
|
||||
UNKNOWN — attribution uncertain
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
|
||||
ROOT_CAUSE_LAYERS = {
|
||||
"MODEL_BEHAVIOR", "PROMPT_CONTRACT", "SCHEMA", "NORMALIZER",
|
||||
"TOOL_INTERFACE", "ARTIFACT_ASSEMBLY", "VALIDATOR", "ROUTING",
|
||||
"STAGE_ARCHITECTURE", "DETERMINISTIC_RUNTIME", "EXTERNAL_DEPENDENCY",
|
||||
"UNKNOWN",
|
||||
}
|
||||
|
||||
RESULT_TYPES = {"SUCCESS", "FAILURE", "INEFFICIENCY"}
|
||||
CANDIDATE_STATUSES = {"SEED", "EVALUATED", "PROMOTED", "REJECTED"}
|
||||
|
||||
|
||||
class ExperienceLedger:
|
||||
"""Append-only ledger of Process Experience records."""
|
||||
|
||||
def __init__(self, path: str):
|
||||
self.path = path
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
|
||||
def record(self, task_run_stage: str, result_type: str, symptom: str,
|
||||
evidence: list[str], root_cause: str, confidence: float,
|
||||
human_intervention: bool = False, pipeline_sha: str = "UNKNOWN",
|
||||
correction_applied: str = "", recurrence_class: str = "",
|
||||
wall_cost_s: float | str = 0, model_cost_s: float | str = 0,
|
||||
tool_cost_s: float | str = 0, quality_outcome: str = "",
|
||||
reusable: bool = False, candidate_status: str = "SEED") -> dict:
|
||||
assert result_type in RESULT_TYPES, f"invalid result_type: {result_type}"
|
||||
assert root_cause in ROOT_CAUSE_LAYERS, f"invalid root_cause: {root_cause}"
|
||||
assert candidate_status in CANDIDATE_STATUSES, f"invalid status: {candidate_status}"
|
||||
entry = {
|
||||
"experience_id": f"PE-{int(time.time())}-{len(self.load_all()) + 1:04d}",
|
||||
"task_run_stage": task_run_stage,
|
||||
"result_type": result_type,
|
||||
"symptom": symptom,
|
||||
"evidence_references": evidence,
|
||||
"root_cause_layer": root_cause,
|
||||
"confidence": confidence,
|
||||
"human_intervention": human_intervention,
|
||||
"pipeline_sha": pipeline_sha,
|
||||
"correction_applied": correction_applied,
|
||||
"recurrence_class": recurrence_class,
|
||||
"wall_cost_s": wall_cost_s,
|
||||
"model_cost_s": model_cost_s,
|
||||
"tool_cost_s": tool_cost_s,
|
||||
"quality_outcome": quality_outcome,
|
||||
"reusable_lesson": reusable,
|
||||
"candidate_status": candidate_status,
|
||||
"recorded_at": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
with open(self.path, "a") as f:
|
||||
f.write(json.dumps(entry) + "\n")
|
||||
return entry
|
||||
|
||||
def load_all(self) -> list[dict]:
|
||||
if not os.path.exists(self.path):
|
||||
return []
|
||||
out = []
|
||||
with open(self.path) as f:
|
||||
for line in f:
|
||||
try: out.append(json.loads(line))
|
||||
except json.JSONDecodeError: continue
|
||||
return out
|
||||
|
||||
def by_root_cause(self, layer: str) -> list[dict]:
|
||||
return [e for e in self.load_all() if e["root_cause_layer"] == layer]
|
||||
|
||||
def successes(self) -> list[dict]:
|
||||
return [e for e in self.load_all() if e["result_type"] == "SUCCESS"]
|
||||
|
||||
def failures(self) -> list[dict]:
|
||||
return [e for e in self.load_all() if e["result_type"] == "FAILURE"]
|
||||
|
||||
def reusable_lessons(self) -> list[dict]:
|
||||
return [e for e in self.load_all() if e["reusable_lesson"]]
|
||||
Reference in new issue
Block a user