Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Whitestone
6cbb9a98e1 fix: refresh burn lane audit for #662
Some checks failed
Agent PR Gate / gate (pull_request) Failing after 48s
Self-Healing Smoke / self-healing-smoke (pull_request) Failing after 8s
Smoke Test / smoke (pull_request) Failing after 6s
Agent PR Gate / report (pull_request) Has been cancelled
2026-04-16 23:43:24 -04:00
5 changed files with 151 additions and 265 deletions

View File

@@ -1,73 +0,0 @@
# Issue #582 Verification — Parent-Epic Orchestration Slice
**Date:** 2026-04-20
**Status:** Slice already present on `main`; epic remains open for full archive consumption.
## What #582 asked for
A single orchestration script that stitches the five Know Thy Father phases together
into one reviewable plan — not a replacement for individual scripts, but a spine
that future passes can run, resume, and verify.
## What exists on `main`
| Artifact | Path | Present |
|----------|------|---------|
| Epic pipeline runner | `scripts/know_thy_father/epic_pipeline.py` | ✅ |
| Pipeline documentation | `docs/KNOW_THY_FATHER_MULTIMODAL_PIPELINE.md` | ✅ |
| Phase 1 — Media Indexing | `scripts/know_thy_father/index_media.py` | ✅ |
| Phase 2 — Multimodal Analysis | `scripts/twitter_archive/analyze_media.py` | ✅ |
| Phase 3 — Holographic Synthesis | `scripts/know_thy_father/synthesize_kernels.py` | ✅ |
| Phase 4 — Cross-Reference Audit | `scripts/know_thy_father/crossref_audit.py` | ✅ |
| Phase 5 — Processing Log | `twitter-archive/know-thy-father/tracker.py` | ✅ |
## Runner capabilities (all implemented)
```bash
# Print the orchestrated plan
python3 scripts/know_thy_father/epic_pipeline.py
# JSON status snapshot of scripts + known artifact paths
python3 scripts/know_thy_father/epic_pipeline.py --status --json
# Execute one concrete step
python3 scripts/know_thy_father/epic_pipeline.py --run-step phase2_multimodal_analysis --batch-size 10
```
## Test coverage
The following test suites confirm the orchestration slice is intact:
- `tests/test_know_thy_father_pipeline.py` — pipeline plan structure, status snapshot, doc presence
- `tests/test_know_thy_father_index.py` — Phase 1 media indexing logic
- `tests/test_know_thy_father_synthesis.py` — Phase 3 kernel synthesis
- `tests/test_know_thy_father_crossref.py` — Phase 4 cross-reference audit
- `tests/twitter_archive/test_ktf_tracker.py` — Phase 5 processing tracker
- `tests/twitter_archive/test_analyze_media.py` — Phase 2 multimodal analysis
Run all with:
```bash
python3 -m pytest tests/test_know_thy_father_pipeline.py tests/test_know_thy_father_index.py tests/test_know_thy_father_synthesis.py tests/test_know_thy_father_crossref.py tests/twitter_archive/test_ktf_tracker.py tests/twitter_archive/test_analyze_media.py -q
```
## Why Refs #582, not Closes #582
The **repo-side orchestration slice** is fully implemented on `main`. However, the
parent epic itself remains open because:
1. The local Twitter archive has not been fully consumed through all five phases.
2. Downstream memory/fact-store integration is not yet wired end-to-end.
3. The processing log (`PROCESSING_LOG.md`) reflects halted progress that has not resumed.
This PR adds durable verification evidence without overstating closure.
## Historical trail
- Parent-epic PR that landed the orchestration slice: [closed on main]
- This verification document: added by #789, superseded by this PR #790.
## Linked issues
- Refs #582 (parent epic — remains open)
- Closes #789 (verification task — closed by this PR)

View File

@@ -1,6 +1,6 @@
# Burn Lane Empty Audit — timmy-home #662
Generated: 2026-04-16T01:22:37Z
Generated: 2026-04-17T03:42:50Z
Source issue: `[ops] Burn lane empty — all open issues triaged (2026-04-14)`
## Source Snapshot
@@ -11,9 +11,9 @@ Issue #662 is an operational status note, not a normal feature request. Its body
- Referenced issues audited: 42
- Already closed: 30
- Open but likely closure candidates (merged PR found): 0
- Open with active PRs: 12
- Open / needs manual review: 0
- Open but likely closure candidates (merged PR found): 1
- Open with active PRs: 0
- Open / needs manual review: 11
## Issue Body Drift
@@ -21,56 +21,56 @@ The body of #662 is not current truth. It mixes closed issues, open issues, rang
| Issue | State | Classification | PR Summary |
|---|---|---|---|
| #579 | closed | already closed | closed PR #644, closed PR #640, closed PR #635, closed PR #620 |
| #648 | open | active pr | open PR #731 |
| #579 | closed | already closed | closed PR #644, closed PR #643, closed PR #640, closed PR #635, closed PR #620 |
| #648 | open | needs manual review | closed PR #731 |
| #647 | closed | already closed | issue already closed |
| #619 | closed | already closed | issue already closed |
| #616 | closed | already closed | issue already closed |
| #614 | closed | already closed | issue already closed |
| #613 | closed | already closed | issue already closed |
| #660 | closed | already closed | issue already closed |
| #659 | closed | already closed | issue already closed |
| #659 | closed | already closed | closed PR #660 |
| #658 | closed | already closed | issue already closed |
| #657 | closed | already closed | issue already closed |
| #656 | closed | already closed | closed PR #658 |
| #655 | closed | already closed | issue already closed |
| #654 | closed | already closed | closed PR #661 |
| #653 | closed | already closed | issue already closed |
| #652 | closed | already closed | merged PR #657 |
| #651 | closed | already closed | issue already closed |
| #650 | closed | already closed | merged PR #654 |
| #649 | closed | already closed | issue already closed |
| #646 | closed | already closed | issue already closed |
| #582 | open | active pr | open PR #738 |
| #653 | closed | already closed | closed PR #660, closed PR #655 |
| #652 | closed | already closed | closed PR #660, merged PR #657, closed PR #655 |
| #651 | closed | already closed | closed PR #655 |
| #650 | closed | already closed | closed PR #661, closed PR #660, merged PR #654, closed PR #651 |
| #649 | closed | already closed | closed PR #660, merged PR #657, closed PR #651 |
| #646 | closed | already closed | closed PR #655, closed PR #651 |
| #582 | open | closure candidate | merged PR #641, merged PR #639, merged PR #637, merged PR #631, merged PR #630 |
| #627 | closed | already closed | issue already closed |
| #631 | closed | already closed | issue already closed |
| #632 | closed | already closed | issue already closed |
| #634 | closed | already closed | issue already closed |
| #639 | closed | already closed | issue already closed |
| #641 | closed | already closed | issue already closed |
| #575 | closed | already closed | merged PR #656 |
| #576 | closed | already closed | closed PR #663, closed PR #660, closed PR #655, closed PR #651, closed PR #646, closed PR #642, closed PR #633 |
| #575 | closed | already closed | closed PR #658, merged PR #656 |
| #576 | closed | already closed | merged PR #664, closed PR #663, closed PR #660, closed PR #655, merged PR #654, closed PR #651, closed PR #646, closed PR #642, closed PR #633 |
| #578 | closed | already closed | merged PR #638, closed PR #636 |
| #636 | closed | already closed | issue already closed |
| #638 | closed | already closed | issue already closed |
| #547 | open | active pr | open PR #730 |
| #548 | open | active pr | open PR #712 |
| #549 | open | active pr | open PR #729 |
| #550 | open | active pr | open PR #727 |
| #551 | open | active pr | open PR #725 |
| #552 | open | active pr | open PR #724 |
| #553 | open | active pr | open PR #722 |
| #562 | open | active pr | open PR #718 |
| #544 | open | active pr | open PR #732 |
| #545 | open | active pr | open PR #719 |
| #547 | open | needs manual review | closed PR #730 |
| #548 | open | needs manual review | closed PR #712 |
| #549 | open | needs manual review | closed PR #729 |
| #550 | open | needs manual review | closed PR #727 |
| #551 | open | needs manual review | closed PR #725 |
| #552 | open | needs manual review | closed PR #724 |
| #553 | open | needs manual review | closed PR #722 |
| #562 | open | needs manual review | closed PR #718 |
| #544 | open | needs manual review | closed PR #732 |
| #545 | open | needs manual review | closed PR #719 |
## Closure Candidates
These issues are still open but already have merged PR evidence in the forge and should be reviewed for bulk closure.
| None |
|---|
| None |
| Issue | State | Classification | PR Summary |
|---|---|---|---|
| #582 | open | closure candidate | merged PR #641, merged PR #639, merged PR #637, merged PR #631, merged PR #630 |
## Still Open / Needs Manual Review
@@ -78,18 +78,17 @@ These issues either have no matching PR signal or still have an active PR / ambi
| Issue | State | Classification | PR Summary |
|---|---|---|---|
| #648 | open | active pr | open PR #731 |
| #582 | open | active pr | open PR #738 |
| #547 | open | active pr | open PR #730 |
| #548 | open | active pr | open PR #712 |
| #549 | open | active pr | open PR #729 |
| #550 | open | active pr | open PR #727 |
| #551 | open | active pr | open PR #725 |
| #552 | open | active pr | open PR #724 |
| #553 | open | active pr | open PR #722 |
| #562 | open | active pr | open PR #718 |
| #544 | open | active pr | open PR #732 |
| #545 | open | active pr | open PR #719 |
| #648 | open | needs manual review | closed PR #731 |
| #547 | open | needs manual review | closed PR #730 |
| #548 | open | needs manual review | closed PR #712 |
| #549 | open | needs manual review | closed PR #729 |
| #550 | open | needs manual review | closed PR #727 |
| #551 | open | needs manual review | closed PR #725 |
| #552 | open | needs manual review | closed PR #724 |
| #553 | open | needs manual review | closed PR #722 |
| #562 | open | needs manual review | closed PR #718 |
| #544 | open | needs manual review | closed PR #732 |
| #545 | open | needs manual review | closed PR #719 |
## Recommendation

View File

@@ -23,6 +23,7 @@ class PullSummary:
state: str
merged: bool
head: str
body: str
url: str
@@ -75,7 +76,8 @@ def api_get(path: str, token: str):
def collect_pull_summaries(repo: str, token: str) -> list[PullSummary]:
pulls: list[PullSummary] = []
for state in ("open", "closed"):
for page in range(1, 6):
page = 1
while True:
batch = api_get(f"/repos/{ORG}/{repo}/pulls?state={state}&limit=100&page={page}", token)
if not batch:
break
@@ -87,18 +89,18 @@ def collect_pull_summaries(repo: str, token: str) -> list[PullSummary]:
state=pr.get("state") or state,
merged=bool(pr.get("merged")),
head=(pr.get("head") or {}).get("ref") or "",
body=pr.get("body") or "",
url=pr.get("html_url") or pr.get("url") or "",
)
)
if len(batch) < 100:
break
page += 1
return pulls
def match_prs(issue_num: int, pulls: Iterable[PullSummary]) -> list[PullSummary]:
matches: list[PullSummary] = []
for pr in pulls:
text = f"{pr.title} {pr.head}"
text = f"{pr.title} {pr.head} {pr.body}"
if f"#{issue_num}" in text or pr.head == f"fix/{issue_num}" or f"/{issue_num}" in pr.head or f"-{issue_num}" in pr.head:
matches.append(pr)
return matches
@@ -116,12 +118,16 @@ def classify_issue(issue: dict, related_prs: list[PullSummary]) -> IssueAuditRow
else:
merged = [pr for pr in related_prs if pr.merged]
open_prs = [pr for pr in related_prs if pr.state == "open"]
closed_unmerged = [pr for pr in related_prs if pr.state != "open" and not pr.merged]
if merged:
classification = "closure_candidate"
pr_summary = summarize_prs(merged)
elif open_prs:
classification = "active_pr"
pr_summary = summarize_prs(open_prs)
elif closed_unmerged:
classification = "needs_manual_review"
pr_summary = summarize_prs(closed_unmerged)
else:
classification = "needs_manual_review"
pr_summary = "no matching PR found"

View File

@@ -1,6 +1,13 @@
from pathlib import Path
from scripts.burn_lane_issue_audit import extract_issue_numbers, render_report
from scripts.burn_lane_issue_audit import (
PullSummary,
classify_issue,
collect_pull_summaries,
extract_issue_numbers,
match_prs,
render_report,
)
def test_extract_issue_numbers_handles_ranges_and_literals() -> None:
@@ -14,6 +21,99 @@ def test_extract_issue_numbers_handles_ranges_and_literals() -> None:
assert extract_issue_numbers(body) == [579, 660, 659, 658, 582, 627, 631, 547, 546, 545]
def test_match_prs_detects_issue_ref_in_pr_body() -> None:
pulls = [
PullSummary(
number=731,
title="docs: verify session harvest report",
state="open",
merged=False,
head="fix/session-harvest-report",
body="Refs #648",
url="https://forge.example/pr/731",
),
PullSummary(
number=732,
title="unrelated",
state="open",
merged=False,
head="fix/unrelated",
body="Refs #700",
url="https://forge.example/pr/732",
),
]
assert [pr.number for pr in match_prs(648, pulls)] == [731]
def test_open_issue_with_closed_unmerged_pr_stays_manual_review_with_history() -> None:
issue = {
"number": 648,
"title": "session harvest report",
"state": "open",
"html_url": "https://forge.example/issues/648",
}
row = classify_issue(
issue,
[
PullSummary(
number=731,
title="docs: add session harvest report",
state="closed",
merged=False,
head="fix/648",
body="Closes #648",
url="https://forge.example/pr/731",
)
],
)
assert row.classification == "needs_manual_review"
assert row.pr_summary == "closed PR #731"
def test_collect_pull_summaries_pages_until_empty(monkeypatch) -> None:
def fake_api_get(path: str, token: str):
if "state=open" in path:
return []
page = int(path.split("page=")[1])
if page <= 5:
return [
{
"number": page * 1000 + i,
"title": f"page {page} pr {i}",
"state": "closed",
"merged": False,
"head": {"ref": f"fix/{page}-{i}"},
"body": f"Refs #{page * 1000 + i}",
"html_url": f"https://forge.example/pr/{page * 1000 + i}",
}
for i in range(100)
]
if page == 6:
return [
{
"number": 900,
"title": "late page pr",
"state": "closed",
"merged": False,
"head": {"ref": "fix/900"},
"body": "Refs #900",
"html_url": "https://forge.example/pr/900",
}
]
return []
monkeypatch.setattr("scripts.burn_lane_issue_audit.api_get", fake_api_get)
pulls = collect_pull_summaries("timmy-home", "token")
assert any(pr.number == 900 for pr in pulls)
def test_render_report_calls_out_drift_and_candidates() -> None:
rows = [
{

View File

@@ -1,146 +0,0 @@
"""Durable verification that the Issue #582 parent-epic orchestration slice exists on main.
These tests confirm:
1. The epic pipeline runner script is present and importable.
2. The pipeline documentation is committed.
3. All five phase scripts exist at their expected paths.
4. The pipeline plan exposes the correct five phases in order.
5. Each plan step references the correct underlying script.
6. The status snapshot reports script_exists=True for all phases.
7. The status snapshot includes expected artifact output paths.
8. The runner can produce a JSON-serialisable plan.
9. The runner can produce a JSON-serialisable status snapshot.
10. The verification document itself is present.
Refs #582. Closes #789.
"""
import importlib.util
import json
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
EPIC_PIPELINE = ROOT / "scripts" / "know_thy_father" / "epic_pipeline.py"
PIPELINE_DOC = ROOT / "docs" / "KNOW_THY_FATHER_MULTIMODAL_PIPELINE.md"
VERIFICATION_DOC = ROOT / "docs" / "issue-582-verification.md"
EXPECTED_PHASES = [
"phase1_media_indexing",
"phase2_multimodal_analysis",
"phase3_holographic_synthesis",
"phase4_cross_reference_audit",
"phase5_processing_log",
]
EXPECTED_SCRIPTS = {
"phase1_media_indexing": "scripts/know_thy_father/index_media.py",
"phase2_multimodal_analysis": "scripts/twitter_archive/analyze_media.py",
"phase3_holographic_synthesis": "scripts/know_thy_father/synthesize_kernels.py",
"phase4_cross_reference_audit": "scripts/know_thy_father/crossref_audit.py",
"phase5_processing_log": "twitter-archive/know-thy-father/tracker.py",
}
EXPECTED_OUTPUTS = {
"phase1_media_indexing": ["twitter-archive/know-thy-father/media_manifest.jsonl"],
"phase3_holographic_synthesis": ["twitter-archive/knowledge/fathers_ledger.jsonl"],
"phase5_processing_log": ["twitter-archive/know-thy-father/REPORT.md"],
}
def _load_epic_module():
spec = importlib.util.spec_from_file_location("ktf_epic_pipeline", EPIC_PIPELINE)
assert spec and spec.loader, "Cannot load epic_pipeline module spec"
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
class TestIssue582Verification(unittest.TestCase):
"""10-test suite proving the #582 orchestration slice is on main."""
# -- existence checks --------------------------------------------------
def test_01_epic_pipeline_script_exists(self):
"""The orchestration runner is committed."""
self.assertTrue(EPIC_PIPELINE.exists(), f"missing {EPIC_PIPELINE.relative_to(ROOT)}")
def test_02_pipeline_documentation_exists(self):
"""The multimodal pipeline doc is committed."""
self.assertTrue(PIPELINE_DOC.exists(), "missing KNOW_THY_FATHER_MULTIMODAL_PIPELINE.md")
def test_03_all_phase_scripts_exist_on_disk(self):
"""Every script referenced by the pipeline exists in the repo."""
for phase_id, script_rel in EXPECTED_SCRIPTS.items():
path = ROOT / script_rel
self.assertTrue(path.exists(), f"{phase_id}: missing {script_rel}")
# -- plan structure ----------------------------------------------------
def test_04_pipeline_plan_has_five_phases_in_order(self):
mod = _load_epic_module()
plan = mod.build_pipeline_plan(batch_size=10)
ids = [step["id"] for step in plan]
self.assertEqual(ids, EXPECTED_PHASES)
def test_05_plan_commands_reference_correct_scripts(self):
mod = _load_epic_module()
plan = mod.build_pipeline_plan(batch_size=10)
for step in plan:
expected_script = EXPECTED_SCRIPTS[step["id"]]
self.assertIn(
expected_script,
step["command"],
f"{step['id']} command missing {expected_script}",
)
# -- status snapshot ---------------------------------------------------
def test_06_status_snapshot_all_scripts_exist(self):
mod = _load_epic_module()
status = mod.build_status_snapshot(ROOT)
for phase_id in EXPECTED_PHASES:
self.assertIn(phase_id, status)
self.assertTrue(
status[phase_id]["script_exists"],
f"{phase_id} script_exists should be True",
)
def test_07_status_snapshot_reports_expected_outputs(self):
mod = _load_epic_module()
status = mod.build_status_snapshot(ROOT)
for phase_id, expected_paths in EXPECTED_OUTPUTS.items():
actual_paths = [o["path"] for o in status[phase_id]["outputs"]]
for p in expected_paths:
self.assertIn(p, actual_paths, f"{phase_id} missing output path {p}")
# -- JSON serialisation ------------------------------------------------
def test_08_plan_is_json_serialisable(self):
mod = _load_epic_module()
plan = mod.build_pipeline_plan(batch_size=10)
dumped = json.dumps(plan)
restored = json.loads(dumped)
self.assertEqual(len(restored), 5)
def test_09_status_snapshot_is_json_serialisable(self):
mod = _load_epic_module()
status = mod.build_status_snapshot(ROOT)
dumped = json.dumps(status)
restored = json.loads(dumped)
for phase_id in EXPECTED_PHASES:
self.assertIn(phase_id, restored)
# -- verification doc --------------------------------------------------
def test_10_verification_document_exists(self):
"""This verification trail is committed."""
self.assertTrue(
VERIFICATION_DOC.exists(),
"missing docs/issue-582-verification.md",
)
if __name__ == "__main__":
unittest.main()