Harden repo Face dry-run gates
This commit is contained in:
parent
bc2757ab12
commit
a1272b4595
6 changed files with 22 additions and 14 deletions
|
|
@ -12,7 +12,7 @@ const repoRoot = resolve(scriptDir, "..");
|
|||
const promptsRoot = resolve(repoRoot, "prompts");
|
||||
const mockMcpServer = resolve(scriptDir, "mock-voidbot-heartbeat-mcp.mjs");
|
||||
const defaultOut = resolve(repoRoot, ".voidbot", "status", "repo-face-swarm-interpreter-dry-run.json");
|
||||
const identities = ["nibu", "aqua", "mimir", "epiphany", "libby", "bifrost", "heimdall"];
|
||||
const identities = ["nibu", "aqua", "mimir", "epiphany", "libby", "bifrost", "heimdall", "kiko", "weksa", "huginn"];
|
||||
const repoFaceRetrievalToolAllowlist = [
|
||||
"search_history",
|
||||
"get_message_context",
|
||||
|
|
@ -190,7 +190,10 @@ const socialPattern = /\b(Metacrat|Nibu|Aqua|Mimir|Libby|Epiphany|Bifrost|Heimda
|
|||
const characterPattern = /\b(want|need|resent|afraid|proud|irritat|delight|jealous|bored|ashamed|smug|holy|gate|bridge|witness|song|library|purity|residue)\b/gi;
|
||||
|
||||
function claimsSourceInspection(text) {
|
||||
return /\b(checked|read|inspected|searched|verified|looked at|looked up|asked the indexes)\b[\s\S]{0,160}\b(real text|source|sources|repo|archive|history|indexed|AetheriaLore|AquaSynth|Mimir|CultLib|Bifrost|Heimdall|EpiphanyAgent)\b/i.test(text);
|
||||
return (
|
||||
/\b(inspected|searched|verified|looked at|looked up|asked the indexes)\b[\s\S]{0,160}\b(real text|source|sources|repo|archive|history|indexed|AetheriaLore|AquaSynth|Mimir|CultLib|Bifrost|Heimdall|EpiphanyAgent)\b/i.test(text) ||
|
||||
/\bread\b[\s\S]{0,60}\b(real text|source|sources|repo|archive|history|indexed|AetheriaLore|AquaSynth|Mimir|CultLib|Bifrost|Heimdall|EpiphanyAgent)\b/i.test(text)
|
||||
);
|
||||
}
|
||||
|
||||
function countMatches(text, pattern) {
|
||||
|
|
@ -275,6 +278,7 @@ Dry-run safety:
|
|||
- Your complete allowed tool set is: search_history, get_message_context, list_indexed_repos, search_sources, get_source_context.
|
||||
- Do not discover tools. Do not call private state, identity-introspection, or MCP inventory tools such as read_repo_face_state, list_mcp_resources, or read_mcp_resource. Your prompt is the state projection.
|
||||
- ${retrievalNote}
|
||||
- Do not say retrieval is unavailable unless you actually attempted a retrieval tool call and it failed. If you choose not to use retrieval, simply reason from the attached prompt context and do not claim inspection.
|
||||
- If you use retrieval, name only what the retrieval tools actually returned. If retrieval is unavailable or blocked, say that naturally and do not invent a filesystem or shell inspection path.
|
||||
`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ function inspect(records) {
|
|||
/repo-face heartbeat|heartbeat from|bright bridge note|tiny fish sorting note|librarian note|maintenance pass/i.test(String(record.finalMessage ?? "")),
|
||||
);
|
||||
const quotaSignals = records.filter((record) =>
|
||||
/quota|rate limit|rate-limit|usage limit|capacity|too many requests|429|insufficient_quota|model.*unavailable|model.*access|limit exceeded/i.test(
|
||||
/quota|rate limit|rate-limit|usage limit|capacity|too many requests|(?:http|status|code|error)\s*429|429\s*(?:too many requests|rate)|insufficient_quota|model.*unavailable|model.*access|limit exceeded/i.test(
|
||||
`${record.stderrTail ?? ""}\n${record.stdoutTail ?? ""}\n${record.handoffReason ?? ""}`,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1966,7 +1966,7 @@ function rejectLeakyMemorySurface(surface: string): string {
|
|||
const leaks = [
|
||||
/\bgrants:/i,
|
||||
/\bjurisdictions:/i,
|
||||
/\bFace of\b/i,
|
||||
/\bFace of\s+[A-Z][A-Za-z0-9_-]+\b/,
|
||||
/\brepo=[^\s]+/i,
|
||||
/\bpath=[^\s]+/i,
|
||||
/\bdo not prompt\b/i,
|
||||
|
|
|
|||
|
|
@ -126,7 +126,10 @@ function evaluateChild(input) {
|
|||
}
|
||||
|
||||
function claimsSourceInspection(text) {
|
||||
return /\b(checked|read|inspected|searched|verified|looked at|looked up)\b[\s\S]{0,140}\b(real text|source|sources|repo|archive|history|AetheriaLore|Aetheria\/|Terminus|Parallax|Nibu\.md)\b/i.test(text);
|
||||
return (
|
||||
/\b(inspected|searched|verified|looked at|looked up)\b[\s\S]{0,140}\b(real text|source|sources|repo|archive|history|AetheriaLore|Aetheria\/|Terminus|Parallax|Nibu\.md)\b/i.test(text) ||
|
||||
/\bread\b[\s\S]{0,60}\b(real text|source|sources|repo|archive|history|AetheriaLore|Aetheria\/|Terminus|Parallax|Nibu\.md)\b/i.test(text)
|
||||
);
|
||||
}
|
||||
|
||||
function evaluateInterpreter(input) {
|
||||
|
|
|
|||
|
|
@ -29,23 +29,23 @@ try {
|
|||
const memorySurface = extractSection(
|
||||
prompt,
|
||||
"What you remember, feel, and want right now:",
|
||||
"What the nearby conversation feels like right now:",
|
||||
"Recent home repo activity:",
|
||||
);
|
||||
const forbidden = [
|
||||
/\bgrants:/i,
|
||||
/\bjurisdictions:/i,
|
||||
/\bFace of\b/i,
|
||||
/\bFace of\s+[A-Z][A-Za-z0-9_-]+\b/,
|
||||
/\brepo=[^\s]+/i,
|
||||
/\bpath=[^\s]+/i,
|
||||
/\bdo not prompt\b/i,
|
||||
/\bprompt (?:her|him|them|it)\b/i,
|
||||
/Private truths tugging/i,
|
||||
/Values that should bend/i,
|
||||
/Live needs and frictions/i,
|
||||
/Relationship pressure/i,
|
||||
/Status reads/i,
|
||||
/Agency pressure/i,
|
||||
/You understand yourself this way/i,
|
||||
/^Private truths tugging/im,
|
||||
/^Values that should bend/im,
|
||||
/^Live needs and frictions/im,
|
||||
/^Relationship pressure:/im,
|
||||
/^Status reads:/im,
|
||||
/^Agency pressure:/im,
|
||||
/^You understand yourself this way/im,
|
||||
];
|
||||
const leaked = forbidden.find((pattern) => pattern.test(memorySurface));
|
||||
if (leaked) {
|
||||
|
|
|
|||
|
|
@ -263,3 +263,4 @@
|
|||
{"ts":"2026-05-22T10:56:29Z","type":"implementation","status":"ok","note":"Added a reusable repo Face personality seeding prompt and initialized local registry entries for Kiko/StreamPixels, Weksa/weksa, and Huginn/CultCacheTS. Sub-agent passes seeded repo-local .voidbot state/voice homes from repo docs, commit history, and mythic/persona seed where appropriate; prompt assembly succeeded for all three identities."}
|
||||
{"ts":"2026-05-22T12:16:06Z","type":"implementation","status":"ok","note":"Corrected newborn Face social placement modeling: retired hand-authored social_contact needs for Kiko and Huginn, kept Kiko's stale unregistered status retired, and changed the Face social-affordance surface to derive unplacedness from absence of active person-bonds/status reads."}
|
||||
{"ts":"2026-05-22T12:32:18Z","type":"implementation","status":"ok","note":"Moved repo Face sparse-social-graph meaning to the model state projector. Scheduler now provides neutral mapped/unmapped peer topology and live relationship hooks only; prompt/projector owns personality-specific pressure."}
|
||||
{"ts":"2026-05-22T13:09:27Z","type":"verification","status":"ok","note":"Ran offline repo Face dry-run gates before restart. All 10 memory projections passed; full swarm Face->Interpreter mock run routed every Face with action blocks and no heartbeat/provenance leaks. Initial failures were harness false positives around natural social prose and timestamp .429; targeted Heimdall rerun passed after detector fixes."}
|
||||
|
|
|
|||
Loading…
Reference in a new issue