9 Commits
Author SHA1 Message Date
jason.woltje 4c8bf9ca4e fix(organization,cli): refusals name the file by label, never by host path
PR #1916 rule: a refusal names the field or file, never a config value
or a host path. readJsonFile's three refusals and parseJsonFileText now
name the file by its `what` label only. Callers whose label alone is
ambiguous add a name that already passed a strict pattern (business id,
role name, org id, turn id, project key) or a fixed path under the data
root. Exit codes, refusal codes and check order are unchanged.

organization: util, access, project, config-command, library-seats,
org-service deleteOrg receipt, agent-levels regex; T1 files role.mjs and
organization-config.mjs change only the readJsonFile label.
cli: access lock, accounts owner, host state/lock, notifier journal,
notify-config, run-evidence, dev-fixture, git-socket, org-bus, org-console.
discord: turn record label names the turn id.

Sentinel tests (sk-test-NOT-A-SECRET-1234 as a path component) cover each
changed refusal and fail on BASE; old path pins updated.
2026-11-11 01:04:15 -06:00
jason.woltje a8d9eecf65 organization: move packages/business to packages/organization (rename r2 stage B1)
git mv packages/business -> packages/organization (@mosaic/organization). The
old package stays as one-line re-export shims of each moved module, with
src/business.mjs re-exporting src/organization-config.mjs and src/cli.mjs
forwarding to the moved executable. BusinessError is OrganizationConfigError
(one constructor, name kept BusinessError); OrganizationError stays distinct.
The bus adapter gains organization-context.mjs (busOrganization), with
business.mjs (busBusiness) as the same function.

Import consumers, manifests, the lockfile, scripts/mosaic, stack-copy.sh
COPY_PATHS (both roots), seat sandbox RUNNER_FILES and the copy closure
walker (organization-imports.mjs, both roots required) move to the new path.
v1 serialization, v1 writers and the stage A fixtures are unchanged; the stage
A contract tests stay where they were and pass as before.
2026-11-09 11:47:48 -06:00
jason.woltje b5a58b48b4 feat(tasks): bind requirement and git admission to product scope (#1839) 2026-11-04 11:24:39 -06:00
jason.woltje 4e22bd49f9 test(git): disable detached fixture maintenance per mos-1369 2026-10-22 22:55:25 -05:00
jason.woltje 9f00397110 roles, harness, cli: a managed session gets its role's skills as prompt text on both harnesses (row 64, #1557)
Author and gate owner: Sage (mos-0855).

Role files take an optional skills list. The bundle reads each named skill
from <dataRoot>/skills-enabled, copies it into the bundle and renders every
file into prompt.md between skill-file markers, so the prompt text matches
the bundle copy byte for byte. The role's skills together are capped at
SKILL_BYTES (64 KiB): the claude adapter passes prompt.md as one argument,
and Linux caps one argument at 128 KiB. Symlinks are refused, not followed.
The launcher checks the list before a run exists: skill-not-enabled names
the activate command, anything else refuses skill-refused.

Pi keeps --no-skills; Claude Code keeps --disable-slash-commands and
--restricted. The two harness modules and MOSAIC_SKILLS are unchanged.
First lists: coder, reviewer, cto and pm, ms-unslop on each.
2026-10-19 16:11:36 -05:00
jason.woltjeandClaude Opus 5.5 f1ee9a9895 bus, business: agents land approved merges into the business working repository (row 137, #1631)
Row 137 round 4, Darkwing's candidate (agents/darkwing/work/queue-137/r4/,
build.patch 0cabe175, manifest 548ee477, 31 paths, base 63c82f1c4).
Filbert approved round 4 (comment 28809) and Dewey approved it (28816)
after round 3 changes (28801, 28805). Darkwing's round 4 ran 9/9 mutant
kills, bus 317, seat 150, land-work 86.

Round 5 is a rebase only (agents/sage/work/queue-137-r5/, build.patch
d6cbaaa8, manifest f73598fe). Row 150 changed docs/TOOLS.md, broker.mjs
and cli/README.md under it. The round 4 patch applied unchanged onto
435d1c616, and with index and @@ lines removed the two patches are
byte-identical. Filbert checked the interdiff (comment 28818).

A landing moves refs/heads/main in <dataRoot>/working/<business>/
<project>.git, never the project root or canonical refactor. The seed now
fetches the root as refs/heads/root and fast-forwards main only when it
is an ancestor, so a landed main survives the next push. Only a
cross-role merge decision lands. Its squash names the real channel:
"via the CLI" for the human, and "as its arbiter, via the broker" for an
arbiter's decision.resolve. Every other class refuses not-authorized
before the human check.

This carries row 139's two items. REQ-LAND-1: a gated merge decision
never lands. REQ-DEC-2: the host land op accepts an arbiter-resolved
merge. land-work's read.mjs stays human-only, and land-work.sh still
accepts only a human CLI resolution.

Sage's landing gate ran on 435d1c616 plus the candidate: 25 steps,
all rc 0 (15 packages, 10 script suites), 20:51:00Z to 20:55:34Z,
network sage-r137_default removed. Cherry-picked onto 5d98fb194, which
added only a docs/SESSIONS.md line.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 15:56:00 -05:00
jason.woltjeandClaude Opus 5.5 465bbdfbbc seat, cli, harness: git kill reach, close bound and host.lock (#1597)
Row 103, the row 100 follow-up. Built by Darkwing, packet
agents/darkwing/work/queue-103/r1/, candidate manifest
6e5ac8c0782bc595d7c0d711d457738ffb42f1ba5f38253912943dd55e55888a.
Sage approved on #1597, comment 28252; Dewey approved, comment 28260.

Host git runs through runGit: a detached group, SIGTERM at the limit,
SIGKILL after the grace, and one more SIGKILL to the group after a
signalled git closes. git-socket close() waits at most 2 s. startHost
claims bus-host/host.lock by hard link before the broker fork.
packages/cli/README.md and tests/host.test.mjs carry row 85's hunks
too; row 85 lands first.

Sage's gate rerun on 3a1e11b83 with rows 85, 102 and 103 applied,
Docker up: node suites bus 128, business 67, cli 165, control-board
124, conversation 182, discord 178, harness 73, ledger 78, mosaic 69,
queue 155, runs 43, seat 113, tasks 92, webui 108; scripts auth 15,
conductor 17, config 24, discord 66, extension-package 18,
foundation 44, queue 28, release 14, task 98. All pass, 0 fail.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 16:34:47 -05:00
jason.woltjeandClaude Opus 5.5 664199f794 cli, seat, harness: git socket hardening and refusal tests, row 100 (#1594)
Row 93 follow-up: SIGTERM then SIGKILL for host git, rollback-failed,
a total body deadline, fetch-aborted for a reviewer gone mid-fetch,
working refs first in have, and tests for five untested refusals.
Dewey approved in 28226 and Sage in 28225; Sage's full gate passed
16:57:32-17:01:32Z. The host side is live at the next bus restart.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:15:52 -05:00
jason.woltjeandClaude Opus 5.5 4da6815293 review loop: working repositories, git socket, push and review verdicts, row 93 (#1587)
Commits move as v2 bundles over bus-host/git.sock (decision 135). The bus
host keeps one bare working repository per business and project, seeds main
from the project root under a per-repository lock, fetches a pushed bundle
with fsck into a temp ref, requires history shared with main, and moves the
task's work ref only as a fast-forward. Host and runner git run with no
system or global config, hooks at /dev/null and local transports only. The
socket binds only for roles holding git.push.working or review.verdict.

The broker records a push as the action.allowed for git.push.working with
its commit, takes review.request for the latest push and one review.verdict
per request, and refuses task.close on a pushed task without an approve
verdict for the latest push. recordEvent reserves both shapes, so agents
can't forge either.

Reviewed by Dewey (28196) and Sage (28197), both approve. Gate on 7a729aef:
14 node suites and 9 scripts green.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 10:48:34 -05:00