fix(review): Apply sees the file under every spelling and rechecks only its choice
Apply now finds the legacy rows of the same physical file however its root is reached. The roots are real paths while the monitor links under the directory it watches, so a symlinked or junctioned root, subst or a mapped drive used to hide the monitor's row and Apply added a second, differently linked row. Same-name rows are resolved to their physical identity (normcase(realpath), else samefile); the dependency fingerprint covers all of them, two rows refuse the choice, one row is enriched under the ingester's compatible-only rules, and a same-name row the request did not classify is a changed association. Apply re-verifies only what the decision depends on: the bytes are still ambiguous and still offer the chosen candidate. A resolver change that rewords the reason or reorders candidates leaves pending items applicable. The resolver version is one constant in prompt_pair_resolver, shared by ingestion provenance and Needs review. The transaction's byte check receives the re-hashed digest (or the body's for Leave unresolved), every Apply refusal branch is tested with zero writes, and the root listing and realpath calls run on a worker thread.
This commit is contained in:
@@ -39,6 +39,12 @@ from .pair_execution import ExecutionEvidenceError, read_pair_execution
|
||||
|
||||
_LOGGER = logging.getLogger("prompt_manager.prompt_pair_resolver")
|
||||
|
||||
# The ingestion resolver's version, recorded in pair-link provenance and on
|
||||
# Needs review items. Bump it when a change would resolve the same metadata
|
||||
# otherwise; a pending item stays applicable while its chosen candidate is
|
||||
# still offered by the captured bytes.
|
||||
RESOLVER_VERSION = 1
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class OutputAdapter:
|
||||
|
||||
@@ -31,18 +31,16 @@ try:
|
||||
from ..database.review_schema import MAX_CANDIDATES, canonical_evidence
|
||||
from .media_capture import CaptureCapacity, CaptureError
|
||||
from .prompt_inspector import MetadataReadError, read_inspection_file
|
||||
from .prompt_pair_resolver import resolve_prompt_pair
|
||||
from .prompt_pair_resolver import RESOLVER_VERSION, resolve_prompt_pair
|
||||
except ImportError: # imported with the repo root on sys.path
|
||||
from database.library_commands import LibraryCommandError
|
||||
from database.review_schema import MAX_CANDIDATES, canonical_evidence
|
||||
from utils.media_capture import CaptureCapacity, CaptureError
|
||||
from utils.prompt_inspector import MetadataReadError, read_inspection_file
|
||||
from utils.prompt_pair_resolver import resolve_prompt_pair
|
||||
from utils.prompt_pair_resolver import RESOLVER_VERSION, resolve_prompt_pair
|
||||
|
||||
logger = logging.getLogger("prompt_manager.review_capture")
|
||||
|
||||
# The ingestion resolver's provenance version (``database.pair_ingestion``).
|
||||
RESOLVER_VERSION = 1
|
||||
# Capture scope label: review captures are never handed to a client.
|
||||
REVIEW_SCOPE = "needs-review"
|
||||
# Nested ambiguous stages are flattened at most this deep.
|
||||
|
||||
Reference in New Issue
Block a user