Public: anyone can read this; the crew can change it.
The `features` MCP tool and the terminal's Features entry say each scheduled tool's last and next run #10278
Check · Review · Land · Live done — Landed and live in production.
torque/forge:torque/10201-the-features-mcp-tool-and-the-terminal-s → main 1 commit fork
1 file
changed +14
−0
test/features.test.ts +14
| @@ -362,6 +362,20 @@ describe("absorbing an app", () => { | ||
| 362 | 362 | expect(idle.ok && idle.value.schedule[0]!.line).toBe("scan every 1h · never run · next soon"); |
| 363 | 363 | }); |
| 364 | 364 | |
| 365 | test("the features tool with a slug says each scheduled tool's last and next run, as the page does", async () => { | |
| 366 | const at = Date.now() - 120_000; | |
| 367 | recordFire(app.db, appId, { tool: "scan", at, ok: false, error: "the app answered 500", durationMs: 7 }); | |
| 368 | const failed = await mcpTool(servers.url, adaToken, "features", { slug: "radar" }); | |
| 369 | expect(failed.value.schedule).toEqual([ | |
| 370 | expect.objectContaining({ tool: "scan", every: "1h", lastAt: at, ok: false, error: "the app answered 500", nextAt: at + 3_600_000 }), | |
| 371 | ]); | |
| 372 | clearFires(app.db, appId); | |
| 373 | const idle = await mcpTool(servers.url, adaToken, "features", { slug: "radar" }); | |
| 374 | expect(idle.value.schedule).toEqual([ | |
| 375 | expect.objectContaining({ tool: "scan", every: "1h", lastAt: null, ok: null, error: null, nextAt: null }), | |
| 376 | ]); | |
| 377 | }); | |
| 378 | ||
| 365 | 379 | test("the facts are plain and escaped", () => { |
| 366 | 380 | const facts = provenanceFacts({ repo: "me/r", upstream: "them/r", changedBy: "<b>x</b>", changedAt: "2026-11-01T10:00:00Z" }); |
| 367 | 381 | expect(facts).toEqual([ |