mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-08-27 01:41:58 +00:00
Make the Assistant resolve a missing target before asking, not deflect
The system prompt framed ask-first as the only safe behavior for a
missing target ("Missing target information is not a safe default...
ask for the missing target"), so any "run X" / "check Y" request
without an explicit host deflected back to the operator — including on
single-host deployments with no real ambiguity. OpenCode-parity gap:
a competent operator looks first.
New policy: resolve-before-asking. Use read-only query/topology tools
to identify plausible targets; if exactly one plausible target matches,
run read-only diagnostics against it and name it in the answer; ask
only when several plausible targets remain or the action changes state.
Unchanged safety: placeholder targets (current_resource outside an
attached-resource turn) stay forbidden in all modes, never guess an
unresolved target, and write actions still need an explicit target.
Contract: resolve-before-asking entries in Extension Points and Current
State supersede the ask-first framing. Proof:
TestBuildSystemPrompt_CurrentResourceRequiresResourceHandoff pins the
new boundary strings. Live "just run X" behavior check is owed to the
interaction-quality corpus (next unit); dev-instance agent exec is
currently broken (known command-token issue), so it cannot be observed
end-to-end from here today.
This commit is contained in:
parent
36b9b2a53d
commit
945ed2198d
3 changed files with 44 additions and 5 deletions
|
|
@ -1284,6 +1284,23 @@ deriving an older display status from `workflowStatusHistory`.
|
|||
(`internal/ai/chat/service_execute_additional_test.go`) are the regression
|
||||
proofs that previously-scoped prompt families all reach the model with the
|
||||
same governed manifest and an unmodified user message.
|
||||
The system prompt's missing-target policy is resolve-before-asking, not
|
||||
ask-first: when a command or diagnostic request names no target, the
|
||||
Assistant must first use read-only query/topology tools to identify
|
||||
plausible targets, proceed against a sole plausible match for read-only
|
||||
diagnostics while naming the target in the answer, and ask the operator
|
||||
only when several plausible targets remain or the action changes state.
|
||||
The earlier ask-first framing ("Missing target information is not a safe
|
||||
default... ask for the missing target") made the Assistant deflect every
|
||||
"run X" request back to the operator — including on single-host
|
||||
deployments where no real ambiguity exists — instead of investigating
|
||||
like a competent operator (the OpenCode-parity gap this supersedes).
|
||||
Placeholder targets remain forbidden in all modes: the model must never
|
||||
guess an unresolved target or substitute `current_resource` outside an
|
||||
attached-resource turn, and write actions still require an explicit or
|
||||
operator-confirmed target.
|
||||
`TestBuildSystemPrompt_CurrentResourceRequiresResourceHandoff`
|
||||
(`internal/ai/chat/service_tooling_test.go`) pins this boundary.
|
||||
Deterministic count-only inventory prompts remain the single Pulse-owned
|
||||
local answer shortcut, and it is an answer path, not tool selection: when
|
||||
canonical topology state already carries the complete aggregate counts,
|
||||
|
|
@ -2311,6 +2328,21 @@ deriving an older display status from `workflowStatusHistory`.
|
|||
|
||||
## Current State
|
||||
|
||||
The Assistant system prompt's missing-target policy is resolve-before-asking
|
||||
(`buildSystemPromptWithToolGovernance`, `internal/ai/chat/service.go`): a
|
||||
command or diagnostic request that names no target sends the model to
|
||||
read-only query/topology tools first; a sole plausible match is used directly
|
||||
for read-only diagnostics and named in the answer; the operator is asked only
|
||||
when several plausible targets remain or the action changes state. This
|
||||
supersedes the ask-first framing ("Missing target information is not a safe
|
||||
default") that deflected every untargeted "run X" request back to the
|
||||
operator even on single-host deployments. Placeholder targets
|
||||
(`current_resource` outside an attached-resource turn) remain forbidden in
|
||||
all modes, and write actions still require an explicit operator-confirmed
|
||||
target. `TestBuildSystemPrompt_CurrentResourceRequiresResourceHandoff` pins
|
||||
the boundary strings; the full Extension-Points entry sits beside the
|
||||
model-owned tool-manifest rule.
|
||||
|
||||
The per-turn Assistant system prompt carries the current wall-clock time (the
|
||||
Pulse server clock) so the Assistant answers "what time/date is it" directly
|
||||
instead of deflecting ("I don't have access to a real-time clock") or demanding
|
||||
|
|
|
|||
|
|
@ -3646,9 +3646,9 @@ func (s *Service) buildSystemPromptWithToolGovernance(toolGovernance string) str
|
|||
- Not every VM or container supports control. Some API-backed platforms are read-only even when the resource type is "vm" or "system-container".
|
||||
- Write tools are allowed only when the user explicitly asks you to perform an action.
|
||||
- Status checks and monitoring are read-oriented; do not change state unless the user asked for a state change.
|
||||
- If a structured clarification tool is offered and you are missing critical information (target, risky choice, preference), use it.
|
||||
- If no structured clarification tool is offered, ask for missing information in normal assistant text.
|
||||
- Missing target information is not a safe default. In autonomous mode, ask for the missing target in normal assistant text instead of attempting a tool call with current_resource or another placeholder.
|
||||
- Resolve a missing target yourself before asking: use read-only query/topology tools to see which hosts, VMs, or containers exist. If exactly one plausible target matches the request (a single connected host, or one resource by that name), run read-only diagnostics against it and name the target in your answer instead of asking.
|
||||
- Ask for the target only when several plausible targets remain after looking, or when the action changes state. If a structured clarification tool is offered, use it for missing critical information (target, risky choice, preference); otherwise ask in normal assistant text.
|
||||
- Never guess a target you did not resolve. Do not attempt a tool call with current_resource or another placeholder as a stand-in for a missing target — in autonomous mode the same rules apply: resolve with read-only tools first, then ask in normal assistant text if genuine ambiguity remains.
|
||||
|
||||
## HOW TO RESPOND
|
||||
You are like a colleague doing pair programming on infrastructure tasks. Tool calls are your internal investigation — the user sees your final synthesized response.
|
||||
|
|
|
|||
|
|
@ -293,8 +293,15 @@ func TestBuildSystemPrompt_CurrentResourceRequiresResourceHandoff(t *testing.T)
|
|||
"The placeholder current_resource is valid only when this turn includes Pulse resource context",
|
||||
"either from a resource-context handoff or from Pulse backend resource-reference resolution",
|
||||
"If no attached resource context is present, do not use target_host=\"current_resource\" or resource_id=\"current_resource\"",
|
||||
"Missing target information is not a safe default.",
|
||||
"In autonomous mode, ask for the missing target in normal assistant text instead of attempting a tool call with current_resource",
|
||||
// Resolve-before-asking: the Assistant must try to identify the target
|
||||
// with read-only tools and proceed against a sole plausible match for
|
||||
// read-only diagnostics, instead of deflecting every "run X" request
|
||||
// back to the user. Placeholder targets remain forbidden.
|
||||
"Resolve a missing target yourself before asking",
|
||||
"run read-only diagnostics against it and name the target in your answer",
|
||||
"Ask for the target only when several plausible targets remain after looking, or when the action changes state",
|
||||
"Never guess a target you did not resolve",
|
||||
"Do not attempt a tool call with current_resource or another placeholder",
|
||||
} {
|
||||
if !strings.Contains(prompt, expected) {
|
||||
t.Fatalf("expected current_resource boundary %q in system prompt, got %q", expected, prompt)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue