Rust test comments/assert messages and deep-research script docstrings cited numbered requirement labels (R3/R5) and task labels (TASK-016, TASK-021) that are defined only in an external plan document. Reword each to say what it means on its own: fail-safe crash guards, the validator's fallback-capture warning, task-queue anchors.
71 lines
2.7 KiB
Python
71 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Join the per-question map outputs into a single `findings` string.
|
|
|
|
The `research_each_question` map writes `question_findings` (an array,
|
|
one entry per sub-question, in input order). Downstream nodes
|
|
(`vet_sources`, `critique`, `synthesize`) read `{{findings}}` as a
|
|
single block, so this script renders the array as a Markdown document
|
|
with one section per question.
|
|
|
|
Fault visibility: a research lane that died lands here as a finding
|
|
starting with "PIPELINE-FAULT:" (written by question_fault inside the map
|
|
branch, where `pipeline_faults` itself is out of reach — map branches only
|
|
surface their collected output_key). This script lifts such findings into
|
|
`pipeline_faults` (deduplicated, since a reflexion or feedback loop can
|
|
re-run the map) so dead lanes surface in the report's Pipeline notes.
|
|
|
|
Fail-safe: on a crash (e.g. malformed GRAPH_STATE), `findings`
|
|
becomes the fault text itself and a PIPELINE-FAULT entry is recorded —
|
|
the pipeline proceeds visibly degraded, and the human approval gate is
|
|
the backstop. Existing faults are preserved best-effort.
|
|
"""
|
|
import json
|
|
import os
|
|
|
|
|
|
def load_state():
|
|
path = os.environ.get("GRAPH_STATE_FILE")
|
|
if path:
|
|
with open(path) as f:
|
|
return json.load(f)
|
|
return json.loads(os.environ.get("GRAPH_STATE", "{}"))
|
|
|
|
|
|
def safe_faults():
|
|
try:
|
|
state = load_state()
|
|
return [f for f in (state.get("pipeline_faults") or []) if isinstance(f, str)]
|
|
except Exception: # noqa: BLE001 — best-effort preservation only
|
|
return []
|
|
|
|
|
|
def main():
|
|
state = load_state()
|
|
questions = state.get("questions") or []
|
|
per_question = state.get("question_findings") or []
|
|
faults = [f for f in (state.get("pipeline_faults") or []) if isinstance(f, str)]
|
|
|
|
sections = []
|
|
for idx, q in enumerate(questions):
|
|
body = per_question[idx] if idx < len(per_question) else ""
|
|
if isinstance(body, dict) or isinstance(body, list):
|
|
body = json.dumps(body, indent=2)
|
|
if isinstance(body, str) and body.startswith("PIPELINE-FAULT:") and body not in faults:
|
|
faults.append(body)
|
|
sections.append(f"## {q}\n\n{body}")
|
|
|
|
findings = "\n\n".join(sections) if sections else "No findings gathered."
|
|
print(json.dumps({"findings": findings, "pipeline_faults": faults}))
|
|
|
|
|
|
try:
|
|
main()
|
|
except Exception as e: # noqa: BLE001 — a crashed join must degrade, not die
|
|
faults = safe_faults()
|
|
fault = (
|
|
f"PIPELINE-FAULT: combining findings crashed — {e}; per-question "
|
|
"findings may exist in state but could not be joined"
|
|
)
|
|
faults.append(fault)
|
|
print(json.dumps({"findings": fault, "pipeline_faults": faults}))
|