Skip to content

feat(migration): implement --drop-code-tokens DELETE pass - #212

Merged
jphein merged 1 commit into
mainfrom
feat/drop-code-tokens-delete
May 31, 2026
Merged

feat(migration): implement --drop-code-tokens DELETE pass#212
jphein merged 1 commit into
mainfrom
feat/drop-code-tokens-delete

Conversation

@jphein

@jphein jphein commented May 31, 2026

Copy link
Copy Markdown
Collaborator

What

Replaces the --drop-code-tokens stub in scripts/canonical_migration.py with a real targeted set-based DELETE of the code-token / shell-command / stopword RELATION edges — the predicates the canonical mapper drops to None (via mempalace.kg_predicate_norm: CODE_TOKEN_BLOCKLIST + SHELL_COMMAND_BLOCKLIST + STOPWORD_BLOCKLIST + the digit/code-look heuristic). These are content-free junk mis-extracted as relations (cd, ls, grep, can, for, …) carrying no entity→entity semantics — deletion, not remap, is the correct disposition. Closes the --drop-code-tokens: NOT YET IMPLEMENTED follow-up (#72b).

Expected affected rows on prod familiar: ~48,135 edges (335 distinct predicates) — exactly the figure the dry-run already reports as code tokens (NOT touched unless --drop-code-tokens).

DELETE mechanism

Targeted, not a remap-plan piggyback. The drop set is computed once during build_plan (plan["drops"]) — the same set counted as dropped_edges, so the deleted rows are byte-for-byte what the dry-run reports (no second definition of "junk" that could drift from the headline number). _drop_code_tokens() then:

  1. CREATE TEMP TABLE drop_predicate + COPY the blocklisted raws into it.
  2. One DELETE ... USING drop_predicate d WHERE coalesce((props)->>'raw_relation_type', (props)->>'relation_type') = d.raw.

Keying on the coalesced original predicate catches both never-migrated edges (junk in relation_type) and already-migrated ones (junk preserved in raw_relation_type). Runs without re-executing the ~11-min embedding remap plan. Idempotent — once deleted, a re-run matches 0 rows.

Gating

Same as the remap UPDATE: defaults to DRY-RUN (prints the count + a TOP CODE-TOKEN DROPS preview that would be deleted); the actual DELETE requires --apply and --i-have-a-backup and a host-side --dsn/MEMPALACE_POSTGRES_DSN. Both gates verified to refuse (exit 1) without their precondition.

Unlike the remap UPDATE (relabel, reversible via raw_relation_type), this DELETE is irreversible — that's why it stays opt-in behind the backup gate. Reachable standalone: --drop-code-tokens still hits the DELETE even when there are no remaps (graph already canonical).

Tests

+7 in tests/test_canonical_migration.py (mirrors the existing mocked-psycopg style):

  • drop-set capture invariant (sum(drops) == dropped_edges)
  • DELETE SQL shape + COPY rows (TEMP table, coalesce key, is-a-DELETE-not-UPDATE)
  • no-op when drop set empty (never opens a connection)
  • runs after remap; runs standalone when no remaps; absent without the flag
  • a real-CanonicalMapper (lexical, no model) integration test asserting the drop set matches SHELL_COMMAND_BLOCKLIST/STOPWORD_BLOCKLIST and excludes real relations

25/25 pass; ruff check clean.

Note: 2 pre-existing failures in tests/test_kg_predicate_norm.py (mergedadds, isnt_aNone) are unrelated drift between the daemon test fixtures and the newer mempalace.kg_predicate_norm — they fail identically on clean main with this branch's changes stashed.

🤖 Generated with Claude Code

Replace the --drop-code-tokens stub in canonical_migration.py with a real
targeted set-based DELETE of the code-token / shell-command / stopword RELATION
edges (the predicates CanonicalMapper.map_predicate drops to None via
mempalace.kg_predicate_norm: CODE_TOKEN_BLOCKLIST + SHELL_COMMAND_BLOCKLIST +
STOPWORD_BLOCKLIST + digit/code-look heuristic).

- build_plan now captures the dropped raws into plan["drops"] (full) and
  plan["top_drops"] (preview) — the SAME set it counts as dropped_edges, so the
  deleted rows are byte-for-byte what the dry-run reports (no drift between a
  second "junk" definition and the headline number).
- _drop_code_tokens() runs a TEMP drop_predicate table (COPY of blocklisted
  raws) + a single DELETE keyed on coalesce(raw_relation_type, relation_type),
  catching both never-migrated edges (junk in relation_type) and already-
  migrated ones (junk preserved in raw_relation_type). Runs WITHOUT re-executing
  the ~11-min embedding remap plan; idempotent (re-run deletes 0).
- Reachable standalone: --drop-code-tokens still hits the DELETE even when there
  are no remaps (graph already canonical). Same --apply + --i-have-a-backup
  gating as the remap UPDATE; unlike that UPDATE this is irreversible, hence
  opt-in behind the backup gate.
- Dry-run now prints a TOP CODE-TOKEN DROPS section; --json keeps top_drops but
  excludes the full drops list (as it already did for remaps).

Tests: +7 in test_canonical_migration.py (drop-set capture invariant, DELETE
SQL shape + COPY rows, no-op-when-empty, runs-after-remap, standalone-no-remaps,
absent-without-flag, and a real-CanonicalMapper integration test asserting the
drop set matches the blocklists). 25/25 pass; ruff check clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 31, 2026 17:16
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new capability to the canonical migration script, allowing for the permanent deletion of 'junk' predicates from the knowledge graph. These predicates, identified as content-free code tokens, shell commands, or stopwords, are now explicitly removed via a robust, idempotent, and safely-gated database operation. This enhancement improves data quality by eliminating irrelevant edges and ensures consistency with the dry-run reports by deleting exactly what was identified as droppable.

Highlights

  • New Feature: --drop-code-tokens: Implemented a new command-line option --drop-code-tokens in scripts/canonical_migration.py to enable the targeted deletion of 'junk' relation edges (code tokens, shell commands, stopwords) from the knowledge graph.
  • Targeted Set-Based DELETE Mechanism: The deletion process utilizes a robust, targeted set-based DELETE operation. It involves creating a temporary table (drop_predicate), populating it with blocklisted raw predicates, and then executing a single DELETE statement that uses COALESCE to match both never-migrated (relation_type) and already-migrated (raw_relation_type) junk predicates.
  • Safety Gating and Irreversibility: The --drop-code-tokens feature is protected by strict gating, requiring --apply, --i-have-a-backup, and a valid --dsn for execution. Unlike remapping, this deletion is irreversible, emphasizing the need for these safety measures.
  • Independent Execution and Idempotency: The deletion pass can run independently of the main remap plan, even when no remapping is required, and does not re-execute the potentially long-running embedding remap plan. The operation is idempotent, meaning re-running it after deletion will result in zero rows matched.
  • Comprehensive Testing: Added extensive unit and integration tests in tests/test_canonical_migration.py to verify the correct capture of dropped predicates, the generated SQL for deletion, the interaction with the _apply function under various conditions, and the integration with the CanonicalMapper to ensure accurate identification of blocklisted predicates.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the --drop-code-tokens option in the canonical migration script, enabling the deletion of blocklisted junk-predicate edges (such as shell commands and stopwords) from the database. It introduces the _drop_code_tokens function to perform a targeted set-based DELETE using a temporary table, updates the plan generation and display logic, and adds comprehensive unit and integration tests. The reviewer suggested optimizing the DELETE query by using a LATERAL join to avoid casting and parsing the properties column to JSONB twice per row, which will improve performance on large tables.

Comment on lines +520 to +528
cur.execute(
"""
DELETE FROM mempalace_kg."RELATION" e
USING drop_predicate d
WHERE COALESCE(
(e.properties::text::jsonb)->>'raw_relation_type',
(e.properties::text::jsonb)->>'relation_type') = d.raw
"""
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Evaluating (e.properties::text::jsonb) twice per row in the COALESCE expression can be highly CPU-intensive, especially during a full table scan on a large table like RELATION (e.g., 1.76M rows).

Using a LATERAL join allows PostgreSQL to cast and parse the properties field to jsonb exactly once per row, which can significantly improve the performance of this bulk DELETE operation.

            cur.execute(
                """
                DELETE FROM mempalace_kg."RELATION" e
                USING drop_predicate d,
                      LATERAL (SELECT e.properties::text::jsonb AS j) p
                WHERE COALESCE(p.j->>'raw_relation_type', p.j->>'relation_type') = d.raw
                """
            )

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@jphein
jphein merged commit 80f47bd into main May 31, 2026
1 check failed
@jphein
jphein deleted the feat/drop-code-tokens-delete branch May 31, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants