Skip to content

[ops]: split Pester execution monolith into context/runtime/selection/execution/post layers #2078

@svelderrainruiz

Description

@svelderrainruiz

Problem

Pester (execution only) still behaves like a monolith even after the service-model split. It currently mixes:

  • repo/control-plane context
  • host/runtime preflight
  • test selection and dispatcher shaping
  • actual execution
  • post-execution classification and receipts

The standing-priority false negative observed during the self-hosted execution path proves the leak: a repo-control-plane concern can still surface as an execution-seam failure.

Current evidence:

  • direct operator proof run 23806250860 admitted the trusted router and cleared readiness
  • the active long pole is pilot / pester-run / Pester (execution only) on GHOST-comparevi-capability-ingress
  • standing-priority discovery is correct in the repo itself (#2069 is open and labeled standing-priority), so this defect class is about execution-layer coupling, not actual queue state

Objective

Break Pester (execution only) into coherent layers so each failure class is attributable to one contract boundary.

Target layers:

  1. pester-context
  2. pester-runtime-preflight
  3. pester-selection
  4. pester-execute
  5. pester-post

Implementation Plan

1. Add a context layer and receipt

Create an explicit pester-context stage ahead of readiness/execution.

Responsibilities:

  • resolve repository slug deterministically
  • validate workflow token presence/usability for issue discovery
  • run standing-priority sync or emit an explicit non-blocking context classification
  • validate worktree/helper-root assumptions if they are needed by downstream scripts
  • emit pester-context-receipt@v1

Outputs:

  • context_status: ready | blocked | warning
  • repository
  • standing_priority_issue
  • standing_priority_reason
  • receipt artifact

2. Make runtime preflight consume context, not discover context

Refactor self-hosted readiness to assume repo/control-plane context is already settled.

Responsibilities:

  • validate session-lock health
  • validate .NET toolchain and runtime dependencies
  • validate Windows Docker runtime
  • validate LVCompare and idle LabVIEW state
  • prepare fixture prerequisites only
  • emit pester-selfhosted-readiness-receipt@v1

Non-goal:

  • no standing-priority or issue discovery here

3. Add a selection layer

Create a pester-selection contract between readiness and execution.

Responsibilities:

  • normalize integration mode
  • resolve include/exclude patterns
  • materialize dispatcher profile
  • resolve the concrete test pack/file selection
  • emit pester-selection-receipt@v1

This separates test-shaping defects from dispatcher/runtime defects.

4. Shrink execution to execution only

Reduce pester-execute to one job: run the dispatcher against a prepared environment.

Responsibilities:

  • consume context, readiness, and selection receipts
  • acquire/release execution lock
  • run Invoke-PesterTests.ps1
  • emit raw execution outputs and a minimal execution exit contract

Non-goals:

  • no standing-priority sync
  • no repo slug resolution
  • no readiness probing
  • no test-pack shaping

5. Move classification into post-processing

Create pester-post as the only place that turns raw execution into operator meaning.

Responsibilities:

  • release lock defensively
  • write execution receipt
  • upload raw artifacts
  • classify terminal status as one of:
    • completed
    • test-failures
    • context-blocked
    • readiness-blocked
    • selection-blocked
    • seam-defect

6. Remove context ownership from Invoke-PesterTests.ps1

Invoke-PesterTests.ps1 should become context-agnostic.

Required outcome:

  • it must not own standing-priority lookup or repository-priority decisions
  • it must assume context/readiness/selection were already proven upstream
  • it may still own dispatcher/runtime/test orchestration

7. Add contract tests per layer

Add workflow and receipt tests for:

  • context-ready path
  • context-blocked path
  • readiness-ready path
  • readiness-blocked path
  • selection receipt generation
  • execution-only path with mocked dispatcher
  • post-processing classification for missing summary / skipped / blocked / failures

8. Promote only after additive proof

Rollout sequence:

  1. land the layer split additively
  2. prove it on direct operator dispatch
  3. prove it on same-owner trusted PR routing
  4. prove it on integration/** mounted upstream proof
  5. only then recast the current monolith as legacy/fallback

Acceptance Criteria

  • standing-priority lookup failures surface in pester-context, not pester-execute
  • readiness failures surface in pester-runtime-preflight, not as generic execution stalls
  • test selection is represented by an explicit receipt
  • execution can run without performing repo/control-plane discovery
  • post-processing can classify failures without guessing their layer
  • at least one end-to-end proof passes on the service-model rail after the split

Risks / Notes

  • this is a follow-up slice under #2069, not a replacement for it
  • the issue should remain out of standing auto-selection while #2069 stays the epic
  • the current run 23806250860 should be preserved as pre-split evidence of the remaining execution-layer ambiguity

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciCI/CD, workflows, and pipeline changesfork-standing-priorityFork-only standing priority for automation routinggovernancePolicy, approvals, and operating model

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions