feat(major2): run_project owns the review sink, keys it per approach and writes it from a finally [skip-docs]
Ordre 20260904T173146Z-8102814273-from-portfolio-optimiser, steg 4 av 10.
run_project faar proposal_reviewer (keyword-only, None => byte-identisk kjoering), eier
sinken expert_reviews ved siden av parse_failures, og skriver
{run_id}-proposal-reviews.json fra den EKSISTERENDE genererings-finally-en.
Skriveregelen er IFF en reviewer ble gitt, OGSAA naar lista er tom (D4). Begge halvdeler
er baerende og trekker hver sin vei: write_debate_tools skriver ubetinget fordi DER er det
tomme tilfellet regresjonen; her maa en reviewer-LOES kjoering la utboksen staa byte-identisk
(to eksisterende tester pinner et EKSAKT fire-navns-listing), mens en reviewer som ble tilbudt
og aldri konsultert er et faktum artefaktet maa kunne SI.
Noeklingen: med mandat er hver post noeklet - kjoeringens eget forslag paa OWN_PROPOSAL_ID -
og None betyr kun EN ting: det fantes intet mandat. RunResult.expert_revisions bygges FRA
sinken, aldri ved siden av (kø-(p)).
RODT foer impl: 8 armer.
REGRESJON FANGET AV FULL SUITE OG RETTET HER: steg 3s _FeedbackAwareChatClient kopierte
_inner_get_response-kroppen og gjorde test_scripted_client_consolidation
::test_inner_get_response_collapsed_to_two_sites roed. Doblen overstyrer naa _next_reply i
stedet - basen har alt lagt DENNE kallets prompt i received_texts naar den ber om et svar,
saa sommen holder uten en tredje kopi av kroppen, og registeret i vakten trenger ingen ny
oppfoering. Aa registrere fila som foreign lineage var ikke mulig og heller ikke riktig:
Group B bruker ScriptedChatClient, som den vakten nekter for nettopp den lista.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
bbf4d3b5b6
commit
59f3fce20a
3 changed files with 410 additions and 27 deletions
|
|
@ -248,6 +248,34 @@ def write_plan_review(
|
|||
return path
|
||||
|
||||
|
||||
def write_proposal_reviews(
|
||||
outbox_dir: str,
|
||||
run_id: str,
|
||||
*,
|
||||
payload: Mapping[str, Any],
|
||||
) -> Path:
|
||||
"""Write ``{run_id}-proposal-reviews.json`` — what a human answered about the proposals this
|
||||
run put on the table (MAJOR-2) — and return its path.
|
||||
|
||||
Takes an already-rendered plain mapping (``proposal_review.proposal_reviews_payload``) for the
|
||||
reason ``write_plan_review`` does: the renderer lives in the module that owns the type, and
|
||||
this layer stays MAF-free. The writer prepends ``run_id`` exactly as its sibling does, so the
|
||||
on-disk object is ``{"reviews": [...], "run_id": ...}`` under ``_dump``'s sorted keys.
|
||||
|
||||
**The write rule is: iff a reviewer was given, INCLUDING when the list is empty** (D4).
|
||||
Both halves are load-bearing and they pull in opposite directions. ``write_debate_tools``
|
||||
writes unconditionally because THERE the empty case is the regression; here a reviewer-LESS
|
||||
run must leave the outbox byte-identical, and two existing tests pin an exact four-name
|
||||
listing on such a run. But a reviewer that was offered and never consulted — no candidate ever
|
||||
validated — is a fact this artefact must be able to STATE, not something an operator has to
|
||||
infer from a missing file. "Iff a reviewer was given" is the only rule that keeps both."""
|
||||
directory = Path(outbox_dir)
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
path = directory / f"{run_id}-proposal-reviews.json"
|
||||
path.write_text(_dump({"run_id": run_id, **dict(payload)}), encoding="utf-8")
|
||||
return path
|
||||
|
||||
|
||||
def write_run_config(
|
||||
config_dir: str,
|
||||
run_id: str,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue