Explain stopped agent commands without credential or state churn

Distinguish private prompt preparation, preflight and read-only profile inspection from installation and destructive removal. Keep existing unavailable-agent and automatic-update investigations separate, and route FAQ and troubleshooting readers to the existing private-file and recovery guides.

Contract-Neutral: Help copy and rendered-document regression checks only; installer, credential, lifecycle and monitoring contracts are unchanged.
Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot] 2026-10-13 12:07:59 +01:00
parent e241788c38
commit ed2107bee0
7 changed files with 218 additions and 6 deletions

View file

@ -15,11 +15,26 @@ See [INSTALL.md](INSTALL.md) for all options (Docker Compose, Kubernetes, system
Go to **Settings → Infrastructure → Install on a host** for systems that should
run the unified agent directly.
- **Recommended (agent setup)**: copy the generated install command and run it on the target host.
- **Agent setup**: use the generated command on the target host, entering the
token only at its private prompt, never in the command itself. Alternatively,
follow the [private-file preparation](UNIFIED_AGENT.md#private-file-installation-linux-macos-and-nas).
- **Manual/API-backed platforms**: use **Settings → Infrastructure** (**Add infrastructure**) for systems such as Proxmox, PBS, PMG, or TrueNAS that connect over an API instead of running the agent locally.
If you want Pulse to find servers automatically, open **Settings → Infrastructure**, select **Configure discovery** (it reads **Settings** once discovery is on), turn on **Automatic scanning** in the Discovery settings dialog, and then review discovered servers in the same section.
### Why does the copied agent command say no installation was attempted?
That message describes a stopped preparation step, not the health of an agent
already installed. If it follows `stty: command not found`, the private token
prompt cannot prepare the terminal; having an interactive shell does not supply
the missing tool. Do not remove the privacy check, put a token in the command,
generate another token or uninstall the existing agent to get past it.
Use the [agent command failure guide](UNIFIED_AGENT.md#copied-agent-command-fails-before-installation)
to distinguish the prompt, preflight and removal paths. Keep the original error
and existing state; a failed new command does not explain an earlier outage or
automatic-update failure.
### How do I change the port?
Distinguish Pulse's web listener from a container's published host port.

View file

@ -24,6 +24,10 @@ establish safe recovery.
[agent authentication and reporting evidence](UNIFIED_AGENT.md#agent-lookup-returns-http-401-or-403)
before replacing a token or reinstalling. Installer success is not an accepted
report.
- **Copied agent install or removal command failed:** distinguish its
[preparation, private prompt and lifecycle action](UNIFIED_AGENT.md#copied-agent-command-fails-before-installation).
A stopped new command does not diagnose the existing agent. Keep state and
credentials; do not repeat removal or installation to obtain an error.
- **Guest readings are missing or disagree:** distinguish
[current, retained and unavailable disks](VM_DISK_MONITORING.md#current-retained-and-unavailable-disk-readings)
from [guest memory pressure](TROUBLESHOOTING.md#guest-memory-is-high-but-available-memory-is-plentiful).

View file

@ -1040,6 +1040,49 @@ Set `--health-addr=""` or `PULSE_HEALTH_ADDR=off` to disable the health/metrics
## Troubleshooting
### Copied agent command fails before installation
The copied Unix command prepares a download and, for installation, runs a
`--preflight-only` check before entering a private token prompt. Passing
preflight is **not installation** or accepted reporting. Read the original
error to identify which step stopped; do not run the command again to find out.
- **`stty: command not found`, followed by a terminal-required message:** the
command's environment cannot run the tool used to prepare the private prompt.
A real terminal can still produce this error. It does not establish that the
token is invalid, that the target platform cannot run an agent, or that an
existing agent was removed.
- **A terminal-required or interrupted-input message without that error:**
token entry did not complete safely. Keep it separate from an installer's
later result; do not assume a missing tool from the terminal message alone.
- **`Safe-profile migration is unsupported on this platform`:** this concerns
the Linux safe-profile migration path. `--safe-profile-inspect` is a
standalone **read-only** action, not removal; `--uninstall` is a separate,
destructive action. The inspection can produce this error on an unsupported
platform such as QNAP. The error alone does not prove that removal ran. Do
not combine those flags or request a broader-privilege fallback.
**Stop rather than bypass the private prompt.** Do not enable token echo, put a
secret in command arguments or an environment assignment, weaken TLS, generate
a replacement token or delete installed identity, connection files or logs.
For a planned first installation where the prompt is unavailable, the
[private-file installation](#private-file-installation-linux-macos-and-nas)
uses a private editor and `--token-file`, with the same download trust and
collector choices. It is not an instruction to repeat a failed recovery attempt.
For an existing unavailable or outdated agent, retain that original failure
separately and use [reporting checks](#agent-lookup-returns-http-401-or-403) or
[update guidance](#auto-update). If removal was intentional, read its
[state-preservation and result checks](#uninstall) before another action. A
failed new command does not establish the cause of the earlier outage or
automatic-update failure.
When reporting a command failure, share only the original failure stage and
manually redacted error. If the action is consequential, name only the flag
already used (`--safe-profile-inspect` or `--uninstall`), or say **unknown**.
Do not post the full copied command, a token, its file contents or service
configuration, and do not repeat installation or removal to complete a report.
### Collect agent logs safely
Prefer existing observations from the original failure. On a **Linux systemd

View file

@ -15,11 +15,26 @@ See [INSTALL.md](INSTALL.md) for all options (Docker Compose, Kubernetes, system
Go to **Settings → Infrastructure → Install on a host** for systems that should
run the unified agent directly.
- **Recommended (agent setup)**: copy the generated install command and run it on the target host.
- **Agent setup**: use the generated command on the target host, entering the
token only at its private prompt, never in the command itself. Alternatively,
follow the [private-file preparation](UNIFIED_AGENT.md#private-file-installation-linux-macos-and-nas).
- **Manual/API-backed platforms**: use **Settings → Infrastructure** (**Add infrastructure**) for systems such as Proxmox, PBS, PMG, or TrueNAS that connect over an API instead of running the agent locally.
If you want Pulse to find servers automatically, open **Settings → Infrastructure**, select **Configure discovery** (it reads **Settings** once discovery is on), turn on **Automatic scanning** in the Discovery settings dialog, and then review discovered servers in the same section.
### Why does the copied agent command say no installation was attempted?
That message describes a stopped preparation step, not the health of an agent
already installed. If it follows `stty: command not found`, the private token
prompt cannot prepare the terminal; having an interactive shell does not supply
the missing tool. Do not remove the privacy check, put a token in the command,
generate another token or uninstall the existing agent to get past it.
Use the [agent command failure guide](UNIFIED_AGENT.md#copied-agent-command-fails-before-installation)
to distinguish the prompt, preflight and removal paths. Keep the original error
and existing state; a failed new command does not explain an earlier outage or
automatic-update failure.
### How do I change the port?
Distinguish Pulse's web listener from a container's published host port.

View file

@ -24,6 +24,10 @@ establish safe recovery.
[agent authentication and reporting evidence](UNIFIED_AGENT.md#agent-lookup-returns-http-401-or-403)
before replacing a token or reinstalling. Installer success is not an accepted
report.
- **Copied agent install or removal command failed:** distinguish its
[preparation, private prompt and lifecycle action](UNIFIED_AGENT.md#copied-agent-command-fails-before-installation).
A stopped new command does not diagnose the existing agent. Keep state and
credentials; do not repeat removal or installation to obtain an error.
- **Guest readings are missing or disagree:** distinguish
[current, retained and unavailable disks](VM_DISK_MONITORING.md#current-retained-and-unavailable-disk-readings)
from [guest memory pressure](TROUBLESHOOTING.md#guest-memory-is-high-but-available-memory-is-plentiful).

View file

@ -1040,6 +1040,49 @@ Set `--health-addr=""` or `PULSE_HEALTH_ADDR=off` to disable the health/metrics
## Troubleshooting
### Copied agent command fails before installation
The copied Unix command prepares a download and, for installation, runs a
`--preflight-only` check before entering a private token prompt. Passing
preflight is **not installation** or accepted reporting. Read the original
error to identify which step stopped; do not run the command again to find out.
- **`stty: command not found`, followed by a terminal-required message:** the
command's environment cannot run the tool used to prepare the private prompt.
A real terminal can still produce this error. It does not establish that the
token is invalid, that the target platform cannot run an agent, or that an
existing agent was removed.
- **A terminal-required or interrupted-input message without that error:**
token entry did not complete safely. Keep it separate from an installer's
later result; do not assume a missing tool from the terminal message alone.
- **`Safe-profile migration is unsupported on this platform`:** this concerns
the Linux safe-profile migration path. `--safe-profile-inspect` is a
standalone **read-only** action, not removal; `--uninstall` is a separate,
destructive action. The inspection can produce this error on an unsupported
platform such as QNAP. The error alone does not prove that removal ran. Do
not combine those flags or request a broader-privilege fallback.
**Stop rather than bypass the private prompt.** Do not enable token echo, put a
secret in command arguments or an environment assignment, weaken TLS, generate
a replacement token or delete installed identity, connection files or logs.
For a planned first installation where the prompt is unavailable, the
[private-file installation](#private-file-installation-linux-macos-and-nas)
uses a private editor and `--token-file`, with the same download trust and
collector choices. It is not an instruction to repeat a failed recovery attempt.
For an existing unavailable or outdated agent, retain that original failure
separately and use [reporting checks](#agent-lookup-returns-http-401-or-403) or
[update guidance](#auto-update). If removal was intentional, read its
[state-preservation and result checks](#uninstall) before another action. A
failed new command does not establish the cause of the earlier outage or
automatic-update failure.
When reporting a command failure, share only the original failure stage and
manually redacted error. If the action is consequential, name only the flag
already used (`--safe-profile-inspect` or `--uninstall`), or say **unknown**.
Do not post the full copied command, a token, its file contents or service
configuration, and do not repeat installation or removal to complete a report.
### Collect agent logs safely
Prefer existing observations from the original failure. On a **Linux systemd

View file

@ -7,13 +7,14 @@ import { renderDocMarkdown } from '../docMarkdown';
const frontendRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
const source = readFileSync(path.join(frontendRoot, '../docs/UNIFIED_AGENT.md'), 'utf8');
function setupSection() {
function docSection(markdown: string, docPath: string, id: string) {
const article = document.createElement('article');
article.innerHTML = renderDocMarkdown(source, 'UNIFIED_AGENT');
const heading = article.querySelector('#private-file-installation-linux-macos-and-nas')!;
article.innerHTML = renderDocMarkdown(markdown, docPath);
const heading = article.querySelector(`#${id}`);
expect(heading, `${docPath}#${id} must be a real rendered destination`).not.toBeNull();
const section = document.createElement('section');
for (
let node = heading.nextElementSibling;
let node = heading!.nextElementSibling;
node && !/^H[23]$/.test(node.tagName);
node = node.nextElementSibling
) {
@ -22,6 +23,10 @@ function setupSection() {
return section;
}
function setupSection() {
return docSection(source, 'UNIFIED_AGENT', 'private-file-installation-linux-macos-and-nas');
}
describe('Unified Agent private-file setup help', () => {
it('renders preparation and download as self-contained fences before installation', () => {
const section = setupSection();
@ -61,3 +66,86 @@ describe('Unified Agent private-file setup help', () => {
);
});
});
describe('Stopped agent-command help', () => {
const failureId = 'copied-agent-command-fails-before-installation';
const faq = readFileSync(path.join(frontendRoot, '../docs/FAQ.md'), 'utf8');
const troubleshooting = readFileSync(
path.join(frontendRoot, '../docs/TROUBLESHOOTING.md'),
'utf8',
);
const normalizedText = (section: HTMLElement) => section.textContent!.replace(/\s+/g, ' ');
it('makes the same failure destination reachable from setup and troubleshooting', () => {
for (const [name, markdown] of [
['FAQ', faq],
['TROUBLESHOOTING', troubleshooting],
]) {
const article = document.createElement('article');
article.innerHTML = renderDocMarkdown(markdown, name);
expect(
article.querySelector(`a[data-doc-link][href="/docs/UNIFIED_AGENT#${failureId}"]`),
).not.toBeNull();
expect(readFileSync(path.join(frontendRoot, `public/docs/${name}.md`), 'utf8')).toBe(
markdown,
);
}
const setup = docSection(faq, 'FAQ', 'how-do-i-add-a-node');
expect(
setup.querySelector(
'a[href="/docs/UNIFIED_AGENT#private-file-installation-linux-macos-and-nas"]',
),
).not.toBeNull();
expect(normalizedText(setup)).toContain('token only at its private prompt');
});
it('distinguishes stopped prompt, read-only inspection and destructive removal', () => {
const section = docSection(source, 'UNIFIED_AGENT', failureId);
const text = normalizedText(section);
expect(section.querySelectorAll(':scope > ul > li')).toHaveLength(3);
for (const fact of [
'Passing preflight is not installation',
'A real terminal can still produce this error',
'do not assume a missing tool from the terminal message alone',
'standalone read-only action, not removal',
'The error alone does not prove that removal ran',
'failed new command does not establish the cause of the earlier outage',
]) {
expect(text).toContain(fact);
}
const producer = readFileSync(
path.join(frontendRoot, 'src/utils/agentInstallCommand.ts'),
'utf8',
);
expect(producer).toContain('--preflight-only');
expect(producer).toContain('--token-file "$token_file"');
const installer = readFileSync(path.join(frontendRoot, '../scripts/install.sh'), 'utf8');
expect(installer).toContain('--safe-profile-inspect is a standalone read-only action');
expect(installer).toContain('Safe-profile migration is unsupported on this platform');
});
it('links to existing private preparation and recovery without another executable recipe', () => {
const section = docSection(source, 'UNIFIED_AGENT', failureId);
const article = document.createElement('article');
article.innerHTML = renderDocMarkdown(source, 'UNIFIED_AGENT');
for (const id of [
'private-file-installation-linux-macos-and-nas',
'agent-lookup-returns-http-401-or-403',
'auto-update',
'uninstall',
]) {
expect(section.querySelector(`a[href="#${id}"]`)).not.toBeNull();
expect(article.querySelector(`#${id}`)).not.toBeNull();
}
expect(section.querySelector('pre')).toBeNull();
for (const boundary of [
'Stop rather than bypass the private prompt',
'not an instruction to repeat a failed recovery attempt',
'name only the flag already used',
'Do not post the full copied command',
'do not repeat installation or removal to complete a report',
]) {
expect(normalizedText(section)).toContain(boundary);
}
});
});