Prefer structured planning hints over raw message heuristics
CI / test (push) Failing after 12s

This commit is contained in:
m
2026-08-18 17:15:56 +03:00
parent 4321bd627d
commit 5db143df3b
2 changed files with 17 additions and 6 deletions
+7 -6
View File
@@ -81,24 +81,25 @@ func DetermineHelpPath(input work.PlanningInput) work.HelpPath {
hasInspectHint := hasPlanningHint(input, capability.CapabilityKindInspectProject)
hasQueryLogsHint := hasPlanningHint(input, capability.CapabilityKindQueryLogs)
hasVerifyHint := hasPlanningHint(input, capability.CapabilityKindVerifyFact)
rawTextFallbackAllowed := len(input.CapabilityHints) == 0 && !input.RequiresClarification && !input.NeedsCognition
topSpeech := input.SpeechAct
switch {
case input.RequiresClarification:
return work.HelpPath{Kind: work.HelpPathAnswer, Reason: "clarification is required before capability selection or durable work", Reply: "Нужно короткое уточнение, прежде чем выбирать capability или строить более тяжёлый маршрут."}
case hasReminderHint || isReminderRequest(lower):
case hasReminderHint || (rawTextFallbackAllowed && isReminderRequest(lower)):
return work.HelpPath{Kind: work.HelpPathDirectCapability, SuggestedCapabilityKinds: []capability.CapabilityKind{capability.CapabilityKindScheduleReminder}, Reason: "reminder is a direct scheduling-capability path, not a coding/project workflow", Reply: "Понял: нужен reminder/scheduler capability. В DEV-000063 я фиксирую это как безопасный путь помощи; само напоминание ещё не зарегистрировано, потому что scheduling adapter не подключён."}
case isEmailReviewRequest(lower) && hasReadEmailHint:
return work.HelpPath{Kind: work.HelpPathDurableWork, NeedsDurableGoal: true, NeedsDurableWork: true, NeedsDurablePlan: true, Reason: "mail triage/review needs structured reading and reasoning without claiming outbound send"}
case hasSendEmailHint || isExplicitEmailGapRequest(lower):
case hasSendEmailHint || (rawTextFallbackAllowed && isExplicitEmailGapRequest(lower)):
return work.HelpPath{Kind: work.HelpPathCapabilityGap, SuggestedCapabilityKinds: []capability.CapabilityKind{capability.CapabilityKindSendEmail}, CapabilityGap: true, Reason: "email sending needs a communication capability implementation and explicit authority", Reply: "Сейчас у меня ещё не подключена возможность отправлять почту. Я зафиксирую этот capability gap, чтобы позже к нему можно было вернуться."}
case hasModifyHint || hasInspectHint || hasQueryLogsHint || hasReadEmailHint || hasRecallHint || hasVerifyHint || needsDurableWorkFromHints(input):
return work.HelpPath{Kind: work.HelpPathDurableWork, NeedsDurableGoal: true, NeedsDurableWork: true, NeedsDurablePlan: true, Reason: "semantic hints indicate project/code work even if cognition may still be useful upstream"}
case requiresDurableWork(lower):
case rawTextFallbackAllowed && requiresDurableWork(lower):
return work.HelpPath{Kind: work.HelpPathDurableWork, NeedsDurableGoal: true, NeedsDurableWork: true, NeedsDurablePlan: true, Reason: "request needs durable coordination, planning, investigation, or outcome tracking"}
case isUnsupportedCapabilityRequest(lower):
case rawTextFallbackAllowed && isUnsupportedCapabilityRequest(lower):
return work.HelpPath{Kind: work.HelpPathCapabilityGap, SuggestedCapabilityKinds: []capability.CapabilityKind{}, CapabilityGap: true, Reason: "requested help needs a currently missing capability and may later trigger acquisition/self-extension", Reply: "Похоже, для этой просьбы нужна capability, которой сейчас нет. Это не задача конкретного executor автоматически: в будущем Домовой сможет найти, подключить или создать подходящую capability и вернуться к исходной потребности."}
case containsAny(lower, "объясни", "расскажи", "что делает"):
case rawTextFallbackAllowed && containsAny(lower, "объясни", "расскажи", "что делает"):
return work.HelpPath{Kind: work.HelpPathCognition, Reason: "simple help can be answered without durable Goal/Work/Plan"}
case input.NeedsCognition && (topSpeech == work.SpeechActRef("QUESTION") || topSpeech == work.SpeechActRef("REQUEST_TO_INVESTIGATE") || hasRecallHint):
return work.HelpPath{Kind: work.HelpPathCognition, Reason: "semantic layer marked this utterance as cognition-relevant and no durable work path outranks it"}
@@ -334,4 +335,4 @@ func isExplicitEmailGapRequest(lower string) bool {
func isUnsupportedCapabilityRequest(lower string) bool {
return containsAny(lower, "не умеешь", "подключи интеграцию", "подключи сервис", "интеграц", "неизвестн", "нет capability", "создай adapter", "создай адаптер", "сервис, которого сейчас нет")
}
}
+10
View File
@@ -109,6 +109,16 @@ func TestHelpPathCapabilityGapDoesNotBecomeCodexTask(t *testing.T) {
}
}
func TestHelpPathStructuredHintsOverrideRawCognitionPhrase(t *testing.T) {
input := planningInputForTest("Объясни, что делает этот код.", "QUESTION", epistemics.VerificationNotApplicable)
input.NeedsCognition = false
input.CapabilityHints = []capability.CapabilityKind{capability.CapabilityKindSendEmail}
path := DetermineHelpPath(input)
if path.Kind != work.HelpPathCapabilityGap || !path.CapabilityGap {
t.Fatalf("structured send-email hint should force capability gap path: %#v", path)
}
}
func planForTest(t *testing.T, message string, act string, verification epistemics.VerificationState) work.PlanningResult {
t.Helper()
result, err := BuildPlanningResult(planningInputForTest(message, act, verification), time.Unix(100, 0))