TenantAtlas/specs/362-sync-capture-backup-operation-semantics/spec.md
ahmido 548a37c888 feat: implement sync capture backup operation semantics (#433)
Implemented sync capture backup operation semantics as requested.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #433
2026-06-07 01:19:08 +00:00

39 KiB

Feature Specification: Spec 362 - Sync, Capture, and Backup Operation Semantics

Feature Branch: 362-sync-capture-backup-operation-semantics
Created: 2026-06-07
Status: Draft
Type: OperationRun semantic hardening / operator-truth follow-through / no new persistence
Runtime posture: Extend the current OperationRun reconciliation path only for selected repo-real sync, capture, and backup run families. Reuse existing artifact or result truth. Do not introduce a new lifecycle table, queue family, or UI framework.
Input: User-provided draft in /Users/ahmeddarrazi/.codex/attachments/c6e1919f-3e04-4f47-b6a8-58c0fdc2ab82/pasted-text.txt plus repo inspection of Specs 358-361 and the current apps/platform runtime seams.

Dependencies And Historical Context

This package continues the current OperationRun truth line:

  • Spec 358 - OperationRun Queue Truth Foundation established honest queued/running stale handling and explicitly deferred business-success reconciliation for sync, capture, backup, restore, and export families.
  • Spec 359 - OperationRun Reconciliation Adapter Framework & Review Compose Adapter introduced one bounded adapter seam and review-compose-specific reconciliation while explicitly excluding report, evidence, sync, and backup adapters.
  • Spec 360 - OperationRun Canonical Cutover Cleanup remains the canonical cutover context for dispatch/correlation and read-side cleanup. Its artifacts are context only here and must not be rewritten.
  • Spec 361 - Report and Evidence Reconciliation Adapters added registry-backed reconciliation for tenant.evidence.snapshot.generate and environment.review_pack.generate while explicitly keeping sync, backup, and restore families out of scope.

Current repo truth already supports this next slice:

  • App\Support\Operations\Reconciliation\OperationRunReconciliationRegistry exists and already hosts multiple real adapters.
  • App\Support\OperationRunOutcome already contains partially_succeeded and blocked.
  • App\Services\Inventory\InventorySyncService already records canonical coverage and result context for inventory.sync.
  • App\Jobs\CaptureBaselineSnapshotJob and related baseline services already record baseline_snapshot_id, gap summaries, and summary counts for baseline.capture.
  • App\Jobs\RunBackupScheduleJob already records backup_schedule_id, backup_set_id, summary counts, and terminal backup outcomes for backup.schedule.execute.

This spec therefore continues an active repo-real line instead of inventing a new planning direction.

Spec Candidate Check (mandatory - SPEC-GATE-001)

  • Problem: Selected sync, capture, and backup run families still depend too heavily on technical completion or generic stale-run failure. When a job dies late, partially finishes, or never writes its final lifecycle update, operators can be left with a stale run that hides whether the system already captured usable truth, only partial truth, or a real blocked state.
  • Today's failure:
    • inventory.sync already persists coverage and error summaries, but stale or interrupted runs can still end as generic failed/stale truth instead of a truthful succeeded, partially succeeded, or blocked result backed by current coverage.
    • baseline.capture already records snapshot IDs, eligibility context, gap summaries, and summary counts, but the current reconciliation path does not promote those signals into a calm terminal outcome when the run itself becomes ambiguous.
    • backup.schedule.execute already records schedule context, backup-set context, and terminal counters in the normal job path, but the stale-run reconciliation path still lacks a proof-based backup-specific truth contract.
  • User-visible improvement: Operators can trust that the Operations hub and run detail pages say what actually happened for the selected families:
    • Succeeded only when completeness is proven.
    • Partially succeeded when usable output exists but some work failed or gaps remain.
    • Blocked when configuration, eligibility, or capability truth prevented a meaningful run.
    • Failed when no safe success or partial proof exists.
  • Smallest enterprise-capable version:
    • add bounded reconciliation for exactly three canonical families:
      • inventory.sync
      • baseline.capture
      • backup.schedule.execute
    • extend the existing reconciliation-result contract to express partially_succeeded using the existing OperationRunOutcome enum
    • reuse only current repo-real proof paths and current operations/detail surfaces
    • keep policy.sync, backup_set.update, restore, and generic report families out of scope
  • Explicit non-goals:
    • no new OperationRun status or outcome family
    • no new table, artifact, queue family, or background worker contract
    • no policy.sync direct adapter in this slice
    • no restore, review-compose, evidence-snapshot, or review-pack expansion
    • no provider/onboarding redesign
    • no dashboard or product-wide operations UX rewrite
    • no customer portal or AI follow-through
  • Permanent complexity imported: three bounded adapters, one bounded partial-success helper on the current reconciliation result if needed, focused Unit/Feature coverage, and one bounded Browser smoke. No new persistence, global framework, or semantic taxonomy is introduced.
  • Why now: Specs 358, 359, and 361 explicitly deferred sync/capture/backup business semantics. The current runtime now exposes the registry, proof, and outcome seams needed to finish the next narrow slice without inventing new platform machinery.
  • Why not local: A local fix in one job or one page would keep outcome truth inconsistent across the registry, scheduled reconciliation, notifications, and current operations surfaces. This must be expressed once in the canonical reconciliation path.
  • Approval class: Core Enterprise.
  • Red flags triggered: cross-surface monitoring truth and bounded adapter growth. Defense: scope stays on three existing families, uses existing OperationRunOutcome values, forbids new persistence, and explicitly keeps weaker families fail-closed.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | Gesamt: 11/12
  • Decision: approve.

Candidate Source And Completed-Spec Guardrail

  • Candidate source:
    • direct user-provided Spec 362 draft in pasted-text.txt
    • repo-real follow-through after Specs 358, 359, and 361
    • roadmap relationship: execution-truth maturity over the existing OperationRun line, especially before broader counted-progress or fan-out UX expansion
  • Queue boundary: docs/product/spec-candidates.md still marks the active queue as empty for auto-selection. This package is an intentional manual promotion from direct user input, not an automatic queue pick.
  • Completed-spec check result:
    • no specs/362-* package existed before this prep
    • Specs 358, 359, and 361 are treated as historical implementation context
    • Spec 360 remains dependency context only; its package must not be rewritten or normalized here
    • earlier manual-promotion product lanes such as Specs 264, 267, 274-277, 339, 341, 342, and 346 are already specced and therefore excluded from next-best-prep selection
  • Close alternatives deferred:
    • First Governed AI Runtime Consumer v1 remains unspecced but is later-stage productization and less directly enabled by the current branch/runtime line
    • policy.sync direct reconciliation is deferred because current repo proof is weaker than inventory.sync
    • broader counted-progress, phase, or activity-center work remains separate from terminal-outcome truth
  • Smallest viable implementation slice: selected repo-real proof for inventory.sync, baseline.capture, and backup.schedule.execute only, plus calm operations-surface fallout and explicit unsupported-family handling.

Summary

This feature makes selected sync, capture, and backup runs honest when technical lifecycle and business truth drift apart.

It does not claim that every long-running job can now auto-complete. It only allows current repo-backed proof to finalize selected families:

  • inventory.sync from coverage and result truth
  • baseline.capture from snapshot and gap truth
  • backup.schedule.execute from backup-set and backup-summary truth

Where proof is incomplete or ambiguous, the feature must fail closed as partially_succeeded, blocked, failed, or not_reconciled instead of pretending success.

Roadmap Relationship

This slice belongs to the execution-truth line rather than the customer-review or productization backlog.

It sharpens terminal outcome semantics before any broader rollout of counted progress, fan-out progress, or calmer activity-center UX:

  • it complements the repo's current progress and activity-truth candidate line
  • it keeps terminal outcome semantics separate from progress semantics
  • it avoids turning backup or sync product surfaces into false green states just because some artifact exists

Spec Scope Fields (mandatory)

  • Scope: canonical-view plus environment-bound execution truth
  • Primary Routes:
    • /admin/workspaces/{workspace}/operations
    • /admin/workspaces/{workspace}/operations/{run}
    • current repo-real related detail surfaces only when a safe link already exists:
      • inventory coverage and inventory-related detail routes
      • baseline profile, baseline snapshot, and current baseline-related detail routes
      • backup schedule, backup set, and backup-item detail routes
  • Data Ownership:
    • operation_runs remain the only execution and reconciliation truth
    • inventory_items.last_seen_operation_run_id and context.inventory.coverage remain inventory observation proof
    • baseline_snapshots, policy-version evidence, and context.baseline_capture.* remain baseline capture proof
    • backup_sets, backup_items, and context.backup_schedule_id / context.backup_set_id remain backup proof
    • no new persistence is introduced
  • RBAC:
    • existing workspace-first OperationRun access remains authoritative
    • existing inventory, baseline, and backup detail/resource policies remain authoritative
    • non-members and out-of-scope actors remain 404
    • no new capability strings are introduced

For canonical-view specs:

  • Default filter behavior when tenant-context is active: the Operations hub remains workspace-scoped with explicit environment filters only; reconciliation must rely on the run's recorded scope, not remembered environment state or current page filters.
  • Explicit entitlement checks preventing cross-tenant leakage: no adapter may reconcile to inventory, snapshot, or backup artifacts outside the run's workspace and managed environment, and no related-artifact link may bypass current scope-safe routes.

UI Surface Impact (mandatory - UI-COV-001)

  • No UI surface impact
  • Existing page changed
  • New page/route added
  • Navigation changed
  • Filament panel/provider surface changed
  • New modal/drawer/wizard/action added
  • New table/form/state added
  • Customer-facing surface changed
  • Dangerous action changed
  • Status/evidence/review presentation changed
  • Workspace/environment context presentation changed

UI/Productization Coverage (mandatory when UI Surface Impact is not "No UI surface impact")

  • Route/page/surface:
    • App\Filament\Pages\Monitoring\Operations
    • App\Filament\Pages\Operations\TenantlessOperationRunViewer
    • current repo-real inventory, baseline, and backup detail surfaces only if outcome copy or related links change there
  • Current or new page archetype: existing monitoring/detail family plus current artifact/detail families
  • Design depth: Domain Pattern Surface
  • Repo-truth level: repo-verified
  • Existing pattern reused: current OperationRun monitoring family, current related-artifact links, current inventory/baseline/backup detail families
  • New pattern required: none; this is a truthful-outcome follow-through inside current families
  • Screenshot required: no by default; one bounded Browser smoke is sufficient unless implementation proves a material first-screen hierarchy change
  • Page audit required: no new page-report identity is required by default
  • Customer-safe review required: no; touched copy remains operator-facing and diagnostic
  • Dangerous-action review required: no; no new mutation surface is added
  • Coverage files updated or explicitly not needed:
    • docs/ui-ux-enterprise-audit/route-inventory.md
    • docs/ui-ux-enterprise-audit/design-coverage-matrix.md
    • docs/ui-ux-enterprise-audit/page-reports/...
    • docs/ui-ux-enterprise-audit/strategic-surfaces.md
    • docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md
    • docs/ui-ux-enterprise-audit/unresolved-pages.md
    • N/A - existing operations, inventory, baseline, and backup surface families already cover the reachable routes
  • No-impact rationale when applicable: no new page family, navigation entry, or route family is added; the feature only adjusts terminal truth within current surfaces

Cross-Cutting / Shared Pattern Reuse (mandatory)

  • Cross-cutting feature?: yes
  • Interaction class(es): status messaging, action links, monitoring/detail explanation, related-artifact linkage
  • Systems touched:
    • App\Services\OperationRunService
    • App\Services\Operations\OperationLifecycleReconciler
    • App\Services\AdapterRunReconciler
    • App\Support\Operations\Reconciliation\OperationRunReconciliationRegistry
    • App\Support\Operations\Reconciliation\ReconciliationResult
    • App\Support\OperationRunLinks
    • App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter
    • current inventory, baseline, and backup proof helpers
  • Existing pattern(s) to extend: current registry-backed reconciliation, current service-owned lifecycle writes, current operations/detail presenters, and current scope-safe related-artifact links
  • Shared contract / presenter / builder / renderer to reuse: OperationRunService::applyReconciliationResult(), OperationRun::reconciliation(), OperationRunLinks, ArtifactTruthPresenter, GovernanceRunDiagnosticSummaryBuilder, and current inventory/baseline/backup detail presenters
  • Why the existing shared path is sufficient or insufficient: the registry and write seam already exist, but they do not yet cover selected sync/capture/backup proof families or partial-success finalization.
  • Allowed deviation and why: one small proof helper is allowed only if duplicated completeness checks across the three selected adapters become noisy. It must remain derived-only and local to App\Support\Operations\Reconciliation\.
  • Consistency impact: outcome wording, summary counts, related links, and supported/unsupported-family boundaries must stay consistent across jobs, reconciliation commands, monitoring/detail surfaces, notifications, and current detail pages.
  • Review focus: no second reconciliation write path, no generic "latest artifact exists" heuristics, no policy-sync widening, and no new persistence.

OperationRun UX Impact (mandatory)

  • Touches OperationRun start/completion/link UX?: yes
  • Shared OperationRun UX contract/layer reused: current OperationRunService, OperationLifecycleReconciler, registry-backed reconciliation, OperationRunLinks, and existing monitoring/detail presenters
  • Delegated start/completion UX behaviors: existing queued toasts, run links, terminal notifications, and run-enqueued browser events remain unchanged
  • Local surface-owned behavior that remains: wording and placement only
  • Queued DB-notification policy: unchanged
  • Terminal notification path: unchanged central lifecycle mechanism
  • Exception required?: none

Provider Boundary / Platform Core Check (mandatory)

  • Shared provider/platform boundary touched?: no new provider boundary is introduced
  • Boundary classification: platform-core execution truth over current provider-backed data
  • Seams affected: run lifecycle, current artifact/result truth, current scope-safe links
  • Neutral platform terms preserved or introduced: operation, reconciliation, coverage, snapshot, backup set, blocked, partially succeeded
  • Provider-specific semantics retained and why: only existing provider error codes or readiness reasons already recorded in current context remain visible secondarily
  • Why this does not deepen provider coupling accidentally: the feature uses platform-owned outcome and artifact/result truth only; it does not add provider-specific persistence, provider-routing rules, or Graph render calls
  • Follow-up path: policy.sync direct semantics, broader counted progress, and provider/onboarding guidance remain separate follow-ups

UI / Surface Guardrail Impact

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Operations hub selected run outcomes yes Native Filament + shared presenters OperationRun monitoring family page, detail, URL-query no no new action family
Run detail selected family explanation yes Native Filament + shared presenters OperationRun monitoring family detail no existing link model stays canonical
Inventory, baseline, and backup proof/detail surfaces yes Native Filament + shared detail helpers related artifact/detail families detail no only if outcome copy or links need alignment

Decision-First Surface Role

Surface Decision Role Human-in-the-loop Moment Immediately Visible for First Decision On-Demand Detail / Evidence Why This Is Primary or Why Not Workflow Alignment Attention-load Reduction
Operations hub Primary Decision Surface Decide whether the selected run still needs follow-up lifecycle, selected-family outcome, safe related proof, next action raw failures, deep proof detail, timestamps primary because operators clear run state from here stays aligned to monitoring workflow removes manual cross-checking across run and artifact pages
Run detail Secondary Context Surface Verify why the run ended as succeeded, partially succeeded, blocked, or failed one calm explanation plus safe related proof link full context payload and existing diagnostics secondary because the run is already selected stays aligned to detail workflow keeps proof in one canonical place
Inventory/baseline/backup detail Tertiary Evidence / Diagnostics Inspect the artifact or result that justified the run outcome current proof state full detail, payloads, counters, existing diagnostics tertiary because detail pages prove or explain the selected run stays aligned to current detail workflows avoids duplicating full proof truth in run rows

Audience-Aware Disclosure

Surface Audience Modes In Scope Decision-First Default-Visible Content Operator Diagnostics Support / Raw Evidence One Dominant Next Action Hidden / Gated By Default Duplicate-Truth Prevention
Operations hub operator-MSP, support-platform run status, selected-family outcome, safe reason, one next action counts, failure categories, timestamps after explicit reveal raw context remains diagnostic-only on current host surfaces Open operation or safe related proof link raw context and low-level provider detail list row states the outcome once; later sections add proof only
Run detail operator-MSP, support-platform calm outcome explanation and safe proof summary full reconciliation metadata and failures after explicit reveal raw payloads stay secondary and host-gated Open related proof when safe low-level payloads and support-only detail no second conflicting default-visible summary
Inventory/baseline/backup detail operator-MSP, support-platform current proof truth that supports or limits the outcome existing detail diagnostics after explicit reveal raw provider or payload detail remains behind existing gates Open related operation when safe payloads, fingerprints, and raw support context detail pages add proof; they do not restate a competing run summary

UI/UX Surface Classification

Surface Action Surface Class Surface Type Likely Next Operator Action Primary Inspect/Open Model Row Click Secondary Actions Placement Destructive Actions Placement Canonical Collection Route Canonical Detail Route Scope Signals Canonical Noun Critical Truth Visible by Default Exception Type / Justification
Operations hub Monitoring / Queue / Workbench Read-only Registry / Report Surface Open the run or its safe proof row click to run detail required existing filters and contextual links only unchanged /admin/workspaces/{workspace}/operations /admin/workspaces/{workspace}/operations/{run} workspace route plus explicit environment filter Operations / Operation honest selected-family outcome none
Run detail Record / Detail / Monitoring Diagnostics-first detail surface Inspect safe proof and deeper diagnostics canonical detail page N/A existing navigation and related links only unchanged /admin/workspaces/{workspace}/operations /admin/workspaces/{workspace}/operations/{run} run-owned workspace/environment scope Operation calm outcome plus proof summary none
Inventory/baseline/backup detail Record / Detail / Monitoring Detail-first proof surface Confirm whether the current proof really supports the outcome canonical detail page N/A existing related links only unchanged existing family collection routes existing family detail routes current workspace/environment scope on host surface Inventory / Baseline Snapshot / Backup Set current proof truth none

Operator Surface Contract

Surface Primary Persona Decision / Operator Action Supported Surface Type Primary Operator Question Default-visible Information Diagnostics-only Information Status Dimensions Used Mutation Scope Primary Actions Dangerous Actions
Operations hub MSP operator Decide whether the run still needs attention list/workbench Did this selected sync/capture/backup run finish successfully, partially, get blocked, or truly fail? lifecycle state, selected-family outcome, safe proof hint, next step raw failures, timestamps, detailed summary counts lifecycle, proof completeness, scope safety none existing inspect/open actions only none
Run detail MSP operator or support Confirm why the run resolved that way detail What exact proof or missing proof drove the final outcome? calm outcome explanation, proof summary, safe related link raw reconciliation context, low-level failure detail lifecycle, proof completeness, support state none open related proof when safe none
Inventory/baseline/backup detail MSP operator or support Confirm the supporting proof detail Does the current proof really justify or limit the selected run outcome? proof readiness, counts, gaps or failures summary payloads, fingerprints, deeper host diagnostics proof completeness, expiration or gaps, scope safety none open related operation when safe none

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: no
  • New persisted entity/table/artifact?: no
  • New abstraction?: yes, bounded adapters and possibly one small proof helper
  • New enum/state/reason family?: no; reuse the existing OperationRunOutcome::PartiallySucceeded and current blocked/failed semantics
  • New cross-domain UI framework/taxonomy?: no
  • Current operator problem: selected sync/capture/backup runs can remain stale or end with generic failure even when repo-real proof already shows success, partial success, or a blocked precondition.
  • Existing structure is insufficient because: the current registry covers restore, review-compose, evidence snapshot, and review-pack truth, but not the selected families that already emit usable proof through current context and artifact models.
  • Narrowest correct implementation: add exactly three bounded proof adapters plus a bounded partial-success helper if the current reconciliation result cannot express the existing enum value cleanly.
  • Ownership cost: adapter maintenance, focused tests, and some monitoring/detail copy review. No migration, new artifact family, or new operator workflow is introduced.
  • Alternative intentionally rejected: a generic "latest artifact exists" rule or a new lifecycle table was rejected because it would overclaim success, weaken scope safety, and import permanent complexity unrelated to the current release.
  • Release truth: current-release truth

Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, migration shims, historical fixture preservation, and compatibility-specific tests are out of scope unless explicitly required by the spec. Canonical current-release truth is preferred over preservation.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Unit, Feature, Browser
  • Validation lane(s): fast-feedback, confidence, browser
  • Why this classification and these lanes are sufficient: proof and decision logic are cheapest in Unit coverage; run finalization, scope-safe related links, and current-family fallout require Feature coverage; one bounded Browser smoke is enough for changed operator wording on the existing Operations surfaces
  • New or expanded test families: one explicit Spec 362 Unit/Feature family and one bounded Browser smoke
  • Fixture / helper cost impact: moderate existing factory usage for OperationRun, InventoryItem, BaselineSnapshot, BackupSet, BackupItem, and workspace/environment membership; no new expensive default fixtures should be introduced
  • Heavy-family visibility / justification: no heavy-governance family is added
  • Special surface test profile: monitoring-state-page
  • Standard-native relief or required special coverage: ordinary Feature coverage for existing Filament surfaces plus one bounded Browser smoke if visible copy changes
  • Reviewer handoff: reviewers must confirm that partial success only lands when current proof is genuinely incomplete but usable, that blocked remains distinct from failed, that unsupported families stay out of scope, and that no new persistence or operation type slips into the implementation
  • Budget / baseline / trend impact: none expected
  • Escalation needed: document-in-feature if a weaker family such as policy.sync still needs a named follow-up; reject-or-split if implementation tries to widen into generic sync or backup taxonomy work
  • Active feature PR close-out entry: Guardrail / Smoke Coverage
  • Planned validation commands:
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Unit/Support/Operations/Reconciliation/Spec362SelectedFamilyRegistryResolutionTest.php tests/Unit/Support/Operations/Reconciliation/Spec362SelectedFamilyProofRulesTest.php tests/Unit/Support/Operations/Reconciliation/Spec359ReconciliationResultTest.php tests/Feature/Operations/Spec362*
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Feature/MonitoringOperationsTest.php tests/Feature/Inventory/InventorySyncServiceTest.php tests/Feature/Inventory/RunInventorySyncJobTest.php tests/Feature/Baselines/BaselineCaptureTest.php tests/Feature/Baselines/BaselineCaptureGapClassificationTest.php tests/Feature/Baselines/BaselineCaptureAmbiguousMatchGapTest.php tests/Feature/BackupScheduling/RunBackupScheduleJobTest.php tests/Feature/Console/ReconcileBackupScheduleOperationRunsCommandTest.php
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec362SyncCaptureBackupSemanticsSmokeTest.php
    • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent

User Stories & Acceptance Scenarios

User Story 1 - Trust inventory sync outcomes (Priority: P1)

As an operator, I need inventory.sync runs to end with truthful terminal outcomes that match current coverage and error proof so I do not mistake a partial or blocked sync for a full success.

Independent Test: a queued/running/stale inventory.sync run finalizes to succeeded only when all attempted types are covered successfully, to partially succeeded when some types failed but usable coverage exists, and to blocked or failed when current repo proof shows a full precondition or execution failure.

Acceptance Scenarios:

  1. Given a stale inventory.sync run with current-scope coverage for every attempted type and no failure categories, When reconciliation evaluates it, Then the run ends completed/succeeded.
  2. Given a stale inventory.sync run with mixed coverage and recorded failed categories, When reconciliation evaluates it, Then the run ends completed/partially_succeeded.
  3. Given a stale inventory.sync run whose current proof shows only blocked or skipped execution reasons, When reconciliation evaluates it, Then the run ends completed/blocked.
  4. Given a stale inventory.sync run without trustworthy current-scope coverage or with wrong-scope evidence only, When reconciliation evaluates it, Then it must not auto-succeed.

User Story 2 - Trust baseline capture outcomes (Priority: P1)

As an operator, I need baseline.capture runs to distinguish complete capture, gap-limited capture, and blocked capture so baseline truth does not overclaim fidelity.

Independent Test: a queued/running/stale baseline.capture run finalizes to succeeded only when a current-scope snapshot exists with no capture gaps, to partially succeeded when a snapshot exists but capture gaps or fallback evidence remain, and to blocked or failed when no safe proof exists.

Acceptance Scenarios:

  1. Given a stale baseline.capture run with a current-scope baseline_snapshot_id and zero gap count, When reconciliation evaluates it, Then the run ends completed/succeeded.
  2. Given a stale baseline.capture run with a current-scope snapshot but recorded capture gaps or meta fallback, When reconciliation evaluates it, Then the run ends completed/partially_succeeded.
  3. Given a stale baseline.capture run whose current context still proves inventory or scope eligibility was blocked, When reconciliation evaluates it, Then the run ends completed/blocked.
  4. Given a stale baseline.capture run without a current-scope snapshot and without safe blocked proof, When reconciliation evaluates it, Then it must end failed or remain unreconciled instead of succeeding.

User Story 3 - Trust backup schedule execution outcomes (Priority: P1)

As an operator, I need backup.schedule.execute runs to distinguish complete backup, partial backup, and blocked backup from current backup-set proof so backup history stays honest.

Independent Test: a queued/running/stale backup.schedule.execute run finalizes to succeeded only when the current backup set proves complete capture, to partially succeeded when usable backup artifacts exist with recorded failures, and to blocked or failed when current schedule or backup proof shows no meaningful successful backup.

Acceptance Scenarios:

  1. Given a stale backup.schedule.execute run with a current-scope backup set and full successful counts, When reconciliation evaluates it, Then the run ends completed/succeeded.
  2. Given a stale backup.schedule.execute run with a backup set plus recorded failed families or missing assignment capture, When reconciliation evaluates it, Then the run ends completed/partially_succeeded.
  3. Given a stale backup.schedule.execute run whose current context proves the schedule was skipped or blocked before meaningful backup work, When reconciliation evaluates it, Then the run ends completed/blocked.
  4. Given a stale backup.schedule.execute run with no usable backup set or wrong-scope backup proof, When reconciliation evaluates it, Then it must not auto-succeed.

User Story 4 - Keep weaker families honest (Priority: P2)

As an operator, I need weaker or more ambiguous families such as policy.sync and backup_set.update to stay unsupported in this slice so the system does not overclaim semantics it cannot yet prove.

Independent Test: unsupported families remain out of the adapter registry and continue to follow the current lifecycle paths unless a future spec adds stronger causal proof.

Functional Requirements

  • FR-362-001: The reconciliation path MUST support only these canonical families in this slice:
    • inventory.sync
    • baseline.capture
    • backup.schedule.execute
  • FR-362-002: The feature MUST NOT add a new OperationRun outcome family. If partial success is needed, it MUST reuse OperationRunOutcome::PartiallySucceeded.
  • FR-362-003: inventory.sync may auto-finalize as succeeded only when current repo proof shows full current-scope coverage of attempted types without failure categories.
  • FR-362-004: inventory.sync may auto-finalize as partially succeeded only when current repo proof shows usable coverage plus explicit failed or gap-like categories for some attempted types.
  • FR-362-005: baseline.capture may auto-finalize as succeeded only when a current-scope baseline snapshot exists and the current gap summary proves no capture gaps remain.
  • FR-362-006: baseline.capture may auto-finalize as partially succeeded only when a current-scope snapshot exists but the current gap summary or fallback proof shows incomplete capture.
  • FR-362-007: backup.schedule.execute may auto-finalize as succeeded only when a current-scope backup set and its current summary counts prove complete backup work.
  • FR-362-008: backup.schedule.execute may auto-finalize as partially succeeded only when a current-scope backup set exists and the current summary counts or failure proof show usable but incomplete backup output.
  • FR-362-009: Selected families may auto-finalize as blocked only when current repo proof shows a meaningful precondition stop before successful work was produced, such as eligibility, capability, configuration, scope, or lock failure. If usable success or partial-success proof exists, succeeded or partially_succeeded MUST take precedence over blocked.
  • FR-362-010: Ambiguous, wrong-scope, or missing proof MUST fail closed as not_reconciled, blocked, or failed depending on what the current repo can safely prove. They MUST NOT become success.
  • FR-362-011: Selected-family reconciliation MUST continue to write lifecycle truth only through OperationRunService.
  • FR-362-012: Current operator-facing monitoring/detail surfaces MUST explain selected-family outcomes calmly and keep raw diagnostics secondary.
  • FR-362-013: policy.sync, backup_set.update, restore, review-compose, evidence snapshot, review-pack, and generic report families MUST remain unchanged in this slice unless current repo truth proves they are already covered elsewhere.

Non-Functional Requirements

  • NFR-362-001: No new schema, table, or persisted artifact may be introduced.
  • NFR-362-002: No new panel, provider registration, global-search contract, or Filament asset strategy may be introduced.
  • NFR-362-003: Reconciliation must stay scope-safe by workspace and managed environment and must not link to foreign artifacts.
  • NFR-362-004: No Graph or provider HTTP calls may be introduced during page render.
  • NFR-362-005: Tests must remain the narrowest honest proof: Unit plus Feature plus one bounded Browser smoke only if visible wording changes.

Edge Cases

  • Legacy alias values must not reintroduce provider-prefixed or legacy-named types as separate semantic families.
  • Current proof may exist but belong to a different workspace or environment; that case must fail closed.
  • Multiple candidate artifacts or result records for the same run must not silently choose a winner without safe deterministic proof.
  • partially_succeeded must remain a terminal outcome distinct from blocked and failed; the UI must not flatten them into one generic caution state.
  • Existing direct job completion paths remain authoritative. The new adapters must not double-finalize already completed runs.

Risks

  • A proof rule that is too permissive could overclaim success for incomplete backup or baseline output.
  • A proof rule that is too strict could keep obviously completed runs stuck in generic failure or attention states.
  • Selected-family proof may duplicate some existing job-local decisions if the adapter boundaries are not kept narrow.

Assumptions

  1. The current registry and correlation seams visible in platform-dev are authoritative enough for a bounded follow-through even though Spec 360 artifacts still exist as context.
  2. inventory.sync, baseline.capture, and backup.schedule.execute remain the strongest current proof families among the sync/capture/backup line.
  3. policy.sync still lacks a safe proof contract equal to inventory.sync, so it is intentionally excluded from the first slice.

Open Questions

No open question blocks preparation.

Implementation must still verify whether any remaining Spec 360 cutover delta is required for these adapters. If runtime inspection proves a missing canonical seam is still blocking, implementation must stop and split that prerequisite explicitly instead of widening Spec 362 silently.

Success Criteria

  • Selected-family stale or interrupted runs no longer overclaim success or collapse into generic stale failure when stronger current proof exists.
  • Operators can distinguish complete, partial, blocked, and failed outcomes on current operations surfaces without reading raw diagnostics first.
  • Unsupported families remain explicit and fail-closed instead of silently drifting into heuristic success.

Acceptance Criteria

  • AC-362-001: inventory.sync, baseline.capture, and backup.schedule.execute each have a bounded proof-based reconciliation path.
  • AC-362-002: Partial success uses the existing OperationRunOutcome::PartiallySucceeded instead of a new outcome family.
  • AC-362-003: policy.sync, backup_set.update, restore, and generic report families remain out of scope and explicit.
  • AC-362-004: Existing operations/detail surfaces show calm, scope-safe outcome wording with diagnostics secondary.
  • AC-362-005: Focused Unit, Feature, and bounded Browser coverage are defined in tasks.md and are sufficient to prove the slice.

Follow-Up Spec Candidates

  • policy.sync direct operator-truth semantics after a stable proof contract exists
  • broader counted-progress and fan-out semantics over the current execution-truth line
  • broader backup or restore outcome taxonomy only if current release truth proves that a shared family is needed