feat(setup): surface operator-pack status and add operations runbook
This commit is contained in:
@@ -770,6 +770,7 @@ Repeated failure/recovery notifications are throttled by `notify_cooldown`.
|
||||
- `automation.minio_sync.notify.channel: webchat`
|
||||
|
||||
`flynn setup` now includes an Operator Pack option in Automation that preconfigures scheduled backups, heartbeat alerts, a daily briefing, and a default MinIO sync task, with prompts for output channel/peer routing.
|
||||
See `docs/operations/OPERATOR_PACK.md` for an operations runbook and verification checklist.
|
||||
|
||||
Example Operator Pack output routing:
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ This documentation is written to be useful to both humans and AI agents. If you
|
||||
5. Production and performance
|
||||
- `docs/deployment/PRODUCTION.md`
|
||||
- `docs/performance/TUNING.md`
|
||||
6. Operations runbooks
|
||||
- `docs/operations/OPERATOR_PACK.md`
|
||||
|
||||
## Quick Map (One Diagram)
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Operator Pack Runbook
|
||||
|
||||
This runbook documents the setup and operating model for Flynn's Operator Pack.
|
||||
|
||||
## What It Configures
|
||||
|
||||
When enabled in `flynn setup` Automation, Operator Pack preconfigures:
|
||||
|
||||
- `backup.enabled: true` with cron schedule and output notifications.
|
||||
- `automation.heartbeat.enabled: true` with output notifications.
|
||||
- `automation.daily_briefing.enabled: true` with scheduled briefing output.
|
||||
- `automation.minio_sync.enabled: true` with a default knowledge sync task (optional during setup).
|
||||
|
||||
Setup prompts for:
|
||||
|
||||
- Output routing: `channel` and `peer` (for backup + heartbeat + daily briefing + minio sync notifications).
|
||||
- Backup cron schedule.
|
||||
- Daily briefing cron schedule.
|
||||
- Include/skip default MinIO sync task.
|
||||
|
||||
## Recommended Baseline
|
||||
|
||||
```yaml
|
||||
backup:
|
||||
enabled: true
|
||||
schedule: "0 2 * * *"
|
||||
notify:
|
||||
channel: telegram
|
||||
peer: "123456789"
|
||||
|
||||
automation:
|
||||
heartbeat:
|
||||
enabled: true
|
||||
interval: "5m"
|
||||
notify:
|
||||
channel: telegram
|
||||
peer: "123456789"
|
||||
notify_cooldown: "30m"
|
||||
daily_briefing:
|
||||
enabled: true
|
||||
schedule: "0 8 * * *"
|
||||
output:
|
||||
channel: telegram
|
||||
peer: "123456789"
|
||||
minio_sync:
|
||||
enabled: true
|
||||
interval: "6h"
|
||||
run_on_start: true
|
||||
notify:
|
||||
channel: telegram
|
||||
peer: "123456789"
|
||||
tasks:
|
||||
- prefix: "knowledge/"
|
||||
namespace_base: "global/knowledge/minio"
|
||||
mode: append
|
||||
max_objects: 20
|
||||
max_chars_per_object: 8000
|
||||
force: false
|
||||
```
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
1. Run `flynn doctor --strict` and verify zero failures/warnings.
|
||||
2. Confirm heartbeat route is valid for the configured channel/peer.
|
||||
3. Confirm backup cron and daily briefing cron schedules match operator expectations.
|
||||
4. If using MinIO ingestion, confirm extractor dependencies via doctor output (`MinIO ingest extractors`).
|
||||
|
||||
## Notes
|
||||
|
||||
- Heartbeat notification noise is controlled by `automation.heartbeat.notify_cooldown` (default `30m`).
|
||||
- If `notify_cooldown` is invalid, Flynn falls back to `30m` and logs a warning.
|
||||
- Re-running setup Automation detects an existing Operator Pack and asks whether to reconfigure.
|
||||
@@ -193,7 +193,7 @@
|
||||
"status": "completed",
|
||||
"date": "2026-02-16",
|
||||
"updated": "2026-02-16",
|
||||
"summary": "Implemented operator-focused hardening and onboarding polish: added setup Operator Pack flows in both Automation menu and first-run wizard to preconfigure scheduled backups, heartbeat alerts, daily briefing, and default MinIO sync; added operator-pack prompts for output channel/peer routing with redundant prompt skip when already configured; added heartbeat notification throttling via `automation.heartbeat.notify_cooldown` (with invalid-value fallback handling); and added `flynn doctor --strict` to treat warnings as failures. Added docs/changelog updates and a consolidated regression run record.",
|
||||
"summary": "Implemented operator-focused hardening and onboarding polish: added setup Operator Pack flows in both Automation menu and first-run wizard to preconfigure scheduled backups, heartbeat alerts, daily briefing, and default MinIO sync; added operator-pack prompts for output channel/peer routing with redundant prompt skip when already configured; added a compact Operator Pack status line in setup menu output; added heartbeat notification throttling via `automation.heartbeat.notify_cooldown` (with invalid-value fallback handling); and added `flynn doctor --strict` to treat warnings as failures. Added docs/changelog updates, including a dedicated Operator Pack operations runbook, and a consolidated regression run record.",
|
||||
"files_modified": [
|
||||
"CHANGELOG.md",
|
||||
"src/cli/setup/config.ts",
|
||||
@@ -213,9 +213,11 @@
|
||||
"src/cli/doctor.test.ts",
|
||||
"config/default.yaml",
|
||||
"README.md",
|
||||
"docs/README.md",
|
||||
"docs/operations/OPERATOR_PACK.md",
|
||||
"docs/plans/state.json"
|
||||
],
|
||||
"test_status": "pnpm test:run src/cli/index.test.ts src/cli/setup/automation.test.ts src/cli/setup/integration.test.ts src/cli/setup/summary.test.ts src/automation/heartbeat.test.ts src/config/schema.test.ts src/cli/doctor.test.ts + pnpm typecheck passing"
|
||||
"test_status": "pnpm test:run src/cli/setup/summary.test.ts src/cli/setup/orchestrator.test.ts src/cli/setup/automation.test.ts src/cli/setup/integration.test.ts + pnpm typecheck passing"
|
||||
},
|
||||
"backup-session-summary-audit-trail": {
|
||||
"status": "completed",
|
||||
@@ -3501,7 +3503,7 @@
|
||||
}
|
||||
},
|
||||
"overall_progress": {
|
||||
"total_test_count": 1872,
|
||||
"total_test_count": 1874,
|
||||
"all_tests_passing": true,
|
||||
"p0_completion": "3/3 (100%)",
|
||||
"p1_completion": "4/4 (100%)",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Prompter } from './prompts.js';
|
||||
import type { ConfigBuilder } from './config.js';
|
||||
import { renderSummary } from './summary.js';
|
||||
import { renderOperatorPackStatus, renderSummary } from './summary.js';
|
||||
import { setupProviders } from './providers.js';
|
||||
import { setupChannels } from './channels.js';
|
||||
import { setupMemory } from './memory.js';
|
||||
@@ -28,9 +28,11 @@ const SECTION_HANDLERS: Record<string, (p: Prompter, b: ConfigBuilder) => Promis
|
||||
|
||||
export async function runMenu(p: Prompter, builder: ConfigBuilder): Promise<void> {
|
||||
while (true) {
|
||||
const config = builder.build();
|
||||
p.println();
|
||||
p.println('Flynn Setup — Current Configuration');
|
||||
p.println(renderSummary(builder.build()));
|
||||
p.println(renderSummary(config));
|
||||
p.println(` ${renderOperatorPackStatus(config)}`);
|
||||
p.println();
|
||||
p.println('What would you like to configure?');
|
||||
for (let i = 0; i < MENU_OPTIONS.length; i++) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { renderSummary } from './summary.js';
|
||||
import { renderOperatorPackStatus, renderSummary } from './summary.js';
|
||||
import type { SetupConfig } from './config.js';
|
||||
|
||||
describe('renderSummary', () => {
|
||||
@@ -24,4 +24,43 @@ describe('renderSummary', () => {
|
||||
expect(output).toContain('Automation: heartbeat, daily-briefing, minio-sync');
|
||||
expect(output).toContain('Backup: enabled (cron 0 2 * * *)');
|
||||
});
|
||||
|
||||
it('renders compact operator pack status line with routing when enabled', () => {
|
||||
const config = {
|
||||
models: {
|
||||
default: { provider: 'anthropic', model: 'claude-sonnet' },
|
||||
},
|
||||
server: { port: 18800, localhost: true },
|
||||
automation: {
|
||||
heartbeat: {
|
||||
enabled: true,
|
||||
notify: { channel: 'telegram', peer: '123' },
|
||||
},
|
||||
daily_briefing: { enabled: true },
|
||||
},
|
||||
backup: {
|
||||
enabled: true,
|
||||
notify: { channel: 'telegram', peer: '123' },
|
||||
},
|
||||
} as unknown as SetupConfig;
|
||||
|
||||
expect(renderOperatorPackStatus(config)).toBe('Operator Pack: enabled (telegram/123)');
|
||||
});
|
||||
|
||||
it('renders compact operator pack status line as disabled when partial config', () => {
|
||||
const config = {
|
||||
models: {
|
||||
default: { provider: 'anthropic', model: 'claude-sonnet' },
|
||||
},
|
||||
server: { port: 18800, localhost: true },
|
||||
automation: {
|
||||
heartbeat: { enabled: true },
|
||||
},
|
||||
backup: {
|
||||
enabled: true,
|
||||
},
|
||||
} as unknown as SetupConfig;
|
||||
|
||||
expect(renderOperatorPackStatus(config)).toBe('Operator Pack: disabled');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
import type { SetupConfig } from './config.js';
|
||||
|
||||
export function renderOperatorPackStatus(config: SetupConfig): string {
|
||||
const automation = config.automation ?? {};
|
||||
const backup = config.backup;
|
||||
const enabled = Boolean(
|
||||
backup?.enabled
|
||||
&& automation.heartbeat?.enabled
|
||||
&& automation.daily_briefing?.enabled,
|
||||
);
|
||||
|
||||
if (!enabled) {
|
||||
return 'Operator Pack: disabled';
|
||||
}
|
||||
|
||||
const notify = backup?.notify ?? (automation.heartbeat as { notify?: { channel?: string; peer?: string } } | undefined)?.notify;
|
||||
if (notify?.channel && notify?.peer) {
|
||||
return `Operator Pack: enabled (${notify.channel}/${notify.peer})`;
|
||||
}
|
||||
|
||||
return 'Operator Pack: enabled';
|
||||
}
|
||||
|
||||
export function renderSummary(config: SetupConfig): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user