feat(typescript): deduplicate scans through SDK and CLI - #661
Merged
kmbroai merged 20 commits intoAug 27, 2026
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This was referenced Aug 27, 2026
soyeon-oai
approved these changes
Aug 27, 2026
zcrab-oai
reviewed
Aug 27, 2026
zcrab-oai
left a comment
Collaborator
There was a problem hiding this comment.
One validated P1 repository-identity issue that breaks shared cross-runner deduplication.
* feat: publish custom findings and persist dedupe groups * refactor(test): translate write-back smoke assertions to TypeScript * test: align findings writeback with pair-only deduplication * test(plugin): include dedupe groups in schema expectations * test(plugin): update dedupe group migration snapshots * feat: persist resumable local findings workflows (#673) * feat: persist resumable local findings workflows * fix: store workflow metadata in explicit SQLite columns * test(plugin): align workflow helper and schema contracts * feat: checkpoint dedupe reviews and replay group writes (#674) * feat: checkpoint dedupe reviews and replay group writes * fix: keep workflow source snapshots within the checkout * fix: migrate dedupe checkpoint bindings to SQLite columns * test: retain required canonical ID in translated checkpoint checks * test: align checkpoint contracts with the updated findings stack * feat(server): add read-only findings dashboard (#679) * feat(server): add read-only findings dashboard * fix(dashboard): show workflows first * refactor(dashboard): simplify rendering and reuse workflow storage * fix(dashboard): preserve filters and completed result semantics * fix(dashboard): retain published repository identities in search * fix(dashboard): include deep scan activity in freshness * refactor(dashboard): use native selects and remove dropdown machinery * refactor(dashboard): show only stored findings and groups --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com> --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com> --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com>
kmbroai
added a commit
that referenced
this pull request
Aug 27, 2026
* feat(typescript): add findings service plumbing * feat(typescript): persist findings and embeddings through the service API * test(typescript): extract findings service Docker smoke runner * refactor(test): translate findings storage fixture to TypeScript * refactor(server): omit provisional bulk dedupe endpoint * docs: use canonical plugin source in findings import example * fix(plugin): support isolated findings helper execution * test(plugin): include findings storage in schema expectations * test(plugin): update findings migration snapshots * test: read findings smoke fixture from canonical plugin source * feat(typescript): deduplicate scans through SDK and CLI (#661) * feat(typescript): deduplicate stored findings with Codex * refactor(typescript): group server deduplication modules * refactor(typescript): run scan deduplication in SDK and CLI * feat(typescript): scope finding retrieval by repository * refactor(typescript): trim redundant deduplication code * fix(typescript): restore complete deduplication reviews * refactor(typescript): trim deduplication setup and smoke bookkeeping * perf(typescript): reduce deduplication review work * test(plugin): include repository associations in schema expectations * test(plugin): update repository migration snapshots * test: read scan smoke manifest from canonical plugin source * feat: publish custom findings and persist dedupe groups (#667) * feat: publish custom findings and persist dedupe groups * refactor(test): translate write-back smoke assertions to TypeScript * test: align findings writeback with pair-only deduplication * test(plugin): include dedupe groups in schema expectations * test(plugin): update dedupe group migration snapshots * feat: persist resumable local findings workflows (#673) * feat: persist resumable local findings workflows * fix: store workflow metadata in explicit SQLite columns * test(plugin): align workflow helper and schema contracts * feat: checkpoint dedupe reviews and replay group writes (#674) * feat: checkpoint dedupe reviews and replay group writes * fix: keep workflow source snapshots within the checkout * fix: migrate dedupe checkpoint bindings to SQLite columns * test: retain required canonical ID in translated checkpoint checks * test: align checkpoint contracts with the updated findings stack * feat(server): add read-only findings dashboard (#679) * feat(server): add read-only findings dashboard * fix(dashboard): show workflows first * refactor(dashboard): simplify rendering and reuse workflow storage * fix(dashboard): preserve filters and completed result semantics * fix(dashboard): retain published repository identities in search * fix(dashboard): include deep scan activity in freshness * refactor(dashboard): use native selects and remove dropdown machinery * refactor(dashboard): show only stored findings and groups --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com> --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com> --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com> --------- Co-authored-by: Kyle Brown <272643392+kmbroai@users.noreply.github.com> * feat(container): publish findings service and distribute workflow runner (#666) * feat(typescript): deduplicate stored findings with Codex * refactor(typescript): group server deduplication modules * refactor(typescript): run scan deduplication in SDK and CLI * feat(typescript): scope finding retrieval by repository * refactor(typescript): trim redundant deduplication code * fix(typescript): restore complete deduplication reviews * feat(container): publish findings service image to GHCR * feat: publish custom findings and persist dedupe groups * refactor(container): trim findings release verification * refactor(typescript): trim deduplication setup and smoke bookkeeping * feat(container): add scanner workflow runner Compose * refactor(test): translate write-back smoke assertions to TypeScript * refactor(test): translate runner smoke fixtures to TypeScript * perf(typescript): reduce deduplication review work * test: align findings writeback with pair-only deduplication * test(plugin): include repository associations in schema expectations * test(plugin): include dedupe groups in schema expectations * test(plugin): update repository migration snapshots * test(plugin): update dedupe group migration snapshots * test: read scan smoke manifest from canonical plugin source --------- Co-authored-by: Kyle Brown <272643392+kmbroai@users.noreply.github.com> --------- Co-authored-by: kmbroai <272643392+kmbroai@users.noreply.github.com>
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.
Summary
Part 3 of the findings service, stacked on #660. Keep storage, embeddings, and repository-scoped candidate retrieval in the HTTP service, and run the deduplication model pipeline locally through the SDK and CLI for a saved scan.
Changes
plugins/codex-security/scripts/; inherit the helper's isolated-import compatibility and generated-bundle packaging. Preserve the scoped import example and existing deduplication contracts.codex-security dedupe --scan SCAN_ID --findings-url URLand the public SDKdeduplicateScan(scanId, { findingsUrl }). Both CLI inputs are required, with no implicit scan or URL. Scan selection shares publish's full ID, unique prefix, andlatestbehavior and validates completed scan artifacts.scan.target.targetId. Add--all-repositories(defaultfalse) and the equivalent SDK optionallRepositories: truefor explicit broader searches.GET /v1/finding/{id}/potential-duplicates?repositoryId=ID, or?allRepositories=true. Return the complete stored anchor and up to 50 compatible candidates with cosine similarity >= 0.55, without vectors. Missing scope or conflicting scopes return 400; an anchor without a current embedding in the selected scope returnsfinding_not_indexed.FindingsStore.findPotentialDuplicates(findingId, scope). SQLite filters repository associations before reading IDs and compatible vectors, ranks them exactly, then loads complete records only for the anchor and selected candidates. One read transaction keeps those steps consistent. Replacing the store with an indexed implementation does not change the service or SDK/CLI.repositoryIdin bulk imports and persist associations atomically with findings and embeddings. Append a migration that backfills associations from scan history, and retain target associations during subsequent local scan indexing. Reimports add associations without removing existing ones.src/deduplication/, both atxhighreasoning effort. Each review receives the complete original findings in a fresh ephemeral Codex thread, without prior model rationales or merged findings.canonicalFindingIdand a generated, inclusivemergedFindingfor everySAMEdecision, including screening nominations. The shared schema makes both fields required and non-null forSAME; screening canonicals must belong to the nominated pair. Decisions must arrive directly throughreview_validator.submit_decisions, with corrections permitted in the same session. Reviews preserve observed severity and priority metadata without reassessment or normalization.Testing
Canonical plugin source update (
ff32fc8b)build:pluginandcheck:plugin-sourcepassed on this branch: 119 generated plugin files, includingworkbench_findings.py, and no tracked files undersdk/typescript/_bundled_plugin.12345and2093783242, each with 1,963 passed, 29 skipped, and zero failures.pnpm run types(including the canonical MCP app),pnpm run format, andgit diff --checkpassed.Deduplication optimization update (
1b82ccca)SAMEfields, independent original inputs, andxhighsettings.umask 022: seed12345and random seed3063214678each passed 1,926 tests, skipped 28, and failed zero across 101 files.pnpm run types,pnpm run format, andgit diff --check: passed.umask 002and failed 35 permission-sensitive fixture tests (1,891 passed, 28 skipped). Two affected legacy-resume cases passed withumask 022. Intermediate full runs were stopped after final review retained the existing self-pair rejection; final verification runs useumask 022.xhigh, no whole-group reviews, three-finding groups in both repository scopes, restart persistence, clean shutdown, and container/volume/network cleanup.Provisional endpoint cleanup (
c8341794)pnpm run types,pnpm run format, andgit diff --check: passed.TypeScript fixture update (
1fa8caf7)Earlier verification
10c9b650): 29 focused tests passed. The full SDK suite passed with seeds12345and3034098448(1,926 passed, 28 skipped, zero failures in each run). Types, formatting, and diff checks passed. The 346-entry npm archive and installed-package smoke passed, including SDK exports and NodeNext types; runtime modules are included and test fixtures are excluded. The packaged Docker smoke passed for candidate retrieval, all review stages, persistence, restart, and cleanup.pnpm run typesandpnpm run formatpassed.SAMEfields, canonical assignment boundaries, the renamed field, independence from earlier merged findings, direct namespace validation, correction, cancellation, and cleanup.review_validator.submit_decisionswith synthetic model responses and completeSAMEoutputs.12345and random seed2763826907each passed 1,925 tests, with 28 skips and zero failures on Linux. These earlier full-suite results predate the prompt and review-contract update.Risk and rollout
repositoryIdmatching the scan manifest'sscan.target.targetId; do not edit sealed scan artifacts. Untagged imports remain accepted but are available only to explicit all-repository retrieval unless they already have an association from scan history or are reimported with one. Repository IDs are exact identifiers, not inferred Git URLs.SAMEreview still requires its canonical finding ID and an inclusive merged finding for the assigned pair. No live quality evaluation or measured speedup is claimed for the changed reasoning effort.Public disclosure review