Commit Graph
4834 Commits
Author SHA1 Message Date
jason.woltje c66f1ec00c fix(webui): sp8 review round, an organization page starts its workspace read beside its own reads, a Dashboard tile with no figures read says so, the Organizations heading gets its jump target from secH (#1873, lane sp8-kpis) 2026-11-15 07:56:00 -06:00
jason.woltje 9400e0d94d feat(webui): sp8, the Dashboard leads with one row of figure tiles and an organization's page with its own, each a link to the page that lists what it counts (#1873, lane sp8-kpis)
The Dashboard's tiles are Agents working of all agents, Organizations running, Needs you, Open tasks,
Done this week and Projects, each added up only from the organizations whose reads gave it; a tile
names every organization it leaves out and why. The Sessions and Model spend tiles go: the first is
the Agents tile now, the second had no figure. An organization's page replaces its KPIs and Metrics
placeholders with Agents working, Open tasks, Needs you and Done this week for that organization,
each a link to the system page filtered to it, from one cross-organization read scoped to it. The
system Agents page's row building is shared so a tile's figure is that page's row count.
2026-11-15 07:33:21 -06:00
jason.woltje a9912983e6 fix(webui): sp7 re-check, a narrow pane wraps its header tools inside the pane, the project page's Review decision and request links keep the conversation's full view, Full view names its thread (#1873, lane sp7-polish) 2026-11-15 06:41:07 -06:00
jason.woltje 626321608f docs(webui): sp7, the Assistant's header comment names the links that keep the organization's own view (#1873, lane sp7-polish) 2026-11-15 06:28:40 -06:00
jason.woltje 5f965cdb30 fix(webui): sp7 review shots, a pane header keeps its title, Full view, Messages and close on one row with the organization and project below (#1873, lane sp7-polish) 2026-11-15 06:27:19 -06:00
jason.woltje 8296d33100 fix(webui): sp7 review round, each pane links its thread's full view in one plain click, a requirement's Open conversation keeps the organization's own view, the gated-pill assertion matches its text (#1873, lane sp7-polish) 2026-11-15 06:24:39 -06:00
jason.woltje 69ac78b97e fix(webui): sp7 shots round, a pane header keeps its close button on one line, and a thread that was not opened is said as a warning (#1873, lane sp7-polish)
- assistant.css: the pane title shrinks before the header tools wrap, so the close button stays on the title's line at 1440.
- assistant.js: paintNote draws the line under the lead; a refusal marks it data-refused and the line shows in the warning colour until the next change clears it.
- assistant-threads browser test: the refusal line carries data-refused, and closing a pane clears it.
2026-11-15 06:03:06 -06:00
jason.woltje a2a7df73df fix(webui): sp7 polish, a system page names itself once, thread links open as Assistant panes, each pane links its organization's messages, resume is a small control, Inbox class chips use words, a stopped organization's page has one restart (#1873, lane sp7-polish)
- A system page with nothing above it in the trail hides the trail that repeats its h1; drill-in trails stay.
- A project's thread link and each open-in-chat link add that thread as a pane on #/assistant. With three
  open, the first pane without an unsent message is replaced; when all three hold one, nothing is
  replaced and the page says why. Per-org chat addresses still work typed or pasted.
- "Messages in <org>" moves from the bar into each pane header as a link.
- The pane composer's Resume assistant is a small secondary control; behaviour unchanged.
- Inbox class chips read the one map of decision classes to words.
- Removes the unused pane, idPrefix and views params from projects.js and workspace.js; fixes the stale
  comment on the held-message status line.
- While an organization's bus is down, the header draws no bus control; the down banner's restart is the one.
2026-11-15 05:55:26 -06:00
jason.woltje 789e2bcdd4 fix(webui): sp6 third review round, a held message line stays steady between polls, only a pane's latest render decides the line, the held preview cuts on whole characters (#1873, lane sp6-threads) 2026-11-15 05:02:28 -06:00
jason.woltje 02df2a3a25 fix(webui): sp6 re-check notes, a held message is never overwritten or held out of sight, and a pane whose organization left the list does not promise it comes back (#1873, lane sp6-threads)
The held draft goes back only into an empty composer and is cleared only once it is in it. A thread
that reads without a composer shows the held message in the pane's line. Only a stopped or
unavailable bus says the message comes back when the pane reads again.
2026-11-15 04:57:37 -06:00
jason.woltje b982404963 fix(webui): sp6 review round, a stopped organization's pane stops reading and keeps its unsent message, an open pane picks up new replies on its own, a pasted thread id in any case shows its pane (#1873, lane sp6-threads)
A pane whose organization's bus is stopped or unavailable no longer polls or offers Refresh; it says
nothing is read until the bus starts again, holds any typed draft, and restores it untouched when the
bus returns. Unsent pane drafts now count for the organization-switch and Console-restart guards.
The Assistant sidebar item drops the Messages unread badge. "Start thread" is the primary action.
Tests cover the stopped pane's draft, a reply arriving with no refresh, and an uppercase show id.
2026-11-15 04:51:23 -06:00
jason.woltje 5dd940165d feat(webui): sp6, the Assistant page holds up to three threads from any organization side by side, with the open set in the address (#1873, lane sp6-threads)
The sidebar Assistant opens one system page, #/assistant. Each pane is the
chat thread view of its own organization: it reads, sends and updates
through that organization's routes, with a header carrying the title, the
organization chip, the project chip and a close control. "Open thread"
lists the threads of every answering organization, grouped by organization,
and starts a new thread in a chosen one. The open set and its order live in
the hash (open=org:id,...&show=org:id), validated on read. A stopped
organization is named at the top and in its own pane; the other panes keep
working. At 390 one pane shows with a tab strip.

Side by side is removed (panes.js, panes.css and its test); its old address
lands on the Assistant page.
2026-11-15 04:37:52 -06:00
jason.woltje ed4f45ed23 fix(webui): sp4 third review round, a move still writing never paints the board over the not-on-your-list page, an archived project keeps its filter while another filter matches none of its tasks (#1873, lane sp4) 2026-11-15 03:54:28 -06:00
jason.woltje 79df01f1de fix(webui): sp4 second review round, a project filter stays while its organization does not answer, a gone filter is cleaned only from the address its read started on, a read in flight never paints over the not-on-your-list page (#1873, lane sp4) 2026-11-15 03:54:28 -06:00
jason.woltje d7b98b4698 fix(webui): sp4, an organization's own task board with no filter on no longer says its tasks match the filters (#1873, lane sp4)
The scope's org= in the workspace read is where the board reads, not a filter, so the
count line and the empty state no longer treat it as one. Found in the retaken shots.
2026-11-15 03:54:28 -06:00
jason.woltje 0f29fe0d92 fix(webui): sp4 review round, one organization chip per card with its avatar, a filter that is gone leaves the address, an impossible organization address is not the system board (#1873, lane sp4)
- The card's organization chip carries the avatar in place of its dot; the bare avatar
  before it is gone (prototype shot 13).
- A filter naming an organization or project that is not on the list is dropped from the
  address after the render, and a dropped project reads again without its server filter.
- #/orgs/<id>/tasks with an id no organization can have says "This organization is not
  on your list." instead of showing every organization's tasks.
- The write check's comment and the test's fake say orgSetup is Console-wide today.
2026-11-15 03:54:28 -06:00
jason.woltje 32be3a01bc feat(webui): one task board for every organization, with organization and project filters in the address (#1873, lane sp4)
#/tasks is a system route that shows every organization's tasks on one board,
with the per-organization columns, organization and project chips on each card,
and the organization and project filters kept in the address. An organization
that did not answer is named first with its reason. A move or edit goes to the
row's own organization and is offered only where that organization's own config
takes task changes. #/orgs/<id>/tasks is the same board scoped to one
organization, and a card opened from the system board links to its task there.
A render replaced by a newer one now draws from that newer read instead of
throwing on an empty board.
2026-11-15 03:54:28 -06:00
jason.woltje f97e0d3aeb fix(webui): sp5 re-check notes, a late named Fire leaves a newer Fire's busy state alone, the picked agent row gets the left bar, tests for the picked agent with the state filter and a refused scope (#1873, lane sp5) 2026-11-15 03:32:32 -06:00
jason.woltje eebdb2f0ce fix(webui): sp5 review round, Open addresses the agent and the scoped page marks it, Fire words name the organization, a named Fire keeps its outcome, Cancel restores focus (#1873, lane sp5)
- Open on #/agents goes to #/orgs/<id>/agents?agent=<key>; the scoped table puts that agent first,
  marks it (aria-current) and draws no Open or Actions column (review F1, F2).
- Fire's aria-label, confirm group and receipt use the organization's label (F5).
- A Fire sent to a named organization keeps its receipt after the opened organization changes (F7).
- Cancel moves focus back to the row's Fire (F10).
- agentsPage refuses a scope that is not an organization id instead of listing every organization (F11).
2026-11-15 03:26:18 -06:00
jason.woltje 5373b110ac feat(webui): one Agents page for the whole system, with organization and state filters, Fire sent to the row's organization (#1873, lane sp5)
#/agents lists every organization's agents in one table: name, role, state,
what each works on, organization and project chips. Org and state filters
live in the hash query. A stopped organization is named at the top. A row
opens the agent in its organization; Fire is drawn only where that
organization's own config lets this Console decide, and posts to that
organization's hire route. #/orgs/<id>/agents leads with the same table
scoped to one organization, above the levels grid and held roles. A hired
agent reads as Hired (or Hired from pack X) with its org:hire id as
secondary text. The sidebar and dashboard Agents links open the system page.
2026-11-15 03:13:54 -06:00
jason.woltje 3885f4628b fix(webui): sp3 second review round, #/inbox keeps the system theme, hire links follow each organization's own decide (#1873, lane sp3) 2026-11-15 02:09:04 -06:00
jason.woltje ba9933309b fix(webui): sp3 review round, answers from the system Inbox read route_to and show who raised them, the hire form is linked, the sidebar count stays system-wide (#1873, lane sp3) 2026-11-15 01:10:13 -06:00
jason.woltje 0785af8129 feat(webui): one Inbox for the whole system, with organization filters and answers pinned to the row's organization (#1873, lane sp3)
#/inbox lists every answering organization's decisions from the one GET /api/workspace read, newest
first, each row with its organization chip and a project chip when it has one. Organization and
type filters live in the hash query. A stopped organization is named at the top with its reason.
An answer from the list reads and posts to the row's own organization (/api/orgs/<org>/...), never
the one opened last, and each item can be opened in its own organization. #/orgs/<id>/inbox is the
same list filtered to that organization. No server route was added.
2026-11-15 01:10:13 -06:00
jason.woltje d1b01329bc fix(webui): sp2 polish, an organization's bare address opens its page and the dashboard keeps the system theme (#1873, lane sp2)
- #/orgs/<id> with no page and no trailing slash now opens #/orgs/<id>/organization instead of the
  system dashboard.
- The system dashboard resolves its own appearance (this browser's choice made
  there, else the default) under mosaic-console-appearance-system; it no
  longer shows the theme of the organization opened last.
- A stopped organization's page shows one bus banner: the page's own down
  banner now carries the restart action, and the shell's "Bus unavailable"
  banner hides on that page (display.js paintBus and app.js busDown).
- The dashboard row for a stopped organization no longer repeats "the bus is
  not running" under "bus stopped"; the last start time still shows.
- Organizations table figures keep to one line (white-space, no font change).
- The Active agents status cell was class "st", which picked up the global
  .st::before "?" glyph; it is now ws-st.
- Tests: red-first browser tests for each item, plus the test sp1 lacked: a
  read still in flight at an organization switch keeps nothing.
- org-switch-browser: a stopped organization's page asserts one banner; the
  shell's "Bus unavailable" is checked on its tasks page instead.
2026-11-15 00:44:18 -06:00
jason.woltje c7aecbffa9 fix(webui): sp1 second review round, a read or file save in flight at a switch keeps nothing (#1873, lane sp1)
The second review found two paths the first fix round left open.

- The project-file save captures orgEpoch before its POST. When a switch
  happened meanwhile, it neither paints nor announces the old file's
  outcome on the new organization's page. An opaqueredirect still signs out.
- A live read (reader, get.api), the palette's inbox and tasks reads and
  the board poll keep their answer in `last` only while the organization
  they were sent for is still open. A later cached render on the new
  organization no longer draws the old one's rows.

single-pane test 11 holds acme's file save across a switch to beta and
asserts nothing is announced: red on the previous bus.js ("Saved as commit
cccccccccccc."), green now. The kept-read guard has no browser test.
2026-11-14 23:51:59 -06:00
jason.woltje bb2f79f3d9 fix(webui): sp1 review round, a switch carries nothing across and first run keeps its board (#1873, lane sp1)
- First run (no organization yet) keeps #/ as its board; the router no longer rewrites it to
  #/dashboard, which first run cannot draw.
- An organization switch stops the agents section's request poll and clears what it held. A
  route-change restart chain finishes on the organization it started in.
- A write in flight at a switch drops its answer: an org epoch in bus.js, checked after each
  await. The switch clears every busy flag, receipt and reply, and the doc drafts.
- The bus banner reads org state again only when the route crosses /dashboard, not on every
  hashchange inside one organization.
- The down banner does not repeat its heading as the reason.
- Tests: first run wordmark, poll stop on switch, restart pinned to its organization, settings
  save in flight at a switch, banner without a repeated reason. The org-switch test comment and
  wait match the in-place switch.
2026-11-14 23:19:05 -06:00
jason.woltje e24e7e93a2 feat(webui): one shell, a system dashboard, organization pages as drill-ins (#1873, lane sp1)
#/dashboard is the system landing route: one row per organization with its bus
state, agent count (organization files), project count and needs-you count,
each only when a read gave it, and active agents. Opening an organization from
the sidebar or a dashboard row is a route inside the same page: no reload, a
Dashboard / <organization> breadcrumb, and later /api reads scoped to it through
the existing fetch wrapper, whose organization is now a variable the router sets
(mosaic-org-switch event). #/orgs/<id>/... stays the address. An organization
whose bus is down says so on the dashboard and on its page, with the reason the
workspace read gives.
2026-11-14 22:35:00 -06:00
jason.woltje 387f73a7a4 fix(harness): r127 review round, only a shell's own not-found line names a program (#1873, lane r127)
Review P3-1: a "No such file or directory" line from another program
(cat, ls) no longer counts. Only bash's "line N:", dash's "N:" and env's
quoted form do.
P3-2: a name with a run of 16 letters and digits looks like a key, so it
stays in the run's private stderr instead of the reply.
P3-3: a 16 KiB stderr window that starts mid-file drops its partial first
line, so a cut name ("aude") isn't reported.
P3-4: CRLF lines read the same as LF lines.
P3-5: tests for the name check (tokens without spaces, key-shaped names),
for a cat line, and for the window boundary through the runner.
2026-11-14 21:19:02 -06:00
jason.woltje 61371adb10 fix(harness): an adapter exit 127 names the program that wasn't found (#1873, lane r127)
A claude-code turn on a Console started without MOSAIC_CLAUDE_BIN failed
with a bare "adapter exited 127". The sandbox binds /usr, so the wrapper
/usr/bin/claude is visible, but its exec target /opt/claude-code/bin/claude
isn't bound, and the shell exits 127.

On exit 127 the runner now reads the tail of the turn's stderr, finds the
shell's "not found" line (bash, dash, env) and adds the program's basename:
"adapter exited 127 (command not found: claude)". It never shows a host
path or anything that isn't a plain program name; a 127 without such a
line keeps the bare reason.

The deploy side (MOSAIC_CLAUDE_BIN on the Console unit) is a Lead-owned
script change, written up in the lane report.
2026-11-14 21:07:14 -06:00
jason.woltje b913f0f4c8 fix(bus,webui): pr2 review round, WebUI receipt carries routeFrom, design note, member and project tests (#1873, lane pr2)
The WebUI packs receipt passes routeFrom through on each hire line; the WebUI
README and TOOLS.md name it. The starter packs design doc gets a dated note
for the 2026-11-14 route ruling. New bus tests: a member pack hire on the
assistant route marks hired and awaiting-owner lines routeFrom assistant, and
a project pack with no chief route hires into the project on the assistant's
harness and model.
2026-11-14 18:37:28 -06:00
jason.woltje bfd2cc5e79 fix(bus,cli,webui): a pack hire falls back to the org assistant's harness and model (#1873, lane pr2)
pack.state gave a pack hire only the chief of staff's resolved route, so an
org whose chief has no model refused every hire pack-hire-route-missing. The
route is now the chief's (launch.by), else the org assistant's (the instance
whose definition is assistant; the one named assistant when there are several,
else the first in key order), else null. Both resolve through resolveInstance,
need harness and model, and carry thinking when set. pack.state adds routeFrom,
and each hired or awaiting-owner receipt line carries it. Refusal next step,
CLI hint, WebUI hire reason and the bus, CLI and TOOLS docs say the refusal now
means neither has a route.
2026-11-14 18:32:01 -06:00
jason.woltje 3e53af3941 fix(bus,webui): pd review round, supersede after apply, one pack hire loop per org, hireError, fromPack (#1873, lane pd)
Review pd-review.md (changes 6). Fixed:
- P2#2: the owner's pack hire withdraws a pack-raised inbox decision only
  after its replacement hire applied; a replacement that refuses (route
  missing, prepare refusal) leaves the old decision open in the inbox.
- P3#3: an apply whose hire loop throws after the apply committed still
  answers the apply receipt, with no hires and the code as hireError; the
  route passes a code through and the card says the hires did not run.
- P3#5: the packs read marks an awaiting-owner line this pack's own hire
  raised fromPack: true; the owner's card counts it in "Hire the N".
- P3#6: one pack hire loop per business; a second refuses
  organization-busy and raises nothing.
- P2#1 docs: TOOLS.md and the bus README say no member surface calls
  pack.hire.console yet (the member surface is a recorded follow-up).

Deferred: P3#4 project agents naming their pack (projectUnion is shared
with the runtime).
2026-11-14 16:09:46 -06:00
jason.woltje 359b3299b4 feat(bus,cli,organization,webui): applying a starter pack is the hire decision (#1873, lane pd)
Ruling 2026-11-14: a person's pack apply records one hire decision per
proposed hire and applies it in the same act, through the hire-decisions
path, with the evidence an inbox approval leaves.

- bus: pack.apply.console runs the pack hire loop; pack.hire.console hires
  an applied record's open proposals. The owner's apply approves flagged and
  credential lines; a member with org.hire gets the unflagged hires and the
  rest open as awaiting-owner decisions; an agent apply still refuses
  human-required. Project packs hire into projects.<p>.agents. Nothing is
  hired twice. Credential lines are approved, not bound. New refusal codes
  pack-not-applied and pack-hire-route-missing. The instances read names the
  pack each hire came from; the packs read lists hired agents and open
  proposals with reasons.
- organization: pack.hire.console maps to org.hire; instances carry
  hireDecision.
- cli: mosaic org pack hire ID PACK [--project P]; apply prints the hires.
- webui: pack card shows N agents hired, open proposals with reasons and
  "Hire the N proposed agents"; Agents and organization pages redraw on
  mosaic-org-changed; agent cards say "from pack X"; Fire (not on the chief
  or assistant) removes the card at once with a receipt.
- docs: design doc section 3 dated note, TOOLS.md, package READMEs.
2026-11-14 15:40:10 -06:00
jason.woltje 65f7288cea fix(webui): template save maps the new template-exists refusal to 409, not outcome-unknown (#1873)
f6c added template-exists for a save under a taken name. The template
route had no entry for it, so a duplicate save answered 503
outcome-unknown. Map it to 409 and move the SP8 pin.
2026-11-13 20:14:49 -06:00
jason.woltje 211b32ef1a fix(cli): f6c re-check, a failed released-marker write still removes the start lock; docs name the new warning and code (#1873) 2026-11-13 20:14:21 -06:00
jason.woltje 163972e08e fix(cli): f6c review round, released start locks, ENOENT and path cut (#1873)
P3-1: releasing a console start lock marks it released through its own
descriptor and removes the path only while it is still that file; a
released lock put back by a racing clear is cleared by the next start or
stop.
P3-2: org definitions reports unknown-organization only when the
organization file itself is missing; another missing file names the
operation.
P3-3: the path cut also covers a path after ':' or inside backticks.
2026-11-13 20:14:21 -06:00
jason.woltje 23e504f331 fix(cli,bus,organization): E2E6 lane f6c, refusal lines name the next step (#1873)
1. Stale bus host lock refusals from bus status, start, stop and restart
   name mosaic bus recover ORG.
2. org definitions: unknown org, unknown or malformed name and bad id give
   one refusal or usage line, no stack trace, no host path.
3. Pack, board and workflow refusals print their hint as template save does;
   tested with the real CliError transport shape.
4. console start and stop clear a console/start.lock whose named supervisor
   (pid and start time) is gone; a live or unnamed holder refuses.
5. Template save keeps free text verbatim and writes no placeholders; the
   preview lists each field that mentions an org-specific name.
6. A request the shim never sent (no socket, connect refused) exits 5 and
   the CLI reports bus-not-running with the start and recover line.
7. autonomy-precondition carries the check that failed, including on the
   hire paths.
8. Saving under an existing template name refuses template-exists with a
   next step; refusal table entry added, channel-proof pins moved.
2026-11-13 20:14:21 -06:00
jason.woltje 23b5e24ebc fix(webui): E2E6 re-check round, consumed-decision wording, autonomy focus and read errors (#1873)
Re-check finding 1 (P2): the wording for refusals that can come after the
decision is consumed told the user to look for the proposal "as answered"
in the inbox and otherwise read "nothing was applied". The bus inbox lists
no closed decision, so a consumed one drops out of it and the user would
read the false claim. Those codes now say only that part of it may already
be applied and to check the Agents page. decision-http tests assert no
"nothing was applied" in any case and no inbox pointer for those codes.

Re-check P3-b: the autonomy controls (Save, Discard, notices, review
summary and buttons) carry data-focus-key, so a focused button in a clean
form gets its focus back after the poll repaints the section.

Re-check P3-c: a failed autonomy read keeps the last read only while the
page holds the form (dirty, or focus inside it). A clean form shows the
read error. org-live-edit-browser test 4 covers both.

Re-check P3-a (harness-off after the consume through a corrupt prior
settings file) is deferred: wording it exactly needs the bus to mark the
phase on the refusal.
2026-11-13 20:05:10 -06:00
jason.woltje 266f3a45ff fix(webui): E2E6 review round, apply-phase refusals, held sections, tab fade, header pins (#1873)
Review finding 1: a hire start refusal the apply step can also raise after the decision is
consumed (decision-stale, organization-instance-*, organization-refused, definition-missing,
invalid-request and the rest) no longer says "Nothing was applied". It says that part may be
applied when the inbox shows the proposal as answered, and to check Agents first. Only codes
that prepare() or the route checks alone raise keep "Nothing was applied".
Review P3: a failed workflows or autonomy read keeps the last good read, so an open editor or
a dirty form stays through it. Focus holds a section only in a field being typed in; a focused
button is rebuilt and gets focus back by data-focus-key. Autonomy has Discard changes. The
project tab fade is 0px when every tab fits.
s8 and s9 header pins at 1440 now measure from the content edge: 1418 was 100vw-based, ran
under the page scrollbar and is the P2-11 clipping itself.

Correction to the previous commit's message: P1-2 is the unknown project, agent or harness
wording; P2-4 names the refused field; P2-6 is the Queue refusal reason; P2-8 is "bus stopped".
2026-11-13 19:52:26 -06:00
jason.woltje 0c35eeed9d fix(webui): E2E6 round, live edits survive refresh, org page layout, decision refusals (#1873)
P1-1 an open workflow editor, a dirty autonomy form and a pack's picked project keep their
node, draft and focus across the 10-second poll and an org-changed repaint.
P1-2 decision-http names the refused field and keeps the bus code and detail.
P1-3 long editors span the full width below the org page split.
P2-1 workflow roles resolve as definitions, templates and human; P2-2 a pack apply re-reads
workflows, autonomy and board and keeps its receipt; P2-3 pack preview fits its column;
P2-4 unknown project, agent or harness say so instead of outcome-unknown; P2-6 a stopped bus
reads "bus stopped"; P2-8 Queue says why it is unavailable; P2-9 pane settings values are not
clipped; P2-10 spend wording; P2-11 project header stays in its column; P2-12 project tabs
fade at the edge until scrolled to the end; P2-13 Restart bus and Stop bus line up in panes;
P2-15 backticks in chat text render as code.
Minor: Same-as commands wrap between words; harness checkboxes share a row.
Tests: org-live-edit-browser, e2e6-layout-browser, chat-replies and decision-http additions.
2026-11-13 19:24:48 -06:00
jason.woltje e6ab8bc1fd feat(bus,plugins,organization,cli,webui): SP9 remove system types outright, bus schema 3v-3w drops project_system_types (#1873)
Jason's 2026-11-12 ruling: the only deployed system is the dev environment on
dragon-lin, so the system-type plug-in kind goes with no retired kind, fence,
conversion or new refusal code.

- plugins: system-type leaves KINDS; system-types.mjs and the five modules are
  deleted. An org file naming the kind refuses unknown-kind.
- organization: the plugins.system-type check, systemTypesFence and the
  system-types.console right are removed.
- bus: system-types.console, project.system-types[.set], the system-type half
  of the tester check, the runtime reads and system-type-not-enabled are
  removed. Step 3v-3w drops project_system_types, its index, its four guards
  and its rows; SCHEMA_VERSION is 3w (32 tables, 126 triggers, 5 views).
- cli: mosaic org system-types and mosaic project system-types[-set] are
  removed; stack-release COUNTED and the budget supervisor's closed list move
  to 3w.
- channel: the project.system-types verbs are removed.
- webui: the System types page, route, dashboard row, chips and project
  selection are removed.
- docs: REQ-SYS-1/2 now describe starter packs; README system-type text and
  the requirements titles follow.
2026-11-12 21:02:46 -06:00
jason.woltje 0251acdad9 fix(packs): SP8 re-check, close before unlink cannot skip it; check the whole reason before the cut (#1873) 2026-11-12 20:05:32 -06:00
jason.woltje 13560660ae fix(packs): SP8 review round, single-pass placeholders, CLI hints, pins (#1873)
- template-save: one alternation pass replaces every literal, so an
  instance named root, org or agent never rewrites a placeholder already
  written in. checkPack's refusal message is passed on as the reason. A
  write or fsync failure removes the partial file it created.
- broker #templateFail drops a reason the credential check refuses.
- cli template words: humanTransport throws a CliError named by the bus
  code; a known code now gains its hint (the test transport throws the
  same CliError).
- template-http: the header notes serve.mjs strips /api/orgs/<id>.
- pins: the two .console verbs in console-decide and request-console;
  the packages/business/src re-export for template-save.mjs.
- tests: placeholder collision, a held-value key masked as [key], and a
  save after a real pack.apply.console keeping {id, version}.
2026-11-12 20:05:32 -06:00
jason.woltje 08e50e513f feat(packs): the owner saves an organization's shape as a template (#1873 SP8)
template-save.mjs captures the org (or one project) as a starter-pack JSON under
<config>/templates/<owner>/<name>.json: copy material and instance credentials
stripped, role credential request lines kept, owner/org/project/agent/root names
replaced by placeholders in free text, at most 8 hires, packs entries {id, version}.
A held credential value in kept text refuses template-secret-suspected naming the
field path. Preview then save with the preview's digest; O_EXCL 0600 write, a
second save refuses.

Bus: template.save/template.list for the owner's CLI cap, .console names for the
owner's Console cap, null in VERB_RIGHTS. CLI: mosaic org template save|list.
Console: GET /api/templates, POST /api/templates/preview, POST /api/templates.
2026-11-12 20:05:32 -06:00
jason.woltje a9d72b3cd1 fix(business): CB5 old-path re-export for copy-binding-status.mjs, the rename r2 B guard (#1873)
Every packages/organization/src module has a one-line re-export at its old packages/business/src
path; the CB5 status table had none, so rename-b-identity refused it.
2026-11-12 19:19:23 -06:00
jason.woltje 4b35e3c1d2 fix(bus): CB5 re-check, a running or failed revoke outranks copy-service-unbindable; unbind summary tested (#1873)
- copy-launch status(): a fenced or closed copy falls through to the gate check, so the owner
  sees credential-revoking or credential-revoke-failed for a binding issued to a copy whose role
  also needs a service a copy cannot bind.
- copy-bindings: an unbind raise reads change 'unbind' in the raise answer, every inbox and trail.
2026-11-12 19:19:22 -06:00
jason.woltje 56aeefb370 fix(bus,webui,cli): CB5 review fixes, binding summary on the inbox, raise and trail reads, copy-service-unbindable status, Console allowlist (#1873)
- broker: the hire.raise answer, the inbox console preview and the trail read carry a
  binding as {instance, change} only; the raise event keeps the full proposal the resolve reads.
- copy-launch status(): a copy whose role needs a service a copy cannot bind reads
  copy-service-unbindable (new fixed status text) instead of a gitea binding step.
- cli instances: an unbound copy's line names its missing services.
- webui serve: the instances verb rebuilds each copy binding from the fixed status table.
- bus.js reads the binding change field only.
- browser tests: system Chromium starts with --disable-extensions; the A3 booted-bus test passes it.
2026-11-12 19:19:22 -06:00
jason.woltje fdbc34413b feat(webui,bus): CB5 Console operator flow, binding confirmation and next steps, copy binding status on the Agents grid (#1873)
The bus instances read adds a copy's binding status only when the copy was
bound at boot or is unbound for want of a bindable service, never to a
tester. decision-http returns an allowlisted binding (instance and change)
on a binding confirmation and fixed next-step text on an approved resolve
and on a binding hire start. The decision page names the copy and the
change; the receipt shows the next step; the Agents grid shows can't launch
with the binding's next step. Every new string is fixed text.
2026-11-12 19:19:22 -06:00
jason.woltje c5bf71ab08 feat(bus,cli): CB5 operator status, each copy's binding status and next step in the owner's instances read and mosaic org instances (#1873)
The launch gate's status() runs the same checks a launch runs, without the loss report, and
answers a fixed { status, next } from organization copy-binding-status.mjs (design section 6
texts plus issue-required and ready). A tester's read never carries it.
2026-11-12 19:19:22 -06:00
jason.woltje dbb69c8a41 test(bus,cli): CB5 two-organization acceptance and the CB4 deferred P3 tests (#1873)
The two-org test boots real buses for two organizations with a shipped
Gitea-requiring thread role, binds each copy through its own owner
decision and verified issue, and checks identity separation, record
isolation, token isolation, B through A's revoke, archive and delete,
and refusal of a replayed raw A binding or A token in B.

P3-1 shadowed cleanup, P3-2 runtime revoke wiring, P3-3 ordinary-run
stop. Each passes on BASE; guard-removal mutants recorded.
2026-11-12 19:19:22 -06:00