Merge branch 'graph-overview/trim-hosts-add-done-total'
This commit is contained in:
commit
dc4645753c
3 files changed
+26
-27
No files matched your search
@@ -103,9 +103,8 @@ func TestGraphOverviewExpandsAssociatedCompanyScope(t *testing.T) {
|
||||
if !ok || len(keywords) != 1 || keywords[0] != keyword {
|
||||
t.Fatalf("company keywords missing: %#v", scopeRows[0]["company_keywords"])
|
||||
}
|
||||
hosts, ok := coverage["hosts"].([]string)
|
||||
if !ok || !containsString(hosts, domain) {
|
||||
t.Fatalf("company asset host missing from agent context: %#v", coverage["hosts"])
|
||||
if hc, _ := coverage["host_count"].(int); hc < 1 {
|
||||
t.Fatalf("company asset host not counted in agent context: %#v", coverage["host_count"])
|
||||
}
|
||||
untested := callReadJSON(t, tools.listUntestedAssets(), `{"type":"root_domain","page":1,"page_size":10}`)
|
||||
if !strings.Contains(fmt.Sprint(untested), domain) {
|
||||
@@ -153,9 +152,8 @@ func TestGraphOverviewExpandsAssociatedCompanyScope(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("coverage-disabled task lost asset context: %#v", disabledOverview["coverage"])
|
||||
}
|
||||
disabledHosts, ok := disabledCoverage["hosts"].([]string)
|
||||
if !ok || !containsString(disabledHosts, domain) {
|
||||
t.Fatalf("coverage-disabled task lost company asset host: %#v", disabledCoverage["hosts"])
|
||||
if hc, _ := disabledCoverage["host_count"].(int); hc < 1 {
|
||||
t.Fatalf("coverage-disabled task lost company asset host count: %#v", disabledCoverage["host_count"])
|
||||
}
|
||||
if _, exists := disabledCoverage["denominator"]; exists {
|
||||
t.Fatalf("coverage-disabled task unexpectedly exposed metrics: %#v", disabledCoverage)
|
||||
@@ -176,15 +174,6 @@ func TestGraphOverviewExpandsAssociatedCompanyScope(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func containsString(items []string, target string) bool {
|
||||
for _, item := range items {
|
||||
if item == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func companiesName(t *testing.T, companies *db.CompanyStore, companyID int64) string {
|
||||
t.Helper()
|
||||
company, err := companies.GetCompany(companyID)
|
||||
@@ -321,9 +310,8 @@ func TestBlackboardToolsReadDirectSources(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("coverage missing from overview: %#v", overview["coverage"])
|
||||
}
|
||||
hosts, ok := coverage["hosts"].([]string)
|
||||
if !ok || len(hosts) != 1 || hosts[0] != host || coverage["host_count"] != 1 {
|
||||
t.Fatalf("inherited host context missing: %#v", coverage)
|
||||
if coverage["host_count"] != 1 {
|
||||
t.Fatalf("inherited host context missing (want host_count=1): %#v", coverage)
|
||||
}
|
||||
|
||||
facts := callReadJSON(t, tools.listFacts(), `{}`).(map[string]any)["facts"].([]any)
|
||||
|
||||
+8
-9
@@ -412,6 +412,12 @@ func (t *ToolSet) graphOverviewData() map[string]any {
|
||||
}
|
||||
out["running_intents"] = compactIntents(running, parentsOf, yieldsOf)
|
||||
out["recent_done_intents"] = compactIntents(recentDone, parentsOf, yieldsOf)
|
||||
// done_intents_total:已结束意图(done/blocked/exhausted)总数,与 recent_done_intents
|
||||
// 平行命名——后者只是它的最新窗口(≤15)截断视图。两键并排即自描述:"看到的是 N/总数",
|
||||
// 让 planner 去重时别把"没显示"当成"没派过",无需在提示词里另行解释。
|
||||
if dt, err := t.ts.CountFinishedIntents(); err == nil {
|
||||
out["done_intents_total"] = dt
|
||||
}
|
||||
out["frontier_open"] = len(fr)
|
||||
// findings (confirmed vulns) and facts (worker exploration results) are
|
||||
// now distinct node kinds. recent_facts surfaces fact summaries (esp.
|
||||
@@ -532,16 +538,9 @@ func (t *ToolSet) graphOverviewData() map[string]any {
|
||||
m["scope"] = scope
|
||||
}
|
||||
if hosts, err := t.as.HostsByTaskWithSources(t.taskID); err == nil {
|
||||
const hostContextLimit = 500
|
||||
visible := hosts
|
||||
if len(visible) > hostContextLimit {
|
||||
visible = visible[:hostContextLimit]
|
||||
}
|
||||
m["hosts"] = visible
|
||||
// 只给主机总数,不再把 host 列表平铺进 graph_overview(大范围任务里那是每轮
|
||||
// 都重复携带的大量字符串,对规划决策价值有限);具体主机按需 list_assets 查。
|
||||
m["host_count"] = len(hosts)
|
||||
if len(visible) < len(hosts) {
|
||||
m["hosts_truncated"] = true
|
||||
}
|
||||
}
|
||||
if len(m) > 0 {
|
||||
out["coverage"] = m
|
||||
|
||||
@@ -706,6 +706,18 @@ func (s *ExplorationStore) countByKindFiltered(kind, q string) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// CountFinishedIntents counts this exploration's intents in a terminal explored
|
||||
// state (done/blocked/exhausted) — graph_overview's done_intents_total, so the planner
|
||||
// knows recent_done_intents (capped at a recent window) is a truncated view and
|
||||
// stays cautious about "already tried" dedup. Excludes 'stopped' (killed/deleted),
|
||||
// matching exactly what recent_done_intents surfaces.
|
||||
func (s *ExplorationStore) CountFinishedIntents() (int, error) {
|
||||
var n int
|
||||
err := s.db.QueryRow(`SELECT COUNT(*) FROM exploration_nodes
|
||||
WHERE exploration_id=$1 AND kind='intent' AND state IN ('done','blocked','exhausted')`, s.expID).Scan(&n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// GetNode returns one node of this exploration by id (nil, nil if not found).
|
||||
func (s *ExplorationStore) GetNode(id int64) (*Node, error) {
|
||||
n, err := scanNode(s.db.QueryRow(`SELECT `+nodeCols+` FROM exploration_nodes WHERE id=$1 AND exploration_id=$2`, id, s.expID))
|
||||
|
||||
Reference in new issue
Block a user