Skip to content

fix(runtime): make capture evidence and provider handoffs composable - #468

Merged
morluto merged 2 commits into
mainfrom
fix/capture-evidence-provider-handoffs
Sep 5, 2026
Merged

fix(runtime): make capture evidence and provider handoffs composable#468
morluto merged 2 commits into
mainfrom
fix/capture-evidence-provider-handoffs

Conversation

@morluto

@morluto morluto commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Capture and provider-preparation results could lose the information needed for the next investigation step. This change separates authoritative outcomes from bounded diagnostics, durable source identity from storage location, and dependency preparation from server activation.

Issues Root cause and resulting behavior
#457, #465 MCP inferred success from the retained execution list and attributed every exit to the workload. Capture now computes complete success/failure counts before compaction, records the invoked executable digest, and identifies collector exits separately from independently observed workload exits.
#464, #467 Resource redaction removed required selectors, while pagination depended on deleted scratch paths. Resources now expose opaque artifact and logical-source selectors plus ordered analysis sources. Continuations bind ordered content, formats, producers, options, and limits and remain consumable after preservation releases scratch.
#462, #463 JSON dispatch examined the first byte, and the preview schema advertised bytes while execution counted rows. Dispatch now handles JSON whitespace, malformed JSON gets a typed decode failure, and the schema documents logical-row offsets.
#458 Repository errors omitted configuration and recovery context. Fail-closed failures now identify the selected store without exposing its path, explain safe recovery, and point to the local flameox evidence location diagnostic.
#459, #460, #461 Preparation conflated installing packages, satisfying the active server contract, and host/workload readiness. Shared environment contracts now live under providers. MCP preparation uses bounded, cancellable subprocesses; pinned py-spy can activate in the existing session, repeated requests reuse its verified binding, and unrelated preparation retains it. Server dependency checks distinguish ready, required-restart, and unknown states. Structured and text results retain host and workload requirements.
#466 A point-estimate classification looked like an inferential decision. point_estimate_classification and an explicit descriptive basis now separate it from interval uncertainty and semantic correctness.

The collector design uses uv's isolated, version-selectable tool environments and py-spy's standalone collector model. No custom package cache or persistent provider inventory is introduced. CLI launchers still declare the complete requested provider set; workload packages and external host prerequisites remain separately verified at capture time where supported.

Compatibility: point_estimate_classification replaces experiment decision. Old path-bound continuation tokens require a fresh analysis. Existing evidence manifests remain readable; new captures add exit-attribution fields and new preservation adds explicit source-layout metadata, both requiring the updated reader. Selectors from an earlier revision of this PR must be re-enumerated from the evidence resource. Same-session independent collector activation currently covers py-spy; Perfetto's native engine and vendor profilers remain external requirements.

Review follow-up (b4220a2): source layout now explicitly records file/directory identity, exact membership, and ordered analysis mapping. This retains empty directories and exact members through repeated preservation without interpreting private filenames as structure. Selectors address public immutable manifest positions. Invocation builders declare exit ownership. Preparation forwards safe uv policy controls and commits collector bindings only when the whole request succeeds; failed concurrent requests cannot roll back successful activation.

Validation:

  • The review regressions produced 10 expected failures against the preceding PR head (22fe870), covering all six comments. Added coverage includes repeated preservation, reopened sessions, malformed source metadata, and concurrent preparation. Independent exact-diff review and one consolidated follow-up completed; its findings were fixed and covered by regression tests before final full validation.
  • New baseline checks reproduced seven failures before implementation; the preservation handoff cases also failed before the source selectors were added.
  • uv run pytest -q -m 'not optional and not performance' --tb=short: 347 passed, 1 skipped, 4 deselected. Includes real subprocess and MCP resource round trips, collector-failure attribution, byte-pressure outcomes, cancellation, and preservation pagination.
  • uv run ruff check src tests tools, uv run ruff format --check src tests tools, and uv run mypy src tests tools: passed.
  • uv run lint-imports, uv run vulture src/flameox --min-confidence 80, and the CI dependency check with deptry: passed.
  • A real uvx --isolated --python 3.12 --from py-spy==0.4.2 probe resolved and executed collector version 0.4.2. The local evidence-location CLI was also exercised.

The AIPerf import test was skipped because that optional package is absent. GPU/vendor tooling and non-Linux collector execution were not exercised; preparation fixtures establish lifecycle behavior, not host profiling permission or universal workload compatibility.

Fixes #457
Fixes #458
Fixes #459
Fixes #460
Fixes #461
Fixes #462
Fixes #463
Fixes #464
Fixes #465
Fixes #466
Fixes #467

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T07:25:55.107484Z b4220a2 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22fe8706be

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/flameox/providers/preparation.py
Comment thread src/flameox/repository.py Outdated
Comment thread src/flameox/repository.py Outdated
Comment thread src/flameox/stateless.py Outdated
Comment thread src/flameox/providers/preparation.py
Comment thread src/flameox/stateless.py Outdated
@morluto
morluto merged commit d62d35a into main Sep 5, 2026
10 checks passed
@morluto
morluto deleted the fix/capture-evidence-provider-handoffs branch September 5, 2026 07:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4220a2b8d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +124 to +126
output = await self._run([str(adjacent), "--version"], min(timeout, 10))
if output.decode().strip() == f"py-spy {PY_SPY_VERSION}":
return self._bind(str(adjacent)), []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bind the same adjacent collector that was version-checked

When the adjacent py-spy executable is replaced between the version probe and this second _bind, preparation activates the replacement even though that identity was never version-checked; later capture validation only confirms that the replacement remains unchanged. Retain the executable binding used by the probe, or re-run the version check against the exact binding being activated.

AGENTS.md reference: AGENTS.md:L33-L35

Useful? React with 👍 / 👎.

Comment thread src/flameox/repository.py
raise RepositoryError("REPOSITORY_CORRUPTION", "Evidence membership is incomplete.")
inputs = body["analysis_request"].get("inputs", [])
indices = layout["analysis_sources"]
if indices and len(indices) != len(inputs):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject missing analysis-source mappings

When a manifest has nonempty analysis_request.inputs but an empty source_layout.analysis_sources, this condition skips the length check and the following zip validates nothing. The manifest is therefore accepted as authoritative, but its resource projection exposes no analysis_sources, making the preserved analysis impossible to replay; require the mapping length to equal the input length even when the mapping is empty.

AGENTS.md reference: AGENTS.md:L40-L41

Useful? React with 👍 / 👎.

Comment thread src/flameox/mcp/server.py

next_action = None
if preparation.restart_required:
if preparation.restart_required is not False:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align server guidance with live py-spy activation

When prepare_providers is called for only py-spy, this new logic correctly leaves next_action null because the collector is activated in the current session, but the MCP server instructions at lines 308–310 still direct the agent to reconnect after every missing managed provider. Following that higher-level guidance can unnecessarily terminate the session and lose unpreserved analyses, so make it tell callers to follow the returned activation status instead.

AGENTS.md reference: AGENTS.md:L44-L48

Useful? React with 👍 / 👎.

Comment on lines +203 to +204
if collector is not None:
self._py_spy = collector

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overwriting a newer concurrent collector binding

When an earlier mixed preparation pauses during server-environment preparation after resolving collector A, a later py-spy-only request can successfully activate a newer collector B; once the earlier request resumes, this unconditional assignment overwrites B with stale A. The next capture then reports an expired collector despite the later preparation succeeding, so serialize binding publication or commit only if the session binding has not advanced since this request began.

AGENTS.md reference: AGENTS.md:L40-L41

Useful? React with 👍 / 👎.

Comment on lines +123 to +124
if adjacent.is_file():
output = await self._run([str(adjacent), "--version"], min(timeout, 10))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fall back when the adjacent collector probe fails

When a py-spy file exists beside the server interpreter but is not executable or exits nonzero for --version, _run raises SetupFailure here and aborts preparation before trying the pinned uvx environment. This prevents an explicit preparation request from recovering from a stale or broken adjacent installation even when uvx is available; treat a failed adjacent probe as a miss and continue to the isolated preparation path.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment