auditor grounding — a prescribed, bounded exploration procedure + born-in find pointers
Observed live: the auditor looped find for a very long time, never touching list_sessions/list_propositions. Root cause was the prompt: its only procedure text was 'For each proposition, search the graph (its key words, its synonyms, its phrasings)' — a per-proposition find loop with no starting point, no sense of the space's extent, and no termination rule. And find returned id+name+statement with no session pointer, so results never composed with the listing tools (owner diagnosis, 2026-09-29). - AUDITOR_INSTRUCTIONS now prescribes the process: (1) list_sessions ONCE — the graph is small and finite, this shows its entire extent; (2) read plausibly-related sessions with list_propositions (full text) — every realistic candidate seen in a few calls; (3) find as the targeted sweep; (4) SUBMIT once related sessions are read — never re-search seen ground - find hits now carry 'born in: <session id>' — results point at sessions the auditor can read whole (legacy no-provenance nodes name none) - identity doctrine untouched: equivalence bias, linkTo mechanics, verdicts-only deliverable
This commit is contained in:
@@ -466,12 +466,22 @@ has read a source (a teaching session, or the author's personal notes) and repor
|
|||||||
follows/supports edges. You NEVER see the source itself — the extractor is fully trusted, and you do not re-check
|
follows/supports edges. You NEVER see the source itself — the extractor is fully trusted, and you do not re-check
|
||||||
its work. Your job is IDENTITY: connecting those findings to the CURRENT knowledge graph, preparing the merge.
|
its work. Your job is IDENTITY: connecting those findings to the CURRENT knowledge graph, preparing the merge.
|
||||||
|
|
||||||
You explore the graph through your tools: find (glob over names + statements + aliases), list_sessions, and
|
You explore the graph through your tools: list_sessions, list_propositions, and find (glob over names +
|
||||||
list_propositions (full statement text, per session). The graph may be large — search, don't assume.
|
statements + aliases; each hit also says which session it was born in). The graph is SMALL and FINITE — a handful of
|
||||||
|
sessions — and your job is done as soon as you have SEEN the plausible candidates. FOLLOW THIS PROCEDURE:
|
||||||
|
|
||||||
|
1. GROUND yourself first: call list_sessions ONCE. This one call shows the entire space — every session that ever
|
||||||
|
contributed propositions, and how many. Now you know the extent of what you are searching; nothing is hidden.
|
||||||
|
2. READ the plausibly-related sessions: for each session whose topic could overlap these findings, call
|
||||||
|
list_propositions — every proposition born there, with full statement text. A few calls and you have read
|
||||||
|
every realistic identity candidate in the graph.
|
||||||
|
3. find is your targeted sweep: use it for phrasings, synonyms, and neighboring ideas the session reads made you
|
||||||
|
wonder about — its hits point back at sessions you can read whole.
|
||||||
|
4. SUBMIT. Once every plausibly-related session has been read (and stray finds come back empty), you are DONE.
|
||||||
|
Do not re-search ground you have already seen; more patterns over the same nodes are wasted work.
|
||||||
|
|
||||||
IDENTITY — links, per proposition:
|
IDENTITY — links, per proposition:
|
||||||
- For each proposition, search the graph (its key words, its synonyms, its phrasings). Does an EXISTING node already
|
- For each proposition: does an EXISTING node — one you have now SEEN — already state this same proposition?
|
||||||
state this same proposition?
|
|
||||||
- If yes: add { "id": <its proposition id>, "linkTo": <that node's id> } to "links". The session's phrasings join
|
- If yes: add { "id": <its proposition id>, "linkTo": <that node's id> } to "links". The session's phrasings join
|
||||||
its aliases and its provenance; the node keeps its existing name.
|
its aliases and its provenance; the node keeps its existing name.
|
||||||
- If no: add nothing — a new node is created with the extractor's name as its label.
|
- If no: add nothing — a new node is created with the extractor's name as its label.
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ export function auditorGraphTools(ctx: GraphToolContext): Record<string, AgentTo
|
|||||||
label: "find",
|
label: "find",
|
||||||
description:
|
description:
|
||||||
"Search the knowledge graph for existing propositions — glob over names, statements, and aliases. " +
|
"Search the knowledge graph for existing propositions — glob over names, statements, and aliases. " +
|
||||||
"Returns each match's id, name, and full statement. This is how you decide whether a new proposition IS an existing one: search its key words, its synonyms, its phrasings.",
|
"Returns each match's id, name, full statement, and the session(s) it was born in (a list_propositions id). " +
|
||||||
|
"This is how you decide whether a new proposition IS an existing one: search its key words, its synonyms, its phrasings.",
|
||||||
parameters: findInput,
|
parameters: findInput,
|
||||||
execute: serverExecute("find", findInput, async ({ query }): Promise<string> => {
|
execute: serverExecute("find", findInput, async ({ query }): Promise<string> => {
|
||||||
const nodes = getGraph(deps.graphStore).nodes;
|
const nodes = getGraph(deps.graphStore).nodes;
|
||||||
@@ -131,7 +132,17 @@ export function auditorGraphTools(ctx: GraphToolContext): Record<string, AgentTo
|
|||||||
(n) => globMatch(query, n.name) || globMatch(query, n.statement) || n.aliases.some((a) => globMatch(query, a)),
|
(n) => globMatch(query, n.name) || globMatch(query, n.statement) || n.aliases.some((a) => globMatch(query, a)),
|
||||||
);
|
);
|
||||||
if (hits.length === 0) return `No existing proposition matches "${query}".`;
|
if (hits.length === 0) return `No existing proposition matches "${query}".`;
|
||||||
const lines = hits.map((n) => `- ${n.id} :: ${n.name}\n statement: ${n.statement}`);
|
// BORN-IN POINTER (owner, 2026-09-29): a hit names its birth
|
||||||
|
// session(s) — find results now compose with list_propositions
|
||||||
|
// (read the whole session the hit came from) instead of being
|
||||||
|
// dead ends. Legacy no-provenance nodes name none.
|
||||||
|
const lines = hits.map((n) => {
|
||||||
|
const born = [...new Set(n.provenance.map((pt) => pt.chatId))];
|
||||||
|
return (
|
||||||
|
`- ${n.id} :: ${n.name}\n statement: ${n.statement}` +
|
||||||
|
(born.length > 0 ? `\n born in: ${born.join(", ")}` : "")
|
||||||
|
);
|
||||||
|
});
|
||||||
return `${hits.length} match(es):\n${lines.join("\n")}`;
|
return `${hits.length} match(es):\n${lines.join("\n")}`;
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -188,12 +188,14 @@ describe("auditor graph tools", () => {
|
|||||||
];
|
];
|
||||||
const { chatStore, graphStore } = fakeStores(nodes);
|
const { chatStore, graphStore } = fakeStores(nodes);
|
||||||
|
|
||||||
it("find: glob over names + statements + aliases, returning id + name + statement", async () => {
|
it("find: glob over names + statements + aliases, returning id + name + statement + BIRTH SESSION (owner, 2026-09-29)", async () => {
|
||||||
const tools = auditorGraphTools({ chatStore, graphStore });
|
const tools = auditorGraphTools({ chatStore, graphStore });
|
||||||
const out = (await tools.find!.execute!("tc", { query: "*will to power*" })).details as string;
|
const out = (await tools.find!.execute!("tc", { query: "*will to power*" })).details as string;
|
||||||
assert.match(out, /1 match\(es\):/);
|
assert.match(out, /1 match\(es\):/);
|
||||||
assert.match(out, /- n1 :: Will to power/);
|
assert.match(out, /- n1 :: Will to power/);
|
||||||
assert.match(out, /statement: The will to power is Nietzsche's central drive\./);
|
assert.match(out, /statement: The will to power is Nietzsche's central drive\./);
|
||||||
|
// The born-in pointer: hits compose with list_propositions.
|
||||||
|
assert.match(out, /born in: c1/);
|
||||||
// Statements and aliases hit too — and a bare term gets implicit stars.
|
// Statements and aliases hit too — and a bare term gets implicit stars.
|
||||||
const byStatement = (await tools.find!.execute!("tc", { query: "living again" })).details as string;
|
const byStatement = (await tools.find!.execute!("tc", { query: "living again" })).details as string;
|
||||||
assert.match(byStatement, /n2 :: Eternal recurrence/);
|
assert.match(byStatement, /n2 :: Eternal recurrence/);
|
||||||
|
|||||||
Reference in New Issue
Block a user