feat(FN-3734): add heartbeat readonly gating and action-gate reload endpoin

Merges reloadable exempt-tools action-gate reload endpoint into the engine alongside a new heartbeat readonly-tools gating mechanism, plus a service worker first-install blank page fix. The engine gains a reload endpoint for action gates, permanent-agent gating exports, and comprehensive test covera

Fusion-Task-Id: FN-3734
This commit is contained in:
Fusion
2026-05-08 07:45:44 -07:00
committed by gsxdsm
parent 7a11a32aa0
commit ad34cb6c58
3 changed files with 25 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Fix permanent-agent tool gating so `fn_heartbeat_done`, `fn_send_message`, and `fn_read_messages` are treated as readonly/exempt and no longer require approval under permission-policy gating.

View File

@@ -24,6 +24,9 @@ describe("permanent-agent-gating", () => {
expect(classifyPermanentAgentToolCall("fn_research_run").category).toBe("network_api");
expect(classifyPermanentAgentToolCall("fn_task_show").category).toBe("none");
expect(classifyPermanentAgentToolCall("fn_research_get").category).toBe("none");
expect(classifyPermanentAgentToolCall("fn_heartbeat_done")).toEqual({ category: "none", recognized: true });
expect(classifyPermanentAgentToolCall("fn_send_message")).toEqual({ category: "none", recognized: true });
expect(classifyPermanentAgentToolCall("fn_read_messages")).toEqual({ category: "none", recognized: true });
});
it("uses only canonical action-category names", () => {
@@ -57,6 +60,20 @@ describe("permanent-agent-gating", () => {
expect(decision.disposition).toBe("require-approval");
});
it("allows recognized readonly heartbeat tools under permission policy", () => {
const decision = resolvePermanentAgentToolDecision({
toolName: "fn_heartbeat_done",
gating: {
permissionPolicy: {
presetId: "approval-required",
rules: {},
},
},
});
expect(decision.disposition).toBe("allow");
});
it("resolves disposition from policy for sensitive categories", () => {
const blockDecision = resolvePermanentAgentToolDecision({
toolName: "write",

View File

@@ -82,6 +82,9 @@ const READONLY_FN_TOOLS = new Set([
"fn_task_update",
"fn_task_log",
"fn_task_done",
"fn_heartbeat_done",
"fn_send_message",
"fn_read_messages",
]);
const MUTATING_GIT_SUBCOMMANDS = new Set([