Repository navigation
FileTree asks the reflector for a rationale and then drops it: carry Diff.rationale into the ledger commit and the rejected-evidence note #247
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
背景 / Motivation
EDIT_PROTOCOL in agentdescent/treestrategy.py asks every reflector for a rationale:
{"rationale": "<one sentence: what was wrong and why this fixes it>", "edits": [...]}
but parse_edits only returns {path: content}, so the rationale is paid for in tokens on every proposal and then thrown away. Downstream, nothing can recover why a change was made:
Diff(agentdescent/evolvable.py) has no field for it.- The ledger commit for an accepted diff is just
merge {diff.diff_id} -> {artifact_id}(aggregator.py), sogit logon the ledger — our lineage — has ids and versions but no reasons. ReplayAwareProposal(agentdescent/replay.py, from feat(replay): settled-evidence pool gets a consumer - ReplaySampler + ProposalContext.rejected #193) shows the inner policy "Recently discarded for this task", but its default note can only render touched paths, base version and measured delta. The reflector learns that an edit toSKILL.mdwas rejected, not what idea was rejected, so "do not re-propose what was just rejected" is weaker than it could be.
Industry signal points the same way: GEPA v0.1.3 now logs reflection prompts/outputs to a proposals table "for run archaeology" and exposes them in on_proposal_end; WikiSkill's ablation finds that a persistent record of past proposals and their accept/reject outcomes (skill-impact.md, read by the proposer so rejected interventions are not proposed again) is critical to its gains.
参考链接 / References
- GEPA v0.1.3 release notes (proposals table for run archaeology, feat: log reflection LM prompts and raw outputs to WandB/MLflow proposals table gepa-ai/gepa#276, feat(rrsi): wire the regularized RRSI mechanism into evolve() through the Policies seams #254): https://github.com/gepa-ai/gepa/releases/tag/v0.1.3
- WikiSkill: Compiling Agent Experience into Persistent Knowledge for Skill Evolution (§3.1 skill-impact tracker, §5.1 ablation): https://arxiv.org/abs/2608.27454
建议实现路径 / Proposed approach
Diffgainsrationale: str = ""(default keeps every existing constructor and pickle/replay path working). It must not enterdiff_id/ the fingerprint, so dedup and eval caching are unchanged.treestrategy.py: addparse_proposal(proposal) -> tuple[dict, str]returning edits plus the rationale (stripped, capped at e.g. 500 chars, non-string →""); keepparse_editsas a thin wrapper for backward compatibility.FileTree.to_diffsetsDiff.rationale.aggregator.py: whendiff.rationaleis non-empty, append it to the commit message body (merge … -> …\n\n<rationale>), sanitised to a single paragraph. Fused diffs (built inaggregator.pykeyed union andfusion.py) concatenate their parents' rationales (deduped, capped).replay.py::_default_noterenderscard.diff.rationalewhen present.- Optional, same PR if small: record
rationaleinMergeReportentries so a run's report can be grepped by reason.
验收标准 / Acceptance criteria
-
parse_proposalreturns the rationale for the<EDITS>, fenced-JSON and bare-object wrappers;parse_editsoutput is byte-for-byte unchanged (existingtests/test_tree_strategy.pypasses untouched). - Two proposals with identical edits but different rationales get the same
diff_id. - An accepted
FileTreediff's ledger commit message contains its rationale (test reads it back viagit log -1 --format=%Bon a scratch ledger). -
ReplayAwareProposalwith the default renderer includes the rejected card's rationale in the note. - Diffs without a rationale (all non-
FileTreestrategies) produce exactly today's commit message.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
fix(rationale): strip NUL/control chars and lone surrogates before gi…
Merge pull request #249 from Birfy/fix/issue-247-filetree-rationale
Merge main into fix/issue-246-skill-dir-structural-gate