TenantAtlas/specs/270-operationrun-progress-contract/spec.md
Ahmed Darrazi 8fce9f0af1
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m44s
chore: commit workspace changes
2026-05-04 18:29:12 +02:00

30 KiB

Feature Specification: OperationRun Progress Contract v1

Feature Branch: 270-operationrun-progress-contract
Created: 2026-05-04
Status: Ready for implementation
Input: Manual promotion from docs/product/spec-candidates.md after repo-based duplicate verification excluded candidate 269 because specs/268-operationrun-activity-feedback/ already owns the terminal-success and terminal-follow-up shell slice.

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

  • Problem: OperationRun progress rendering is still decided ad hoc in the shell activity view and raw summary_counts conventions. The repo sanitizes numeric counts and normalizes lifecycle status, but it does not yet have one shared product contract that answers whether a run should show no progress, indeterminate activity, determinate counted progress, or a future phase/composite fallback.
  • Today's failure: BulkOperationProgress currently calculates progress inline from raw summary_counts, while other current or future surfaces can only see status, outcome, and flattened counters. That makes it too easy for a surface to invent fake percentages from status, duration, or outcome counters such as failed, succeeded, or skipped, and it leaves future OperationRun hosts without one truthful progress language.
  • User-visible improvement: Operators see one consistent, honest progress language across the covered Ops-UX surfaces: queued work and active work without trustworthy counts show activity only, active running work with trustworthy processed and total counts shows determinate progress, and terminal outcomes never masquerade as progress.
  • Smallest enterprise-capable version: introduce one shared Ops-UX progress contract or presenter over existing OperationRun truth, adopt it in the current shell activity feedback surface that already renders progress, and document the contract in the UI standards so later run hosts and later rollout specs extend the same rules instead of improvising them locally.
  • Explicit non-goals: no broad counted-progress rollout across run writers, no new OperationRun type or lifecycle, no dashboard redesign, no new queue or notification policy, no new summary_counts keys, no persistence for progress modes, no AI summaries, no customer-facing review changes, and no reopening of specs/268-operationrun-activity-feedback/ or specs/266-tenant-dashboard-productization-v1/ as the primary scope.
  • Permanent complexity imported: one bounded shared progress-semantics helper in App\Support\OpsUx, one derived progress-capability vocabulary (none, activity, counted, phased, composite) kept in code and docs only, focused unit plus feature coverage, and one UI standards update.
  • Why now: specs/268-operationrun-activity-feedback/ already captures shell terminal outcome semantics, which makes the remaining abstraction gap visible: progress meaning still lives inline in a Blade view. The candidate backlog explicitly sequences 270 ahead of 271 and 272, and the repo already contains the concrete seams needed to prepare this contract without inventing a new foundation.
  • Why not local: a local shell-only math cleanup would still leave future OperationRun surfaces, future counted rollouts, and future phase/composite work free to invent their own progress semantics from raw counters.
  • Approval class: Core Enterprise
  • Red flags triggered: new derived capability vocabulary, one shared Ops-UX presenter/contract seam, and one cross-surface truth contract. Defense: the vocabulary stays derived only, the contract is justified by multiple real consumers, and no new persistence or framework layer is introduced.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
  • Decision: approve

Spec Scope Fields (mandatory)

  • Scope: tenant + canonical-view
  • Primary Routes:
    • /admin/t/{tenant}/... tenant-scoped start surfaces that receive the shared shell activity hint
    • /admin/operations and /admin/operations/{run} remain the canonical operations collection/detail routes whose summaries must stay compatible with the shared progress contract even when this slice does not broaden their visible UI
    • /admin/t/{tenant} remains contextual-only for any existing recent-operation summary that already consumes the same Ops-UX family; no new dashboard card is introduced in this slice
  • Data Ownership: existing OperationRun.status, OperationRun.outcome, OperationRun.summary_counts, and OperationRun.context remain the only persisted truth. The progress contract is derived and must not introduce a new table, cache, mirror entity, or persisted progress mode.
  • RBAC: existing OperationRun policies remain authoritative. Out-of-scope tenants stay deny-as-not-found (404 semantics through the current tenant/admin boundaries), and in-scope actors only see progress states for runs they can already view.

Cross-Cutting / Shared Pattern Reuse (mandatory)

  • Cross-cutting feature?: yes
  • Interaction class(es): status messaging, activity feedback, progress disclosure, canonical run links, and execution-truth summaries
  • Systems touched: BulkOperationProgress, ActiveRuns, OperationRunService, SummaryCountsNormalizer, OperationSummaryKeys, OperationStatusNormalizer, OperationUxPresenter, current Ops-UX tests, and docs/ui/tenantpilot-enterprise-ui-standards.md
  • Existing pattern(s) to extend: current numeric-only summary_counts normalization, current lifecycle normalization, current active shell feedback surface, and the existing Ops-UX 3-surface contract
  • Shared contract / presenter / builder / renderer to reuse: App\Support\OpsUx\SummaryCountsNormalizer, App\Support\OpsUx\OperationSummaryKeys, App\Support\OpsUx\ActiveRuns, App\Support\OpsUx\OperationStatusNormalizer, App\Support\OpsUx\OperationUxPresenter, App\Services\OperationRunService, and apps/platform/resources/views/livewire/bulk-operation-progress.blade.php
  • Why the existing shared path is sufficient or insufficient: the repo already sanitizes allowed counters and normalizes lifecycle state, but none of those helpers currently decides whether a surface should show progress, what kind of progress is allowed, or when progress must collapse back to terminal outcome or simple activity.
  • Allowed deviation and why: none planned. The feature must remove shell-local progress inference instead of creating a second widget-local contract.
  • Consistency impact: Queued, In progress, Completed successfully, indeterminate activity labels, determinate progress labels, and the rule that outcome counters never substitute for processed must keep one meaning across covered Ops-UX surfaces and docs.
  • Review focus: reviewers must block any implementation that derives percentage from status, duration, stale-state heuristics, or outcome counters, or that leaves a second local progress calculator in Blade or Livewire code.

OperationRun UX Impact (mandatory)

  • Touches OperationRun start/completion/link UX?: yes
  • Shared OperationRun UX contract/layer reused: the existing Ops-UX start contract through OperationRunLinks, OperationRunUrl, ActiveRuns, OperationStatusNormalizer, and OperationUxPresenter, extended with one shared progress-semantics helper
  • Delegated start/completion UX behaviors: queued toasts, canonical View operation link generation, tenant-safe URL resolution, current run-enqueued browser events, and existing terminal database-notification behavior remain delegated to the current shared path and are unchanged in this slice
  • Local surface-owned behavior that remains: shell layout, copy density, and bounded host placement stay local to the existing shell surface; progress semantics no longer remain view-local
  • Queued DB-notification policy: N/A - unchanged
  • Terminal notification path: unchanged central lifecycle mechanism
  • Exception required?: none

Provider Boundary / Platform Core Check (mandatory)

  • Shared provider/platform boundary touched?: no
  • Boundary classification: N/A
  • Seams affected: N/A
  • Neutral platform terms preserved or introduced: Operation, activity, progress, counted progress, terminal outcome
  • Provider-specific semantics retained and why: none
  • Why this does not deepen provider coupling accidentally: the feature only formalizes progress semantics over existing platform-owned OperationRun truth
  • Follow-up path: none

UI / Surface Guardrail Impact (mandatory)

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Tenant shell activity hint progress treatment yes Native Filament + existing Livewire/Blade surface Ops UX activity feedback, execution-truth summaries shell, page no The shell remains the visible v1 adopter; this slice moves progress semantics out of inline Blade math and into one shared contract

Decision-First Surface Role (mandatory)

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
Tenant shell activity hint Primary Decision Surface Decide whether current work simply needs time, needs inspection now, or is already terminal operation label, lifecycle state, one truthful progress mode, and the canonical View operation action full run detail, logs, evidence, and diagnostics stay in Operations detail Primary because it is the current visible progress host and must not invent execution truth Follows the existing start-surface workflow Replaces ad hoc progress math with one trustworthy meaning

Audience-Aware Disclosure (mandatory)

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
Tenant shell activity hint operator-MSP operation label, lifecycle state, either activity-only or counted-progress treatment, and canonical open link one concise guidance line only when it changes the next decision raw payloads, failure summaries, logs, and debug context View operation raw/support detail stays in Operations detail progress mode is derived once from the shared contract instead of each surface inventing its own explanation

UI/UX Surface Classification (mandatory)

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
Tenant shell activity hint Monitoring hint Activity shell hint Open the most relevant operation if follow-up is needed explicit View operation link forbidden overflow navigation only none /admin/operations?tenant_id={currentTenant} /admin/operations/{run} current tenant context from the shell Operation lifecycle state plus one truthful progress mode none

Operator Surface Contract (mandatory)

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
Tenant shell activity hint Tenant operator Decide whether active work is merely progressing, still waiting, or already terminal Start-surface hint What operation state do I need to react to right now? operation label, lifecycle state, activity-only or counted-progress treatment, canonical open link detailed run diagnostics and evidence on Operations pages lifecycle, progress capability none View operation, Show all operations none

UI Action Matrix: N/A - no Filament Resource, RelationManager, or Page action surface is being introduced or reclassified. The changed surface remains a shell/widget hint and shared Ops-UX semantics layer only.

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: no new persisted source of truth; one shared derived progress contract over existing OperationRun truth only
  • New persisted entity/table/artifact?: no
  • New abstraction?: yes - one bounded shared progress contract/helper inside App\Support\OpsUx
  • New enum/state/reason family?: yes - one derived progress-capability vocabulary (none, activity, counted, phased, composite) used in code and docs only, not persisted
  • New cross-domain UI framework/taxonomy?: no
  • Current operator problem: operators currently rely on progress semantics that are computed locally inside a shell view rather than from one central rule set
  • Existing structure is insufficient because: numeric-only summary_counts sanitization and lifecycle normalization do not answer whether a surface is allowed to show determinate progress or how terminal, queued, phased, or composite work must degrade safely
  • Narrowest correct implementation: one shared progress-semantics helper plus current shell adoption and one standards-doc update, with no count rollout and no new persistence
  • Ownership cost: one helper, focused unit plus feature tests, and one standards-doc update
  • Alternative intentionally rejected: leaving the progress math in bulk-operation-progress.blade.php or persisting an explicit progress mode on operation_runs were both rejected as either too local or too heavy
  • Release truth: current-release truth. The repo already has multiple real surfaces and writers using summary_counts; this slice keeps them from drifting into conflicting progress claims

Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, migration shims, and compatibility-specific tests are out of scope unless a later implementation slice proves they are required.

Canonical replacement of ad hoc progress inference is preferred over preserving duplicate logic.

Testing / Lane / Runtime Impact (mandatory)

  • Test purpose / classification: Unit, Feature
  • Validation lane(s): fast-feedback, confidence
  • Why this classification and these lanes are sufficient: one unit suite can prove the progress-capability mapping and render-model rules cheaply, while focused feature coverage can prove the current shell host consumes the shared contract and does not regress into fake percentage output. Browser proof is not required for this slice because layout and clickability are already owned by specs/268-operationrun-activity-feedback/.
  • New or expanded test families: one focused tests/Unit/Support/OpsUx/OperationRunProgressContractTest.php family plus focused extensions to the current tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php, tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php, and tests/Feature/OpsUx/SummaryCountsWhitelistTest.php
  • Fixture / helper cost impact: low to moderate. Reuse current OperationRun factories, tenant context helpers, and current Ops-UX feature fixtures; do not add provider-heavy setup or a new browser family.
  • Heavy-family visibility / justification: none
  • Special surface test profile: global-context-shell
  • Standard-native relief or required special coverage: standard unit plus feature coverage is sufficient; this spec deliberately does not create new browser obligations
  • Reviewer handoff: reviewers must confirm that the shell consumes a single shared progress contract, queued runs never show determinate progress, terminal runs never keep progress UI, outcome counters do not masquerade as progress, and the feature does not introduce new summary_counts keys or a second local helper
  • Budget / baseline / trend impact: small feature-local increase only
  • Escalation needed: reject-or-split if implementation widens into run-writer rollout, dashboard redesign, or a second persisted progress model
  • Active feature PR close-out entry: Guardrail / Smoke Coverage
  • Planned validation commands:
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/OpsUx/OperationRunProgressContractTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php tests/Feature/OpsUx/SummaryCountsWhitelistTest.php

User Scenarios & Testing (mandatory)

User Story 1 - Derive truthful progress modes from existing run truth (Priority: P1)

As an operator, I need one shared progress contract to decide whether a run shows no progress, activity-only feedback, or determinate counted progress, so the product does not invent conflicting execution claims across Ops-UX surfaces.

Why this priority: this is the core truth gap. Without a shared contract, later shell, dashboard, and rollout work will continue to duplicate or drift progress semantics.

Independent Test: create queued, running, completed-success, completed-failed, and follow-up runs with different summary_counts, then assert that the shared contract returns the correct capability and render model without depending on a specific UI surface.

Acceptance Scenarios:

  1. Given a running run with numeric summary_counts.total and summary_counts.processed, When the shared contract evaluates that run, Then it returns counted progress and clamps the rendered values safely.
  2. Given a queued run or a running run without trustworthy numeric processed and total counts, When the shared contract evaluates it, Then it returns activity-only progress and does not fabricate a percentage.
  3. Given a terminal run, When the shared contract evaluates it, Then it returns no progress line or bar even if outcome counters are present.

User Story 2 - Keep the current shell host on the shared contract (Priority: P1)

As a tenant operator, I need the current shell activity hint to consume the shared progress contract instead of local view math, so active work stays truthful and terminal work never keeps stale progress UI.

Why this priority: the current shell view is the real, repo-visible seam where ad hoc progress logic already exists.

Independent Test: render the current shell activity surface with queued, running, and terminal runs, then verify that it uses counted progress only when the shared contract allows it and otherwise falls back to activity-only or terminal semantics.

Acceptance Scenarios:

  1. Given a running run with valid processed and total counts, When the shell hint renders it, Then the shell shows determinate counted progress derived through the shared contract rather than view-local math.
  2. Given a queued run with a planned total, When the shell hint renders it, Then the shell shows waiting or activity state only and does not promote it to determinate progress.
  3. Given a completed run with succeeded, failed, or skipped counters but no trustworthy active progress truth, When the shell hint renders it, Then the shell shows terminal outcome semantics and not a percentage.

User Story 3 - Document future-safe progress boundaries (Priority: P2)

As a maintainer, I need the UI standards and developer guidance to define what counted, activity-only, phased, and composite progress mean, so later rollout specs extend one contract instead of inventing new progress languages.

Why this priority: the contract only stays useful if later surfaces and writer rollouts know exactly what they may and may not claim.

Independent Test: review the standards guidance and the focused validation suite together, then confirm the package explicitly defers counted rollout and future phase/composite implementation to named follow-up specs.

Acceptance Scenarios:

  1. Given the UI standards are updated for this package, When a maintainer reads the progress rules, Then they can tell that processed and total are the only v1 determinate source and that outcome counters remain outcome-only.
  2. Given future phased or composite work is still unspecced, When a maintainer reads the package, Then the package clearly states that those categories must not masquerade as counted percentages until trustworthy persisted truth exists.

Edge Cases

  • Queued runs may already know total, but they still render as activity-only rather than counted progress.
  • Running runs with processed > total, negative counters, or non-numeric counter values must clamp or degrade safely rather than showing impossible percentages.
  • Terminal runs that retain processed and total counts for summary truth must still drop progress UI and show terminal outcome only.
  • Runs that only have succeeded, failed, or skipped counts must not silently use those outcome counters as progress substitutes.
  • Phase/composite categories may be declared in the shared contract for future use, but until trustworthy phase or child-run truth exists they must degrade to non-counted display and not invent percentages.

Requirements (mandatory)

Constitution alignment summary: This feature adds no new Graph calls, no new write path, no new OperationRun lifecycle, no new summary_counts key, and no new persistence. It reuses the current Ops-UX 3-surface contract, the current summary_counts whitelist, and current shell activity host while centralizing progress semantics into one shared rule set.

Functional Requirements

  • FR-001: The implementation MUST provide one shared Ops-UX progress contract or presenter that derives progress capability and render model from existing OperationRun truth instead of Blade- or widget-local progress math.
  • FR-002: The shared contract MUST define one derived vocabulary for none, activity, counted, phased, and composite progress capability, and that vocabulary MUST live in code and docs only rather than as persisted OperationRun state.
  • FR-003: Determinate counted progress MUST be allowed only when the run is actively running and summary_counts.total plus summary_counts.processed are trustworthy numeric values with total > 0.
  • FR-004: Queued runs and active runs without trustworthy processed and total counts MUST render as activity-only or indeterminate and MUST NOT fabricate a percentage from status, duration, stale-state heuristics, or outcome counters.
  • FR-005: Terminal runs MUST render no progress bar, no percentage, and no processed / total progress line, even when retained counters are present for audit or summary truth.
  • FR-006: summary_counts.succeeded, summary_counts.failed, and summary_counts.skipped remain outcome counters. They MUST NOT silently replace summary_counts.processed as the determinate progress source.
  • FR-007: When counted progress is allowed, the shared contract MUST sanitize or clamp processed, total, and percentage output so rendered values stay within a truthful 0-100 percent range and processed never exceeds total visibly.
  • FR-008: The shared contract MUST declare safe future phased and composite capabilities, and those categories MUST NOT masquerade as counted percentages until trustworthy persisted phase or child-progress truth exists.
  • FR-009: The current shell activity feedback surface MUST consume the shared progress contract and MUST NOT keep inline percentage calculation or progress-mode inference in bulk-operation-progress.blade.php.
  • FR-010: The feature MUST update docs/ui/tenantpilot-enterprise-ui-standards.md and the relevant Spec Kit artifacts so the progress contract, anti-patterns, and follow-up ownership are documented once.
  • FR-011: This slice MUST NOT add new OperationRun status values, outcome values, notification surfaces, summary_counts keys, or persisted progress-mode flags.

Authorization and Safety Requirements

  • AR-001: Tenant/admin-plane authorization semantics remain unchanged: out-of-scope access remains deny-as-not-found (404 semantics through current tenant/admin boundaries), while in-scope visibility continues to reuse server-side OperationRun policies.
  • AR-002: No covered surface may reveal progress state or progress-derived copy for a run the current actor cannot already view.
  • AR-003: No destructive or mutating action is introduced. Existing run start, retry, and detail actions remain responsible for their current confirmation and authorization rules.

Non-Functional Requirements

  • NFR-001: The slice MUST stay Filament-native and Livewire v4-compatible. No panel-provider registration change is allowed; apps/platform/bootstrap/providers.php remains authoritative.
  • NFR-002: No new panel, no new globally searchable resource, and no new asset registration strategy are allowed.
  • NFR-003: Polling remains intentional and bounded. The feature may reuse existing poller families, but it MUST NOT introduce new parallel polling loops.
  • NFR-004: OperationSummaryKeys and SummaryCountsNormalizer remain the only allowed summary-count whitelist and sanitization owners. The progress contract must build on them rather than bypass them.

Deferred Follow-Ups / Explicit Non-Goals

  • 269 — OperationRun Terminal Outcome Feedback, because the repo-based duplicate check shows that specs/268-operationrun-activity-feedback/ already owns that shell slice
  • 271 — Counted Progress Rollout v1
  • 272 — OperationRun Phase & Composite Progress v1
  • 273 — Tenant Dashboard Active Operations Summary Card
  • any run-writer rollout that adds or changes summary_counts.total / summary_counts.processed
  • any dashboard, tray, or customer-facing redesign beyond consuming the shared contract later
  • any new persisted progress model or telemetry system

Key Entities

  • OperationRun Progress Capability: the derived classification that answers whether a run currently supports no progress, activity-only feedback, determinate counted progress, or a future phased/composite mode.
  • OperationRun Progress Render Model: the derived payload that a host surface consumes to show activity-only copy, counted progress values, or terminal no-progress behavior without doing its own math.
  • Counted Progress Truth: the specific case where active running work has trustworthy numeric processed and total counters suitable for determinate rendering.
  • Outcome Counters: retained numeric counts such as succeeded, failed, and skipped that remain outcome summary truth and do not become determinate progress implicitly.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: In focused unit coverage, the shared progress contract classifies the covered fixtures into none, activity, counted, and safe future phased/composite fallbacks without relying on a specific view.
  • SC-002: In focused shell feature coverage, queued and terminal runs show no determinate percentage in 100% of covered scenarios.
  • SC-003: In focused shell feature coverage, determinate progress appears only for active running runs with trustworthy numeric processed and total values.
  • SC-004: In regression coverage, outcome counters such as succeeded, failed, and skipped never produce counted progress unless processed and total also satisfy the shared contract.
  • SC-005: The UI standards and Spec Kit artifacts document one canonical progress contract and explicitly assign counted rollout and phase/composite rollout to later follow-up specs.

Candidate Selection Rationale

  • Selected candidate: OperationRun Progress Contract v1
  • Source locations:
    • docs/product/spec-candidates.md
    • docs/product/roadmap.md
    • specs/268-operationrun-activity-feedback/spec.md
    • apps/platform/app/Support/OpsUx/ActiveRuns.php
    • apps/platform/app/Support/OpsUx/SummaryCountsNormalizer.php
    • apps/platform/app/Support/OpsUx/OperationSummaryKeys.php
    • apps/platform/resources/views/livewire/bulk-operation-progress.blade.php
  • Why selected: the active auto-prep queue is intentionally empty, candidate 269 fails the duplicate check because specs/268-operationrun-activity-feedback/ already covers shell terminal-success and terminal-follow-up semantics, and the current repo still shows inline progress logic inside the shell view with no shared contract. Candidate 270 is the next bounded backlog item that closes a real truth gap without widening into dashboard work or run-writer rollout.
  • Why this is the smallest viable implementation slice: v1 stays on one shared progress contract plus current shell adoption and one standards update. It explicitly excludes counted writer rollout, dashboard productization, and future phase/composite execution truth.
  • Why close alternatives were deferred:
    • 269 — OperationRun Terminal Outcome Feedback is already covered by specs/268-operationrun-activity-feedback/ and is therefore not a safe prep target.
    • 273 — Tenant Dashboard Active Operations Summary Card remains conditional on post-268 dashboard drift and should not be promoted before that drift is visible.
    • 271 — Counted Progress Rollout v1 depends on the shared contract from this package.
    • 272 — OperationRun Phase & Composite Progress v1 depends on the shared contract from this package and likely on later trustworthy phase/composite truth.
  • specs/268-operationrun-activity-feedback/: prep package, not completed, and not safe to refresh through this skill because it already owns the shell terminal outcome slice.
  • specs/266-tenant-dashboard-productization-v1/: different dashboard surface with its own implementation history; used only as context for why 273 remains conditional.
  • specs/055-ops-ux-rollout/, specs/160-operation-lifecycle-guarantees/, and specs/134-audit-log-foundation/: implemented foundation specs that already define the numeric-only summary_counts and three-surface lifecycle rules; used as inherited truth only.