@@ -277,7 +277,7 @@ def preview(
277277 attachment_manifest : Optional [list [dict ]] = None ,
278278 ) -> dict :
279279 policy = self ._policy (on_conflict )
280- vault , items = self ._preview_manifest (
280+ vault , items , manifest_complete = self ._preview_manifest (
281281 scan , workspace_id = workspace_id , repo_id = repo_id ,
282282 session_id = session_id , vault_id = vault_id , manifest = manifest ,
283283 scope = scope , memory_type = memory_type , strict_root = strict_root ,
@@ -286,11 +286,18 @@ def preview(
286286 plans , missing = self ._plan (
287287 scan , identity , items , inspect_memories = manifest is None ,
288288 )
289+ # A bounded manifest is enough to plan visible notes, but not enough to claim
290+ # that an unseen historical row was deleted. Match confirmed execution by
291+ # surfacing those rows as deferred rather than actionable ``missing`` items.
292+ pending_missing = missing if not manifest_complete else []
293+ if pending_missing :
294+ missing = []
289295 return self ._report (
290296 plans , missing , scan , state = "preview" , vault_id = (vault or {}).get ("id" ),
291297 workspace_id = workspace_id , repo_id = repo_id , session_id = session_id ,
292298 scope = scope , memory_type = memory_type , policy = policy ,
293299 vault_label = vault_label , attachment_manifest = attachment_manifest ,
300+ pending_missing = pending_missing , manifest_complete = manifest_complete ,
294301 )
295302
296303 def import_scan (
@@ -426,6 +433,7 @@ def import_scan(
426433 workspace_id = workspace_id , repo_id = repo_id , session_id = session_id ,
427434 scope = scope , memory_type = memory_type , policy = policy ,
428435 vault_label = vault_label , attachment_manifest = attachment_manifest ,
436+ manifest_complete = manifest_complete ,
429437 )
430438 if terminal_state == "completed" and report ["counts" ].get ("conflict" , 0 ):
431439 terminal_state = "partial"
@@ -476,7 +484,7 @@ def _preview_manifest(
476484 repo_id : Optional [str ], session_id : Optional [str ], vault_id : Optional [str ],
477485 scope : Scope , memory_type : MemoryType , manifest : Optional [dict ],
478486 strict_root : bool ,
479- ) -> tuple [Optional [dict ], list [dict ]]:
487+ ) -> tuple [Optional [dict ], list [dict ], bool ]:
480488 vaults = (
481489 list ((manifest or {}).get ("vaults" ) or [])
482490 if manifest is not None else self .store .list_source_vaults (kind = self .SOURCE_KIND )
@@ -486,6 +494,7 @@ def _preview_manifest(
486494 if manifest is not None else []
487495 )
488496 vault : Optional [dict ] = None
497+ manifest_complete = True
489498 if vault_id :
490499 vault = (
491500 self .store .get_source_vault (vault_id )
@@ -513,12 +522,12 @@ def _preview_manifest(
513522 if manifest is None :
514523 # Page the manifest like import_scan does so previews on manifests
515524 # larger than one list page plan against the full item set.
516- items , _ = self ._all_source_items (vault_id = str (vault ["id" ]))
525+ items , manifest_complete = self ._all_source_items (vault_id = str (vault ["id" ]))
517526 else :
518527 items = [row for row in items if row .get ("vault_id" ) == vault .get ("id" )]
519528 else :
520529 items = []
521- return vault , items
530+ return vault , items , manifest_complete
522531
523532 def _resolve_or_register_vault (
524533 self , scan : _ImportScan , * , workspace_id : str ,
@@ -1332,6 +1341,8 @@ def _report(
13321341 repo_id : Optional [str ], session_id : Optional [str ], scope : Scope ,
13331342 memory_type : MemoryType , policy : str , vault_label : str ,
13341343 attachment_manifest : Optional [list [dict ]],
1344+ pending_missing : Optional [list [dict ]] = None ,
1345+ manifest_complete : bool = True ,
13351346 ) -> dict :
13361347 files = [self ._preview_row (plan ) for plan in plans ]
13371348 files .extend ({
@@ -1346,11 +1357,16 @@ def _report(
13461357 "relative_path" : str (item .get ("relative_path" ) or "" ), "status" : "missing" ,
13471358 "action" : "missing" , "reason" : "source_not_seen" , "warnings" : [],
13481359 } for item in missing )
1360+ files .extend ({
1361+ "relative_path" : str (item .get ("relative_path" ) or "" ), "status" : "pending" ,
1362+ "action" : "pending" , "reason" : "missing_check_deferred" , "warnings" : [],
1363+ } for item in pending_missing or [])
13491364 return self ._report_payload (
13501365 files , scan , state = state , vault_id = vault_id ,
13511366 workspace_id = workspace_id , repo_id = repo_id , session_id = session_id ,
13521367 scope = scope , memory_type = memory_type , policy = policy ,
13531368 vault_label = vault_label , attachment_manifest = attachment_manifest ,
1369+ manifest_complete = manifest_complete ,
13541370 )
13551371
13561372 def _final_report (
@@ -1360,6 +1376,7 @@ def _final_report(
13601376 import_id : str , workspace_id : str , repo_id : Optional [str ],
13611377 session_id : Optional [str ], scope : Scope , memory_type : MemoryType ,
13621378 policy : str , vault_label : str , attachment_manifest : Optional [list [dict ]],
1379+ manifest_complete : bool = True ,
13631380 ) -> dict :
13641381 files = list (outcomes )
13651382 processed_paths = {
@@ -1396,6 +1413,7 @@ def _final_report(
13961413 workspace_id = workspace_id , repo_id = repo_id , session_id = session_id ,
13971414 scope = scope , memory_type = memory_type , policy = policy ,
13981415 vault_label = vault_label , attachment_manifest = attachment_manifest ,
1416+ manifest_complete = manifest_complete ,
13991417 )
14001418 report .update ({"job_id" : job_id , "import_id" : import_id })
14011419 return report
@@ -1423,6 +1441,7 @@ def _report_payload(
14231441 vault_id : Optional [str ], workspace_id : Optional [str ], repo_id : Optional [str ],
14241442 session_id : Optional [str ], scope : Scope , memory_type : MemoryType ,
14251443 policy : str , vault_label : str , attachment_manifest : Optional [list [dict ]],
1444+ manifest_complete : bool = True ,
14261445 ) -> dict :
14271446 counts : dict [str , int ] = {}
14281447 for row in files :
@@ -1440,6 +1459,7 @@ def _report_payload(
14401459 formats [name ] = formats .get (name , 0 ) + 1
14411460 return {
14421461 "state" : state , "status" : state , "vault_id" : vault_id ,
1462+ "manifest_complete" : bool (manifest_complete ),
14431463 "vault_label" : str (vault_label or "" )[:200 ],
14441464 "source_id" : vault_id ,
14451465 "source_label" : str (vault_label or "" )[:200 ],
0 commit comments