docs: add learned-facet detail pass and session-window pitfall

Teach the agent to derive second-pass filters from first-pass evidence
  instead of pulling large message windows. Add the pattern and a pitfall
  warning against defaulting to LIMIT 25 transcript browsing.
This commit is contained in:
tommy0103
2026-06-07 18:35:08 +08:00
parent 700ca0bdd3
commit 0128881d04
3 changed files with 84 additions and 1 deletions
+1 -1
View File
@@ -138,7 +138,7 @@ Keep queries scoped, bounded, and structural.
- Treat project scope as three distinct semantics: exact `sessions.project` slug, exact `sessions.project_path`, or fuzzy `LIKE` search. Use `sql()` for exact slug/path membership; helper `project` means fuzzy `LIKE`.
- Start with cheap locators: `sessions()`, `summaries()`, `search()`, or a small SQL query.
- Expand incrementally with `context()`, `trace()`, neighbor SQL, or `raw()` windows.
- For conclusion, broad history, failure investigation, or file evolution questions, prefer one bounded query script that locates, expands, dedupes, groups, and returns compact evidence rows. Do not spend multiple conversation turns showing intermediate query results.
- For conclusion, broad history, failure investigation, or file evolution questions, prefer one bounded query script that locates, expands, dedupes, groups, and returns compact evidence rows. If a second detail pass is needed, derive its filters or facets from the first pass; do not dump whole session windows by default.
- Return compact evidence with stable IDs (`session_id`, `uuid`, `tool_call_id`, `run_id`, `agent_id`) and short snippets.
- Avoid `thread()` unless the user explicitly asks for a full transcript or all smaller probes are insufficient.
- Keep runtime JSON small, ideally under 10k-12k chars for synthesis tasks. Do not return all sessions, all summaries, all tool calls, complete workflow trees, full raw messages, or whole tool results.
+17
View File
@@ -125,6 +125,23 @@ the script:
Do not show every intermediate result to the conversation. Return the final
compact evidence view, then use the model for the conclusion.
## Session Windows Are Not Evidence Plans
After finding a relevant session, avoid defaulting to `LIMIT 25` or `LIMIT 40`
message windows. That is transcript browsing in miniature: it often brings back
thinking, transitions, and repeated context instead of the evidence needed for
the question.
Preferred detail pass:
1. extract candidate terms, files, tools, or decisions from the first pass;
2. query by learned facets inside the candidate sessions;
3. return 2-4 rows per facet, 8-12 rows total, with 160-220 char snippets.
If the vocabulary is still unclear, use a small session window as fallback:
5-8 rows per session, filtered by timestamp, role, or discovered terms when
possible, and explain the fallback in `query_plan`.
## Compact Vs Raw
Default to compact evidence. Raw/full access is a conscious escalation.
+66
View File
@@ -92,6 +92,72 @@ return {
};
```
## Learned Faceted Detail Pass
Use this after a broad sweep has identified candidate sessions and vocabulary.
Prefer detail facets learned from the first pass over pulling large session
windows. Fall back to small filtered windows only when the vocabulary is still
unclear, and record that reason in `query_plan`.
```js
const sessionIds = [
'first-pass-session-id-a',
'first-pass-session-id-b',
];
const learnedFacets = [
{ facet: 'architecture comparison', terms: ['ultrawork', 'TaskTree', 'parallel'] },
{ facet: 'key judgment', terms: ['ridiculous', 'serial', 'parallel'] },
{ facet: 'merge direction', terms: ['replan', 'merge', 'workflow'] },
{ facet: 'prompt observation', terms: ['prompt', 'guideline', 'skill'] },
];
const rows = [];
for (const { facet, terms } of learnedFacets) {
const clauses = terms.map(() => 'm.text LIKE ?').join(' OR ');
const params = [
...sessionIds,
...terms.map(t => `%${t}%`),
];
rows.push(...sql(`
SELECT
? AS facet,
m.uuid,
m.session_id,
s.title AS session_title,
m.timestamp,
substr(m.text, 1, 220) AS snippet
FROM messages m
JOIN sessions s ON s.id = m.session_id
WHERE m.session_id IN (${sessionIds.map(() => '?').join(',')})
AND m.text IS NOT NULL
AND (${clauses})
ORDER BY m.timestamp
LIMIT 3
`, facet, ...params));
}
const seen = new Set();
const evidence = [];
for (const row of rows) {
if (seen.has(row.uuid)) continue;
seen.add(row.uuid);
evidence.push(row);
if (evidence.length >= 12) break;
}
return {
query_plan: {
mode: 'learned_faceted_detail',
source: 'terms discovered in first pass',
session_count: sessionIds.length,
facets: learnedFacets.map(f => f.facet),
per_facet_limit: 3,
},
evidence,
};
```
## Facet Sweep For Broad History
Use this only for broad synthesis questions such as "how did X evolve", "what