Files
2026-11-12 05:06:03 +01:00

63 lines
3.8 KiB
TypeScript

// The tools of the forge module's state `failed-steps` (novox/hq design 47 §83, §84): the read of everything it holds, with the
// store's fill against its cap, and the one recovery, dropping a held key, written in the hand-act log before it is done.
import type { ToolDefinition } from "@novox/mesh-sdk/tools";
import { callerOf } from "@novox/mesh-sdk/callers";
import type { HandAct } from "@novox/mesh-sdk/views";
import type { FailedSteps } from "../failedsteps.js";
export function failedStepsTools(kept: FailedSteps, acts: (act: HandAct) => Promise<void>): ToolDefinition[] {
return [
{
name: "git_failed_steps",
description: "The failed required steps the forge module holds, by module and fingerprint, each with the run that failed it, the commits it was seen at and why; " +
"the `seen` keys (each commit's fingerprints, a commit's with `commit`); and the store's fill against its cap (design 47 §83, §487).",
input: { type: "object", properties: { commit: { type: "string", description: "only what names this commit" } } },
run: async (args: Record<string, unknown>) => {
const commit = typeof args.commit === "string" && args.commit !== "" ? args.commit : undefined;
const held = await kept.held(commit);
return { failed: held.failed.map((f) => ({ ...f, key: `${f.module}.${f.fingerprint}.${f.step}` })), seen: held.seen, fill: held.fill };
},
},
{
name: "git_failed_steps_drop",
description: "Drops one held key of the state failed-steps, a failed step by its key (<module>.<fingerprint>.<step>) or a seen key (seen.<commit>.<module>), with why; " +
"the head it refused merges. Written in the hand-act log first (design 47 §84).",
input: {
type: "object", required: ["key", "why"],
properties: { key: { type: "string", description: "the key, as git_failed_steps shows it" }, why: { type: "string", description: "why it is dropped, in plain words" } },
},
run: async (args: Record<string, unknown>) => {
const key = typeof args.key === "string" ? args.key.trim() : "";
const why = typeof args.why === "string" ? args.why.trim() : "";
if (!key || !why) throw new Error("git_failed_steps_drop names the key and why");
const by = callerOf(args);
try {
await acts({ what: `dropped the held ${key} of the forge module's failed-steps`, why: `${why} (${by})`, cause: "failed-step-dropped", verb: "git_failed_steps_drop" });
} catch (err) {
throw new Error(`the hand act was not recorded, so nothing was dropped: ${err instanceof Error ? err.message : String(err)}`);
}
return { dropped: await kept.drop(key), key, why, by };
},
},
{
name: "git_seen_expire",
description: "Deletes the seen keys of the state failed-steps that are more than 30 days old, the oldest first, at most 100: the removal the forge module does on each step-ended, now, with why. " +
"Written in the hand-act log first (design 47 §581).",
input: { type: "object", required: ["why"], properties: { why: { type: "string", description: "why it is run now, in plain words" } } },
run: async (args: Record<string, unknown>) => {
const why = typeof args.why === "string" ? args.why.trim() : "";
if (!why) throw new Error("git_seen_expire says why");
const by = callerOf(args);
try {
await acts({ what: "deleted the seen keys of the forge module's failed-steps past 30 days", why: `${why} (${by})`, cause: "seen-expired", verb: "git_seen_expire" });
} catch (err) {
throw new Error(`the hand act was not recorded, so nothing was deleted: ${err instanceof Error ? err.message : String(err)}`);
}
const deleted = await kept.expireSeen();
return { deleted, why, by };
},
},
];
}