✔ the role file loads and resolves through loadBusiness (7.929509ms)
✔ the shipped file is exactly the approved list (1.079892ms)
✔ the assistant's authority is message.send and record.write within role (3.298451ms)
✔ the assistant talks to the user and the chief of staff only, and no other shipped role is limited (1.020607ms)
✔ a business grant through limits does not widen the role (2.388552ms)
✔ a launch block whose by is the assistant is refused (2.451951ms)
✔ the instance takes no credential references and no tracker (3.928097ms)
✔ an arbiter whose role definition declares messaging lists is refused, for each kind (6.5876ms)
✔ an arbiter without messaging lists is accepted beside the limited assistant (3.512997ms)
✔ the contract passes work to the chief of staff and directs no one (1.057909ms)
✔ REQ-HARN-2: the assistant holds the web grant, and no other role file does (3.380536ms)
✔ config directory and file path follow MOSAIC_CONFIG (1.651392ms)
✔ the fixture business validates and comes back frozen (6.006836ms)
✔ two instances may share a definition (2.11792ms)
✔ top-level refusals (6.029439ms)
✔ arbiters and projects (8.407723ms)
✔ role instances (4.169441ms)
✔ Vikunja bots (11.377763ms)
✔ a role without Vikunja takes no tracker block (4.009778ms)
✔ credential references match the definition's services (7.455587ms)
✔ launch (16.05423ms)
✔ REQ-THREAD-2 REQ-LAUNCH-1 launch.threadIdleSeconds: absent is the default, a positive integer is used, anything else refuses (5.726951ms)
✔ loadBusiness: file checks (2.809678ms)
✔ loadBusiness: not a regular file (51.910285ms)
✔ loading writes nothing (1.254006ms)
✔ names that are Object.prototype properties don't count as declared (3.712369ms)
✔ the shipped example refuses as written and validates once filled in (0.835526ms)
✔ the role file loads and resolves through loadBusiness (9.270525ms)
✔ the shipped file is exactly the approved list (0.320488ms)
✔ the resolved record matches the approved list, so a widened file fails (2.67441ms)
✔ the chief of staff holds role.launch, message.send, role.end, organization.change, record.write and instance.name; every other action is gated (1.983325ms)
✔ the pm does not hold role.launch (2.149848ms)
✔ a business grant of a gated action through limits does not widen the role (3.651443ms)
✔ a limit that drops role.launch leaves the chief of staff with no launch block (1.578343ms)
✔ a launch block whose by is the pm instance is refused (3.575449ms)
✔ the contract names no duty to talk to the human and the pm contract no launch (0.717751ms)
✔ the instance takes no credential references and no tracker (3.893174ms)
✔ usage errors exit 4 (312.904362ms)
✔ validate: a good business exits 0 and prints instance digests (63.1198ms)
✔ validate: project files (309.036038ms)
✔ validate: missing files and a broken system config (235.425605ms)
✔ validate: credential reference problems exit 2 and name each one (63.717825ms)
✔ validate: a token file inside the repository is refused (64.757084ms)
✔ validate: role definitions come from MOSAIC_ROLES_DIR (188.697359ms)
✔ resolve: prints one instance's record (257.046546ms)
✔ resolve: refusals (361.53608ms)
✔ parse: exactly one of file or env, plus the service's date (3.380388ms)
✔ check: a good file has no problems (1.556167ms)
✔ check never opens the file: a write-only token passes (0.445777ms)
✔ check: file problems (1.181938ms)
✔ check: token files can't live in the repository or dataRoot, even through a linked directory (1.111565ms)
✔ check: dates and environment references (0.521178ms)
✔ each definition loads, with a contract file, and is exactly the approved list (5.675588ms)
✔ an organization file that declares them passes, and each resolves to least privilege (8.914833ms)
✔ the chief of staff launches each one; no other role does (5.52708ms)
✔ a C-suite role can't be made the launcher: launch.by must hold role.launch (2.659148ms)
✔ limits can narrow a C-suite role but never widen it (2.921008ms)
✔ any unknown key, tool, action or version in a role file is refused (0.970689ms)
✔ REQ-WAIT-1: GATED_ONLY is exactly the hard waits; the new actions are in the vocabulary (1.58579ms)
✔ REQ-ROLE-2: END_PROTECTED includes the assistant's thread definition (0.21425ms)
✔ REQ-WAIT-3: every action is routed or a hard wait, never both, and the routed list names only actions (0.231407ms)
✔ REQ-WAIT-3: instance.name is routed under REQ-MSG-2 (1.5), not a hard wait (row 141, sage-0589) (0.301259ms)
✔ REQ-WAIT-2: a role listing a hard wait at either class is refused; the actions that left can be granted (4.798816ms)
✔ row 165 read lists each instance and the definitions add accepts (15.583175ms)
✔ row 165 add: two instances join, validate exits 0, the log names the human, and the bus restart is reported (122.905071ms)
✔ row 165 change: definition, vars and launch membership log before and after; only a definition change asks for a restart (101.226825ms)
✔ row 165 refuses each validation failure and leaves the file's bytes alone (26.213424ms)
✔ row 165 refuses an added instance whose definition declares credentials, and says why (2.986015ms)
✔ row 165 refuses a definition change to or from one that declares credentials (3.8576ms)
✔ row 165 a vars or launch change on an instance with its binding succeeds and keeps the binding (73.570977ms)
✔ row 165 refuses an END_PROTECTED definition and every change to a protected instance (6.517957ms)
✔ row 165 refuses while a project file doesn't resolve, as validate would (13.631662ms)
✔ row 165 refuses a stale revision and leaves the file's bytes alone (9.660864ms)
✔ row 65 an instance write refuses harness-off, thinking-unsupported, an unknown model and a partial fallback (25.304252ms)
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (26.573518ms)
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (1.431373ms)
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (31.738142ms)
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (20.028677ms)
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (4.06586ms)
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (26.574335ms)
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.863974ms)
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (11.167016ms)
✔ Q169 assistants: vars and definition change and log the actor; tracker null leaves no tracker (20.144138ms)
✔ Q169 assistants: refuses other instances, other definitions, holder and credentials, empty entries, a tracker the definition has no credential for and a stale revision (17.674874ms)
✔ Q169 assistants: a definition with a vikunja credential takes a tracker change and refuses its removal or a used bot (11.542517ms)
✔ row 65 routes lists every instance with harness, model, thinking and fallback, the switched-on harnesses, the model keys and each harness's levels (2.090466ms)
✔ row 65 setRoutes saves a harness, model, thinking and whole fallback, reads each back from the file, logs the actor, and a null fallback clears all three (16.827369ms)
✔ row 65 setRoutes refuses a partial fallback, a switched-off harness, a level the harness doesn't apply, an unloaded module, an unknown model or instance, a malformed route, no change and a stale revision, with the file unchanged (19.850867ms)
✔ row 65 a file with harness vars and no plugins.harness loads and its views read; a model change still saves, and a route change refuses harness-off (8.841138ms)
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (16.740004ms)
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (45.755955ms)
✔ vikunja:19/309 a patch changes only the kinds it names; null removes one kind, explicitly and in the trail (33.308372ms)
✔ vikunja:19/309 an unknown kind (set or removed), a bad module, an empty patch and null on the wrong shape are refused, nothing written (2.574058ms)
✔ REQ-PLUG-1 REQ-ROLE-3 the writer checks the bytes it writes: a Date in plugins is refused there too (6.004927ms)
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (2.089948ms)
✔ vikunja:19/305 with an exists check, the setter refuses a module no tree file answers to, before anything is written (9.240242ms)
✔ optional project repo is preserved and must be a normalized absolute path (12.975208ms)
✔ loaded business project repo cannot be nested in any declared code checkout (4.11159ms)
✔ path and load (3.402714ms)
✔ refusals (2.008907ms)
✔ record.write is within-role for the eleven approved v2 agents, never gated-only (4.057795ms)
✔ systemVars flattens the validated config (2.94441ms)
✔ precedence: system, business, project, project role, agent (7.488558ms)
✔ limits narrow the definition and never widen it (3.867784ms)
✔ role.launch stays within-role only for the instance the launch block names (7.329824ms)
✔ limits.authority without role.launch leaves the launcher with no launch block (2.977002ms)
✔ limits.authority narrows cross-role actions too (1.429868ms)
✔ classify (1.237443ms)
✔ the record carries what the broker and launcher need (1.422183ms)
✔ digest: key order doesn't matter, any value change does (9.895786ms)
✔ refusals (2.41466ms)
✔ the four shipped version 2 roles load (4.369365ms)
✔ shipped role scopes match addendum B section 2 and the SR runbook (1.54727ms)
✔ shipped authority follows the note's table (3.397797ms)
✔ every role file in roles/ loads through the validator, and a v2 contract exists (1.48427ms)
✔ version 1 files keep loading with no authority (1.240896ms)
✔ the conductor policy isn't a role (0.265695ms)
✔ a missing role file is exit 4, a symbolic link too (0.522971ms)
✔ version 2 refusals (2.321145ms)
✔ authority: closed vocabulary, no gated-only action, no overlap (2.858323ms)
✔ messaging: optional, role definitions and human, never the tester (5.02576ms)
✔ credentials: Gitea scopes (1.017755ms)
✔ credentials: Vikunja scopes are a group-to-verbs map from the grantable list (1.17252ms)
✔ credentials: services (0.658901ms)
✔ contract: a non-empty regular Markdown file beside the role file (1.034747ms)
✔ the pm and the cto check a saved spec against settled decisions and work in flight, and answer with a BLOCK or an accept (5.410553ms)
✔ the chief of staff relays a BLOCK or an accept to the assistant as a reply to the message that carried it (0.713057ms)
✔ the assistant summarizes a spec review in its own words and doesn't repeat the chief of staff's text (0.650528ms)
✔ REQ-LIMIT-3 schema: each subject kind, limit 0 and no ceiling are accepted; bad limits, times, keys and undeclared instances refuse (12.434971ms)
✔ REQ-LIMIT-3 the writer stamps since: a new limit gets now, a changed one keeps its time, a different time is refused (48.648497ms)
✔ REQ-LIMIT-3 only tokens.* at schema depth holds token limits: agent limits named `limit` save as sent, and a token limit named `limit` is stamped and reset (46.793529ms)
✔ REQ-LIMIT-3 a reset moves since to now, is logged with its actor, and refuses a path that is not a limit (23.584123ms)
✔ REQ-LIMIT-2 schema: launch.account names a credential set; a daily quota needs a reset and an IANA zone and names the account (20.437174ms)
✔ REQ-LIMIT-2 the writer stamps a daily quota's since, keeps its reset and zone, and a reset moves since (21.600162ms)
✔ every key names known layers and a merge rule (0.707802ms)
✔ unknown keys and wrong layers refuse (0.626123ms)
✔ types (1.937988ms)
✔ merge: defaults, then the most specific layer wins (0.286392ms)
✔ merge: limits only narrow, and provenance lists each source (0.291005ms)
✔ merge doesn't change its inputs (0.130731ms)
✔ web.searxng takes https anywhere and http on loopback, so Jason's 127.0.0.1:8888 passes (0.267787ms)
✔ both definitions load, with a contract file, and are exactly the approved lists (2.296474ms)
✔ security-reviewer has no write or shell tool and classifies only the verdict as its own (4.432902ms)
✔ merge-gate's only grant is git.merge.protected cross-role, and it has no write tool (1.915404ms)
✔ neither role can be an arbiter: its messaging lists refuse the business file (row 133) (5.195025ms)
✔ every role contract carries the proactive line in its Authority section (0.671001ms)
✔ pm and chief-of-staff say where a raise goes under REQ-DEC-2 (0.509059ms)
✔ the merge landing takes two runs: merge-gate, cto and chief-of-staff each say their part (0.335527ms)
ℹ tests 148
ℹ suites 0
ℹ pass 148
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 1933.153192
