brief: row 65 keeps the instance vars as its one source, adds fallback vars and the full harness list (decision 151, #1558)
This commit is contained in:
@@ -3401,3 +3401,34 @@ which stay with him. Each item names who decided it and what happened.
|
||||
check name and tested.
|
||||
- Limits live in the organization file. Row 125 needs no bus schema
|
||||
change, so Mos's re-pin plan carries no migration for it.
|
||||
|
||||
151. **Row 65 keeps the instance vars as its one source instead of adding
|
||||
a `routing` table (2026-10-19, Sage, before the row 65 build).** The
|
||||
brief section from 2026-10-11 asked for a top-level `routing` table
|
||||
and the removal of the agent `harness`, `model` and `thinking` vars.
|
||||
Rows 122 and 165 then built that table out of those vars:
|
||||
`launch.models` maps a key to a provider and model, each instance's
|
||||
vars select a harness, a key and a thinking level, the CLI and the
|
||||
Console edit them, the limits count exact provider and model, and the
|
||||
live file sets all three on every instance. A second table would be a
|
||||
second source for the same fact and would undo two landed rows.
|
||||
- The vars stay. Session resolution and the Console views stop
|
||||
falling back to `execution.adapter` and `execution.model`, and a
|
||||
missing var refuses with `no-route`.
|
||||
- The fallback Q83 asked for becomes three agent vars,
|
||||
`fallback.harness`, `fallback.model` and `fallback.thinking`, all or
|
||||
none, used only when the primary fails its launch preflight. Every
|
||||
fallback starts unset.
|
||||
- The family cap drops out of row 65, since row 122 removed
|
||||
`family()`. Thinking on both harnesses and the harness plug-in kind
|
||||
stay as written, and the hard-coded list now covers `runner.mjs`,
|
||||
`usage.mjs` and the row 126 account branch too.
|
||||
- `harness-off` refuses launches and writes, not loading the file, so
|
||||
the Console and the bus keep working while `plugins.harness` is
|
||||
unset. The only business-file entry Jason gets at landing is
|
||||
`plugins.harness` with `claude-code`, through `mosaic plugins set`.
|
||||
- Q83 option A's text isn't in the repository. This keeps what the
|
||||
brief derived from it (one source, fallback at launch only, thinking
|
||||
applied) and changes only where the data lives. If Jason's ruling
|
||||
named a separate table, Mos tells me and the amendment is redone
|
||||
before the review.
|
||||
|
||||
@@ -20,7 +20,8 @@ Two decisions shape the set. Q84 is its own row, not part of the skills
|
||||
row: the ms-unslop skill is guidance the model reads, and the hook is a
|
||||
check that runs on its output. They differ in files, failure mode and
|
||||
tests. Row 29 (console model switching) stays parked. It is a WebUI
|
||||
feature. When Jason reopens it, it reads the routing table this set adds.
|
||||
feature. When Jason reopens it, it reads the instance vars that row 65
|
||||
makes the one source (amended 2026-10-19).
|
||||
|
||||
Constraints that hold for all three rows:
|
||||
|
||||
@@ -125,30 +126,52 @@ showing the four skills and their digests.
|
||||
|
||||
## Model routing table: sessions resolve harness, model and thinking from one table
|
||||
|
||||
Amended 2026-10-19 by Sage before the build started (lead decision 151).
|
||||
Rows 122 and 165 landed after this section was written and built most of
|
||||
the table it asked for. `launch.models` maps a key to a provider and a
|
||||
model. Each role instance's agent vars name a `harness`, a `model` (a
|
||||
`launch.models` key) and a `thinking` level. The `mosaic` CLI and the
|
||||
Console edit them, and the launch limits count exact provider and model,
|
||||
so `family()` and the family cap are already gone. The live file sets
|
||||
all three vars on every instance. A second `routing` table would hold
|
||||
the same data twice, so the vars stay the one source and this row adds
|
||||
what is still missing: no execution fallback, a fallback route, thinking
|
||||
applied on both harnesses, and the harness plug-in kind. The first
|
||||
version of this section is blob 8872802c in git.
|
||||
|
||||
### Problem
|
||||
|
||||
A session's harness, model and thinking come from free-string agent-layer
|
||||
vars (`packages/business/src/vars.mjs:106-108`) with the system's
|
||||
`execution.adapter` and `execution.model` as fallback
|
||||
(`packages/harness/src/bundle.mjs:51-55`). The launch cap guesses a
|
||||
model's family by substring (`packages/seat/src/session.mjs:51`, used at
|
||||
`packages/cli/src/launcher.mjs:148`), so a model name that contains
|
||||
neither `opus` nor `sonnet`, or both, refuses for the wrong reason, and a
|
||||
renamed model can move between families unnoticed. `thinking` is
|
||||
recorded in the manifest and applied to neither harness
|
||||
(`packages/harness/README.md:188-190`). The live business file
|
||||
`mosaic-stack.json` sets no harness, model or thinking for any role, and
|
||||
the system config has no `execution.adapter`, so a managed launch there
|
||||
refuses today with `unsupported-harness`. The row 41 recorded run used a
|
||||
test business with `claude-code` and `claude-sonnet-5-5`.
|
||||
At 54786df03:
|
||||
|
||||
The harness names are hard-coded too, which PRD 1.3 REQ-PLUG-2 says
|
||||
this row converts (Q156). The pair `pi` and `claude-code` is a list in
|
||||
`packages/harness/src/bundle.mjs:20` and a check in
|
||||
`packages/bus/src/broker.mjs:197`. `packages/seat/src/session.mjs:39`
|
||||
maps each to its adapter script, `packages/seat/src/sandbox.mjs:104`
|
||||
adds the Claude Code mounts, and `packages/cli/src/launcher.mjs:171` and
|
||||
`:209` branch on `claude-code` for the credential and version checks.
|
||||
- Session resolution falls back to the system's `execution.adapter` and
|
||||
`execution.model` when an instance sets no `harness` or `model`
|
||||
(`packages/harness/src/bundle.mjs:68-70`). The Console views do the
|
||||
same (`packages/business/src/launch-settings.mjs:84-88` and `:162`,
|
||||
`packages/business/src/instance-settings.mjs:132`). The system config
|
||||
has no `execution.adapter`, and its `execution.model` is the pi worker
|
||||
model, so an instance that drops a var refuses with a message about a
|
||||
system key instead of the var it is missing.
|
||||
- `thinking` is optional. The manifest records it and neither harness
|
||||
applies it (`packages/harness/README.md`).
|
||||
- There is no fallback. A launch whose harness binary or credential is
|
||||
missing refuses.
|
||||
- The harness names are hard-coded, which PRD 1.3 REQ-PLUG-2 says this
|
||||
row converts (Q156):
|
||||
- `packages/business/src/vars.mjs:128`, where `harness` takes only
|
||||
`pi` or `claude-code`;
|
||||
- `packages/harness/src/bundle.mjs:31`, `:37`, `:47-53`, `:104`,
|
||||
`:179` and `:204-212`: the web-builtin check, the list, the relies-on
|
||||
lines and gate timeout, the builtins prompt line, the pi extension or Claude settings
|
||||
files, and the manifest fields;
|
||||
- `packages/harness/src/runner.mjs:251` and `:275`, the turn-end marker
|
||||
and the adapter environment;
|
||||
- `packages/seat/src/session.mjs:42-43`, the adapter scripts;
|
||||
- `packages/seat/src/sandbox.mjs:105-106`, the mounts;
|
||||
- `packages/cli/src/launcher.mjs:242`, `:249` and `:316`, the
|
||||
credential check, the row 126 account and the versions;
|
||||
- `packages/bus/src/broker.mjs:421`, the `invalid-harness` check;
|
||||
- `packages/bus/src/usage.mjs:77-78`, where each harness keeps its
|
||||
session files.
|
||||
|
||||
### Owner and reviewer
|
||||
|
||||
@@ -157,129 +180,147 @@ adds the Claude Code mounts, and `packages/cli/src/launcher.mjs:171` and
|
||||
|
||||
### Files owned
|
||||
|
||||
- `packages/business/src/business.mjs`, `vars.mjs`, `vocabulary.mjs`,
|
||||
`index.mjs` and their tests, `packages/business/README.md`
|
||||
- `packages/business/src/vars.mjs`, `business.mjs`, `launch-settings.mjs`,
|
||||
`instance-settings.mjs`, `index.mjs` and their tests,
|
||||
`packages/business/README.md`
|
||||
- `packages/harness/src/bundle.mjs`, `runner.mjs`, tests, README
|
||||
- `packages/seat/src/session.mjs` and its tests (the `family` match
|
||||
goes)
|
||||
- `packages/seat/src/session.mjs`, `packages/seat/src/sandbox.mjs` (the
|
||||
mounts only) and their tests
|
||||
- `packages/cli/src/launcher.mjs` and its tests
|
||||
- `packages/bus/src/broker.mjs` (the harness check only),
|
||||
`packages/bus/src/usage.mjs` (the session directory only) and their
|
||||
tests
|
||||
- `adapters/pi/adapter.sh`, `adapters/claude/adapter.sh`,
|
||||
`adapters/README.md`
|
||||
- the `harness` entry in `packages/plugins/src/kinds.mjs`,
|
||||
`packages/plugins/harness/pi/` and `packages/plugins/harness/claude-code/`,
|
||||
their tests, and the harness section of `packages/plugins/README.md`
|
||||
- `packages/bus/src/broker.mjs` (the harness check only) and
|
||||
`packages/seat/src/sandbox.mjs` (the Claude Code mounts only), with
|
||||
their tests
|
||||
- test business fixtures that set `harness`, `model` or `thinking`
|
||||
- `agents/sage/work/queue-<row>/`
|
||||
- `agents/sage/work/queue-65/`
|
||||
|
||||
A change outside this list is named in the packet with its reason.
|
||||
|
||||
### What ships
|
||||
|
||||
- Harnesses as plug-in modules (PRD 1.3 REQ-PLUG-1, REQ-PLUG-2; Q156).
|
||||
Row 131's loader and kind registry are in place first.
|
||||
Row 131's loader and kind registry are in place.
|
||||
- A `harness` entry in `packages/plugins/src/kinds.mjs` at interface
|
||||
version 1. The organization file switches on a list,
|
||||
`plugins.harness`, through the write path from row 122.
|
||||
`plugins.harness`, through `mosaic plugins set`.
|
||||
- Two modules, `packages/plugins/harness/pi/` and
|
||||
`packages/plugins/harness/claude-code/`. Each `index.mjs` exports
|
||||
the adapter script it runs (a path under `adapters/`, which stay
|
||||
where they are), a preflight (binary present, version, credential
|
||||
status), its sandbox mounts, its bundle notes and gate timeout, and
|
||||
how it passes `thinking`. Rows 64 and 66 add their skills and
|
||||
`packages/plugins/harness/claude-code/`. Each `index.mjs` exports a
|
||||
function for every place core branches on a harness today: the
|
||||
adapter script it runs (a path under `adapters/`, which stay where
|
||||
they are), a preflight (binary present, version, credential status),
|
||||
its sandbox mounts, its bundle files, relies-on lines and gate
|
||||
timeout, the adapter environment, the turn-end check, where its
|
||||
session files live for the usage reader, whether its launches count
|
||||
against `launch.account`, whether it serves `harness-builtin` web,
|
||||
and how it passes `thinking`. The packet and the plug-ins README
|
||||
list the final export names. Rows 64 and 66 add their skills and
|
||||
unslop exports to these modules.
|
||||
- Core reaches a harness only through the loader. The five places
|
||||
listed under Problem read the module instead, and none of them
|
||||
names `pi` or `claude-code` after this row. The broker's
|
||||
`invalid-harness` check accepts a harness that is switched on.
|
||||
- A routing entry or fallback that names a harness not switched on
|
||||
refuses the business file at load with `harness-off`. The loader's
|
||||
own refusals (bad name, missing directory, symlink, load failure,
|
||||
missing export, other version) refuse the launch and name the
|
||||
module.
|
||||
- A top-level `routing` table in the business file, keyed by role
|
||||
instance name (the keys of `roles`). Each entry has `harness`
|
||||
(a harness module that is switched on), `model`, `family` (a key of
|
||||
`LAUNCH_CEILING`), `thinking` (the existing six levels), and
|
||||
`fallback`: null, or an object with the same four keys. Unknown keys
|
||||
refuse. A `launch.instances` or `launch.by` name with no entry refuses
|
||||
the business file at load.
|
||||
- One source. The agent-layer `harness`, `model` and `thinking` vars are
|
||||
removed, and session resolution no longer reads `execution.adapter`
|
||||
or `execution.model`. Those system keys stay for `scripts/run-task.sh`
|
||||
workers, which this row doesn't touch. A business file that still sets
|
||||
the removed vars refuses with a message pointing at `routing`.
|
||||
- Resolution. A launch for an instance with no `routing` entry refuses
|
||||
with `no-route`. The fallback is used only when the entry states one,
|
||||
and only at launch, when the primary harness fails its preflight
|
||||
- Core reaches a harness only through the loader. None of the places
|
||||
listed under Problem names `pi` or `claude-code` after this row. The
|
||||
broker's `invalid-harness` check accepts a harness that is switched
|
||||
on.
|
||||
- The `harness` var takes a module name (the loader's name pattern),
|
||||
not a fixed pair. A launch whose harness, primary or fallback, isn't
|
||||
switched on refuses with `harness-off`. So does a CLI or Console
|
||||
write that sets one. Loading the business file doesn't refuse on
|
||||
it, so the Console and the bus keep working while `plugins.harness`
|
||||
is unset, and only launches refuse. The loader's own refusals (bad
|
||||
name, missing directory, symlink, load failure, missing export,
|
||||
other version) refuse the launch and name the module.
|
||||
- One source. A managed session takes its harness, model and thinking
|
||||
from its instance's three vars. Session resolution and the Console
|
||||
views stop reading `execution.adapter` and `execution.model`. Those
|
||||
system keys stay for `scripts/run-task.sh` workers, which this row
|
||||
doesn't touch, and for the print-only `migrate-launch.mjs`. A launch
|
||||
for an instance missing any of the three refuses with `no-route` and
|
||||
names the missing var.
|
||||
- Fallback. Three agent vars, `fallback.harness`, `fallback.model` (a
|
||||
`launch.models` key) and `fallback.thinking`, set all together or not
|
||||
at all. A partial set refuses the business file at load. The fallback
|
||||
is used only at launch, when the primary harness fails its preflight
|
||||
(binary missing, or credential status not ok). Never mid-session. The
|
||||
manifest records which entry was used (`primary` or `fallback`) and
|
||||
why.
|
||||
- The launch cap counts sessions by the `family` of the entry each was
|
||||
launched under. `family()` in `session.mjs` goes. `launch.max` keeps
|
||||
its meaning.
|
||||
limit checks and `mayLaunch` run on the route the launch actually
|
||||
takes. The manifest records `route` as `primary` or `fallback`, with
|
||||
the preflight reason that chose the fallback.
|
||||
- `thinking` reaches both harnesses. Pi gets its thinking flag. Claude
|
||||
Code gets its effort or thinking setting. Probe the exact flag or
|
||||
setting on the pinned versions first and record it in the packet and
|
||||
`adapters/README.md`. The README line saying thinking isn't applied
|
||||
goes.
|
||||
- First table. The live business file sets nothing today, so this table
|
||||
starts from the row 41 recorded run and the R26 caps. Every fallback
|
||||
is null: a pi fallback on `zai/glm-5.3-flash` would need a `glm`
|
||||
family ceiling, which is a separate ruling.
|
||||
|
||||
| Role | Harness | Model | Family | Thinking | Fallback |
|
||||
|---|---|---|---|---|---|
|
||||
| coder | claude-code | claude-sonnet-5-5 | sonnet | medium | none |
|
||||
| reviewer | claude-code | claude-opus-5-5 | opus | high | none |
|
||||
| cto | claude-code | claude-opus-5-5 | opus | high | none |
|
||||
| pm | claude-code | claude-opus-5-5 | opus | high | none |
|
||||
|
||||
- Tests: a session resolves harness, model and thinking from its table
|
||||
entry; an unknown role or a missing entry refuses the launch; a stated
|
||||
fallback is used when the primary's preflight fails and an unstated
|
||||
one never is; the cap counts by entry family, so a model name holding
|
||||
`opus` launched under a `sonnet` entry counts as sonnet; thinking
|
||||
reaches the Pi and Claude Code fake adapters as the recorded flag.
|
||||
- Harness tests: a route to a harness that isn't switched on refuses
|
||||
with `harness-off`; a fixture harness module switched on in a test
|
||||
organization file launches a fake session with no core file changed;
|
||||
a grep test that no file under `packages/*/src` outside
|
||||
`packages/plugins` names `pi` or `claude-code` as a harness, with the
|
||||
exceptions under Out of scope listed in the test. One mutant per
|
||||
refusal, and one that puts a harness name back in core.
|
||||
- No new table. The live file already sets the three vars on every
|
||||
instance, and this row changes none of them. Every fallback starts
|
||||
unset. The first table in the old version of this section is void.
|
||||
- Tests: a session resolves harness, model and thinking from its vars;
|
||||
a missing var refuses with `no-route`, and a session never reads
|
||||
`execution.adapter` or `execution.model`; a partial fallback refuses
|
||||
the file at load; a stated fallback is used when the primary's
|
||||
preflight fails, an unstated one never is, and a primary that passes
|
||||
never uses it; the manifest records the route and the reason; the
|
||||
limit check sees the fallback's provider and model; thinking reaches
|
||||
the Pi and Claude Code fake adapters as the recorded flag.
|
||||
- Harness tests: a launch on a harness that isn't switched on refuses
|
||||
with `harness-off`, primary or fallback, and so does a write that
|
||||
sets one; a business file with harness vars and no `plugins.harness`
|
||||
still loads and its Console view reads; a fixture harness module
|
||||
switched on in a test organization file launches a fake session with
|
||||
no core file changed; a grep test that no file under `packages/*/src`
|
||||
outside `packages/plugins` names `pi` or `claude-code` as a harness,
|
||||
with the exceptions under Out of scope listed in the test. One mutant
|
||||
per refusal (`no-route`, `harness-off` at launch, `harness-off` at a
|
||||
write, a partial fallback, a fallback taken when the primary passes),
|
||||
and one that puts a harness name back in core.
|
||||
- Gate suites: `node --test 'packages/plugins/tests/*.test.mjs'`,
|
||||
`node --test 'packages/bus/tests/*.test.mjs'`,
|
||||
`node --test 'packages/business/tests/*.test.mjs'`,
|
||||
`node --test 'packages/harness/tests/*.test.mjs'`,
|
||||
`node --test 'packages/seat/tests/*.test.mjs'`,
|
||||
`node --test 'packages/cli/tests/*.test.mjs'`, and every
|
||||
`scripts/test-*.sh`.
|
||||
`node --test 'packages/cli/tests/*.test.mjs'`,
|
||||
`node --test 'packages/webui/tests/*.test.mjs'` (the Console reads the
|
||||
launch view), and every `scripts/test-*.sh`.
|
||||
|
||||
### Out of scope
|
||||
|
||||
The provider and profile registry in `packages/mosaic` stays parked; it
|
||||
comes with CLIProxyAPI. Model switching in a running session and the
|
||||
console UI for it (row 29, parked). `scripts/run-task.sh` worker model
|
||||
selection.
|
||||
selection. Changing any instance's harness, model or thinking in the
|
||||
live file.
|
||||
|
||||
The tool-policy gate stays in core: `packages/harness/src/gate.mjs` and
|
||||
`claude-gate.mjs` enforce the session's tool policy, and a module
|
||||
mustn't be able to change that boundary (PRD REQ-PLUG-1). Pi started
|
||||
directly by `packages/conversation` and the Discord CLI converts when a
|
||||
row changes those engines (Q156 item 2). No model provider kind; row
|
||||
122 names providers as data, and the kind waits on row 127.
|
||||
These keep a harness name, and the grep test lists them:
|
||||
|
||||
- the tool-policy gate: `packages/harness/src/gate.mjs`,
|
||||
`claude-gate.mjs` and `pi-extension.mjs` enforce the session's tool
|
||||
policy, and a module mustn't be able to change that boundary (PRD
|
||||
REQ-PLUG-1);
|
||||
- `packages/bus/src/human.mjs:85`, the human-proof check that refuses
|
||||
any agent harness binary, which is a security boundary;
|
||||
- `packages/conversation` and `packages/discord`, which start pi
|
||||
directly and convert when a row changes those engines (Q156 item 2);
|
||||
- `packages/control-board/src/scan.mjs`, which matches running process
|
||||
names.
|
||||
|
||||
No model provider kind; row 122 names providers as data, and the kind
|
||||
waits on row 127.
|
||||
|
||||
### Gate
|
||||
|
||||
Darkwing and Dewey approve on the issue, naming the candidate manifest.
|
||||
The suites above pass on a gate rerun in a clean worktree. Jason edits
|
||||
the business file himself (decision 144), so at landing Sage sends him,
|
||||
through Mos, the exact `plugins.harness` and `routing` entries for
|
||||
`mosaic-stack.json`. Once he has added them, Sage starts one managed
|
||||
coder session, attaching the manifest that shows the module loaded, the
|
||||
entry used, the family counted and the thinking flag passed. The
|
||||
modules go live only through a re-pin on Mos's go (decision 109).
|
||||
the business file himself (decision 144). This row needs one entry from
|
||||
him: at landing Sage sends him, through Mos, the exact
|
||||
`mosaic plugins set` patch that adds `"harness": ["claude-code"]` to
|
||||
whatever `plugins` holds then. Only claude-code goes on, because no live
|
||||
instance uses pi. Until he runs it on a stack pinned past this row,
|
||||
every managed launch refuses `harness-off`, as chat refuses before
|
||||
`plugins.channel` (row 164), and the re-pin plan says so. Once he has
|
||||
run it, Sage starts one managed coder session and attaches the manifest
|
||||
showing the module loaded, the route used, the provider and model
|
||||
counted, and the thinking flag passed. The modules go live only through
|
||||
a re-pin on Mos's go (decision 109).
|
||||
|
||||
## Managed sessions run the unslop check on both harnesses
|
||||
|
||||
|
||||
Reference in New Issue
Block a user