feat(unic-spec-review): dedup + cancellable Approval Loop#237
Merged
orioltf merged 8 commits intoJun 9, 2026
Merged
Conversation
The --post path had no deduplication and could only post one Finding, so reruns and other reviewers' runs silently piled up duplicate comments. Changes: - Add scripts/lib/dedup-matcher.mjs: pure Jaccard word-token similarity matcher comparing a Finding against all existing page comments; returns a post/skip/flag decision plus near-duplicates. No hidden marker, no local state (reads the shared page, so multi-user/multi-run safe). - Add --comments <url> CLI mode to atlassian-fetch (collectComments, parseCommentsArg) mirroring the never-throws collectChildPages pattern. - Replace review-spec.md Step 10 with a multi-Finding Approval Loop: annotated ranked list, comma-separated selection, human tiebreak on flagged/skip matches, cancellable at every step incl. post-none exit. - Add tests/dedup-matcher.test.mjs covering tokenize/jaccard/matchDedup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote [Unreleased] dedup + Approval Loop entries to 0.1.7 and sync the version into marketplace.json and package.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e-unic-spec-review-208-dedup-approval-loop
The PR-merge CI build fails Prettier on this docs file (added to develop in 4674275): it uses *asterisk* emphasis where Prettier expects _underscore_. Normalise it so root checks pass. Docs-only, no semantic change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixed: - README.md/CONTEXT.md/AGENTS.md: update S5→S8 status blocks (multi-Finding loop + dedup now implemented, not deferred) - atlassian-fetch.mjs: CommentsOutput.truncated JSDoc missing trailing clause; parseCommentsArg JSDoc missing empty-value null case - dedup-matcher.mjs: remove unreachable `union===0` guard; split ambiguous try/catch to name failing file - tests/dedup-matcher.test.mjs: fix Jaccard comment notation (single-letter→two-letter to match code); add null/undefined tests for tokenize defensive guard; add null-array test for matchDedup - tests/atlassian-fetch.test.mjs: add collectComments (3 cases) and parseCommentsArg (3 cases) tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Member
Author
⚡ Self-Fix Report (Aggressive)Status: COMPLETE Fixes Applied (12 total)
View all fixes
Tests Added
Skipped (1)
Suggested Follow-up Issues(none — all actionable findings addressed) Validation✅ Type check | ✅ Lint | ✅ Tests (301 passed) Self-fix by Archon · aggressive mode · fixes pushed to |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6 tasks
Issue #208 forbids em dashes in authored text (the CHANGELOG version header is the only sanctioned exception). The S8 status-line rewrites in README.md and AGENTS.md introduced em dashes; replace them with a colon separator so the authored prose complies. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR #237 review follow-ups: - Guard matchDedup against a Finding whose title/body is null/undefined so candidate text never tokenizes the literal "undefined". - Add deterministic threshold-boundary tests pinning the exact Jaccard scores at and just below FLAG_THRESHOLD and SKIP_THRESHOLD (the prior prose fixtures sat far from the boundaries, so a >= to > drift or a constant change went undetected), plus null-field and credential-load exception coverage for collectComments. - Correct the CommentsOutput.truncated JSDoc to name the comment-list pagination cap (MAX_PAGES) rather than a page-count cap, and document that the dedup-matcher CLI accepts a bare ConfluenceComment[] array. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7 tasks
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.
What
Closes the
unic-spec-reviewposting path (S8) with content-similarity deduplication and a fully cancellable multi-Finding Approval Loop. Resolves #208.Why
The
--postpath (S5) had no deduplication and could post only one Finding per run, so reruns — by the same reviewer or anyone else — silently piled up duplicate comments on a page. There was no safeguard against re-raising an issue someone already commented on.How
scripts/lib/dedup-matcher.mjs(new pure library):matchDedup(finding, existingComments)computes Jaccard word-token similarity between a Finding (title + body) and every existing page comment, returning apost/skip/flagdecision plus near-duplicate candidates sorted by similarity. No hidden marker and no local state file — it reads the shared page, so it is multi-user and multi-run safe by construction (ADR-0002). Exportstokenize/jaccardhelpers andSKIP_THRESHOLD/FLAG_THRESHOLDconstants, plus a--findings-file/--comments-fileCLI mode for command integration.scripts/atlassian-fetch.mjs: adds a--comments <url>CLI mode wrappingfetchConfluenceCommentsin the same never-throwscollectCommentspattern as--child-pages.commands/review-spec.mdStep 10: replaced the single-Finding picker with a multi-Finding Approval Loop — fetch existing comments → run dedup-matcher → present a ranked list annotated with[~near-dup]/[~likely-dup]badges → comma-separated selection → explicit human tiebreak on flagged/skip matches (never silently dropped or re-raised) → post approved Findings via the S7 write path with anchors + attribution footers. Cancellable at every step, including a post-none exit after selection. Bare/review-specstays strictly read-only.tests/dedup-matcher.test.mjs: 22node:testcases coveringtokenize,jaccard, andmatchDedupwith injected comment sets; no live services. The Approval Loop driver (markdown instructions) is not unit-tested by design.Validation
pnpm --filter unic-spec-review typecheck— ✅pnpm --filter unic-spec-review test— ✅ 292 passed (22 new)pnpm --filter unic-spec-review verify:changelog— ✅ → 0.1.7pnpm ci:check— ✅🤖 Generated with Claude Code