✔ config directory and file path follow MOSAIC_CONFIG (1.321193ms)
✔ the fixture business validates and comes back frozen (4.687127ms)
✔ two instances may share a definition (1.810628ms)
✔ top-level refusals (3.788242ms)
✔ arbiters and projects (5.242864ms)
✔ role instances (2.429966ms)
✔ Vikunja bots (5.470738ms)
✔ a role without Vikunja takes no tracker block (2.189017ms)
✔ credential references match the definition's services (2.398879ms)
✔ launch (6.863709ms)
✔ loadBusiness: file checks (1.564557ms)
✔ loadBusiness: not a regular file (35.048766ms)
✔ loading writes nothing (0.974609ms)
✔ names that are Object.prototype properties don't count as declared (2.575013ms)
✔ the shipped example refuses as written and validates once filled in (0.820943ms)
✔ the role file loads and resolves through loadBusiness (5.877368ms)
✔ the shipped file is exactly decision 104's list (0.584942ms)
✔ the resolved record matches decision 104, so a widened file fails (1.520389ms)
✔ message.send is within role and every other action is gated (1.581668ms)
✔ a business grant of a gated action through limits does not widen the role (1.116976ms)
✔ a launch block whose by is the chief-of-staff instance is refused (1.487857ms)
✔ the instance takes no credential references and no tracker (1.80515ms)
✔ usage errors exit 4 (257.995578ms)
✔ validate: a good business exits 0 and prints instance digests (67.096159ms)
✔ validate: project files (295.297719ms)
✔ validate: missing files and a broken system config (233.28047ms)
✔ validate: credential reference problems exit 2 and name each one (65.655802ms)
✔ validate: a token file inside the repository is refused (58.998863ms)
✔ validate: role definitions come from MOSAIC_ROLES_DIR (178.568189ms)
✔ resolve: prints one instance's record (185.33035ms)
✔ resolve: refusals (351.447287ms)
✔ parse: exactly one of file or env, plus the service's date (1.961373ms)
✔ check: a good file has no problems (0.676509ms)
✔ check never opens the file: a write-only token passes (0.262342ms)
✔ check: file problems (0.637505ms)
✔ check: token files can't live in the repository or dataRoot, even through a linked directory (0.621696ms)
✔ check: dates and environment references (0.448876ms)
✔ path and load (2.620814ms)
✔ refusals (1.233241ms)
✔ systemVars flattens the validated config (3.451177ms)
✔ precedence: system, business, project, project role, agent (4.169078ms)
✔ limits narrow the definition and never widen it (2.334135ms)
✔ role.launch stays within-role only for the instance the launch block names (5.40089ms)
✔ limits.authority without role.launch leaves the launcher with no launch block (1.549211ms)
✔ limits.authority narrows cross-role actions too (0.868372ms)
✔ classify (1.018188ms)
✔ the record carries what the broker and launcher need (0.911184ms)
✔ digest: key order doesn't matter, any value change does (5.172475ms)
✔ refusals (1.958311ms)
✔ the four shipped version 2 roles load (2.570572ms)
✔ shipped role scopes match addendum B section 2 and the SR runbook (1.150152ms)
✔ shipped authority follows the note's table (0.675188ms)
✔ version 1 files keep loading with no authority (0.937733ms)
✔ the conductor policy isn't a role (0.190986ms)
✔ a missing role file is exit 4, a symbolic link too (0.325947ms)
✔ version 2 refusals (1.428208ms)
✔ authority: closed vocabulary, no gated-only action, no overlap (1.745317ms)
✔ credentials: Gitea scopes (0.697614ms)
✔ credentials: Vikunja scopes are a group-to-verbs map from the grantable list (0.99846ms)
✔ credentials: services (0.479386ms)
✔ contract: a non-empty regular Markdown file beside the role file (0.595185ms)
✔ every key names known layers and a merge rule (0.700528ms)
✔ unknown keys and wrong layers refuse (0.618688ms)
✔ types (1.4323ms)
✔ merge: defaults, then the most specific layer wins (0.300338ms)
✔ merge: limits only narrow, and provenance lists each source (0.42645ms)
✔ merge doesn't change its inputs (0.170421ms)
ℹ tests 67
ℹ suites 0
ℹ pass 67
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 1758.099594
