roles: chief-of-staff role file, contract and tests, row 84 (#1578)

Lands the Haiku subagent build from agents/researcher/work/queue-84/r1/
(candidate manifest f72730de, base ac6b56ee). roles/chief-of-staff.json
and .md follow decision 104's list; packages/business/tests/
chief-of-staff.test.mjs covers the contract, and the business README
names the role.

Approved by Filbert (comment 28176) and Darkwing (comment 28183). Sage's
gate on 11bf4cb0 plus the patch: 14 node suites and all nine
scripts/test-*.sh green, 15:33:26-15:37:31Z.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-13 10:38:03 -05:00
co-authored by Claude Opus 5.5
parent 11bf4cb00a
commit 7be720fd72
4 changed files with 210 additions and 0 deletions
@@ -0,0 +1,133 @@
// The chief-of-staff role (lead decision 104, M1, row 84). The role file is
// policy: its tools, network, authority and credentials must equal the list
// Jason approved, so a widened file fails here. Fixtures live in a temp
// directory and nothing reads the real config.
import { test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { ACTIONS, BusinessError, classify, loadBusiness, loadRole, resolveInstance } from "../src/index.mjs";
import { businessDoc, REPO_ROLES, systemFor, tmp, writeJson } from "./helpers.mjs";
// Decision 104's list, as approved. A role file that differs from it fails.
const APPROVED = Object.freeze({
tools: ["read", "grep", "find", "ls"],
network: "api-only",
authority: Object.freeze({ withinRole: Object.freeze(["message.send"]), crossRole: Object.freeze([]) }),
credentials: Object.freeze([]),
});
// A fixture instance name. The shipped entry for Jason's business is `mos`.
const INSTANCE = "chief";
function refuses(fn, pattern) {
assert.throws(fn, (error) => {
assert.ok(error instanceof BusinessError, `expected BusinessError, got ${error}`);
assert.equal(error.exitCode, 2);
assert.match(error.message, pattern);
return true;
});
}
// Write a business file to a temp config directory and load it with
// loadBusiness. The file is the shipped four roles from businessDoc(), plus
// one chief-of-staff instance, with `mutate` applied after both.
function loadFixture(mutate = () => {}) {
const root = tmp();
const doc = businessDoc(root, "acme");
doc.roles[INSTANCE] = { definition: "chief-of-staff", holder: "mos" };
mutate(doc);
writeJson(join(root, "businesses", "acme.json"), doc);
return { root, business: loadBusiness("acme", { dir: root, rolesDir: REPO_ROLES }) };
}
function resolved({ root, business }) {
return resolveInstance({ system: systemFor(root), business, instance: INSTANCE });
}
test("the role file loads and resolves through loadBusiness", () => {
const fixture = loadFixture();
const role = loadRole(REPO_ROLES, "chief-of-staff");
assert.equal(role.roleVersion, 2);
assert.equal(role.name, "chief-of-staff");
assert.equal(role.contract, "chief-of-staff.md");
assert.equal(role.contractPath, join(REPO_ROLES, "chief-of-staff.md"));
const record = resolved(fixture);
assert.equal(record.definition, "chief-of-staff");
assert.equal(record.holder, "mos");
assert.equal(record.contract, join(REPO_ROLES, "chief-of-staff.md"));
assert.equal(record.launch, null);
assert.equal(record.tracker, null);
});
test("the shipped file is exactly decision 104's list", () => {
const raw = JSON.parse(readFileSync(join(REPO_ROLES, "chief-of-staff.json"), "utf8"));
const { title, ...rest } = raw;
assert.equal(typeof title, "string");
assert.deepEqual(rest, {
roleVersion: 2,
name: "chief-of-staff",
contract: "chief-of-staff.md",
...APPROVED,
});
});
test("the resolved record matches decision 104, so a widened file fails", () => {
const record = resolved(loadFixture());
assert.deepEqual(record.limits, {
tools: APPROVED.tools,
network: APPROVED.network,
authority: APPROVED.authority,
});
assert.deepEqual(record.credentials, {});
});
test("message.send is within role and every other action is gated", () => {
const record = resolved(loadFixture());
for (const action of ACTIONS) {
assert.equal(classify(record, action), action === "message.send" ? "within" : "gated", action);
}
assert.equal(classify(record, "message.send"), "within");
assert.equal(classify(record, "task.create"), "gated");
assert.equal(classify(record, "role.launch"), "gated");
});
test("a business grant of a gated action through limits does not widen the role", () => {
// limits.authority only narrows, so the grant has no effect and both
// actions stay gated. limits only narrow (resolve.mjs), so the grant has
// no effect; this asserts that, rather than a refusal.
const fixture = loadFixture((doc) => {
doc.roles[INSTANCE].vars = { "limits.authority": ["message.send", "task.create", "role.launch"] };
});
const record = resolved(fixture);
assert.deepEqual(record.limits.authority, { withinRole: ["message.send"], crossRole: [] });
assert.equal(classify(record, "task.create"), "gated");
assert.equal(classify(record, "role.launch"), "gated");
assert.equal(record.launch, null);
});
test("a launch block whose by is the chief-of-staff instance is refused", () => {
refuses(
() => loadFixture((doc) => {
doc.launch = { by: INSTANCE, instances: ["coder"], max: { sonnet: 1 } };
}),
/launch\.by names chief, whose role chief-of-staff doesn't hold role\.launch within-role/,
);
});
test("the instance takes no credential references and no tracker", () => {
refuses(
() => loadFixture((doc) => {
doc.roles[INSTANCE].credentials = { gitea: { file: "/x/token", rotateBy: "2099-01-01" } };
}),
/must reference exactly the services its role definition needs \(none; got gitea\)/,
);
refuses(
() => loadFixture((doc) => {
doc.roles[INSTANCE].tracker = { bot: "bot-acme-chief", botId: 7 };
}),
/has "tracker" but chief-of-staff uses no vikunja credential/,
);
});