fix(#136): memory pipeline hardening + issue relinking (#135)#138
Open
alexosugo wants to merge 17 commits into
Open
fix(#136): memory pipeline hardening + issue relinking (#135)#138alexosugo wants to merge 17 commits into
alexosugo wants to merge 17 commits into
Conversation
…; flag no-issue PRs; share link
…ross-check, collision-aware)
…ref filter, Sonar fixes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…SonarCloud S6594) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… — addresses #129 review Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
R2: open-review-pr rejects a draft whose issueNumber aliases its own source PR number, or whose filename slug contradicts its frontmatter issueNumber (src/scripts/dedup.ts ciGuardReason). R3: a cross-domain dedupeByIssueId pass collapses backport cherry-picks and multi-PR epics that resolve to the same issue id into one canonical draft (lowest source PR number), tagging it with source_prs[]. Adds the source_prs field to agent-memory/schema.json. Builds on the R1 issue-resolution fix already on this branch (cherry-picked from PR #129's gh-classify.ts/issue-linkage.ts), which makes issueNumber a stable, non-aliased key these checks can trust.
…dence gradient R5: CONSTRAINTS block in distiller buildPrompt grounds relatedFiles/entities in the PR's file list, bans ungrounded channels/reviewers/process trivia, and tightens domainReasoning/rootCause field descriptions to stop leaked classifier language and vague root causes. Adds an onboarding/navigation DOMAIN_PITFALLS entry so route-guard/modal/i18n-only PRs aren't forced into forms-and-reports. R6: scraper.ts strips HTML-comment template boilerplate (e.g. CHT's PHI warning block) from PR and issue bodies before any truncation happens. distiller.ts grants an expanded ISSUE_BODY_LIMIT when the PR body is near-empty, so a bare "Fixes #N" PR doesn't lose the issue's root-cause mechanism to truncation (cht-core #10912 / memory 10914). R7: confidence is now computeConfidence(draft, pr) instead of a hardcoded 'medium' — 'low' when relatedFiles aren't grounded in the PR's file list or the PR looks like a backport cherry-pick. related_issues is now populated from the PR's own secondary linked issues (candidate cht-core-<n> memory ids) instead of always being an empty array awaiting a pass that never ran.
…ry-run collectValidPlans previously rewrote a canonical draft's frontmatter (source_prs) unconditionally, and never deleted a collapsed duplicate from _pending. Two bugs followed: dry-run silently mutated draft files on disk, and an apply run's collapsed duplicate stayed in _pending — on the next run it was the only member of its group, so it got promoted as a fresh memory for an issue already in the corpus, defeating R3's one-memory-per-issue invariant. collectValidPlans is now pure planning (returns kept/dropped alongside plans/skipped); the frontmatter rewrite and duplicate deletion happen in a new applyDedupMutations, called only when --apply is passed. Adds an integration test through openReviewPR covering both the dry-run no-mutation case and the apply collapse-and-delete case, verified against the real schema validator.
…run-hygiene
Adds a small reconcile.ts module: reconcile() buckets a batch's skip-log
entries into CI-guard rejections, dedup collapses, and other human-review
flags (matching on .includes since open-review-pr.ts's writeSkipEntry always
prefixes reasons with "open-review-pr: ", never a bare prefix match), and
hallucinationRate() is a ground-truth check comparing a distilled draft's
relatedFiles/entities against the PR's real fileList. distillPR now returns
hallucinationRate on written drafts; run-pipeline's reportOutcome prints both
the reconciliation summary and a count of drafts with unverified file refs
(a >0 reporting threshold, not a gate — entities may legitimately name a
module/concept rather than a literal path).
Root-caused the real _skipped.ndjson pollution: filter.spec.ts's
"touchesMultipleServices: single service..." test called
filterPR(pr, { skipLlm: true }) without a logPath override, so the skipLlm
branch's flag-for-human write landed in the real DEFAULT_PIPELINE_LOG_PATH
on every `npm test` run. Fixed by passing a tmpLogPath() like every other
test in the file. Cleaned the 7 already-committed prNumber:1 rows (all
"LLM triage skipped", 2026-06-16 — leftover fixture noise); verified no
further pollution by emptying the file and running the full suite to
confirm it stays empty.
…y-pipeline-roadmap
…e and issue number slugify() deleted punctuation instead of replacing it with a boundary, so "fix(#11218):" collapsed to "fix11218" with no separator between the commit type and the issue number. Replace stripped characters with a space so they become a hyphen after collapsing, e.g. "fix-11218-...". The filename-token regexes in dedup.ts and relink-issues.ts that cross-check a draft's slug against its frontmatter issueNumber assumed the no-separator shape; made the separator optional there so both old (already-promoted, never-rewritten) and new drafts keep resolving correctly.
…is missing roborev review #223: comparator returned NaN when two drafts for the same issue both lacked source_pr, making canonical draft selection non-deterministic.
- dedup.ts: extract groupByIssueId/collapseGroup/draftId to bring dedupeByIssueId's cognitive complexity under threshold; avoid [object Object] stringification of a non-primitive frontmatter id - distiller.ts: group BACKPORT_MARKER regex alternation to make operator precedence explicit - open-review-pr.ts: extract validateDraft, buildPlansByDomain, buildSkippedDomains, rewriteCanonicalFrontmatter, and removeDroppedDrafts to bring three functions' cognitive complexity under threshold - dedup.spec.ts: use to.be.null/to.be.undefined instead of to.equal(null/undefined) for more specific assertions
…instead The helper splits in bd954fa existed only to dodge the cognitive-complexity linter on straight-line, single-caller code. Inlined back and suppressed the specific Sonar rule at each site instead of forking functions.
Open
8 tasks
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Two related pieces of work on the memory distillation pipeline:
#135 — Issue resolution and relinking: replaces the buggy
pr.prNumber-as-issue-number aliasing with proper GitHub issue resolution viaclosingIssuesReferences+ title scope + body keywords, plus a one-offrelink-issuestool to repair previously mislinked drafts.#136 — Memory pipeline hardening (first-run post-mortem follow-through):
dedupeByIssueId) collapsing backport/multi-PR duplicates into a single canonical draft'medium'dedupeByIssueId's sort comparator: returnedNaN(non-deterministic ordering) when two drafts for the same issue both lackedsource_pr— flagged by roborev review #223, fixed with a stablepathtiebreaker, regression tests added#135
#136
Code review checklist
relink-issuesrepair tool for previously mislinked drafts.License
The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.