Skip to content

fix(cache): only ALLOW may advance safe-prefix cache - #117

Open
chirag-gamer wants to merge 1 commit into
UnplugAI:devfrom
chirag-gamer:fix/safe-prefix-nonallow-cache
Open

fix(cache): only ALLOW may advance safe-prefix cache#117
chirag-gamer wants to merge 1 commit into
UnplugAI:devfrom
chirag-gamer:fix/safe-prefix-nonallow-cache

Conversation

@chirag-gamer

Copy link
Copy Markdown

Summary

Fixes #116

ScanCache.should_advance_prefix() returned True for Action.REDACT (when advance_prefix_on_redact=True, the default) and unconditionally for Action.REVIEW. A safe-prefix entry is documented as a verified-clean prefix, but REDACT and REVIEW are non-ALLOW findings. A later append-only scan of the same document_id could then scan only the tail/overlap and return ALLOW, omitting the earlier flagged content.

Invariant enforced: A safe-prefix cache entry may be created only after Action.ALLOW.

Changes

File Change
sdk/src/unplug/core/runtime/cache.py should_advance_prefix() returns action == Action.ALLOW only
sdk/src/unplug/config/cache.py advance_prefix_on_redact marked deprecated=True via Pydantic Field
sdk/src/unplug/guard.py Fingerprint uses stable True constant; call passes advance_on_redact=False
sdk/tests/unit/core/runtime/test_cache.py 9 new regression tests

advance_prefix_on_redact handling

The config field is deprecated (Pydantic Field(deprecated=True)) and retained for signature compatibility. It has no effect — the cache now always requires ALLOW to advance. The cache policy fingerprint uses str(True) to preserve the same value, avoiding invalidation of existing cache entries.

Distinction from #82/#87

PR #87 fixed split-injection patterns across the cache boundary (256-char overlap + source/policy-scoped keys). This fix is about non-ALLOW results being treated as verified-clean prefixes, which is orthogonal to the boundary-overlap fix.

Checklist

  • The issue this closes was assigned to me (see CONTRIBUTING.md)
  • This is my only open PR, or my first PR has already been merged
  • Target branch is dev (see BRANCHING.md)
  • cd sdk && uv run ruff check . passes locally
  • cd sdk && uv run ruff format --check . passes locally
  • cd sdk && uv run pytest -q passes locally (1088 passed, 59 skipped, 0 failed)
  • New code has tests (9 regression tests in test_cache.py)
  • No secrets, internal URLs, or private paths in the diff

Test plan

  1. New regression tests (fail before fix, pass after):

    • TestShouldAdvancePrefix: ALLOW advances; BLOCK/REDACT/REVIEW/ABSTAIN do not
    • TestNonAllowPrefixNotCached: Guard-level tests using a controlled fake pipeline:
      • REDACT does not create safe-prefix entry
      • REVIEW does not create safe-prefix entry
      • ALLOW still creates safe-prefix entry
      • Append after REDACT re-scans full document (matches cache-disabled result)
  2. Existing tests preserved:

  3. Full suite: uv run pytest -q — 1088 passed, 59 skipped, 0 failed

Notes for reviewers

  • The advance_on_redact parameter on should_advance_prefix() is retained for signature compatibility but is now intentionally ignored. A future major version can remove it.
  • The cache policy fingerprint uses str(True) (matching the previous default) to avoid invalidating existing cache entries for users who had advance_prefix_on_redact=True (the default).

SafePrefixState is documented as a verified-clean prefix, but
should_advance_prefix() returned True for REDACT (when
advance_prefix_on_redact=True, the default) and unconditionally for
REVIEW.  A later append-only scan of the same document_id could then
scan only the tail/overlap and return ALLOW, omitting the earlier
flagged content from the resulting findings and redacted output.

Fix: should_advance_prefix() now returns True only for Action.ALLOW.
The advance_prefix_on_redact config field is deprecated (retained for
signature compatibility, no effect).  The cache policy fingerprint
keeps a stable value to avoid invalidating existing cache entries.

Regression tests:
- TestShouldAdvancePrefix: ALLOW advances; BLOCK/REDACT/REVIEW/ABSTAIN do not
- TestNonAllowPrefixNotCached: Guard-level tests using a controlled fake
  pipeline to verify REDACT and REVIEW do not create safe-prefix entries,
  and that appending after REDACT re-scans the full document
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown

Greptile Summary

The PR enforces that only an ALLOW result can create or advance a verified-clean safe prefix, preventing earlier REDACT or REVIEW findings from disappearing during append-only scans.

  • Deprecates the now-ignored advance_prefix_on_redact configuration field while retaining signature compatibility.
  • Stabilizes the cache-policy fingerprint and updates Guard’s cache advancement call.
  • Adds unit and Guard-level regression coverage for every action and the REDACT-then-append flow.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code defect remaining.

The new ALLOW-only advancement rule matches the verified-clean prefix invariant, Guard applies it consistently, and the regression tests cover both cache state and append-only rescanning behavior.

Important Files Changed

Filename Overview
sdk/src/unplug/core/runtime/cache.py Restricts safe-prefix advancement to ALLOW and documents that the compatibility parameter is intentionally ignored.
sdk/src/unplug/guard.py Uses the ALLOW-only cache policy and keeps the policy fingerprint stable for the deprecated default setting.
sdk/src/unplug/config/cache.py Marks the retained but behaviorally ignored cache option as deprecated through Pydantic metadata.
sdk/tests/unit/core/runtime/test_cache.py Adds action-level and Guard-level regressions proving non-ALLOW results do not create prefixes and appended documents are fully rescanned.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Scan full document] --> B{Result action}
  B -->|ALLOW| C[Store verified-clean safe prefix]
  B -->|REDACT, REVIEW, BLOCK, or ABSTAIN| D[Do not store safe prefix]
  C --> E[Later append-only scan]
  E --> F[Verify prefix and scan overlap plus suffix]
  D --> G[Later append-only scan]
  G --> H[Rescan full document]
Loading

Reviews (1): Last reviewed commit: "fix(cache): only ALLOW may advance safe-..." | Re-trigger Greptile

@chiruu12 chiruu12 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verified it reproduces with real scanners (first chunk needs to be over 256 chars so the finding sits outside the overlap window), and your branch fixes it. make check-ci green, 1093 passed.

One change: drop the str(True) line from the fingerprint instead of keeping a constant. ScanCache is in-memory dicts with no persistence, so an upgrade restarts the process and there are no entries to preserve. A value that never varies just misleads the next reader.

Rest looks good.

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.

Safe-prefix cache treats REDACT and REVIEW as verified clean

2 participants