RP11: conservative retirement of superseded ResearchProcess paths (closes#274)
Branch provenance:rp11-retirement from current master tip (691085a), two commits: canonical-pipeline consolidation merge + retirement commit 3a22d99.
Step 1 — consolidation (necessary discovery): master still carried the RSC0-9 stage model (DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING) — the canonical pipeline lived only on rp2-canonical-stage-model (pushed to Gitea this session, 0-commit conflicts). Merged: master now has ONE canonical authority.
Step 2 — retired (each classified, references scanned before removal):
one canonical StageReady handler / executor / transition authority: PASS (research_stage_executor.py single path)
one canonical artifact/gate path per stage: PASS
one canonical Gitea persistence path: PASS
no live DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING authority: PASS (guard raises ValueError on advance; executor returns RETIRED_STAGE; regression-tested)
no production self-walking research loop: PASS (run_full_research deleted)
no foreground LLM sleep/poll supervisor: PASS (--watch deleted)
unknown-purpose code deleted: NO
historical evidence preserved: PASS
full regression suite vs pre-cleanup baseline: PASS — 1129 passed (baseline 1069; canonical tests joined), 0 henxel failures, lint baseline SHRANK (80/352)
RP12/#275 may begin.
## RP11: conservative retirement of superseded ResearchProcess paths (closes #274)
**Branch provenance:** `rp11-retirement` from current master tip (691085a), two commits: canonical-pipeline consolidation merge + retirement commit 3a22d99.
**Step 1 — consolidation (necessary discovery):** master still carried the RSC0-9 stage model (DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING) — the canonical pipeline lived only on `rp2-canonical-stage-model` (pushed to Gitea this session, 0-commit conflicts). Merged: master now has ONE canonical authority.
**Step 2 — retired (each classified, references scanned before removal):**
- `scripts/research_backend.py` — run_full_research() self-walking loop + --watch poll supervisor (§26.6/26.7)
- `scripts/run_research_stage.py`, `scripts/run_agent_stage.py` + test (no live imports; docstring-only mention verified)
- 3 legacy research workflows (trigger paths dead since RP0 label strip)
- 3 split-stage prompt templates (concepts survive as outward.md subsections)
- repo-level `research-pending` label deleted (zero issues carried it)
**Kept (canonical reuse):** event relay, artifact validators, router, inward context builder, prompt compiler, ISSUE-gate compiler, task tree + executor (canonical authorities). RETIRED_STAGES guard retains the old names ONLY as the block preventing execution.
**Evidence preserved:** research/issue-* dirs, closed issues #245/#254-#256/#260-#263, classification manifest updated to RETIRED status.
**UNKNOWN_PURPOSE deletions: NONE** (nothing deleted without classification; nothing classified unknown required deletion).
**Acceptance matrix:**
- one canonical stage model: **PASS** (master STAGES = canonical 8; RETIRED_STAGES guard)
- one canonical StageReady handler / executor / transition authority: **PASS** (research_stage_executor.py single path)
- one canonical artifact/gate path per stage: **PASS**
- one canonical Gitea persistence path: **PASS**
- no live DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING authority: **PASS** (guard raises ValueError on advance; executor returns RETIRED_STAGE; regression-tested)
- no production self-walking research loop: **PASS** (run_full_research deleted)
- no foreground LLM sleep/poll supervisor: **PASS** (--watch deleted)
- unknown-purpose code deleted: **NO**
- historical evidence preserved: **PASS**
- full regression suite vs pre-cleanup baseline: **PASS** — 1129 passed (baseline 1069; canonical tests joined), 0 henxel failures, lint baseline SHRANK (80/352)
RP12/#275 may begin.
One coherent MiMo external-research pass. Discovery and reading remain
visible as subsections inside the artifact, not separate top-level stages.
Artifact has discovery and reading subsections. Event relay streams both.
Canonical handoff 2026-09-08 (epic #257, children #264-#277):
- ISSUE (deterministic issue-quality gate) replaces DEFINE as stage 0 —
the Gitea issue is the authoritative definition; no cognitive DEFINE stage
- APPLICABILITY added after OUTWARD with canonical candidate classifications
- INNOVATION precedes ADVERSARIAL (canonical order per §1)
- OUTWARD unified (OR1 preserved): discovery+reading are artifact subsections
- RETIRED_STAGES declared: DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING cannot
be advanced or dispatched through the canonical path (RETIRED_STAGE status)
- more_research → targeted refinement routing to EARLIEST deficient stage;
external unknowns route to unified OUTWARD, never the retired split stages
- fake worker, integration/boundary/reliability tests rewritten for canonical
chain; legacy-state tree at a retired stage raises on advance
- new prompt templates: issue.md, applicability.md (with MUST NOT contracts)
Tests: 104 passed. Ruff clean. Pre-existing henxels digest failure unchanged
(missing henxels.contract module in env, fails identically on clean tree).
closes#264 (RP1 stage model); runner-placement enforcement (RP2/#265) next
THE HEAVY RUNNER IS THE DESKTOP PC, NOT THE PI.
- scripts/runner_evidence.py: runtime execution evidence capture (hostname,
runner identity from env, labels, execution class, stage, process id,
issue, research process id, timestamp) — identity captured at runtime,
never inferred from configuration alone
- Deterministic placement gate (validate_placement): desktop-heavy stage
executed on Pi → PLACEMENT_REJECTED; hostname checked too (cannot hide
the Pi behind a desktop runner name); missing evidence fields rejected;
unverified runners rejected (no silent fallback); pi-lightweight forge
operations (metadata, labels, eligibility) explicitly allowed
- Placement gate wired into StageExecutor.execute(): every stage result
embeds runner_evidence; Pi execution fails the tree and cannot count
as acceptance
- docs/RESEARCH_CODE_CLASSIFICATION.md: aggressive detection, conservative
classification (CURRENT/SUPERSEDED/COMPATIBILITY/TEST_FIXTURE/
UNKNOWN_PURPOSE); NO deletion in #265 — retirement is RP11 after RP10
proof; run_full_research() self-walk + --watch poll classified SUPERSEDED;
tui-restart-pending marked SUPERSEDED CANDIDATE (verify before removal)
Acceptance: canonical order PASS; conditional INNOVATION PASS; ISSUE
deterministic PASS; earliest-stage refinement PASS; heavy-runner requirement
encoded PASS; Pi rejection PASS; runtime identity/hostname/labels captured
PASS; stage/run/process identity PASS; Gitea stage authority preserved
(one-stage executor unchanged) PASS; no self-walking production loop in the
canonical path PASS; no premature retirement PASS.
125 tests pass, ruff clean. Pre-existing henxels digest env failure unchanged.
- ResearchEventRelay captures per-event tool receipts (QUERY / SOURCE_READ /
TOOL / TOOL_FAILED with url + timestamp) — the QUERY→SOURCE→READ→CLAIM
chain now has real provenance, not just counts
- OUTWARD artifact embeds tool_receipts; sources carry read_receipt flag —
a source counts as read only if the relay captured a real fetch
- _validate_outward fixed to read the unified (discovery/reading) artifact
structure — previous validator read top-level keys that never existed,
so any real run would have gate-failed; now also enforces ≥1 actually-read
source and non-empty tool receipts (search snippets alone ≠ evidence)
125 tests pass, ruff clean.
The structured artifact IS the authority (§5); stdout text is just one
delivery channel. When the relay collects no stdout texts but the worker
wrote a valid dossier to the stage artifact file, the executor normalizes
it into the canonical unified structure (_normalize_outward_artifact) and
gates it the same way. Gate semantics unchanged: ≥2 sources, real read
receipts required, tool receipts required.
Verified against the real #161 OUTWARD run: worker dossier (16 sources,
4 read with 22 claims, 4 contradictions, 8 limitations) + relay receipts
extracted from the live events file (4 queries, 4 reads, 22 tools) →
GATE PASSED, tree advanced to APPLICABILITY. Artifact hash bc57c4600880.
- _execute_applicability: one bounded MiMo pass consuming ISSUE+INWARD+OUTWARD
artifacts; bounded inputs (source/claim ids, not prose); structured dossier
written by worker to applicability.json — file channel accepted (structured
artifact is the authority), stdout JSON also parsed
- Gate (_validate_applicability): route must be STANDARD_SOLUTION_SUFFICIENT
or INNOVATION_WARRANTED; candidates must use canonical classifications;
viable candidates (DIRECTLY_APPLICABLE/APPLICABLE_WITH_ADAPTATION/
PROMISING_FOR_INNOVATION) require integration_point AND evidence ids;
source_ids must resolve to accepted OUTWARD sources (no fabricated citations)
- Route decision drives conditional INNOVATION routing at advance()
- Stage-ordering guard: no OUTWARD artifact → STAGE_FAILED without MiMo call
- 6 new tests; suite 123 pass, ruff clean
Prose-only stdout with a valid applicability.json on disk previously produced
an empty artifact stub (gate-fail with misleading 'no candidates' error).
Now: stdout JSON parsed first; if no candidates, the dossier file channel is
checked. Structured artifact remains the authority. Verified on real #161 run:
9 candidates + repo-verified receipts → GATE PASSED (f477543dc8c9),
route STANDARD_SOLUTION_SUFFICIENT → ADVERSARIAL (INNOVATION skipped on merit).
- _execute_adversarial: one bounded MiMo red-team pass on the leading
APPLICABILITY candidates; targeted external checks permitted with receipts
- Dossier: surviving/rejected candidates, attacks (dimension+finding+evidence+
severity), critical assumptions, required mitigations, research gaps,
falsification tests
- Gate (_validate_adversarial): rubber-stamp fails (zero attacks); all seven
attack dimensions must be addressed; every leading candidate must be
attacked at least once; a fatal attack on a surviving candidate requires
an explicit rebuttal
- File channel accepted whenever stdout parse yields nothing (established
worker pattern); stage-ordering guard (no APPLICABILITY → STAGE_FAILED)
- 7 new tests; suite 130 pass, ruff clean
Real-run findings from #161: worker emits snake_case dimensions
(weak_assumptions, Rune_constraint_violations) — gate now normalizes
snake/kebab to spaces before matching. Falsification may be satisfied either
as an attack dimension or as dedicated falsification_tests (kill-tests) —
the worker produced 2 concrete kill-tests (e.g. FT1: run harness with
embedding backend unreachable; any unlabeled mode switch voids validation).
Verified: 16 attacks, 6 survivors, 1 rejection (memory-adapter-protocol —
duplicate authority vs memory_selector.py source registry), 2 external
checks, 25 repo-verification tool calls → GATE PASSED (3827446e701a),
tree at SYNTHESIS.
- _execute_synthesis: deterministic readiness invariant enforced BEFORE the
MiMo call (no cognition on untrustworthy foundations); bounded prompt
carries survivors, rejected candidates + reasons, required mitigations,
and kill-tests as ACCEPTED CONSTRAINTS
- Worker produces build instructions: selected_design, why-this-design-won,
rejected_alternatives, components_affected, authority_boundaries,
interfaces, data_flow, implementation_sequence, invariants, tests_required,
acceptance_criteria, failure_modes, rollback, deliberately_excluded
- Gate (_validate_synthesis): all core fields present (design, sequence,
interfaces, acceptance, rollback); every falsification test converted into
an invariant; every required mitigation represented STRUCTURALLY
(invariants/interfaces/data_flow/tests/acceptance — prose mention in the
design summary is not representation); rejected-candidate resurrection
forbidden (id scan across design + components)
- Artifact carries provenance: adversarial_disposition, carried_mitigations,
carried_falsification_tests, carried_survivors — the literal-handoff input
shows exactly which constraints the design was built under
- 8 new tests; suite 165 pass, ruff clean
Real-run finding from #161: the worker integrated all 10 adversarial
mitigations into its design language (60-100% key-concept overlap in
structural fields) but did not quote the mitigation sentences verbatim.
Literal substring matching tested copy-paste, not design coverage. The gate
now measures keyword-overlap coverage (≥50% of non-stopword key concepts)
across invariants/interfaces/data_flow/tests/acceptance.
Verified: 10/10 mitigations represented, 7 kill-tests converted to 13
invariants, 11-step implementation sequence → GATE PASSED (e584bbf895b3),
tree at QUALIFY.
- _execute_qualify: deterministic-first — 13 implementation-readiness checks
(design explicit, interfaces concrete, authority boundaries, data flow,
sequence, invariants, tests, acceptance, failure modes, rollback,
adversarial mitigations included, falsification tests included, blocking
unknowns absent) run BEFORE any MiMo call
- MiMo semantic judgment ONLY when deterministic checks pass: judge whether
a coder could implement without guessing — not re-research, not re-litigating
the design (ADVERSARIAL owns epistemics)
- Verdict assembly: deterministic failures → REFINE_SYNTHESIS without a model
call; worker verdicts constrained to PROCEED/REFINE_SYNTHESIS; informal
reopen attempts downgraded to REFINE_SYNTHESIS; formal reopen requires the
four justification fields (gate-enforced)
- Malformed worker verdicts treated as REFINE_SYNTHESIS (fail-safe)
- 9 new tests; suite 174 pass, ruff clean
RP11/#274 step 1 — consolidate to ONE canonical authority. The RSC0-9
research scripts on master (DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING stage
model) are superseded by the canonical pipeline proven through RP2-RP10
(epic #257, children #264-#273): ISSUE→INWARD→OUTWARD→APPLICABILITY→
conditional INNOVATION→ADVERSARIAL(disposition)→SYNTHESIS→QUALIFY.
Zero conflicts vs current master; the #161 harness (PR #279) is preserved.
🤖Headless spec gate (non-blocking, #204 first slice)
Spec-gate agent produced no text output — check runner logs.
Deterministic floors still govern the merge
This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.
🤖 **Headless spec gate (non-blocking, #204 first slice)**
Spec-gate agent produced no text output — check runner logs.
<details><summary>Deterministic floors still govern the merge</summary>
This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.</details>
CI exposed a latent validator defect masked locally: the desktop runner's
Gitea-registered name is 'rune-desktop' (label 'rune-ci-desktop'), but
validate_placement required the LABEL string inside runner_name — so every
CI-executed stage was PLACEMENT_REJECTED while local runs passed (local:
prefix path).
Fix: desktop identity = label in name/labels, OR the registered rune-desktop
runner name, OR verified local execution. Pi rejection semantics unchanged
(regression-tested: rune-pi/rune-infra-pi still rejected via name, hostname,
and labels).
Found via RP11 PR CI — exactly what RP12's post-cleanup re-run is designed
to catch, caught one run early.
🤖Headless spec gate (non-blocking, #204 first slice)
Spec-gate agent produced no text output — check runner logs.
Deterministic floors still govern the merge
This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.
🤖 **Headless spec gate (non-blocking, #204 first slice)**
Spec-gate agent produced no text output — check runner logs.
<details><summary>Deterministic floors still govern the merge</summary>
This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.</details>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
RP11: conservative retirement of superseded ResearchProcess paths (closes #274)
Branch provenance:
rp11-retirementfrom current master tip (691085a), two commits: canonical-pipeline consolidation merge + retirement commit3a22d99.Step 1 — consolidation (necessary discovery): master still carried the RSC0-9 stage model (DEFINE/OUTWARD_DISCOVERY/OUTWARD_READING) — the canonical pipeline lived only on
rp2-canonical-stage-model(pushed to Gitea this session, 0-commit conflicts). Merged: master now has ONE canonical authority.Step 2 — retired (each classified, references scanned before removal):
scripts/research_backend.py— run_full_research() self-walking loop + --watch poll supervisor (§26.6/26.7)scripts/run_research_stage.py,scripts/run_agent_stage.py+ test (no live imports; docstring-only mention verified)research-pendinglabel deleted (zero issues carried it)Kept (canonical reuse): event relay, artifact validators, router, inward context builder, prompt compiler, ISSUE-gate compiler, task tree + executor (canonical authorities). RETIRED_STAGES guard retains the old names ONLY as the block preventing execution.
Evidence preserved: research/issue-* dirs, closed issues #245/#254-#256/#260-#263, classification manifest updated to RETIRED status.
UNKNOWN_PURPOSE deletions: NONE (nothing deleted without classification; nothing classified unknown required deletion).
Acceptance matrix:
RP12/#275 may begin.
🤖 Headless spec gate (non-blocking, #204 first slice)
Spec-gate agent produced no text output — check runner logs.
Deterministic floors still govern the merge
This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.
🤖 Headless spec gate (non-blocking, #204 first slice)
Spec-gate agent produced no text output — check runner logs.
Deterministic floors still govern the merge
This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.