Investigation Guidance & Safety Policies¶
pg-logstats models the database triage process as a directed acyclic investigation graph (DAG) with developer or agent judgement at branch points.
Instead of requiring callers to invent database-specific diagnostic commands, every triage report includes a list of safe, contextual next_actions[] that the caller can select from.
Some next actions are directly executable. Others are delegated branch points where the agent must ask the operator for a decision, such as whether to provide a DSN and rerun inspect.
Next Action Structure¶
Every machine-readable triage report (JSON output) includes a top-level next_actions[] field. Each next action in the list has the following shape:
{
"action_id": "query_family.pg_stat_activity.by_dimensions:qf_51125b8829ab1fdf",
"action_type": "run_sql",
"label": "Find current active sessions for the same query-family dimensions",
"status": "allowed",
"priority": "optional",
"judgement_required": true,
"reason": "The finding includes database, user, or application attribution that can bound pg_stat_activity.",
"target_id": "qf_51125b8829ab1fdf",
"command": {
"argv": ["pg-logstats", "--triage-report", "20260613T181530123456Z-top_query_families", "--action-id", "query_family.pg_stat_activity.by_dimensions:qf_51125b8829ab1fdf", "run-sql"]
},
"risk": "safe",
"action_class": "bounded_activity_queries"
}
Action Schema Details¶
Action Types¶
run_workflow: Run anotherpg-logstatsrunbook directly.run_sql: Run a safe built-in SQL action throughpg-logstats run-sql.prompt_user: Ask the operator to choose how the investigation should proceed.stop: End the current investigation branch.
Priorities¶
requiredrecommendedoptional
Next Action Status¶
allowed: The action is safe to execute in the current state.blocked_by_mode: The action requires a different operating mode (e.g.log_backed).blocked_by_verdict: The database safety verdict blocks this action.blocked_by_config: The action has been disabled or exceedsmax_riskin the configuration.blocked_by_policy: The action is blocked by built-in security policies.omitted_not_enough_context: The action requires missing identifiers (e.g., missing query ID).omitted_unsupported_target: The action target is not supported.
Delegated Operator Actions¶
When a report cannot proceed safely on its own, pg-logstats may emit a delegated prompt_user action instead of a runnable SQL action.
Example:
{
"action_id": "workspace.prompt_user.enable_live_follow_up",
"action_type": "prompt_user",
"label": "Enable live follow-up or stop",
"status": "allowed",
"priority": "recommended",
"reason": "This investigation ranked historical findings from logs only. Live follow-up requires a configured DSN and a fresh inspect run.",
"survey": {
"question": "How should the investigation proceed?",
"choices": [
{
"choice_id": "configure_dsn_and_rerun_inspect",
"label": "Configure DSN and rerun inspect",
"description": "Provide database access for this workspace so pg-logstats can unlock live SQL follow-up.",
"workflow": "inspect",
"command": {
"argv": ["pg-logstats", "inspect"]
}
},
{
"choice_id": "stop_with_offline_findings",
"label": "Stop with offline findings",
"description": "End the investigation after offline log triage without enabling live database access.",
"workflow": "stop"
}
]
}
}
The important rule is:
- only
action_type = "run_sql"should be executed throughpg-logstats run-sql action_type = "prompt_user"means the agent must ask the operator for a decision first
Interpreted SQL Results¶
run-sql reports can include a small payload.insights[] list when pg-logstats recognizes a strong pattern in the bounded result set of one of its own built-in SQL actions.
Example:
{
"workflow": "run_sql",
"payload": {
"action_id": "query_family.pg_stat_activity.by_dimensions:qf_51125b8829ab1fdf",
"source_report_id": "20260613T181530123456Z-top_query_families",
"source_finding_id": "qf_51125b8829ab1fdf",
"insights": [
{
"insight_id": "transactionid_lock_wait",
"label": "The query appears blocked on another transaction",
"confidence": "high",
"reason": "A matching active session is waiting on wait_event_type=Lock and wait_event=transactionid."
}
],
"row_count": 1,
"truncated": false,
"columns": ["pid", "usename", "datname", "application_name", "state", "wait_event_type", "wait_event", "query_start", "query_id", "query"],
"rows": [[42137, "app", "appdb", "api", "active", "Lock", "transactionid", "2026-06-14T10:00:18+00:00", null, "SELECT * FROM invoices WHERE workspace_id = $1 ORDER BY created_at DESC LIMIT $2"]]
}
}
Current product rule:
source_finding_idties the live follow-up back to the parent findinginsights[]is emitted only when the built-in action result supports a bounded interpretation- an empty
insights[]is valid;pg-logstatsshould not invent certainty from weak or ambiguous SQL output
Safety Policy Matrix¶
To prevent diagnostic activity from adding harmful overhead to an already stressed database, actions are allowed or blocked dynamically based on the current verdict of the triage report.
| Verdict | Allowed Action Classes | Blocked Action Classes | Agent / Caller Instruction |
|---|---|---|---|
clear |
system_catalog_reads, stats_view_reads, bounded_activity_queries, text_pattern_stats_search, explain_without_analyze |
large_unbounded_selects, explain_analyze, write_or_admin_action |
Continue with bounded diagnostic reads. |
busy |
system_catalog_reads, stats_view_reads, bounded_activity_queries |
text_pattern_stats_search, explain_without_analyze, large_unbounded_selects, explain_analyze, write_or_admin_action |
Keep follow-up narrow and low-impact. |
saturated |
None | All action classes | Stop adding database load and escalate. |
unknown |
None | All action classes | Do not infer safety; escalate or get better evidence. |
Executing SQL Actions with Linkage Flags¶
For action_type = "run_sql", the caller executes pg-logstats run-sql and links it to the parent report using global audit flags.
Command Usage Example¶
pg-logstats \
--triage-report 20260613T181530123456Z-top_query_families \
--action-id query_family.pg_stat_activity.by_dimensions:qf_51125b8829ab1fdf \
run-sql
Global Audit Linkage Options¶
--triage-report <REPORT>: The persisted report that led to this follow-up action. Accepts a report ID or a report path.--action-id <ACTION_ID>: Theaction_idfrom the parent report'snext_actionsarray.
Behavior & Security¶
- Safety Re-evaluation:
pg-logstatsreads the parent report, finds the requested action, and re-validates the policy matrix against the current state and parameters. If the action is blocked, unknown, or not a SQL action, execution is rejected with a structured error. - Execution: The subcommand (e.g.
run-sql) is executed with safety checks in place. - Report Output & Persistence: The command outputs a new triage report containing the results. Follow-up actions persist immutable reports under
<workspace>/reports/<timestamp>-<runbook>.jsonso the investigation history remains auditable without overwriting prior steps.
Built-In SQL Actions¶
The gateway provides a set of pre-approved, built-in SQL actions for query-family and temp-file triage:
| Rule ID | Purpose | Required identifiers | Risk | Action class | Attribution |
|---|---|---|---|---|---|
query_family.pg_stat_statements.by_queryid |
Exact pg_stat_statements lookup for the query family. |
queryid |
safe |
stats_view_reads |
PostgreSQL pg_stat_statements exact queryid lookup |
query_family.pg_stat_activity.by_dimensions |
Bounded pg_stat_activity lookup using the finding's database, user, and application attribution. |
at least one of database, user, application_name |
safe when application_name is present, otherwise bounded |
bounded_activity_queries |
PostgreSQL pg_stat_activity lookup by app, database, and user |
query_family.explain |
Explain query execution plan for query family. | (None) | safe |
explain_without_analyze |
PostgreSQL EXPLAIN query plan |
query_family.explain_analyze |
Explain analyze query execution plan for query family. | (None) | bounded |
explain_analyze |
PostgreSQL EXPLAIN ANALYZE BUFFERS query plan |
temp_file.pg_stat_database.temp_counters |
Check database temp counters in pg_stat_database. | database |
safe |
stats_view_reads |
PostgreSQL pg_stat_database counters lookup |
temp_file.pg_stat_statements.temp_blocks |
Check pg_stat_statements temp block activity. | (None) | safe |
stats_view_reads |
PostgreSQL pg_stat_statements temp blocks lookup |
temp_file.explain |
Explain query execution plan for the temp-file query. | (None) | safe |
explain_without_analyze |
PostgreSQL EXPLAIN query plan for temp files |
temp_file.explain_analyze |
Explain analyze query execution plan for the temp-file query. | (None) | bounded |
explain_analyze |
PostgreSQL EXPLAIN ANALYZE BUFFERS query plan for temp files |
run-sql executes only built-in SQL actions selected from a parent report. The caller can supply --parameter NAME=VALUE, but cannot supply raw SQL text.
Attribution¶
The runbook-level attribution lives in engg/design/internal-ai-app-triage-v1.md, especially the "Workflow Attribution And Selection" section and its initial V1 reference map.
For the query-family SQL actions in this phase, the intended prior art is:
- PostgreSQL
pg_stat_statementsdocumentation for exactqueryidlookup and normalized statement identity. - PostgreSQL
pg_stat_activitydocumentation for active-session inspection by database, user, application name, wait state, andquery_id. - pgBadger top-query reports as report-shape prior art for carrying query text plus attribution dimensions into follow-up investigation.