Conversation
📝 WalkthroughWalkthroughChangesService readiness lifecycle
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant CLI as autopg restart
participant PM2
participant ServiceState as service-state helpers
participant Runtime as runtime.json
CLI->>PM2: verify autopg-server registration
CLI->>PM2: restart autopg-server
CLI->>ServiceState: waitForServiceReadiness()
ServiceState->>PM2: inspect supervisor state
ServiceState->>Runtime: inspect runtime metadata
ServiceState-->>CLI: ready or formatted failure
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (4)
tests/lib/service-state.test.js (1)
8-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the
stoppedandfailedstatus branches.The tests cover
readyanddegraded. They do not cover the classification atsrc/lib/service-state.cjslines 105-106:supervisorStatusofstoppedormissingmaps tostopped, anderroredmaps tofailed. The install and status paths now report these values to operators. The non-pm2 supervisor branch (supervisor: 'external') is also untested; it makespm2ReadyandruntimeOwnedBySupervisorunconditionally true.🧪 Proposed additional cases
+ test('classifies a stopped pm2 entry as stopped', () => { + const state = evaluateServiceState({ + supervisor: 'pm2', + supervisorStatus: 'stopped', + supervisorPid: null, + configuredPort: 5432, + runtime: null, + runtimeLive: false, + }); + + expect(state.ready).toBe(false); + expect(state.status).toBe('stopped'); + }); + + test('classifies an errored pm2 entry as failed', () => { + const state = evaluateServiceState({ + supervisor: 'pm2', + supervisorStatus: 'errored', + supervisorPid: null, + configuredPort: 5432, + runtime: null, + runtimeLive: false, + }); + + expect(state.status).toBe('failed'); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/lib/service-state.test.js` around lines 8 - 67, Add tests in the evaluateServiceState suite for supervisorStatus values stopped and missing mapping to stopped, and errored mapping to failed, asserting readiness, status, and relevant reasons as appropriate. Also cover the supervisor: 'external' branch, verifying pm2Ready and runtimeOwnedBySupervisor are treated as true and the resulting classification is correct.src/cli-restart.cjs (1)
14-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse the shared
pm2GetProcessinstead of duplicating it.Lines 20-34 duplicate
pm2GetProcessfromsrc/lib/service-state.cjslines 48-62 exactly. This file already imports from that module. The duplicate creates two places to change the PM2 probe timeout or the parsing rules. Export the helper from the module's public surface, or read it from_internals.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/cli-restart.cjs` around lines 14 - 34, Remove the local pm2GetProcess implementation and reuse the shared helper from service-state.cjs. Export pm2GetProcess through that module’s public API, or obtain it via the existing _internals surface, then update cli-restart.cjs to reference the shared symbol while preserving its current process lookup behavior.tests/cli-install.test.js (1)
615-631: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the install readiness-failure branch.
This test covers the degraded status report. No test covers the new failure branch at
src/cli-install.cjslines 1034-1039, where a fresh install aborts because the service never becomes ready. That branch waits 30 s by default and produces the operator-facing diagnostic. A test that suppresses the stub'srefreshRuntimebefore install would cover it. Pass a short readiness timeout, or keep the default and accept the runtime cost.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/cli-install.test.js` around lines 615 - 631, Add a test covering the fresh-install readiness failure branch in the install flow, where the service never becomes ready and the operator-facing diagnostic is emitted. Suppress the stub’s refreshRuntime before invoking install, and configure a short readiness timeout so the test remains fast; assert that installation aborts with the expected failure result and diagnostic.src/commands/doctor.js (1)
263-266: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe message strings still hardcode the process name.
Line 263 now uses
PM2_PROCESS_NAME. Lines 265-266 still embed the literalautopg-serverin the operator messages. If the constant changes, the probe and the reported name diverge. Interpolate the constant in the messages.♻️ Proposed change
const r = pm2EntryOnline(PM2_PROCESS_NAME); return r.ok - ? check('supervisor_liveness', 'pm2 autopg-server entry online', SEVERITY.PASS) - : check('supervisor_liveness', 'pm2 autopg-server entry not online', SEVERITY.FAIL, r.reason, 'run `pgserve install` to (re-)register pm2 entry'); + ? check('supervisor_liveness', `pm2 ${PM2_PROCESS_NAME} entry online`, SEVERITY.PASS) + : check('supervisor_liveness', `pm2 ${PM2_PROCESS_NAME} entry not online`, SEVERITY.FAIL, r.reason, 'run `pgserve install` to (re-)register pm2 entry');🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/commands/doctor.js` around lines 263 - 266, Update the success and failure messages in the supervisor_liveness check to interpolate PM2_PROCESS_NAME instead of hardcoding “autopg-server,” keeping the existing check behavior and remediation text unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Line 140: Update the neighbouring autopg status documentation entry to
describe cmdStatus’s computed status and ready fields as readiness
classification derived from PM2 state and the postmaster runtime record, and
mention supervisorStatus for the raw PM2 value instead of the outdated on-disk
config snapshot wording.
In `@src/cli-install.cjs`:
- Around line 899-910: Update the pre-flight condition around
assertPortAvailable so it skips only when an existing PM2 entry will be
retained; ensure --redeploy still performs the port check because its existing
entry is later removed and replaced.
- Around line 1008-1016: Detect whether the requested port differs from the
existing supervisor configuration before calling writeSupervisorRecord in the
installation flow. When the port changes and the live process is intentionally
retained, fail immediately with guidance to rerun using --redeploy; preserve
idempotent success for unchanged ports and ensure the new port is not persisted
to admin.json before validation.
In `@tests/cli-install.test.js`:
- Around line 82-96: Update the start handling around the registered and online
sentinel writes so they occur only when the stub is in success mode, while
preserving the existing failure exit behavior. Ensure failed pm2 start attempts
do not write service state or trigger refreshRuntime, and successful starts
retain the current registration flow.
In `@tests/lib/service-state.test.js`:
- Around line 1-6: Update tests/lib/service-state.test.js:1-6 and
tests/cli/restart.test.js:9-18 to support CommonJS loading in strict ESM tests
by creating a local require with node:module’s createRequire before each require
call. In tests/cli/restart.test.js, also replace __dirname with a path derived
from import.meta.url while preserving the existing path behavior.
---
Nitpick comments:
In `@src/cli-restart.cjs`:
- Around line 14-34: Remove the local pm2GetProcess implementation and reuse the
shared helper from service-state.cjs. Export pm2GetProcess through that module’s
public API, or obtain it via the existing _internals surface, then update
cli-restart.cjs to reference the shared symbol while preserving its current
process lookup behavior.
In `@src/commands/doctor.js`:
- Around line 263-266: Update the success and failure messages in the
supervisor_liveness check to interpolate PM2_PROCESS_NAME instead of hardcoding
“autopg-server,” keeping the existing check behavior and remediation text
unchanged.
In `@tests/cli-install.test.js`:
- Around line 615-631: Add a test covering the fresh-install readiness failure
branch in the install flow, where the service never becomes ready and the
operator-facing diagnostic is emitted. Suppress the stub’s refreshRuntime before
invoking install, and configure a short readiness timeout so the test remains
fast; assert that installation aborts with the expected failure result and
diagnostic.
In `@tests/lib/service-state.test.js`:
- Around line 8-67: Add tests in the evaluateServiceState suite for
supervisorStatus values stopped and missing mapping to stopped, and errored
mapping to failed, asserting readiness, status, and relevant reasons as
appropriate. Also cover the supervisor: 'external' branch, verifying pm2Ready
and runtimeOwnedBySupervisor are treated as true and the resulting
classification is correct.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8563b9d7-de90-4a3c-aecf-87e2b59e413d
📒 Files selected for processing (8)
README.mdsrc/cli-install.cjssrc/cli-restart.cjssrc/commands/doctor.jssrc/lib/service-state.cjstests/cli-install.test.jstests/cli/restart.test.jstests/lib/service-state.test.js
| autopg url | autopg port # canonical connection string / port | ||
| autopg config <list|get|set|edit|path|init> # manage ~/.autopg/settings.json | ||
| autopg restart # pm2-aware: pm2 restart pgserve, else SIGTERM+respawn | ||
| autopg restart # restart autopg-server; succeeds only when PostgreSQL is ready |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
The restart description is accurate. Update the status description in the same block.
Line 140 matches the new behavior in src/cli-restart.cjs. The neighbouring autopg status description still reads "pm2 + on-disk config snapshot". cmdStatus now reports a computed status and ready field derived from PM2 state and the postmaster runtime record, and it moved the PM2 value to supervisorStatus. Operators reading this table will not learn that the reported status is a readiness classification.
📝 Proposed change
-autopg status # pm2 + on-disk config snapshot
+autopg status # readiness + supervisor state + on-disk config snapshot🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` at line 140, Update the neighbouring autopg status documentation
entry to describe cmdStatus’s computed status and ready fields as readiness
classification derived from PM2 state and the postmaster runtime record, and
mention supervisorStatus for the raw PM2 value instead of the outdated on-disk
config snapshot wording.
| const noUi = args.includes('--no-ui'); | ||
| const withUi = args.includes('--with-ui'); | ||
| const redeploy = args.includes('--redeploy'); | ||
| const existingBeforeInstall = pm2GetProcess(PM2_PROCESS_NAME); | ||
|
|
||
| // B3 (v2.6.1): pre-flight bind-test the chosen port BEFORE creating | ||
| // pm2 entries / admin.json / data dir. Without this, an operator on | ||
| // a host where 5432 is already occupied gets pm2 reporting `online` | ||
| // while the postmaster crashes silently — divergence between | ||
| // supervisor state and data-plane state. Fail fast with a clear hint. | ||
| try { | ||
| await assertPortAvailable(port); | ||
| if (!withUi && !existingBeforeInstall) await assertPortAvailable(port); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
--redeploy now skips the port pre-flight.
Line 910 skips assertPortAvailable whenever a PM2 entry already exists. With --redeploy, that entry is deleted at lines 985-992 and a fresh postmaster is started. The redeploy path is therefore a fresh install, but it never bind-tests the port. If a foreign process holds the port, the operator loses the fast EADDRINUSE diagnostic that the B3 comment describes, and instead waits the full 30 s readiness timeout for a generic "did not become ready" message.
Skip the pre-flight only when the existing entry is kept.
🐛 Proposed fix
try {
- if (!withUi && !existingBeforeInstall) await assertPortAvailable(port);
+ if (!withUi && (redeploy || !existingBeforeInstall)) await assertPortAvailable(port);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const noUi = args.includes('--no-ui'); | |
| const withUi = args.includes('--with-ui'); | |
| const redeploy = args.includes('--redeploy'); | |
| const existingBeforeInstall = pm2GetProcess(PM2_PROCESS_NAME); | |
| // B3 (v2.6.1): pre-flight bind-test the chosen port BEFORE creating | |
| // pm2 entries / admin.json / data dir. Without this, an operator on | |
| // a host where 5432 is already occupied gets pm2 reporting `online` | |
| // while the postmaster crashes silently — divergence between | |
| // supervisor state and data-plane state. Fail fast with a clear hint. | |
| try { | |
| await assertPortAvailable(port); | |
| if (!withUi && !existingBeforeInstall) await assertPortAvailable(port); | |
| const noUi = args.includes('--no-ui'); | |
| const withUi = args.includes('--with-ui'); | |
| const redeploy = args.includes('--redeploy'); | |
| const existingBeforeInstall = pm2GetProcess(PM2_PROCESS_NAME); | |
| // B3 (v2.6.1): pre-flight bind-test the chosen port BEFORE creating | |
| // pm2 entries / admin.json / data dir. Without this, an operator on | |
| // a host where 5432 is already occupied gets pm2 reporting `online` | |
| // while the postmaster crashes silently — divergence between | |
| // supervisor state and data-plane state. Fail fast with a clear hint. | |
| try { | |
| if (!withUi && (redeploy || !existingBeforeInstall)) await assertPortAvailable(port); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/cli-install.cjs` around lines 899 - 910, Update the pre-flight condition
around assertPortAvailable so it skips only when an existing PM2 entry will be
retained; ensure --redeploy still performs the port check because its existing
entry is later removed and replaced.
| writeConfig({ port, dataDir, registeredAt: readConfig()?.registeredAt ?? new Date().toISOString() }); | ||
| writeSupervisorRecord(adminJson, { supervisor: 'pm2', socketDir, port }); | ||
| const state = await waitForServiceReadiness(); | ||
| if (!state.ready) { | ||
| fail( | ||
| `pm2 process "${PM2_PROCESS_NAME}" did not become ready: ${formatServiceState(state)}. ` | ||
| + `Logs: ${getLogsDir()}/${PM2_PROCESS_NAME}-error.log`, | ||
| ); | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Re-running install with a different --port now fails and leaves a wrong admin.json.
Line 1009 writes the newly parsed port into the supervisor record. The comment at lines 1005-1007 states that the live process is intentionally not torn down, so it keeps serving the old port. waitForServiceReadiness reads configuredPort from admin.json and compares it to runtime.port (see src/lib/service-state.cjs lines 77-79 and 137-141). The two values now disagree, so readiness never succeeds and line 1012 aborts with runtime port X does not match configured port Y.
Two effects follow. The documented idempotent no-op success becomes a 30 s hang plus a failure. admin.json is already persisted with a port that nothing listens on, so autopg url and downstream discovery point at a dead port.
Detect the port change before writing the record and tell the operator to use --redeploy.
🐛 Proposed fix
+ // A live entry keeps its original port. Refusing here avoids
+ // recording a port that nothing listens on.
+ const livePort = readConfig()?.port ?? null;
+ if (Number.isInteger(livePort) && livePort !== port) {
+ fail(`pm2 process "${PM2_PROCESS_NAME}" is already running on port ${livePort}. Pass --redeploy to move it to port ${port}.`);
+ }
writeConfig({ port, dataDir, registeredAt: readConfig()?.registeredAt ?? new Date().toISOString() });
writeSupervisorRecord(adminJson, { supervisor: 'pm2', socketDir, port });
const state = await waitForServiceReadiness();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| writeConfig({ port, dataDir, registeredAt: readConfig()?.registeredAt ?? new Date().toISOString() }); | |
| writeSupervisorRecord(adminJson, { supervisor: 'pm2', socketDir, port }); | |
| const state = await waitForServiceReadiness(); | |
| if (!state.ready) { | |
| fail( | |
| `pm2 process "${PM2_PROCESS_NAME}" did not become ready: ${formatServiceState(state)}. ` | |
| + `Logs: ${getLogsDir()}/${PM2_PROCESS_NAME}-error.log`, | |
| ); | |
| } | |
| // A live entry keeps its original port. Refusing here avoids | |
| // recording a port that nothing listens on. | |
| const livePort = readConfig()?.port ?? null; | |
| if (Number.isInteger(livePort) && livePort !== port) { | |
| fail(`pm2 process "${PM2_PROCESS_NAME}" is already running on port ${livePort}. Pass --redeploy to move it to port ${port}.`); | |
| } | |
| writeConfig({ port, dataDir, registeredAt: readConfig()?.registeredAt ?? new Date().toISOString() }); | |
| writeSupervisorRecord(adminJson, { supervisor: 'pm2', socketDir, port }); | |
| const state = await waitForServiceReadiness(); | |
| if (!state.ready) { | |
| fail( | |
| `pm2 process "${PM2_PROCESS_NAME}" did not become ready: ${formatServiceState(state)}. ` | |
| `Logs: ${getLogsDir()}/${PM2_PROCESS_NAME}-error.log`, | |
| ); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/cli-install.cjs` around lines 1008 - 1016, Detect whether the requested
port differs from the existing supervisor configuration before calling
writeSupervisorRecord in the installation flow. When the port changes and the
live process is intentionally retained, fail immediately with guidance to rerun
using --redeploy; preserve idempotent success for unchanged ports and ensure the
new port is not persisted to admin.json before validation.
| if (args[0] === 'start') { | ||
| fs.writeFileSync(${JSON.stringify(path.join(dir, 'registered'))}, ''); | ||
| fs.writeFileSync(${JSON.stringify(statusFile)}, 'online'); | ||
| const nameIndex = args.indexOf('--name'); | ||
| if (nameIndex >= 0 && args[nameIndex + 1] === 'autopg-server') { | ||
| const socketIndex = args.lastIndexOf('--socket-dir'); | ||
| const portIndex = args.lastIndexOf('--port'); | ||
| fs.writeFileSync(serviceStatePath, JSON.stringify({ | ||
| socketDir: args[socketIndex + 1], | ||
| port: Number(args[portIndex + 1]) | ||
| })); | ||
| refreshRuntime(); | ||
| } | ||
| process.exit(${exitCode}); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
The stub marks the process registered and online even in failure mode.
Lines 83-84 write the registered sentinel and the online status before line 95 exits with exitCode, which is 1 in failure mode. A failed pm2 start therefore leaves the stub reporting a healthy autopg-server on the next jlist. Any test that asserts on install failure and then inspects state observes a process that was never started.
Write the sentinel and the status only on the success path.
🧪 Proposed fix
if (args[0] === 'start') {
+ if (${exitCode} !== 0) { process.exit(${exitCode}); }
fs.writeFileSync(${JSON.stringify(path.join(dir, 'registered'))}, '');
fs.writeFileSync(${JSON.stringify(statusFile)}, 'online');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (args[0] === 'start') { | |
| fs.writeFileSync(${JSON.stringify(path.join(dir, 'registered'))}, ''); | |
| fs.writeFileSync(${JSON.stringify(statusFile)}, 'online'); | |
| const nameIndex = args.indexOf('--name'); | |
| if (nameIndex >= 0 && args[nameIndex + 1] === 'autopg-server') { | |
| const socketIndex = args.lastIndexOf('--socket-dir'); | |
| const portIndex = args.lastIndexOf('--port'); | |
| fs.writeFileSync(serviceStatePath, JSON.stringify({ | |
| socketDir: args[socketIndex + 1], | |
| port: Number(args[portIndex + 1]) | |
| })); | |
| refreshRuntime(); | |
| } | |
| process.exit(${exitCode}); | |
| } | |
| if (args[0] === 'start') { | |
| if (${exitCode} !== 0) { process.exit(${exitCode}); } | |
| fs.writeFileSync(${JSON.stringify(path.join(dir, 'registered'))}, ''); | |
| fs.writeFileSync(${JSON.stringify(statusFile)}, 'online'); | |
| const nameIndex = args.indexOf('--name'); | |
| if (nameIndex >= 0 && args[nameIndex + 1] === 'autopg-server') { | |
| const socketIndex = args.lastIndexOf('--socket-dir'); | |
| const portIndex = args.lastIndexOf('--port'); | |
| fs.writeFileSync(serviceStatePath, JSON.stringify({ | |
| socketDir: args[socketIndex + 1], | |
| port: Number(args[portIndex + 1]) | |
| })); | |
| refreshRuntime(); | |
| } | |
| process.exit(${exitCode}); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/cli-install.test.js` around lines 82 - 96, Update the start handling
around the registered and online sentinel writes so they occur only when the
stub is in success mode, while preserving the existing failure exit behavior.
Ensure failed pm2 start attempts do not write service state or trigger
refreshRuntime, and successful starts retain the current registration flow.
| import { describe, expect, test } from 'bun:test'; | ||
|
|
||
| const { | ||
| evaluateServiceState, | ||
| waitForServiceReadiness, | ||
| } = require('../../src/lib/service-state.cjs'); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
ESM test files use CommonJS require without ESLint support. Both new test files import from bun:test with ESM syntax and then load repository modules with require. ESLint reports 'require' is not defined in each file. The PR lists bun run lint as a validation step, so the lint run fails. Fix this once by declaring the CommonJS globals for the test glob in the ESLint config, or per file with createRequire.
tests/lib/service-state.test.js#L1-L6: addimport { createRequire } from 'node:module';andconst require = createRequire(import.meta.url);before therequirecall at line 6.tests/cli/restart.test.js#L9-L18: apply the samecreateRequiredeclaration for lines 16-17, and replace__dirnameat line 12 with a path derived fromimport.meta.urlif the file is strict ESM.
🧰 Tools
🪛 ESLint
[error] 6-6: 'require' is not defined.
(no-undef)
📍 Affects 2 files
tests/lib/service-state.test.js#L1-L6(this comment)tests/cli/restart.test.js#L9-L18
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/lib/service-state.test.js` around lines 1 - 6, Update
tests/lib/service-state.test.js:1-6 and tests/cli/restart.test.js:9-18 to
support CommonJS loading in strict ESM tests by creating a local require with
node:module’s createRequire before each require call. In
tests/cli/restart.test.js, also replace __dirname with a path derived from
import.meta.url while preserving the existing path behavior.
Source: Linters/SAST tools
Summary
Validation
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
autopg restartdocumentation to reflect readiness-based success criteria.