import { test } from "node:test"; import assert from "node:assert/strict"; import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { main, readNotifyConfig } from "../src/cli.mjs"; import { CliError } from "../src/errors.mjs"; import { hostDir, hostFile, startTimeOf } from "../src/host.mjs"; import { broker, io, notifyConfig, tmp } from "./helpers.mjs"; import { writeJson } from "../../business/tests/helpers.mjs"; import { join } from "node:path"; const exitOf = async (p) => { try { await p; return 0; } catch (e) { if (!(e instanceof CliError)) throw e; return e.exitCode; } }; function setup(t) { const bus = broker(t); const dataRoot = tmp(t); const run = async (argv, x = io()) => ({ code: await exitOf(main(argv, x, { system: { dataRoot }, transport: bus.transport })), io: x }); return { ...bus, dataRoot, run }; } test("inbox lists only decisions routed to the human, with what approving authorizes and how to decide", async (t) => { const s = setup(t); s.raise("task.scope.change", { domain: "technical", target: "task-1" }); const gated = s.raise("git.push.protected", { target: "refactor", blocking: true, task_ref: "vikunja:1/7" }); const { code, io: x } = await s.run(["inbox", "--business", "demo"]); assert.equal(code, 0); const text = x.out.text; assert.match(text, /^inbox: 1 open decision\(s\)/); assert.match(text, new RegExp(`${gated.id.slice(0, 8)} git\\.push\\.protected \\(gated, blocking\\)`)); assert.match(text, /action: git\.push\.protected on refactor/); assert.match(text, /choosing "yes" authorizes it; any other choice declines/); assert.match(text, /task: vikunja:1\/7/); assert.match(text, new RegExp(`decide: mosaic decide ${gated.id.slice(0, 8)}