@@ -8,8 +8,8 @@ experiments.
88 ` pg_stand ` plan.
99- Keeps human-facing component CLIs small while exposing a typed MCP workflow
1010 to an AI agent.
11- - Records immutable plan hashes, run state, component versions, and artifact
12- hashes.
11+ - Records immutable plan hashes, durable run state, append-only events,
12+ component versions, and artifact hashes.
1313- Validates and compares ` pg_diag ` JSON reports without treating a partial
1414 collection as a successful complete run.
1515- Plans and runs ` pg_perf_bench ` only against an explicitly selected disposable
@@ -62,7 +62,7 @@ The control layers are deliberately separate:
6262agent skills workflow and interpretation rules
6363 |
6464 v
65- pg-play-mcp thirteen typed, high-level operations
65+ pg-play-mcp twenty-six typed, high-level operations
6666 |
6767 v
6868pg_play core validation, planning, state, comparison
@@ -221,8 +221,12 @@ The `pg-play` CLI contains only complete experiment operations:
221221| `capabilities` | Read installed component contracts |
222222| `validate MANIFEST` | Validate the manifest and non-mutating component inputs |
223223| `plan MANIFEST` | Calculate the current read-only plan and its hash |
224- | `run MANIFEST --plan-hash HASH --run-id ID` | Execute exactly that plan |
225- | `status MANIFEST --run-id ID` | Read durable run state |
224+ | `start MANIFEST --plan-hash HASH --run-id ID` | Start exactly that plan in a detached worker and return immediately |
225+ | `status MANIFEST --run-id ID` | Read durable state and detect a lost worker |
226+ | `events MANIFEST --run-id ID [--after-sequence N]` | Read ordered durable events, with cursor pagination |
227+ | `cancel MANIFEST --run-id ID [--reason TEXT]` | Request cooperative cancellation |
228+ | `resume MANIFEST --plan-hash HASH --run-id ID` | Verify and resume a failed, cancelled, or interrupted attempt |
229+ | `run MANIFEST --plan-hash HASH --run-id ID` | Execute synchronously for compatibility |
226230| `inspect-report REPORT.json` | Validate and summarize one diagnostic artifact |
227231| `compare-reports BASELINE.json CANDIDATE.json` | Produce deterministic summary deltas |
228232| `inspect-benchmark-report REPORT.json` | Validate and summarize one benchmark artifact |
@@ -241,17 +245,22 @@ pg-workload init --directory workload
241245pg-play validate experiment.yaml
242246pg-play plan experiment.yaml > plan.json
243247
244- # Copy plan_hash from the reviewed plan.
245- pg-play run experiment.yaml \
248+ # Copy plan_hash from the reviewed plan. This command returns after spawning
249+ # the durable worker; it does not wait for the experiment to finish.
250+ pg-play start experiment.yaml \
246251 --plan-hash sha256:... \
247252 --run-id baseline-001
248253
249254pg-play status experiment.yaml --run-id baseline-001
255+ pg-play events experiment.yaml --run-id baseline-001 --after-sequence 0
250256pg-play inspect-report .pg_play/experiments/pg18-mixed-baseline/baseline-001/report.json
251257` ` `
252258
253- ` run` recalculates the plan and rejects a stale hash. A run id is immutable;
254- retry a changed or failed experiment under a new id.
259+ ` start` recalculates the plan and rejects a stale hash. A `run_id` remains
260+ permanently bound to the same manifest and plan. Use `resume` with that same id
261+ for a verified failed, cancelled, or interrupted attempt; use a new id when the
262+ manifest or plan changes. `run` retains the old synchronous behavior for
263+ scripts that explicitly need it.
255264
256265# # MCP server
257266
@@ -264,11 +273,28 @@ pg-play-mcp
264273Configure an MCP client to launch that executable with no shell wrapper. The
265274server exposes only :
266275
276+ See [Agent client setup](https://github.com/O2eg/pg_play/blob/main/docs/agent-client-setup.md)
277+ for concise MCP and Agent Skills configuration examples for Codex CLI, Claude
278+ Code, Hermes Agent, Kimi Code CLI, Gemini CLI, and OpenCode.
279+
267280- ` component_capabilities`
281+ - ` plan_live_diagnostics`
282+ - ` start_live_diagnostics`
283+ - ` live_diagnostics_status`
284+ - ` live_diagnostics_events`
285+ - ` cancel_live_diagnostics`
286+ - ` plan_configuration_review`
287+ - ` collect_configuration_facts`
288+ - ` generate_configuration_candidate`
289+ - ` compare_configuration_candidate`
268290- ` validate_experiment`
269291- ` plan_experiment`
292+ - ` start_experiment`
270293- ` run_experiment`
271294- ` experiment_status`
295+ - ` experiment_events`
296+ - ` cancel_experiment`
297+ - ` resume_experiment`
272298- ` inspect_diagnostic_report`
273299- ` compare_diagnostic_reports`
274300- ` inspect_benchmark_report`
@@ -279,23 +305,115 @@ server exposes only:
279305- ` teardown_experiment`
280306
281307An agent should validate, plan, show the mutation to the user, and then call
282- ` run_experiment` with the unchanged hash and a new run id. The implementation
283- uses the stable [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
284- 1.x line and intentionally excludes the 2.x prerelease API.
308+ ` start_experiment` with the unchanged hash and a new run id. It can poll
309+ ` experiment_status` and page through `experiment_events` without holding one
310+ long MCP request open. The implementation uses the stable
311+ [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) 1.x line
312+ and intentionally excludes the 2.x prerelease API.
313+
314+ The durable schemas are also exposed as `pgplay://run-state-schema` and
315+ ` pgplay://run-event-schema` .
285316
286317# # Agent skills
287318
288- The wheel contains two optional workflow skills under `pg_play/skills/` :
319+ The wheel contains five optional workflow skills under `pg_play/skills/` :
289320
290- - ` run-postgres-experiment` — validate, plan, execute, and recover a run;
291- - ` analyze-postgres-experiment` — inspect reports, compare controlled runs,
292- and design the next single-variable iteration.
321+ - ` run-postgres-experiment` — validate, plan, start, and monitor a new run;
322+ - ` recover-postgres-experiment` — inspect, cancel, and safely resume an
323+ existing durable run;
324+ - ` diagnose-live-postgres` — capture a bounded, read-only diagnostic window on
325+ an existing PostgreSQL host and interpret the validated report;
326+ - ` review-postgres-configuration` — inspect an existing server with a minimal
327+ read-only diagnostic set, generate a candidate, and compare changed settings;
328+ - ` analyze-postgres-experiment` — inspect reports, compare or join controlled
329+ runs, and design the next single-variable iteration.
293330
294331Skills contain procedural guidance; they do not reimplement orchestration or
295332invoke raw component commands. Skill registration is agent-runtime-specific,
296333so installing a Python wheel does not automatically activate them in every
297334agent product.
298335
336+ # # Live-server incident diagnostics
337+
338+ ` plan_live_diagnostics` accepts PostgreSQL and SSH access references, one of
339+ the reviewed intents (`performance`, `locks`, `io`, or `cpu`), and a bounded
340+ snapshots window. It returns missing inputs, the exact versioned item allowlist,
341+ safety limits, and a content hash without connecting to the target. Passwords,
342+ private-key contents, arbitrary SQL, shell commands, tags, and caller-selected
343+ item ids are not accepted.
344+
345+ ` start_live_diagnostics` stores the unchanged plan in a new immutable capture
346+ directory and starts a detached worker. The worker invokes `pg_diag snapshots`
347+ in full remote mode, writes portable JSON and HTML, validates the JSON artifact,
348+ and records ordered events and terminal state. MCP disconnection does not stop
349+ the worker. Use `live_diagnostics_status` and `live_diagnostics_events` to
350+ observe it and `cancel_live_diagnostics` for cooperative cancellation.
351+
352+ Capture duration is limited to 30–900 seconds, interval to 5–60 seconds, and
353+ the schedule to at most 121 snapshots. A lost worker produces `interrupted`;
354+ the existing evidence is retained and a new time window requires a new capture
355+ id rather than a misleading resume or merge.
356+
357+ # # Existing-server configuration review
358+
359+ ` pg_play` exposes a deliberately read-only review workflow for an existing
360+ PostgreSQL server. `plan_configuration_review` reports missing database, SSH,
361+ and tuning-intent inputs. `collect_configuration_facts` runs one bounded
362+ ` pg_diag one-shot` collection containing only server version, effective
363+ ` pg_settings` , database size, CPU, RAM, filesystem, mount, disk, and extension
364+ inventory items. It stores both the original diagnostic report and a compact
365+ ` pg_diag/configuration-facts-v1` artifact.
366+
367+ ` generate_configuration_candidate` combines those observed facts with the
368+ explicit database duty, storage class, replication mode, and PITR intent. The
369+ result remains a `pg_configurator/v1` candidate. Finally,
370+ ` compare_configuration_candidate` writes JSON and Markdown containing only
371+ changed or unobserved parameters, including current source, apply mode,
372+ pending-restart state, calculation rule, and warnings.
373+
374+ The workflow never applies configuration, reloads PostgreSQL, restarts a
375+ service, or treats a candidate as a benchmark-proven optimum. During collection,
376+ ` pg_diag` remote mode opens a bounded dynamic local SSH forward to the requested
377+ PostgreSQL endpoint and closes it with the collection session. Passwords and
378+ private-key contents are not accepted; callers provide passfile, key, and strict
379+ known-hosts paths.
380+
381+ # # Recovery model
382+
383+ Each run directory contains `state.json`, the original `experiment.yaml`, the
384+ reviewed `plan.json`, `postgresql-parameters.json`, append-only `events.jsonl`,
385+ and `worker.log`. `start_experiment` launches a detached worker with its own
386+ session, so closing or crashing the MCP stdio process does not terminate the
387+ experiment. If the worker itself disappears, the next `experiment_status`
388+ changes an active run to `interrupted`.
389+
390+ Cancellation is a durable request in `cancel.request.json`. The worker checks
391+ it before every step and while a component is running. A running component is
392+ started in its own process group; before pg_play signals a process left behind
393+ by a crashed worker, it verifies the recorded PID start time, operating-system
394+ user, and executable identity.
395+
396+ Resume is intentionally conservative :
397+
398+ | Step | Safe resume rule |
399+ | --- | --- |
400+ | stand | Recalculate a read-only pg_stand plan and reconcile only the reviewed desired configuration |
401+ | benchmark | Retry only through pg_perf_bench's idempotent dedicated-database reset |
402+ | prepare database | Retry the declarative database preparation operation |
403+ | install workload | Retry the idempotent profile installation operation |
404+ | start/stop workload | Reconcile the requested running/stopped state |
405+ | diagnostics | Retry the read-only collection operation |
406+
407+ Before a resume, pg_play verifies the manifest hash, plan hash, configuration
408+ artifact, installed component versions, the exact allowlisted resume policy
409+ for every recorded step, and all recorded artifact paths, sizes, and SHA-256
410+ hashes that are available.
411+
412+ Completed benchmark and diagnostic steps must have report artifacts. A valid
413+ completed step is reused; an incomplete step or a step with missing or changed
414+ artifacts is rerun only when its operation is in the allowlist above. Any
415+ unknown step or changed core artifact blocks recovery.
416+
299417# # Determinism and safety
300418
301419- Every component returns the exact `pg_play/component/v1` envelope in hidden
@@ -310,12 +428,14 @@ agent product.
310428 component contract does not yet provision a client certificate for the
311429 dedicated workload role. Direct TLS use of each component remains available.
312430- ` pg_stand apply` verifies its component plan hash; `pg_play run` verifies the
313- combined plan hash. Machine-mode `pg_perf_bench benchmark` independently
431+ combined plan hash. `start` and `resume` enforce the same hash. Machine-mode
432+ ` pg_perf_bench benchmark` independently
314433 verifies a content-sensitive benchmark plan hash before resetting its database.
315434- Subprocesses receive argument arrays with `shell=False`.
316435- Password-bearing CLI arguments and password-bearing machine output are
317436 rejected.
318- - Background workload stop verifies PID ownership before signaling a process.
437+ - Detached component cleanup verifies PID start time, process ownership, and
438+ executable identity before signaling a process group.
319439- A failed cleanup cannot hide the original collection failure; a cleanup
320440 failure after successful diagnostics marks the run partial.
321441- ` pg_diag` partial artifacts are retained and explicitly marked partial.
@@ -331,9 +451,11 @@ run evidence.
331451The first contract covers one configuration candidate, one managed stand,
332452an optional controlled benchmark, selected workload profiles, a one-shot or
333453snapshots report, and deterministic diagnostic and benchmark comparison.
334- Automatic extraction of OS facts and generation or
335- application of TuneD/systemd artifacts remains a roadmap item; it is not
336- silently approximated by the current implementation.
454+ Existing-server incident capture is separately limited to the four reviewed
455+ read-only profiles and one bounded snapshots window per immutable capture id.
456+ Configuration review extracts the bounded CPU, RAM, filesystem, mount, and disk
457+ facts listed above. Generation or application of TuneD/systemd artifacts remains
458+ a roadmap item; it is not silently approximated by the current implementation.
337459
338460# # Development
339461
0 commit comments