Skip to content

fix: normalize numeric local-plugin source refs - #2312

Merged
syzsunshine219 merged 16 commits into
mainfrom
fix/local-plugin-numeric-sha-postprocess
Sep 1, 2026
Merged

fix: normalize numeric local-plugin source refs#2312
syzsunshine219 merged 16 commits into
mainfrom
fix/local-plugin-numeric-sha-postprocess

Conversation

@MLittleprince

@MLittleprince MLittleprince commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • canonicalize evidence-backed SHA aliases before final release-note validation
  • repair the exact #10786401 numeric-SHA formatting failure from the v2.0.18 dry-run
  • support short/full/unique-prefix SHA forms plus explicit commit/PR wrappers and GitHub URLs
  • preserve real PR references and keep explicit unknown PRs, ambiguous SHAs, foreign-repository URLs, and unknown references fail-closed
  • deduplicate repeated evidence commits so one real SHA cannot become spuriously ambiguous
  • fail closed when every generated item becomes invalid during normalization
  • write sanitized failure diagnostics on a best-effort basis without masking the original validation error
  • place failure diagnostics under RUNNER_TEMP so the existing Action upload step always finds them
  • render every stable public GitHub Release body in English, including evidence-bound manual input, while retaining bilingual text and evidence refs in the hidden Doc Agent payload
  • normalize a single GitHub URL source_refs value consistently with array inputs and tolerate evidence producers that omit either SHA alias

Root cause

The v2.0.18 dry-run covered all 9 required evidence groups, but the draft returned #10786401 for the real short SHA 10786401. Final postprocessing treated that value as an unknown PR number. The prior fix protected evidence generation, but not equivalent source-ref formats returned by the draft service.

Safety boundaries

A bare numeric #ref is repaired only when it exactly equals a short or full SHA already present in collected evidence; numeric prefixes are never coerced. Bare SHA values and explicit sha: wrappers may use a unique evidence prefix. Explicit commit wrappers and same-repository commit URLs are resolved as SHAs. Explicit PR wrappers and same-repository pull URLs are accepted only when that PR is present in evidence. Repository URLs are trusted only when they match GITHUB_REPOSITORY; absent repository context and foreign-repository URLs fail closed. Invented PRs, ambiguous SHA prefixes, invented refs, missing refs, and missing required commit coverage still stop the workflow.

Duplicate evidence commit rows are collapsed by full SHA before prefix matching. Only references that actually resolve to collected evidence increment normalized_evidence_backed_source_refs; unresolved and ambiguous references remain visible in diagnostics and fail validation.

Failure-diagnostic I/O or a non-serializable validation report can no longer replace the real release-note validation error; an artifact-write failure is still visible as a CI warning. By default the files are now written under $RUNNER_TEMP/memos-local-plugin-release-notes-failure, matching the workflow upload path. { ok: true, needs_review: true } is explicitly tested and rejected.

The public GitHub Release body is always re-rendered from validated text_en, including the manual-notes path. The hidden doc-agent-release-notes-json payload continues to carry text_cn, text_en, and source_refs, so the Chinese website output and the 106 evidence contract remain unchanged. Package-only prerelease notes were already English.

This PR changes only the MemOS local-plugin release-note caller and tests. It does not modify 106 Doc Agent, CLI, cloud-plugin, weekly release notifications, npm publication, tag creation, or Release creation.

Verification

  • targeted release-note tests: 57/57
  • complete release automation script tests: 186/186
  • real v2.0.18 evidence replay (memos-local-plugin-v2.0.17..bc9ccd1e): 35 path commits and 57 changed files compacted into 9 topics, 9/9 covered, 0 missing, 0 invalid; injected #10786401 normalized once; 7 final items
  • replayed public body contains no CJK text, while the hidden payload retains Chinese text for docs generation
  • manual stable input with a Chinese visible bullet is re-rendered to English after evidence validation; its hidden bilingual payload remains intact
  • explicit unknown PR, foreign/similarly-named repository URL, missing repository boundary, numeric/hex ambiguous SHA-prefix, duplicate commit rows, malformed-all-items, and unwritable-diagnostic tests remain fail-closed
  • exact evidence short-SHA aliases resolve even when supplied by a nonstandard evidence producer that does not make them a full-SHA prefix
  • fork/canonical repository commit and PR URLs are tested independently
  • final postprocess rejection produces a sanitized failure artifact at the exact workflow upload path and always preserves the original validation failure

@Memtensor-AI Memtensor-AI added area:core MOS 编排层 / 框架底座 / 跨模块问题 status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 31, 2026
@Memtensor-AI
Memtensor-AI requested a review from WeiminLee August 31, 2026 13:05
@Memtensor-AI

Memtensor-AI commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

🤖 Open Code Review

Target: PR #2312
Task: b296e0fcc79ca619
Base: main
Head: fix/local-plugin-numeric-sha-postprocess

🔍 OpenCodeReview found 5 issue(s) in this PR.

⚠️ 1 warning(s) occurred during review.


1. .github/scripts/draft-local-plugin-release-notes.test.mjs (L832)

source_refs is a bare string here, but every other fixture in this file passes an array. At line 840, [...acceptedPull.release_items[0].source_refs] will iterate over the string's individual characters rather than throwing — so the spread succeeds but the sort comparison will fail with characters, not URL segments. If the production code does not explicitly coerce strings to arrays, no URL validation occurs and this test passes for the wrong reason. Change to: source_refs: ["https://github.com/ForkOwner/ForkRepo/pull/1234"].

💡 Suggested Change

Before:

          source_refs: "https://github.com/ForkOwner/ForkRepo/pull/1234",

After:

          source_refs: ["https://github.com/ForkOwner/ForkRepo/pull/1234"],

2. .github/scripts/draft-local-plugin-release-notes.test.mjs (L980-L984)

The short_sha ("abcdef12") is not a prefix of sha ("12345678...") — that is intentional per the test's intent. However, the fixture submits source_refs: [commit.short_sha], which is an exact short_sha match. This means the test passes whether resolution checks sha.startsWith first or short_sha equality first. A complementary negative fixture (where short_sha does NOT match the ref but sha does start with it) is needed to confirm the resolution fallback order is actually exercised.


3. .github/scripts/draft-local-plugin-release-notes.test.mjs (L493-L507)

The boundary tested here is 7-char "#1234567" vs 8-char short_sha: "12345678". The more common LLM mis-format is an equal-length "#12345678" (8 chars matching the short SHA exactly). That equal-length case is the critical boundary for the stripping logic — if length is part of the guard condition, a "#12345678" ref would slip through untested. Add a dedicated fixture with source_refs: ["#12345678"] against short_sha: "12345678" to pin this boundary explicitly.


4. .github/scripts/draft-local-plugin-release-notes.mjs (L814-L823)

Silent data loss when two commits share the same short_sha with no sha field. Both map to identityRef = "short:<hash>". The else if condition shaEntriesByFullRef.get(identityRef)?.shortRef !== canonicalShortRef evaluates to false (shortRefs are identical), so the branch is skipped entirely — the second commit is silently dropped from shaEntries with no diagnostic. Any source_refs pointing to that SHA in a release item will become unresolvable, triggering a false-positive needs_review with no operator-visible explanation.

Recommendation: add a warning for the true-duplicate case (same key already set, same shortRef — i.e., the condition falls through both branches):

    } else {
      if (canonicalShortRef && identityRef) {
        warn(`Evidence contains a duplicate short SHA ${canonicalShortRef} (no full SHA); second occurrence ignored.`);
      }
    }

5. .github/scripts/draft-local-plugin-release-notes.mjs (L894-L896)

The entry.fullRef.startsWith(shaCandidate) prefix match can return multiple results if two evidence commits share a common SHA prefix (possible with short SHAs of 7–12 hex chars). In that case matches.length > 1, the ref goes into ambiguousShaRefs, and coverage validation fails with needs_review: true. Git guarantees uniqueness of abbreviations within a single repo at the moment of authoring, but the evidence payload is stored and replayed later — if the repo grows new commits with the same prefix, a previously valid release note will silently start failing validation.

The warning emitted at line 903 only records the original ref string, not which two full SHAs collided, making it hard for an operator to diagnose. Consider including the conflicting SHAs in the warning message:

} else if (matches.length > 1) {
  ambiguousShaRefs.add(ref);
  warn(`SHA candidate "${shaCandidate}" is ambiguous; matches: ${matches.map((e) => e.fullRef).join(", ")}`);
}

🧹 Filtered 1 low-confidence OCR finding(s) before posting/fix-loop (duplicate: 1).

Generated by cloud-assistant via Open Code Review.

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 1s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 31, 2026
@Memtensor-AI Memtensor-AI added status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Aug 31, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 1s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Aug 31, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 1s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 31, 2026
@Memtensor-AI Memtensor-AI added status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Aug 31, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 1s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added the status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 label Aug 31, 2026
@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 31, 2026
@Memtensor-AI Memtensor-AI added status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Aug 31, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 4s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 4s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 31, 2026
@Memtensor-AI Memtensor-AI added status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Sep 1, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 2s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Sep 1, 2026
@Memtensor-AI Memtensor-AI added status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Sep 1, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 2s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Sep 1, 2026
@Memtensor-AI Memtensor-AI added status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 and removed status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 labels Sep 1, 2026
@Memtensor-AI

Copy link
Copy Markdown
Collaborator

✅ Automated Test Results: PASSED

All tests passed (1/1 executed). memos_github_open_source/smoke: 1/1. Duration: 1s

Branch: fix/local-plugin-numeric-sha-postprocess

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Sep 1, 2026
@syzsunshine219
syzsunshine219 merged commit 28dfb4e into main Sep 1, 2026
18 checks passed
@syzsunshine219
syzsunshine219 deleted the fix/local-plugin-numeric-sha-postprocess branch September 1, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core MOS 编排层 / 框架底座 / 跨模块问题 status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants